claude_agent/subagents/
provider.rs1use super::{SubagentDefinition, SubagentLoader};
4use crate::common::{
5 FileProvider, InMemoryProvider as GenericInMemoryProvider, SubagentLookupStrategy,
6};
7
8pub type InMemorySubagentProvider = GenericInMemoryProvider<SubagentDefinition>;
9
10pub type FileSubagentProvider =
11 FileProvider<SubagentDefinition, SubagentLoader, SubagentLookupStrategy>;
12
13pub fn file_subagent_provider() -> FileSubagentProvider {
14 FileSubagentProvider::new(SubagentLoader::new(), SubagentLookupStrategy)
15}
16
17pub type ChainSubagentProvider = crate::common::ChainProvider<SubagentDefinition>;
18
19#[cfg(test)]
20mod tests {
21 use super::*;
22 use crate::common::Provider;
23 use crate::subagents::builtin_subagents;
24
25 #[tokio::test]
26 async fn test_in_memory_provider() {
27 let subagent = SubagentDefinition::new("test", "Test agent", "Do something");
28 let provider = InMemorySubagentProvider::new().with_item(subagent);
29
30 let names = provider.list().await.unwrap();
31 assert_eq!(names, vec!["test"]);
32
33 let loaded = provider.get("test").await.unwrap();
34 assert!(loaded.is_some());
35 assert_eq!(loaded.unwrap().name, "test");
36 }
37
38 #[tokio::test]
39 async fn test_in_memory_with_builtins() {
40 let provider = InMemorySubagentProvider::new().with_items(builtin_subagents());
41 let names = provider.list().await.unwrap();
42
43 assert!(names.contains(&"explore".to_string()));
44 assert!(names.contains(&"plan".to_string()));
45 assert!(names.contains(&"general".to_string()));
46 }
47
48 #[tokio::test]
49 async fn test_chain_provider_priority() {
50 let low = InMemorySubagentProvider::new()
51 .with_item(SubagentDefinition::new("shared", "Low", "Low content"))
52 .with_priority(0);
53
54 let high = InMemorySubagentProvider::new()
55 .with_item(SubagentDefinition::new("shared", "High", "High content"))
56 .with_priority(10);
57
58 let chain = ChainSubagentProvider::new().with(low).with(high);
59
60 let subagent = chain.get("shared").await.unwrap().unwrap();
61 assert_eq!(subagent.description, "High");
62 }
63
64 #[tokio::test]
65 async fn test_file_provider() {
66 use crate::subagents::SubagentSourceType;
67
68 let temp = tempfile::tempdir().unwrap();
69 let provider = file_subagent_provider()
70 .with_path(temp.path())
71 .with_priority(5)
72 .with_source_type(SubagentSourceType::Project);
73
74 assert_eq!(provider.priority(), 5);
75 assert_eq!(provider.paths().len(), 1);
76 }
77
78 #[tokio::test]
79 async fn test_file_provider_load_subagent() {
80 let temp = tempfile::tempdir().unwrap();
81 let subagent_file = temp.path().join("test.md");
82 tokio::fs::write(
83 &subagent_file,
84 r#"---
85name: test-agent
86description: A test agent
87---
88
89Agent prompt here.
90"#,
91 )
92 .await
93 .unwrap();
94
95 let provider = file_subagent_provider().with_path(temp.path());
96
97 let subagent = provider.get("test").await.unwrap();
98 assert!(subagent.is_some());
99 assert_eq!(subagent.unwrap().name, "test-agent");
100 }
101}