import type { Sql } from '../db.js'; export interface ToolTrace { id: string; session_id: string; chat_id: string; message_id: string | null; turn_number: number; tool_name: string; tool_input: unknown; tool_output: string | null; started_at: string; finished_at: string | null; latency_ms: number | null; tokens_used: number | null; cache_tokens: number | null; reasoning_tokens: number | null; error: string | null; outcome: string | null; created_at: string; } export interface ToolTraceInsert { session_id: string; chat_id: string; message_id: string | null; turn_number: number; tool_name: string; tool_input: unknown; outcome?: string; } export interface ToolTraceUpdate { finished_at?: string; latency_ms?: number; tool_output?: string; tokens_used?: number; cache_tokens?: number; reasoning_tokens?: number; error?: string; outcome?: string; } export async function insertToolTrace( sql: Sql, insert: ToolTraceInsert, ): Promise { const [row] = await sql` INSERT INTO tool_traces ( session_id, chat_id, message_id, turn_number, tool_name, tool_input, outcome ) VALUES ( ${insert.session_id}, ${insert.chat_id}, ${insert.message_id}, ${insert.turn_number}, ${insert.tool_name}, ${sql.json(insert.tool_input as never)}, ${insert.outcome ?? null} ) RETURNING * `; if (!row) throw new Error('insertToolTrace returned no row'); return row; } export async function updateToolTrace( sql: Sql, id: string, updates: ToolTraceUpdate, ): Promise { const cols: string[] = []; const vals: any[] = []; if (updates.finished_at !== undefined) { cols.push('finished_at'); vals.push(updates.finished_at); } if (updates.latency_ms !== undefined) { cols.push('latency_ms'); vals.push(updates.latency_ms); } if (updates.tool_output !== undefined) { cols.push('tool_output'); vals.push(updates.tool_output); } if (updates.tokens_used !== undefined) { cols.push('tokens_used'); vals.push(updates.tokens_used); } if (updates.cache_tokens !== undefined) { cols.push('cache_tokens'); vals.push(updates.cache_tokens); } if (updates.reasoning_tokens !== undefined) { cols.push('reasoning_tokens'); vals.push(updates.reasoning_tokens); } if (updates.error !== undefined) { cols.push('error'); vals.push(updates.error); } if (updates.outcome !== undefined) { cols.push('outcome'); vals.push(updates.outcome); } if (cols.length === 0) { const [row] = await sql`SELECT * FROM tool_traces WHERE id = ${id}`; return row ?? null; } const setClause = cols.map((c, i) => `${c} = $${i + 1}`).join(', '); const [row] = await sql.unsafe( `UPDATE tool_traces SET ${setClause} WHERE id = $${cols.length + 1} RETURNING *`, [...vals, id], ); return row ?? null; }