pub mod escalation; pub mod mailbox; pub mod taskqueue; use crate::utils::AbortSignal; use fmt::{Debug, Formatter}; use mailbox::Inbox; use taskqueue::TaskQueue; use anyhow::{Result, bail}; use std::collections::HashMap; use std::fmt; use std::sync::Arc; use tokio::task::JoinHandle; #[derive(Debug, Clone, PartialEq, Eq)] pub enum AgentExitStatus { Completed, Failed(String), } pub struct AgentResult { pub id: String, pub agent_name: String, pub output: String, pub exit_status: AgentExitStatus, } pub struct AgentHandle { pub id: String, pub agent_name: String, pub depth: usize, pub inbox: Arc, pub abort_signal: AbortSignal, pub join_handle: JoinHandle>, } pub struct Supervisor { handles: HashMap, task_queue: TaskQueue, max_concurrent: usize, max_depth: usize, } impl Supervisor { pub fn new(max_concurrent: usize, max_depth: usize) -> Self { Self { handles: HashMap::new(), task_queue: TaskQueue::new(), max_concurrent, max_depth, } } pub fn active_count(&self) -> usize { self.handles.len() } pub fn max_concurrent(&self) -> usize { self.max_concurrent } pub fn max_depth(&self) -> usize { self.max_depth } pub fn task_queue(&self) -> &TaskQueue { &self.task_queue } pub fn task_queue_mut(&mut self) -> &mut TaskQueue { &mut self.task_queue } pub fn register(&mut self, handle: AgentHandle) -> Result<()> { if self.handles.len() >= self.max_concurrent { bail!( "Cannot spawn agent: at capacity ({}/{})", self.handles.len(), self.max_concurrent ); } if handle.depth > self.max_depth { bail!( "Cannot spawn agent: max depth exceeded ({}/{})", handle.depth, self.max_depth ); } self.handles.insert(handle.id.clone(), handle); Ok(()) } pub fn is_finished(&self, id: &str) -> Option { self.handles.get(id).map(|h| h.join_handle.is_finished()) } pub fn take(&mut self, id: &str) -> Option { self.handles.remove(id) } pub fn inbox(&self, id: &str) -> Option<&Arc> { self.handles.get(id).map(|h| &h.inbox) } pub fn list_agents(&self) -> Vec<(&str, &str)> { self.handles .values() .map(|h| (h.id.as_str(), h.agent_name.as_str())) .collect() } pub fn cancel_all(&self) { for handle in self.handles.values() { handle.abort_signal.set_ctrlc(); } } } impl Debug for Supervisor { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("Supervisor") .field("active_agents", &self.handles.len()) .field("max_concurrent", &self.max_concurrent) .field("max_depth", &self.max_depth) .finish() } }