Skip to content

fix(responses): close passthrough streams at terminal events - #942

Open
L14nY1Wang wants to merge 1 commit into
lidge-jun:devfrom
L14nY1Wang:codex/fix-responses-terminal-close
Open

fix(responses): close passthrough streams at terminal events#942
L14nY1Wang wants to merge 1 commit into
lidge-jun:devfrom
L14nY1Wang:codex/fix-responses-terminal-close

Conversation

@L14nY1Wang

@L14nY1Wang L14nY1Wang commented Aug 3, 2026

Copy link
Copy Markdown

Summary

  • End native Responses passthrough streams as soon as a valid response.completed, response.failed, or response.incomplete event arrives, instead of waiting for the upstream HTTP connection to reach EOF.
  • Append the conventional data: [DONE] sentinel when a compatible gateway omits it, then cancel the retained upstream reader so Codex leaves its thinking state promptly.
  • Apply the same terminal boundary to the eager single-reader relay and route Windows passthrough through that terminal-aware path, including no-rewrite traffic that previously used an uncontrollable native tee branch.
  • Keep terminal accounting, continuation-state reconstruction, cancellation behavior, and failed-tail handling intact, and update the transport source-of-truth documentation.

Verification

  • bun test tests/sse-failed-tail.test.ts tests/passthrough-abort.test.ts tests/consume-for-inspection-cancel.test.ts tests/relay-eager.test.ts tests/bun-stream-caps.test.ts — 84 passed, 0 failed.
  • bun run typecheck — passed.
  • bun run privacy:scan — passed.
  • git diff --check — passed.
  • The full suite was attempted in the restricted workspace; tests that open Bun.serve({ port: 0 }) failed with environment-level EADDRINUSE. No focused assertion failed.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Transport architecture documentation was updated.
  • No authentication, credential, or secret-handling behavior changed.

Summary by CodeRabbit

  • Bug Fixes
    • Improved passthrough SSE handling on Windows so streams terminate reliably.
    • Added consistent data: [DONE] completion markers when terminal responses omit them.
    • Prevented trailing data from being sent after a response completes.
    • Ensured upstream streams stop and client connections close promptly after terminal events.
    • Improved handling of open connections following completed responses.
  • Documentation
    • Clarified platform-specific SSE relay behavior for Windows and macOS, including automatic modes.

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

PR quality gates passed

This pull request now targets dev with acceptable ancestry and description.

The title was left unchanged. The pull request has been marked ready for review again.

@github-actions
github-actions Bot marked this pull request as draft August 3, 2026 09:30
@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

Review Change Stack

Warning

Review limit reached

@L14nY1Wang, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 29 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1241a9b1-82d5-465f-8988-c9b39036ccfe

📥 Commits

Reviewing files that changed from the base of the PR and between eed07d2 and 88d60c3.

📒 Files selected for processing (9)
  • src/lib/bun-stream-caps.ts
  • src/server/index.ts
  • src/server/relay-eager.ts
  • src/server/relay.ts
  • src/server/responses/core.ts
  • structure/04_transports-and-sidecars.md
  • tests/passthrough-abort.test.ts
  • tests/relay-eager.test.ts
  • tests/sse-failed-tail.test.ts
📝 Walkthrough

Walkthrough

Windows passthrough SSE now uses terminal-aware eager relaying. Relays detect protocol terminals, emit data: [DONE] when absent, close client streams, cancel upstream reads, and discard trailing data. Darwin routing remains unchanged.

Changes

SSE terminal handling

Layer / File(s) Summary
Terminal-aware relay behavior
src/server/relay.ts, src/server/relay-eager.ts
The relays frame SSE output, detect terminal events, emit [DONE] when needed, discard later data, flush incomplete frames, cancel upstream readers, and dispose boundary state.
Platform relay routing and documentation
src/server/responses/core.ts, src/server/index.ts, src/lib/bun-stream-caps.ts, structure/04-transports-and-sidecars.md
Windows passthrough SSE always selects the eager terminal-aware relay. Darwin retains its existing eager and tee policies. Documentation reflects the routing.
Terminal behavior tests
tests/relay-eager.test.ts, tests/sse-failed-tail.test.ts, tests/passthrough-abort.test.ts
Tests verify terminal closure, [DONE] handling, upstream cancellation, trailing-data discard, incomplete-block handling, and Windows relay selection.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ResponsesCore
  participant Relay
  participant SSEBoundary
  participant Client
  ResponsesCore->>Relay: select terminal-aware SSE relay
  Relay->>SSEBoundary: inspect streamed chunks
  SSEBoundary-->>Relay: detect response.completed
  Relay->>Client: emit terminal event and data: [DONE]
  Relay->>ResponsesCore: cancel upstream reader
