1use adk_core::{Content, Result};
2use async_trait::async_trait;
3use chrono::{DateTime, Utc};
4
5#[derive(Debug, Clone)]
6pub struct MemoryEntry {
7 pub content: Content,
8 pub author: String,
9 pub timestamp: DateTime<Utc>,
10}
11
12#[derive(Debug, Clone, serde::Deserialize)]
13pub struct SearchRequest {
14 pub query: String,
15 pub user_id: String,
16 pub app_name: String,
17 pub limit: Option<usize>,
19 pub min_score: Option<f32>,
22 #[serde(default)]
25 pub project_id: Option<String>,
26}
27
28#[derive(Debug, Clone)]
29pub struct SearchResponse {
30 pub memories: Vec<MemoryEntry>,
31}
32
33pub fn validate_project_id(project_id: &str) -> Result<()> {
38 if project_id.is_empty() {
39 return Err(adk_core::AdkError::memory("project_id must not be empty"));
40 }
41 if project_id.len() > 256 {
42 return Err(adk_core::AdkError::memory(format!(
43 "project_id exceeds maximum length of 256 characters (got {})",
44 project_id.len()
45 )));
46 }
47 Ok(())
48}
49
50#[async_trait]
51pub trait MemoryService: Send + Sync {
52 async fn add_session(
53 &self,
54 app_name: &str,
55 user_id: &str,
56 session_id: &str,
57 entries: Vec<MemoryEntry>,
58 ) -> Result<()>;
59 async fn search(&self, req: SearchRequest) -> Result<SearchResponse>;
60
61 async fn delete_user(&self, app_name: &str, user_id: &str) -> Result<()> {
66 let _ = (app_name, user_id);
67 Err(adk_core::AdkError::memory("delete_user not implemented"))
68 }
69
70 async fn delete_session(&self, app_name: &str, user_id: &str, session_id: &str) -> Result<()> {
72 let _ = (app_name, user_id, session_id);
73 Err(adk_core::AdkError::memory("delete_session not implemented"))
74 }
75
76 async fn add_entry(&self, app_name: &str, user_id: &str, entry: MemoryEntry) -> Result<()> {
78 let _ = (app_name, user_id, entry);
79 Err(adk_core::AdkError::memory("add_entry not implemented"))
80 }
81
82 async fn delete_entries(&self, app_name: &str, user_id: &str, query: &str) -> Result<u64> {
84 let _ = (app_name, user_id, query);
85 Err(adk_core::AdkError::memory("delete_entries not implemented"))
86 }
87
88 async fn list_recent(
93 &self,
94 app_name: &str,
95 user_id: &str,
96 limit: usize,
97 ) -> Result<Vec<MemoryEntry>> {
98 let _ = (app_name, user_id, limit);
99 Err(adk_core::AdkError::memory("list_recent not implemented"))
100 }
101
102 async fn health_check(&self) -> Result<()> {
107 Ok(())
108 }
109
110 fn supports_project_scoping(&self) -> bool {
116 false
117 }
118
119 async fn add_session_to_project(
128 &self,
129 app_name: &str,
130 user_id: &str,
131 session_id: &str,
132 project_id: &str,
133 entries: Vec<MemoryEntry>,
134 ) -> Result<()> {
135 let _ = (app_name, user_id, session_id, project_id, entries);
136 Err(project_scoping_unsupported("add_session_to_project"))
137 }
138
139 async fn add_entry_to_project(
146 &self,
147 app_name: &str,
148 user_id: &str,
149 project_id: &str,
150 entry: MemoryEntry,
151 ) -> Result<()> {
152 let _ = (app_name, user_id, project_id, entry);
153 Err(project_scoping_unsupported("add_entry_to_project"))
154 }
155
156 async fn delete_entries_in_project(
163 &self,
164 app_name: &str,
165 user_id: &str,
166 project_id: &str,
167 query: &str,
168 ) -> Result<u64> {
169 let _ = (app_name, user_id, project_id, query);
170 Err(project_scoping_unsupported("delete_entries_in_project"))
171 }
172
173 async fn delete_project(&self, app_name: &str, user_id: &str, project_id: &str) -> Result<u64> {
176 let _ = (app_name, user_id, project_id);
177 Err(adk_core::AdkError::memory("delete_project not implemented"))
178 }
179}
180
181fn project_scoping_unsupported(method: &str) -> adk_core::AdkError {
183 adk_core::AdkError::memory(format!(
184 "this memory backend does not implement project scoping, so `{method}` cannot honour \
185 the project boundary; use a backend whose `supports_project_scoping` returns true, or \
186 call the global method explicitly if global scope is intended"
187 ))
188}