
























@@ -2895,6 +2895,18 @@ describe("runCodexAppServerAttempt", () => {
28952895});
2896289628972897await harness.waitForMethod("turn/start");
2898+await harness.handleServerRequest({
2899+id: "request-tool-1",
2900+method: "item/tool/call",
2901+params: {
2902+threadId: "thread-1",
2903+turnId: "turn-1",
2904+callId: "call-1",
2905+namespace: null,
2906+tool: "message",
2907+arguments: { action: "send", text: "already sent" },
2908+},
2909+});
28982910await harness.notify({
28992911method: "rawResponseItem/completed",
29002912params: {
@@ -2922,6 +2934,58 @@ describe("runCodexAppServerAttempt", () => {
29222934expect(harness.request.mock.calls.some(([method]) => method === "turn/interrupt")).toBe(false);
29232935});
292429362937+it("does not treat a user prompt containing the interrupted marker as terminal", async () => {
2938+const harness = createStartedThreadHarness();
2939+const run = runCodexAppServerAttempt(
2940+createParams(path.join(tempDir, "session.jsonl"), path.join(tempDir, "workspace")),
2941+{ turnTerminalIdleTimeoutMs: 60_000 },
2942+);
2943+let resolved = false;
2944+void run.then(() => {
2945+resolved = true;
2946+});
2947+2948+await harness.waitForMethod("turn/start");
2949+await harness.notify({
2950+method: "rawResponseItem/completed",
2951+params: {
2952+threadId: "thread-1",
2953+turnId: "turn-1",
2954+item: {
2955+id: "user-prompt-1",
2956+type: "message",
2957+role: "user",
2958+content: [
2959+{
2960+type: "input_text",
2961+text: "What does <turn_aborted> mean?",
2962+},
2963+],
2964+},
2965+},
2966+});
2967+await new Promise((resolve) => setTimeout(resolve, 20));
2968+expect(resolved).toBe(false);
2969+2970+await harness.notify({
2971+method: "turn/completed",
2972+params: {
2973+threadId: "thread-1",
2974+turn: {
2975+id: "turn-1",
2976+status: "completed",
2977+items: [{ type: "agentMessage", id: "msg-1", text: "It marks an interrupted turn." }],
2978+},
2979+},
2980+});
2981+2982+const result = await run;
2983+expect(resolved).toBe(true);
2984+expect(result.aborted).toBe(false);
2985+expect(result.timedOut).toBe(false);
2986+expect(result.assistantTexts).toEqual(["It marks an interrupted turn."]);
2987+});
2988+29252989it("releases completion when a projector callback throws during turn/completed", async () => {
29262990// Regression for openclaw/openclaw#67996: a throw inside the projector's
29272991// turn/completed handler must not strand resolveCompletion, otherwise the
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。