1use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct Message {
9 pub role: String,
10 pub content: String,
11}
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct ApiAddRequest {
16 pub user_id: String,
17 #[serde(default)]
18 pub session_id: Option<String>,
19 #[serde(default)]
20 pub task_id: Option<String>,
21 #[serde(default)]
22 pub writable_cube_ids: Option<Vec<String>>,
23 #[serde(default)]
24 pub mem_cube_id: Option<String>,
25 #[serde(default = "default_async_mode")]
26 pub async_mode: String,
27 #[serde(default)]
28 pub messages: Option<Vec<Message>>,
29 #[serde(default)]
30 pub memory_content: Option<String>,
31 #[serde(default)]
32 pub chat_history: Option<Vec<Message>>,
33 #[serde(default)]
34 pub custom_tags: Option<Vec<String>>,
35 #[serde(default)]
36 pub info: Option<HashMap<String, serde_json::Value>>,
37 #[serde(default)]
39 pub relations: Option<Vec<AddMemoryRelation>>,
40 #[serde(default)]
41 pub is_feedback: bool,
42}
43
44fn default_async_mode() -> String {
45 "sync".to_string()
46}
47
48impl ApiAddRequest {
49 pub fn writable_cube_ids(&self) -> Vec<String> {
51 if let Some(ref ids) = self.writable_cube_ids {
52 if !ids.is_empty() {
53 return ids.clone();
54 }
55 }
56 if let Some(ref id) = self.mem_cube_id {
57 return vec![id.clone()];
58 }
59 vec![self.user_id.clone()]
60 }
61
62 pub fn content_to_store(&self) -> Option<String> {
64 if let Some(ref msgs) = self.messages {
65 if !msgs.is_empty() {
66 let parts: Vec<String> = msgs
67 .iter()
68 .map(|m| format!("{}: {}", m.role, m.content))
69 .collect();
70 return Some(parts.join("\n"));
71 }
72 }
73 self.memory_content.clone()
74 }
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
79pub struct ApiSearchRequest {
80 pub query: String,
81 pub user_id: String,
82 #[serde(default)]
83 pub readable_cube_ids: Option<Vec<String>>,
84 #[serde(default)]
85 pub mem_cube_id: Option<String>,
86 #[serde(default = "default_top_k")]
87 pub top_k: u32,
88 #[serde(default)]
89 pub session_id: Option<String>,
90 #[serde(default)]
91 pub relativity: f64,
92 #[serde(default)]
93 pub include_preference: bool,
94 #[serde(default)]
95 pub pref_top_k: u32,
96 #[serde(default)]
97 pub filter: Option<HashMap<String, serde_json::Value>>,
98}
99
100fn default_top_k() -> u32 {
101 10
102}
103
104impl ApiSearchRequest {
105 pub fn readable_cube_ids(&self) -> Vec<String> {
107 if let Some(ref ids) = self.readable_cube_ids {
108 if !ids.is_empty() {
109 return ids.clone();
110 }
111 }
112 if let Some(ref id) = self.mem_cube_id {
113 return vec![id.clone()];
114 }
115 vec![self.user_id.clone()]
116 }
117}
118
119#[derive(Debug, Clone, Serialize, Deserialize)]
121pub struct BaseResponse<T> {
122 #[serde(default = "default_code")]
123 pub code: i32,
124 pub message: String,
125 #[serde(default)]
126 pub data: Option<T>,
127}
128
129fn default_code() -> i32 {
130 200
131}
132
133pub type MemoryResponse = BaseResponse<Vec<serde_json::Value>>;
135
136#[derive(Debug, Clone, Serialize, Deserialize)]
138pub struct MemoryItem {
139 pub id: String,
140 pub memory: String,
141 #[serde(default)]
142 pub metadata: HashMap<String, serde_json::Value>,
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct MemoryBucket {
148 #[serde(skip_serializing_if = "Option::is_none")]
149 pub name: Option<String>,
150 pub memories: Vec<MemoryItem>,
151 #[serde(skip_serializing_if = "Option::is_none")]
152 pub total_nodes: Option<usize>,
153}
154
155#[derive(Debug, Clone, Default, Serialize, Deserialize)]
157pub struct SearchResponseData {
158 #[serde(default)]
159 pub text_mem: Vec<MemoryBucket>,
160 #[serde(default)]
161 pub pref_mem: Vec<MemoryBucket>,
162}
163
164#[derive(Debug, Clone, Serialize, Deserialize)]
166pub struct SearchResponse {
167 #[serde(default = "default_code")]
168 pub code: i32,
169 pub message: String,
170 #[serde(default)]
171 pub data: Option<SearchResponseData>,
172}
173
174#[derive(Debug, Clone, Serialize, Deserialize)]
176pub struct UpdateMemoryRequest {
177 pub memory_id: String,
178 pub user_id: String,
179 #[serde(default)]
180 pub mem_cube_id: Option<String>,
181 #[serde(skip_serializing_if = "Option::is_none")]
182 pub memory: Option<String>,
183 #[serde(default)]
184 pub metadata: Option<HashMap<String, serde_json::Value>>,
185}
186
187#[derive(Debug, Clone, Serialize, Deserialize)]
189pub struct ForgetMemoryRequest {
190 pub memory_id: String,
191 pub user_id: String,
192 #[serde(default)]
193 pub mem_cube_id: Option<String>,
194 #[serde(default)]
196 pub soft: bool,
197}
198
199pub type UpdateMemoryResponse = BaseResponse<Vec<serde_json::Value>>;
201pub type ForgetMemoryResponse = BaseResponse<Vec<serde_json::Value>>;
202
203#[derive(Debug, Clone, Serialize, Deserialize)]
205pub struct AddMemoryRelation {
206 pub memory_id: String,
208 pub relation: String,
209 #[serde(default)]
212 pub direction: GraphDirection,
213 #[serde(default)]
214 pub metadata: HashMap<String, serde_json::Value>,
215}
216
217#[derive(Debug, Clone, Serialize, Deserialize)]
219pub struct GetMemoryRequest {
220 pub memory_id: String,
221 pub user_id: String,
222 #[serde(default)]
223 pub mem_cube_id: Option<String>,
224 #[serde(default)]
226 pub include_deleted: bool,
227}
228
229#[derive(Debug, Clone, Serialize, Deserialize)]
231pub struct GetMemoryResponse {
232 #[serde(default = "default_code")]
233 pub code: i32,
234 pub message: String,
235 #[serde(default)]
236 pub data: Option<MemoryItem>,
237}
238
239#[derive(Debug, Clone)]
241pub struct MemoryNode {
242 pub id: String,
243 pub memory: String,
244 pub metadata: HashMap<String, serde_json::Value>,
245 pub embedding: Option<Vec<f32>>,
246}
247
248#[derive(Debug, Clone, Serialize, Deserialize)]
250pub struct MemoryEdge {
251 pub id: String,
252 pub from: String,
253 pub to: String,
254 pub relation: String,
255 #[serde(default)]
256 pub metadata: HashMap<String, serde_json::Value>,
257}
258
259#[derive(Debug, Clone)]
261pub struct GraphNeighbor {
262 pub edge: MemoryEdge,
263 pub node: MemoryNode,
264}
265
266#[derive(Debug, Clone, Serialize, Deserialize)]
268pub struct GraphNeighborsRequest {
269 pub memory_id: String,
270 pub user_id: String,
271 #[serde(default)]
272 pub mem_cube_id: Option<String>,
273 #[serde(default)]
274 pub relation: Option<String>,
275 #[serde(default)]
276 pub direction: GraphDirection,
277 #[serde(default = "default_graph_limit")]
278 pub limit: u32,
279 #[serde(default)]
281 pub cursor: Option<String>,
282 #[serde(default)]
283 pub include_embedding: bool,
284 #[serde(default)]
285 pub include_deleted: bool,
286}
287
288fn default_graph_limit() -> u32 {
289 10
290}
291
292#[derive(Debug, Clone, Serialize, Deserialize)]
294pub struct GraphNeighborItem {
295 pub edge: MemoryEdge,
296 pub memory: MemoryItem,
297}
298
299#[derive(Debug, Clone, Serialize, Deserialize)]
301pub struct GraphNeighborsData {
302 pub items: Vec<GraphNeighborItem>,
303 #[serde(skip_serializing_if = "Option::is_none")]
304 pub next_cursor: Option<String>,
305}
306
307pub type GraphNeighborsResponse = BaseResponse<GraphNeighborsData>;
309
310#[derive(Debug, Clone)]
312pub struct GraphPath {
313 pub node_ids: Vec<String>,
314 pub edges: Vec<MemoryEdge>,
315}
316
317#[derive(Debug, Clone, Serialize, Deserialize)]
319pub struct GraphPathRequest {
320 pub source_memory_id: String,
321 pub target_memory_id: String,
322 pub user_id: String,
323 #[serde(default)]
324 pub mem_cube_id: Option<String>,
325 #[serde(default)]
326 pub relation: Option<String>,
327 #[serde(default)]
328 pub direction: GraphDirection,
329 #[serde(default = "default_graph_max_depth")]
330 pub max_depth: u32,
331 #[serde(default)]
332 pub include_deleted: bool,
333}
334
335fn default_graph_max_depth() -> u32 {
336 6
337}
338
339#[derive(Debug, Clone, Serialize, Deserialize)]
341pub struct GraphPathData {
342 pub hops: u32,
343 pub nodes: Vec<MemoryItem>,
344 pub edges: Vec<MemoryEdge>,
345}
346
347pub type GraphPathResponse = BaseResponse<GraphPathData>;
349
350#[derive(Debug, Clone, Serialize, Deserialize)]
352pub struct GraphPathsRequest {
353 pub source_memory_id: String,
354 pub target_memory_id: String,
355 pub user_id: String,
356 #[serde(default)]
357 pub mem_cube_id: Option<String>,
358 #[serde(default)]
359 pub relation: Option<String>,
360 #[serde(default)]
361 pub direction: GraphDirection,
362 #[serde(default = "default_graph_max_depth")]
363 pub max_depth: u32,
364 #[serde(default = "default_graph_top_k_paths")]
365 pub top_k_paths: u32,
366 #[serde(default)]
367 pub include_deleted: bool,
368}
369
370fn default_graph_top_k_paths() -> u32 {
371 3
372}
373
374pub type GraphPathsResponse = BaseResponse<Vec<GraphPathData>>;
376
377#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
379#[serde(rename_all = "snake_case")]
380pub enum GraphDirection {
381 Outbound,
382 Inbound,
383 Both,
384}
385
386impl Default for GraphDirection {
387 fn default() -> Self {
388 Self::Outbound
389 }
390}
391
392#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
394pub enum MemoryScope {
395 WorkingMemory,
396 LongTermMemory,
397 UserMemory,
398}
399
400impl MemoryScope {
401 pub fn as_str(self) -> &'static str {
402 match self {
403 MemoryScope::WorkingMemory => "WorkingMemory",
404 MemoryScope::LongTermMemory => "LongTermMemory",
405 MemoryScope::UserMemory => "UserMemory",
406 }
407 }
408}
409
410impl std::fmt::Display for MemoryScope {
411 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
412 f.write_str(self.as_str())
413 }
414}