Repository navigation
OpenAI-compatible non-streaming Responses requests fail on Codex pool (Hindsight 0.10.1) #6162
Description
Client or integration
OpenAI-compatible SDK: Hindsight 0.10.1's openai-responses provider.
Provider or upstream service
OpenAI Codex through an OpenCodex OAuth account pool.
OpenCodex version
Reproduced on 2.64.0. I inspected the v2.69.0 source but have not run this reproduction on 2.69.0, so I am not claiming a runtime failure on that release.
Endpoint or capability
POST /v1/responses, non-streaming requests.
Current behaviour
A non-streaming Responses request reaches the Codex pool but returns HTTP 400 with {"detail":"Stream must be set to true"}. The same model and admission key work with stream:true: HTTP 200 with a response.completed event. OpenCodex's request log identifies the successful route as an OpenAI Codex pool account.
A disposable process using Hindsight 0.10.1's actual OpenAIResponsesLLM.call() path also raises BadRequestError (HTTP 400) with that detail. Hindsight calls responses.create(**params) without setting stream; its normal and tool-call request builders both use this pattern:
- Hindsight v0.10.1 provider call
- Hindsight v0.10.1 request body
- Hindsight v0.10.1 tool-call request body
Expected behaviour
The official OpenAI Responses create reference defines stream as optional; setting it to true enables server-sent events. An OpenAI-compatible client that omits stream or sets it to false expects a complete JSON Response.
For a Codex upstream that requires SSE, OpenCodex could make the upstream request with stream:true and return a complete JSON Response to a non-streaming client. If this endpoint intentionally supports streaming clients only, please document that limitation so compatible clients can choose another route.
Minimal redacted request or reproduction
curl -i http://127.0.0.1:50000/v1/responses \
-H 'content-type: application/json' \
-H 'x-opencodex-api-key: <REDACTED>' \
-d '{"model":"gpt-6-luna","input":[{"role":"user","content":"Reply PONG"}],"store":false,"stream":false}'Control: set "stream":true in the same request. It returns HTTP 200 and reaches response.completed.
Actual response or error
HTTP/1.1 400 Bad Request
{"detail":"Stream must be set to true"}
Upstream documentation
OpenAI Responses create reference: stream is optional and enables server-sent events when set to true.
Suggested mapping or implementation notes
A focused implementation should preserve complete output and usage, fail closed when no terminal event arrives, retain the existing storage semantics, and leave stream:true callers unchanged.
Additional context and attachments
The related PR #293 proposed SSE-to-JSON buffering but was closed without merge. Maintainer review identified incomplete reconstruction of tool calls, reasoning summaries, refusals, and annotations; false HTTP 200 on truncated streams; and unintended store changes.
Checks
- I searched existing provider and compatibility issues.
- The request and response were redacted.
- The expected behaviour is based on an upstream specification or a concrete client requirement.
Activity
Ingwannu commentedon Sep 28, 2026
Confirmed against current
devcbe0d40(2.70.0) by tracing the request path. The Responses parser preserves omitted/falsestreamas non-streaming, canonical-forward normalization only defaults an absentstoretofalse, and the passthrough adapter serializesstreamunchanged. The Codex backend'sstream:truerequirement therefore still produces the reported 400.#882 is the earlier auto-closed report and #293 was a related implementation attempt closed because reconstruction was incomplete and fail-open. This issue should remain the canonical valid report. Accepting as P2; no more reporter information is needed.
The fix should separate client negotiation from the mandatory canonical upstream transport: send
stream:trueupstream, then boundedly reconstruct the complete terminal Response JSON for non-streaming callers. It must preserve explicitstoresemantics; retain ordered text, annotations, refusals, reasoning summaries, function/custom-tool arguments and usage; leavestream:truecallers unchanged; and fail closed on EOF, malformed/oversized frames, read errors, stalls or cancellation without one valid terminal response.lidge-jun commentedon Sep 29, 2026
Fixed on dev by #6200: a non-streaming caller on the canonical ChatGPT upstream now gets a JSON Responses object folded from an SSE upstream call, so the
Stream must be set to truerejection no longer occurs. Client disconnects during the deferred replay no longer publish a completed result, and failed-terminal diagnostics are credential-masked. Ships in the next release; please reopen if Hindsight's non-streaming requests still fail.fix(fork): 恢复 canonical 缓冲成功路径官方直调以通过 lidge-jun#6162 断言
fix(fork): 恢复 canonical 缓冲成功路径官方直调以通过 lidge-jun#6162 断言
fix(fork): 恢复 canonical 缓冲成功路径官方直调以通过 lidge-jun#6162 断言
fix(fork): 恢复 canonical 缓冲成功路径官方直调以通过 lidge-jun#6162 断言
fix(fork): 恢复 canonical 缓冲成功路径官方直调以通过 lidge-jun#6162 断言
fix(fork): 恢复 canonical 缓冲成功路径官方直调以通过 lidge-jun#6162 断言