144 lines · 5.0 KB · Rust
RawDownload
use crate::{    ModelUsageContext,    language_model_selector::{LanguageModelSelector, language_model_selector},    ui::ModelSelectorTooltip,};use fs::Fs;use gpui::{Entity, FocusHandle, SharedString};use language_model::IconOrSvg;use picker::popover_menu::PickerPopoverMenu;use settings::update_settings_file;use std::sync::Arc;use ui::{PopoverMenuHandle, Tooltip, prelude::*}; pub struct AgentModelSelector {    selector: Entity<LanguageModelSelector>,    menu_handle: PopoverMenuHandle<LanguageModelSelector>,} impl AgentModelSelector {    pub(crate) fn new(        fs: Arc<dyn Fs>,        menu_handle: PopoverMenuHandle<LanguageModelSelector>,        focus_handle: FocusHandle,        model_usage_context: ModelUsageContext,        window: &mut Window,        cx: &mut Context<Self>,    ) -> Self {        Self {            selector: cx.new(move |cx| {                language_model_selector(                    {                        let model_context = model_usage_context.clone();                        move |cx| model_context.configured_model(cx)                    },                    {                        let fs = fs.clone();                        move |model, cx| {                            let provider = model.provider_id().0.to_string();                            let model_id = model.id().0.to_string();                            match &model_usage_context {                                ModelUsageContext::InlineAssistant => {                                    update_settings_file(fs.clone(), cx, move |settings, _cx| {                                        settings                                            .agent                                            .get_or_insert_default()                                            .set_inline_assistant_model(provider.clone(), model_id);                                    });                                }                            }                        }                    },                    {                        let fs = fs.clone();                        move |model, should_be_favorite, cx| {                            crate::favorite_models::toggle_in_settings(                                model,                                should_be_favorite,                                fs.clone(),                                cx,                            );                        }                    },                    true, // Use popover styles for picker                    focus_handle.clone(),                    window,                    cx,                )            }),            menu_handle,        }    }     pub fn toggle(&self, window: &mut Window, cx: &mut Context<Self>) {        self.menu_handle.toggle(window, cx);    }     pub fn active_model(&self, cx: &App) -> Option<language_model::ConfiguredModel> {        self.selector.read(cx).delegate.active_model(cx)    }     pub fn cycle_favorite_models(&self, window: &mut Window, cx: &mut Context<Self>) {        self.selector.update(cx, |selector, cx| {            selector.delegate.cycle_favorite_models(window, cx);        });    }} impl Render for AgentModelSelector {    fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> 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 color = if self.menu_handle.is_deployed() {            Color::Accent        } else {            Color::Muted        };         let show_cycle_row = self.selector.read(cx).delegate.favorites_count() > 1;         let tooltip = Tooltip::element({            move |_, _cx| {                ModelSelectorTooltip::new()                    .show_cycle_row(show_cycle_row)                    .into_any_element()            }        });         PickerPopoverMenu::new(            self.selector.clone(),            Button::new("active-model", model_name)                .label_size(LabelSize::Small)                .color(color)                .when_some(provider_icon, |this, icon| {                    this.start_icon(                        match icon {                            IconOrSvg::Svg(path) => Icon::from_external_svg(path),                            IconOrSvg::Icon(name) => Icon::new(name),                        }                        .color(color)                        .size(IconSize::XSmall),                    )                })                .end_icon(                    Icon::new(IconName::ChevronDown)                        .color(color)                        .size(IconSize::XSmall),                ),            tooltip,            gpui::Corner::TopRight,            cx,        )        .with_handle(self.menu_handle.clone())        .offset(gpui::Point {            x: px(0.0),            y: px(2.0),        })        .render(window, cx)    }}