Offer the models the account can actually reach in the model picker - #241
Merged
Conversation
The Claude side of GET /api/models was a hardcoded current-generation list plus whatever agent.model/agent.models named, so every model shipped after that constant was written stayed invisible in the composer even though the configured credentials could use it. Ask the Anthropic Models API (GET /v1/models) instead: primed once at gateway startup, cached in-process for 6h and refreshed in the background, so a newly released model needs no code change or config edit. Best-effort throughout — an explicit agent.models still wins, and Bedrock (no Models API on that client), a missing API key or an unreachable API all fall back to the built-in list. agent.model_discovery turns it off.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
claude-fable-5doesn't appear in the web composer's model selector, even though the configured API key can use it.GET /api/modelsbuilt the Claude list from config alone:agent.model+agent.models, and whenagent.modelswas unset, a hardcodedDEFAULT_CLAUDE_MODELStuple (claude-opus-5,claude-sonnet-4-6,claude-haiku-4-5-20251001). Every model Anthropic ships after that constant is written is invisible until someone edits code or config. On this install the API key exposes 11 models; the picker offered 3.The fix
Ask the Anthropic Models API (
GET /v1/models) which models the configured credentials actually reach, and offer those.New
nerve/models_catalog.py:proxy.enabled), cached in-process for 6h, then refreshed in the background — a stale entry is still served immediately, so only a cold cache ever waits on the network.proxy.enabledthe request is served by CLIProxyAPI, whose catalog can include non-Anthropic upstreams (Ollama, ...) that the picker lists separately.Resolution order is now, in
NerveConfig.selectable_claude_models():agent.models— an explicit list still wins outrightDEFAULT_CLAUDE_MODELS(the previous behaviour)agent.modelalways leads the list, as before. Discovery is skipped — falling through to 3 — on Bedrock (the Bedrock client has no Models API, and Bedrock IDs are region-prefixed), without an API key (OAuth-token installs), or when the API is unreachable.agent.model_discovery: falseturns it off entirely.config.claude_modelsstays as the config-only view, so nothing else that reads it changes.Verification
tests/test_models_catalog.py(10 tests): ordering, non-Claude filtering + dedup, Bedrock/no-key short-circuits, error swallowing, client cleanup, caching, failure backoff, credential-change invalidation, stale-serve-while-refreshing.tests/test_models_route.pyextended (6 tests): discovered models reach the picker, configured default leads, explicitagent.modelswins,model_discovery: falseand discovery failure both fall back to the built-in list.claude-fable-5andclaude-sonnet-5.No frontend change: the composer renders whatever the endpoint returns.