1use crate::agents::*;
4use crate::tools::ToolRegistry;
5use crate::traits::{AgentError, Result, SpecializedAgent};
6use std::collections::HashMap;
7use std::sync::Arc;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11pub enum AgentType {
12 Architect,
14 Cto,
16 Reviewer,
18 Explorer,
20 Planner,
22 Scientist,
24}
25
26impl AgentType {
27 pub fn name(&self) -> &'static str {
29 match self {
30 AgentType::Architect => "architect",
31 AgentType::Cto => "cto",
32 AgentType::Reviewer => "reviewer",
33 AgentType::Explorer => "explorer",
34 AgentType::Planner => "planner",
35 AgentType::Scientist => "scientist",
36 }
37 }
38
39 pub fn from_str(s: &str) -> Option<Self> {
41 match s.to_lowercase().as_str() {
42 "architect" => Some(AgentType::Architect),
43 "cto" => Some(AgentType::Cto),
44 "reviewer" | "review" => Some(AgentType::Reviewer),
45 "explorer" | "explore" => Some(AgentType::Explorer),
46 "planner" | "plan" => Some(AgentType::Planner),
47 "scientist" | "research" => Some(AgentType::Scientist),
48 _ => None,
49 }
50 }
51
52 pub fn all() -> Vec<AgentType> {
54 vec![
55 AgentType::Architect,
56 AgentType::Cto,
57 AgentType::Reviewer,
58 AgentType::Explorer,
59 AgentType::Planner,
60 AgentType::Scientist,
61 ]
62 }
63}
64
65impl std::fmt::Display for AgentType {
66 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67 write!(f, "{}", self.name())
68 }
69}
70
71pub struct AgentRegistry {
78 tool_registry: Arc<ToolRegistry>,
79 agents: HashMap<AgentType, Arc<dyn SpecializedAgent>>,
80}
81
82impl AgentRegistry {
83 pub fn new() -> Self {
85 let tool_registry = Arc::new(ToolRegistry::with_defaults());
86 Self {
87 tool_registry,
88 agents: HashMap::new(),
89 }
90 }
91
92 pub fn with_tools(tool_registry: Arc<ToolRegistry>) -> Self {
94 Self {
95 tool_registry,
96 agents: HashMap::new(),
97 }
98 }
99
100 pub fn tool_registry(&self) -> Arc<ToolRegistry> {
102 self.tool_registry.clone()
103 }
104
105 pub fn get(&mut self, agent_type: AgentType) -> Result<Arc<dyn SpecializedAgent>> {
107 if let Some(agent) = self.agents.get(&agent_type) {
108 return Ok(agent.clone());
109 }
110
111 let agent: Arc<dyn SpecializedAgent> = match agent_type {
112 AgentType::Architect => Arc::new(ArchitectAgent::new(self.tool_registry.clone())),
113 AgentType::Cto => Arc::new(CtoAgent::new(self.tool_registry.clone())),
114 AgentType::Reviewer => Arc::new(ReviewerAgent::new(self.tool_registry.clone())),
115 AgentType::Explorer => Arc::new(ExplorerAgent::new(self.tool_registry.clone())),
116 AgentType::Planner => Arc::new(PlannerAgent::new(self.tool_registry.clone())),
117 AgentType::Scientist => Arc::new(ScientistAgent::new(self.tool_registry.clone())),
118 };
119
120 self.agents.insert(agent_type, agent.clone());
121 Ok(agent)
122 }
123
124 pub fn get_by_name(&mut self, name: &str) -> Result<Arc<dyn SpecializedAgent>> {
126 let agent_type = AgentType::from_str(name)
127 .ok_or_else(|| AgentError::ConfigError(format!("Unknown agent type: {}", name)))?;
128 self.get(agent_type)
129 }
130
131 pub fn list_agents(&self) -> Vec<(AgentType, &'static str)> {
133 vec![
134 (
135 AgentType::Architect,
136 "High-level system design and architecture",
137 ),
138 (AgentType::Cto, "Technical leadership and code quality"),
139 (AgentType::Reviewer, "Code review and quality assurance"),
140 (
141 AgentType::Explorer,
142 "Codebase exploration and documentation",
143 ),
144 (
145 AgentType::Planner,
146 "Task planning and implementation strategy",
147 ),
148 (AgentType::Scientist, "Research and analysis"),
149 ]
150 }
151}
152
153impl Default for AgentRegistry {
154 fn default() -> Self {
155 Self::new()
156 }
157}
158
159#[cfg(test)]
160mod tests {
161 use super::*;
162
163 #[test]
164 fn test_agent_type_from_str() {
165 assert_eq!(AgentType::from_str("architect"), Some(AgentType::Architect));
166 assert_eq!(AgentType::from_str("CTO"), Some(AgentType::Cto));
167 assert_eq!(AgentType::from_str("review"), Some(AgentType::Reviewer));
168 assert_eq!(AgentType::from_str("unknown"), None);
169 }
170
171 #[test]
172 fn test_registry_creation() {
173 let mut registry = AgentRegistry::new();
174 let agent = registry.get(AgentType::Architect).unwrap();
175 assert_eq!(agent.name(), "architect");
176 }
177
178 #[test]
179 fn test_registry_caching() {
180 let mut registry = AgentRegistry::new();
181 let agent1 = registry.get(AgentType::Cto).unwrap();
182 let agent2 = registry.get(AgentType::Cto).unwrap();
183 assert!(Arc::ptr_eq(&agent1, &agent2));
185 }
186}