1use std::sync::Arc;
20
21use async_trait::async_trait;
22use chrono::Utc;
23
24use crate::{MemoryService, SearchRequest};
25
26pub struct MemoryServiceAdapter {
31 inner: Arc<dyn MemoryService>,
32 app_name: String,
33 user_id: String,
34 project_id: Option<String>,
35}
36
37impl MemoryServiceAdapter {
38 pub fn new(
40 inner: Arc<dyn MemoryService>,
41 app_name: impl Into<String>,
42 user_id: impl Into<String>,
43 ) -> Self {
44 Self { inner, app_name: app_name.into(), user_id: user_id.into(), project_id: None }
45 }
46
47 pub fn with_project_id(mut self, project_id: impl Into<String>) -> Self {
52 self.project_id = Some(project_id.into());
53 self
54 }
55}
56
57#[async_trait]
58impl adk_core::Memory for MemoryServiceAdapter {
59 async fn search(&self, query: &str) -> adk_core::Result<Vec<adk_core::MemoryEntry>> {
60 let inner = self.inner.clone();
61 let resp = inner
62 .search(SearchRequest {
63 query: query.to_string(),
64 app_name: self.app_name.clone(),
65 user_id: self.user_id.clone(),
66 limit: None,
67 min_score: None,
68 project_id: self.project_id.clone(),
69 })
70 .await?;
71
72 Ok(resp
73 .memories
74 .into_iter()
75 .map(|m| adk_core::MemoryEntry { content: m.content, author: m.author })
76 .collect())
77 }
78
79 async fn add(&self, entry: adk_core::MemoryEntry) -> adk_core::Result<()> {
80 let inner = self.inner.clone();
81 let mem_entry = crate::MemoryEntry {
82 content: entry.content,
83 author: entry.author,
84 timestamp: Utc::now(),
85 };
86 if let Some(ref pid) = self.project_id {
87 inner.add_entry_to_project(&self.app_name, &self.user_id, pid, mem_entry).await
88 } else {
89 inner.add_entry(&self.app_name, &self.user_id, mem_entry).await
90 }
91 }
92
93 async fn delete(&self, query: &str) -> adk_core::Result<u64> {
94 let inner = self.inner.clone();
95 if let Some(ref pid) = self.project_id {
96 inner.delete_entries_in_project(&self.app_name, &self.user_id, pid, query).await
97 } else {
98 inner.delete_entries(&self.app_name, &self.user_id, query).await
99 }
100 }
101
102 async fn health_check(&self) -> adk_core::Result<()> {
103 let inner = self.inner.clone();
104 inner.health_check().await
105 }
106
107 async fn search_in_project(
108 &self,
109 query: &str,
110 project_id: &str,
111 ) -> adk_core::Result<Vec<adk_core::MemoryEntry>> {
112 let inner = self.inner.clone();
113 let resp = inner
114 .search(SearchRequest {
115 query: query.to_string(),
116 app_name: self.app_name.clone(),
117 user_id: self.user_id.clone(),
118 limit: None,
119 min_score: None,
120 project_id: Some(project_id.to_string()),
121 })
122 .await?;
123
124 Ok(resp
125 .memories
126 .into_iter()
127 .map(|m| adk_core::MemoryEntry { content: m.content, author: m.author })
128 .collect())
129 }
130
131 async fn add_to_project(
132 &self,
133 entry: adk_core::MemoryEntry,
134 project_id: &str,
135 ) -> adk_core::Result<()> {
136 let inner = self.inner.clone();
137 let mem_entry = crate::MemoryEntry {
138 content: entry.content,
139 author: entry.author,
140 timestamp: Utc::now(),
141 };
142 inner.add_entry_to_project(&self.app_name, &self.user_id, project_id, mem_entry).await
143 }
144}