import { type ReactElement } from 'react'; import type { InteractiveModeResult } from '../interactive/interactive.js'; import { type TranscriptEntry } from './TranscriptEntryView.js'; import type { UserMessageColors } from './terminalColors.js'; import { type EditorDraft } from './editorState.js'; import type { InteractiveResultSource, TuiConversation, TuiHandoffId } from './tuiConversation.js'; export interface ConversationUiText { thinking: string; hint: string; placeholder: string; /** Shown under the queued lines while the assistant is still answering. */ queuedHint: string; /** `{count}` stands for the queued lines that did not fit on screen. */ queuedMore: string; /** Appended to the status row while a call can still be interrupted. */ interruptHint: string; /** System line left behind when Esc stops an answer. */ responseInterrupted: string; /** System line left behind when Esc stops `/go`. */ instructionInterrupted: string; } /** What the conversation phase asks the surrounding TUI to do next. */ export type ConversationExit = { kind: 'result'; result: InteractiveModeResult; } /** * `origin` is the command path that produced the task. It always travels with * it — the selector and the meaning of a rejected draft both depend on it — * while whether it reaches the result is the mode's decision. */ | { kind: 'choose_action'; task: string; origin?: InteractiveResultSource; } | { kind: 'resume_session'; } /** The caller runs `id` with Ink unmounted, then this view is mounted again. */ | { kind: 'handoff'; id: TuiHandoffId; text?: string; } | { kind: 'failed'; error: unknown; }; /** * What survives a mount: the recall history, the lines still waiting, and the * line that was being written when the mount ended. */ export interface ConversationCarryOver { readonly history: readonly string[]; readonly queue: readonly string[]; /** * Absent when the prompt stood empty. That is a state the prompt is really * in, not a draft that failed to come along: a mount that ends on a typed * command has already taken the draft, and one that ends on a queued command * hands over whatever the user had reached by then. */ readonly draft?: EditorDraft; } export interface ConversationViewProps { readonly ui: ConversationUiText; readonly lang: 'en' | 'ja'; readonly conversation: TuiConversation; readonly initialEntries: readonly TranscriptEntry[]; /** Colors resolved once for this run and reused when the transcript is finalized. */ readonly userMessageColors: UserMessageColors; /** `summarize` turns the first input straight into an instruction. */ readonly submitMode: 'chat' | 'summarize'; /** Summarize the seeded input on mount, without waiting for a keystroke. */ readonly autoSubmit: boolean; /** * Lines already submitted in this conversation. The view is unmounted and * mounted again around every selector, so the recall list is kept by the * caller and handed back on the next mount. */ readonly initialHistory: readonly string[]; /** * The line the mount before this one was in the middle of, put back with its * caret. `undefined` says there was none — every mount answers this, so a * draft is never dropped by omission. */ readonly initialDraft: EditorDraft | undefined; /** Provider and model the current session calls, read again after a session rebuild. */ readonly modelLabel: () => string; /** * True when the caller carries a decision out and mounts this view again. The * image store then outlives the decision, and sealing it here would refuse * every paste that follows. */ readonly residentSession: boolean; /** Lines still waiting from the mount before this one. */ readonly initialQueue: readonly string[]; /** Queues the confirmed history for output after Ink erases the live frame. */ readonly finalizeTranscript: (entries: readonly TranscriptEntry[], columns: number) => void; /** Reads the live run status while this mounted view remains open. */ readonly liveStatusReader?: () => string; /** Polling interval for the live run status. */ readonly liveStatusRefreshIntervalMs?: number; /** Called once, with what the next mount has to carry on from. */ readonly onExit: (exit: ConversationExit, carried: ConversationCarryOver) => void; } export declare function ConversationView({ ui, lang, conversation, initialEntries, userMessageColors, submitMode, autoSubmit, initialHistory, initialDraft, modelLabel, residentSession, initialQueue, finalizeTranscript, liveStatusReader, liveStatusRefreshIntervalMs, onExit, }: ConversationViewProps): ReactElement; //# sourceMappingURL=ConversationView.d.ts.map