model_selector.rs

 1use std::sync::Arc;
 2
 3use crate::{assistant_settings::AssistantSettings, CompletionProvider, ToggleModelSelector};
 4use fs::Fs;
 5use settings::update_settings_file;
 6use ui::{prelude::*, ButtonLike, ContextMenu, PopoverMenu, PopoverMenuHandle, Tooltip};
 7
 8#[derive(IntoElement)]
 9pub struct ModelSelector {
10    handle: PopoverMenuHandle<ContextMenu>,
11    fs: Arc<dyn Fs>,
12}
13
14impl ModelSelector {
15    pub fn new(handle: PopoverMenuHandle<ContextMenu>, fs: Arc<dyn Fs>) -> Self {
16        ModelSelector { handle, fs }
17    }
18}
19
20impl RenderOnce for ModelSelector {
21    fn render(self, cx: &mut WindowContext) -> impl IntoElement {
22        PopoverMenu::new("model-switcher")
23            .with_handle(self.handle)
24            .menu(move |cx| {
25                ContextMenu::build(cx, |mut menu, cx| {
26                    for model in CompletionProvider::global(cx).available_models(cx) {
27                        menu = menu.custom_entry(
28                            {
29                                let model = model.clone();
30                                move |_| Label::new(model.display_name()).into_any_element()
31                            },
32                            {
33                                let fs = self.fs.clone();
34                                let model = model.clone();
35                                move |cx| {
36                                    let model = model.clone();
37                                    update_settings_file::<AssistantSettings>(
38                                        fs.clone(),
39                                        cx,
40                                        move |settings| settings.set_model(model),
41                                    );
42                                }
43                            },
44                        );
45                    }
46                    menu
47                })
48                .into()
49            })
50            .trigger(
51                ButtonLike::new("active-model")
52                    .style(ButtonStyle::Subtle)
53                    .child(
54                        h_flex()
55                            .w_full()
56                            .gap_0p5()
57                            .child(
58                                div()
59                                    .overflow_x_hidden()
60                                    .flex_grow()
61                                    .whitespace_nowrap()
62                                    .child(
63                                        Label::new(
64                                            CompletionProvider::global(cx).model().display_name(),
65                                        )
66                                        .size(LabelSize::Small)
67                                        .color(Color::Muted),
68                                    ),
69                            )
70                            .child(
71                                Icon::new(IconName::ChevronDown)
72                                    .color(Color::Muted)
73                                    .size(IconSize::XSmall),
74                            ),
75                    )
76                    .tooltip(move |cx| {
77                        Tooltip::for_action("Change Model", &ToggleModelSelector, cx)
78                    }),
79            )
80            .attach(gpui::AnchorCorner::BottomLeft)
81    }
82}