export interface StreamEvent { type: string; subtype?: string; message?: { content?: Array<{ type: string; name?: string; input?: Record; text?: string; }>; }; tool_use_result?: { success?: boolean; commandName?: string; content?: string; }; result?: string; is_error?: boolean; duration_ms?: number; total_cost_usd?: number; } export function formatEventForLog(event: StreamEvent): string | null { if (event.type === "system" && event.subtype === "init") { return `=== Session started ===\n`; } if (event.type === "assistant" && event.message?.content) { const parts: string[] = []; for (const block of event.message.content) { if (block.type === "text" && block.text) { parts.push(`[assistant]\n${block.text}\n`); } else if (block.type === "tool_use" && block.name) { const inputStr = block.input ? JSON.stringify(block.input, null, 2) : "{}"; parts.push(`[tool_use: ${block.name}]\n${inputStr}\n`); } } return parts.length > 0 ? parts.join("\n") : null; } if (event.type === "user" && event.message?.content) { const parts: string[] = []; for (const block of event.message.content as Array<{ type: string; content?: string; }>) { if (block.type === "tool_result" && block.content) { parts.push(`[tool_result]\n${block.content}\n`); } } return parts.length > 0 ? parts.join("\n") : null; } if (event.type === "result") { const lines = [`=== Result ===`]; if (event.is_error) lines.push(`ERROR`); if (event.result) lines.push(event.result); if (event.duration_ms) lines.push(`Duration: ${(event.duration_ms / 1000).toFixed(1)}s`); if (event.total_cost_usd) lines.push(`Cost: $${event.total_cost_usd.toFixed(4)}`); return lines.join("\n") + "\n"; } return null; } export function parseStreamEvents(output: string): StreamEvent[] { return output .split("\n") .filter((line) => line.trim()) .map((line) => { try { return JSON.parse(line) as StreamEvent; } catch { return null; } }) .filter((e): e is StreamEvent => e !== null); }