1use std::collections::HashMap;
4use std::sync::Arc;
5
6use crate::agent::Agent;
7
8#[derive(Default)]
10pub struct AgentRegistry {
11 agents: HashMap<String, Arc<dyn Agent>>,
12}
13
14impl AgentRegistry {
15 pub fn new() -> Self {
17 Self::default()
18 }
19
20 pub fn register(&mut self, agent: Arc<dyn Agent>) {
22 self.agents.insert(agent.name().to_string(), agent);
23 }
24
25 pub fn resolve(&self, name: &str) -> Option<Arc<dyn Agent>> {
27 self.agents.get(name).cloned()
28 }
29
30 pub fn names(&self) -> Vec<String> {
32 self.agents.keys().cloned().collect()
33 }
34
35 pub fn len(&self) -> usize {
37 self.agents.len()
38 }
39
40 pub fn is_empty(&self) -> bool {
42 self.agents.is_empty()
43 }
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49 use crate::context::InvocationContext;
50 use crate::error::AgentError;
51 use async_trait::async_trait;
52
53 struct DummyAgent {
54 name: String,
55 }
56
57 #[async_trait]
58 impl Agent for DummyAgent {
59 fn name(&self) -> &str {
60 &self.name
61 }
62 async fn run_live(&self, _ctx: &mut InvocationContext) -> Result<(), AgentError> {
63 Ok(())
64 }
65 }
66
67 #[test]
68 fn register_and_resolve() {
69 let mut registry = AgentRegistry::new();
70 registry.register(Arc::new(DummyAgent {
71 name: "billing".into(),
72 }));
73 registry.register(Arc::new(DummyAgent {
74 name: "tech".into(),
75 }));
76 assert_eq!(registry.len(), 2);
77 assert!(registry.resolve("billing").is_some());
78 assert!(registry.resolve("nonexistent").is_none());
79 }
80
81 #[test]
82 fn names_list() {
83 let mut registry = AgentRegistry::new();
84 registry.register(Arc::new(DummyAgent { name: "a".into() }));
85 registry.register(Arc::new(DummyAgent { name: "b".into() }));
86 let mut names = registry.names();
87 names.sort();
88 assert_eq!(names, vec!["a", "b"]);
89 }
90
91 #[test]
92 fn empty_registry() {
93 let registry = AgentRegistry::new();
94 assert!(registry.is_empty());
95 assert_eq!(registry.len(), 0);
96 }
97}