import { describe, expect, it } from "bun:test"; import { appendBackendToolArtifact, cancelBackendTodos, completeBackendActivities, completeBackendTodos, upsertBackendQuestion, } from "../../src/routes/chatUiState.js"; describe("completeBackendActivities", () => { it("closes running child actions when the stream terminates", () => { const activities = completeBackendActivities([ { id: "activity-1", status: "running", startedAt: Date.now() - 100, actions: [ { id: "action-1", status: "running", startedAt: Date.now() - 50, }, ], }, ], "error") as Array>; expect(activities[0]).toMatchObject({ status: "error", actions: [expect.objectContaining({ status: "error" })], }); }); }); describe("appendBackendToolArtifact", () => { it("persists show_chart tool calls as chart artifacts", () => { const artifacts = appendBackendToolArtifact([], { session_id: "session-1", tool: "show_chart", params: { title: "压力曲线", chart_type: "line", x_data: ["00:00", "01:00"], series: [{ name: "P-101", data: [0.42, 0.41] }], }, }) as Array>; expect(artifacts).toHaveLength(1); expect(artifacts[0]).toMatchObject({ tool: "show_chart", kind: "chart", title: "压力曲线", params: { chart_type: "line", x_data: ["00:00", "01:00"], series: [{ name: "P-101", data: [0.42, 0.41] }], }, }); expect(artifacts[0]).toEqual( expect.objectContaining({ id: expect.stringMatching(/^show_chart-/), }), ); }); }); describe("upsertBackendQuestion", () => { it("replaces a tool-call placeholder with the actionable question request", () => { const questions = upsertBackendQuestion( [ { requestId: "call-1", sessionId: "session-1", questions: [ { header: "测试问题", question: "你觉得这个 question 工具好用吗?", options: [{ label: "非常好用", description: "交互清晰,选项方便" }], }, ], tool: { messageID: "message-1", callID: "call-1" }, createdAt: 123, status: "pending", }, ], { session_id: "session-1", request_id: "question-1", questions: [ { header: "测试问题", question: "你觉得这个 question 工具好用吗?", options: [{ label: "非常好用", description: "交互清晰,选项方便" }], }, ], tool: { messageID: "message-1", callID: "call-1" }, created_at: 456, }, ); expect(questions).toHaveLength(1); expect(questions[0]).toMatchObject({ requestId: "question-1", tool: { callID: "call-1" }, status: "pending", }); }); it("does not replace an actionable question request with a later tool-call placeholder", () => { const questions = upsertBackendQuestion( [ { requestId: "question-1", sessionId: "session-1", questions: [ { header: "测试问题", question: "你觉得这个 question 工具好用吗?", options: [{ label: "非常好用", description: "交互清晰,选项方便" }], }, ], tool: { messageID: "message-1", callID: "call-1" }, createdAt: 123, status: "pending", }, ], { session_id: "session-1", request_id: "call-1", questions: [ { header: "测试问题", question: "你觉得这个 question 工具好用吗?", options: [{ label: "非常好用", description: "交互清晰,选项方便" }], }, ], tool: { messageID: "message-1", callID: "call-1" }, created_at: 456, }, ); expect(questions).toHaveLength(1); expect(questions[0]).toMatchObject({ requestId: "question-1", tool: { callID: "call-1" }, status: "pending", }); }); }); describe("cancelBackendTodos", () => { it("marks pending and in-progress todos as cancelled", () => { const cancelled = cancelBackendTodos([ { sessionId: "session-1", todos: [ { id: "todo-1", content: "分析水位", status: "in_progress" }, { id: "todo-2", content: "生成建议", status: "pending" }, { id: "todo-3", content: "完成报告", status: "completed" }, ], createdAt: 123, }, ]); expect(cancelled).toEqual([ expect.objectContaining({ todos: [ expect.objectContaining({ id: "todo-1", status: "cancelled", updatedAt: expect.any(Number), }), expect.objectContaining({ id: "todo-2", status: "cancelled", updatedAt: expect.any(Number), }), expect.objectContaining({ id: "todo-3", status: "completed", }), ], }), ]); }); }); describe("completeBackendTodos", () => { it("marks pending and in-progress todos as completed after a successful run", () => { const completed = completeBackendTodos([ { sessionId: "session-1", todos: [ { id: "todo-1", content: "分析水位", status: "in_progress" }, { id: "todo-2", content: "生成建议", status: "pending" }, { id: "todo-3", content: "完成报告", status: "completed" }, ], createdAt: 123, }, ]); expect(completed).toEqual([ expect.objectContaining({ todos: [ expect.objectContaining({ id: "todo-1", status: "completed" }), expect.objectContaining({ id: "todo-2", status: "completed" }), expect.objectContaining({ id: "todo-3", status: "completed" }), ], }), ]); }); });