import type { TeacherToolActivity } from '../../shared/coding-teacher'; export interface ToolActivityUpdate { id: string; name?: string; status: TeacherToolActivity['status']; } function object(value: unknown): Record | undefined { return value && typeof value === 'object' && !Array.isArray(value) ? value as Record : undefined; } /** Project Yuxi's typed tool events; arguments, outputs and internal errors never enter the UI. */ export function cloudToolActivity(chunk: Record, runId: string): ToolActivityUpdate | undefined { const event = object(chunk.stream_event); if (event?.type === 'tool_call' || event?.type === 'tool_call_delta') { if (typeof event.tool_call_id !== 'string' || !event.tool_call_id || typeof event.name !== 'string' || !event.name) return; return { id: runId + ':' + event.tool_call_id, name: event.name, status: 'running' }; } const custom = object(chunk.event); if (chunk.status !== 'stream_event' || custom?.method !== 'tools') return; const data = object(custom.data); if (!data || typeof data.tool_call_id !== 'string' || !data.tool_call_id) return; if (data.event !== 'tool-started' && data.event !== 'tool-finished' && data.event !== 'tool-error') return; const output = object(data.output); return { id: runId + ':' + data.tool_call_id, ...(typeof data.tool_name === 'string' && data.tool_name ? { name: data.tool_name } : {}), status: data.event === 'tool-started' ? 'running' : data.event === 'tool-error' || data.error || output?.status === 'error' || output?.status === 'failed' ? 'failed' : 'completed', }; }