extension_context_server.rs

 1use std::pin::Pin;
 2use std::sync::Arc;
 3
 4use anyhow::{anyhow, Result};
 5use async_trait::async_trait;
 6use context_servers::manager::{NativeContextServer, ServerCommand, ServerConfig};
 7use context_servers::protocol::InitializedContextServerProtocol;
 8use context_servers::ContextServer;
 9use extension_host::wasm_host::{ExtensionProject, WasmExtension, WasmHost};
10use futures::{Future, FutureExt};
11use gpui::{AsyncAppContext, Model};
12use project::Project;
13use wasmtime_wasi::WasiView as _;
14
15pub struct ExtensionContextServer {
16    #[allow(unused)]
17    pub(crate) extension: WasmExtension,
18    #[allow(unused)]
19    pub(crate) host: Arc<WasmHost>,
20    id: Arc<str>,
21    context_server: Arc<NativeContextServer>,
22}
23
24impl ExtensionContextServer {
25    pub async fn new(
26        extension: WasmExtension,
27        host: Arc<WasmHost>,
28        id: Arc<str>,
29        project: Model<Project>,
30        mut cx: AsyncAppContext,
31    ) -> Result<Self> {
32        let extension_project = project.update(&mut cx, |project, cx| ExtensionProject {
33            worktree_ids: project
34                .visible_worktrees(cx)
35                .map(|worktree| worktree.read(cx).id().to_proto())
36                .collect(),
37        })?;
38        let command = extension
39            .call({
40                let id = id.clone();
41                |extension, store| {
42                    async move {
43                        let project = store.data_mut().table().push(extension_project)?;
44                        let command = extension
45                            .call_context_server_command(store, id.clone(), project)
46                            .await?
47                            .map_err(|e| anyhow!("{}", e))?;
48                        anyhow::Ok(command)
49                    }
50                    .boxed()
51                }
52            })
53            .await?;
54
55        let config = Arc::new(ServerConfig {
56            settings: None,
57            command: Some(ServerCommand {
58                path: command.command,
59                args: command.args,
60                env: Some(command.env.into_iter().collect()),
61            }),
62        });
63
64        anyhow::Ok(Self {
65            extension,
66            host,
67            id: id.clone(),
68            context_server: Arc::new(NativeContextServer::new(id, config)),
69        })
70    }
71}
72
73#[async_trait(?Send)]
74impl ContextServer for ExtensionContextServer {
75    fn id(&self) -> Arc<str> {
76        self.id.clone()
77    }
78
79    fn config(&self) -> Arc<ServerConfig> {
80        self.context_server.config()
81    }
82
83    fn client(&self) -> Option<Arc<InitializedContextServerProtocol>> {
84        self.context_server.client()
85    }
86
87    fn start<'a>(
88        self: Arc<Self>,
89        cx: &'a AsyncAppContext,
90    ) -> Pin<Box<dyn 'a + Future<Output = Result<()>>>> {
91        self.context_server.clone().start(cx)
92    }
93
94    fn stop(&self) -> Result<()> {
95        self.context_server.stop()
96    }
97}