Skip to main content

adk_memory/
adapter.rs

1//! Adapter bridging [`MemoryService`] to [`adk_core::Memory`].
2//!
3//! The runner expects `Arc<dyn adk_core::Memory>`, which has a simple
4//! `search(&str)` signature. [`MemoryService`] requires a [`SearchRequest`]
5//! with `app_name` and `user_id`. This adapter binds those fields at
6//! construction time so any `MemoryService` can be used as `adk_core::Memory`.
7//!
8//! # Example
9//!
10//! ```rust,ignore
11//! use adk_memory::{InMemoryMemoryService, MemoryServiceAdapter};
12//! use std::sync::Arc;
13//!
14//! let service = Arc::new(InMemoryMemoryService::new());
15//! let memory = Arc::new(MemoryServiceAdapter::new(service, "my-app", "user-1"));
16//! // memory implements adk_core::Memory and can be passed to RunnerConfig
17//! ```
18
19use std::sync::Arc;
20
21use async_trait::async_trait;
22use chrono::Utc;
23
24use crate::{MemoryService, SearchRequest};
25
26/// Adapts any [`MemoryService`] into an [`adk_core::Memory`] implementation.
27///
28/// Binds `app_name` and `user_id` at construction so the runner's
29/// `search(query: &str)` calls are forwarded with full context.
30pub struct MemoryServiceAdapter {
31    inner: Arc<dyn MemoryService>,
32    app_name: String,
33    user_id: String,
34}
35
36impl MemoryServiceAdapter {
37    /// Create a new adapter binding a memory service to a specific app and user.
38    pub fn new(
39        inner: Arc<dyn MemoryService>,
40        app_name: impl Into<String>,
41        user_id: impl Into<String>,
42    ) -> Self {
43        Self { inner, app_name: app_name.into(), user_id: user_id.into() }
44    }
45}
46
47#[async_trait]
48impl adk_core::Memory for MemoryServiceAdapter {
49    async fn search(&self, query: &str) -> adk_core::Result<Vec<adk_core::MemoryEntry>> {
50        let inner = self.inner.clone();
51        let resp = inner
52            .search(SearchRequest {
53                query: query.to_string(),
54                app_name: self.app_name.clone(),
55                user_id: self.user_id.clone(),
56                limit: None,
57                min_score: None,
58            })
59            .await?;
60
61        Ok(resp
62            .memories
63            .into_iter()
64            .map(|m| adk_core::MemoryEntry { content: m.content, author: m.author })
65            .collect())
66    }
67
68    async fn add(&self, entry: adk_core::MemoryEntry) -> adk_core::Result<()> {
69        let inner = self.inner.clone();
70        let mem_entry = crate::MemoryEntry {
71            content: entry.content,
72            author: entry.author,
73            timestamp: Utc::now(),
74        };
75        inner.add_entry(&self.app_name, &self.user_id, mem_entry).await
76    }
77
78    async fn delete(&self, query: &str) -> adk_core::Result<u64> {
79        let inner = self.inner.clone();
80        inner.delete_entries(&self.app_name, &self.user_id, query).await
81    }
82
83    async fn health_check(&self) -> adk_core::Result<()> {
84        let inner = self.inner.clone();
85        inner.health_check().await
86    }
87}