Skip to content

feat(models): expose model capabilities in the catalog - #2281

Merged
chuks-qua merged 6 commits into
mainfrom
feat/mpe-01-model-capabilities
Oct 23, 2026
Merged

chuks-qua merged 6 commits into
mainfrom
feat/mpe-01-model-capabilities

Conversation

@chuks-qua

@chuks-qua chuks-qua commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

What

Closes #2225. Part of #1813.

Before this change, the composer and Settings decided Fast mode, the 1M context window, and reasoning levels with provider checks and model-name rules. Now each provider model declares those capabilities in the catalog, and the UI reads them.

 ProviderModelInfo (packages/contracts)
   supportedReasoningEfforts
+  supportsFastMode?: boolean
+  contextWindowOptions?: ("200k" | "1m")[]

 ComposerModelPreferences
-  hasCodexFast = provider === "codex"
-  has1M = supports1MContextWindow(modelId)
+  hasFast = model.supportsFastMode === true
+  has1M = model.contextWindowOptions includes "1m"

 ModelSection / composer reasoning control
-  provider branches + PROVIDERS_WITHOUT_REASONING_LEVELS
+  getReasoningLevels(providerId, modelId)

Where the values come from:

  • Codex. Live model/list reports serviceTiers. A model supports Fast when that list contains priority. When the field is absent, the static row decides. Every static Codex row declares Fast.
  • Claude. Static rows other than Haiku declare ["200k", "1m"]. Models from the Anthropic REST list get reasoning levels from the shared effort rules, then merge with the static row. No Claude row declares Fast yet. MPE-03 (feat(MPE-03): Claude Fast mode adapter #2229) adds it.
  • Web registry. toModelDefinition is the one mapper from contract row to ModelDefinition. findProviderModel(providerId, modelId) and getReasoningLevels(providerId, modelId) replace the unscoped helpers, which are deleted.

Verified with targeted Vitest runs in contracts, providers, and web, plus bun run typecheck and bun run lint (0 errors).

Why

Provider quirks belong in adapters. Each new capability or model previously meant another branch in the composer, Settings, and the registry. With the capability on the model row, MPE-02 (Fast for every provider) and MPE-03 (Claude Fast) only change data in the adapters.

Two behaviour changes follow from reading declared levels:

  • The composer and Settings show a reasoning control for Copilot and Cursor models that declare levels. Before, both providers were in PROVIDERS_WITHOUT_REASONING_LEVELS, so declared levels were hidden.
  • If the Claude catalog has no row for a model, Settings no longer shows a disabled X-High button built from name rules. It shows the levels the catalog declares, or no row.

UI Changes

Parity captures on the fixture runtime, main against this branch. All four before and after pairs are byte-identical (same SHA-256). The 1M pill on Sonnet 4.6 and the Fast bolt on Codex now come from the new fields. The Copilot change needs a live Copilot CLI that declares levels, so it is covered by tests, not a capture.

Composer, Claude Sonnet 4.6, before and after:

before
after

Composer, Codex GPT-6 Luna, before and after:

before
after

Review Notes

Door: two-way. The new contract fields are optional, and a revert restores the old checks. No migration.

Blast radius: model controls. A wrong capability row would show or hide Fast, 1M, or a reasoning level for one model.

  • Live Claude SDK discovery is skipped. supportedModels() on SDK 0.3.291 takes about 1.3 s because it spawns the CLI (measured). It reports Fast for Opus 5.5, Opus 5, and Opus 4.8, effort levels identical to the static rows, and no 1M field. The static rows give the same data without the spawn. MPE-03 adds Claude Fast.
  • Codex facts. codex-cli 0.163.0 model/list reports serviceTiers: [{ id: "priority", name: "Fast" }] for every visible model (measured).
  • Follow-ups. codexFastMode keeps its name. MPE-02 renames it and adds Fast for other providers.
  • Tests. A new Devin test proves the reasoning snap reads the Devin catalog. It fails when the lookup uses the Codex catalog.
  • Docs. None needed.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

…m the provider-scoped catalog

Settings showed the reasoning row from declared levels but built its options from a second lookup with Copilot and Claude fallbacks that could no longer render. Both now read getReasoningLevels. The Devin model switch reads findProviderModel, and the unscoped getModelReasoningLevels, getModelDefaultReasoningLevel, getCodex* and isXhighModel helpers are deleted.
@chuks-qua
chuks-qua merged commit 3407175 into main Oct 23, 2026
11 checks passed
@chuks-qua
chuks-qua deleted the feat/mpe-01-model-capabilities branch October 23, 2026 11:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(MPE-01): expose model capabilities in the catalog

1 participant