1use async_trait::async_trait;
4use serde_json::Value;
5
6#[derive(Debug, Clone)]
8pub struct MemoryEntry {
9 pub key: String,
10 pub value: String,
11 pub metadata: Option<Value>,
12 pub created_at: chrono::DateTime<chrono::Utc>,
13}
14
15#[derive(Debug, Clone)]
17pub struct EmbeddingEntry {
18 pub namespace: String,
19 pub key: String,
20 pub vector: Vec<f32>,
21 pub text: String,
22 pub created_at: chrono::DateTime<chrono::Utc>,
23}
24
25#[derive(Debug, Clone)]
27pub struct FileIndex {
28 pub path: String,
29 pub hash: String,
30 pub last_indexed: chrono::DateTime<chrono::Utc>,
31}
32
33#[derive(Debug, Clone)]
35pub struct Chunk {
36 pub file_path: String,
37 pub start_line: u32,
38 pub end_line: u32,
39 pub content: String,
40 pub embedding: Option<Vec<f32>>,
41 pub created_at: chrono::DateTime<chrono::Utc>,
42}
43
44#[derive(Debug, Clone)]
45pub struct ConversationSearchHit {
46 pub chat_id: String,
47 pub role: String,
48 pub content: String,
49 pub created_at: chrono::DateTime<chrono::Utc>,
50}
51
52#[async_trait]
54pub trait MemoryBackend: Send + Sync {
55 fn as_any(&self) -> &dyn std::any::Any;
57
58 async fn store(
60 &self,
61 namespace: &str,
62 key: &str,
63 value: &str,
64 metadata: Option<Value>,
65 ) -> anyhow::Result<()>;
66
67 async fn recall(&self, namespace: &str, key: &str) -> anyhow::Result<Option<MemoryEntry>>;
69
70 async fn search(
72 &self,
73 namespace: &str,
74 query: &str,
75 limit: usize,
76 ) -> anyhow::Result<Vec<MemoryEntry>>;
77
78 async fn forget(&self, namespace: &str, key: &str) -> anyhow::Result<()>;
80
81 async fn list(&self, namespace: &str) -> anyhow::Result<Vec<MemoryEntry>>;
83
84 async fn store_conversation(
86 &self,
87 chat_id: &str,
88 sender_id: &str,
89 role: &str,
90 content: &str,
91 ) -> anyhow::Result<()>;
92
93 async fn store_conversation_batch(
95 &self,
96 entries: &[(&str, &str, &str, &str)],
97 ) -> anyhow::Result<()> {
98 for (chat_id, sender_id, role, content) in entries {
99 self.store_conversation(chat_id, sender_id, role, content)
100 .await?;
101 }
102 Ok(())
103 }
104
105 async fn get_conversation_history(
107 &self,
108 chat_id: &str,
109 limit: usize,
110 ) -> anyhow::Result<Vec<(String, String)>>;
111
112 async fn search_conversations(
113 &self,
114 query: &str,
115 limit: usize,
116 chat_id: Option<&str>,
117 ) -> anyhow::Result<Vec<ConversationSearchHit>> {
118 let _ = (query, limit, chat_id);
119 Ok(Vec::new())
120 }
121
122 async fn get_sticker_cache(&self, sticker_id: &str) -> anyhow::Result<Option<String>>;
124
125 async fn store_sticker_cache(
127 &self,
128 sticker_id: &str,
129 file_id: &str,
130 description: &str,
131 ) -> anyhow::Result<()>;
132
133 async fn store_embedding(
137 &self,
138 namespace: &str,
139 key: &str,
140 vector: &[f32],
141 text: &str,
142 ) -> anyhow::Result<()> {
143 let _ = (namespace, key, vector, text);
144 Ok(())
145 }
146
147 async fn search_embeddings(
149 &self,
150 namespace: &str,
151 query_vector: &[f32],
152 limit: usize,
153 ) -> anyhow::Result<Vec<EmbeddingEntry>> {
154 let _ = (namespace, query_vector, limit);
155 Ok(Vec::new())
156 }
157
158 async fn store_file_index(&self, path: &str, hash: &str) -> anyhow::Result<()> {
162 let _ = (path, hash);
163 Ok(())
164 }
165
166 async fn get_file_index(&self, path: &str) -> anyhow::Result<Option<FileIndex>> {
168 let _ = path;
169 Ok(None)
170 }
171
172 async fn store_chunk(
176 &self,
177 file_path: &str,
178 start_line: u32,
179 end_line: u32,
180 content: &str,
181 embedding: Option<&[f32]>,
182 ) -> anyhow::Result<()> {
183 let _ = (file_path, start_line, end_line, content, embedding);
184 Ok(())
185 }
186
187 async fn get_chunks_for_file(&self, file_path: &str) -> anyhow::Result<Vec<Chunk>> {
189 let _ = file_path;
190 Ok(Vec::new())
191 }
192
193 async fn delete_chunks_for_file(&self, file_path: &str) -> anyhow::Result<()> {
195 let _ = file_path;
196 Ok(())
197 }
198}