Skip to content

Make apply_patch streaming parser stateful#19160

Merged
akshaynathan merged 13 commits into
mainfrom
codex/stateful-apply-patch-streaming
Apr 30, 2026
Merged

Make apply_patch streaming parser stateful#19160
akshaynathan merged 13 commits into
mainfrom
codex/stateful-apply-patch-streaming

Conversation

@akshaynathan

@akshaynathan akshaynathan commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Adds an incremental "streaming" parser for apply_patch. Instead of reparsing the entire patch every time, the incremental parser holds the current state and only parses the delta (line by line). Local n=1 benchmark shows this is 10-15x faster on reasonably sized patches.

@akshaynathan akshaynathan force-pushed the codex/stateful-apply-patch-streaming branch 15 times, most recently from 7bf74ff to 6374f9f Compare April 24, 2026 23:25
@akshaynathan akshaynathan force-pushed the codex/stateful-apply-patch-streaming branch from 6374f9f to 4c0c1b7 Compare April 24, 2026 23:46
Wires patch_updated events through app_server. These events are parsed
and streamed while apply_patch is being written by the model. Also adds 500ms of buffering to the patch_updated events in the diff_consumer.

The eventual goal is to use this to display better progress indicators in
the codex app.
…patch-streaming

# Conflicts:
#	codex-rs/app-server-protocol/schema/json/ServerNotification.json
#	codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json
#	codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json
#	codex-rs/app-server-protocol/schema/typescript/ServerNotification.ts
#	codex-rs/core/src/tools/handlers/apply_patch.rs
#	codex-rs/core/src/tools/handlers/apply_patch_tests.rs
@akshaynathan akshaynathan requested a review from pakrym-oai April 25, 2026 05:29
@akshaynathan akshaynathan marked this pull request as ready for review April 25, 2026 15:42
@akshaynathan akshaynathan requested a review from a team as a code owner April 25, 2026 15:42

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f2924bf70c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines 86 to 88
let hunks = self.parser.push_delta(delta).ok()??;
let changes = convert_apply_patch_hunks_to_protocol(&hunks);
self.last_progress = Some(hunks);
let event = PatchApplyUpdatedEvent { call_id, changes };

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Skip emitting unchanged apply_patch progress events

ApplyPatchArgumentDiffConsumer::push_delta now converts and emits an update for every successful parser call, but StreamingPatchParser::push_delta can return the same hunk set even when the incoming delta contains no newline (so no new patch line was actually parsed). In streamed custom-tool calls with long lines, this produces repeated identical PatchApplyUpdated payloads every buffer window, which the app-server forwards as redundant FileChangePatchUpdated notifications and can cause avoidable event/UI churn; reintroducing a last_progress equality guard (as before) prevents this regression.

Useful? React with 👍 / 👎.

@pakrym-oai

Copy link
Copy Markdown
Collaborator

I think the streaming parser also requires a trailing newline which the old parser didn't

@akshaynathan akshaynathan force-pushed the codex/stateful-apply-patch-streaming branch 2 times, most recently from ec11648 to 9ebf25c Compare April 29, 2026 15:59
@akshaynathan akshaynathan force-pushed the codex/stateful-apply-patch-streaming branch from 9ebf25c to 6bd78a5 Compare April 29, 2026 17:15

#[test]
fn test_parse_one_hunk() {
assert_eq!(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we keep this one?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and the one below?

@akshaynathan akshaynathan enabled auto-merge (squash) April 30, 2026 21:16
@akshaynathan akshaynathan merged commit 8426edf into main Apr 30, 2026
35 of 36 checks passed
@akshaynathan akshaynathan deleted the codex/stateful-apply-patch-streaming branch April 30, 2026 21:41
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 30, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants