assistant2: Add context server list to configuration view (#27028)

This PR adds a context server list to the configuration view in
Assistant2:

<img width="1394" alt="Screenshot 2025-03-18 at 5 26 23 PM"
src="https://github.com/user-attachments/assets/58bf3920-1e35-4cb8-a32a-5ae9f98ce387"
/>

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2025-03-18 17:41:39 -04:00 committed by GitHub
parent 777c88bcea
commit 1d4afe6daa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 56 additions and 4 deletions

View file

@ -1,19 +1,25 @@
use std::sync::Arc; use std::sync::Arc;
use collections::HashMap; 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 language_model::{LanguageModelProvider, LanguageModelProviderId, LanguageModelRegistry};
use ui::{prelude::*, Divider, DividerColor, ElevationIndex}; use ui::{prelude::*, Divider, DividerColor, ElevationIndex, Indicator};
use zed_actions::assistant::DeployPromptLibrary; use zed_actions::assistant::DeployPromptLibrary;
pub struct AssistantConfiguration { pub struct AssistantConfiguration {
focus_handle: FocusHandle, focus_handle: FocusHandle,
configuration_views_by_provider: HashMap<LanguageModelProviderId, AnyView>, configuration_views_by_provider: HashMap<LanguageModelProviderId, AnyView>,
context_server_manager: Entity<ContextServerManager>,
_registry_subscription: Subscription, _registry_subscription: Subscription,
} }
impl AssistantConfiguration { impl AssistantConfiguration {
pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self { pub fn new(
context_server_manager: Entity<ContextServerManager>,
window: &mut Window,
cx: &mut Context<Self>,
) -> Self {
let focus_handle = cx.focus_handle(); let focus_handle = cx.focus_handle();
let registry_subscription = cx.subscribe_in( let registry_subscription = cx.subscribe_in(
@ -36,6 +42,7 @@ impl AssistantConfiguration {
let mut this = Self { let mut this = Self {
focus_handle, focus_handle,
configuration_views_by_provider: HashMap::default(), configuration_views_by_provider: HashMap::default(),
context_server_manager,
_registry_subscription: registry_subscription, _registry_subscription: registry_subscription,
}; };
this.build_provider_configuration_views(window, cx); this.build_provider_configuration_views(window, cx);
@ -143,6 +150,42 @@ impl AssistantConfiguration {
}), }),
) )
} }
fn render_context_servers_section(&mut self, cx: &mut Context<Self>) -> 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 { impl Render for AssistantConfiguration {
@ -182,6 +225,8 @@ impl Render for AssistantConfiguration {
), ),
) )
.child(Divider::horizontal().color(DividerColor::Border)) .child(Divider::horizontal().color(DividerColor::Border))
.child(self.render_context_servers_section(cx))
.child(Divider::horizontal().color(DividerColor::Border))
.child( .child(
v_flex() v_flex()
.p(DynamicSpacing::Base16.rems(cx)) .p(DynamicSpacing::Base16.rems(cx))

View file

@ -415,8 +415,11 @@ impl AssistantPanel {
} }
pub(crate) fn open_configuration(&mut self, window: &mut Window, cx: &mut Context<Self>) { pub(crate) fn open_configuration(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let context_server_manager = self.thread_store.read(cx).context_server_manager();
self.active_view = ActiveView::Configuration; 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() { if let Some(configuration) = self.configuration.as_ref() {
self.configuration_subscription = Some(cx.subscribe_in( self.configuration_subscription = Some(cx.subscribe_in(

View file

@ -65,6 +65,10 @@ impl ThreadStore {
Ok(this) Ok(this)
} }
pub fn context_server_manager(&self) -> Entity<ContextServerManager> {
self.context_server_manager.clone()
}
/// Returns the number of threads. /// Returns the number of threads.
pub fn thread_count(&self) -> usize { pub fn thread_count(&self) -> usize {
self.threads.len() self.threads.len()