fix(tui): scope model candidates to active provider#3428
Conversation
Make the /model command, model picker main section, and slash completions stay inside the active provider scope. Cross-provider saved/catalog rows no longer appear as bare model choices or silently switch providers; explicit route-switch UX remains deferred to the route resolver/search work. Tests: cargo test -p codewhale-tui --bin codewhale-tui --locked tui::model_picker; cargo test -p codewhale-tui --bin codewhale-tui --locked tui::widgets; cargo test -p codewhale-tui --bin codewhale-tui --locked visible_slash_model_completions_are_provider_scoped; cargo test -p codewhale-tui --bin codewhale-tui --locked commands::groups::core::core; cargo test -p codewhale-tui --bin codewhale-tui --locked model_inventory; cargo test -p codewhale-tui --bin codewhale-tui --locked route_resolver; python3 scripts/check-provider-registry.py; cargo fmt --all -- --check; git diff --check
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
There was a problem hiding this comment.
Code Review
This pull request refactors the model picker and slash command completions to scope model choices strictly to the active provider, removing the automatic cross-provider switching behavior. The reviewer feedback recommends removing the unused _api_provider parameter from the newly introduced slash_completion_hints_with_model_candidates function and its callers to simplify the function signatures and reduce coupling.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| let model_candidates = model_completion_names_for_provider(api_provider) | ||
| .into_iter() | ||
| .map(str::to_string) | ||
| .collect::<Vec<_>>(); | ||
| slash_completion_hints_with_model_candidates( | ||
| input, | ||
| limit, | ||
| cached_skills, | ||
| locale, | ||
| workspace, | ||
| api_provider, | ||
| &model_candidates, | ||
| ) | ||
| } | ||
|
|
||
| pub(crate) fn slash_completion_hints_with_model_candidates( | ||
| input: &str, | ||
| limit: usize, | ||
| cached_skills: &[(String, String)], | ||
| locale: crate::localization::Locale, | ||
| workspace: Option<&std::path::Path>, | ||
| _api_provider: ApiProvider, | ||
| model_candidates: &[String], | ||
| ) -> Vec<SlashMenuEntry> { |
There was a problem hiding this comment.
The _api_provider parameter in slash_completion_hints_with_model_candidates is unused. We can remove it to simplify the function signature and reduce coupling.
let model_candidates = model_completion_names_for_provider(api_provider)
.into_iter()
.map(str::to_string)
.collect::<Vec<_>>();
slash_completion_hints_with_model_candidates(
input,
limit,
cached_skills,
locale,
workspace,
&model_candidates,
)
}
pub(crate) fn slash_completion_hints_with_model_candidates(
input: &str,
limit: usize,
cached_skills: &[(String, String)],
locale: crate::localization::Locale,
workspace: Option<&std::path::Path>,
model_candidates: &[String],
) -> Vec<SlashMenuEntry> {| slash_completion_hints_with_model_candidates( | ||
| &app.input, | ||
| limit, | ||
| &app.cached_skills, | ||
| app.ui_locale, | ||
| Some(&app.workspace), | ||
| app.api_provider, | ||
| &model_candidates, | ||
| ) |
| let candidates = slash_completion_hints_with_model_candidates( | ||
| &app.input, | ||
| 128, | ||
| &app.cached_skills, | ||
| app.ui_locale, | ||
| Some(&app.workspace), | ||
| app.api_provider, | ||
| &model_candidates, | ||
| ) |
There was a problem hiding this comment.
Keep the slash completion convenience wrapper test-only after the production slash menu path moved to explicit provider-scoped candidates. This avoids dead-code and unused-import failures under release/clippy builds while preserving the existing widget unit tests.
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
Goal
Advance #3383 by making the main
/modelsurfaces provider-scoped by default. A bare model string should no longer look like permission to switch providers.Changes
/model <name>so saved models from other providers no longer silently emitSwitchProviderVerification
cargo test -p codewhale-tui --bin codewhale-tui --locked tui::model_pickercargo test -p codewhale-tui --bin codewhale-tui --locked tui::widgetscargo test -p codewhale-tui --bin codewhale-tui --locked visible_slash_model_completions_are_provider_scopedcargo test -p codewhale-tui --bin codewhale-tui --locked commands::groups::core::corecargo test -p codewhale-tui --bin codewhale-tui --locked model_inventorycargo test -p codewhale-tui --bin codewhale-tui --locked route_resolver(0 matching tests)python3 scripts/check-provider-registry.pycargo fmt --all -- --checkgit diff --checkRisks
slash_completion_hints(...)test helper still defaults to static provider rows; the live app path now passes the provider-scoped candidate projection fromApp.ReadyRouteCandidateor v0.8.65: Provider-owned live catalogs and secret-free model cache #3385 live catalog/cache work.Fixes #3383.