Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions apps/desktop/src/main/engine/backends/codex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -740,16 +740,18 @@ export function codexPhase(phase: string | null | undefined): MessagePhase {
* How a completed Codex tool item ended, from its own status (codex-cli 0.163.0): `declined` is a
* denial, `failed` a failure, `completed` a success, except a command that completed with a non-zero
* exit code (failed) or none at all (unknown). A command with no status is judged by its exit code.
* Any other item that reports no status (web search) is unknown unless it reports an error; so is a
* tool still `inProgress` when it completes. Exported for tests.
* A web search has neither a status nor an error field, so its `item/completed` is the only report it
* makes: it finished. Any other item without a status is unknown unless it reports an error, and so
* is a tool still `inProgress` when it completes. Exported for tests.
*/
export function codexOutcome(item: { type: string; status?: string; exitCode?: number | null; error?: unknown }): SettledOutcome {
if (item.status === "declined") return "denied";
if (item.status === "failed") return "failed";
const exit = item.exitCode === 0 ? "succeeded" : typeof item.exitCode === "number" ? "failed" : "unknown";
if (item.status === "completed") return item.type === "commandExecution" ? exit : "succeeded";
if (item.status === undefined && item.type === "commandExecution" && exit !== "unknown") return exit;
return item.error ? "failed" : "unknown";
if (item.error) return "failed";
return item.status === undefined && item.type === "webSearch" ? "succeeded" : "unknown";
}

function codexStepStatus(status: unknown): PlanStepStatus {
Expand Down
4 changes: 3 additions & 1 deletion apps/desktop/test/conversation-events.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,9 @@ test("every Codex 0.163.0 phase and tool status has a mapping, and none but a cl
assert.equal(codexOutcome({ type: "commandExecution", status: "completed", exitCode: null }), "unknown");
assert.equal(codexOutcome({ type: "commandExecution", exitCode: 0 }), "succeeded", "no status: the exit code decides");
assert.equal(codexOutcome({ type: "commandExecution", exitCode: 1 }), "failed");
assert.equal(codexOutcome({ type: "webSearch" }), "unknown", "web search reports no status");
// codex-cli 0.163.0's webSearch item has neither a status nor an error field, so item/completed is
// the only report a search makes: it finished. Unknown stays for work that never reported (#277).
assert.equal(codexOutcome({ type: "webSearch" }), "succeeded", "a web search that completed finished");
assert.equal(codexOutcome({ type: "mcpToolCall", error: { message: "boom" } }), "failed");
});

Expand Down
2 changes: 1 addition & 1 deletion docs/conversation-events.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ id and the item id.
| `completed`, any other tool | `succeeded` |
| `inProgress` when the item completes | `unknown` |
| no status, a command with an exit code | from the exit code |
| no status (web search), no error | `unknown` |
| no status (web search), no error | `succeeded`: codex-cli 0.163.0 gives a web search no status or error field, so its completion is its only report |
| no status, an error | `failed` |

`turn/completed` ends the turn: `completed`, `interrupted` and `failed` become the attempt's
Expand Down
4 changes: 4 additions & 0 deletions docs/status.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ and [landing verification](reviews/2026-10-11-landing-clarity.md).
turn, still holding its edit, changed since, deleted since, or not compared, with the reason.
Main reads only the named files inside the thread's folder and returns verdicts, never contents.
Codex file changes now keep their per-file paths beside the patch.
- **Codex web searches fold away again when a turn finishes.** Since #284, work whose result is
unknown stays in view, and every Codex web search read as unknown: codex-cli 0.163.0 gives a
search no status or error field. Its completion is its only report, so a completed search now
reads as done and folds like other finished work (#277).

## In flight

Expand Down
Loading