Skip to content

fix(examples): reject incomplete multi-agent streams - #2666

Merged
HAYDEN-OAI merged 1 commit into
mainfrom
codex/multi-agent-streaming-eof
Sep 7, 2026
Merged

fix(examples): reject incomplete multi-agent streams#2666
HAYDEN-OAI merged 1 commit into
mainfrom
codex/multi-agent-streaming-eof

Conversation

@HAYDEN-OAI

Copy link
Copy Markdown
Contributor

Summary

Require a coordinator response.completed event before the multi-agent SSE example treats stream termination as success. The production change is six added lines in the handwritten example.

Child-agent completion/failure remains nonterminal for the coordinator. The example still consumes the stream after coordinator completion, preserving explicit root failures, named SSE errors, and transport errors rather than hiding them with an early break.

Reproduction

On current main, the actual executable example exits successfully when the server sends [DONE] or closes the SSE body before the coordinator completes—even with only partial coordinator text or a completed/failed child agent. Ten new executable regressions fail before the source change, while fourteen controls pass.

Validation

  • Final example suite: 25/25 tests pass on exact Node 22.0.0, Node 24.19.0, and Node 26.7.0.
  • Covers empty/partial/child-only EOF and [DONE], omitted/null/explicit root ownership, child-status continuation, and a named SSE error received after coordinator completion.
  • Independent public built CommonJS/ESM checks pass on Node 22/24/26, including later root failures, malformed SSE, transport-error identity, output preservation, and existing sentinel behavior.
  • Full canonical handwritten suite: 7,817 tests pass across 205 files.
  • Canonical format, lint, TypeScript checking, build, and git diff --check pass. The entire built SDK is byte-for-byte identical to the base build.
  • Adversarial review completed against the final source and test hashes with no remaining findings.

Only the example and its existing regression-test file change. No SDK runtime/parser changes, generated files, dependencies, new payload limits, or WebSocket changes. All inputs and responses are synthetic; no live API calls. This complements the existing explicit-terminal-error handling and the separate WebSocket early-close fix.

@HAYDEN-OAI
HAYDEN-OAI requested a review from a team as a code owner September 6, 2026 23:50
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 6, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-06T23:52:05.441738Z 5d64d68 PR opened
🔒 Security Review Completed 2026-09-06T23:53:22.606875Z 5d64d68 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Castiron custom code

✅ No new custom-code files detected.

32 mixed files remain; 0 existing customizations changed.

Compared 7b5d1209090f5d64d6892276. Generated baselines verified.

32 existing customizations unchanged
  • api.md
  • scripts/castiron/README.md
  • scripts/castiron/custom_code_report.py
  • scripts/castiron/test_custom_code_report.py
  • src/client.ts
  • src/resources/audio/transcriptions.ts
  • src/resources/audio/translations.ts
  • src/resources/beta/assistants.ts
  • src/resources/beta/beta.ts
  • src/resources/beta/index.ts
  • src/resources/beta/responses/internal-base.ts
  • src/resources/beta/responses/responses.ts
  • src/resources/beta/threads/index.ts
  • src/resources/beta/threads/runs/index.ts
  • src/resources/beta/threads/runs/runs.ts
  • src/resources/beta/threads/threads.ts
  • src/resources/chat/completions/completions.ts
  • src/resources/chat/completions/index.ts
  • src/resources/conversations/index.ts
  • src/resources/embeddings.ts
  • src/resources/files.ts
  • src/resources/fine-tuning/checkpoints/permissions.ts
  • src/resources/images.ts
  • src/resources/responses/internal-base.ts
  • src/resources/responses/responses.ts
  • src/resources/skills/skills.ts
  • src/resources/skills/versions/versions.ts
  • src/resources/vector-stores/file-batches.ts
  • src/resources/vector-stores/files.ts
  • src/resources/webhooks/index.ts
  • src/resources/webhooks/webhooks.ts
  • tests/lib/data-residency.test.ts

A changed generated baseline means this report cannot reliably identify which handwritten lines changed.

Inspect the custom-code diff

Download the exact patch produced by this run (requires repository access):

gh run download 34068029038 --repo openai/openai-node \
  --name castiron-custom-code-34068029038-1 --dir /tmp/castiron-custom-code-34068029038-1
git apply --stat /tmp/castiron-custom-code-34068029038-1/custom-code.patch
cat /tmp/castiron-custom-code-34068029038-1/custom-code.patch

Or reproduce it from an SDK checkout containing the vendored reporter:

git fetch --no-tags origin 7b5d1209090f82f56b4971976147b5c2a859452e 5d64d68922760ed420d35657c1f6a023ac85062c
python3 scripts/castiron/custom_code_report.py report \
  --base 7b5d1209090f82f56b4971976147b5c2a859452e \
  --head 5d64d68922760ed420d35657c1f6a023ac85062c --fetch --require-head-hash --public \
  --out /tmp/castiron-custom-code-5d64d6892276
cat /tmp/castiron-custom-code-5d64d6892276/custom-code.patch

This is the current full custom patch for mixed files, not an attribution of only the handwritten lines changed by this PR.

Full report and patch

@openai-sdks

openai-sdks Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

OkTest Summary

237/237 SDK tests passed in 10.22s for Node SDK PR #2666.

