Skip to content

fix(provider): propagate options.extraBody for openai-compatible providers - #26233

Closed
jeremy-newhouse wants to merge 1 commit into
anomalyco:devfrom
jeremy-newhouse:fix/openai-compatible-extra-body
Closed

fix(provider): propagate options.extraBody for openai-compatible providers#26233
jeremy-newhouse wants to merge 1 commit into
anomalyco:devfrom
jeremy-newhouse:fix/openai-compatible-extra-body

Conversation

@jeremy-newhouse

@jeremy-newhousejeremy-newhouse commented May 7, 2026

Copy link
Copy Markdown

Issue for this PR

Closes#13584
Closes#23995
Closes#24264

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

provider.<id>.options.extraBody from opencode.json is silently dropped — extraBody is permitted by the schema's rest record but never read. Users of OpenAI-compatible servers (vLLM, NVIDIA NIM, SGLang, direct DashScope) can't pass server-specific body fields like chat_template_kwargs that those endpoints need.

The fix: read input.providerOptions.extraBody in ProviderTransform.options() and Object.assign it into result. Routing then matches the existing alibaba-cnenable_thinking=true block at transform.ts:1040 — which is proof the path reaches the wire (DashScope users rely on it). Also adds a typed extraBody field to Info.options for IDE completion.

Pattern matches #25573 (cf-ai-gateway fix); avoids the larger surface change in #6761 (closed without merge).

How did you verify your code works?

7 new unit tests in transform.test.ts: positive case, nested objects, undefined/null/array no-ops, non-clobbering of unrelated fields, explicit precedence (user extraBody overrides hardcoded blocks). Full provider suite passes (291/291).

End-to-end against vLLM serving Qwen3.6-35B-A3B (--reasoning-parser qwen3 --tool-call-parser qwen3_coder):

  • Vanilla v1.14.39 with extraBody.chat_template_kwargs.enable_thinking=false in opencode.json: agent loop dies — model emits EOS without finishing tool calls because enable_thinking=false never reaches vLLM and qwen3 produces runaway reasoning.
  • Same config + this patch: agent run finishes cleanly (537s, 5 commits in a multi-feature run, no hallucinations). Direct routing to vLLM verified — no proxy in the path.

Screenshots / recordings

n/a — not a UI change

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

@github-actionsgithub-actionsBot added the needs:compliance This means the issue will auto-close after 2 hours. label May 7, 2026
…iders
opencode silently drops `provider.<id>.options.extraBody` from
opencode.json, so users of OpenAI-compatible servers (vLLM, SGLang,
NVIDIA NIM, direct DashScope) cannot pass server-specific
chat-completions body fields like `chat_template_kwargs`.
Concrete impact (vLLM + qwen3): without `chat_template_kwargs.enable_thinking=false`
on the wire, qwen3 produces pathological reasoning that consumes its
output budget and emits EOS without finishing tool calls; the agent
loop dies mid-flight. The harness today ships a Python wire proxy as
a stopgap.
Fix: read `input.providerOptions.extraBody` in
`ProviderTransform.options()` and merge into `result`. The fields then
ride the same path as the existing alibaba-cn `enable_thinking=true`
hardcoding (transform.ts:1040-1047) — `providerOptions()` wraps the
result under the SDK-recognized key for `@ai-sdk/openai-compatible`,
and the Vercel AI SDK serializes it onto the request body. The
alibaba-cn block proves this routing reaches the wire (DashScope
users rely on it).
Also adds a typed `extraBody` field on the `Info.options` schema for
documentation and IDE completion. The existing rest record on
`Info.options` already permits the field; this purely improves
discoverability.
Tests cover: positive case (qwen3 enable_thinking), nested objects,
undefined / null / array no-ops, non-clobbering of unrelated fields,
and explicit precedence (user config wins over hardcoded blocks).
Closes#13584Closes#23995Closes#24264
@jeremy-newhouse
jeremy-newhouseforce-pushed the fix/openai-compatible-extra-body branch from 8551430 to cd2b14bCompareMay 7, 2026 19:17
@github-actionsgithub-actionsBot removed the needs:compliance This means the issue will auto-close after 2 hours. label May 7, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

@fungaren

Copy link
Copy Markdown

@adamdotdevin Very Very Very important feature for users who are using DeepSeek-V4 models :)

@fungaren

Copy link
Copy Markdown

@rekram1-node Hi, can you please help us to review and merge this PR? Thanks!

acje added a commit to acje/.config that referenced this pull request Jun 10, 2026
Three changes to the dramallama provider, all reversing breakage that left
the model returning blank responses with no error:
- baseURL: revert 127.0.0.1:8787 (headroom proxy, commit 9603a27) back to
the direct https://aiapi.mattilsynet.no/v1 endpoint. The proxy was
uninstalled, so requests hit a dead local port.
- thinking model: remove options.chat_template_kwargs.enable_thinking.
opencode v1.17.1 silently drops this field for custom providers
(transform.ts has no generic passthrough; fix is open PR anomalyco/opencode#26233),
and Qwen3 on vLLM enables reasoning by default regardless, so the field
was a no-op twice over.
- thinking model: raise limit.output 8000 -> 32000. Qwen3 spends the output
budget on reasoning before emitting content; 8000 truncated mid-thought
(finish_reason=length, content=null) which opencode renders as a blank
message. Higher cap lets content survive the reasoning preamble.
@vartiait-ay

Copy link
Copy Markdown

Also important feature for Qwen 3.6 model users :)

@jeremy-newhousejeremy-newhouse closed this by deleting the head repository Aug 17, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants

@jeremy-newhouse@fungaren@vartiait-ay