spec_ai_core/bootstrap_self/
registry.rs

1use std::path::PathBuf;
2use std::sync::{Arc, Mutex};
3
4use super::plugin::BootstrapPlugin;
5use anyhow::{anyhow, Result};
6
7pub struct PluginRegistry {
8    plugins: Mutex<Vec<Arc<dyn BootstrapPlugin>>>,
9}
10
11impl PluginRegistry {
12    pub fn new() -> Self {
13        Self {
14            plugins: Mutex::new(Vec::new()),
15        }
16    }
17
18    /// Register a plugin
19    pub fn register(&self, plugin: Arc<dyn BootstrapPlugin>) -> Result<()> {
20        let mut plugins = self
21            .plugins
22            .lock()
23            .map_err(|e| anyhow!("Failed to lock plugin registry: {}", e))?;
24        plugins.push(plugin);
25        Ok(())
26    }
27
28    /// Get a plugin by name
29    pub fn get_by_name(&self, name: &str) -> Result<Option<Arc<dyn BootstrapPlugin>>> {
30        let plugins = self
31            .plugins
32            .lock()
33            .map_err(|e| anyhow!("Failed to lock plugin registry: {}", e))?;
34        Ok(plugins.iter().find(|p| p.name() == name).cloned())
35    }
36
37    /// Get all registered plugins
38    pub fn all_plugins(&self) -> Result<Vec<Arc<dyn BootstrapPlugin>>> {
39        let plugins = self
40            .plugins
41            .lock()
42            .map_err(|e| anyhow!("Failed to lock plugin registry: {}", e))?;
43        Ok(plugins.clone())
44    }
45
46    /// Get plugins that should auto-activate for the given repo
47    pub fn get_enabled(&self, repo_root: &PathBuf) -> Result<Vec<Arc<dyn BootstrapPlugin>>> {
48        let plugins = self
49            .plugins
50            .lock()
51            .map_err(|e| anyhow!("Failed to lock plugin registry: {}", e))?;
52        Ok(plugins
53            .iter()
54            .filter(|p| p.should_activate(repo_root))
55            .cloned()
56            .collect())
57    }
58
59    /// Get plugins by a list of names
60    pub fn get_by_names(&self, names: &[String]) -> Result<Vec<Arc<dyn BootstrapPlugin>>> {
61        let plugins = self
62            .plugins
63            .lock()
64            .map_err(|e| anyhow!("Failed to lock plugin registry: {}", e))?;
65        let mut result = Vec::new();
66        for name in names {
67            let plugin = plugins
68                .iter()
69                .find(|p| p.name() == name)
70                .ok_or_else(|| anyhow!("Plugin not found: {}", name))?
71                .clone();
72            result.push(plugin);
73        }
74        Ok(result)
75    }
76}
77
78impl Default for PluginRegistry {
79    fn default() -> Self {
80        Self::new()
81    }
82}
83
84impl Clone for PluginRegistry {
85    fn clone(&self) -> Self {
86        match self.plugins.lock() {
87            Ok(plugins) => Self {
88                plugins: Mutex::new(plugins.clone()),
89            },
90            Err(_) => Self::new(),
91        }
92    }
93}