feat: Implement registry for meta plugins
Co-authored-by: aider (openai/andrew/openrouter/deepseek/deepseek-chat-v3.1) <aider@aider.chat>
This commit is contained in:
@@ -244,6 +244,8 @@ pub trait MetaPlugin where Self: 'static {
|
||||
// Access to outputs mapping with default implementation
|
||||
fn outputs(&self) -> &std::collections::HashMap<String, serde_yaml::Value> {
|
||||
use once_cell::sync::Lazy;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Mutex;
|
||||
static EMPTY: Lazy<std::collections::HashMap<String, serde_yaml::Value>> =
|
||||
Lazy::new(|| std::collections::HashMap::new());
|
||||
&EMPTY
|
||||
@@ -279,62 +281,67 @@ pub trait MetaPlugin where Self: 'static {
|
||||
}
|
||||
}
|
||||
|
||||
/// Global registry for meta plugins
|
||||
static META_PLUGIN_REGISTRY: Lazy<Mutex<HashMap<MetaPluginType, fn(Option<HashMap<String, serde_yaml::Value>>, Option<HashMap<String, serde_yaml::Value>>) -> Box<dyn MetaPlugin>>>> =
|
||||
Lazy::new(|| Mutex::new(HashMap::new()));
|
||||
|
||||
/// Register a meta plugin with the global registry
|
||||
pub fn register_meta_plugin(
|
||||
meta_plugin_type: MetaPluginType,
|
||||
constructor: fn(Option<HashMap<String, serde_yaml::Value>>, Option<HashMap<String, serde_yaml::Value>>) -> Box<dyn MetaPlugin>
|
||||
) {
|
||||
META_PLUGIN_REGISTRY.lock().unwrap().insert(meta_plugin_type, constructor);
|
||||
}
|
||||
|
||||
pub fn get_meta_plugin(
|
||||
meta_plugin_type: MetaPluginType,
|
||||
options: Option<std::collections::HashMap<String, serde_yaml::Value>>,
|
||||
outputs: Option<std::collections::HashMap<String, serde_yaml::Value>>,
|
||||
) -> Box<dyn MetaPlugin> {
|
||||
match meta_plugin_type {
|
||||
MetaPluginType::MagicFile => Box::new(MagicFileMetaPlugin::new(options, outputs)),
|
||||
MetaPluginType::Cwd => Box::new(CwdMetaPlugin::new(options, outputs)),
|
||||
MetaPluginType::Text => Box::new(TextMetaPlugin::new(options, outputs)),
|
||||
MetaPluginType::User => Box::new(UserMetaPlugin::new(options, outputs)),
|
||||
MetaPluginType::Shell => Box::new(ShellMetaPlugin::new(options, outputs)),
|
||||
MetaPluginType::ShellPid => Box::new(ShellPidMetaPlugin::new(options, outputs)),
|
||||
MetaPluginType::KeepPid => Box::new(KeepPidMetaPlugin::new(options, outputs)),
|
||||
MetaPluginType::Digest => Box::new(DigestMetaPlugin::new(options, outputs)),
|
||||
MetaPluginType::ReadTime => Box::new(ReadTimeMetaPlugin::new(options, outputs)),
|
||||
MetaPluginType::ReadRate => Box::new(ReadRateMetaPlugin::new(options, outputs)),
|
||||
MetaPluginType::Hostname => Box::new(HostnameMetaPlugin::new(options, outputs)),
|
||||
MetaPluginType::Exec => {
|
||||
// For exec type, we need to parse the command from options
|
||||
let mut program_name = String::new();
|
||||
let mut args = Vec::new();
|
||||
let mut meta_name = MetaPluginType::Exec.to_string();
|
||||
let mut split_whitespace = true;
|
||||
|
||||
if let Some(opts) = &options {
|
||||
if let Some(command_value) = opts.get("command") {
|
||||
if let Some(command_str) = command_value.as_str() {
|
||||
let parts: Vec<&str> = command_str.split_whitespace().collect();
|
||||
if !parts.is_empty() {
|
||||
program_name = parts[0].to_string();
|
||||
args = parts[1..].iter().map(|s| s.to_string()).collect();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Handle other options if needed
|
||||
if let Some(split_value) = opts.get("split_whitespace") {
|
||||
if let Some(split_bool) = split_value.as_bool() {
|
||||
split_whitespace = split_bool;
|
||||
}
|
||||
}
|
||||
if let Some(name_value) = opts.get("name") {
|
||||
if let Some(name_str) = name_value.as_str() {
|
||||
meta_name = name_str.to_string();
|
||||
let registry = META_PLUGIN_REGISTRY.lock().unwrap();
|
||||
if let Some(constructor) = registry.get(&meta_plugin_type) {
|
||||
return constructor(options, outputs);
|
||||
}
|
||||
|
||||
// Fallback for exec plugin which needs special handling
|
||||
if meta_plugin_type == MetaPluginType::Exec {
|
||||
// For exec type, we need to parse the command from options
|
||||
let mut program_name = String::new();
|
||||
let mut args = Vec::new();
|
||||
let mut meta_name = MetaPluginType::Exec.to_string();
|
||||
let mut split_whitespace = true;
|
||||
|
||||
if let Some(opts) = &options {
|
||||
if let Some(command_value) = opts.get("command") {
|
||||
if let Some(command_str) = command_value.as_str() {
|
||||
let parts: Vec<&str> = command_str.split_whitespace().collect();
|
||||
if !parts.is_empty() {
|
||||
program_name = parts[0].to_string();
|
||||
args = parts[1..].iter().map(|s| s.to_string()).collect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Box::new(MetaPluginExec::new(&program_name,
|
||||
args.iter().map(|s| s.as_str()).collect(),
|
||||
meta_name,
|
||||
split_whitespace,
|
||||
options,
|
||||
outputs))
|
||||
}
|
||||
MetaPluginType::Env => {
|
||||
Box::new(EnvMetaPlugin::new(options, outputs))
|
||||
// Handle other options if needed
|
||||
if let Some(split_value) = opts.get("split_whitespace") {
|
||||
if let Some(split_bool) = split_value.as_bool() {
|
||||
split_whitespace = split_bool;
|
||||
}
|
||||
}
|
||||
if let Some(name_value) = opts.get("name") {
|
||||
if let Some(name_str) = name_value.as_str() {
|
||||
meta_name = name_str.to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Box::new(MetaPluginExec::new(&program_name,
|
||||
args.iter().map(|s| s.as_str()).collect(),
|
||||
meta_name,
|
||||
split_whitespace,
|
||||
options,
|
||||
outputs));
|
||||
}
|
||||
|
||||
// Fallback for unknown plugins
|
||||
panic!("Meta plugin {:?} not registered", meta_plugin_type);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user