fix(web): isolate rectification answers from tool-step planning text

Mastra intermediate text-delta was published as answer.delta, then set-focus domain errors reset the attempt and replayed evidence. Publish only the terminal no-tool step, persist the next probe on the server, and ground batch quotes in the source turn.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-08-24 21:26:57 +08:00
co-authored by Cursor
parent 167bdad20d
commit fe87a9ecdb
30 changed files with 1373 additions and 237 deletions
+11 -6
View File
@@ -75,13 +75,12 @@ test("system prompt carries only high-priority boundaries, never the method copy
assert.match(prompt, /方法覆盖已齐只进入候选区分/);
assert.doesNotMatch(prompt, /方法覆盖已齐且 propose_allowed 时本轮 adopt/);
assert.match(prompt, /不得询问外貌、体质、胎记或疤痕/);
assert.match(prompt, /expectedAnswerSchema.choice/);
assert.match(prompt, /不要写 choice/);
assert.match(prompt, /「先这样」由服务器补全/);
assert.match(prompt, /不要调用 rectification-set-focus/);
assert.match(prompt, /open_question\.prompt/);
assert.match(prompt, /「先这样」由服务器/);
assert.match(prompt, /盘外核对(不计分)/);
assert.match(prompt, /verify_adopted_time/);
assert.match(prompt, /event_probe/);
assert.match(prompt, /题干由你写成自然语言/);
assert.match(prompt, /不得发明年份/);
assert.doesNotMatch(prompt, /两套盘各自的前事/);
assert.doesNotMatch(prompt, /外貌、体质、胎记或疤痕可以问/);
@@ -302,7 +301,13 @@ test("server-loaded Skill is bound before the provider and the first model step
toolChoice: "auto",
});
assert.equal(typeof firstStep?.toolChoice, "string");
assert.equal(await observedStreamOptions.prepareStep?.({ stepNumber: 1 }), undefined);
assert.deepEqual(
(await observedStreamOptions.prepareStep?.({ stepNumber: 1 }) as { activeTools?: string[] }).activeTools?.includes("rectification-set-focus"),
false,
);
assert.ok(
((await observedStreamOptions.prepareStep?.({ stepNumber: 1 })) as { activeTools?: string[] }).activeTools?.includes("rectification-read-case"),
);
assert.equal(observedStreamOptions.modelSettings?.maxOutputTokens, 8192);
assert.deepEqual(observedStreamOptions.providerOptions?.openai, { thinking: { type: "disabled" } });
assert.equal(emitted.filter((event) => event.type === "skill.bound").length, 1);
@@ -410,7 +415,7 @@ test("a repeated identical tool call is detected and aborts the turn", async ()
chunk("start"),
chunk("tool-call", { toolName: "skill", args: { name: RECTIFICATION_SKILL_NAME } }),
chunk("tool-result", { toolName: "skill" }),
...Array.from({ length: 4 }, () => chunk("tool-call", { toolName: "rectification-read-case", args: { caseId: CASE_ID } })),
...Array.from({ length: 2 }, () => chunk("tool-call", { toolName: "rectification-read-case", args: { caseId: CASE_ID } })),
chunk("finish"),
]) as never,
});