feat(claude): modernize model defaults and bound inline-completion output#46
feat(claude): modernize model defaults and bound inline-completion output#46herikwebb wants to merge 5 commits into
Conversation
…tput - Default chat fallback moves to claude-sonnet-5 (current Sonnet tier); the previous claude-sonnet-4-5 default is a generation behind. - Inline completion falls back to claude-haiku-4-5: a suggestion has to beat the user's next keystroke and fires on every pause in typing, so the fastest/cheapest tier is the right default there. - Cap inline-completion max_tokens at 1024 (override with NBI_CLAUDE_INLINE_COMPLETION_MAX_TOKENS); the old 10K ceiling let a rambling response generate for many seconds before the extraction regex threw most of it away. - fetch_claude_models prefers the Models API's max_input_tokens over litellm's static database, which lags new model releases; litellm remains the fallback when the field is absent.
Automated PR ReviewModel: Changed files: Review result: Automated Review FindingsMedium —
|
…ride Review follow-up (PR #46): NBI_CLAUDE_INLINE_COMPLETION_MAX_TOKENS was passed to the API unvalidated — a non-integer raised ValueError at import time and blocked the backend from starting, 0/negative values produced failing API requests, and a large value silently restored the unbounded behavior the cap exists to prevent. Parse via _bounded_int_env: malformed values warn and fall back to the 1024 default; out-of-range values are clamped to [1, 4096] with a warning.
Automated PR ReviewModel: Changed files: Review result: Automated findingsHigh —
|
Review follow-up (PR #46): the CLAUDE_DEFAULT_* constants name current first-party aliases, but a custom base_url can front an endpoint that serves a different catalog. resolve_default_model prefers the constant only when the endpoint lists it, then falls back to the newest id in the same tier, then to the first listed model. An empty cache (fetch not yet run, or failed) trusts the constant.
|
Re the finding on |
Automated PR ReviewModel: Changed files: Review result: FindingsMedium —
|
Review follow-up (PR #46): resolve_default_model validated defaults against a global cache with no endpoint identity, so after switching to a custom base_url (or while its refresh was in flight) the default could resolve against another endpoint's catalog and send it a model id it doesn't serve. fetch_claude_models now stamps the cache with the normalized (api_key, base_url) it fetched from, and resolve_default_model treats the cache as authoritative only for a matching endpoint — otherwise it trusts the constant until the endpoint's own fetch lands. Credential normalization makes ''/None equivalent, matching the settings-panel empty-field behavior.
Automated PR ReviewModel: Changed files: Review result: FindingsHigh —
|
Review follow-ups (PR #46, round 4): - The 'newest same tier' fallback sorted model ids lexicographically, which ranks claude-sonnet-4-6 above claude-sonnet-4-10. Sort by the extracted numeric version components instead ([4,6] < [4,10] < [5]), id as tiebreak. - When the cache demonstrably belongs to another endpoint (credentials changed), resolve_default_model now kicks off a background catalog refresh so subsequent resolutions converge on the new endpoint's catalog. It deliberately never blocks on the network: it runs in model constructors on the request path, and a slow or dead custom endpoint must degrade to one possibly-failing request, not a hung chat turn. A never-stamped cache is left to the startup fetch that update_models_from_config already fires.
|
Round-4 follow-ups pushed: tier fallback now sorts by numeric version components (fixes the |
Automated PR ReviewModel: Changed files: Review result: No automated findings were found. Residual risks: the new default model IDs and endpoint-aware fallback behavior depend on live Anthropic/custom-endpoint catalogs, so integration coverage against real or contract-tested model-list responses would still be valuable. |
Manual test results (2026-07-07)All four scenarios pass against the live first-party Anthropic API (credits now available):
Observation (not a defect)The Models API lists Haiku only under its dated id Leaving the constant as the rolling alias deliberately — resolving it via the fallback is exactly what this change is for. |
|
Raised upstream as plmbr#389; closing this fork PR. Review history retained here. |
Changes
claude-sonnet-4-5→claude-sonnet-5(current Sonnet tier).claude-haiku-4-5: a suggestion has to beat the user's next keystroke and fires on every pause in typing, so the fastest/cheapest tier is the right default.max_tokenscapped at 1024 (was 10000), overridable viaNBI_CLAUDE_INLINE_COMPLETION_MAX_TOKENS. The old ceiling let a rambling response generate for many seconds before the extraction regex threw most of it away.fetch_claude_modelsprefers the Models API'smax_input_tokens(validated as a positive int) over litellm's static database, which lags new model releases; litellm remains the fallback.Testing
Full Python suite passes (1298 tests).