anomalyco / anomalyco/opencode
Free Zen models with reasoning=true show zero thinking variants (reasoning_options=[] blocks fallback)
@nexxeln is already working on this.
Since Sep 14, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Summary
Several free OpenCode Zen models advertise reasoning = true in models.dev but expose zero thinking variants in OpenCode (/models picker + variant_cycle). Users cannot select low / medium / high thinking effort for these models.
Affected models (provider = opencode)
Verified against https://models.dev/api.json (opencode provider) and Zen docs (2026-09-13):
| Model ID | reasoning |
reasoning_options |
Variants shown |
|---|---|---|---|
big-pickle |
true | [] |
none (bug) |
mimo-v2.5-free |
true | [] |
none (bug) |
nemotron-3-ultra-free |
true | [] |
none (bug) |
nemotron-3.5-lightning-free |
true | [] |
none (bug) |
minimax-m2.5-free |
true | [] |
none (bug) |
ling-3.0-flash-fin-free |
true | [{type="toggle"}] |
low/medium/high via fallback (OK) |
muse-spark-1.3-contributor-free |
true | [{type="effort", values=[minimal,low,medium,high,xhigh]}] |
5 variants (OK) |
deepseek-v4-flash-free |
true | [{type="effort", values=[low,high,max]}] |
OK |
kimi-k2.5-free / glm-5-free / qwen3.6-plus-free |
true | [{type="toggle"}] (+budget for qwen) |
none — fallback denylisted (see below) |
Zen endpoint table serves 5/6 advertised free models via https://opencode.ai/zen/v1/chat/completions (@ai-sdk/openai-compatible); only muse-spark-1.3-contributor-free uses .../v1/responses (@ai-sdk/openai).
Expected vs actual
- Expected: models with
reasoning = trueserved over OpenAI-compatible API expose genericlow/medium/highvariants (same asling-3.0-flash-fin-freedoes today). - Actual: models with
reasoning_options = []show no variants at all.
Root cause (two layers)
1. reasoningVariants() returns {} instead of undefined for []
packages/opencode/src/provider/transform.ts:1704:
export function reasoningVariants(model: ModelsDev.Model, target: Provider.Model) {
const options = model.reasoning_options
if (options === undefined) return
if (options.length === 0) return {}
// ...
}
2. ?? fallback never runs on {}
packages/opencode/src/provider/provider.ts:1314:
const variants = ProviderTransform.reasoningVariants(model, base) ?? ProviderTransform.variants(base)
{} is not nullish, so generic variants(base) never runs for the [] models. Result: zero variants despite reasoning=true.
3. Hardcoded denylist in variants() also returns {}
packages/opencode/src/provider/transform.ts:777:
if (
id.includes("deepseek-chat") ||
id.includes("deepseek-reasoner") ||
id.includes("deepseek-r1") ||
id.includes("deepseek-v3") ||
id.includes("minimax") ||
(id.includes("glm") && !glm52) ||
id.includes("kimi") ||
id.includes("k2p") ||
id.includes("qwen") ||
id.includes("big-pickle")
)
return {}
This blocks fallback for big-pickle, kimi-*, qwen-*, glm-* (non-5.2), minimax-* even when reasoning=true. For toggle-only models on @ai-sdk/openai-compatible, reasoningToggle() returns {} -> nonEmptyVariants({}) -> undefined -> fallback -> denylist {}. Net: no variants.
Models.dev evidence
Raw TOMLs (anomalyco/models.dev@dev:providers/opencode/models/):
mimo-v2.5-free.toml:reasoning = true,reasoning_options = []nemotron-3-ultra-free.toml:reasoning = true,reasoning_options = []nemotron-3.5-lightning-free.toml:reasoning_options = []big-pickle.toml:reasoning = true,reasoning_options = []minimax-m2.5-free.toml:reasoning = true,reasoning_options = []ling-3.0-flash-fin-free.toml:reasoning_options = [{ type = "toggle" }](works via fallback)muse-spark-1.3-contributor-free.toml:reasoning_options = [{ type = "effort", values = [...] }]+[provider] npm = "@ai-sdk/openai"(works)
Suggested fix (either side, ideally both)
- Option A (code,
anomalyco/opencode): treat empty variants as missing. E.g.reasoningVariants() returns undefined for [], or change call site to fall back whenObject.keys(variants).length === 0. - Option B (data,
anomalyco/models.dev): give free OpenAI-compatible reasoning models real effort options, e.g.reasoning_options = [{ type = "effort", values = ["low", "medium", "high"] }], or document that[]means fixed always-on reasoning with no knob. - Re-evaluate denylist entry for
big-pickleifreasoningEffortpassthrough works on Zen chat-completions endpoint.
Workaround
Custom variants in opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"opencode": {
"models": {
"mimo-v2.5-free": {
"variants": {
"low": { "reasoningEffort": "low" },
"medium": { "reasoningEffort": "medium" },
"high": { "reasoningEffort": "high" }
}
}
}
}
}
}
Environment
opencode v2.0.3(Windows,C:\Users\baban\.bun\bin\opencode.exe)- Zen docs last updated 2026-09-13,
/zen/v1/modelschecked 2026-09-14 - models.dev
opencodeprovider, 102 models
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.