refactor(backend): alihkan Memory ke zesdex-cms MarkdownMemoryRepository

Ganti semua pemanggilan Memory::read/write/remove/list di zesdex-backend
dengan MarkdownMemoryRepository dari zesdex-cms. Hapus re-export
model::memory yang sudah tidak dipakai.

Method mapping: read -> load, write -> save, remove -> delete, list -> list.
Import trait MemoryRepository untuk method resolution.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
asepharyana
2026-07-17 09:08:41 +07:00
co-authored by Claude Sonnet 5
parent dc9fd4dbd1
commit 0ad3b0e539
8 changed files with 37 additions and 28 deletions
@@ -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<LearningItem> {
}
// 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,
+13 -7
View File
@@ -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<Vec<String>> {
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);
@@ -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,
@@ -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};
-3
View File
@@ -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;
@@ -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}'"))
@@ -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}");
@@ -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})"))
}