Current status
This issue is now narrowed to the remaining OpenCode Zen / DeepSeek streaming compatibility defect.
The startup syntax crash reported against 2.12.0 is already resolved on current dev: the invalid continue outside a loop is no longer present. That part should not be reimplemented.
Current dev also already accepts [DONE] without a finish_reason: the [DONE] branch flushes pending tool calls and emits done. A raw EOF with neither [DONE] nor finish_reason remains a truncation condition and should stay fail-closed unless provider evidence proves a safe alternative.
Remaining defect
openai-chat can still flush a pending tool call with an empty function name.
Current flushToolCalls() emits:
yield { type: "tool_call_start", id: call.id, name: call.name };
without first proving that call.name is non-empty.
The affected OpenCode Zen route can stream argument deltas while omitting the matching function.name. When that incomplete call is flushed, the downstream Codex tool-call contract receives an unusable call and the turn can fail.
This issue now tracks only the provider-compatibility question around incomplete streamed tool-call metadata.
Reproduction
- Route Codex through
opencode-free/deepseek-v4-flash-free using the openai-chat adapter.
- Run a turn that causes the upstream to emit tool-call argument deltas without a usable
function.name.
- Allow the stream to reach a normal flush boundary such as
[DONE].
- Observe the pending call being emitted with an empty name and the downstream turn failing.
Expected behavior
OpenCodex must not emit a completed usable tool call with an empty name.
A fix must preserve the existing fail-closed rules for genuinely malformed or truncated tool calls. In particular:
Resolved portion
The 2.12.0 startup failure:
Cannot use "continue" here
is no longer present on current dev and is closed as part of this issue's history.
Related
Acceptance criteria
Current status
This issue is now narrowed to the remaining OpenCode Zen / DeepSeek streaming compatibility defect.
The startup syntax crash reported against 2.12.0 is already resolved on current
dev: the invalidcontinueoutside a loop is no longer present. That part should not be reimplemented.Current
devalso already accepts[DONE]without afinish_reason: the[DONE]branch flushes pending tool calls and emitsdone. A raw EOF with neither[DONE]norfinish_reasonremains a truncation condition and should stay fail-closed unless provider evidence proves a safe alternative.Remaining defect
openai-chatcan still flush a pending tool call with an empty function name.Current
flushToolCalls()emits:without first proving that
call.nameis non-empty.The affected OpenCode Zen route can stream argument deltas while omitting the matching
function.name. When that incomplete call is flushed, the downstream Codex tool-call contract receives an unusable call and the turn can fail.This issue now tracks only the provider-compatibility question around incomplete streamed tool-call metadata.
Reproduction
opencode-free/deepseek-v4-flash-freeusing theopenai-chatadapter.function.name.[DONE].Expected behavior
OpenCodex must not emit a completed usable tool call with an empty name.
A fix must preserve the existing fail-closed rules for genuinely malformed or truncated tool calls. In particular:
tool_callsvalidation from [Bug] Nested field shapes bypass the #1219 frame guard and crash both adapter paths #1325;Resolved portion
The 2.12.0 startup failure:
is no longer present on current
devand is closed as part of this issue's history.Related
tool_callsvalidation and fail-closed behavior.Acceptance criteria
[DONE]withoutfinish_reasonremains accepted.tool_callsshapes remain fail-closed.