mirror of
https://github.com/zed-industries/zed.git
synced 2026-06-01 03:14:56 +07:00
Show recommended models under normal category too (#42489)
<img width="395" height="444" alt="Screenshot 2025-11-11 at 4 04 57 PM" src="https://github.com/user-attachments/assets/8da68721-6e33-4d01-810d-4aa1e2f3402d" /> Discussed with @danilo-leal and we're going with the "it's checked in both places" design! Closes #40910 Release Notes: - Recommended AI models now still appear in their normal category in addition to "Recommended:"
This commit is contained in:
parent
2ad7ecbcf0
commit
cf6ae01d07
2 changed files with 34 additions and 52 deletions
|
|
@ -133,9 +133,7 @@ impl LanguageModels {
|
|||
for model in provider.provided_models(cx) {
|
||||
let model_info = Self::map_language_model_to_info(&model, &provider);
|
||||
let model_id = model_info.id.clone();
|
||||
if !recommended_models.contains(&(model.provider_id(), model.id())) {
|
||||
provider_models.push(model_info);
|
||||
}
|
||||
provider_models.push(model_info);
|
||||
models.insert(model_id, model);
|
||||
}
|
||||
if !provider_models.is_empty() {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use std::{cmp::Reverse, sync::Arc};
|
||||
|
||||
use collections::{HashSet, IndexMap};
|
||||
use collections::IndexMap;
|
||||
use fuzzy::{StringMatch, StringMatchCandidate, match_strings};
|
||||
use gpui::{Action, AnyElement, App, BackgroundExecutor, DismissEvent, Subscription, Task};
|
||||
use language_model::{
|
||||
|
|
@ -57,7 +57,7 @@ fn all_models(cx: &App) -> GroupedModels {
|
|||
})
|
||||
.collect();
|
||||
|
||||
let other = providers
|
||||
let all = providers
|
||||
.iter()
|
||||
.flat_map(|provider| {
|
||||
provider
|
||||
|
|
@ -70,7 +70,7 @@ fn all_models(cx: &App) -> GroupedModels {
|
|||
})
|
||||
.collect();
|
||||
|
||||
GroupedModels::new(other, recommended)
|
||||
GroupedModels::new(all, recommended)
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
@ -210,33 +210,24 @@ impl LanguageModelPickerDelegate {
|
|||
|
||||
struct GroupedModels {
|
||||
recommended: Vec<ModelInfo>,
|
||||
other: IndexMap<LanguageModelProviderId, Vec<ModelInfo>>,
|
||||
all: IndexMap<LanguageModelProviderId, Vec<ModelInfo>>,
|
||||
}
|
||||
|
||||
impl GroupedModels {
|
||||
pub fn new(other: Vec<ModelInfo>, recommended: Vec<ModelInfo>) -> Self {
|
||||
let recommended_ids = recommended
|
||||
.iter()
|
||||
.map(|info| (info.model.provider_id(), info.model.id()))
|
||||
.collect::<HashSet<_>>();
|
||||
|
||||
let mut other_by_provider: IndexMap<_, Vec<ModelInfo>> = IndexMap::default();
|
||||
for model in other {
|
||||
if recommended_ids.contains(&(model.model.provider_id(), model.model.id())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pub fn new(all: Vec<ModelInfo>, recommended: Vec<ModelInfo>) -> Self {
|
||||
let mut all_by_provider: IndexMap<_, Vec<ModelInfo>> = IndexMap::default();
|
||||
for model in all {
|
||||
let provider = model.model.provider_id();
|
||||
if let Some(models) = other_by_provider.get_mut(&provider) {
|
||||
if let Some(models) = all_by_provider.get_mut(&provider) {
|
||||
models.push(model);
|
||||
} else {
|
||||
other_by_provider.insert(provider, vec![model]);
|
||||
all_by_provider.insert(provider, vec![model]);
|
||||
}
|
||||
}
|
||||
|
||||
Self {
|
||||
recommended,
|
||||
other: other_by_provider,
|
||||
all: all_by_provider,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -252,7 +243,7 @@ impl GroupedModels {
|
|||
);
|
||||
}
|
||||
|
||||
for models in self.other.values() {
|
||||
for models in self.all.values() {
|
||||
if models.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -267,20 +258,6 @@ impl GroupedModels {
|
|||
}
|
||||
entries
|
||||
}
|
||||
|
||||
fn model_infos(&self) -> Vec<ModelInfo> {
|
||||
let other = self
|
||||
.other
|
||||
.values()
|
||||
.flat_map(|model| model.iter())
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
self.recommended
|
||||
.iter()
|
||||
.chain(&other)
|
||||
.cloned()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
|
||||
enum LanguageModelPickerEntry {
|
||||
|
|
@ -425,8 +402,9 @@ impl PickerDelegate for LanguageModelPickerDelegate {
|
|||
.collect::<Vec<_>>();
|
||||
|
||||
let available_models = all_models
|
||||
.model_infos()
|
||||
.iter()
|
||||
.all
|
||||
.values()
|
||||
.flat_map(|models| models.iter())
|
||||
.filter(|m| configured_provider_ids.contains(&m.model.provider_id()))
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
|
|
@ -764,46 +742,52 @@ mod tests {
|
|||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_exclude_recommended_models(_cx: &mut TestAppContext) {
|
||||
fn test_recommended_models_also_appear_in_other(_cx: &mut TestAppContext) {
|
||||
let recommended_models = create_models(vec![("zed", "claude")]);
|
||||
let all_models = create_models(vec![
|
||||
("zed", "claude"), // Should be filtered out from "other"
|
||||
("zed", "claude"), // Should also appear in "other"
|
||||
("zed", "gemini"),
|
||||
("copilot", "o3"),
|
||||
]);
|
||||
|
||||
let grouped_models = GroupedModels::new(all_models, recommended_models);
|
||||
|
||||
let actual_other_models = grouped_models
|
||||
.other
|
||||
let actual_all_models = grouped_models
|
||||
.all
|
||||
.values()
|
||||
.flatten()
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Recommended models should not appear in "other"
|
||||
assert_models_eq(actual_other_models, vec!["zed/gemini", "copilot/o3"]);
|
||||
// Recommended models should also appear in "all"
|
||||
assert_models_eq(
|
||||
actual_all_models,
|
||||
vec!["zed/claude", "zed/gemini", "copilot/o3"],
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_dont_exclude_models_from_other_providers(_cx: &mut TestAppContext) {
|
||||
fn test_models_from_different_providers(_cx: &mut TestAppContext) {
|
||||
let recommended_models = create_models(vec![("zed", "claude")]);
|
||||
let all_models = create_models(vec![
|
||||
("zed", "claude"), // Should be filtered out from "other"
|
||||
("zed", "claude"), // Should also appear in "other"
|
||||
("zed", "gemini"),
|
||||
("copilot", "claude"), // Should not be filtered out from "other"
|
||||
("copilot", "claude"), // Different provider, should appear in "other"
|
||||
]);
|
||||
|
||||
let grouped_models = GroupedModels::new(all_models, recommended_models);
|
||||
|
||||
let actual_other_models = grouped_models
|
||||
.other
|
||||
let actual_all_models = grouped_models
|
||||
.all
|
||||
.values()
|
||||
.flatten()
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Recommended models should not appear in "other"
|
||||
assert_models_eq(actual_other_models, vec!["zed/gemini", "copilot/claude"]);
|
||||
// All models should appear in "all" regardless of recommended status
|
||||
assert_models_eq(
|
||||
actual_all_models,
|
||||
vec!["zed/claude", "zed/gemini", "copilot/claude"],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue