use crate::{ ModelUsageContext, language_model_selector::{LanguageModelSelector, language_model_selector}, }; use agent_settings::AgentSettings; use fs::Fs; use gpui::{Entity, FocusHandle, SharedString}; use language_model::{ConfiguredModel, LanguageModelRegistry}; use picker::popover_menu::PickerPopoverMenu; use settings::update_settings_file; use std::sync::Arc; use ui::{ButtonLike, PopoverMenuHandle, Tooltip, prelude::*}; use zed_actions::agent::ToggleModelSelector; pub struct AgentModelSelector { selector: Entity, menu_handle: PopoverMenuHandle, focus_handle: FocusHandle, } impl AgentModelSelector { pub(crate) fn new( fs: Arc, menu_handle: PopoverMenuHandle, focus_handle: FocusHandle, model_usage_context: ModelUsageContext, window: &mut Window, cx: &mut Context, ) -> Self { Self { selector: cx.new(move |cx| { let fs = fs.clone(); language_model_selector( { let model_context = model_usage_context.clone(); move |cx| model_context.configured_model(cx) }, move |model, cx| { let provider = model.provider_id().0.to_string(); let model_id = model.id().0.to_string(); match &model_usage_context { ModelUsageContext::Thread(thread) => { thread.update(cx, |thread, cx| { let registry = LanguageModelRegistry::read_global(cx); if let Some(provider) = registry.provider(&model.provider_id()) { thread.set_configured_model( Some(ConfiguredModel { provider, model: model.clone(), }), cx, ); } }); update_settings_file::( fs.clone(), cx, move |settings, _cx| { settings.set_model(model.clone()); }, ); } ModelUsageContext::InlineAssistant => { update_settings_file::( fs.clone(), cx, move |settings, _cx| { settings.set_inline_assistant_model( provider.clone(), model_id.clone(), ); }, ); } } }, window, cx, ) }), menu_handle, focus_handle, } } pub fn toggle(&self, window: &mut Window, cx: &mut Context) { self.menu_handle.toggle(window, cx); } } impl Render for AgentModelSelector { fn render(&mut self, window: &mut Window, cx: &mut Context) -> impl IntoElement { let model = self.selector.read(cx).delegate.active_model(cx); let model_name = model .as_ref() .map(|model| model.model.name().0) .unwrap_or_else(|| SharedString::from("Select a Model")); let provider_icon = model.as_ref().map(|model| model.provider.icon()); let focus_handle = self.focus_handle.clone(); PickerPopoverMenu::new( self.selector.clone(), ButtonLike::new("active-model") .when_some(provider_icon, |this, icon| { this.child(Icon::new(icon).color(Color::Muted).size(IconSize::XSmall)) }) .child( Label::new(model_name) .color(Color::Muted) .size(LabelSize::Small) .ml_0p5(), ) .child( Icon::new(IconName::ChevronDown) .color(Color::Muted) .size(IconSize::XSmall), ), move |window, cx| { Tooltip::for_action_in( "Change Model", &ToggleModelSelector, &focus_handle, window, cx, ) }, gpui::Corner::BottomRight, cx, ) .with_handle(self.menu_handle.clone()) .render(window, cx) } }