export type ConversationThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high'; export interface ProductModelRef { accountId: string; modelId: string; thinkingLevel: ConversationThinkingLevel; } export interface ConversationModelState { model: ProductModelRef | null; modelResolution: 'resolved' | 'required'; } export interface PublicUsage { inputTokens: number; outputTokens: number; cacheReadTokens?: number; cacheWriteTokens?: number; } export type CodingRuntimeErrorCode = | 'CODING_RUNTIME_START_FAILED' | 'CODING_RUNTIME_READY_TIMEOUT' | 'CODING_RUNTIME_PROTOCOL_ERROR' | 'CODING_PROVIDER_AUTH_REQUIRED' | 'CODING_MODEL_UNAVAILABLE' | 'CODING_SESSION_UNREADABLE' | 'CODING_STORAGE_WRITE_FAILED' | 'CODING_REQUEST_UNCERTAIN' | 'CODING_MIGRATION_MODEL_REQUIRED' | 'CODING_CONVERSATION_NOT_FOUND'; export interface CodingRuntimePublicError { code: CodingRuntimeErrorCode; message: string; recoverable: boolean; } export type ConversationRunStatus = | 'idle' | 'preparing' | 'queued' | 'running' | 'retrying' | 'compacting' | 'aborting' | 'error'; export type PromptMode = 'prompt' | 'steer' | 'follow-up'; export interface ConversationRunState { status: ConversationRunStatus; runId?: string; mode?: PromptMode; startedAt?: number; settledAt?: number; terminalReason?: 'completed' | 'aborted' | 'failed'; retry?: { attempt: number; delayMs: number; }; error?: CodingRuntimePublicError; } export interface ConversationQueueItem { id: string; clientRequestId: string; mode: 'steer' | 'follow-up'; text: string; attachmentIds: string[]; } export interface ConversationQueueState { items: ConversationQueueItem[]; } export interface ConversationContextState { usedTokens: number; contextWindow: number; outputLimit?: number; compaction: 'idle' | 'running'; lastCompactionId?: string; recalculating?: boolean; } export interface ConversationInteractionOption { id: string; label: string; description?: string; } export interface ConversationInteraction { id: string; conversationId: string; runId: string; kind: 'select' | 'confirm' | 'input' | 'editor'; title: string; message?: string; options?: ConversationInteractionOption[]; status: 'pending' | 'answered' | 'rejected' | 'cancelled'; } export interface PublicWorkerState { status: 'stopped' | 'starting' | 'ready' | 'recovering' | 'error'; generation: number; error?: CodingRuntimePublicError; } export type ConversationContentBlock = | { kind: 'text'; id: string; text: string; status: 'streaming' | 'complete'; } | { kind: 'thinking'; id: string; text: string; status: 'streaming' | 'complete'; } | { kind: 'image'; id: string; attachmentId: string; mime: string; }; export interface ConversationMessageNode { kind: 'message'; id: string; sourceEntryId?: string; clientRequestId?: string; role: 'user' | 'assistant'; status: 'optimistic' | 'streaming' | 'complete' | 'error' | 'aborted'; blocks: ConversationContentBlock[]; usage?: PublicUsage; stopReason?: 'stop' | 'length' | 'tool-use' | 'error' | 'aborted'; } export interface ChangedFileDetailsV1 { schema: 'changed-file.v1'; paths: string[]; } export interface TaskStateDetailsV1 { schema: 'task-state.v1'; tasks: Array<{ id: string; title: string; status: 'pending' | 'running' | 'complete' | 'error'; }>; } export interface WriteLeaseDetailsV1 { schema: 'write-lease.v1'; status: 'waiting' | 'held' | 'released'; } export interface AgentBrowserDetailsV1 { schema: 'agent-browser.v1'; action: 'open' | 'status' | 'close' | 'reset_profile' | 'navigate' | 'send_cdp' | 'read_events' | 'read_payload'; attachmentId?: string; mime?: string; } export interface GameAssetsDetailsV1 { schema: 'game-assets.v1'; invocationId: string; candidateIds: string[]; status: 'pending' | 'resolved'; pendingAssetIds: string[]; approvedAssetIds: string[]; discardedAssetIds: string[]; } export interface RuntimeContextDetailsV1 { schema: 'runtime-context.v1'; skills: Array<{ id: string; name: string; description: string; selected: boolean; }>; commands: Array<{ name: string; title: string; description: string; source: 'makelore' | 'pi' | 'skill'; skillId?: string; }>; } export interface SubagentDetailsV1 { schema: 'subagent.v1'; dispatchId: string; mode: 'single' | 'parallel' | 'chain'; tasks: Array<{ taskId: string; agentId: string; toolProfile: 'read-only' | 'coding'; status: 'queued' | 'running' | 'complete' | 'error' | 'aborted' | 'skipped'; summary?: string; errorCode?: string; usage?: PublicUsage; }>; } export type KnownToolDetails = | ChangedFileDetailsV1 | TaskStateDetailsV1 | WriteLeaseDetailsV1 | AgentBrowserDetailsV1 | GameAssetsDetailsV1 | RuntimeContextDetailsV1 | SubagentDetailsV1; export interface ConversationToolNode { kind: 'tool'; id: string; toolCallId: string; toolName: string; title: string; inputText: string; status: 'declared' | 'waiting' | 'running' | 'complete' | 'error' | 'aborted'; output: ConversationContentBlock[]; details?: KnownToolDetails; } export interface ConversationCompactionNode { kind: 'compaction'; id: string; runId: string; source: 'manual' | 'automatic'; status: 'running' | 'complete' | 'error'; willRetry: boolean; summary?: string; } export interface ConversationBoundaryNode { kind: 'boundary'; id: string; runId: string; boundary: 'turn-start' | 'turn-end' | 'retry'; attempt?: number; delayMs?: number; } export interface ConversationSubagentNode { kind: 'subagent'; id: string; runId: string; details: SubagentDetailsV1; } export interface ConversationNoticeNode { kind: 'notice'; id: string; code: string; level: 'info' | 'warning' | 'error'; message: string; } export type ConversationNode = | ConversationMessageNode | ConversationToolNode | ConversationCompactionNode | ConversationBoundaryNode | ConversationSubagentNode | ConversationNoticeNode; export interface ConversationSnapshot { schemaVersion: 1; conversation: { id: string; projectId: string; agentId: string; title: string; model: ConversationModelState; }; nodes: ConversationNode[]; run: ConversationRunState; queue: ConversationQueueState; context: ConversationContextState; pendingInteractions: ConversationInteraction[]; worker: PublicWorkerState; cursor: { workerGeneration: number; seq: number; leafEntryId?: string; }; } export type ConversationPatch = | { op: 'worker.state'; state: PublicWorkerState } | { op: 'run.state'; run: ConversationRunState } | { op: 'message.upsert'; node: ConversationMessageNode } | { op: 'message.block-delta'; messageId: string; blockId: string; delta: string } | { op: 'tool.upsert'; node: ConversationToolNode } | { op: 'compaction.upsert'; node: ConversationCompactionNode } | { op: 'boundary.upsert'; node: ConversationBoundaryNode } | { op: 'subagent.upsert'; node: ConversationSubagentNode } | { op: 'queue.replace'; queue: ConversationQueueState } | { op: 'interaction.upsert'; interaction: ConversationInteraction } | { op: 'interaction.remove'; interactionId: string } | { op: 'context.replace'; context: ConversationContextState } | { op: 'snapshot.invalidated'; reason: string }; export interface ConversationPatchEnvelope { conversationId: string; workerGeneration: number; runId?: string; seq: number; at: number; patch: ConversationPatch; } export interface PrepareConversationInput { conversationId: string; projectId: string; agentId: string; title: string; model: ConversationModelState; } export interface ConversationRuntimeState { conversationId: string; status: PublicWorkerState['status']; workerGeneration: number; error?: CodingRuntimePublicError; } export interface PromptConversationInput { clientRequestId: string; conversationId: string; mode: PromptMode; text: string; attachments: Array<{ attachmentId: string }>; } export interface QueueMessageInput { clientRequestId: string; conversationId: string; text: string; attachments: Array<{ attachmentId: string }>; } export interface PromptAcceptance { accepted: true; conversationId: string; clientRequestId: string; runId: string; mode: PromptMode; queuePosition?: number; } export interface QueueAcceptance { accepted: true; conversationId: string; clientRequestId: string; mode: 'steer' | 'follow-up'; queuePosition: number; } export interface SetConversationModelInput { conversationId: string; accountId: string; modelId: string; } export interface SetThinkingLevelInput { conversationId: string; thinkingLevel: ConversationThinkingLevel; } export interface ForkConversationInput { sourceConversationId: string; sourceEntryId?: string; conversation: PrepareConversationInput; } export interface ForkResult { conversationId: string; snapshot: ConversationSnapshot; } export interface CodingConversationRuntime { prepare(input: PrepareConversationInput): Promise; getSnapshot(conversationId: string): Promise; prompt(input: PromptConversationInput): Promise; steer(input: QueueMessageInput): Promise; followUp(input: QueueMessageInput): Promise; abort(conversationId: string): Promise; setModel(input: SetConversationModelInput): Promise; setThinking(input: SetThinkingLevelInput): Promise; compact(conversationId: string): Promise; fork(input: ForkConversationInput): Promise; recover(conversationId: string): Promise; dispose(conversationId: string): Promise; subscribe(listener: (patch: ConversationPatchEnvelope) => void): () => void; }