use crate::{Result, VxPackageManager, VxPlugin, VxTool};
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
#[derive(Default)]
pub struct PluginRegistry {
plugins: Arc<RwLock<HashMap<String, Box<dyn VxPlugin>>>>,
tool_index: Arc<RwLock<HashMap<String, String>>>,
pm_index: Arc<RwLock<HashMap<String, String>>>,
}
impl PluginRegistry {
pub fn new() -> Self {
Self::default()
}
pub async fn register_plugin(&self, mut plugin: Box<dyn VxPlugin>) -> Result<()> {
let plugin_name = plugin.name().to_string();
plugin.initialize().await?;
{
let mut tool_index = self.tool_index.write().unwrap();
for tool in plugin.tools() {
tool_index.insert(tool.name().to_string(), plugin_name.clone());
for alias in tool.aliases() {
tool_index.insert(alias.to_string(), plugin_name.clone());
}
}
}
{
let mut pm_index = self.pm_index.write().unwrap();
for pm in plugin.package_managers() {
pm_index.insert(pm.name().to_string(), plugin_name.clone());
}
}
{
let mut plugins = self.plugins.write().unwrap();
plugins.insert(plugin_name, plugin);
}
Ok(())
}
pub async fn unregister_plugin(&self, plugin_name: &str) -> Result<()> {
let mut plugin = {
let mut plugins = self.plugins.write().unwrap();
plugins.remove(plugin_name)
};
if let Some(ref mut plugin) = plugin {
plugin.shutdown().await?;
{
let mut tool_index = self.tool_index.write().unwrap();
tool_index.retain(|_, p_name| p_name != plugin_name);
}
{
let mut pm_index = self.pm_index.write().unwrap();
pm_index.retain(|_, p_name| p_name != plugin_name);
}
}
Ok(())
}
pub fn get_tool(&self, tool_name: &str) -> Option<Box<dyn VxTool>> {
let tool_index = self.tool_index.read().unwrap();
let plugins = self.plugins.read().unwrap();
if let Some(plugin_name) = tool_index.get(tool_name) {
if let Some(plugin) = plugins.get(plugin_name) {
return plugin
.tools()
.into_iter()
.find(|tool| tool.name() == tool_name || tool.aliases().contains(&tool_name));
}
}
None
}
pub fn get_package_manager(&self, pm_name: &str) -> Option<Box<dyn VxPackageManager>> {
let pm_index = self.pm_index.read().unwrap();
let plugins = self.plugins.read().unwrap();
if let Some(plugin_name) = pm_index.get(pm_name) {
if let Some(plugin) = plugins.get(plugin_name) {
return plugin
.package_managers()
.into_iter()
.find(|pm| pm.name() == pm_name);
}
}
None
}
pub fn list_plugins(&self) -> Vec<String> {
let plugins = self.plugins.read().unwrap();
plugins.keys().cloned().collect()
}
pub fn list_tools(&self) -> Vec<String> {
let tool_index = self.tool_index.read().unwrap();
tool_index.keys().cloned().collect()
}
pub fn list_package_managers(&self) -> Vec<String> {
let pm_index = self.pm_index.read().unwrap();
pm_index.keys().cloned().collect()
}
pub fn has_tool(&self, tool_name: &str) -> bool {
let tool_index = self.tool_index.read().unwrap();
tool_index.contains_key(tool_name)
}
pub fn has_package_manager(&self, pm_name: &str) -> bool {
let pm_index = self.pm_index.read().unwrap();
pm_index.contains_key(pm_name)
}
pub fn get_plugin_info(&self, plugin_name: &str) -> Option<HashMap<String, String>> {
let plugins = self.plugins.read().unwrap();
plugins.get(plugin_name).map(|plugin| plugin.metadata())
}
pub fn get_all_plugin_info(&self) -> HashMap<String, HashMap<String, String>> {
let plugins = self.plugins.read().unwrap();
plugins
.iter()
.map(|(name, plugin)| (name.clone(), plugin.metadata()))
.collect()
}
pub async fn shutdown_all(&self) -> Result<()> {
let plugins = {
let mut plugins_guard = self.plugins.write().unwrap();
std::mem::take(&mut *plugins_guard)
};
for (_, mut plugin) in plugins {
if let Err(e) = plugin.shutdown().await {
eprintln!(
"Warning: Failed to shutdown plugin {}: {}",
plugin.name(),
e
);
}
}
{
let mut tool_index = self.tool_index.write().unwrap();
tool_index.clear();
}
{
let mut pm_index = self.pm_index.write().unwrap();
pm_index.clear();
}
Ok(())
}
}
#[derive(Default)]
pub struct PluginRegistryBuilder {
plugins: Vec<Box<dyn VxPlugin>>,
}
impl PluginRegistryBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn with_plugin(mut self, plugin: Box<dyn VxPlugin>) -> Self {
self.plugins.push(plugin);
self
}
pub async fn build(self) -> Result<PluginRegistry> {
let registry = PluginRegistry::new();
for plugin in self.plugins {
registry.register_plugin(plugin).await?;
}
Ok(registry)
}
}
pub struct ToolRegistry {
plugin_registry: PluginRegistry,
}
impl ToolRegistry {
pub fn new() -> Self {
Self {
plugin_registry: PluginRegistry::new(),
}
}
pub async fn register_plugin(&self, plugin: Box<dyn VxPlugin>) -> Result<()> {
self.plugin_registry.register_plugin(plugin).await
}
pub fn get_tool(&self, tool_name: &str) -> Option<Box<dyn VxTool>> {
self.plugin_registry.get_tool(tool_name)
}
pub fn supports_tool(&self, tool_name: &str) -> bool {
self.plugin_registry.has_tool(tool_name)
}
pub fn get_tool_names(&self) -> Vec<String> {
self.plugin_registry.list_tools()
}
pub fn get_all_tools(&self) -> Vec<Box<dyn VxTool>> {
let plugins = self.plugin_registry.plugins.read().unwrap();
plugins.values().flat_map(|plugin| plugin.tools()).collect()
}
pub async fn initialize_all(&self) -> Result<()> {
let plugins = {
let plugins_guard = self.plugin_registry.plugins.read().unwrap();
plugins_guard.keys().cloned().collect::<Vec<_>>()
};
for _plugin_name in plugins {
}
Ok(())
}
}
impl Default for ToolRegistry {
fn default() -> Self {
Self::new()
}
}