























@@ -4,6 +4,10 @@ import path from "node:path";
44import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
55import { loadSessionStore, type SessionEntry } from "../config/sessions.js";
66import { callGateway } from "../gateway/call.js";
7+import {
8+INTERNAL_RUNTIME_CONTEXT_BEGIN,
9+INTERNAL_RUNTIME_CONTEXT_END,
10+} from "./internal-runtime-context.js";
711import {
812markRestartAbortedMainSessionsFromLocks,
913recoverRestartAbortedMainSessions,
@@ -330,6 +334,47 @@ describe("main-session-restart-recovery", () => {
330334);
331335});
332336337+it("sanitizes durable pending final delivery payloads before resume prompts", async () => {
338+const sessionsDir = await makeSessionsDir();
339+const pendingPayload = [
340+"The final answer is 42.",
341+INTERNAL_RUNTIME_CONTEXT_BEGIN,
342+"internal recovery detail",
343+INTERNAL_RUNTIME_CONTEXT_END,
344+"",
345+"Conversation info (untrusted metadata):",
346+"```json",
347+'{"message_id":"msg-1"}',
348+"```",
349+].join("\n");
350+await writeStore(sessionsDir, {
351+"agent:main:main": {
352+sessionId: "main-session",
353+updatedAt: Date.now() - 10_000,
354+status: "running",
355+abortedLastRun: true,
356+pendingFinalDelivery: true,
357+pendingFinalDeliveryText: pendingPayload,
358+pendingFinalDeliveryCreatedAt: Date.now() - 5_000,
359+},
360+});
361+await writeTranscript(sessionsDir, "main-session", [
362+{ role: "user", content: "calculate the answer" },
363+{ role: "assistant", content: [{ type: "toolCall", id: "call-1", name: "calc" }] },
364+{ role: "toolResult", content: "42" },
365+]);
366+367+const result = await recoverRestartAbortedMainSessions({ stateDir: tmpDir });
368+369+expect(result).toEqual({ recovered: 1, failed: 0, skipped: 0 });
370+expect(firstGatewayParams().message).toContain("The final answer is 42.");
371+expect(firstGatewayParams().message).not.toContain(INTERNAL_RUNTIME_CONTEXT_BEGIN);
372+expect(firstGatewayParams().message).not.toContain("Conversation info");
373+374+const store = loadSessionStore(path.join(sessionsDir, "sessions.json"));
375+expect(store["agent:main:main"]?.pendingFinalDeliveryText).toBe("The final answer is 42.");
376+});
377+333378it("does not scan ordinary running sessions without the restart-aborted marker", async () => {
334379const sessionsDir = await makeSessionsDir();
335380await writeStore(sessionsDir, {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。