Skip to main content

zeroclaw_memory/
none.rs

1use super::traits::{Memory, MemoryCategory, MemoryEntry};
2use async_trait::async_trait;
3
4/// Explicit no-op memory backend.
5///
6/// This backend is used when `memory.backend = "none"` to disable persistence
7/// while keeping the runtime wiring stable.
8#[derive(Debug, Default, Clone)]
9pub struct NoneMemory {
10    alias: String,
11}
12
13impl NoneMemory {
14    pub fn new(alias: &str) -> Self {
15        Self {
16            alias: alias.to_string(),
17        }
18    }
19}
20
21impl ::zeroclaw_api::attribution::Attributable for NoneMemory {
22    fn role(&self) -> ::zeroclaw_api::attribution::Role {
23        ::zeroclaw_api::attribution::Role::Memory(::zeroclaw_api::attribution::MemoryKind::None)
24    }
25    fn alias(&self) -> &str {
26        &self.alias
27    }
28}
29
30#[async_trait]
31impl Memory for NoneMemory {
32    fn name(&self) -> &str {
33        "none"
34    }
35
36    async fn store(
37        &self,
38        _key: &str,
39        _content: &str,
40        _category: MemoryCategory,
41        _session_id: Option<&str>,
42    ) -> anyhow::Result<()> {
43        Ok(())
44    }
45
46    async fn recall(
47        &self,
48        _query: &str,
49        _limit: usize,
50        _session_id: Option<&str>,
51        _since: Option<&str>,
52        _until: Option<&str>,
53    ) -> anyhow::Result<Vec<MemoryEntry>> {
54        Ok(Vec::new())
55    }
56
57    async fn get(&self, _key: &str) -> anyhow::Result<Option<MemoryEntry>> {
58        Ok(None)
59    }
60
61    async fn list(
62        &self,
63        _category: Option<&MemoryCategory>,
64        _session_id: Option<&str>,
65    ) -> anyhow::Result<Vec<MemoryEntry>> {
66        Ok(Vec::new())
67    }
68
69    async fn forget(&self, _key: &str) -> anyhow::Result<bool> {
70        Ok(false)
71    }
72
73    async fn forget_for_agent(&self, _key: &str, _agent_id: &str) -> anyhow::Result<bool> {
74        Ok(false)
75    }
76
77    async fn purge_session_for_agent(
78        &self,
79        _session_id: &str,
80        _agent_id: &str,
81    ) -> anyhow::Result<usize> {
82        Ok(0)
83    }
84
85    async fn count(&self) -> anyhow::Result<usize> {
86        Ok(0)
87    }
88
89    async fn health_check(&self) -> bool {
90        true
91    }
92
93    async fn store_with_agent(
94        &self,
95        _key: &str,
96        _content: &str,
97        _category: MemoryCategory,
98        _session_id: Option<&str>,
99        _namespace: Option<&str>,
100        _importance: Option<f64>,
101        _agent_id: Option<&str>,
102    ) -> anyhow::Result<()> {
103        Ok(())
104    }
105
106    async fn recall_for_agents(
107        &self,
108        _allowed_agent_ids: &[&str],
109        _query: &str,
110        _limit: usize,
111        _session_id: Option<&str>,
112        _since: Option<&str>,
113        _until: Option<&str>,
114    ) -> anyhow::Result<Vec<MemoryEntry>> {
115        Ok(Vec::new())
116    }
117}
118
119#[cfg(test)]
120mod tests {
121    use super::*;
122
123    #[tokio::test]
124    async fn none_memory_is_noop() {
125        let memory = NoneMemory::new("none");
126
127        memory
128            .store("k", "v", MemoryCategory::Core, None)
129            .await
130            .unwrap();
131
132        assert!(memory.get("k").await.unwrap().is_none());
133        assert!(
134            memory
135                .recall("k", 10, None, None, None)
136                .await
137                .unwrap()
138                .is_empty()
139        );
140        assert!(memory.list(None, None).await.unwrap().is_empty());
141        assert!(!memory.forget("k").await.unwrap());
142        assert_eq!(memory.count().await.unwrap(), 0);
143        assert!(memory.health_check().await);
144    }
145}