1use assistant_settings::AssistantSettings;
2use fs::Fs;
3use gpui::{Entity, FocusHandle, SharedString};
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 let model_name = match active_model {
52 Some(model) => model.name().0,
53 _ => SharedString::from("No model selected"),
54 };
55
56 LanguageModelSelectorPopoverMenu::new(
57 self.selector.clone(),
58 ButtonLike::new("active-model")
59 .style(ButtonStyle::Subtle)
60 .child(
61 h_flex()
62 .gap_0p5()
63 .child(
64 div().max_w_32().child(
65 Label::new(model_name)
66 .size(LabelSize::Small)
67 .color(Color::Muted)
68 .text_ellipsis()
69 .into_any_element(),
70 ),
71 )
72 .child(
73 Icon::new(IconName::ChevronDown)
74 .color(Color::Muted)
75 .size(IconSize::XSmall),
76 ),
77 )
78 .tooltip(move |window, cx| {
79 Tooltip::for_action_in(
80 "Change Model",
81 &ToggleModelSelector,
82 &focus_handle,
83 window,
84 cx,
85 )
86 }),
87 )
88 .with_handle(self.menu_handle.clone())
89 }
90}