Loading

Possibly related PRs

Suggested reviewers: ingwannu, lidge-jun, wibias

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary change: closing Responses passthrough streams when terminal events arrive.
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.

@L14nY1Wang
L14nY1Wang force-pushed the codex/fix-responses-terminal-close branch from 4f34411 to 5254e45 Compare August 3, 2026 09:34
@github-actions
github-actions Bot marked this pull request as ready for review August 3, 2026 09:34

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@src/server/relay-eager.ts`:
- Around line 235-256: Make both relay emission paths frame-aware: in
src/server/relay-eager.ts lines 235-256 and src/server/relay.ts lines 117-139,
buffer complete SSE blocks, emit only through the first terminal event block,
and discard trailing frames from the same chunk. Append the [DONE] sentinel only
when the terminal-boundary output lacks an actual [DONE] data event, not based
on substring matching. Add focused coverage in tests/relay-eager.test.ts and
tests/sse-failed-tail.test.ts for terminal-plus-trailing data and non-sentinel
content containing the sentinel text.
🪄 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: 68108577-8de9-4f3a-b5cc-66a5b4806bad

📥 Commits

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

📒 Files selected for processing (9)
  • src/lib/bun-stream-caps.ts
  • src/server/index.ts
  • src/server/relay-eager.ts
  • src/server/relay.ts
  • src/server/responses/core.ts
  • structure/04_transports-and-sidecars.md
  • tests/passthrough-abort.test.ts
  • tests/relay-eager.test.ts
  • tests/sse-failed-tail.test.ts

Comment thread src/server/relay-eager.ts
@L14nY1Wang
L14nY1Wang force-pushed the codex/fix-responses-terminal-close branch from 5254e45 to eed07d2 Compare August 3, 2026 09:42
@L14nY1Wang

Copy link
Copy Markdown
Author

Addressed the review feedback in eed07d2. Both relays now share a frame-aware SSE output boundary that emits only complete blocks through the first Responses terminal, drops coalesced post-terminal frames, and recognizes [DONE] only as an actual data event before deciding whether to append the canonical sentinel. Added regression coverage for terminal + trailing data in one chunk and ordinary payload text containing data: [DONE]. Focused suite: 89 passed; typecheck, privacy scan, and diff check also pass.

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

Copy link
Copy Markdown

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: 5254e45073

ℹ️ 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 thread src/server/responses/core.ts Outdated
Comment thread src/server/relay.ts Outdated
@L14nY1Wang
L14nY1Wang force-pushed the codex/fix-responses-terminal-close branch from eed07d2 to d0ab275 Compare August 3, 2026 09:49

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@src/server/responses/core.ts`:
- Around line 1878-1880: Extend tests in relay-eager.test.ts with a regression
case that creates the inspector without onTerminal, cancels the client, and
delivers a terminal event while the upstream remains open. Assert onClientCancel
is not called, no synthetic terminal is emitted, and onDone occurs before the
drain timeout, exercising the sawTerminal callback passed from the response
flow.
🪄 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: 96e181ad-23ac-44b7-88b1-c11ecd6dc28e

📥 Commits

Reviewing files that changed from the base of the PR and between 5254e45 and eed07d2.

📒 Files selected for processing (9)
  • src/lib/bun-stream-caps.ts
  • src/server/index.ts
  • src/server/relay-eager.ts
  • src/server/relay.ts
  • src/server/responses/core.ts
  • structure/04_transports-and-sidecars.md
  • tests/passthrough-abort.test.ts
  • tests/relay-eager.test.ts
  • tests/sse-failed-tail.test.ts

Comment thread src/server/responses/core.ts
@lidge-jun

Copy link
Copy Markdown
Owner

Carried onto the review stack as #953 (stack 3/3), unmodified.

Your commits were taken with git cherry-pick -x, so they keep your authorship — git log --format='%an' on the stack branch shows you, not me. No content was changed; the diff on the stack is byte-identical to what you wrote here, and it applied to dev with no conflict resolution.

Verified on the stack: bun x tsc --noEmit exit 0, and the full suite at 7691 pass / 8 skip / 0 fail across 507 files.

This PR stays open until #953 lands. If a maintainer prefers to take yours directly instead, that path is unaffected — the stack commits get dropped and this one merges. Once #953 merges I'll close this as carried, with the credit already in the commit history rather than in a comment.

Stack: #951 (plan, base dev) → #952 (#908 long-context pricing) → #953 (this carry). Review bottom-up.

Thanks for the fix.

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.

2 participants