// Aider Message Adapter — transforms Aider runner events to internal AgentMessage format // Aider runner emits: system/init, assistant (text lines), result, error import type { AgentMessage, InitContent, TextContent, ThinkingContent, ToolCallContent, ToolResultContent, CostContent, ErrorContent, } from './claude-messages'; import { str, num } from '../utils/type-guards'; /** * Adapt a raw Aider runner event to AgentMessage[]. * * The Aider runner emits events in this format: * - {type:'system', subtype:'init', model, session_id, cwd} * - {type:'assistant', message:{role:'assistant', content:'...'}} — batched text block * - {type:'thinking', content:'...'} — thinking/reasoning block * - {type:'input', prompt:'...'} — incoming prompt/message (shown in console) * - {type:'tool_use', id, name, input} — shell command execution * - {type:'tool_result', tool_use_id, content} — shell command output * - {type:'result', subtype:'result', cost_usd, duration_ms, is_error} * - {type:'error', message:'...'} */ export function adaptAiderMessage(raw: Record): AgentMessage[] { const timestamp = Date.now(); const uuid = crypto.randomUUID(); switch (raw.type) { case 'system': if (str(raw.subtype) === 'init') { return [{ id: uuid, type: 'init', content: { sessionId: str(raw.session_id), model: str(raw.model), cwd: str(raw.cwd), tools: [], } satisfies InitContent, timestamp, }]; } return [{ id: uuid, type: 'unknown', content: raw, timestamp, }]; case 'input': return [{ id: uuid, type: 'text', content: { text: `📨 **Received:**\n${str(raw.prompt)}` } satisfies TextContent, timestamp, }]; case 'thinking': return [{ id: uuid, type: 'thinking', content: { text: str(raw.content) } satisfies ThinkingContent, timestamp, }]; case 'assistant': { const msg = typeof raw.message === 'object' && raw.message !== null ? raw.message as Record : {}; const text = str(msg.content); if (!text) return []; return [{ id: uuid, type: 'text', content: { text } satisfies TextContent, timestamp, }]; } case 'tool_use': return [{ id: uuid, type: 'tool_call', content: { toolUseId: str(raw.id), name: str(raw.name, 'shell'), input: raw.input, } satisfies ToolCallContent, timestamp, }]; case 'tool_result': return [{ id: uuid, type: 'tool_result', content: { toolUseId: str(raw.tool_use_id), output: raw.content, } satisfies ToolResultContent, timestamp, }]; case 'result': return [{ id: uuid, type: 'cost', content: { totalCostUsd: num(raw.cost_usd), durationMs: num(raw.duration_ms), inputTokens: 0, outputTokens: 0, numTurns: num(raw.num_turns) || 1, isError: raw.is_error === true, } satisfies CostContent, timestamp, }]; case 'error': return [{ id: uuid, type: 'error', content: { message: str(raw.message, 'Aider error') } satisfies ErrorContent, timestamp, }]; default: return [{ id: uuid, type: 'unknown', content: raw, timestamp, }]; } }