Repository navigation
feat(core): read model reasoning from config - #55853
Conversation
ec18200 to
4db586a
Compare
There was a problem hiding this comment.
I found nothing that should block this. I ran serve from source on the base and on this branch with one config for a custom aisdk:@ai-sdk/openai provider and checked GET /api/model:
- On the base,
capabilities.reasoningis ignored and every model gets the full default variant list. - On this branch,
effort: ["default","low","high"]giveslow/high, andsupported: truewith no controls gives no variants. A model withoutreasoningkeeps the default list.
The new tests in packages/core and the typecheck scripts in packages/core and packages/schema pass. The change reuses Variant.resolve the same way the models.dev loader does.
Public API: this adds the optional config key providers.*.models.*.capabilities.reasoning ({ supported, toggle?, effort?, budget?: { min?, max? } }). It also adds the schema Config.Model.Reasoning to the OpenAPI spec and the generated client types. Nothing is removed or renamed, so it is backwards compatible: existing configs behave as before. Model.mergeCapabilities still drops reasoning, so GET /api/model does not report capabilities.reasoning.
4db586a to
7238523
Compare
Follow-up to the port, now layered on top of the rich Config.Model.Reasoning that landed in anomalyco#55853: - capabilities: mergeCapabilities accepts the rich config reasoning object and derives the runtime reasoning flag from its `supported` value, so a config-declared capability survives into Model.Info - v1 migration: migrateModel keeps a declared reasoning flag by translating it to { supported } and includes reasoning-only models in the capabilities guard - protocol/client: regenerate generated outputs (Model.Capabilities.reasoning) - tests: v1 migration + config overlay coverage Co-authored-by: hril3 <hril3@users.noreply.github.com>
Follow-up to the port, now layered on top of the rich Config.Model.Reasoning that landed in anomalyco#55853: - capabilities: mergeCapabilities accepts the rich config reasoning object and derives the runtime reasoning flag from its `supported` value, so a config-declared capability survives into Model.Info - v1 migration: migrateModel keeps a declared reasoning flag by translating it to { supported } and includes reasoning-only models in the capabilities guard - protocol/client: regenerate generated outputs (Model.Capabilities.reasoning) - tests: v1 migration + config overlay coverage Co-authored-by: hril3 <hril3@users.noreply.github.com>
Follow-up to the port, now layered on top of the rich Config.Model.Reasoning that landed in anomalyco#55853: - capabilities: mergeCapabilities accepts the rich config reasoning object and derives the runtime reasoning flag from its `supported` value, so a config-declared capability survives into Model.Info - v1 migration: migrateModel keeps a declared reasoning flag by translating it to { supported } and includes reasoning-only models in the capabilities guard - protocol/client: regenerate generated outputs (Model.Capabilities.reasoning) - tests: v1 migration + config overlay coverage Co-authored-by: hril3 <hril3@users.noreply.github.com>
Why
Org admins can now set which reasoning controls a model accepts in the OpenCode Console (anomalyco/opencode-console#3690): none, fixed, effort levels, or a token budget. The Console sends these controls in the pulled config, but OpenCode had no config field for them. So a team couldn't fix a custom model's reasoning variants without writing raw request bodies for each provider.
What changes
providers.*.models.*.capabilities.reasoningin models.dev v2's shape:{ supported, toggle?, effort?, budget?: { min?, max? } }.capabilities.reasoningis set, OpenCode builds the model's variants from it for the model's package. These replace the base variants.supported: false, orsupported: truewith no controls ("fixed"), means no variants.defaulteffort adds no variant, since it means the provider's own default.variantsstill apply on top.releaseDate(YYYY-MM-DDorYYYY-MM) sets the model's release time.capabilities.temperaturerecords whether the model accepts a temperature. Model capabilities now carry it as optional metadata.compatibility.reasoningField; the Console now sends it.Verification
bun run checkpasses.Variant.supports, for the config plugin with effort, fixed, and unsupported models, and for the release date, temperature, and reasoning field. Tests run in CI. Checked end to end against a local Console: a GPT-5.2 override ofeffort: ["low", "high"]gave exactlylowandhighvariants, while the unchanged branch kept all five catalog levels.Added by the opencode bot (AI-generated).
Related: #53202, #51846, #50257
Public API: adds the optional config key
providers.*.models.*.capabilities.reasoningand theConfig.Model.Reasoningschema to the OpenAPI spec and client types (backwards compatible)