diff --git a/crates/assistant2/src/assistant_configuration.rs b/crates/assistant2/src/assistant_configuration.rs index 8e906ad66d16190a2d05ad15e7ac66947b766916..49c299940bc1575e4eb9d9e2776cb51a13b61003 100644 --- a/crates/assistant2/src/assistant_configuration.rs +++ b/crates/assistant2/src/assistant_configuration.rs @@ -1,19 +1,25 @@ use std::sync::Arc; use collections::HashMap; -use gpui::{Action, AnyView, App, EventEmitter, FocusHandle, Focusable, Subscription}; +use context_server::manager::ContextServerManager; +use gpui::{Action, AnyView, App, Entity, EventEmitter, FocusHandle, Focusable, Subscription}; use language_model::{LanguageModelProvider, LanguageModelProviderId, LanguageModelRegistry}; -use ui::{prelude::*, Divider, DividerColor, ElevationIndex}; +use ui::{prelude::*, Divider, DividerColor, ElevationIndex, Indicator}; use zed_actions::assistant::DeployPromptLibrary; pub struct AssistantConfiguration { focus_handle: FocusHandle, configuration_views_by_provider: HashMap, + context_server_manager: Entity, _registry_subscription: Subscription, } impl AssistantConfiguration { - pub fn new(window: &mut Window, cx: &mut Context) -> Self { + pub fn new( + context_server_manager: Entity, + window: &mut Window, + cx: &mut Context, + ) -> Self { let focus_handle = cx.focus_handle(); let registry_subscription = cx.subscribe_in( @@ -36,6 +42,7 @@ impl AssistantConfiguration { let mut this = Self { focus_handle, configuration_views_by_provider: HashMap::default(), + context_server_manager, _registry_subscription: registry_subscription, }; this.build_provider_configuration_views(window, cx); @@ -143,6 +150,42 @@ impl AssistantConfiguration { }), ) } + + fn render_context_servers_section(&mut self, cx: &mut Context) -> impl IntoElement { + let context_servers = self.context_server_manager.read(cx).servers().clone(); + + const SUBHEADING: &str = "Connect to context servers via the Model Context Protocol either via Zed extensions or directly."; + + v_flex() + .p(DynamicSpacing::Base16.rems(cx)) + .mt_1() + .gap_6() + .flex_1() + .child( + v_flex() + .gap_0p5() + .child(Headline::new("Context Servers (MCP)").size(HeadlineSize::Small)) + .child(Label::new(SUBHEADING).color(Color::Muted)), + ) + .children(context_servers.into_iter().map(|context_server| { + let is_running = context_server.client().is_some(); + + h_flex() + .gap_2() + .px_2() + .py_1() + .border_1() + .rounded_sm() + .border_color(cx.theme().colors().border) + .bg(cx.theme().colors().editor_background) + .child(Indicator::dot().color(if is_running { + Color::Success + } else { + Color::Error + })) + .child(Label::new(context_server.id())) + })) + } } impl Render for AssistantConfiguration { @@ -182,6 +225,8 @@ impl Render for AssistantConfiguration { ), ) .child(Divider::horizontal().color(DividerColor::Border)) + .child(self.render_context_servers_section(cx)) + .child(Divider::horizontal().color(DividerColor::Border)) .child( v_flex() .p(DynamicSpacing::Base16.rems(cx)) diff --git a/crates/assistant2/src/assistant_panel.rs b/crates/assistant2/src/assistant_panel.rs index cb73bfe09ca964064eceb592fd6e46cda5bc6bad..6422cf4190016facd0cd355d9b4b518e7ec0a929 100644 --- a/crates/assistant2/src/assistant_panel.rs +++ b/crates/assistant2/src/assistant_panel.rs @@ -415,8 +415,11 @@ impl AssistantPanel { } pub(crate) fn open_configuration(&mut self, window: &mut Window, cx: &mut Context) { + let context_server_manager = self.thread_store.read(cx).context_server_manager(); + self.active_view = ActiveView::Configuration; - self.configuration = Some(cx.new(|cx| AssistantConfiguration::new(window, cx))); + self.configuration = + Some(cx.new(|cx| AssistantConfiguration::new(context_server_manager, window, cx))); if let Some(configuration) = self.configuration.as_ref() { self.configuration_subscription = Some(cx.subscribe_in( diff --git a/crates/assistant2/src/thread_store.rs b/crates/assistant2/src/thread_store.rs index 66657a500d55921df06b0f4381b8cd18d007f718..1d0e17e4327bdd5cd8c792cd26fb0733fcdffb0b 100644 --- a/crates/assistant2/src/thread_store.rs +++ b/crates/assistant2/src/thread_store.rs @@ -65,6 +65,10 @@ impl ThreadStore { Ok(this) } + pub fn context_server_manager(&self) -> Entity { + self.context_server_manager.clone() + } + /// Returns the number of threads. pub fn thread_count(&self) -> usize { self.threads.len()