Skip to main content

zeroclaw_runtime/agent/
memory_strategy.rs

1use std::sync::Arc;
2use zeroclaw_api::memory_traits::{Memory, MemoryStrategy};
3use zeroclaw_api::model_provider::ModelProvider;
4
5use crate::agent::memory_loader::{DefaultMemoryLoader, MemoryLoader};
6
7/// Default memory strategy that delegates to existing implementations.
8///
9/// Phase 1: This is a thin wrapper. It does not duplicate logic;
10/// it calls `DefaultMemoryLoader`, `consolidation::consolidate_turn`,
11/// and `hygiene::run_if_due` directly, preserving current behavior
12/// byte-for-byte.
13pub struct DefaultMemoryStrategy {
14    memory: Arc<dyn Memory>,
15    limit: usize,
16    min_relevance_score: f64,
17    memory_config: zeroclaw_config::schema::MemoryConfig,
18    workspace_dir: std::path::PathBuf,
19}
20
21impl DefaultMemoryStrategy {
22    pub fn new(
23        memory: Arc<dyn Memory>,
24        memory_config: zeroclaw_config::schema::MemoryConfig,
25        workspace_dir: impl Into<std::path::PathBuf>,
26    ) -> Self {
27        Self {
28            memory,
29            limit: 5,
30            min_relevance_score: memory_config.min_relevance_score,
31            memory_config,
32            workspace_dir: workspace_dir.into(),
33        }
34    }
35
36    /// Convenience constructor that takes the live `MemoryConfig` so
37    /// `run_governance` uses the operator's actual settings (archive
38    /// windows, hygiene toggle, etc.) rather than hardcoded defaults.
39    pub fn with_config(
40        memory: Arc<dyn Memory>,
41        memory_config: zeroclaw_config::schema::MemoryConfig,
42        workspace_dir: impl Into<std::path::PathBuf>,
43    ) -> Self {
44        Self::new(memory, memory_config, workspace_dir)
45    }
46}
47
48#[async_trait::async_trait]
49impl MemoryStrategy for DefaultMemoryStrategy {
50    async fn load_context(&self, query: &str, session_id: Option<&str>) -> anyhow::Result<String> {
51        let loader = DefaultMemoryLoader::new(self.limit, self.min_relevance_score);
52        loader
53            .load_context(self.memory.as_ref(), query, session_id)
54            .await
55    }
56
57    async fn consolidate_turn(
58        &self,
59        user_message: &str,
60        assistant_response: &str,
61        provider: &dyn ModelProvider,
62        model: &str,
63        temperature: Option<f64>,
64    ) -> anyhow::Result<()> {
65        zeroclaw_memory::consolidation::consolidate_turn(
66            provider,
67            model,
68            temperature,
69            self.memory.as_ref(),
70            user_message,
71            assistant_response,
72        )
73        .await
74    }
75
76    async fn run_governance(&self) -> anyhow::Result<()> {
77        // Delegate to the existing hygiene routine.
78        // Phase 1: `hygiene::run_if_due` returns `Result<()>`.
79        // A structured report will be wired in a follow-up when hygiene
80        // exposes per-action counters.
81        zeroclaw_memory::hygiene::run_if_due(&self.memory_config, &self.workspace_dir)
82    }
83}