mofa_kernel/agent/components/
memory.rs1use crate::agent::error::AgentResult;
6use async_trait::async_trait;
7use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9
10#[async_trait]
38pub trait Memory: Send + Sync {
39 async fn store(&mut self, key: &str, value: MemoryValue) -> AgentResult<()>;
41
42 async fn retrieve(&self, key: &str) -> AgentResult<Option<MemoryValue>>;
44
45 async fn remove(&mut self, key: &str) -> AgentResult<bool>;
47
48 async fn contains(&self, key: &str) -> AgentResult<bool> {
50 Ok(self.retrieve(key).await?.is_some())
51 }
52
53 async fn search(&self, query: &str, limit: usize) -> AgentResult<Vec<MemoryItem>>;
55
56 async fn clear(&mut self) -> AgentResult<()>;
58
59 async fn get_history(&self, session_id: &str) -> AgentResult<Vec<Message>>;
61
62 async fn add_to_history(&mut self, session_id: &str, message: Message) -> AgentResult<()>;
64
65 async fn clear_history(&mut self, session_id: &str) -> AgentResult<()>;
67
68 async fn stats(&self) -> AgentResult<MemoryStats> {
70 Ok(MemoryStats::default())
71 }
72
73 fn memory_type(&self) -> &str {
75 "memory"
76 }
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize)]
81pub enum MemoryValue {
82 Text(String),
84 Embedding(Vec<f32>),
86 Structured(serde_json::Value),
88 Binary(Vec<u8>),
90 TextWithEmbedding { text: String, embedding: Vec<f32> },
92}
93
94impl MemoryValue {
95 pub fn text(s: impl Into<String>) -> Self {
97 Self::Text(s.into())
98 }
99
100 pub fn embedding(e: Vec<f32>) -> Self {
102 Self::Embedding(e)
103 }
104
105 pub fn structured(v: serde_json::Value) -> Self {
107 Self::Structured(v)
108 }
109
110 pub fn text_with_embedding(text: impl Into<String>, embedding: Vec<f32>) -> Self {
112 Self::TextWithEmbedding {
113 text: text.into(),
114 embedding,
115 }
116 }
117
118 pub fn as_text(&self) -> Option<&str> {
120 match self {
121 Self::Text(s) => Some(s),
122 Self::TextWithEmbedding { text, .. } => Some(text),
123 _ => None,
124 }
125 }
126
127 pub fn as_embedding(&self) -> Option<&[f32]> {
129 match self {
130 Self::Embedding(e) => Some(e),
131 Self::TextWithEmbedding { embedding, .. } => Some(embedding),
132 _ => None,
133 }
134 }
135
136 pub fn as_structured(&self) -> Option<&serde_json::Value> {
138 match self {
139 Self::Structured(v) => Some(v),
140 _ => None,
141 }
142 }
143}
144
145impl From<String> for MemoryValue {
146 fn from(s: String) -> Self {
147 Self::Text(s)
148 }
149}
150
151impl From<&str> for MemoryValue {
152 fn from(s: &str) -> Self {
153 Self::Text(s.to_string())
154 }
155}
156
157impl From<serde_json::Value> for MemoryValue {
158 fn from(v: serde_json::Value) -> Self {
159 Self::Structured(v)
160 }
161}
162
163#[derive(Debug, Clone, Serialize, Deserialize)]
165pub struct MemoryItem {
166 pub key: String,
168 pub value: MemoryValue,
170 pub score: f32,
172 pub metadata: HashMap<String, String>,
174 pub created_at: u64,
176 pub last_accessed: u64,
178}
179
180impl MemoryItem {
181 pub fn new(key: impl Into<String>, value: MemoryValue) -> Self {
183 let now = std::time::SystemTime::now()
184 .duration_since(std::time::UNIX_EPOCH)
185 .unwrap_or_default()
186 .as_millis() as u64;
187
188 Self {
189 key: key.into(),
190 value,
191 score: 1.0,
192 metadata: HashMap::new(),
193 created_at: now,
194 last_accessed: now,
195 }
196 }
197
198 pub fn with_score(mut self, score: f32) -> Self {
200 self.score = score.clamp(0.0, 1.0);
201 self
202 }
203
204 pub fn with_metadata(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
206 self.metadata.insert(key.into(), value.into());
207 self
208 }
209}
210
211#[derive(Debug, Clone, Serialize, Deserialize)]
213pub struct Message {
214 pub role: MessageRole,
216 pub content: String,
218 pub timestamp: u64,
220 pub metadata: HashMap<String, serde_json::Value>,
222}
223
224impl Message {
225 pub fn new(role: MessageRole, content: impl Into<String>) -> Self {
227 let now = std::time::SystemTime::now()
228 .duration_since(std::time::UNIX_EPOCH)
229 .unwrap_or_default()
230 .as_millis() as u64;
231
232 Self {
233 role,
234 content: content.into(),
235 timestamp: now,
236 metadata: HashMap::new(),
237 }
238 }
239
240 pub fn system(content: impl Into<String>) -> Self {
242 Self::new(MessageRole::System, content)
243 }
244
245 pub fn user(content: impl Into<String>) -> Self {
247 Self::new(MessageRole::User, content)
248 }
249
250 pub fn assistant(content: impl Into<String>) -> Self {
252 Self::new(MessageRole::Assistant, content)
253 }
254
255 pub fn tool(tool_name: impl Into<String>, content: impl Into<String>) -> Self {
257 let mut msg = Self::new(MessageRole::Tool, content);
258 msg.metadata.insert(
259 "tool_name".to_string(),
260 serde_json::Value::String(tool_name.into()),
261 );
262 msg
263 }
264
265 pub fn with_metadata(mut self, key: impl Into<String>, value: serde_json::Value) -> Self {
267 self.metadata.insert(key.into(), value);
268 self
269 }
270}
271
272#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
274pub enum MessageRole {
275 System,
277 User,
279 Assistant,
281 Tool,
283}
284
285impl std::fmt::Display for MessageRole {
286 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
287 match self {
288 Self::System => write!(f, "system"),
289 Self::User => write!(f, "user"),
290 Self::Assistant => write!(f, "assistant"),
291 Self::Tool => write!(f, "tool"),
292 }
293 }
294}
295
296#[derive(Debug, Clone, Default, Serialize, Deserialize)]
298pub struct MemoryStats {
299 pub total_items: usize,
301 pub total_sessions: usize,
303 pub total_messages: usize,
305 pub memory_bytes: usize,
307}