1use std::sync::Arc;
2
3use anyhow::Result;
4use collections::HashMap;
5use context_server::ContextServerCommand;
6use extension::ContextServerConfiguration;
7use gpui::{App, AppContext as _, AsyncApp, Context, Entity, Global, Task};
8
9use crate::worktree_store::WorktreeStore;
10
11pub trait ContextServerDescriptor {
12 fn command(
13 &self,
14 worktree_store: Entity<WorktreeStore>,
15 cx: &AsyncApp,
16 ) -> Task<Result<ContextServerCommand>>;
17 fn configuration(
18 &self,
19 worktree_store: Entity<WorktreeStore>,
20 cx: &AsyncApp,
21 ) -> Task<Result<Option<ContextServerConfiguration>>>;
22}
23
24struct GlobalContextServerDescriptorRegistry(Entity<ContextServerDescriptorRegistry>);
25
26impl Global for GlobalContextServerDescriptorRegistry {}
27
28#[derive(Default)]
29pub struct ContextServerDescriptorRegistry {
30 context_servers: HashMap<Arc<str>, Arc<dyn ContextServerDescriptor>>,
31}
32
33impl ContextServerDescriptorRegistry {
34 /// Returns the global [`ContextServerDescriptorRegistry`].
35 ///
36 /// Inserts a default [`ContextServerDescriptorRegistry`] if one does not yet exist.
37 pub fn default_global(cx: &mut App) -> Entity<Self> {
38 if !cx.has_global::<GlobalContextServerDescriptorRegistry>() {
39 let registry = cx.new(|_| Self::new());
40 cx.set_global(GlobalContextServerDescriptorRegistry(registry));
41 }
42 cx.global::<GlobalContextServerDescriptorRegistry>()
43 .0
44 .clone()
45 }
46
47 pub fn new() -> Self {
48 Self {
49 context_servers: HashMap::default(),
50 }
51 }
52
53 pub fn context_server_descriptors(&self) -> Vec<(Arc<str>, Arc<dyn ContextServerDescriptor>)> {
54 self.context_servers
55 .iter()
56 .map(|(id, factory)| (id.clone(), factory.clone()))
57 .collect()
58 }
59
60 pub fn context_server_descriptor(&self, id: &str) -> Option<Arc<dyn ContextServerDescriptor>> {
61 self.context_servers.get(id).cloned()
62 }
63
64 /// Registers the provided [`ContextServerDescriptor`].
65 pub fn register_context_server_descriptor(
66 &mut self,
67 id: Arc<str>,
68 descriptor: Arc<dyn ContextServerDescriptor>,
69 cx: &mut Context<Self>,
70 ) {
71 self.context_servers.insert(id, descriptor);
72 cx.notify();
73 }
74
75 /// Unregisters the [`ContextServerDescriptor`] for the server with the given ID.
76 pub fn unregister_context_server_descriptor_by_id(
77 &mut self,
78 server_id: &str,
79 cx: &mut Context<Self>,
80 ) {
81 self.context_servers.remove(server_id);
82 cx.notify();
83 }
84}