You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
bug(provider): thinking/reasoning options not gated by model.capabilities.reasoning #34282
Thinking/reasoning provider options aren't gated by model.capabilities.reasoning. This breaks non-reasoning models, most visibly when a subagent uses one:
A non-thinking model's normal output gets stored as reasoning ("thinking") instead of normal assistant text.
Trying to opt out via agent options: { thinking: { type: "disable" } } passes the field straight through to the provider, and the non-thinking model's API rejects the unknown thinking parameter with an error.
Root cause: ProviderTransform.options() in packages/opencode/src/provider/transform.ts force-injects thinking/reasoning params from model id/provider substrings without checking capabilities.reasoning, e.g.:
~L1174 id contains gpt-5 → reasoningEffort: "medium"
Compare the google (~L1127) and alibaba-cn (~L1162) branches, which do gate on capabilities.reasoning. The stream side (session/llm/ai-sdk.ts, session/processor.ts) and the option merge (session/llm/request.ts ~L91 → providerOptions()) also don't filter by capability, so the disable workaround in (2) leaks straight to the provider.
Suggested fix: gate every thinking/reasoning branch in options() on model.capabilities.reasoning (like the google/alibaba branches), and/or strip thinking/reasoning/reasoningEffort/thinkingConfig/enable_thinking in providerOptions() when !capabilities.reasoning.
Configure a subagent using a non-reasoning model whose id/provider matches one of the ungated branches (e.g. a non-thinking zai/zhipuai model via @ai-sdk/openai-compatible).
Invoke it via the task tool — its normal output is recorded as thinking.
Add options: { thinking: { type: "disable" } } to that agent to try to disable it.
The provider rejects the request because the non-thinking model has no thinking parameter.
Still reproduces on current dev (v1.18.11, 0eac096). Confirming the gpt-5 branch from bullet 3 with a minimal runnable case, and refreshing the line references since they've drifted from the ~L1174 in the report.
The branch is now at packages/opencode/src/provider/transform.ts:1278:
if(input.model.api.id.includes("gpt-5")&&!input.model.api.id.includes("gpt-5-chat")){if(!input.model.api.id.includes("gpt-5-pro")){result["reasoningEffort"]="medium"// :1280 — never checks capabilities.reasoning// reasoningSummary / include below ARE npm-gated, but reasoningEffort is not}if(input.model.api.id.includes("gpt-5.")&&!input.model.api.id.includes("codex")&&!input.model.api.id.includes("-chat")&&input.model.providerID!=="azure"){result["textVerbosity"]="low"// :1302 — same, no capability check}}
Repro — a self-hosted OpenAI-compatible gateway serving a model whose id contains gpt-5, with capabilities.reasoning: false:
capabilities.reasoning === false for every model below
api.id="gpt-5.1" => options() => {"reasoningEffort":"medium","textVerbosity":"low"}
api.id="gpt-5.2" => options() => {"reasoningEffort":"medium","textVerbosity":"low"}
api.id="gpt-5" => options() => {"reasoningEffort":"medium"}
Downstream this isn't inert: @ai-sdk/openai-compatible's getArgs() maps reasoningEffort → reasoning_effort and textVerbosity → verbosity straight onto the /chat/completions body, so a non-reasoning model on a custom gateway ends up sending params it never advertised.
One case-sensitivity note for whoever picks this up: the match is includes("gpt-5") on the raw api.id (never lowercased, unlike most other id checks in this file), so lowercase LiteLLM-style aliases like gpt-5.1 trigger it while an uppercase alias like GPT-5.5 does not — worth normalizing alongside the capability gate.
Not touching the fix since this is assigned — just adding a reproducible anchor at current HEAD. Happy to help test a gate patch.
Activity
github-actions commentedon Jun 28, 2026
This issue might be a duplicate of existing issues. Please check:
thinkingConfig/ thinking options injected intransform.tswithout checkingcapabilities.reasoning, breaking non-thinking models (reported for Vertex AI / Google provider, but the same pattern)a-yeyang commentedon Aug 1, 2026
Still reproduces on current
dev(v1.18.11,0eac096). Confirming thegpt-5branch from bullet 3 with a minimal runnable case, and refreshing the line references since they've drifted from the~L1174in the report.The branch is now at
packages/opencode/src/provider/transform.ts:1278:Repro — a self-hosted OpenAI-compatible gateway serving a model whose id contains
gpt-5, withcapabilities.reasoning: false:Downstream this isn't inert:
@ai-sdk/openai-compatible'sgetArgs()mapsreasoningEffort → reasoning_effortandtextVerbosity → verbositystraight onto the/chat/completionsbody, so a non-reasoning model on a custom gateway ends up sending params it never advertised.One case-sensitivity note for whoever picks this up: the match is
includes("gpt-5")on the rawapi.id(never lowercased, unlike most other id checks in this file), so lowercase LiteLLM-style aliases likegpt-5.1trigger it while an uppercase alias likeGPT-5.5does not — worth normalizing alongside the capability gate.Not touching the fix since this is assigned — just adding a reproducible anchor at current HEAD. Happy to help test a gate patch.
github-actions commentedon Oct 1, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.