extension_context_server.rs

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