1use crate::{Result, VxPackageManager, VxPlugin, VxTool};
7use std::collections::HashMap;
8use std::sync::{Arc, RwLock};
9
10#[derive(Default)]
18pub struct PluginRegistry {
19 plugins: Arc<RwLock<HashMap<String, Box<dyn VxPlugin>>>>,
21 tool_index: Arc<RwLock<HashMap<String, String>>>,
23 pm_index: Arc<RwLock<HashMap<String, String>>>,
25}
26
27impl PluginRegistry {
28 pub fn new() -> Self {
30 Self::default()
31 }
32
33 pub async fn register_plugin(&self, mut plugin: Box<dyn VxPlugin>) -> Result<()> {
38 let plugin_name = plugin.name().to_string();
39
40 plugin.initialize().await?;
42
43 {
45 let mut tool_index = self.tool_index.write().unwrap();
46 for tool in plugin.tools() {
47 tool_index.insert(tool.name().to_string(), plugin_name.clone());
48 for alias in tool.aliases() {
50 tool_index.insert(alias.to_string(), plugin_name.clone());
51 }
52 }
53 }
54
55 {
57 let mut pm_index = self.pm_index.write().unwrap();
58 for pm in plugin.package_managers() {
59 pm_index.insert(pm.name().to_string(), plugin_name.clone());
60 }
61 }
62
63 {
65 let mut plugins = self.plugins.write().unwrap();
66 plugins.insert(plugin_name, plugin);
67 }
68
69 Ok(())
70 }
71 pub async fn unregister_plugin(&self, plugin_name: &str) -> Result<()> {
75 let mut plugin = {
77 let mut plugins = self.plugins.write().unwrap();
78 plugins.remove(plugin_name)
79 };
80
81 if let Some(ref mut plugin) = plugin {
82 plugin.shutdown().await?;
84
85 {
87 let mut tool_index = self.tool_index.write().unwrap();
88 tool_index.retain(|_, p_name| p_name != plugin_name);
89 }
90
91 {
93 let mut pm_index = self.pm_index.write().unwrap();
94 pm_index.retain(|_, p_name| p_name != plugin_name);
95 }
96 }
97
98 Ok(())
99 }
100
101 pub fn get_tool(&self, tool_name: &str) -> Option<Box<dyn VxTool>> {
105 let tool_index = self.tool_index.read().unwrap();
106 let plugins = self.plugins.read().unwrap();
107
108 if let Some(plugin_name) = tool_index.get(tool_name) {
109 if let Some(plugin) = plugins.get(plugin_name) {
110 return plugin
111 .tools()
112 .into_iter()
113 .find(|tool| tool.name() == tool_name || tool.aliases().contains(&tool_name));
114 }
115 }
116
117 None
118 }
119
120 pub fn get_package_manager(&self, pm_name: &str) -> Option<Box<dyn VxPackageManager>> {
124 let pm_index = self.pm_index.read().unwrap();
125 let plugins = self.plugins.read().unwrap();
126
127 if let Some(plugin_name) = pm_index.get(pm_name) {
128 if let Some(plugin) = plugins.get(plugin_name) {
129 return plugin
130 .package_managers()
131 .into_iter()
132 .find(|pm| pm.name() == pm_name);
133 }
134 }
135
136 None
137 }
138 pub fn list_plugins(&self) -> Vec<String> {
142 let plugins = self.plugins.read().unwrap();
143 plugins.keys().cloned().collect()
144 }
145
146 pub fn list_tools(&self) -> Vec<String> {
150 let tool_index = self.tool_index.read().unwrap();
151 tool_index.keys().cloned().collect()
152 }
153
154 pub fn list_package_managers(&self) -> Vec<String> {
158 let pm_index = self.pm_index.read().unwrap();
159 pm_index.keys().cloned().collect()
160 }
161
162 pub fn has_tool(&self, tool_name: &str) -> bool {
166 let tool_index = self.tool_index.read().unwrap();
167 tool_index.contains_key(tool_name)
168 }
169
170 pub fn has_package_manager(&self, pm_name: &str) -> bool {
174 let pm_index = self.pm_index.read().unwrap();
175 pm_index.contains_key(pm_name)
176 }
177
178 pub fn get_plugin_info(&self, plugin_name: &str) -> Option<HashMap<String, String>> {
182 let plugins = self.plugins.read().unwrap();
183 plugins.get(plugin_name).map(|plugin| plugin.metadata())
184 }
185
186 pub fn get_all_plugin_info(&self) -> HashMap<String, HashMap<String, String>> {
190 let plugins = self.plugins.read().unwrap();
191 plugins
192 .iter()
193 .map(|(name, plugin)| (name.clone(), plugin.metadata()))
194 .collect()
195 }
196 pub async fn shutdown_all(&self) -> Result<()> {
201 let plugins = {
202 let mut plugins_guard = self.plugins.write().unwrap();
203 std::mem::take(&mut *plugins_guard)
204 };
205
206 for (_, mut plugin) in plugins {
208 if let Err(e) = plugin.shutdown().await {
209 eprintln!(
210 "Warning: Failed to shutdown plugin {}: {}",
211 plugin.name(),
212 e
213 );
214 }
215 }
216
217 {
219 let mut tool_index = self.tool_index.write().unwrap();
220 tool_index.clear();
221 }
222 {
223 let mut pm_index = self.pm_index.write().unwrap();
224 pm_index.clear();
225 }
226
227 Ok(())
228 }
229}
230
231#[derive(Default)]
236pub struct PluginRegistryBuilder {
237 plugins: Vec<Box<dyn VxPlugin>>,
238}
239
240impl PluginRegistryBuilder {
241 pub fn new() -> Self {
243 Self::default()
244 }
245
246 pub fn with_plugin(mut self, plugin: Box<dyn VxPlugin>) -> Self {
250 self.plugins.push(plugin);
251 self
252 }
253
254 pub async fn build(self) -> Result<PluginRegistry> {
258 let registry = PluginRegistry::new();
259
260 for plugin in self.plugins {
261 registry.register_plugin(plugin).await?;
262 }
263
264 Ok(registry)
265 }
266}
267
268pub struct ToolRegistry {
273 plugin_registry: PluginRegistry,
274}
275
276impl ToolRegistry {
277 pub fn new() -> Self {
279 Self {
280 plugin_registry: PluginRegistry::new(),
281 }
282 }
283
284 pub async fn register_plugin(&self, plugin: Box<dyn VxPlugin>) -> Result<()> {
286 self.plugin_registry.register_plugin(plugin).await
287 }
288
289 pub fn get_tool(&self, tool_name: &str) -> Option<Box<dyn VxTool>> {
291 self.plugin_registry.get_tool(tool_name)
292 }
293
294 pub fn supports_tool(&self, tool_name: &str) -> bool {
296 self.plugin_registry.has_tool(tool_name)
297 }
298
299 pub fn get_tool_names(&self) -> Vec<String> {
301 self.plugin_registry.list_tools()
302 }
303
304 pub fn get_all_tools(&self) -> Vec<Box<dyn VxTool>> {
306 let plugins = self.plugin_registry.plugins.read().unwrap();
307 plugins.values().flat_map(|plugin| plugin.tools()).collect()
308 }
309
310 pub async fn initialize_all(&self) -> Result<()> {
312 let plugins = {
314 let plugins_guard = self.plugin_registry.plugins.read().unwrap();
315 plugins_guard.keys().cloned().collect::<Vec<_>>()
316 };
317
318 for _plugin_name in plugins {
319 }
323
324 Ok(())
325 }
326}
327
328impl Default for ToolRegistry {
329 fn default() -> Self {
330 Self::new()
331 }
332}