1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct Memory {
12 pub id: Uuid,
13 pub content: String,
14 pub content_hash: String, pub tags: Vec<String>,
17 pub context: String, pub summary: String, pub chunk_index: Option<i32>, pub total_chunks: Option<i32>, pub parent_id: Option<Uuid>, pub created_at: DateTime<Utc>,
23 pub updated_at: DateTime<Utc>,
24}
25
26impl Memory {
27 pub fn new(
30 content: String,
31 context: String,
32 summary: String,
33 tags: Option<Vec<String>>,
34 ) -> Self {
35 use sha2::{Digest, Sha256};
36
37 let mut content_hasher = Sha256::new();
39 content_hasher.update(content.as_bytes());
40 let content_hash = hex::encode(content_hasher.finalize());
41
42 let now = Utc::now();
43 Self {
44 id: Uuid::new_v4(),
45 content,
46 content_hash,
47 tags: tags.unwrap_or_default(),
48 context,
49 summary,
50 chunk_index: None,
51 total_chunks: None,
52 parent_id: None,
53 created_at: now,
54 updated_at: now,
55 }
56 }
57
58 pub fn new_chunk(
61 content: String,
62 context: String,
63 summary: String,
64 tags: Option<Vec<String>>,
65 chunk_index: i32,
66 total_chunks: i32,
67 parent_id: Uuid,
68 ) -> Self {
69 use sha2::{Digest, Sha256};
70
71 let mut content_hasher = Sha256::new();
73 content_hasher.update(content.as_bytes());
74 let content_hash = hex::encode(content_hasher.finalize());
75
76 let now = Utc::now();
77 Self {
78 id: Uuid::new_v4(),
79 content,
80 content_hash,
81 tags: tags.unwrap_or_default(),
82 context,
83 summary,
84 chunk_index: Some(chunk_index),
85 total_chunks: Some(total_chunks),
86 parent_id: Some(parent_id),
87 created_at: now,
88 updated_at: now,
89 }
90 }
91
92 pub fn is_semantically_similar(&self, other: &Memory, similarity_threshold: f64) -> bool {
99 let content_similarity = self.simple_text_similarity(&self.content, &other.content);
102 let context_similarity = self.simple_text_similarity(&self.context, &other.context);
103
104 let combined_similarity = (content_similarity * 0.6) + (context_similarity * 0.4);
106 combined_similarity >= similarity_threshold
107 }
108
109 fn simple_text_similarity(&self, text1: &str, text2: &str) -> f64 {
112 use std::collections::HashSet;
113
114 let words1: HashSet<&str> = text1.split_whitespace().collect();
115 let words2: HashSet<&str> = text2.split_whitespace().collect();
116
117 let intersection = words1.intersection(&words2).count();
118 let union = words1.union(&words2).count();
119
120 if union == 0 {
121 0.0
122 } else {
123 intersection as f64 / union as f64
124 }
125 }
126}
127
128#[derive(Debug, Serialize, Deserialize)]
130pub struct StorageStats {
131 pub total_memories: i64,
132 pub table_size: String,
133 pub last_memory_created: Option<DateTime<Utc>>,
134}