From 4311c3aebd3d2a4973dee744dec51031c933affc Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Fri, 28 Nov 2025 19:57:46 +0000 Subject: [PATCH] feat(codex): add structured file edit output with diffs for restored sessions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add structured output matching StructuredToolResult type for Codex apply_patch operations when parsing rollout files. This enables the frontend to render file edit diffs for restored Codex sessions, matching the behavior of Claude agent file edits. Note: For live streaming, the Codex SDK only provides file_change events with {path, kind} without actual patch content. The structured diffs are only available for restored sessions via rollout file parsing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../src/server/agent/providers/codex-agent.ts | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/packages/server/src/server/agent/providers/codex-agent.ts b/packages/server/src/server/agent/providers/codex-agent.ts index 719898eb0..5a50fdedc 100644 --- a/packages/server/src/server/agent/providers/codex-agent.ts +++ b/packages/server/src/server/agent/providers/codex-agent.ts @@ -609,7 +609,6 @@ class CodexAgentSession implements AgentSession { } private *translateEvent(event: ThreadEvent): Generator { - const permissionEvents = this.handlePermissionEvent(event); if (permissionEvents) { for (const permissionEvent of permissionEvents) { @@ -1147,8 +1146,17 @@ function finalizeRolloutFunctionCall( function handleRolloutCustomToolCall(payload: RolloutCustomToolCallPayload, events: AgentStreamEvent[]): void { if (payload?.name === "apply_patch" && typeof payload.input === "string") { - const files = parsePatchFiles(payload.input); + const patchText = payload.input; + const files = parsePatchFiles(patchText); if (files.length) { + // Build structured output with the patch/diff for each file + const parsedEdits = files.map((file) => ({ + filePath: file.path, + kind: file.kind, + // Include the full patch as diff - frontend will render it + diff: patchText, + })); + events.push({ type: "timeline", provider: "codex", @@ -1158,7 +1166,12 @@ function handleRolloutCustomToolCall(payload: RolloutCustomToolCallPayload, even status: "completed", displayName: buildFileChangeSummary(files), kind: "edit", - output: { files }, + output: { + type: "file_edit" as const, + filePath: files[0]?.path ?? "unknown", + diff: patchText, + parsedEdits, + }, }), }); }