diff --git a/crates/zesdex-backend/src/app/mode/learning.rs b/crates/zesdex-backend/src/app/mode/learning.rs index b0a09ca..f4c2c44 100644 --- a/crates/zesdex-backend/src/app/mode/learning.rs +++ b/crates/zesdex-backend/src/app/mode/learning.rs @@ -1,4 +1,5 @@ use crate::app::state::rest::AppStateRest; +use zesdex_cms::domain::repository::MemoryRepository; /// A unified representation of a lesson item for the interactive TUI overlay. #[derive(Debug, Clone)] @@ -53,9 +54,9 @@ pub fn get_learning_items(state: &AppStateRest) -> Vec { } // 2. Load stored memory lessons from long-term memory directory - let names = crate::model::memory::Memory::list(&state.memory_dir); + let names = zesdex_cms::infrastructure::persistence::memory_repo::MarkdownMemoryRepository::new().list(&state.memory_dir).unwrap_or_default(); for name in names { - if let Ok(mem) = crate::model::memory::Memory::read(&state.memory_dir, &name) { + if let Ok(mem) = zesdex_cms::infrastructure::persistence::memory_repo::MarkdownMemoryRepository::new().load(&state.memory_dir, &name) { if mem.kind == "lesson" { items.push(LearningItem::Stored { name: mem.name, diff --git a/crates/zesdex-backend/src/app/review/mod.rs b/crates/zesdex-backend/src/app/review/mod.rs index dfb9e19..10f7b61 100644 --- a/crates/zesdex-backend/src/app/review/mod.rs +++ b/crates/zesdex-backend/src/app/review/mod.rs @@ -9,6 +9,9 @@ use crate::app::subagent::context::build_subagent_context; use crate::app::subagent::engine::run_subagent; use crate::app::subagent::spawn::AgentDefinition; use serde::{Deserialize, Serialize}; +use zesdex_cms::domain::memory::Memory; +use zesdex_cms::domain::repository::MemoryRepository; +use zesdex_cms::infrastructure::persistence::memory_repo::MarkdownMemoryRepository; /// How much trust a lesson's origin/verification warrants. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] @@ -484,14 +487,15 @@ const STALE_AFTER_DAYS: i64 = 60; /// `mem.write`. pub fn run_staleness_sweep(memory_dir: &std::path::Path) -> std::io::Result> { let mut flagged = Vec::new(); - let names = crate::model::memory::Memory::list(memory_dir); + let names = MarkdownMemoryRepository::new().list(memory_dir).unwrap_or_default(); let now = chrono::Utc::now().timestamp_millis(); let cutoff = now - STALE_AFTER_DAYS * 24 * 3600 * 1000; for name in names { - if let Ok(mut mem) = crate::model::memory::Memory::read(memory_dir, &name) { + if let Ok(mut mem) = MarkdownMemoryRepository::new().load(memory_dir, &name) { if mem.updated_at < cutoff && mem.lifecycle != "stale" { mem.lifecycle = "stale".to_string(); - mem.write(memory_dir)?; + MarkdownMemoryRepository::new().save(memory_dir, &mem) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; flagged.push(name); } } @@ -581,7 +585,7 @@ pub fn process_pending_lessons(session_dir: &std::path::Path, memory_dir: &std:: } } for lesson in &to_keep { - let mem = crate::model::memory::Memory { + let mem = Memory { name: lesson.name.clone(), description: lesson.content.chars().take(80).collect(), content: lesson.content.clone(), @@ -595,7 +599,8 @@ pub fn process_pending_lessons(session_dir: &std::path::Path, memory_dir: &std:: after_snippet: None, provenances: vec![], }; - mem.write(memory_dir)?; + MarkdownMemoryRepository::new().save(memory_dir, &mem) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; } save_pending_lessons(session_dir, &remaining)?; @@ -625,7 +630,7 @@ pub fn resolve_pending_lesson( for p in pending { if p.lesson.name == lesson_name { if keep { - let mem = crate::model::memory::Memory { + let mem = Memory { name: p.lesson.name.clone(), description: p.lesson.content.chars().take(80).collect(), content: p.lesson.content.clone(), @@ -639,7 +644,8 @@ pub fn resolve_pending_lesson( after_snippet: None, provenances: vec![], }; - mem.write(memory_dir)?; + MarkdownMemoryRepository::new().save(memory_dir, &mem) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; } } else { remaining.push(p); diff --git a/crates/zesdex-backend/src/app/runtime/actions/mod.rs b/crates/zesdex-backend/src/app/runtime/actions/mod.rs index cc91bb0..757c87d 100644 --- a/crates/zesdex-backend/src/app/runtime/actions/mod.rs +++ b/crates/zesdex-backend/src/app/runtime/actions/mod.rs @@ -29,6 +29,8 @@ use crate::app::state::rest::{AppStateRest, ChatMessageDisplay}; use crate::app::state::runtime::TurnEvent; use crate::app::state::types::{Origin, Overlay, Toast, ToastKind}; use crate::dto::chat::message::{ChatMessage, Role}; +use zesdex_cms::domain::repository::MemoryRepository; +use zesdex_cms::infrastructure::persistence::memory_repo::MarkdownMemoryRepository; /// A single, well-typed event in the app — produced by key input, the /// streaming pipeline, or subagent threads — that mutates `AppStateRest` @@ -589,7 +591,7 @@ pub fn apply_action(state: &mut AppStateRest, action: Action) { state.dirty = true; } Action::LessonDelete { name } => { - let _ = crate::model::memory::Memory::remove(&state.memory_dir, &name); + let _ = MarkdownMemoryRepository::new().delete(&state.memory_dir, &name); if let Some(ref mut rt) = state.session_runtime { refresh_lesson_counters(&state.memory_dir, rt); } @@ -795,7 +797,7 @@ fn generate_workspace_tree(roots: &[std::path::PathBuf]) -> String { /// /// Return: a formatted string (may be empty if no memory entries exist). fn build_memory_section(memory_dir: &std::path::Path) -> String { - let names = crate::model::memory::Memory::list(memory_dir); + let names = MarkdownMemoryRepository::new().list(memory_dir).unwrap_or_default(); if names.is_empty() { return String::new(); } @@ -808,7 +810,7 @@ fn build_memory_section(memory_dir: &std::path::Path) -> String { section.push_str("... (more entries omitted, use recall() to see all)\n"); break; } - if let Ok(mem) = crate::model::memory::Memory::read(memory_dir, name) { + if let Ok(mem) = MarkdownMemoryRepository::new().load(memory_dir, name) { if mem.lifecycle == "stale" { continue; } @@ -831,7 +833,7 @@ fn build_memory_section(memory_dir: &std::path::Path) -> String { /// breakdown counters. This runs on every user submit so the dashboard /// reflects actual memory state. fn refresh_lesson_counters(memory_dir: &std::path::Path, rt: &mut crate::app::state::runtime::SessionRuntime) { - let names = crate::model::memory::Memory::list(memory_dir); + let names = MarkdownMemoryRepository::new().list(memory_dir).unwrap_or_default(); rt.lesson_count = 0; rt.lessons_user = 0; rt.lessons_feedback = 0; @@ -841,7 +843,7 @@ fn refresh_lesson_counters(memory_dir: &std::path::Path, rt: &mut crate::app::st rt.lessons_stale = 0; rt.lessons_contradicted = 0; for name in &names { - if let Ok(mem) = crate::model::memory::Memory::read(memory_dir, name) { + if let Ok(mem) = MarkdownMemoryRepository::new().load(memory_dir, name) { rt.lesson_count += 1; match mem.kind.as_str() { "user" => rt.lessons_user += 1, diff --git a/crates/zesdex-backend/src/app/workflow/docs.rs b/crates/zesdex-backend/src/app/workflow/docs.rs index 5340e31..11b1b3d 100644 --- a/crates/zesdex-backend/src/app/workflow/docs.rs +++ b/crates/zesdex-backend/src/app/workflow/docs.rs @@ -7,7 +7,7 @@ //! Core Intelligence can omit or reshape — and always runs after any //! hive-mind convergence completes. use crate::app::workflow::hive_mind::NodeReport; -use crate::model::memory::Memory; +use zesdex_cms::domain::memory::Memory; use std::fmt::Write as _; use std::path::{Path, PathBuf}; diff --git a/crates/zesdex-backend/src/model/mod.rs b/crates/zesdex-backend/src/model/mod.rs index 5e252ec..dacbf0e 100644 --- a/crates/zesdex-backend/src/model/mod.rs +++ b/crates/zesdex-backend/src/model/mod.rs @@ -8,9 +8,6 @@ pub mod store { pub mod editlog { pub use zesdex_entities::seaorm::common::edit_log::*; } -pub mod memory { - pub use zesdex_entities::seaorm::common::memory::*; -} /// Local modules not extracted to workspace crates pub mod msglog; pub mod agent_def; diff --git a/crates/zesdex-backend/src/tool/memory/forget.rs b/crates/zesdex-backend/src/tool/memory/forget.rs index 3f36a73..45375c9 100644 --- a/crates/zesdex-backend/src/tool/memory/forget.rs +++ b/crates/zesdex-backend/src/tool/memory/forget.rs @@ -1,7 +1,8 @@ //! Tool for deleting a persisted memory entry by name. use super::super::Tool; use super::super::ToolCtx; -use crate::model::memory::Memory; +use zesdex_cms::domain::repository::MemoryRepository; +use zesdex_cms::infrastructure::persistence::memory_repo::MarkdownMemoryRepository; use anyhow::{anyhow, Result}; use serde_json::{json, Value}; @@ -42,7 +43,7 @@ impl Tool for Forget { .and_then(|v| v.as_str()) .ok_or_else(|| anyhow!("missing required argument: name"))?; - Memory::remove(&ctx.memory_dir, name) + MarkdownMemoryRepository::new().delete(&ctx.memory_dir, name) .map_err(|e| anyhow!("failed to remove memory '{name}': {e}"))?; Ok(format!("removed memory '{name}'")) diff --git a/crates/zesdex-backend/src/tool/memory/recall.rs b/crates/zesdex-backend/src/tool/memory/recall.rs index 0871b18..e50b4e2 100644 --- a/crates/zesdex-backend/src/tool/memory/recall.rs +++ b/crates/zesdex-backend/src/tool/memory/recall.rs @@ -1,7 +1,8 @@ //! Tool for reading a single memory entry or listing the whole memory index. use super::super::Tool; use super::super::ToolCtx; -use crate::model::memory::Memory; +use zesdex_cms::domain::repository::MemoryRepository; +use zesdex_cms::infrastructure::persistence::memory_repo::MarkdownMemoryRepository; use anyhow::{anyhow, Result}; use serde_json::{json, Value}; use std::fmt::Write; @@ -41,7 +42,7 @@ impl Tool for Recall { if name.is_empty() { return Ok(list_all(ctx)); } - let memory = Memory::read(&ctx.memory_dir, name) + let memory = MarkdownMemoryRepository::new().load(&ctx.memory_dir, name) .map_err(|e| anyhow!("memory '{name}' not found: {e}"))?; Ok(format!( "---\nname: {}\ndescription: {}\nkind: {}\nlifecycle: {}\n---\n\n{}", @@ -60,13 +61,13 @@ impl Tool for Recall { /// /// Return: `Ok` with the formatted index (never fails; missing dir yields "(no memory entries)"). fn list_all(ctx: &ToolCtx) -> String { - let names = Memory::list(&ctx.memory_dir); + let names = MarkdownMemoryRepository::new().list(&ctx.memory_dir).unwrap_or_default(); if names.is_empty() { return "(no memory entries)".to_string(); } let mut lines = String::new(); for name in &names { - if let Ok(mem) = Memory::read(&ctx.memory_dir, name) { + if let Ok(mem) = MarkdownMemoryRepository::new().load(&ctx.memory_dir, name) { let _ = writeln!(lines, "- {} [{}]: {}", name, mem.kind, mem.description); } else { let _ = writeln!(lines, "- {name}"); diff --git a/crates/zesdex-backend/src/tool/memory/remember.rs b/crates/zesdex-backend/src/tool/memory/remember.rs index 948c7c2..e01e4c4 100644 --- a/crates/zesdex-backend/src/tool/memory/remember.rs +++ b/crates/zesdex-backend/src/tool/memory/remember.rs @@ -1,7 +1,9 @@ //! Tool for saving a new memory entry to persistent project memory. use super::super::Tool; use super::super::ToolCtx; -use crate::model::memory::Memory; +use zesdex_cms::domain::memory::Memory; +use zesdex_cms::domain::repository::MemoryRepository; +use zesdex_cms::infrastructure::persistence::memory_repo::MarkdownMemoryRepository; use anyhow::{anyhow, Result}; use serde_json::{json, Value}; @@ -91,9 +93,8 @@ impl Tool for Remember { provenances: vec![], }; - memory - .write(&ctx.memory_dir) - .map_err(|e| anyhow!("failed to write memory '{name}': {e}"))?; + MarkdownMemoryRepository::new().save(&ctx.memory_dir, &memory) + .map_err(|e| anyhow!("failed to save memory '{name}': {e}"))?; Ok(format!("saved memory '{name}' ({kind})")) }