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 Label::new(model_name)
65 .size(LabelSize::Small)
66 .color(Color::Muted),
67 )
68 .child(
69 Icon::new(IconName::ChevronDown)
70 .color(Color::Muted)
71 .size(IconSize::XSmall),
72 ),
73 ),
74 move |window, cx| {
75 Tooltip::for_action_in(
76 "Change Model",
77 &ToggleModelSelector,
78 &focus_handle,
79 window,
80 cx,
81 )
82 },
83 gpui::Corner::BottomRight,
84 )
85 .with_handle(self.menu_handle.clone())
86 }
87}