Client or integration
Other — downstream application embedding the OpenCodex proxy.
Provider or upstream service
Private OpenAI-compatible model gateway (provider identity and endpoint redacted).
OpenCodex version
@bitkyc08/opencodex 2.7.42
Endpoint or capability
/v1/chat/completions streaming (SSE)
Current behaviour
The OpenAI Chat adapter only processes lines starting with data: (a colon followed by a space).
The upstream emits valid SSE data fields without that optional space, for example data:{...}. As a result, every JSON frame is ignored. A terminal chunk carrying finish_reason: "stop" and a trailing usage-only chunk are also ignored. When the upstream closes the stream, OpenCodex reports:
upstream stream ended without a terminal signal ([DONE] or finish_reason) — possible truncation
Expected behaviour
OpenCodex should accept both data:{...} and data: {...} as SSE data fields.
A non-empty OpenAI finish_reason should remain a valid terminal signal even when the upstream omits the OpenAI-specific data: [DONE] sentinel.
Minimal redacted request or reproduction
curl -N -sS "$BASE_URL/chat/completions" \
-H "Content-Type: application/json" \
-H "X-Example-Auth: <redacted>" \
-d '{
"model": "<model>",
"messages": [{"role": "user", "content": "hello"}],
"stream": true
}'
The upstream response uses this framing pattern:
data:{"id":"<id>","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"..."},"finish_reason":null}]}
...
data:{"id":"<id>","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data:{"id":"<id>","object":"chat.completion.chunk","choices":[],"usage":{"prompt_tokens":0,"completion_tokens":0,"total_tokens":0}}
There is no data: [DONE] frame.
Actual response or error
MODEL_RUNTIME_CANARY_FAILED: turn status failed; stream disconnected before completion:
upstream stream ended without a terminal signal ([DONE] or finish_reason) — possible truncation
Upstream documentation
SSE field syntax permits the value to begin immediately after the colon; one optional U+0020 space is stripped when present:
https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation
The non-null finish_reason behavior is an OpenAI-compatible streaming convention. The upstream has no public provider-specific specification.
Suggested mapping or implementation notes
The shared data-line handler can accept the data: field name regardless of whether a space follows it:
if (!line.startsWith("data:")) return "continue";
const payload = line.slice("data:".length).trim();
Regression coverage should include:
- Unspaced
data:{...} frames with a final non-null finish_reason and no [DONE] -> successful completion.
- Standard
data: {...} framing -> unchanged behavior.
- A genuinely truncated stream with no
[DONE], no final finish_reason, and no terminal usage frame -> still fail closed.
Additional context and attachments
The report is fully redacted. No production endpoint, model identifier, request content, or credentials are included.
Client or integration
Other — downstream application embedding the OpenCodex proxy.
Provider or upstream service
Private OpenAI-compatible model gateway (provider identity and endpoint redacted).
OpenCodex version
@bitkyc08/opencodex 2.7.42
Endpoint or capability
/v1/chat/completionsstreaming (SSE)Current behaviour
The OpenAI Chat adapter only processes lines starting with
data:(a colon followed by a space).The upstream emits valid SSE data fields without that optional space, for example
data:{...}. As a result, every JSON frame is ignored. A terminal chunk carryingfinish_reason: "stop"and a trailing usage-only chunk are also ignored. When the upstream closes the stream, OpenCodex reports:Expected behaviour
OpenCodex should accept both
data:{...}anddata: {...}as SSE data fields.A non-empty OpenAI
finish_reasonshould remain a valid terminal signal even when the upstream omits the OpenAI-specificdata: [DONE]sentinel.Minimal redacted request or reproduction
The upstream response uses this framing pattern:
There is no
data: [DONE]frame.Actual response or error
Upstream documentation
SSE field syntax permits the value to begin immediately after the colon; one optional U+0020 space is stripped when present:
https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation
The non-null
finish_reasonbehavior is an OpenAI-compatible streaming convention. The upstream has no public provider-specific specification.Suggested mapping or implementation notes
The shared data-line handler can accept the
data:field name regardless of whether a space follows it:Regression coverage should include:
data:{...}frames with a final non-nullfinish_reasonand no[DONE]-> successful completion.data: {...}framing -> unchanged behavior.[DONE], no finalfinish_reason, and no terminal usage frame -> still fail closed.Additional context and attachments
The report is fully redacted. No production endpoint, model identifier, request content, or credentials are included.