1use serde::{Deserialize, Serialize};
7
8use crate::error::Result;
9use crate::DakeraClient;
10
11#[derive(Debug, Clone, Serialize, Deserialize, Default)]
17pub enum MemoryType {
18 #[default]
19 Episodic,
20 Semantic,
21 Procedural,
22 Working,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct StoreMemoryRequest {
28 pub agent_id: String,
29 pub content: String,
30 #[serde(default)]
31 pub memory_type: MemoryType,
32 #[serde(default = "default_importance")]
33 pub importance: f32,
34 #[serde(default)]
35 pub tags: Vec<String>,
36 #[serde(skip_serializing_if = "Option::is_none")]
37 pub session_id: Option<String>,
38 #[serde(skip_serializing_if = "Option::is_none")]
39 pub metadata: Option<serde_json::Value>,
40}
41
42fn default_importance() -> f32 {
43 0.5
44}
45
46impl StoreMemoryRequest {
47 pub fn new(agent_id: impl Into<String>, content: impl Into<String>) -> Self {
49 Self {
50 agent_id: agent_id.into(),
51 content: content.into(),
52 memory_type: MemoryType::default(),
53 importance: 0.5,
54 tags: Vec::new(),
55 session_id: None,
56 metadata: None,
57 }
58 }
59
60 pub fn with_type(mut self, memory_type: MemoryType) -> Self {
62 self.memory_type = memory_type;
63 self
64 }
65
66 pub fn with_importance(mut self, importance: f32) -> Self {
68 self.importance = importance.clamp(0.0, 1.0);
69 self
70 }
71
72 pub fn with_tags(mut self, tags: Vec<String>) -> Self {
74 self.tags = tags;
75 self
76 }
77
78 pub fn with_session(mut self, session_id: impl Into<String>) -> Self {
80 self.session_id = Some(session_id.into());
81 self
82 }
83
84 pub fn with_metadata(mut self, metadata: serde_json::Value) -> Self {
86 self.metadata = Some(metadata);
87 self
88 }
89}
90
91#[derive(Debug, Clone, Serialize, Deserialize)]
93pub struct StoreMemoryResponse {
94 pub memory_id: String,
95 pub agent_id: String,
96 pub namespace: String,
97}
98
99#[derive(Debug, Clone, Serialize, Deserialize)]
101pub struct RecallRequest {
102 pub agent_id: String,
103 pub query: String,
104 #[serde(default = "default_top_k")]
105 pub top_k: usize,
106 #[serde(skip_serializing_if = "Option::is_none")]
107 pub memory_type: Option<MemoryType>,
108 #[serde(default)]
109 pub min_importance: f32,
110 #[serde(skip_serializing_if = "Option::is_none")]
111 pub session_id: Option<String>,
112 #[serde(default)]
113 pub tags: Vec<String>,
114}
115
116fn default_top_k() -> usize {
117 5
118}
119
120impl RecallRequest {
121 pub fn new(agent_id: impl Into<String>, query: impl Into<String>) -> Self {
123 Self {
124 agent_id: agent_id.into(),
125 query: query.into(),
126 top_k: 5,
127 memory_type: None,
128 min_importance: 0.0,
129 session_id: None,
130 tags: Vec::new(),
131 }
132 }
133
134 pub fn with_top_k(mut self, top_k: usize) -> Self {
136 self.top_k = top_k;
137 self
138 }
139
140 pub fn with_type(mut self, memory_type: MemoryType) -> Self {
142 self.memory_type = Some(memory_type);
143 self
144 }
145
146 pub fn with_min_importance(mut self, min: f32) -> Self {
148 self.min_importance = min;
149 self
150 }
151
152 pub fn with_session(mut self, session_id: impl Into<String>) -> Self {
154 self.session_id = Some(session_id.into());
155 self
156 }
157
158 pub fn with_tags(mut self, tags: Vec<String>) -> Self {
160 self.tags = tags;
161 self
162 }
163}
164
165#[derive(Debug, Clone, Serialize, Deserialize)]
167pub struct RecalledMemory {
168 pub id: String,
169 pub content: String,
170 pub memory_type: MemoryType,
171 pub importance: f32,
172 pub score: f32,
173 #[serde(default)]
174 pub tags: Vec<String>,
175 #[serde(skip_serializing_if = "Option::is_none")]
176 pub session_id: Option<String>,
177 #[serde(skip_serializing_if = "Option::is_none")]
178 pub metadata: Option<serde_json::Value>,
179 pub created_at: u64,
180 pub last_accessed_at: u64,
181 pub access_count: u32,
182}
183
184#[derive(Debug, Clone, Serialize, Deserialize)]
186pub struct RecallResponse {
187 pub memories: Vec<RecalledMemory>,
188 pub total_found: usize,
189}
190
191#[derive(Debug, Clone, Serialize, Deserialize)]
193pub struct ForgetRequest {
194 pub agent_id: String,
195 #[serde(default)]
196 pub memory_ids: Vec<String>,
197 #[serde(default)]
198 pub tags: Vec<String>,
199 #[serde(skip_serializing_if = "Option::is_none")]
200 pub session_id: Option<String>,
201 #[serde(skip_serializing_if = "Option::is_none")]
202 pub before_timestamp: Option<u64>,
203}
204
205impl ForgetRequest {
206 pub fn by_ids(agent_id: impl Into<String>, ids: Vec<String>) -> Self {
208 Self {
209 agent_id: agent_id.into(),
210 memory_ids: ids,
211 tags: Vec::new(),
212 session_id: None,
213 before_timestamp: None,
214 }
215 }
216
217 pub fn by_tags(agent_id: impl Into<String>, tags: Vec<String>) -> Self {
219 Self {
220 agent_id: agent_id.into(),
221 memory_ids: Vec::new(),
222 tags,
223 session_id: None,
224 before_timestamp: None,
225 }
226 }
227
228 pub fn by_session(agent_id: impl Into<String>, session_id: impl Into<String>) -> Self {
230 Self {
231 agent_id: agent_id.into(),
232 memory_ids: Vec::new(),
233 tags: Vec::new(),
234 session_id: Some(session_id.into()),
235 before_timestamp: None,
236 }
237 }
238}
239
240#[derive(Debug, Clone, Serialize, Deserialize)]
242pub struct ForgetResponse {
243 pub deleted_count: u64,
244}
245
246#[derive(Debug, Clone, Serialize, Deserialize)]
248pub struct SessionStartRequest {
249 pub agent_id: String,
250 #[serde(skip_serializing_if = "Option::is_none")]
251 pub metadata: Option<serde_json::Value>,
252}
253
254#[derive(Debug, Clone, Serialize, Deserialize)]
256pub struct Session {
257 pub id: String,
258 pub agent_id: String,
259 pub started_at: u64,
260 #[serde(skip_serializing_if = "Option::is_none")]
261 pub ended_at: Option<u64>,
262 #[serde(skip_serializing_if = "Option::is_none")]
263 pub summary: Option<String>,
264 #[serde(skip_serializing_if = "Option::is_none")]
265 pub metadata: Option<serde_json::Value>,
266}
267
268#[derive(Debug, Clone, Serialize, Deserialize)]
270pub struct SessionEndRequest {
271 #[serde(skip_serializing_if = "Option::is_none")]
272 pub summary: Option<String>,
273}
274
275#[derive(Debug, Clone, Serialize, Deserialize)]
277pub struct UpdateMemoryRequest {
278 #[serde(skip_serializing_if = "Option::is_none")]
279 pub content: Option<String>,
280 #[serde(skip_serializing_if = "Option::is_none")]
281 pub metadata: Option<serde_json::Value>,
282 #[serde(skip_serializing_if = "Option::is_none")]
283 pub memory_type: Option<MemoryType>,
284}
285
286#[derive(Debug, Clone, Serialize, Deserialize)]
288pub struct UpdateImportanceRequest {
289 pub memory_ids: Vec<String>,
290 pub importance: f32,
291}
292
293#[derive(Debug, Clone, Serialize, Deserialize)]
295pub struct ConsolidateRequest {
296 #[serde(skip_serializing_if = "Option::is_none")]
297 pub memory_type: Option<String>,
298 #[serde(skip_serializing_if = "Option::is_none")]
299 pub threshold: Option<f32>,
300 #[serde(default)]
301 pub dry_run: bool,
302}
303
304#[derive(Debug, Clone, Serialize, Deserialize)]
306pub struct ConsolidateResponse {
307 pub consolidated_count: usize,
308 pub removed_count: usize,
309 pub new_memories: Vec<String>,
310}
311
312#[derive(Debug, Clone, Serialize, Deserialize)]
314pub struct FeedbackRequest {
315 pub memory_id: String,
316 pub feedback: String,
317 #[serde(skip_serializing_if = "Option::is_none")]
318 pub relevance_score: Option<f32>,
319}
320
321#[derive(Debug, Clone, Serialize, Deserialize)]
323pub struct FeedbackResponse {
324 pub status: String,
325 pub updated_importance: Option<f32>,
326}
327
328impl DakeraClient {
333 pub async fn store_memory(&self, request: StoreMemoryRequest) -> Result<StoreMemoryResponse> {
357 let url = format!("{}/v1/memory/store", self.base_url);
358 let response = self.client.post(&url).json(&request).send().await?;
359 self.handle_response(response).await
360 }
361
362 pub async fn recall(&self, request: RecallRequest) -> Result<RecallResponse> {
383 let url = format!("{}/v1/memory/recall", self.base_url);
384 let response = self.client.post(&url).json(&request).send().await?;
385 self.handle_response(response).await
386 }
387
388 pub async fn recall_simple(
390 &self,
391 agent_id: &str,
392 query: &str,
393 top_k: usize,
394 ) -> Result<RecallResponse> {
395 self.recall(RecallRequest::new(agent_id, query).with_top_k(top_k))
396 .await
397 }
398
399 pub async fn get_memory(&self, memory_id: &str) -> Result<RecalledMemory> {
401 let url = format!("{}/v1/memory/get/{}", self.base_url, memory_id);
402 let response = self.client.get(&url).send().await?;
403 self.handle_response(response).await
404 }
405
406 pub async fn forget(&self, request: ForgetRequest) -> Result<ForgetResponse> {
408 let url = format!("{}/v1/memory/forget", self.base_url);
409 let response = self.client.post(&url).json(&request).send().await?;
410 self.handle_response(response).await
411 }
412
413 pub async fn search_memories(&self, request: RecallRequest) -> Result<RecallResponse> {
415 let url = format!("{}/v1/memory/search", self.base_url);
416 let response = self.client.post(&url).json(&request).send().await?;
417 self.handle_response(response).await
418 }
419
420 pub async fn update_memory(
422 &self,
423 agent_id: &str,
424 memory_id: &str,
425 request: UpdateMemoryRequest,
426 ) -> Result<StoreMemoryResponse> {
427 let url = format!(
428 "{}/v1/agents/{}/memories/{}",
429 self.base_url, agent_id, memory_id
430 );
431 let response = self.client.put(&url).json(&request).send().await?;
432 self.handle_response(response).await
433 }
434
435 pub async fn update_importance(
437 &self,
438 agent_id: &str,
439 request: UpdateImportanceRequest,
440 ) -> Result<serde_json::Value> {
441 let url = format!(
442 "{}/v1/agents/{}/memories/importance",
443 self.base_url, agent_id
444 );
445 let response = self.client.put(&url).json(&request).send().await?;
446 self.handle_response(response).await
447 }
448
449 pub async fn consolidate(
451 &self,
452 agent_id: &str,
453 request: ConsolidateRequest,
454 ) -> Result<ConsolidateResponse> {
455 let url = format!(
456 "{}/v1/agents/{}/memories/consolidate",
457 self.base_url, agent_id
458 );
459 let response = self.client.post(&url).json(&request).send().await?;
460 self.handle_response(response).await
461 }
462
463 pub async fn memory_feedback(
465 &self,
466 agent_id: &str,
467 request: FeedbackRequest,
468 ) -> Result<FeedbackResponse> {
469 let url = format!("{}/v1/agents/{}/memories/feedback", self.base_url, agent_id);
470 let response = self.client.post(&url).json(&request).send().await?;
471 self.handle_response(response).await
472 }
473
474 pub async fn start_session(&self, agent_id: &str) -> Result<Session> {
480 let url = format!("{}/v1/sessions/start", self.base_url);
481 let request = SessionStartRequest {
482 agent_id: agent_id.to_string(),
483 metadata: None,
484 };
485 let response = self.client.post(&url).json(&request).send().await?;
486 self.handle_response(response).await
487 }
488
489 pub async fn start_session_with_metadata(
491 &self,
492 agent_id: &str,
493 metadata: serde_json::Value,
494 ) -> Result<Session> {
495 let url = format!("{}/v1/sessions/start", self.base_url);
496 let request = SessionStartRequest {
497 agent_id: agent_id.to_string(),
498 metadata: Some(metadata),
499 };
500 let response = self.client.post(&url).json(&request).send().await?;
501 self.handle_response(response).await
502 }
503
504 pub async fn end_session(&self, session_id: &str, summary: Option<String>) -> Result<Session> {
506 let url = format!("{}/v1/sessions/{}/end", self.base_url, session_id);
507 let request = SessionEndRequest { summary };
508 let response = self.client.post(&url).json(&request).send().await?;
509 self.handle_response(response).await
510 }
511
512 pub async fn get_session(&self, session_id: &str) -> Result<Session> {
514 let url = format!("{}/v1/sessions/{}", self.base_url, session_id);
515 let response = self.client.get(&url).send().await?;
516 self.handle_response(response).await
517 }
518
519 pub async fn list_sessions(&self, agent_id: &str) -> Result<Vec<Session>> {
521 let url = format!("{}/v1/sessions?agent_id={}", self.base_url, agent_id);
522 let response = self.client.get(&url).send().await?;
523 self.handle_response(response).await
524 }
525
526 pub async fn session_memories(&self, session_id: &str) -> Result<RecallResponse> {
528 let url = format!("{}/v1/sessions/{}/memories", self.base_url, session_id);
529 let response = self.client.get(&url).send().await?;
530 self.handle_response(response).await
531 }
532}