Conversation
…ibutors-20260913 Welcome pull requests from all contributors
config.provider.default_model is persisted by the model picker as a full model spec that may carry an explicit provider/credential prefix (e.g. "claude-oauth:claude-sonnet-5"), but route.model in the live catalog is always the bare model id. The comparison in provider_model_to_select_after_auth_with_configured_default compared the raw prefixed string against route.model, which never matched, so the "preserve configured default" branch silently no-op'd and execution fell through to the flagship-first fallback (Opus) on every /login or /refresh-model-list. Strip the prefix via jcode_provider_core::selection::explicit_model_provider_prefix before comparing. Added a regression test reproducing the exact scenario.
|
| let configured_bare = configured_model.map(|model| { | ||
| jcode_provider_core::selection::explicit_model_provider_prefix(model) | ||
| .map(|(_, _, bare)| bare) | ||
| .unwrap_or(model) | ||
| }); |
There was a problem hiding this comment.
When a configured default explicitly selects claude-api:claude-sonnet-5, this code removes the claude-api credential-route prefix and accepts the bare model during a Claude OAuth login. The later selection rebuild changes it to claude-oauth:claude-sonnet-5, so an API-key route configured by the user is silently replaced with OAuth credentials. Preserve the configured route constraint when matching the post-authentication catalog, or do not accept the configured default when it is incompatible with the activated route.
Artifacts
- This is the full temporary Rust test source executed against the changed selection and rebuild path, showing the configured API-key route is expected to become an OAuth route.
- This is the exact shell command wrapper used to copy the temporary test into the crate, run Cargo, capture its status, and remove it afterward.
- Cargo executed one focused test successfully and printed the configured, selected, and rebuilt values, confirming the explicit API-key route changed to OAuth.
Ran code and verified through T-Rex
Prompt To Fix With AI
This is a comment left during a code review.
Path: crates/jcode-base/src/auth/lifecycle.rs
Line: 238-242
Comment:
**Credential Route Is Rewritten**
When a configured default explicitly selects `claude-api:claude-sonnet-5`, this code removes the `claude-api` credential-route prefix and accepts the bare model during a Claude OAuth login. The later selection rebuild changes it to `claude-oauth:claude-sonnet-5`, so an API-key route configured by the user is silently replaced with OAuth credentials. Preserve the configured route constraint when matching the post-authentication catalog, or do not accept the configured default when it is incompatible with the activated route.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
Problem
When
config.provider.default_modelis set to a provider-prefixed spec (e.g.claude-oauth:claude-sonnet-5, which is exactly what the model picker persists via/model-> "save as default"), running/loginto re-authenticate or/refresh-model-listsilently reverts the active model to the flagship default (Opus) instead of keeping the configured Sonnet model.Root cause
provider_model_to_select_after_auth_with_configured_defaultincrates/jcode-base/src/auth/lifecycle.rscompares the configured default model directly againstroute.modelfrom the live catalog:route.modelin the catalog is always the bare model id (e.g.claude-sonnet-5), butconfig.provider.default_modelis persisted by the model picker as a full spec that may carry an explicit provider/credential prefix (e.g.claude-oauth:claude-sonnet-5,claude-api:claude-fable-5). The direct string comparison never matches when a prefix is present, so the "preserve the configured default" branch silently no-ops and falls through to the flagship-first fallback, which always prefers Opus.The cold-start path (
MultiProvider::set_config_default_model) already handles this correctly by checkingexplicit_model_provider_prefixbefore matching — this is why a freshjcodelaunch respects the configured Sonnet default, but re-authenticating via/loginor refreshing the catalog via/refresh-model-listdoes not.Fix
Strip the provider prefix off the configured model (using the existing
jcode_provider_core::selection::explicit_model_provider_prefixhelper) before comparing againstroute.model.Testing
post_auth_model_selection_preserves_provider_prefixed_configured_default, a regression test reproducing the exact reported scenario (prefixed config default + Claude re-auth), confirmed it fails on the old code and passes with the fix.cargo test -p jcode-base --lib auth::lifecycle::— 39/40 pass; the one pre-existing failure (every_model_login_provider_has_explicit_lifecycle_normalization, missinggrok-buildnormalization) reproduces identically onmasterbefore this change and is unrelated.