1use async_trait::async_trait;
2use deepstrike_core::memory::curator::CurationResult;
3use deepstrike_core::memory::durable::SessionData;
4use deepstrike_core::memory::semantic::MemoryEntry;
5
6#[async_trait]
17pub trait DreamStore: Send + Sync {
18 async fn load_sessions(&self, agent_id: &str) -> crate::Result<Vec<SessionData>>;
21
22 async fn load_memories(&self, agent_id: &str) -> crate::Result<Vec<MemoryEntry>>;
24
25 async fn commit(
30 &self,
31 agent_id: &str,
32 result: CurationResult,
33 existing: &[MemoryEntry],
34 ) -> crate::Result<()>;
35
36 async fn search(
39 &self,
40 agent_id: &str,
41 query: &str,
42 top_k: usize,
43 ) -> crate::Result<Vec<MemoryEntry>>;
44
45 async fn save_session(
47 &self,
48 data: deepstrike_core::memory::durable::SessionData,
49 ) -> crate::Result<()>;
50}
51
52#[derive(Debug, Default, Clone)]
54pub struct DreamResult {
55 pub sessions_processed: usize,
56 pub insights_extracted: usize,
57 pub entries_added: usize,
58 pub entries_removed: usize,
59}
60
61#[derive(Default)]
63pub struct WorkingMemory {
64 store: std::collections::HashMap<String, serde_json::Value>,
65}
66
67impl WorkingMemory {
68 pub fn set(&mut self, key: impl Into<String>, value: impl Into<serde_json::Value>) {
69 self.store.insert(key.into(), value.into());
70 }
71 pub fn get(&self, key: &str) -> Option<&serde_json::Value> {
72 self.store.get(key)
73 }
74 pub fn clear(&mut self) {
75 self.store.clear();
76 }
77}
78
79pub struct InMemoryDreamStore {
86 sessions: std::sync::Mutex<std::collections::HashMap<String, Vec<SessionData>>>,
87 memories: std::sync::Mutex<std::collections::HashMap<String, Vec<MemoryEntry>>>,
88 initial_memories: Vec<MemoryEntry>,
89 saved_sessions: std::sync::Mutex<Vec<SessionData>>,
90}
91
92impl InMemoryDreamStore {
93 pub fn new() -> Self {
94 Self::with_initial_memories(Vec::new())
95 }
96
97 pub fn with_initial_memories(initial: Vec<MemoryEntry>) -> Self {
98 Self {
99 sessions: std::sync::Mutex::new(std::collections::HashMap::new()),
100 memories: std::sync::Mutex::new(std::collections::HashMap::new()),
101 initial_memories: initial,
102 saved_sessions: std::sync::Mutex::new(Vec::new()),
103 }
104 }
105
106 pub fn add_session(&self, agent_id: impl Into<String>, session: SessionData) {
107 self.sessions
108 .lock()
109 .unwrap()
110 .entry(agent_id.into())
111 .or_default()
112 .push(session);
113 }
114
115 pub fn add_memories(&self, agent_id: impl Into<String>, entries: Vec<MemoryEntry>) {
116 self.memories
117 .lock()
118 .unwrap()
119 .entry(agent_id.into())
120 .or_default()
121 .extend(entries);
122 }
123
124 pub fn saved_sessions(&self) -> Vec<SessionData> {
125 self.saved_sessions.lock().unwrap().clone()
126 }
127}
128
129impl Default for InMemoryDreamStore {
130 fn default() -> Self {
131 Self::new()
132 }
133}
134
135#[async_trait]
136impl DreamStore for InMemoryDreamStore {
137 async fn load_sessions(&self, agent_id: &str) -> crate::Result<Vec<SessionData>> {
138 Ok(self.sessions.lock().unwrap().get(agent_id).cloned().unwrap_or_default())
139 }
140
141 async fn load_memories(&self, agent_id: &str) -> crate::Result<Vec<MemoryEntry>> {
142 let mut memories = self.memories.lock().unwrap();
143 if let Some(existing) = memories.get(agent_id) {
144 return Ok(existing.clone());
145 }
146 if !self.initial_memories.is_empty() {
147 memories.insert(agent_id.to_string(), self.initial_memories.clone());
148 return Ok(self.initial_memories.clone());
149 }
150 Ok(Vec::new())
151 }
152
153 async fn commit(
154 &self,
155 agent_id: &str,
156 result: CurationResult,
157 existing: &[MemoryEntry],
158 ) -> crate::Result<()> {
159 let remove: std::collections::HashSet<usize> = result.to_remove_indices.iter().copied().collect();
160 let mut kept: Vec<MemoryEntry> = existing
161 .iter()
162 .enumerate()
163 .filter_map(|(i, m)| if remove.contains(&i) { None } else { Some(m.clone()) })
164 .collect();
165 kept.extend(result.to_add);
166 self.memories
167 .lock()
168 .unwrap()
169 .insert(agent_id.to_string(), kept);
170 Ok(())
171 }
172
173 async fn search(
174 &self,
175 agent_id: &str,
176 _query: &str,
177 top_k: usize,
178 ) -> crate::Result<Vec<MemoryEntry>> {
179 let all = self.load_memories(agent_id).await?;
180 Ok(all.into_iter().take(top_k).collect())
181 }
182
183 async fn save_session(&self, data: SessionData) -> crate::Result<()> {
184 self.saved_sessions.lock().unwrap().push(data.clone());
185 self.sessions
186 .lock()
187 .unwrap()
188 .entry(data.agent_id.clone())
189 .or_default()
190 .push(data);
191 Ok(())
192 }
193}