Skip to content

Commit 1f272b3

Browse files
committed
fix(codex): clarify unsafe app-server completion stalls
1 parent 938b2a8 commit 1f272b3

5 files changed

Lines changed: 45 additions & 7 deletions

File tree

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { describe, expect, it } from "vitest";
2+
import { describeNotificationActivity } from "./attempt-notifications.js";
3+
4+
describe("Codex app-server attempt notifications", () => {
5+
it("describes completed item activity for timeout diagnostics", () => {
6+
expect(
7+
describeNotificationActivity({
8+
method: "item/completed",
9+
params: {
10+
threadId: "thread-1",
11+
turnId: "turn-1",
12+
item: {
13+
id: "tool-1",
14+
type: "dynamicToolCall",
15+
tool: "sessions_list",
16+
status: "completed",
17+
},
18+
},
19+
}),
20+
).toEqual({
21+
lastNotificationMethod: "item/completed",
22+
lastNotificationItemId: "tool-1",
23+
lastNotificationItemType: "dynamicToolCall",
24+
lastNotificationItemRole: undefined,
25+
lastNotificationItemStatus: "completed",
26+
lastNotificationTool: "sessions_list",
27+
});
28+
});
29+
});

extensions/codex/src/app-server/attempt-notifications.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,19 @@ export function describeNotificationActivity(
2424
if (!isJsonObject(notification.params)) {
2525
return { lastNotificationMethod: notification.method };
2626
}
27+
const item = isJsonObject(notification.params.item) ? notification.params.item : undefined;
2728
if (notification.method !== "rawResponseItem/completed") {
28-
return { lastNotificationMethod: notification.method };
29+
return item
30+
? {
31+
lastNotificationMethod: notification.method,
32+
lastNotificationItemId: readString(item, "id"),
33+
lastNotificationItemType: readString(item, "type"),
34+
lastNotificationItemRole: readString(item, "role"),
35+
lastNotificationItemStatus: readString(item, "status"),
36+
lastNotificationTool: readString(item, "tool") ?? readString(item, "name"),
37+
}
38+
: { lastNotificationMethod: notification.method };
2939
}
30-
const item = isJsonObject(notification.params.item) ? notification.params.item : undefined;
3140
if (!item) {
3241
return { lastNotificationMethod: notification.method };
3342
}

extensions/codex/src/app-server/attempt-results.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ describe("Codex app-server attempt results", () => {
8585
}),
8686
).toEqual({
8787
message:
88-
"Codex stopped before confirming the turn was complete. Some work may already have been performed; verify the current state before retrying.",
88+
"Codex stopped after tool activity before confirming the turn was complete. Some work may already have been performed, so OpenClaw did not replay the turn automatically. Verify the current state before retrying.",
8989
replayInvalid: true,
9090
livenessState: "abandoned",
9191
});

extensions/codex/src/app-server/attempt-results.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import type { CodexSystemPromptReport } from "./attempt-context.js";
88
const CODEX_APP_SERVER_MISSING_TERMINAL_EVENT_USER_MESSAGE =
99
"Codex stopped before confirming the turn was complete. The response may be incomplete; retry if needed.";
1010
const CODEX_APP_SERVER_MISSING_TERMINAL_EVENT_SIDE_EFFECT_USER_MESSAGE =
11-
"Codex stopped before confirming the turn was complete. Some work may already have been performed; verify the current state before retrying.";
11+
"Codex stopped after tool activity before confirming the turn was complete. Some work may already have been performed, so OpenClaw did not replay the turn automatically. Verify the current state before retrying.";
1212

1313
export function collectTerminalAssistantText(result: EmbeddedRunAttemptResult): string {
1414
return result.assistantTexts.join("\n\n").trim();

extensions/codex/src/app-server/run-attempt.turn-watches.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ describe("runCodexAppServerAttempt turn watches", () => {
151151
expect(result.itemLifecycle.completedCount).toBe(1);
152152
expect(result.promptTimeoutOutcome).toEqual({
153153
message:
154-
"Codex stopped before confirming the turn was complete. Some work may already have been performed; verify the current state before retrying.",
154+
"Codex stopped after tool activity before confirming the turn was complete. Some work may already have been performed, so OpenClaw did not replay the turn automatically. Verify the current state before retrying.",
155155
replayInvalid: true,
156156
livenessState: "abandoned",
157157
});
@@ -198,7 +198,7 @@ describe("runCodexAppServerAttempt turn watches", () => {
198198
}),
199199
).toEqual({
200200
message:
201-
"Codex stopped before confirming the turn was complete. Some work may already have been performed; verify the current state before retrying.",
201+
"Codex stopped after tool activity before confirming the turn was complete. Some work may already have been performed, so OpenClaw did not replay the turn automatically. Verify the current state before retrying.",
202202
replayInvalid: true,
203203
livenessState: "abandoned",
204204
});
@@ -237,7 +237,7 @@ describe("runCodexAppServerAttempt turn watches", () => {
237237
expect(result.itemLifecycle).toMatchObject({ activeCount: 1, completedCount: 0 });
238238
expect(result.promptTimeoutOutcome).toEqual({
239239
message:
240-
"Codex stopped before confirming the turn was complete. Some work may already have been performed; verify the current state before retrying.",
240+
"Codex stopped after tool activity before confirming the turn was complete. Some work may already have been performed, so OpenClaw did not replay the turn automatically. Verify the current state before retrying.",
241241
replayInvalid: true,
242242
livenessState: "abandoned",
243243
});

0 commit comments

Comments
 (0)