import assert from "node:assert/strict"; import { describe, it } from "node:test"; import { describeToolActivity } from "../../src/modules/agent/tool-labels"; import { encodeSseEvent, thinkingLabel } from "../../src/modules/agent/server/progress"; import { createMockLlmClient } from "../../src/lib/llm/mock"; import { runAgentChat } from "../../src/modules/agent/server/run"; describe("describeToolActivity", () => { it("uses item text when adding to a list", () => { const label = describeToolActivity("add_list_item", JSON.stringify({ text: "milk" })); assert.match(label, /milk/); }); it("mentions the API path for call_api", () => { const label = describeToolActivity( "call_api", JSON.stringify({ method: "GET", path: "/api/v1/notes" }), ); assert.match(label, /\/api\/v1\/notes/); }); }); describe("agent progress", () => { it("encodes SSE payloads", () => { const encoded = encodeSseEvent({ type: "thinking", label: "Planning…", round: 0 }); assert.equal(encoded, 'data: {"type":"thinking","label":"Planning…","round":0}\n\n'); }); it("uses different labels per round", () => { assert.match(thinkingLabel(0), /request/i); assert.match(thinkingLabel(1), /found/i); }); it("emits progress events during tool execution", async () => { const events: string[] = []; await runAgentChat({ messages: [{ role: "user", content: "add milk to the shopping list" }], request: new Request("http://localhost:3000/api/agent/chat"), llm: createMockLlmClient(), executeTool: async () => JSON.stringify({ status: 201, body: { id: "item-1", text: "milk" } }), onProgress: (event) => { if (event.type === "tool") events.push(event.label); if (event.type === "thinking") events.push(event.label); }, }); assert.ok(events.some((label) => label.includes("milk"))); assert.ok(events.some((label) => /request|found/i.test(label))); }); });