ai_agent/utils/settings/
settings_cache.rs1use std::collections::HashMap;
10use std::sync::{LazyLock, Mutex};
11
12use super::SettingSource;
13use super::validation::{SettingsWithErrors, ValidationError};
14
15#[derive(Debug, Clone, Default, PartialEq)]
17pub struct ParsedSettings {
18 pub settings: Option<serde_json::Value>,
19 pub errors: Vec<ValidationError>,
20}
21
22struct SettingsCacheInner {
23 session_settings: Option<SettingsWithErrors>,
25 per_source_cache: HashMap<SettingSource, Option<serde_json::Value>>,
27 parse_file_cache: HashMap<String, ParsedSettings>,
29 plugin_settings_base: Option<serde_json::Value>,
31}
32
33static SETTINGS_CACHE: LazyLock<Mutex<SettingsCacheInner>> = LazyLock::new(|| {
34 Mutex::new(SettingsCacheInner {
35 session_settings: None,
36 per_source_cache: HashMap::new(),
37 parse_file_cache: HashMap::new(),
38 plugin_settings_base: None,
39 })
40});
41
42pub fn get_session_settings_cache() -> Option<SettingsWithErrors> {
44 SETTINGS_CACHE.lock().unwrap().session_settings.clone()
45}
46
47pub fn set_session_settings_cache(value: SettingsWithErrors) {
49 SETTINGS_CACHE.lock().unwrap().session_settings = Some(value);
50}
51
52pub fn get_cached_settings_for_source(
55 source: &SettingSource,
56) -> Option<Option<serde_json::Value>> {
57 SETTINGS_CACHE
58 .lock()
59 .unwrap()
60 .per_source_cache
61 .get(source)
62 .cloned()
63}
64
65pub fn set_cached_settings_for_source(
67 source: &SettingSource,
68 value: Option<serde_json::Value>,
69) {
70 let mut cache = SETTINGS_CACHE.lock().unwrap();
71 cache.per_source_cache.insert(source.clone(), value);
72}
73
74pub fn get_cached_parsed_file(path: &str) -> Option<ParsedSettings> {
76 SETTINGS_CACHE
77 .lock()
78 .unwrap()
79 .parse_file_cache
80 .get(path)
81 .cloned()
82}
83
84pub fn set_cached_parsed_file(path: &str, value: ParsedSettings) {
86 SETTINGS_CACHE
87 .lock()
88 .unwrap()
89 .parse_file_cache
90 .insert(path.to_string(), value);
91}
92
93pub fn get_plugin_settings_base() -> Option<serde_json::Value> {
95 SETTINGS_CACHE.lock().unwrap().plugin_settings_base.clone()
96}
97
98pub fn set_plugin_settings_base(value: Option<serde_json::Value>) {
100 SETTINGS_CACHE.lock().unwrap().plugin_settings_base = value;
101}
102
103pub fn clear_plugin_settings_base() {
105 SETTINGS_CACHE.lock().unwrap().plugin_settings_base = None;
106}
107
108pub fn reset_settings_cache() {
110 let mut cache = SETTINGS_CACHE.lock().unwrap();
111 cache.session_settings = None;
112 cache.per_source_cache.clear();
113 cache.parse_file_cache.clear();
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119
120 #[test]
121 fn test_session_cache_roundtrip() {
122 reset_settings_cache();
123 assert!(get_session_settings_cache().is_none());
124
125 let settings = SettingsWithErrors {
126 settings: serde_json::json!({"permissions": {"defaultMode": "allow"}}),
127 errors: vec![],
128 };
129 set_session_settings_cache(settings.clone());
130 assert_eq!(
131 get_session_settings_cache().as_ref(),
132 Some(&settings),
133 );
134 }
135
136 #[test]
137 fn test_per_source_cache() {
138 reset_settings_cache();
139 let source = SettingSource::UserSettings;
140 assert!(get_cached_settings_for_source(&source).is_none());
142
143 set_cached_settings_for_source(
145 &source,
146 Some(serde_json::json!({"permissions": {"defaultMode": "deny"}})),
147 );
148 assert!(get_cached_settings_for_source(&source).is_some());
149
150 set_cached_settings_for_source(&source, None);
152 assert!(get_cached_settings_for_source(&source).is_some());
153 assert!(get_cached_settings_for_source(&source).unwrap().is_none());
154 }
155
156 #[test]
157 fn test_parse_file_cache() {
158 reset_settings_cache();
159 assert!(get_cached_parsed_file("/nonexistent").is_none());
160
161 let parsed = ParsedSettings {
162 settings: Some(serde_json::json!({})),
163 errors: vec![],
164 };
165 set_cached_parsed_file("/test/path.json", parsed.clone());
166 assert_eq!(
167 get_cached_parsed_file("/test/path/path.json").as_ref(),
168 None,
169 );
170 assert_eq!(
171 get_cached_parsed_file("/test/path.json").as_ref(),
172 Some(&parsed),
173 );
174 }
175
176 #[test]
177 fn test_plugin_settings_base() {
178 reset_settings_cache();
179 assert!(get_plugin_settings_base().is_none());
180
181 set_plugin_settings_base(Some(serde_json::json!({"model": {"name": "test"}})));
182 assert!(get_plugin_settings_base().is_some());
183
184 clear_plugin_settings_base();
185 assert!(get_plugin_settings_base().is_none());
186 }
187
188 #[test]
189 fn test_reset_clears_all() {
190 set_session_settings_cache(SettingsWithErrors {
192 settings: serde_json::json!({}),
193 errors: vec![],
194 });
195 set_cached_settings_for_source(
196 &SettingSource::UserSettings,
197 Some(serde_json::json!({})),
198 );
199 set_cached_parsed_file(
200 "/test.json",
201 ParsedSettings {
202 settings: Some(serde_json::json!({})),
203 errors: vec![],
204 },
205 );
206 set_plugin_settings_base(Some(serde_json::json!({})));
207
208 reset_settings_cache();
209
210 assert!(get_session_settings_cache().is_none());
211 assert!(get_cached_settings_for_source(&SettingSource::UserSettings).is_none());
212 assert!(get_cached_parsed_file("/test.json").is_none());
213 }
216}