use std::collections::HashMap;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use cruxx_core::prelude::{Agent, CruxCtx, CruxErr};
use serde_json::Value;
pub type BoxHandler = Arc<
dyn Fn(Value) -> Pin<Box<dyn Future<Output = Result<Value, CruxErr>> + Send>> + Send + Sync,
>;
pub type BoxAgentRunner = Arc<
dyn Fn(Value) -> Pin<Box<dyn Future<Output = Result<Value, CruxErr>> + Send>> + Send + Sync,
>;
pub struct HandlerRegistry {
handlers: HashMap<String, BoxHandler>,
agents: HashMap<String, BoxAgentRunner>,
}
impl HandlerRegistry {
pub fn new() -> Self {
Self {
handlers: HashMap::new(),
agents: HashMap::new(),
}
}
pub fn handler<F, Fut>(&mut self, name: impl Into<String>, f: F)
where
F: Fn(Value) -> Fut + Send + Sync + 'static,
Fut: Future<Output = Result<Value, CruxErr>> + Send + 'static,
{
let name = name.into();
self.handlers
.insert(name, Arc::new(move |v| Box::pin(f(v))));
}
pub fn agent<A>(&mut self, name: impl Into<String>)
where
A: Agent<Input = Value, Output = Value>,
{
let name_str = name.into();
let agent_name = name_str.clone();
self.agents.insert(
name_str,
Arc::new(move |input: Value| {
let n = agent_name.clone();
Box::pin(async move {
let mut ctx = CruxCtx::new(&n);
A::run(&mut ctx, input).await
}) as Pin<Box<dyn Future<Output = Result<Value, CruxErr>> + Send>>
}),
);
}
pub fn get_handler(&self, name: &str) -> Option<&BoxHandler> {
self.handlers.get(name)
}
pub fn get_agent(&self, name: &str) -> Option<&BoxAgentRunner> {
self.agents.get(name)
}
}
impl Default for HandlerRegistry {
fn default() -> Self {
Self::new()
}
}