aagt_core/agent/
namespaced_memory.rs1use std::sync::Arc;
2use std::time::Duration;
3use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5use crate::agent::memory::{MemoryManager, Memory};
6use crate::error::Result;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct MemoryEntry {
11 pub value: String,
13 pub created_at: DateTime<Utc>,
15 pub expires_at: Option<DateTime<Utc>>,
17 pub namespace: String,
19 pub author: Option<String>,
21}
22
23impl MemoryEntry {
24 pub fn is_expired(&self) -> bool {
26 if let Some(expires) = self.expires_at {
27 Utc::now() > expires
28 } else {
29 false
30 }
31 }
32}
33
34pub struct NamespacedMemory {
61 memory: Arc<MemoryManager>,
62}
63
64impl NamespacedMemory {
65 pub fn new(memory: Arc<MemoryManager>) -> Self {
67 Self { memory }
68 }
69
70 pub async fn store(
93 &self,
94 namespace: &str,
95 key: &str,
96 value: &str,
97 ttl: Option<Duration>,
98 author: Option<String>,
99 ) -> Result<()> {
100 let full_key = format!("{}::{}", namespace, key);
101
102 let entry = MemoryEntry {
103 value: value.to_string(),
104 created_at: Utc::now(),
105 expires_at: ttl.map(|d| Utc::now() + chrono::Duration::from_std(d).unwrap()),
106 namespace: namespace.to_string(),
107 author,
108 };
109
110 let serialized = serde_json::to_string(&entry)
111 .map_err(|e| crate::error::Error::Internal(format!("Failed to serialize entry: {}", e)))?;
112
113 self.memory.store_knowledge("system", None, &full_key, &serialized, "namespaced_memory").await
114 }
115
116 pub async fn read(&self, namespace: &str, key: &str) -> Result<Option<String>> {
132 let full_key = format!("{}::{}", namespace, key);
133
134 let results = self.memory.search("system", None, &full_key, 1).await?;
135
136 if results.is_empty() {
137 return Ok(None);
138 }
139
140 let content = &results[0].content;
142
143 let entry: MemoryEntry = serde_json::from_str(content)
144 .map_err(|e| crate::error::Error::Internal(format!("Failed to deserialize entry: {}", e)))?;
145
146 if entry.is_expired() {
148 return Ok(None);
149 }
150
151 Ok(Some(entry.value))
152 }
153
154 pub async fn read_with_metadata(&self, namespace: &str, key: &str) -> Result<Option<MemoryEntry>> {
156 let full_key = format!("{}::{}", namespace, key);
157
158 let results = self.memory.search("system", None, &full_key, 1).await?;
159
160 if results.is_empty() {
161 return Ok(None);
162 }
163
164 let content = &results[0].content;
165
166 let entry: MemoryEntry = serde_json::from_str(content)
167 .map_err(|e| crate::error::Error::Internal(format!("Failed to deserialize entry: {}", e)))?;
168
169 if entry.is_expired() {
170 return Ok(None);
171 }
172
173 Ok(Some(entry))
174 }
175
176 pub async fn list_keys(&self, namespace: &str) -> Result<Vec<String>> {
178 let prefix = format!("{}::", namespace);
179 let results = self.memory.search("system", None, &prefix, 100).await?;
180
181 let mut keys = Vec::new();
182 for result in results {
183 if let Ok(entry) = serde_json::from_str::<MemoryEntry>(&result.content) {
184 if !entry.is_expired() {
185 let key = result.title.strip_prefix(&prefix)
187 .unwrap_or(&result.title)
188 .to_string();
189 keys.push(key);
190 }
191 }
192 }
193
194 Ok(keys)
195 }
196
197 pub async fn delete(&self, namespace: &str, key: &str) -> Result<()> {
199 self.store(namespace, key, "", Some(Duration::from_secs(0)), None).await
202 }
203
204 pub async fn clear_namespace(&self, namespace: &str) -> Result<()> {
206 let keys = self.list_keys(namespace).await?;
207 for key in keys {
208 self.delete(namespace, &key).await?;
209 }
210 Ok(())
211 }
212}
213
214#[cfg(test)]
215mod tests {
216 use super::*;
217
218 #[tokio::test]
219 async fn test_store_and_read() {
220 }
223
224 #[test]
225 fn test_entry_expiration() {
226 let entry = MemoryEntry {
227 value: "test".to_string(),
228 created_at: Utc::now(),
229 expires_at: Some(Utc::now() - chrono::Duration::hours(1)),
230 namespace: "test".to_string(),
231 author: None,
232 };
233
234 assert!(entry.is_expired());
235 }
236}