Skip to content

fix(streaming): prevent Darwin rewrite stalls - #947

Closed
WZBbiao wants to merge 2 commits into
lidge-jun:devfrom
WZBbiao:fix/codex-0146-local-provider-compat
Closed

fix(streaming): prevent Darwin rewrite stalls#947
WZBbiao wants to merge 2 commits into
lidge-jun:devfrom
WZBbiao:fix/codex-0146-local-provider-compat

Conversation

@WZBbiao

@WZBbiao WZBbiao commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Prevent Codex Desktop turns on macOS from remaining in Thinking when passthrough SSE needs a client-facing payload rewrite.
  • Route rewrite-required traffic on Windows and Darwin through the existing bounded eager single-reader relay, with the rewrite applied inline.
  • Preserve the current runtime/config policy for ordinary no-rewrite streams and preserve existing Linux behavior.
  • Document the transport-safety exception in the architecture source of truth and all existing troubleshooting locales.

Root cause and safety

Codex Desktop requests that advertise the image_gen namespace require OpenCodex to restore client-facing tool payloads. On Darwin, the ReadableStream.tee() plus JS-pull rewrite chain can stall before forwarding its first large SSE event. The upstream can return a complete stream while the WebSocket bridge sends zero frames, leaving Codex in Thinking until its 300-second retry.

This change reuses the relay already required for Windows rewrite traffic. Raw upstream bytes still feed inspection, request-log metadata, and continuation state before the client-only transform. The incomplete rewrite frame remains charged to the turn translator budget, and cancellation/error teardown releases that charge. streamMode cannot pin the known-bad rewrite chain, while ordinary streams remain configurable exactly as before.

Upstream integration

The branch is rebased on e44d234f, which already contains the terminal-event closure carried by #953 from #942. The eager relay therefore uses inspector.terminalSeen() and closes at response.completed even when no outcome callback is configured; this PR adds the Darwin rewrite-path selection without replacing or weakening that behavior.

Verification

  • bun test tests/bun-stream-caps.test.ts tests/passthrough-abort.test.ts tests/relay-eager.test.ts tests/responses-image-gen-repair.test.ts - 80 passed, 0 failed on final head 015ca8fc.
  • bun run prepush from a detached /tmp worktree on final head 015ca8fc - 8,215 passed, 8 skipped, 0 failed; typecheck, dashboard lint, full tests, privacy scan, and React Doctor all passed.
  • Packaged dashboard build - passed.
  • Documentation build - 216 pages built.
  • bun scripts/darwin-eager-abort-stress.ts --seed 260801 --per-class 67 --deadline-ms 240000 - PASS-WITH-CAVEAT: 67/67 before-first-byte and 67/67 mid-frame aborts completed without crash or hang; the real socket probe reported all 67 backpressure cases unreachable. Deterministic relay tests cover queue-full pause, cancel wakeup, abort wakeup, and budget release.
  • Real Codex 0.146.0 with WebSockets enabled completed with turn.completed under both pinned legacy-tee and installed auto configurations; no five-minute reconnect or duplicate upstream request occurred.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs and architecture notes were updated.
  • No authentication, credential, request logging, or unsafe-default behavior changed.

Summary by CodeRabbit

  • Bug Fixes

    • Improved streaming reliability for payload-rewrite requests on Windows and macOS by automatically using a bounded relay, regardless of streaming mode.
    • Preserved safe cancellation, buffering, rewrite limits, and completion behavior during interrupted streams.
    • Clarified platform-specific handling for ordinary streams, including automatic mode and explicit relay selection.
  • Documentation

    • Updated troubleshooting and streaming documentation across supported languages to explain relay selection, payload rewriting, and platform-specific behavior.

@github-actions github-actions Bot added the bug Something isn't working label Aug 3, 2026
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b11e8a54-0339-496b-914a-3312808ddbfa

📥 Commits

Reviewing files that changed from the base of the PR and between 2c18223 and 015ca8f.

📒 Files selected for processing (10)
  • docs-site/src/content/docs/ja/troubleshooting/windows-memory.md
  • docs-site/src/content/docs/ko/troubleshooting/windows-memory.md
  • docs-site/src/content/docs/ru/troubleshooting/windows-memory.md
  • docs-site/src/content/docs/troubleshooting/windows-memory.md
  • docs-site/src/content/docs/zh-cn/troubleshooting/windows-memory.md
  • src/lib/bun-stream-caps.ts
  • src/server/index.ts
  • src/server/relay-eager.ts
  • src/server/responses/core.ts
  • structure/04_transports-and-sidecars.md

📝 Walkthrough

