import { describe, expect, it } from "bun:test"; import publishPresentation from "../../.opencode/tools/publish_task_presentation.js"; import publishProgress from "../../.opencode/tools/publish_task_progress.js"; import { taskPublicationCommandSchema, taskPublicationGraphProgressSchema } from "../../.opencode/tools/task-publication-schema.js"; import { taskProgressSchema } from "../../src/product/investigation-report.js"; import { taskPresentationCommandSchema } from "../../src/product/task-presentation.js"; describe("task presentation input boundaries", () => { it("accepts finite display commands and rejects unsupported data, layers and chart evidence", () => { const chart = { title: "压力", chart_type: "line", x_data: ["10:00"], series: [{ name: "MP01", data: [0.4] }] }; const commands = [ { action: "highlight_features", layer: "scada", feature_ids: ["MP01"], effect: "pulse" }, { action: "clear_highlights" }, { action: "open_chart", chart_id: "pressure", chart, evidence_refs: ["reading-1"] }, { action: "close_chart", chart_id: "pressure" }, { action: "set_overlay", overlay_id: "complaints", title: "实际投诉", mode: "heatmap", evidence_id: "query-1" }, { action: "clear_overlay", overlay_id: "complaints" }, ]; for (const command of commands) { expect(taskPresentationCommandSchema.parse(taskPublicationCommandSchema.parse(command))).toEqual(taskPresentationCommandSchema.parse(command)); } for (const command of [ { ...commands[0], layer: "drainage" }, { ...commands[2], evidence_refs: [] }, { ...commands[2], chart: { ...chart, series: [{ name: "MP01", data: [0.4, 0.5] }] } }, { ...commands[4], data: { coordinates: [1, 2] } }, { ...commands[4], script: "alert(1)" }, ]) expect(() => taskPresentationCommandSchema.parse(command)).toThrow(); }); it("exposes incremental graph updates instead of generated Mermaid to the Agent", () => { const update = { summary: "首次定位超时,调整窗口重试", graph_update: { nodes: [{ node_id: "locate_1", label: "首次定位", status: "failed", detail: "计算超时" }, { node_id: "locate_2", label: "调整窗口重试", status: "reference" }], edges: [{ source: "locate_1", target: "locate_2", label: "重试" }], } }; expect(taskProgressSchema.parse(taskPublicationGraphProgressSchema.parse(update))) .toEqual(taskProgressSchema.parse(update)); expect(taskPublicationGraphProgressSchema.safeParse({ summary: "重新生成", diagram: { title: "替换图", mermaid: "flowchart TD\nA[新图]", } }).success).toBe(false); expect(taskProgressSchema.safeParse({ ...update, diagram: { title: "替换图", mermaid: "flowchart TD\nA[新图]", } }).success).toBe(false); expect(taskProgressSchema.parse(taskPublicationGraphProgressSchema.parse({ summary: "继续等待" }))) .toEqual({ summary: "继续等待", diagram: null }); }); it("accepts optional reference annotations and rejects live execution states in new graph updates", () => { for (const status of [undefined, "reference", "recorded", "needs_input", "failed", "not_taken"]) { const progress = { summary: "整理流程参考", graph_update: { nodes: [{ node_id: "check", label: "核查路线", ...(status ? { status } : {}) }], edges: [], } }; expect(taskPublicationGraphProgressSchema.safeParse(progress).success).toBe(true); expect(taskProgressSchema.safeParse(progress).success).toBe(true); } for (const status of ["running", "completed", "pending", "waiting", "waiting_human", "skipped", "cancelled"]) { const progress = { summary: "整理流程参考", graph_update: { nodes: [{ node_id: "check", label: "核查路线", status }], edges: [], } }; expect(taskPublicationGraphProgressSchema.safeParse(progress).success).toBe(false); expect(taskProgressSchema.safeParse(progress).success).toBe(false); } }); it("revalidates semantic chart and Mermaid inputs before sending a tool request", async () => { const request_id = "60000000-0000-4000-8000-000000000001"; await expect(publishPresentation.execute({ request_id, command: { action: "open_chart", chart_id: "pressure", evidence_refs: ["reading-1"], chart: { title: "压力", chart_type: "line", x_data: ["10:00"], series: [{ name: "MP01", data: [0.4, 0.5] }] }, } }, { sessionID: "test" })).rejects.toThrow("series must align"); await expect(publishProgress.execute({ request_id, progress: { summary: "查询", diagram: { title: "路线", mermaid: "flowchart TD; A-->B; click A callback", node_refs: [] }, } } as never, { sessionID: "test" })).rejects.toThrow(); await expect(publishProgress.execute({ request_id, progress: { summary: "查询", diagram: { title: "路线", mermaid: "flowchart TD\nA-->B", node_refs: [{ node_id: "query", label: "查询", status: "running", evidence_refs: [], action_refs: [], map_targets: [] }] }, } } as never, { sessionID: "test" })).rejects.toThrow(); }); });