Repository navigation
Description
Description
Models whose models.dev entry declares reasoning_options = [{ type = "toggle" }] get no variants at all when their provider package is @ai-sdk/openai-compatible. Since variants is what clients render a reasoning control from, those models look like they have no reasoning support — even though reasoning: true is set and the API does support toggling.
reasoningToggle() in packages/opencode/src/provider/transform.ts only maps two packages and returns an empty object for everything else:
function reasoningToggle(model: Provider.Model) {
if (model.api.npm === "@ai-sdk/alibaba")
return { none: { enableThinking: false }, high: { enableThinking: true } }
if (model.api.npm === "@ai-sdk/cohere")
return { none: { thinking: { type: "disabled" } }, high: { thinking: { type: "enabled" } } }
return {}
}reasoningVariants() then calls nonEmptyVariants(reasoningToggle(target)), and nonEmptyVariants({}) returns undefined → variants is empty. nvidia escapes via a dedicated branch in reasoningEffort's sibling path, and openrouter has its own transform that implements case "toggle".
Count from the current models.dev catalog: 499 models across 83 providers declare a toggle on @ai-sdk/openai-compatible; 14 of those are nvidia, so 485 get no reasoning control. Affected providers include all four Xiaomi token-plan providers (xiaomi, xiaomi-token-plan-cn, xiaomi-token-plan-ams, xiaomi-token-plan-sgp — every mimo-v2*, mimo-v2.5*, mimo-v2.6* model), plus zenmux, llmgateway-providers, novita-ai, qiniu-ai, ofox, wandb, zhipuai, empiriolabs, 302ai, opencode, and ~70 more.
Concrete case: MiMo-V2.6-Pro on Xiaomi Token Plan (Europe)
models.dev is correct here and documents its source:
# providers/xiaomi-token-plan-ams/models/mimo-v2.6-pro.toml
# Toggle: thinking.type = enabled|disabled
# Source: https://mimo.mi.com/docs/en-US/tokenplan/Token Plan/quick-access
reasoning_options = [{ type = "toggle" }]Measured against the live endpoint (token-plan-ams.xiaomimimo.com, mimo-v2.6-pro, identical prompt):
| request | completion_tokens_details.reasoning_tokens |
reasoning_content in reply |
|---|---|---|
thinking: {type: "disabled"} |
0 | absent |
thinking: {type: "enabled"} |
12 | present |
reasoning_effort: "low" |
12 | present |
reasoning_effort: "high" |
12 | present |
So the toggle is the only control the API honours, reasoning_effort is ignored, and opencode v2 cannot express the toggle on this package.
For contrast, an effort model on the same package does get variants: deepseek-v4.1-flash → low/high/max.
No config-level workaround
Model-level options are filtered through opencode's own option schema before reaching the provider, not passed through verbatim. Against a local echo server on the OpenAI-compatible path:
options: { reasoningEffort: "high" }→ body containsreasoning_effort: "high"options: { thinking: { type: "disabled" } }→ body containsthinking: nulloptions: { user: "probe-marker" }→ dropped
So there is no way to hand-write the thinking body field from config for an openai-compatible provider.
Steps to reproduce
- Configure an
@ai-sdk/openai-compatibleprovider, e.g.xiaomi-token-plan-amswithnpm: "@ai-sdk/openai-compatible". - Request the model info for a toggle model, e.g.
GET /provider(v2.0.12) and readvariantsformimo-v2.6-pro→[]. - Repeat with an effort model on the same provider, e.g.
deepseek-v4.1-flash→["low", "high", "max"]. reasoningVariants()inpackages/opencode/src/provider/transform.tsshows the toggle branch resolving toundefinedfor this package.
Question about the fix shape
Adding a reasoningToggle() case is a small code change, but the wire field is provider-specific: MiMo wants thinking.type, Alibaba enableThinking, nvidia chat_template_kwargs.enable_thinking, OpenRouter reasoning.enabled. A generic default for @ai-sdk/openai-compatible would be wrong for most of the 485. Options I see:
- models.dev gains a field describing the toggle body shape (e.g.
reasoning_options: [{ type = "toggle", body = { thinking = { type = ... } } }]), andreasoningToggle()honours it. - dedicated provider packages for the big ones (
@opencode/ai/providers/xiaomi), as exists for deepseek/zai/anthropic/etc. - at minimum, keep the capability visible to clients even when no variant can be built, so the model isn't presented as non-reasoning.
Happy to go with whatever direction you prefer — I can also test a candidate mapping against the providers' documented APIs.
Environment
- OpenCode version: 2.0.12
- Operating System: macOS (darwin-arm64)
- Terminal: OpenChamber desktop (managed
opencode serve) - Plugins: none
Activity
github-actions commentedon Sep 26, 2026
This issue might overlap with existing reports. Please check:
reasoningToggle()returning{}for@ai-sdk/openai-compatiblemodels declaring a toggle, leaving GLM models without reasoning variants.opencodejr commentedon Oct 28, 2026
Thanks for the detailed write-up and the live-endpoint measurements!
To restate the request: models on the generic
@ai-sdk/openai-compatiblepackage whose catalog entry declares only a reasoning toggle (e.g. all Xiaomi MiMo models) should getnone/thinkingvariants, sent in the shape each provider expects (for MiMo,thinking.type).A couple of notes from the current v2 code:
packages/core/src/variant.ts, notprovider/transform.ts. There,@opencode/ai/providers/openai-compatibleonly builds toggle variants fornvidia. For every other provider it falls back to effort-only, so toggle models get no variants. That's deliberate for now, because, as you point out, the toggle field differs per provider and a generic default would be wrong for most of them. So I'm treating this as a feature request rather than a bug.body, which is a different mechanism fromoptions. Something like this should send thethinkingfield as-is:{ "providers": { "xiaomi-token-plan-ams": { "models": { "mimo-v2.6-pro": { "variants": [ { "id": "none", "body": { "thinking": { "type": "disabled" } } }, { "id": "thinking", "body": { "thinking": { "type": "enabled" } } } ] } } } } }The fix directions you listed are useful input: a toggle body shape in models.dev, per-provider mappings or dedicated packages, or keeping the reasoning capability visible to clients. Maintainers will consider which one fits. Please reply if the
bodyvariants above don't reach the wire for you.