1use assistant_settings::AssistantSettings;
2use fs::Fs;
3use gpui::{Entity, FocusHandle, SharedString};
4use language_model::LanguageModelRegistry;
5use language_model_selector::{
6 LanguageModelSelector, LanguageModelSelectorPopoverMenu, ToggleModelSelector,
7};
8use settings::update_settings_file;
9use std::sync::Arc;
10use ui::{ButtonLike, PopoverMenuHandle, Tooltip, prelude::*};
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 pub fn toggle(&self, window: &mut Window, cx: &mut Context<Self>) {
47 self.menu_handle.toggle(window, cx);
48 }
49}
50
51impl Render for AssistantModelSelector {
52 fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
53 let active_model = LanguageModelRegistry::read_global(cx).active_model();
54 let focus_handle = self.focus_handle.clone();
55 let model_name = match active_model {
56 Some(model) => model.name().0,
57 _ => SharedString::from("No model selected"),
58 };
59
60 LanguageModelSelectorPopoverMenu::new(
61 self.selector.clone(),
62 ButtonLike::new("active-model")
63 .style(ButtonStyle::Subtle)
64 .child(
65 h_flex()
66 .gap_0p5()
67 .child(
68 Label::new(model_name)
69 .size(LabelSize::Small)
70 .color(Color::Muted),
71 )
72 .child(
73 Icon::new(IconName::ChevronDown)
74 .color(Color::Muted)
75 .size(IconSize::XSmall),
76 ),
77 ),
78 move |window, cx| {
79 Tooltip::for_action_in(
80 "Change Model",
81 &ToggleModelSelector,
82 &focus_handle,
83 window,
84 cx,
85 )
86 },
87 gpui::Corner::BottomRight,
88 )
89 .with_handle(self.menu_handle.clone())
90 }
91}