import assert from "node:assert/strict"; import test from "node:test"; import { backendEventToUiChunk } from "./cad-stream"; import { activeCheckpointPreview, latestSuccessfulResult } from "./cad-artifacts"; import { messagesForBackend } from "./cad-messages"; import type { CadUIMessage } from "./cad-types"; test("maps backend cad_result SSE into an AI SDK data part", () => { const chunk = backendEventToUiChunk({ event: "cad_result", data: { taskId: "cad_abc", revisionId: "rev_001" }, }, "text_1"); assert.equal(chunk?.type, "data-cad-result"); assert.deepEqual("data" in chunk! ? chunk.data : null, { taskId: "cad_abc", revisionId: "rev_001" }); }); test("keeps progressive revisions as separate data parts", () => { const first = backendEventToUiChunk({ event: "cad_result", data: { taskId: "cad_abc", revisionId: "rev_001" } }, "text_1"); const second = backendEventToUiChunk({ event: "cad_result", data: { taskId: "cad_abc", revisionId: "rev_002" } }, "text_1"); assert.notEqual(first?.id, second?.id); }); test("maps final visual repair review into a blocking progress state", () => { const chunk = backendEventToUiChunk({ event: "final_review", data: { taskId: "cad_abc", review: { verdict: "repair", confidence: 0.92, evidence: ["missing round"] } }, }, "text_1"); assert.equal(chunk?.type, "data-cad-progress"); assert.deepEqual("data" in chunk! ? chunk.data : null, { step: "final_review", label: "最终视觉复核", status: "error", message: "missing round", taskId: "cad_abc", }); }); test("maps a rejected independent candidate review into a blocking progress state", () => { const chunk = backendEventToUiChunk({ event: "candidate_review", data: { taskId: "cad_abc", review: { verdict: "reject", evidence: ["base is disconnected"] } }, }, "text_1"); assert.equal(chunk?.type, "data-cad-progress"); assert.deepEqual("data" in chunk! ? chunk.data : null, { step: "candidate_review", label: "候选独立复核", status: "error", message: "base is disconnected", taskId: "cad_abc", }); }); test("maps a modeling plan revision request into a blocking progress state", () => { const chunk = backendEventToUiChunk({ event: "modeling_plan_review", data: { taskId: "cad_abc", review: { verdict: "revise", issues: [{ message: "split unrelated finish" }] } }, }, "text_1"); assert.equal(chunk?.type, "data-cad-progress"); assert.equal("data" in chunk! ? (chunk.data as { label?: string }).label : null, "计划独立复核"); assert.equal("data" in chunk! ? (chunk.data as { status?: string }).status : null, "error"); }); test("keeps a server-verified plan skip visible in the timeline", () => { const chunk = backendEventToUiChunk({ event: "plan_step_skipped", data: { taskId: "cad_abc", planStepId: "step_6", nextPlanStepId: "", evidenceRef: "completion_ledger:rev_008", status: "success", message: "The current revision already satisfies this plan step.", }, }, "text_1"); assert.equal(chunk?.type, "data-cad-progress"); assert.equal("data" in chunk! ? (chunk.data as { label?: string }).label : null, "计划步骤已满足"); assert.equal("data" in chunk! ? (chunk.data as { status?: string }).status : null, "success"); }); test("gives repeated tool events unique ordered parts", () => { const first = backendEventToUiChunk({ event: "tool_call", data: { taskId: "cad_abc", tool: "inspect_model", status: "running" } }, "text_1", 4); const second = backendEventToUiChunk({ event: "tool_call", data: { taskId: "cad_abc", tool: "inspect_model", status: "success" } }, "text_1", 5); assert.notEqual(first?.id, second?.id); assert.equal("data" in first! ? (first.data as { sequence?: number }).sequence : null, 4); assert.equal("data" in second! ? (second.data as { sequence?: number }).sequence : null, 5); }); test("reuses an invocation id so tool completion updates its running card", () => { const running = backendEventToUiChunk({ event: "tool_call", data: { taskId: "cad_abc", eventId: "call_1", invocationId: "call_1", tool: "submit_cdsl_fragment", status: "running" } }, "text_1", 4); const complete = backendEventToUiChunk({ event: "tool_call", data: { taskId: "cad_abc", eventId: "call_1", invocationId: "call_1", tool: "submit_cdsl_fragment", status: "success" } }, "text_1", 5); assert.equal(running?.id, complete?.id); }); test("keeps frozen requirement markdown visible in the timeline", () => { const chunk = backendEventToUiChunk({ event: "requirements_document", data: { taskId: "cad_abc", status: "frozen", markdown: "# 冻结需求\n\n- 创建底座" }, }, "text_1", 2); assert.equal(chunk?.type, "data-cad-progress"); assert.equal("data" in chunk! ? (chunk.data as { markdown?: string }).markdown : null, "# 冻结需求\n\n- 创建底座"); }); test("restores the latest successful task revision for the viewer", () => { const result = latestSuccessfulResult({ task_id: "cad_abc", current_revision: "rev_002", revisions: [ { revision_id: "rev_001", status: "success", cdsl_path: "a", step_path: "b", glb_path: "c", report_path: "d" }, { revision_id: "rev_002", status: "success", cdsl_path: "aa", step_path: "bb", glb_path: "cc", report_path: "dd", summary: "done" }, ], }); assert.equal(result?.glbPath, "cc"); assert.equal(result?.summary, "done"); }); test("prefers the published revision over an active checkpoint", () => { const result = latestSuccessfulResult({ task_id: "cad_abc", current_revision: "rev_002", active_revision: "rev_002", published_revision: "rev_001", lifecycle: "running", revisions: [ { revision_id: "rev_001", status: "success", visibility: "final", cdsl_path: "a", step_path: "b", glb_path: "c", report_path: "d" }, { revision_id: "rev_002", status: "success", visibility: "checkpoint", cdsl_path: "aa", step_path: "bb", glb_path: "cc", report_path: "dd" }, ], }); assert.equal(result?.revisionId, "rev_001"); assert.equal(result?.checkpoint, false); }); test("does not restore a private checkpoint after a failed run", () => { const result = latestSuccessfulResult({ task_id: "cad_abc", current_revision: "rev_002", active_revision: "rev_002", lifecycle: "failed", revisions: [ { revision_id: "rev_002", status: "success", visibility: "checkpoint", cdsl_path: "aa", step_path: "bb", glb_path: "cc", report_path: "dd" }, ], }); assert.equal(result, null); }); test("restores an active checkpoint only while the task is running", () => { const result = activeCheckpointPreview({ task_id: "cad_abc", current_revision: "rev_002", active_revision: "rev_002", published_revision: "rev_001", lifecycle: "running", revisions: [ { revision_id: "rev_001", status: "success", visibility: "final", cdsl_path: "a", step_path: "b", glb_path: "c", report_path: "d" }, { revision_id: "rev_002", status: "success", visibility: "checkpoint", cdsl_path: "aa", step_path: "bb", glb_path: "cc", report_path: "dd" }, ], }); assert.equal(result?.revisionId, "rev_002"); assert.equal(result?.checkpoint, true); }); test("strips non-text and non-CAD parts before sending to FastAPI", () => { const messages: CadUIMessage[] = [{ id: "m1", role: "assistant", parts: [ { type: "text", text: "hello" }, { type: "data-cad-progress", data: { step: "s", label: "S", status: "running" } }, { type: "file", mediaType: "model/gltf-binary", url: "/x.glb" }, ], }]; assert.deepEqual(messagesForBackend(messages)[0].parts, [ { type: "text", text: "hello" }, { type: "data-cad-progress", data: { step: "s", label: "S", status: "running" } }, ]); });