What happened
On the opencode-go provider, deepseek-v4-flash has no thinking-strength control in the model picker. The model is reasoning-capable in Maka's own metadata (capabilities.reasoning === true), and models.dev declares reasoning_options for it: [{ "type": "effort", "values": ["high", "max"] }] (api.json fetched 2026-08-02).
The same model on the native deepseek provider does show the control with high/max. Expected behavior is that opencode-go exposes the upstream-declared effort options, or states explicitly that this path does not support a knob.
How to reproduce
- Add an
opencode-go connection and start a new chat with it.
- Select
deepseek-v4-flash. No thinking-strength control appears.
- Repeat with the native
deepseek provider and the same model. The control appears with high / max.
No configuration or code change is needed; this is the shipped behavior on main @ 92cde3d.
Environment
- Maka commit: 92cde3d (main)
- Surface: Desktop (renderer model picker + runtime)
- models.dev api.json fetched 2026-08-02
Root cause
-
scripts/sync-model-metadata.mjs toMetadata (line 117) reads model.reasoning (lines 124/137) but never reads model.reasoning_options, so packages/core/src/model-metadata.generated.ts can never carry thinking options. Running the script against today's api.json produces 0 thinkingOptions in the output while the input has 10 opencode-go models with non-empty reasoning_options.
-
Thinking options are declared by hand per provider path in STATIC_MODEL_METADATA (packages/core/src/model-metadata.ts), and only a few paths are covered (native deepseek at line 434). There are no entries for opencode, opencode-go, or opencode-free, so thinkingOptionsForModel('opencode-go', 'deepseek-v4-flash') is undefined, thinkingVariantsForModel(...) returns [], and the UI hides the knob (apps/desktop/src/renderer/use-shell-chat-model.ts:125,141).
-
The runtime wire is a separate manual switch. buildProviderOptions (packages/runtime/src/model-factory.ts) has no case for the opencode paths and falls through to default: return {}. Verified: buildProviderOptions({providerType:'opencode-go'}, 'deepseek-v4-flash', 'high') returns {}. Even a forced knob would send no parameter.
The problem is systemic, not an opencode-go typo: 41 of 44 providers with reasoning-capable models have at least one reasoning model without a thinking declaration (opencode-go 13/13, opencode 55/55, openrouter 201/205, vercel 142/143, ...). In the current data model, "model has no knob" and "we forgot to declare it" are indistinguishable, and both fail silently.
Suggested direction
- Pass
reasoning_options through scripts/sync-model-metadata.mjs (normalize effort / toggle / budget_tokens), so every plan inherits upstream-declared effort options on sync.
- Replace the manual metadata plus runtime-switch pairing with a single per-path thinking-wire declaration that drives both
thinkingVariantsForModel and buildProviderOptions.
- Classify every reasoning model as exactly one of: declared and wired, explicitly opaque (with reason), or non-reasoning. No "forgot" state.
- Enforce the above in
packages/core/src/__tests__/provider-catalog-contract.test.ts across PROVIDER_REGISTRY, so a new plan cannot regress silently.
Logs, screenshots, or additional context
- Verification against today's api.json:
deepseek-v4-flash has reasoning_options: [{"type":"effort","values":["high","max"]}] on opencode-go (no toggle), on opencode, and on native deepseek (which adds toggle).
opencode-go has 23 models, 13 reasoning-capable, 10 with non-empty reasoning_options (e.g. glm-5.2, hy3, grok-4.5, kimi-k3, gpt-5.6-luna, qwen3.x toggle + budget_tokens).
- OpenCode Zen docs serve
deepseek-v4-flash over OpenAI-compatible chat/completions. Actual reasoning_effort passthrough on https://opencode.ai/zen/go/v1 is not yet verified against the live endpoint (needs a key); this decides whether opencode-go is wired or first declared opaque with a documented reason.
- Side observation: today's api.json names the model "DeepSeek V4 Flash (New)" while the repo snapshot says "DeepSeek V4 Flash". The snapshot is stale relative to upstream, which is expected since sync is periodic.
What happened
On the
opencode-goprovider,deepseek-v4-flashhas no thinking-strength control in the model picker. The model is reasoning-capable in Maka's own metadata (capabilities.reasoning === true), and models.dev declaresreasoning_optionsfor it:[{ "type": "effort", "values": ["high", "max"] }](api.json fetched 2026-08-02).The same model on the native
deepseekprovider does show the control withhigh/max. Expected behavior is thatopencode-goexposes the upstream-declared effort options, or states explicitly that this path does not support a knob.How to reproduce
opencode-goconnection and start a new chat with it.deepseek-v4-flash. No thinking-strength control appears.deepseekprovider and the same model. The control appears withhigh/max.No configuration or code change is needed; this is the shipped behavior on
main@ 92cde3d.Environment
Root cause
scripts/sync-model-metadata.mjstoMetadata(line 117) readsmodel.reasoning(lines 124/137) but never readsmodel.reasoning_options, sopackages/core/src/model-metadata.generated.tscan never carry thinking options. Running the script against today's api.json produces 0thinkingOptionsin the output while the input has 10 opencode-go models with non-emptyreasoning_options.Thinking options are declared by hand per provider path in
STATIC_MODEL_METADATA(packages/core/src/model-metadata.ts), and only a few paths are covered (nativedeepseekat line 434). There are no entries foropencode,opencode-go, oropencode-free, sothinkingOptionsForModel('opencode-go', 'deepseek-v4-flash')isundefined,thinkingVariantsForModel(...)returns[], and the UI hides the knob (apps/desktop/src/renderer/use-shell-chat-model.ts:125,141).The runtime wire is a separate manual switch.
buildProviderOptions(packages/runtime/src/model-factory.ts) has no case for the opencode paths and falls through todefault: return {}. Verified:buildProviderOptions({providerType:'opencode-go'}, 'deepseek-v4-flash', 'high')returns{}. Even a forced knob would send no parameter.The problem is systemic, not an opencode-go typo: 41 of 44 providers with reasoning-capable models have at least one reasoning model without a thinking declaration (
opencode-go13/13,opencode55/55,openrouter201/205,vercel142/143, ...). In the current data model, "model has no knob" and "we forgot to declare it" are indistinguishable, and both fail silently.Suggested direction
reasoning_optionsthroughscripts/sync-model-metadata.mjs(normalizeeffort/toggle/budget_tokens), so every plan inherits upstream-declared effort options on sync.thinkingVariantsForModelandbuildProviderOptions.packages/core/src/__tests__/provider-catalog-contract.test.tsacrossPROVIDER_REGISTRY, so a new plan cannot regress silently.Logs, screenshots, or additional context
deepseek-v4-flashhasreasoning_options: [{"type":"effort","values":["high","max"]}]onopencode-go(notoggle), onopencode, and on nativedeepseek(which addstoggle).opencode-gohas 23 models, 13 reasoning-capable, 10 with non-emptyreasoning_options(e.g.glm-5.2,hy3,grok-4.5,kimi-k3,gpt-5.6-luna, qwen3.xtoggle+budget_tokens).deepseek-v4-flashover OpenAI-compatiblechat/completions. Actualreasoning_effortpassthrough onhttps://opencode.ai/zen/go/v1is not yet verified against the live endpoint (needs a key); this decides whether opencode-go is wired or first declared opaque with a documented reason.