Test results — 42 files
Test Result Time
tests/chat-completions-complex-body.test.ts ✅ Passed 152ms
tests/chat-completions-create.test.ts ✅ Passed 226ms
tests/chat-completions-stream.test.ts ✅ Passed 201ms
tests/files-content-binary.test.ts ✅ Passed 187ms
tests/files-create-multipart.test.ts ✅ Passed 131ms
tests/files-list-pagination.test.ts ✅ Passed 143ms
tests/initialize-config.test.ts ✅ Passed 151ms
tests/instance-isolation.test.ts ✅ Passed 94ms
tests/models-list.test.ts ✅ Passed 124ms
tests/responses-background-lifecycle.test.ts ✅ Passed 214ms
tests/responses-body-method-errors.test.ts ✅ Passed 383ms
tests/responses-cancel-timeout.test.ts ✅ Passed 240ms
tests/responses-cancel.test.ts ✅ Passed 193ms
tests/responses-compact-retries.test.ts ✅ Passed 240ms
tests/responses-compact.test.ts ✅ Passed 196ms
tests/responses-create-advanced-stream.test.ts ✅ Passed 116ms
tests/responses-create-advanced.test.ts ✅ Passed 126ms
tests/responses-create-disconnect.test.ts ✅ Passed 1.092s
tests/responses-create-errors.test.ts ✅ Passed 187ms
tests/responses-create-malformed-api-responses.test.ts ✅ Passed 133ms
tests/responses-create-retries.test.ts ✅ Passed 302ms
tests/responses-create-stream-failures.test.ts ✅ Passed 203ms
tests/responses-create-stream-timeout.test.ts ✅ Passed 2.15s
tests/responses-create-stream-wire.test.ts ✅ Passed 2.585s
tests/responses-create-stream.test.ts ✅ Passed 95ms
tests/responses-create-terminal-states.test.ts ✅ Passed 190ms
tests/responses-create-timeout.test.ts ✅ Passed 221ms
tests/responses-create.test.ts ✅ Passed 185ms
tests/responses-delete.test.ts ✅ Passed 222ms
tests/responses-input-items-errors.test.ts ✅ Passed 256ms
tests/responses-input-items-list.test.ts ✅ Passed 179ms
tests/responses-input-items-options.test.ts ✅ Passed 111ms
tests/responses-input-tokens-count-timeout.test.ts ✅ Passed 272ms
tests/responses-input-tokens-count.test.ts ✅ Passed 226ms
tests/responses-malformed-inputs.test.ts ✅ Passed 2.175s
tests/responses-not-found-errors.test.ts ✅ Passed 240ms
tests/responses-parse.test.ts ✅ Passed 190ms
tests/responses-retrieve-retries.test.ts ✅ Passed 259ms
tests/responses-retrieve.test.ts ✅ Passed 203ms
tests/responses-stored-method-errors.test.ts ✅ Passed 489ms
tests/retry-behavior.test.ts ✅ Passed 2.962s
tests/sdk-error-shape.test.ts ✅ Passed 261ms

View OkTest run #34068012070

SDK merge (21ce52ec3a88) · head (5d64d6892276) · base (7b5d1209090f) · OkTest (2b1bdfd25e98)

@jbeckwith-oai jbeckwith-oai 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.

Reviewed exact head 5d64d68.\n\nThe example now requires an explicit coordinator response.completed event before treating normal iterator termination—whether [DONE] or EOF—as success. Child completion/failure/incomplete events remain nonterminal, and the loop deliberately continues after coordinator completion so later root failures, named SSE errors, malformed frames, or transport errors retain precedence rather than being hidden.\n\nThe new terminal error is generic and does not surface response payload or private failure detail. Root ownership handling remains aligned with the existing failed/incomplete logic (omitted, null, or explicit /root).\n\nVerified locally at the exact head:\n- focused executable multi-agent SSE suite: 25/25 passed\n- oxlint passed for both changed files\n- oxfmt check passed\n- git diff --check passed\n\nNo unresolved review threads and no in-scope blocking findings. Hosted Node 22/26 and ecosystem jobs were still running at submission; all completed checks were green or neutral.

@markstuart-oai markstuart-oai 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.

Reviewed exact head 5d64d68 against base/merge-base 7b5d120. No actionable correctness, security, or maintainability findings.

The coordinator-completion bit is the minimal state needed to reject incomplete EOF/[DONE] without breaking early and hiding later errors. Ownership matches the existing omitted/null/explicit /root contract; child terminal events remain nonterminal. This policy belongs in the example, not the shared SSE parser. Growth is proportionate: example 44→50 lines; existing focused test file 179→223.

Independent validation:

  • Actual executable example: 25/25 tests on Node 22.0.0 and 24.20.0.
  • Existing SSE sentinel/error/privacy/early-exit suites: 83/83 tests.
  • 28 synthetic source-execution cases against built CommonJS and ESM SDKs on Node 22.0.0, 24.20.0, and 26.7.0, including ten base-negative controls, later root failures, malformed/named errors, transport-error identity, cleanup, partial output, child continuation, and preserved sentinel behavior.
  • Build, focused type check, changed-file Oxlint/Oxfmt, and diff whitespace check passed.

All fixtures were local/synthetic. Whole-project type checking was limited by missing optional Azure/Express example dependencies; I did not rerun the full handwritten/generated suites or independently compare base/head build bytes. SDK source and dependencies are unchanged.

Workspace: full clone; corrected detached worktree created at freshly fetched default main@518756a59fa9693c0751fb91403d017cfcd0037a, then checked out the exact PR head. Refreshed open/non-draft state, unchanged head, discussion, and complete review history immediately before submission; no prior Mark outcome or hold.

@HAYDEN-OAI
HAYDEN-OAI added this pull request to the merge queue Sep 7, 2026
Merged via the queue into main with commit 152b98d Sep 7, 2026
38 checks passed
@HAYDEN-OAI
HAYDEN-OAI deleted the codex/multi-agent-streaming-eof branch September 7, 2026 17:15
@openai-sdks openai-sdks Bot mentioned this pull request Sep 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants