diff --git a/src/lib/chatStream.test.ts b/src/lib/chatStream.test.ts index a2e5103..6cf3f16 100644 --- a/src/lib/chatStream.test.ts +++ b/src/lib/chatStream.test.ts @@ -97,6 +97,35 @@ describe("streamAgentChat", () => { }); }); + it("parses legacy tool_call arguments when params is empty", async () => { + apiFetch.mockResolvedValue({ + ok: true, + body: makeStream([ + 'event: tool_call\ndata: {"conversationId":"agent-1e75dd01-29e","tool":"locate_features","params":{},"arguments":"{\\"ids\\":[\\"142902\\"],\\"feature_type\\":\\"junction\\"}"}\n\n', + 'event: done\ndata: {"session_id":"agent-1e75dd01-29e"}\n\n', + ]), + }); + + const events: Array<{ + type: string; + sessionId?: string; + tool?: string; + params?: Record; + }> = []; + + await streamAgentChat({ + message: "hi", + onEvent: (event) => events.push(event), + }); + + expect(events[0]).toEqual({ + type: "tool_call", + sessionId: "agent-1e75dd01-29e", + tool: "locate_features", + params: { ids: ["142902"], feature_type: "junction" }, + }); + }); + it("emits error when response is not ok", async () => { apiFetch.mockResolvedValue({ ok: false, diff --git a/src/lib/chatStream.ts b/src/lib/chatStream.ts index 4d2746a..187cd59 100644 --- a/src/lib/chatStream.ts +++ b/src/lib/chatStream.ts @@ -52,6 +52,30 @@ const parseEventBlock = (block: string): { event?: string; data?: string } => { }; }; +const isObjectRecord = (value: unknown): value is Record => + typeof value === "object" && value !== null && !Array.isArray(value); + +const resolveToolParams = ( + params: unknown, + argumentsPayload: unknown, +): Record => { + if (isObjectRecord(params) && Object.keys(params).length > 0) { + return params; + } + if (isObjectRecord(argumentsPayload)) { + return argumentsPayload; + } + if (typeof argumentsPayload === "string") { + try { + const parsed = JSON.parse(argumentsPayload) as unknown; + return isObjectRecord(parsed) ? parsed : {}; + } catch { + return {}; + } + } + return isObjectRecord(params) ? params : {}; +}; + export const streamAgentChat = async ({ message, sessionId, @@ -125,11 +149,13 @@ export const streamAgentChat = async ({ try { const parsed = JSON.parse(data) as { session_id?: string; + conversationId?: string; content?: string; message?: string; detail?: string; tool?: string; params?: Record; + arguments?: unknown; id?: string; phase?: string; status?: "running" | "completed" | "error"; @@ -166,9 +192,9 @@ export const streamAgentChat = async ({ } else if (event === "tool_call") { onEvent({ type: "tool_call", - sessionId: parsed.session_id ?? "", + sessionId: parsed.session_id ?? parsed.conversationId ?? "", tool: parsed.tool ?? "", - params: parsed.params ?? {}, + params: resolveToolParams(parsed.params, parsed.arguments), }); } } catch {