claude_agent/context/
level.rs1use std::path::PathBuf;
7
8use async_trait::async_trait;
9
10use super::{ContextResult, MemoryContent, MemoryProvider, RuleIndex};
11
12#[derive(Debug, Default)]
18pub struct LeveledMemoryProvider {
19 contents: Vec<MemoryContent>,
20}
21
22impl LeveledMemoryProvider {
23 pub fn new() -> Self {
24 Self::default()
25 }
26
27 pub fn add_content(&mut self, content: impl Into<String>) {
29 let mut mc = MemoryContent::default();
30 mc.claude_md.push(content.into());
31 self.contents.push(mc);
32 }
33
34 pub fn add_local_content(&mut self, content: impl Into<String>) {
36 let mut mc = MemoryContent::default();
37 mc.local_md.push(content.into());
38 self.contents.push(mc);
39 }
40
41 pub fn add_rule(&mut self, rule: RuleIndex) {
43 let mut mc = MemoryContent::default();
44 mc.rule_indices.push(rule);
45 self.contents.push(mc);
46 }
47
48 pub fn add_memory_content(&mut self, content: MemoryContent) {
50 self.contents.push(content);
51 }
52}
53
54#[async_trait]
55impl MemoryProvider for LeveledMemoryProvider {
56 fn name(&self) -> &str {
57 "leveled"
58 }
59
60 async fn load(&self) -> ContextResult<MemoryContent> {
61 let mut combined = MemoryContent::default();
62 for content in &self.contents {
63 combined.merge(content.clone());
64 }
65 Ok(combined)
66 }
67}
68
69pub fn enterprise_base_path() -> Option<PathBuf> {
70 #[cfg(target_os = "macos")]
71 {
72 let path = PathBuf::from("/Library/Application Support/ClaudeCode");
73 if path.exists() {
74 return Some(path);
75 }
76 }
77 #[cfg(target_os = "linux")]
78 {
79 let path = PathBuf::from("/etc/claude-code");
80 if path.exists() {
81 return Some(path);
82 }
83 }
84 None
85}
86
87pub fn user_base_path() -> Option<PathBuf> {
88 crate::common::home_dir().map(|h| h.join(".claude"))
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94
95 #[tokio::test]
96 async fn test_leveled_memory_provider() {
97 let mut provider = LeveledMemoryProvider::new();
98 provider.add_content("# Enterprise Rules");
99 provider.add_content("# User Preferences");
100 provider.add_content("# Project Guidelines");
101
102 let content = provider.load().await.unwrap();
103 assert_eq!(content.claude_md.len(), 3);
104 }
105
106 #[tokio::test]
107 async fn test_leveled_with_local() {
108 let mut provider = LeveledMemoryProvider::new();
109 provider.add_content("Main content");
110 provider.add_local_content("Local content");
111
112 let content = provider.load().await.unwrap();
113 assert_eq!(content.claude_md.len(), 1);
114 assert_eq!(content.local_md.len(), 1);
115
116 let combined = content.combined_claude_md();
117 assert!(combined.contains("Main content"));
118 assert!(combined.contains("Local content"));
119 }
120}