claude_agent/output_style/
provider.rs

1//! Output style provider implementations using common infrastructure.
2
3use super::{OutputStyle, OutputStyleLoader};
4use crate::common::{
5    FileProvider, InMemoryProvider as GenericInMemoryProvider, OutputStyleLookupStrategy,
6};
7
8pub type InMemoryOutputStyleProvider = GenericInMemoryProvider<OutputStyle>;
9
10pub type FileOutputStyleProvider =
11    FileProvider<OutputStyle, OutputStyleLoader, OutputStyleLookupStrategy>;
12
13pub type ChainOutputStyleProvider = crate::common::ChainProvider<OutputStyle>;
14
15pub fn file_output_style_provider() -> FileOutputStyleProvider {
16    FileOutputStyleProvider::new(OutputStyleLoader::new(), OutputStyleLookupStrategy)
17}
18
19#[cfg(test)]
20mod tests {
21    use super::*;
22    use crate::common::Provider;
23
24    #[tokio::test]
25    async fn test_in_memory_provider() {
26        let style = OutputStyle::new("test", "Test style", "Do something");
27        let provider = InMemoryOutputStyleProvider::new().with_item(style);
28
29        let names = provider.list().await.unwrap();
30        assert_eq!(names, vec!["test"]);
31
32        let loaded = provider.get("test").await.unwrap();
33        assert!(loaded.is_some());
34        assert_eq!(loaded.unwrap().name, "test");
35    }
36
37    #[tokio::test]
38    async fn test_chain_provider() {
39        let low = InMemoryOutputStyleProvider::new()
40            .with_item(OutputStyle::new("shared", "Low", "Low content"))
41            .with_priority(0);
42
43        let high = InMemoryOutputStyleProvider::new()
44            .with_item(OutputStyle::new("shared", "High", "High content"))
45            .with_priority(10);
46
47        let chain = ChainOutputStyleProvider::new().with(low).with(high);
48
49        let style = chain.get("shared").await.unwrap().unwrap();
50        assert_eq!(style.description, "High");
51    }
52
53    #[tokio::test]
54    async fn test_file_provider() {
55        use crate::common::SourceType;
56
57        let temp = tempfile::tempdir().unwrap();
58        let provider = file_output_style_provider()
59            .with_path(temp.path())
60            .with_priority(5)
61            .with_source_type(SourceType::Project);
62
63        assert_eq!(provider.priority(), 5);
64        assert_eq!(provider.paths().len(), 1);
65    }
66
67    #[tokio::test]
68    async fn test_file_provider_load_style() {
69        let temp = tempfile::tempdir().unwrap();
70        let style_file = temp.path().join("custom.md");
71        tokio::fs::write(
72            &style_file,
73            r#"---
74name: custom-style
75description: A custom style
76---
77
78Custom content here.
79"#,
80        )
81        .await
82        .unwrap();
83
84        let provider = file_output_style_provider().with_path(temp.path());
85
86        let style = provider.get("custom").await.unwrap();
87        assert!(style.is_some());
88        assert_eq!(style.unwrap().name, "custom-style");
89    }
90}