fix(ai): align model picker filtering
Some checks failed
Rust check (native) / macos-latest / 1.94 (push) Waiting to run
Rust check (native) / windows-latest / 1.94 (push) Waiting to run
Rust multi-platform build / linux-aarch64 (push) Waiting to run
Rust multi-platform build / macos-aarch64 (push) Waiting to run
Rust multi-platform build / windows-x86_64 (push) Waiting to run
Rust multi-platform build / macos-x86_64 (push) Waiting to run
Rust multi-platform build / windows-aarch64 (push) Waiting to run
Rust multi-platform build / ios-aarch64 (cargo check only) (push) Waiting to run
Rust multi-platform build / ios-aarch64-sim (cargo check only) (push) Waiting to run
Rust check (native) / ubuntu-latest / 1.94 (push) Failing after 2s
Rust check (native) / cargo-deny (native) (push) Failing after 1s
Rust check (native) / diagnostics golden drift (push) Failing after 2s
Rust multi-platform build / linux-x86_64 (push) Failing after 2s
Rust multi-platform build / wasm32-unknown-unknown / op-host-web (compile guard) (push) Failing after 1s
Rust multi-platform build / android-aarch64 (cargo check only) (push) Failing after 1s
Rust multi-platform build / android-x86_64 (cargo check only) (push) Failing after 1s
WASM bundle check (kickoff §1.2) / cargo check --target wasm32-unknown-unknown (push) Failing after 1s
WASM bundle check (kickoff §1.2) / cargo-deny --target wasm32-unknown-unknown check bans (push) Failing after 1s

This commit is contained in:
Fini 2026-05-31 03:23:03 +08:00
parent ba7292358e
commit 23bf862f16

View file

@ -23,7 +23,7 @@ pub const MODEL_SEARCH_H: f32 = 40.0;
/// Hard cap on the dropdown's painted height. A connected catalog /// Hard cap on the dropdown's painted height. A connected catalog
/// taller than this (e.g. OpenCode's 75+ models) scrolls inside the /// taller than this (e.g. OpenCode's 75+ models) scrolls inside the
/// card instead of growing off the top of the screen. /// card instead of growing off the top of the screen.
pub const MODEL_PICKER_MAX_H: f32 = 320.0; pub const MODEL_PICKER_MAX_H: f32 = 288.0;
const MODEL_EMPTY_H: f32 = 44.0; const MODEL_EMPTY_H: f32 = 44.0;
/// Painted height of the dropdown for `models` — the content height /// Painted height of the dropdown for `models` — the content height
@ -68,8 +68,12 @@ fn model_matches(entry: &ModelEntry, q: &str) -> bool {
|| entry.display_name.to_lowercase().contains(q) || entry.display_name.to_lowercase().contains(q)
|| entry.value.to_lowercase().contains(q) || entry.value.to_lowercase().contains(q)
|| provider_label(entry.provider).to_lowercase().contains(q) || provider_label(entry.provider).to_lowercase().contains(q)
|| group_label_for_entry(entry).to_lowercase().contains(q) || entry
|| (is_builtin(entry) && "api key".contains(q)) .builtin_provider_display_name
.as_deref()
.map(str::trim)
.filter(|label| !label.is_empty())
.is_some_and(|label| label.to_lowercase().contains(q))
} }
pub fn visible_model_indices(models: &[ModelEntry], search: &str) -> Vec<usize> { pub fn visible_model_indices(models: &[ModelEntry], search: &str) -> Vec<usize> {
@ -618,6 +622,16 @@ mod tests {
assert!(max_picker_scroll(&models, "") > 0.0); assert!(max_picker_scroll(&models, "") > 0.0);
} }
#[test]
fn long_catalog_height_is_capped_to_ts_dropdown_height_and_still_scrolls() {
let models: Vec<ModelEntry> = (0..40)
.map(|i| entry(AgentProvider::OpenCode, &format!("m{i}")))
.collect();
assert!((picker_view_height(&models, "") - 288.0).abs() < 0.01);
assert!(max_picker_scroll(&models, "") > 0.0);
}
#[test] #[test]
fn model_at_filters_by_search_and_returns_original_index() { fn model_at_filters_by_search_and_returns_original_index() {
let models = vec![ let models = vec![
@ -670,6 +684,27 @@ mod tests {
assert_eq!(visible_model_indices(&[entry], "百炼"), vec![0]); assert_eq!(visible_model_indices(&[entry], "百炼"), vec![0]);
} }
#[test]
fn builtin_search_does_not_match_api_key_badge_text() {
let builtin = ModelEntry::builtin(
AgentProvider::CodexCli,
"builtin-1",
"builtin:builtin-1:deepseek-v4-pro",
"deepseek-v4-pro",
);
let provider_model = entry(AgentProvider::CodexCli, "gpt-5.5");
assert_eq!(
visible_model_indices(&[builtin.clone()], "api key"),
Vec::<usize>::new()
);
assert_eq!(
visible_model_indices(&[builtin.clone()], "deepseek"),
vec![0]
);
assert_eq!(visible_model_indices(&[provider_model], "openai"), vec![0]);
}
#[test] #[test]
fn builtin_group_header_falls_back_to_generic_label_without_retained_name() { fn builtin_group_header_falls_back_to_generic_label_without_retained_name() {
let entry = ModelEntry::builtin( let entry = ModelEntry::builtin(