Repository navigation
Conversation
The models.dev catalog carries a `reasoning` flag for every model, but it was dropped when building V2 model capabilities, so the desktop model picker tooltip always showed "No reasoning". Carry the flag through the chain: - schema: add optional `reasoning` to `Model.Capabilities` - models-dev plugin: populate it from the catalog entry - config provider plugin: preserve it when user config overrides capabilities (and allow explicit override) - app global-sync mapper: map `capabilities.reasoning` into the app model store instead of hardcoding `false` - regenerate client types and refresh the vendored client snapshot so the app typecheck sees the new optional field The tooltip itself already reads `model.capabilities.reasoning` and needs no change.
The v1 provider config allowed declaring reasoning: true on a model, but migrateModel dropped it while building v2 capabilities, so explicitly configured reasoning models still reported no reasoning capability (the desktop model tooltip showed "No reasoning"). Include the flag in the capabilities construction condition and pass it through when defined, so a reasoning-only model still receives capabilities while keeping the empty defaults for tools/input/output. Requires anomalyco#50283 (reasoning on Model.Capabilities). Fixes anomalyco#51846
|
The following comment was made by an LLM, it may be inaccurate: |
VerificationVerified on Windows from a source build (bun 1.4.2), reproducing the config from #51846. 1. Unit — 2. Static — 3. API, end to end — with a v1 config in the project directory: {
"provider": {
"localtest": {
"npm": "@ai-sdk/openai-compatible",
"options": { "baseURL": "http://127.0.0.1:9999/v1", "apiKey": "sk-local-test" },
"models": {
"glm-flash": { "name": "GLM Flash", "reasoning": true },
"plain-model": { "name": "Plain Model", "tool_call": true }
}
}
}
}
{"id":"glm-flash","providerID":"localtest","capabilities":{"tools":false,"reasoning":true,"input":[],"output":[]}}
{"id":"plain-model","providerID":"localtest","capabilities":{"tools":true,"input":[],"output":[]}}Reverting only 4. UI — in the model picker ( Heads-up: this branch currently also carries the commit from #50283 (the |
|
Thanks for updating your PR! It now meets our contributing guidelines. 👍 |

Issue for this PR
Closes #51846
Type of change
What does this PR do?
A v1 config can mark a model as reasoning-capable with
reasoning: true.migrateModelinpackages/core/src/v1/config/migrate.tsbuilds the v2capabilitiesobject out oftool_callandmodalitiesand never looked atreasoning, so the flag was dropped during migration. For a model that only declaresreasoningthe result is nocapabilitiesobject at all, the config merge inconfig/plugin/provider.tsis skipped entirely, and the model keeps the catalog default, which has no reasoning capability. The client then renders "No reasoning" in the model tooltip for a model the user explicitly configured as reasoning-capable.The fix reads the flag in two places:
info.reasoning !== undefinedis added to the condition that decides whether acapabilitiesobject is built at all. Without that, the reasoning-only shape from desktop: model tooltip shows "No reasoning" for openai-compatible models configured with reasoning: true #51846 still producescapabilities: undefined.Building
capabilitiesfor a reasoning-only model is safe for the other fields:ModelV2.Info.empty()defaults to{tools: false, input: [], output: []}, which is exactly what the fallbacks in this function produce, so the model ends up with the values it already had, plus the declared reasoning flag.This depends on #50283, which adds
reasoningtoModel.Capabilitiesand preservesconfig.capabilities.reasoningwhen config is merged over the catalog. Without it the key is stripped while the migrated config is decoded, so this change alone would be a no-op. That commit is currently in this branch; I will rebase so only the migration change remains once it lands.How did you verify your code works?
Unit:
bun test test/config/config.test.tsinpackages/core, 18/18 pass. Three tests added: the flag is carried through, a reasoning-only model still gets capabilities and the migrated document still decodes as valid v2 config, and the key is omitted when the v1 model does not declare it. The existing FastCheck property test over arbitrary v1 configs still passes.Static:
bun turbo typecheck --filter=@opencode-ai/corepasses,bun run linton the changed files reports 0 errors (one pre-existing unused-import warning in that test file, untouched). The fullpackages/coresuite fails the same 16 tests with and without my change (cross-spawn / npm / network tests that need a different environment on Windows), so nothing regressed.End to end, with the config shape from the issue in the project directory:
{ "provider": { "localtest": { "npm": "@ai-sdk/openai-compatible", "options": { "baseURL": "http://127.0.0.1:9999/v1", "apiKey": "sk-local-test" }, "models": { "glm-flash": { "name": "GLM Flash", "reasoning": true }, "plain-model": { "name": "Plain Model", "tool_call": true } } } } }Running both versions of
migrate.tsside by side over that config:glm-flashpreviously got no capabilities object at all.plain-model, which does not declare the flag, is identical before and after.GET /api/modelfrom a source server booted in that directory:{"id":"glm-flash","providerID":"localtest","capabilities":{"tools":false,"reasoning":true,"input":[],"output":[]}} {"id":"plain-model","providerID":"localtest","capabilities":{"tools":true,"input":[],"output":[]}}Reverting only
migrate.tsand restarting the same server drops thereasoningkey fromglm-flash, which is the state the client renders as "No reasoning".UI: ran that server against
bun run dev:weband hovered both rows in the model picker.Screenshots / recordings
glm-flash, declared with v1reasoning: true, after the fix:plain-modelin the same list still shows "No reasoning", so the fallback is unchanged.Checklist