























@@ -465,6 +465,60 @@ describe("repairSessionFileIfNeeded", () => {
465465expect(after).toBe(original);
466466});
467467468+it("preserves final text assistant turn that follows a tool-call/tool-result pair", async () => {
469+// Regression: a trailing assistant message with stopReason "stop" that follows a
470+// tool-call turn and its matching tool-result must never be trimmed by the repair
471+// pass. This is the exact sequence produced by any agent run that calls at least
472+// one tool before returning a final text response, and it must survive intact so
473+// subsequent user messages are parented to the correct leaf node.
474+const { file } = await createTempSessionPath();
475+const { header, message } = buildSessionHeaderAndMessage();
476+const toolCallAssistant = {
477+type: "message",
478+id: "msg-asst-tc",
479+parentId: "msg-1",
480+timestamp: new Date().toISOString(),
481+message: {
482+role: "assistant",
483+content: [{ type: "toolCall", id: "call_1", name: "get_tasks", input: {} }],
484+stopReason: "toolUse",
485+},
486+};
487+const toolResult = {
488+type: "message",
489+id: "msg-tool-result",
490+parentId: "msg-asst-tc",
491+timestamp: new Date().toISOString(),
492+message: {
493+role: "toolResult",
494+toolCallId: "call_1",
495+toolName: "get_tasks",
496+content: [{ type: "text", text: "Task A, Task B" }],
497+isError: false,
498+},
499+};
500+const finalAssistant = {
501+type: "message",
502+id: "msg-asst-final",
503+parentId: "msg-tool-result",
504+timestamp: new Date().toISOString(),
505+message: {
506+role: "assistant",
507+content: [{ type: "text", text: "Here are your tasks: Task A, Task B." }],
508+stopReason: "stop",
509+},
510+};
511+const original = `${JSON.stringify(header)}\n${JSON.stringify(message)}\n${JSON.stringify(toolCallAssistant)}\n${JSON.stringify(toolResult)}\n${JSON.stringify(finalAssistant)}\n`;
512+await fs.writeFile(file, original, "utf-8");
513+514+const result = await repairSessionFileIfNeeded({ sessionFile: file });
515+516+expect(result.repaired).toBe(false);
517+518+const after = await fs.readFile(file, "utf-8");
519+expect(after).toBe(original);
520+});
521+468522it("preserves assistant-only session history after the header", async () => {
469523const { file } = await createTempSessionPath();
470524const { header } = buildSessionHeaderAndMessage();
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。