fix(frontend): recover rectification and consultation retries
This commit is contained in:
@@ -159,6 +159,54 @@ test("domain plan enforces the raw plan upper bound and one input mode", async (
|
||||
assert.equal(calls, 0);
|
||||
});
|
||||
|
||||
test("invalid model input does not poison a later valid contract retry", async () => {
|
||||
let calls = 0;
|
||||
const state = createConsultationRuntimeState();
|
||||
const tool = createConsultationTools({
|
||||
userId: "u", sessionId: "s", requestId: "r-retry", consultationMode: "verified_chart",
|
||||
serverChart, state,
|
||||
runWorkflow: async (input) => { calls += 1; return workflow(input.theme); },
|
||||
})["run-jyotish-consultation"];
|
||||
const context = { observe: { span: async (_n: string, fn: () => Promise<unknown>) => fn(), log() {} } } as never;
|
||||
|
||||
await assert.rejects(
|
||||
tool.execute!({ question: "先给出错误参数", domains: ["career"], theme: "career" }, context),
|
||||
/invalid_consultation_domain_plan/,
|
||||
);
|
||||
assert.equal(calls, 0);
|
||||
assert.equal(state.consultationToolCallCount, 0);
|
||||
|
||||
const result = await tool.execute!({ question: "改用合法参数", theme: "timing" }, context) as { domains: string[] };
|
||||
assert.equal(calls, 1);
|
||||
assert.deepEqual(result.domains, ["timing"]);
|
||||
assert.equal(state.consultationToolCallCount, 1);
|
||||
assert.equal(state.consultationToolCompleted, true);
|
||||
});
|
||||
|
||||
test("a rejected workflow promise is cleared before a later tool call", async () => {
|
||||
let calls = 0;
|
||||
const state = createConsultationRuntimeState();
|
||||
const tool = createConsultationTools({
|
||||
userId: "u", sessionId: "s", requestId: "r-rejected-promise", consultationMode: "verified_chart",
|
||||
serverChart, state,
|
||||
runWorkflow: async (input) => {
|
||||
calls += 1;
|
||||
if (calls === 1) throw new Error("workflow_temporarily_failed");
|
||||
return workflow(input.theme);
|
||||
},
|
||||
})["run-jyotish-consultation"];
|
||||
const context = { observe: { span: async (_n: string, fn: () => Promise<unknown>) => fn(), log() {} } } as never;
|
||||
|
||||
await assert.rejects(
|
||||
tool.execute!({ question: "第一次计算", theme: "career" }, context),
|
||||
/workflow_temporarily_failed/,
|
||||
);
|
||||
const result = await tool.execute!({ question: "重新计算", theme: "timing" }, context) as { domains: string[] };
|
||||
|
||||
assert.equal(calls, 2);
|
||||
assert.deepEqual(result.domains, ["timing"]);
|
||||
});
|
||||
|
||||
test("personal Agent exposes the Jyotish Skill and named server tool", async () => {
|
||||
const state = createConsultationRuntimeState();
|
||||
const agent = getJyotishAgent({
|
||||
|
||||
@@ -102,6 +102,30 @@ test("server profile failures pause automatic rectification resume", () => {
|
||||
);
|
||||
});
|
||||
|
||||
test("homepage rectification open failures always surface a visible recovery message", () => {
|
||||
const opening = page.slice(
|
||||
page.indexOf("async function openRectificationCase"),
|
||||
page.indexOf("async function openRectificationFromHomepage"),
|
||||
);
|
||||
|
||||
assert.match(
|
||||
opening,
|
||||
/code === "profile_incomplete"[\s\S]*?handleRectificationProfileIncomplete\(\)/,
|
||||
);
|
||||
assert.match(
|
||||
opening,
|
||||
/code === "invalid_open_request"[\s\S]*?setRectificationError\(/,
|
||||
);
|
||||
assert.match(
|
||||
opening,
|
||||
/catch \{[\s\S]*?setRectificationError\("生时校正会话暂时无法打开,请稍后重试。"\)/,
|
||||
);
|
||||
assert.match(
|
||||
page,
|
||||
/rectificationError && !rectificationSurfaceOpen && \([\s\S]*?role="alert"[\s\S]*?rectificationErrorMessage/,
|
||||
);
|
||||
});
|
||||
|
||||
test("account rehydration normalizes persisted ISO birth dates before completeness checks", () => {
|
||||
const profileReader = page.slice(
|
||||
page.indexOf("function readProfile"),
|
||||
|
||||
Reference in New Issue
Block a user