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