defect_agent/session/
tool_registry.rs1use std::collections::{HashMap, HashSet};
10use std::sync::Arc;
11
12use crate::session::ToolRegistry;
13use crate::tool::{Tool, ToolSchema};
14
15pub struct StaticToolRegistry {
20 schemas: Vec<ToolSchema>,
21 by_name: HashMap<String, Arc<dyn Tool>>,
22}
23
24impl StaticToolRegistry {
25 pub fn builder() -> StaticToolRegistryBuilder {
26 StaticToolRegistryBuilder::default()
27 }
28
29 pub fn empty() -> Self {
31 Self {
32 schemas: Vec::new(),
33 by_name: HashMap::new(),
34 }
35 }
36}
37
38impl ToolRegistry for StaticToolRegistry {
39 fn schemas(&self) -> Vec<ToolSchema> {
40 self.schemas.clone()
41 }
42
43 fn get(&self, name: &str) -> Option<Arc<dyn Tool>> {
44 self.by_name.get(name).cloned()
45 }
46}
47
48#[derive(Default)]
50pub struct StaticToolRegistryBuilder {
51 schemas: Vec<ToolSchema>,
52 by_name: HashMap<String, Arc<dyn Tool>>,
53}
54
55impl StaticToolRegistryBuilder {
56 pub fn insert(mut self, tool: Arc<dyn Tool>) -> Self {
60 let schema = tool.schema().clone();
61 if let Some(pos) = self.schemas.iter().position(|s| s.name == schema.name) {
62 if let Some(slot) = self.schemas.get_mut(pos) {
63 *slot = schema.clone();
64 }
65 } else {
66 self.schemas.push(schema.clone());
67 }
68 self.by_name.insert(schema.name, tool);
69 self
70 }
71
72 pub fn build(self) -> StaticToolRegistry {
73 StaticToolRegistry {
74 schemas: self.schemas,
75 by_name: self.by_name,
76 }
77 }
78}
79
80pub struct CompositeRegistry {
86 session: Arc<dyn ToolRegistry>,
87 process: Arc<dyn ToolRegistry>,
88}
89
90impl CompositeRegistry {
91 pub fn new(session: Arc<dyn ToolRegistry>, process: Arc<dyn ToolRegistry>) -> Self {
92 Self { session, process }
93 }
94}
95
96impl ToolRegistry for CompositeRegistry {
97 fn schemas(&self) -> Vec<ToolSchema> {
98 let mut session_schemas = self.session.schemas();
99 let mut process_schemas = self.process.schemas();
100 let session_names: HashSet<&str> =
103 session_schemas.iter().map(|s| s.name.as_str()).collect();
104 process_schemas.retain(|s| !session_names.contains(s.name.as_str()));
105 session_schemas.append(&mut process_schemas);
106 session_schemas
107 }
108
109 fn get(&self, name: &str) -> Option<Arc<dyn Tool>> {
110 self.session.get(name).or_else(|| self.process.get(name))
111 }
112}
113
114#[cfg(test)]
115mod tests;