ResumeConversation.tsx
1 import React from 'react' 2 import { render } from 'ink' 3 import { REPL } from './REPL.js' 4 import { deserializeMessages } from '../utils/conversationRecovery.js' 5 import { LogSelector } from '../components/LogSelector.js' 6 import type { LogOption } from '../types/logs.js' 7 import { logError, getNextAvailableLogForkNumber } from '../utils/log.js' 8 import type { Tool } from '../Tool.js' 9 import { Command } from '../commands.js' 10 import { isDefaultSlowAndCapableModel } from '../utils/model.js' 11 12 type Props = { 13 commands: Command[] 14 context: { unmount?: () => void } 15 logs: LogOption[] 16 tools: Tool[] 17 verbose: boolean | undefined 18 } 19 20 export function ResumeConversation({ 21 context, 22 commands, 23 logs, 24 tools, 25 verbose, 26 }: Props): React.ReactNode { 27 async function onSelect(index: number) { 28 const log = logs[index] 29 if (!log) { 30 return 31 } 32 33 // Load and deserialize the messages 34 try { 35 context.unmount?.() 36 // Start a new REPL with the loaded messages 37 // Increment the fork number by 1 to generate a new transcript 38 // Check if using default model before rendering 39 const isDefaultModel = await isDefaultSlowAndCapableModel() 40 41 render( 42 <REPL 43 messageLogName={log.date} 44 initialPrompt="" 45 shouldShowPromptInput={true} 46 verbose={verbose} 47 commands={commands} 48 tools={tools} 49 initialMessages={deserializeMessages(log.messages, tools)} 50 initialForkNumber={getNextAvailableLogForkNumber( 51 log.date, 52 log.forkNumber ?? 1, 53 0, 54 )} 55 isDefaultModel={isDefaultModel} 56 />, 57 { 58 exitOnCtrlC: false, 59 }, 60 ) 61 } catch (e) { 62 logError(`Failed to load conversation: ${e}`) 63 throw e 64 } 65 } 66 67 return <LogSelector logs={logs} onSelect={onSelect} /> 68 }