fix: tolerate missing streamed response content type#90205
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 4, 2026, 2:53 PM ET / 18:53 UTC. Summary PR surface: Source +79, Tests +193. Total +272 across 2 files. Reproducibility: yes. Source inspection shows current main and v2026.6.1 reject successful streamed SDK responses with a missing content-type, and the PR body includes red/green live Codex proof plus focused regression tests. Review metrics: 1 noteworthy metric.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land the narrow transport fix after maintainer sign-off and current-head CI, while keeping the broader duplicate Codex path refactor in #90193. Do we have a high-confidence way to reproduce the issue? Yes. Source inspection shows current main and v2026.6.1 reject successful streamed SDK responses with a missing content-type, and the PR body includes red/green live Codex proof plus focused regression tests. Is this the best way to solve the issue? Yes. This is the best narrow incident fix because it changes the shared OpenAI SDK transport guard while preserving HTML rejection, and leaves the broader duplicate Codex-path refactor to the existing follow-up issue. AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against 9dcf42472b8a. Label changesLabel justifications:
Evidence reviewedPR surface: Source +79, Tests +193. Total +272 across 2 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
8335c78 to
0d7f8ab
Compare
|
Land-ready verification for head
Known proof gap: full |
|
Merged via squash.
Thanks @jalehman! |
Summary
What problem does this PR solve?
content-typeheader was rejected before the OpenAI SDK could parse the body.Why does this matter now?
openai/gpt-5.5pluginllm.completecalls can route throughopenclaw-openai-responses-transportand hithttps://chatgpt.com/backend-api/codex/responses.content-typeheader, causing background lossless/context-engine summarization to fail withinvalid_provider_content_type.What is the intended outcome?
What is intentionally out of scope?
What does success look like?
llm.completeCodex calls no longer fail solely because the upstream omittedcontent-typeon a valid stream.What should reviewers focus on?
Linked context
Which issue does this close?
Closes #
Which issues, PRs, or discussions are related?
Related #90193
Was this requested by a maintainer or owner?
Yes, requested during live Phaedrus/OpenClaw incident triage.
Real behavior proof (required for external PRs)
content-typeno longer block or fail before the SDK sees valid SSE/JSON bodies.openai/gpt-5.5, and the ChatGPT Codex responses endpoint.node --import tsxprobe that calledcompleteSimplethroughopenclaw-openai-responses-transportagainsthttps://chatgpt.com/backend-api/codex/responses; thennode scripts/run-vitest.mjs src/agents/provider-transport-fetch.test.ts -- --reporter=verbose.status=200, emptycontentType=,first_event ... type=response.created,stream_done ... events=15, and final probe outputPATCHED_CODEX_TRANSPORT_OKwithusagePresent=true. Focused Vitest passed 73 tests including missing-header SSE, still-open SSE, split-prefix SSE, JSON fallback, and HTML rejection cases.HOMEcould not see a portable API key/auth profile.40880bca88reachedstatus=200with emptycontentType=from ChatGPT Codex and then timed out after 180s beforefirst_eventor completion. The new still-open SSE regression also failed against40880bca88withexpected Symbol(timeout) not to be Symbol(timeout).Tests and validation
Which commands did you run?
40880bca88with only the still-open SSE regression applied: failed withexpected Symbol(timeout) not to be Symbol(timeout).40880bca88: reached ChatGPT Codex HTTP 200 with missingcontent-type, then timed out after 180s before first SSE event/completion.0f621713b0: reached ChatGPT Codex HTTP 200 with missingcontent-type, sawresponse.created, completed 15 SSE events, and returnedPATCHED_CODEX_TRANSPORT_OK.node scripts/run-vitest.mjs src/agents/provider-transport-fetch.test.ts -- --reporter=verbose: passed 73 tests.git diff --check: passed.What regression coverage was added or updated?
content-typewith valid SSE is accepted.content-typewith a still-open SSE stream returns promptly instead of waiting for stream close.content-typewith split SSE prefix is accepted.content-typewith JSON is normalized into the existing JSON-to-SSE path.content-typewith HTML is rejected.text/htmlrejection remains covered.What failed before this fix, if known?
40880bca88by timing out before the response was returned.contentType=and then timed out before first event/completion.If no test was added, why not?
Risk checklist
Did user-visible behavior change? (
Yes/No)Yes. Valid missing-header streamed OpenAI/Codex transport responses are no longer rejected.
Did config, environment, or migration behavior change? (
Yes/No)No.
Did security, auth, secrets, network, or tool execution behavior change? (
Yes/No)Yes, narrowly in provider transport response validation for streamed SDK requests.
What is the highest-risk area?
How is that risk mitigated?
text/event-streamorapplication/jsonfor bodies that look like SSE or JSON.Current review state
What is the next action?
0f621713b0.What is still waiting on author, maintainer, CI, or external proof?
Which bot or reviewer comments were addressed?
Agent Transcript
Redacted codex session transcript