1use std::sync::Arc;
2
3use context_server::ContextServerId;
4use extension::ExtensionManifest;
5use fs::Fs;
6use gpui::WeakEntity;
7use language::LanguageRegistry;
8use settings::update_settings_file;
9use ui::prelude::*;
10use util::ResultExt;
11use workspace::Workspace;
12
13use crate::agent_configuration::ConfigureContextServerModal;
14
15pub(crate) fn init(language_registry: Arc<LanguageRegistry>, fs: Arc<dyn Fs>, cx: &mut App) {
16 cx.observe_new(move |_: &mut Workspace, window, cx| {
17 let Some(window) = window else {
18 return;
19 };
20
21 if let Some(extension_events) = extension::ExtensionEvents::try_global(cx).as_ref() {
22 cx.subscribe_in(extension_events, window, {
23 let language_registry = language_registry.clone();
24 let fs = fs.clone();
25 move |_, _, event, window, cx| match event {
26 extension::Event::ExtensionInstalled(manifest) => {
27 show_configure_mcp_modal(
28 language_registry.clone(),
29 manifest,
30 cx.weak_entity(),
31 window,
32 cx,
33 );
34 }
35 extension::Event::ExtensionUninstalled(manifest) => {
36 remove_context_server_settings(
37 manifest.context_servers.keys().cloned().collect(),
38 fs.clone(),
39 cx,
40 );
41 }
42 extension::Event::ConfigureExtensionRequested(manifest) => {
43 if !manifest.context_servers.is_empty() {
44 show_configure_mcp_modal(
45 language_registry.clone(),
46 manifest,
47 cx.weak_entity(),
48 window,
49 cx,
50 );
51 }
52 }
53 _ => {}
54 }
55 })
56 .detach();
57 } else {
58 log::info!(
59 "No extension events global found. Skipping context server configuration wizard"
60 );
61 }
62 })
63 .detach();
64}
65
66fn remove_context_server_settings(
67 context_server_ids: Vec<Arc<str>>,
68 fs: Arc<dyn Fs>,
69 cx: &mut App,
70) {
71 update_settings_file(fs, cx, move |settings, _| {
72 settings
73 .project
74 .context_servers
75 .retain(|server_id, _| !context_server_ids.contains(server_id));
76 });
77}
78
79fn show_configure_mcp_modal(
80 language_registry: Arc<LanguageRegistry>,
81 manifest: &Arc<ExtensionManifest>,
82 workspace: WeakEntity<Workspace>,
83 window: &mut Window,
84 cx: &mut Context<'_, Workspace>,
85) {
86 if !window.is_window_active() {
87 return;
88 }
89
90 let ids = manifest.context_servers.keys().cloned().collect::<Vec<_>>();
91 if ids.is_empty() {
92 return;
93 }
94
95 window
96 .spawn(cx, async move |cx| {
97 for id in ids {
98 let Some(task) = cx
99 .update(|window, cx| {
100 ConfigureContextServerModal::show_modal_for_existing_server(
101 ContextServerId(id.clone()),
102 language_registry.clone(),
103 workspace.clone(),
104 window,
105 cx,
106 )
107 })
108 .ok()
109 else {
110 continue;
111 };
112 task.await.log_err();
113 }
114 })
115 .detach();
116}