import type { AssistantMessage, ToolResultMessage } from "@bastani/pi-ai/compat"; import type { AgentMessage } from "@earendil-works/pi-agent-core"; import { type Component, type MarkdownTheme, type TUI } from "@earendil-works/pi-tui"; import type { MarkdownTransformer, MessageRenderer, ToolRenderers } from "../../../core/extensions/types.ts"; import { type BashExecutionMessage, type BranchSummaryMessage, type CustomMessage } from "../../../core/messages.ts"; import type { TaskRecord } from "../../../core/tasks/contracts.js"; import type { OwnerTaskStore, TaskActivity } from "../../../core/tasks/owner-store.js"; import { type StreamingAssistantDelta } from "../streaming-assistant-message.ts"; export interface PersistedMessageMeta { id: string; timestamp: string; } export type ChatMessageEntry = { role: "assistant"; kind: "assistant"; message: AssistantMessage; messageId?: string; timestamp?: string; } | { role: "tool"; kind: "task"; task: TaskRecord; duplicate: boolean; siblings: readonly TaskRecord[]; activity: TaskActivity[]; activityOmitted: boolean; } | { role: "tool"; kind: "tool"; toolName: string; toolCallId: string; args: unknown; result?: RenderableToolResult; isPartial?: boolean; } | { role: "tool"; kind: "bashExecution"; message: BashExecutionMessage; isPartial?: boolean; } | { role: "user"; kind: "user"; text: string; messageId?: string; timestamp?: string; } | { role: "custom"; kind: "custom"; message: CustomMessage; } | { role: "summary"; kind: "branchSummary"; message: BranchSummaryMessage; } | { role: "system"; kind: "system"; text: string; }; export interface ChatMessageRenderOptions { ui: Pick; cwd: string; markdownTheme?: MarkdownTheme; hideThinkingBlock?: boolean; hiddenThinkingLabel?: string; toolOutputExpanded?: boolean; showImages?: boolean; imageWidthCells?: number; outputPad?: number; isStreaming?: boolean; markdownTransformers?: readonly MarkdownTransformer[]; renderLatex?: boolean; getToolDefinition?: (toolName: string) => ToolRenderers | undefined; getCustomMessageRenderer?: (customType: string) => MessageRenderer | undefined; createToolComponent?: (entry: Extract) => Component; createCustomMessageComponent?: (message: CustomMessage) => Component; } export declare function chatEntriesFromAgentMessages(messages: readonly AgentMessage[], messageMeta?: ReadonlyMap): ChatMessageEntry[]; export interface LiveChatEventLike { readonly type?: unknown; readonly message?: unknown; readonly assistantMessageEvent?: StreamingAssistantDelta; readonly toolCallId?: unknown; readonly parentToolCallId?: unknown; readonly toolName?: unknown; readonly args?: unknown; readonly partialResult?: unknown; readonly result?: unknown; readonly isError?: unknown; readonly durationMs?: unknown; } type LiveChatEntry = ChatMessageEntry | { role: string; }; export declare class LiveChatEntriesController { private streamingAssistantIndex; private pendingToolIndexes; private readonly entries; constructor(entries: LiveChatEntry[]); clearTasks(): void; upsertTasks(tasks: readonly TaskRecord[], store?: OwnerTaskStore): void; appendMessages(messages: readonly AgentMessage[]): void; replaceMessages(messages: readonly AgentMessage[], preservedEntries?: readonly { role: string; }[]): void; appendUserText(text: string): void; /** * Seed the assistant message a chat mounted mid-stream never saw start. * * Delta-only updates carry just the next fragment, so a consumer attached * part-way through a turn cannot recover the text that already streamed. The * live session keeps that in-flight message, and seeding it here makes the * deltas that arrive afterwards continue it instead of opening a second * assistant message. A stream this consumer is already following wins. */ hydrateStreamingAssistantMessage(message: unknown): boolean; applyEvent(event: LiveChatEventLike): boolean; pendingToolIds(): string[]; clearPendingTools(): void; isStreamingAssistantEntry(entry: ChatMessageEntry): boolean; private handleMessageStart; private handleMessageUpdate; private handleMessageEnd; private updateAssistantMessage; private currentStreamingAssistantMessage; private upsertToolEntry; private updateToolResult; private isSyntheticToolCallId; private findToolEntryIndex; private reindexPendingTools; private isAssistantEntry; private isToolEntry; } /** UI progress may contain in-memory details; only durable transcript results are JSON. */ type RenderableToolResult = Omit & { details?: unknown; }; export declare function renderChatMessageEntry(entry: ChatMessageEntry, options: ChatMessageRenderOptions): Component; export {}; //# sourceMappingURL=chat-message-renderer.d.ts.map