extension_context_server.rs

 1use std::sync::Arc;
 2
 3use extension::{Extension, ExtensionContextServerProxy, ExtensionHostProxy, ProjectDelegate};
 4use gpui::{AppContext, Model};
 5
 6use crate::manager::ServerCommand;
 7use crate::ContextServerFactoryRegistry;
 8
 9struct ExtensionProject {
10    worktree_ids: Vec<u64>,
11}
12
13impl ProjectDelegate for ExtensionProject {
14    fn worktree_ids(&self) -> Vec<u64> {
15        self.worktree_ids.clone()
16    }
17}
18
19pub fn init(cx: &mut AppContext) {
20    let proxy = ExtensionHostProxy::default_global(cx);
21    proxy.register_context_server_proxy(ContextServerFactoryRegistryProxy {
22        context_server_factory_registry: ContextServerFactoryRegistry::global(cx),
23    });
24}
25
26struct ContextServerFactoryRegistryProxy {
27    context_server_factory_registry: Model<ContextServerFactoryRegistry>,
28}
29
30impl ExtensionContextServerProxy for ContextServerFactoryRegistryProxy {
31    fn register_context_server(
32        &self,
33        extension: Arc<dyn Extension>,
34        id: Arc<str>,
35        cx: &mut AppContext,
36    ) {
37        self.context_server_factory_registry
38            .update(cx, |registry, _| {
39                registry.register_server_factory(
40                    id.clone(),
41                    Arc::new({
42                        move |project, cx| {
43                            log::info!(
44                                "loading command for context server {id} from extension {}",
45                                extension.manifest().id
46                            );
47
48                            let id = id.clone();
49                            let extension = extension.clone();
50                            cx.spawn(|mut cx| async move {
51                                let extension_project =
52                                    project.update(&mut cx, |project, cx| {
53                                        Arc::new(ExtensionProject {
54                                            worktree_ids: project
55                                                .visible_worktrees(cx)
56                                                .map(|worktree| worktree.read(cx).id().to_proto())
57                                                .collect(),
58                                        })
59                                    })?;
60
61                                let command = extension
62                                    .context_server_command(id.clone(), extension_project)
63                                    .await?;
64
65                                log::info!("loaded command for context server {id}: {command:?}");
66
67                                Ok(ServerCommand {
68                                    path: command.command,
69                                    args: command.args,
70                                    env: Some(command.env.into_iter().collect()),
71                                })
72                            })
73                        }
74                    }),
75                )
76            });
77    }
78}