Files
Jyotisha/frontend/tests/rectification-activity-receipt.test.ts
T
Jesse_Chen 6a44c778c3 fix(web): show live agent work progress and fail truncated rectification answers
Rectification dropped tool.activity started events and treated length finishes as completed. Share generation settings with consultation, keep the activity line through streaming, and name multi-domain chart calculation.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-21 12:39:09 +08:00

121 lines
4.3 KiB
TypeScript

import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import test from "node:test";
import {
createRectificationActivityReceiptState,
reduceRectificationActivityReceipt,
receiptFromRectificationActivityState,
} from "../src/lib/rectification-activity-receipt";
test("a successful retry clears the same tool's earlier failure", () => {
let state = createRectificationActivityReceiptState();
for (const event of [
{ tool: "rectification-read-case", status: "completed" },
{ tool: "rectification-propose-evidence", status: "failed" },
{ tool: "rectification-propose-evidence", status: "started" },
{ tool: "rectification-propose-evidence", status: "completed" },
{ tool: "rectification-confirm-evidence", status: "completed" },
] as const) {
state = reduceRectificationActivityReceipt(state, event);
}
assert.deepEqual(receiptFromRectificationActivityState(state), {
steps: [
"rectification-read-case",
"rectification-propose-evidence",
"rectification-confirm-evidence",
],
methods: [],
});
});
test("an unrecovered latest tool failure remains visible", () => {
let state = createRectificationActivityReceiptState();
state = reduceRectificationActivityReceipt(state, {
tool: "rectification-read-case",
status: "completed",
});
state = reduceRectificationActivityReceipt(state, {
tool: "rectification-propose-evidence",
status: "failed",
});
assert.deepEqual(receiptFromRectificationActivityState(state), {
steps: ["rectification-read-case"],
methods: [],
failedTool: "rectification-propose-evidence",
});
});
test("a later failure overrides an earlier completion for the same tool", () => {
let state = createRectificationActivityReceiptState();
state = reduceRectificationActivityReceipt(state, {
tool: "rectification-read-case",
status: "completed",
});
state = reduceRectificationActivityReceipt(state, {
tool: "rectification-read-case",
status: "failed",
});
assert.deepEqual(receiptFromRectificationActivityState(state), {
steps: [],
methods: [],
failedTool: "rectification-read-case",
});
});
test("a later failure removes methods contributed by the failed tool", () => {
let state = createRectificationActivityReceiptState();
state = reduceRectificationActivityReceipt(state, {
tool: "rectification-compare-candidates",
status: "completed",
methods: ["d1-rashi", "vimshottari-dasha"],
});
state = reduceRectificationActivityReceipt(state, {
tool: "rectification-read-diagnostics",
status: "completed",
methods: ["d1-rashi", "shadbala"],
});
state = reduceRectificationActivityReceipt(state, {
tool: "rectification-compare-candidates",
status: "failed",
});
assert.deepEqual(receiptFromRectificationActivityState(state), {
steps: ["rectification-read-diagnostics"],
methods: ["d1-rashi", "shadbala"],
failedTool: "rectification-compare-candidates",
});
});
const chatSource = readFileSync(
new URL("../src/components/rectification-agentic-chat.tsx", import.meta.url),
"utf8",
);
test("answer deltas preserve a still-running server activity", () => {
const deltaBranch = chatSource.slice(
chatSource.indexOf('event.type === "answer.delta"'),
chatSource.indexOf('event.type === "run.failed"'),
);
assert.match(deltaBranch, /state: "streaming"/);
assert.match(deltaBranch, /正在组织回答/);
assert.doesNotMatch(deltaBranch, /activeActivity:\s*undefined/);
});
test("failed server turns retain their receipt state without parsing activity from answer text", () => {
assert.match(chatSource, /failed:\s*true/);
assert.match(chatSource, /completedReceipt/);
assert.match(chatSource, /message\.state === "settled" && message\.failed/);
assert.doesNotMatch(chatSource, /parsed\.(?:activity|receipt|tools|methods)/);
});
test("candidate acceptance copy never presents adoption as confirmation", () => {
assert.match(chatSource, /当前可能的出生时间/);
assert.match(chatSource, /采用不等于确认出生时间/);
assert.match(chatSource, /当前排盘时间(代表性候选,还不能确认唯一分钟)/);
assert.match(chatSource, /已确认校正时间/);
assert.doesNotMatch(chatSource, /candidateResult\.confirmationAllowed \? "确认校正时间"/);
});