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() {
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                    .child(
53                        h_flex()
54                            .w_full()
55                            .gap_0p5()
56                            .child(
57                                div()
58                                    .overflow_x_hidden()
59                                    .flex_grow()
60                                    .whitespace_nowrap()
61                                    .child(
62                                        Label::new(
63                                            CompletionProvider::global(cx).model().display_name(),
64                                        )
65                                        .size(LabelSize::Small)
66                                        .color(Color::Muted),
67                                    ),
68                            )
69                            .child(
70                                div().child(
71                                    Icon::new(IconName::ChevronDown)
72                                        .color(Color::Muted)
73                                        .size(IconSize::XSmall),
74                                ),
75                            ),
76                    )
77                    .style(ButtonStyle::Subtle)
78                    .tooltip(move |cx| {
79                        Tooltip::for_action("Change Model", &ToggleModelSelector, cx)
80                    }),
81            )
82            .anchor(gpui::AnchorCorner::BottomRight)
83    }
84}