Walkthrough

The change extends eager SSE relay selection from Windows-only payload rewrites to Windows and Darwin. It updates stream-policy documentation and adds coverage for platform selection, large payloads, cancellation cleanup, and completion events.

Changes

Cross-platform rewrite relay

Layer / File(s) Summary
Rewrite safety policy
src/lib/bun-stream-caps.ts, tests/bun-stream-caps.test.ts
requiresEagerRewriteRelay replaces the Windows-only helper and returns true for rewrite traffic on Windows and Darwin. Tests cover supported platforms, Linux, and no-rewrite cases.
Eager relay routing
src/server/responses/core.ts, src/server/index.ts, src/server/relay-eager.ts, structure/04_transports-and-sidecars.md
Passthrough SSE responses select the eager relay for Windows and Darwin rewrite traffic. Inline rewriting, bounded buffering, continuation ordering, cancellation draining, and rewrite-budget handling remain in place.
Relay validation and documentation
tests/relay-eager.test.ts, tests/passthrough-abort.test.ts, tests/responses-image-gen-repair.test.ts, docs-site/src/content/docs/*/troubleshooting/windows-memory.md
Tests cover partial-frame cancellation, large rewritten payloads, platform-specific selection, payload preservation, and single completion events. Troubleshooting pages document platform-specific streamMode behavior.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant responsesCore
  participant requiresEagerRewriteRelay
  participant relayEager
  Client->>responsesCore: Request passthrough SSE with payload rewrite
  responsesCore->>requiresEagerRewriteRelay: Check platform and rewrite requirement
  requiresEagerRewriteRelay-->>responsesCore: Select eager relay on Windows or Darwin
  responsesCore->>relayEager: Rewrite and stream with bounded buffering
  relayEager-->>Client: Deliver rewritten SSE events
Loading

Possibly related PRs

Suggested reviewers: ingwannu, wibias, lidge-jun

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: preventing Darwin stalls during streaming payload rewrites.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@WZBbiao

WZBbiao commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep them coming!

Reviewed commit: e247a0d43d

ℹ️ 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".

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/relay-eager.test.ts`:
- Around line 273-280: Replace the fixed settle(60) wait in the reader.cancel
test with a promise resolved by hooks.onDone, awaiting that promise before
assertions; retain a separate timeout that fails if relay completion hangs. Keep
the existing abort, budget, cancellation, completion, and synthetic-record
assertions unchanged.
- Around line 258-266: Ensure the test scope around relaySseEagerBounded
disposes the caller-owned budget by adding budget.dispose() in a finally block.
Use the existing budget created by createTranslatorBudget and preserve cleanup
even when the relay assertions or execution fail.

In `@tests/responses-image-gen-repair.test.ts`:
- Around line 347-350: Update the large-payload assertion in the response test
to verify that clientBody contains largeEcho, rather than only comparing their
lengths. Keep the existing isEagerRelaySseResponse assertion unchanged and
preserve the test’s large-payload scenario.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 44347c50-36ae-4a17-9fe3-c404609fe8ca

📥 Commits

Reviewing files that changed from the base of the PR and between 6a7351b and e247a0d.

📒 Files selected for processing (14)
  • docs-site/src/content/docs/ja/troubleshooting/windows-memory.md
  • docs-site/src/content/docs/ko/troubleshooting/windows-memory.md
  • docs-site/src/content/docs/ru/troubleshooting/windows-memory.md
  • docs-site/src/content/docs/troubleshooting/windows-memory.md
  • docs-site/src/content/docs/zh-cn/troubleshooting/windows-memory.md
  • src/lib/bun-stream-caps.ts
  • src/server/index.ts
  • src/server/relay-eager.ts
  • src/server/responses/core.ts
  • structure/04_transports-and-sidecars.md
  • tests/bun-stream-caps.test.ts
  • tests/passthrough-abort.test.ts
  • tests/relay-eager.test.ts
  • tests/responses-image-gen-repair.test.ts

Comment thread tests/relay-eager.test.ts Outdated
Comment thread tests/relay-eager.test.ts Outdated
Comment thread tests/responses-image-gen-repair.test.ts Outdated
@WZBbiao

WZBbiao commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Delightful!

Reviewed commit: 2c182230da

ℹ️ 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".

@WZBbiao

WZBbiao commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

Maintainer action required: GitHub is holding the fork workflows at action_required with zero jobs, so the PR remains UNSTABLE even though every visible check is green.

Please approve and run both workflows. The exact head 2c182230dab8cf09ecf2250a81a32de193d7d91d has already passed the repository pre-push gate locally in an isolated worktree: 7,591 passed, 8 skipped, 0 failed; TypeScript, GUI lint, privacy scan, and React Doctor all passed. CodeRabbit has no remaining actionable comments, all review threads are resolved, and Codex reviewed this head with no major issues.

@WZBbiao
WZBbiao force-pushed the fix/codex-0146-local-provider-compat branch from 2c18223 to 015ca8f Compare August 4, 2026 11:04
@WZBbiao

WZBbiao commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@WZBbiao
WZBbiao marked this pull request as ready for review August 4, 2026 11:07
@Wibias
Wibias marked this pull request as draft August 5, 2026 19:32

@Ingwannu Ingwannu left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

The underlying Darwin rewrite-stall fix is still valuable, but I will not approve the held fork workflows on this old head.

Current dev still keeps Darwin's eager selection explicit-only for ordinary no-rewrite traffic, while this PR addresses a different observed failure: client-facing payload rewrite over the tee + JS-pull chain. Reusing the bounded single-reader relay for rewrite-required Darwin traffic remains the right architectural direction, and this diff does not modify workflows, dependency manifests, lockfiles, or install scripts.

However, head 015ca8fc is now 473 commits behind dev, the PR is draft and conflicting, and the shared relay/inspection/terminal paths have changed substantially since its base (including the current SSE-bound work). The old action_required runs are no longer evidence for the tree we could merge today. Please rebase onto current dev, resolve the relay policy against the current createSseInspector/eager-relay invariants, rerun the focused Darwin/Windows rewrite tests locally, and tick the current review-readiness checklist before requesting workflow approval again. Do not merge dev into the contributor branch.

I am leaving it open because the bug and proposed boundary are meaningful; it is not mergeable or workflow-approvable in its present state.

@lidge-jun

Copy link
Copy Markdown
Owner

Thank you — your predicate is landing as #1142 (closing #1127), credited to you via Co-authored-by.

You identified the right condition: selectEagerPath rejects on needsClientRewrite before platform logic runs, so macOS rewrite traffic could never take the eager path even when explicitly selected.

Why I rebuilt rather than cherry-picked, so this is not mysterious: the branch conflicts with current dev across 14 files, and the tests assert through fixed settle() waits — timing-based assertions can go green while the behavior is broken, so they could not carry the change. The stack PR ports your predicate and rewrites the tests around a deterministic onDone promise with a bounded failure timeout, plus a full platform × mode × rewrite-required matrix.

I also kept the change narrower than the original: Darwin auto stays tee, and only an explicit eager-relay selection admits rewrite traffic. Changing the default transport strategy inside a bug fix felt like more than the defect warranted.

Verified natively on macOS: red-then-green confirmed, 70 pass / 0 fail on the affected suites, 101 pass after rebasing onto the Copilot phase, full suite 9,513 pass / 0 fail.

Leaving this PR open for you.

eachann1024 pushed a commit to eachann1024/opencodex that referenced this pull request Aug 7, 2026
Reimplement the explicit Darwin config-eager predicate from PR lidge-jun#947 for issue lidge-jun#1127, and apply client rewrites with their budget inside the selected single-reader relay.

This was rebuilt instead of cherry-picked because PR lidge-jun#947 conflicts with the current stacked transport code and its fixed settle waits did not deterministically prove relay cleanup.

Co-authored-by: biao <16611004+WZBbiao@users.noreply.github.com>
@lidge-jun

Copy link
Copy Markdown
Owner

Closing — your predicate is on dev, credited via Co-authored-by: biao, carried by #1142 (merge commit abf430e83). Issue #1127 is closed by that merge.

You identified the right condition: selectEagerPath rejects on needsClientRewrite before platform logic runs, so macOS rewrite traffic could never take the eager path even when explicitly selected.

Why it was rebuilt rather than cherry-picked, so this is not mysterious: the branch conflicted with dev across 14 files, and the tests asserted through fixed settle() waits — timing-based assertions can go green while the behavior is broken, so they could not carry the change. The landed version ports your predicate and rewrites the tests around a deterministic onDone promise with a bounded failure timeout, plus a full platform × mode × rewrite-required matrix.

I also kept it narrower than the original: Darwin auto stays tee, and only an explicit eager-relay selection admits rewrite traffic. Changing the default transport strategy inside a bug fix felt like more than the defect warranted.

Closing since the fix shipped, not because the work was rejected — the diagnosis was yours. Verified natively on macOS: red-then-green confirmed; 9,593 pass / 0 fail on the merged tree; CI green on the exact dev SHA.

@lidge-jun lidge-jun closed this Aug 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants