assistant_model_selector.rs

 1use assistant_settings::AssistantSettings;
 2use fs::Fs;
 3use gpui::{Entity, FocusHandle};
 4use language_model::LanguageModelRegistry;
 5use language_model_selector::{LanguageModelSelector, LanguageModelSelectorPopoverMenu};
 6use settings::update_settings_file;
 7use std::sync::Arc;
 8use ui::{prelude::*, ButtonLike, PopoverMenuHandle, Tooltip};
 9
10use crate::ToggleModelSelector;
11
12pub struct AssistantModelSelector {
13    selector: Entity<LanguageModelSelector>,
14    menu_handle: PopoverMenuHandle<LanguageModelSelector>,
15    focus_handle: FocusHandle,
16}
17
18impl AssistantModelSelector {
19    pub(crate) fn new(
20        fs: Arc<dyn Fs>,
21        menu_handle: PopoverMenuHandle<LanguageModelSelector>,
22        focus_handle: FocusHandle,
23        window: &mut Window,
24        cx: &mut App,
25    ) -> Self {
26        Self {
27            selector: cx.new(|cx| {
28                let fs = fs.clone();
29                LanguageModelSelector::new(
30                    move |model, cx| {
31                        update_settings_file::<AssistantSettings>(
32                            fs.clone(),
33                            cx,
34                            move |settings, _cx| settings.set_model(model.clone()),
35                        );
36                    },
37                    window,
38                    cx,
39                )
40            }),
41            menu_handle,
42            focus_handle,
43        }
44    }
45}
46
47impl Render for AssistantModelSelector {
48    fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
49        let active_model = LanguageModelRegistry::read_global(cx).active_model();
50        let focus_handle = self.focus_handle.clone();
51
52        LanguageModelSelectorPopoverMenu::new(
53            self.selector.clone(),
54            ButtonLike::new("active-model")
55                .style(ButtonStyle::Subtle)
56                .child(
57                    h_flex()
58                        .gap_0p5()
59                        .child(
60                            div()
61                                .overflow_x_hidden()
62                                .flex_grow()
63                                .whitespace_nowrap()
64                                .child(match active_model {
65                                    Some(model) => h_flex()
66                                        .child(
67                                            Label::new(model.name().0)
68                                                .size(LabelSize::Small)
69                                                .color(Color::Muted),
70                                        )
71                                        .into_any_element(),
72                                    _ => Label::new("No model selected")
73                                        .size(LabelSize::Small)
74                                        .color(Color::Muted)
75                                        .into_any_element(),
76                                }),
77                        )
78                        .child(
79                            Icon::new(IconName::ChevronDown)
80                                .color(Color::Muted)
81                                .size(IconSize::XSmall),
82                        ),
83                )
84                .tooltip(move |window, cx| {
85                    Tooltip::for_action_in(
86                        "Change Model",
87                        &ToggleModelSelector,
88                        &focus_handle,
89                        window,
90                        cx,
91                    )
92                }),
93        )
94        .with_handle(self.menu_handle.clone())
95    }
96}