import type { ContentBlock, SessionSnapshot } from "./types.js"; import type { StructuredRunnerTurnState } from "./structured-runner.js"; export declare function buildCodexPatchApplyBlocks(item: Record): ContentBlock[]; interface CodexFileSnapshot { exists: boolean; text: string | null; unavailableReason?: string; } type CodexFileSnapshotMap = Map; export declare function buildCodexFileChangeBlocks(item: Record, completed: boolean, beforeSnapshots?: CodexFileSnapshotMap, afterSnapshots?: CodexFileSnapshotMap): ContentBlock[]; /** * Codex `exec --json` only publishes authoritative usage with `turn.completed`. * Keep the bottom usage row useful while the turn is running by estimating the * model-produced text/tool arguments; the final provider value replaces this. */ export declare function estimateCodexOutputTokens(blocks: ContentBlock[]): number; interface CodexTurnState extends StructuredRunnerTurnState { codexBlockIndex: Map; codexFileSnapshots: CodexFileSnapshotMap; cwd: string; } export declare class CodexProtocolReducer { readonly state: CodexTurnState; readonly errors: string[]; primaryError: string | null; constructor(session: SessionSnapshot); apply(parsed: unknown): boolean; private refreshUsage; private normalizeToolResultContent; private unwrapCodexStreamEvent; private applyCodexLooseEvent; private codexFunctionToolUse; private codexMcpToolBlocks; private extractCodexText; /** * Merge one codex `item.*` event into `turnState.blocks`. * * 三种 phase 行为: * - "started": 首次出现的 item,块直接 push(tool_result 走 upsert 配对)。 * text/thinking/TodoWrite 这种"靠 id 替换"的块记录到 * codexBlockIndex 里,方便后续 updated/completed 找回原位。 * - "updated": codex 重发完整 ThreadItem(不是 delta)。已记录过的块就 * 替换;新块按 started 路径处理。 * - "completed": 把"in_progress"卡片定型——text 同时更新 turnState.result * 以便 result fallback 不为空;tool_use ↔ tool_result 通过 * 共享 id 配对到一起(包括 file_change 子项的 `${id}#i`)。 */ private applyCodexItem; /** * Map a codex `item.{started,updated,completed}` payload into wand's * `ContentBlock[]` so the chat UI's existing tool/diff/todo cards just work. * * Codex `exec --json` emits 8 item.type values (see * `codex-rs/exec/src/exec_events.rs`); below they're routed to whatever wand * tool name reuses an existing renderer: * * agent_message → text * reasoning → thinking * command_execution → tool_use "Bash" + tool_result * file_change → one Edit/Write per file; snapshots taken between * item.started/completed restore the omitted diff body * mcp_tool_call → tool_use named "__" + tool_result * web_search → tool_use "WebSearch" + tool_result (results not in stream) * todo_list → tool_use "TodoWrite" (replaced in place on each update) * error → text block prefixed with ❌ * * Returns [] when there is nothing to emit yet (e.g. agent_message at * `item.started` before any text has been produced). * * Callers handle in-place replacement for `item.updated` via * `turnState.codexBlockIndex`; tool_use ↔ tool_result pairing still goes * through `upsertCodexBlock` by matching ids. */ private extractCodexItemBlock; private upsertCodexBlock; private extractCodexUsage; } export {};