1use chrono::{DateTime, Utc};
6use serde::{Deserialize, Serialize};
7use sha2::{Digest, Sha256};
8use std::collections::HashMap;
9use uuid::Uuid;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct MemoryRecord {
14 pub id: Uuid,
16
17 pub content: String,
19
20 pub metadata: HashMap<String, serde_json::Value>,
22
23 pub user_id: Option<String>,
25
26 pub agent_id: Option<String>,
28
29 pub run_id: Option<String>,
31
32 pub hash: String,
34
35 pub created_at: DateTime<Utc>,
37
38 pub updated_at: DateTime<Utc>,
40}
41
42impl MemoryRecord {
43 pub fn new(content: impl Into<String>, metadata: serde_json::Value) -> Self {
45 let content = content.into();
46 let hash = Self::compute_hash(&content);
47 let now = Utc::now();
48
49 let metadata_map = match metadata {
50 serde_json::Value::Object(map) => map.into_iter().collect(),
51 _ => HashMap::new(),
52 };
53
54 Self {
55 id: Uuid::new_v4(),
56 content,
57 metadata: metadata_map,
58 user_id: None,
59 agent_id: None,
60 run_id: None,
61 hash,
62 created_at: now,
63 updated_at: now,
64 }
65 }
66
67 pub fn with_scoping(
69 content: impl Into<String>,
70 metadata: serde_json::Value,
71 user_id: Option<String>,
72 agent_id: Option<String>,
73 run_id: Option<String>,
74 ) -> Self {
75 let mut record = Self::new(content, metadata);
76 record.user_id = user_id;
77 record.agent_id = agent_id;
78 record.run_id = run_id;
79 record
80 }
81
82 fn compute_hash(content: &str) -> String {
84 let mut hasher = Sha256::new();
85 hasher.update(content.as_bytes());
86 hex::encode(hasher.finalize())
87 }
88
89 pub fn update_content(&mut self, content: impl Into<String>) {
91 self.content = content.into();
92 self.hash = Self::compute_hash(&self.content);
93 self.updated_at = Utc::now();
94 }
95}
96
97#[derive(Debug, Clone, Serialize, Deserialize)]
99pub struct ScoredMemory {
100 pub record: MemoryRecord,
102
103 pub score: f32,
105}
106
107#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
109#[serde(rename_all = "lowercase")]
110pub enum Role {
111 System,
113 User,
115 Assistant,
117}
118
119#[derive(Debug, Clone, Serialize, Deserialize)]
121pub struct Message {
122 pub role: Role,
124
125 pub content: String,
127
128 pub name: Option<String>,
130}
131
132impl Message {
133 pub fn user(content: impl Into<String>) -> Self {
135 Self {
136 role: Role::User,
137 content: content.into(),
138 name: None,
139 }
140 }
141
142 pub fn assistant(content: impl Into<String>) -> Self {
144 Self {
145 role: Role::Assistant,
146 content: content.into(),
147 name: None,
148 }
149 }
150
151 pub fn system(content: impl Into<String>) -> Self {
153 Self {
154 role: Role::System,
155 content: content.into(),
156 name: None,
157 }
158 }
159
160 pub fn with_name(mut self, name: impl Into<String>) -> Self {
162 self.name = Some(name.into());
163 self
164 }
165}
166
167#[derive(Debug, Clone)]
169pub enum Messages {
170 Text(String),
172 Single(Message),
174 Multiple(Vec<Message>),
176}
177
178impl From<&str> for Messages {
179 fn from(s: &str) -> Self {
180 Messages::Text(s.to_string())
181 }
182}
183
184impl From<String> for Messages {
185 fn from(s: String) -> Self {
186 Messages::Text(s)
187 }
188}
189
190impl From<Message> for Messages {
191 fn from(m: Message) -> Self {
192 Messages::Single(m)
193 }
194}
195
196impl From<Vec<Message>> for Messages {
197 fn from(v: Vec<Message>) -> Self {
198 Messages::Multiple(v)
199 }
200}
201
202impl Messages {
203 pub fn into_messages(self) -> Vec<Message> {
205 match self {
206 Messages::Text(s) => vec![Message::user(s)],
207 Messages::Single(m) => vec![m],
208 Messages::Multiple(v) => v,
209 }
210 }
211}
212
213#[derive(Debug, Clone, Default, Serialize, Deserialize)]
215pub struct AddOptions {
216 pub user_id: Option<String>,
218
219 pub agent_id: Option<String>,
221
222 pub run_id: Option<String>,
224
225 pub metadata: Option<HashMap<String, serde_json::Value>>,
227
228 pub infer: bool,
230}
231
232impl AddOptions {
233 pub fn for_user(user_id: impl Into<String>) -> Self {
235 Self {
236 user_id: Some(user_id.into()),
237 infer: true,
238 ..Default::default()
239 }
240 }
241
242 pub fn for_agent(agent_id: impl Into<String>) -> Self {
244 Self {
245 agent_id: Some(agent_id.into()),
246 infer: true,
247 ..Default::default()
248 }
249 }
250
251 pub fn raw(mut self) -> Self {
253 self.infer = false;
254 self
255 }
256}
257
258#[derive(Debug, Clone, Serialize, Deserialize)]
260pub struct AddResult {
261 pub results: Vec<MemoryEvent>,
263}
264
265#[derive(Debug, Clone, Serialize, Deserialize)]
267pub struct MemoryEvent {
268 pub id: Uuid,
270
271 pub memory: String,
273
274 pub event: EventType,
276}
277
278#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
280#[serde(rename_all = "UPPERCASE")]
281pub enum EventType {
282 Add,
284 Update,
286 Delete,
288 Noop,
290}
291
292#[derive(Debug, Clone, Default, Serialize, Deserialize)]
294pub struct SearchOptions {
295 pub user_id: Option<String>,
297
298 pub agent_id: Option<String>,
300
301 pub run_id: Option<String>,
303
304 pub limit: Option<usize>,
306
307 pub threshold: Option<f32>,
309
310 pub filters: Option<Filters>,
312
313 pub rerank: bool,
315}
316
317impl SearchOptions {
318 pub fn for_user(user_id: impl Into<String>) -> Self {
320 Self {
321 user_id: Some(user_id.into()),
322 limit: Some(10),
323 ..Default::default()
324 }
325 }
326
327 pub fn with_limit(mut self, limit: usize) -> Self {
329 self.limit = Some(limit);
330 self
331 }
332
333 pub fn with_threshold(mut self, threshold: f32) -> Self {
335 self.threshold = Some(threshold);
336 self
337 }
338}
339
340#[derive(Debug, Clone, Serialize, Deserialize)]
342pub struct SearchResult {
343 pub results: Vec<ScoredMemory>,
345}
346
347#[derive(Debug, Clone, Default, Serialize, Deserialize)]
349pub struct Filters {
350 pub conditions: Vec<FilterCondition>,
352
353 pub logic: FilterLogic,
355}
356
357#[derive(Debug, Clone, Serialize, Deserialize)]
359pub struct FilterCondition {
360 pub field: String,
362
363 pub operator: FilterOperator,
365
366 pub value: serde_json::Value,
368}
369
370#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
372#[serde(rename_all = "lowercase")]
373pub enum FilterOperator {
374 Eq,
376 Ne,
378 Gt,
380 Gte,
382 Lt,
384 Lte,
386 In,
388 Nin,
390 Contains,
392 IContains,
394}
395
396#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
398#[serde(rename_all = "UPPERCASE")]
399pub enum FilterLogic {
400 #[default]
401 And,
402 Or,
403}
404
405#[derive(Debug, Clone, Default, Serialize, Deserialize)]
407pub struct GetAllOptions {
408 pub user_id: Option<String>,
410
411 pub agent_id: Option<String>,
413
414 pub run_id: Option<String>,
416
417 pub limit: Option<usize>,
419}
420
421#[derive(Debug, Clone, Serialize, Deserialize)]
423pub struct HistoryEntry {
424 pub id: Uuid,
426
427 pub memory_id: Uuid,
429
430 pub previous_content: Option<String>,
432
433 pub new_content: String,
435
436 pub event: EventType,
438
439 pub timestamp: DateTime<Utc>,
441}
442
443#[derive(Debug, Clone, Default, Serialize, Deserialize)]
445pub struct ResetOptions {
446 pub user_id: Option<String>,
448
449 pub agent_id: Option<String>,
451}
452
453#[derive(Debug, Clone, Serialize, Deserialize)]
455pub struct Payload {
456 pub data: String,
458
459 pub hash: String,
461
462 pub created_at: DateTime<Utc>,
464
465 pub user_id: Option<String>,
467
468 pub agent_id: Option<String>,
470
471 pub run_id: Option<String>,
473
474 #[serde(flatten)]
476 pub metadata: HashMap<String, serde_json::Value>,
477}
478
479impl From<&MemoryRecord> for Payload {
480 fn from(record: &MemoryRecord) -> Self {
481 Self {
482 data: record.content.clone(),
483 hash: record.hash.clone(),
484 created_at: record.created_at,
485 user_id: record.user_id.clone(),
486 agent_id: record.agent_id.clone(),
487 run_id: record.run_id.clone(),
488 metadata: record.metadata.clone(),
489 }
490 }
491}