gemini_adk_rs/artifacts/
forwarding.rs

1//! Forwarding artifact service that proxies all calls to a parent service.
2
3use std::sync::Arc;
4
5use async_trait::async_trait;
6
7use super::{Artifact, ArtifactError, ArtifactMetadata, ArtifactService};
8
9/// Artifact service that proxies all calls to a parent service.
10/// Used by ToolContext to give tools scoped artifact access.
11pub struct ForwardingArtifactService {
12    inner: Arc<dyn ArtifactService>,
13}
14
15impl ForwardingArtifactService {
16    /// Create a new forwarding artifact service wrapping the given inner service.
17    pub fn new(inner: Arc<dyn ArtifactService>) -> Self {
18        Self { inner }
19    }
20}
21
22#[async_trait]
23impl ArtifactService for ForwardingArtifactService {
24    async fn save(
25        &self,
26        session_id: &str,
27        artifact: Artifact,
28    ) -> Result<ArtifactMetadata, ArtifactError> {
29        self.inner.save(session_id, artifact).await
30    }
31
32    async fn load(&self, session_id: &str, name: &str) -> Result<Option<Artifact>, ArtifactError> {
33        self.inner.load(session_id, name).await
34    }
35
36    async fn load_version(
37        &self,
38        session_id: &str,
39        name: &str,
40        version: u32,
41    ) -> Result<Option<Artifact>, ArtifactError> {
42        self.inner.load_version(session_id, name, version).await
43    }
44
45    async fn list(&self, session_id: &str) -> Result<Vec<ArtifactMetadata>, ArtifactError> {
46        self.inner.list(session_id).await
47    }
48
49    async fn delete(&self, session_id: &str, name: &str) -> Result<(), ArtifactError> {
50        self.inner.delete(session_id, name).await
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57    use crate::artifacts::InMemoryArtifactService;
58
59    #[tokio::test]
60    async fn forwarding_save_delegates() {
61        let inner = Arc::new(InMemoryArtifactService::new());
62        let fwd = ForwardingArtifactService::new(inner.clone());
63
64        let artifact = Artifact::text("notes", "hello");
65        let meta = fwd.save("s1", artifact).await.unwrap();
66        assert_eq!(meta.name, "notes");
67        assert_eq!(meta.version, 1);
68
69        // Verify the inner service actually received the artifact.
70        let loaded = inner.load("s1", "notes").await.unwrap().unwrap();
71        assert_eq!(std::str::from_utf8(&loaded.data).unwrap(), "hello");
72    }
73
74    #[tokio::test]
75    async fn forwarding_load_delegates() {
76        let inner = Arc::new(InMemoryArtifactService::new());
77        inner
78            .save("s1", Artifact::text("doc", "content"))
79            .await
80            .unwrap();
81
82        let fwd = ForwardingArtifactService::new(inner);
83        let loaded = fwd.load("s1", "doc").await.unwrap().unwrap();
84        assert_eq!(std::str::from_utf8(&loaded.data).unwrap(), "content");
85    }
86
87    #[tokio::test]
88    async fn forwarding_load_version_delegates() {
89        let inner = Arc::new(InMemoryArtifactService::new());
90        inner.save("s1", Artifact::text("doc", "v1")).await.unwrap();
91        inner.save("s1", Artifact::text("doc", "v2")).await.unwrap();
92
93        let fwd = ForwardingArtifactService::new(inner);
94        let v1 = fwd.load_version("s1", "doc", 1).await.unwrap().unwrap();
95        assert_eq!(std::str::from_utf8(&v1.data).unwrap(), "v1");
96        let v2 = fwd.load_version("s1", "doc", 2).await.unwrap().unwrap();
97        assert_eq!(std::str::from_utf8(&v2.data).unwrap(), "v2");
98    }
99
100    #[tokio::test]
101    async fn forwarding_list_delegates() {
102        let inner = Arc::new(InMemoryArtifactService::new());
103        inner.save("s1", Artifact::text("a", "data")).await.unwrap();
104        inner.save("s1", Artifact::text("b", "data")).await.unwrap();
105
106        let fwd = ForwardingArtifactService::new(inner);
107        let list = fwd.list("s1").await.unwrap();
108        assert_eq!(list.len(), 2);
109    }
110
111    #[tokio::test]
112    async fn forwarding_delete_delegates() {
113        let inner = Arc::new(InMemoryArtifactService::new());
114        inner
115            .save("s1", Artifact::text("notes", "data"))
116            .await
117            .unwrap();
118
119        let fwd = ForwardingArtifactService::new(inner.clone());
120        fwd.delete("s1", "notes").await.unwrap();
121
122        // Verify deletion happened in the inner service.
123        let result = inner.load("s1", "notes").await.unwrap();
124        assert!(result.is_none());
125    }
126}