Hasil audit round 4 (workflow/hive_mind + memory + semantic_search). - fix(memory): recall.search selama ini TIDAK pernah dipakai — tool mengiklankan keyword search di skema tapi run() cuma list semua nama. Kini search benar-benar memfilter (cocok di name/description/content, case-insensitive), + output 'No memories match' bila kosong. - fix(memory): ToolCtxBuilder tidak punya setter memory_dir dan tak ada call-site yang mengisinya — remember/recall/forget memakai PathBuf kosong dan menulis memory ke CWD (bukan lokasi persisten). Tambah setter memory_dir + worktrees_dir, dan helper resolve_memory_dir() yang fallback ke Store::new().memory_dir bila ctx.memory_dir kosong; dipakai di ketiga tool memory. - refactor(workflow): hapus LlmClient dummy di WorkflowRun (dibuat dengan API key kosong + model default + base_url default lalu tak pernah dipakai — execute_workflow menerimanya sebagai _llm_client). Kini execute_workflow tak ambil parameter tak terpakai; LLM asli tetap lewat execute_primitive yang resolve kredensial dengan benar. - test: +2 (recall search memfilter; resolve_memory_dir fallback/eksplisit). Catatan audit yang dilaporkan (belum difix): synth_consensus hanya menggabungkan output (label Consensus menyesatkan, bukan sintesis LLM), dan semantic_search memegang Mutex index global saat full rebuild (bottleneck saat paralel) + index tidak workspace-aware. PENTING (infra): disk root 100% saat kerja. Saya bebaskan ~4.6G dari /tmp + cache aman (sekai*, verify-z, bun/npm cache). target/debug di repo = 38G — rampah, perlu cargo clean + rebuild (jangan dibiarkan).
91 lines
2.9 KiB
Rust
91 lines
2.9 KiB
Rust
//! Remember a lesson or fact as persistent memory.
|
|
//!
|
|
//! Constructs a `Memory` struct from tool arguments and persists it
|
|
//! via `MarkdownMemoryRepository` to the memory directory.
|
|
|
|
use crate::tools::{Tool, ToolCtx};
|
|
use anyhow::Result;
|
|
use serde_json::{json, Value};
|
|
use tracing::{info, instrument};
|
|
|
|
use zesdex_domain::cms::{Memory, MemoryRepository};
|
|
|
|
/// Tool that saves a lesson or fact to persistent memory.
|
|
///
|
|
/// Flow: parse name/description/content/kind → construct a `Memory` struct
|
|
/// with timestamps → instantiate `MarkdownMemoryRepository` → call
|
|
/// `repo.save()` with the memory directory → confirm save.
|
|
pub struct Remember;
|
|
|
|
impl Tool for Remember {
|
|
fn name(&self) -> &'static str {
|
|
"remember"
|
|
}
|
|
|
|
fn description(&self) -> &'static str {
|
|
"Save a lesson or fact to persistent memory"
|
|
}
|
|
|
|
fn parameters(&self) -> Value {
|
|
json!({
|
|
"type": "object",
|
|
"properties": {
|
|
"name": {
|
|
"type": "string",
|
|
"description": "Unique name for this memory"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"description": "Short summary of the memory"
|
|
},
|
|
"content": {
|
|
"type": "string",
|
|
"description": "Full content of the memory"
|
|
},
|
|
"kind": {
|
|
"type": "string",
|
|
"enum": ["lesson", "reference", "fact"],
|
|
"description": "Category of memory"
|
|
}
|
|
},
|
|
"required": ["name", "description", "content"]
|
|
})
|
|
}
|
|
|
|
#[instrument(skip(self, ctx, args))]
|
|
fn run(&self, ctx: &ToolCtx, args: &Value) -> Result<String> {
|
|
let name = crate::tools::arg_str(args, "name")?;
|
|
let description = crate::tools::arg_str(args, "description")?;
|
|
let content = crate::tools::arg_str(args, "content")?;
|
|
let kind = args
|
|
.get("kind")
|
|
.and_then(|v| v.as_str())
|
|
.unwrap_or("reference")
|
|
.to_string();
|
|
|
|
info!(name, kind, "remember invoked");
|
|
|
|
let memory = Memory {
|
|
name: name.clone(),
|
|
description,
|
|
content,
|
|
kind,
|
|
created_at: chrono::Utc::now().timestamp(),
|
|
updated_at: chrono::Utc::now().timestamp(),
|
|
outcome: None,
|
|
lifecycle: "active".to_string(),
|
|
scope: None,
|
|
before_snippet: None,
|
|
after_snippet: None,
|
|
provenances: Vec::new(),
|
|
};
|
|
|
|
let repo = crate::persistence::cms::memory_repo::MarkdownMemoryRepository::new();
|
|
let memory_dir = crate::tools::memory::resolve_memory_dir(&ctx.memory_dir);
|
|
repo.save(&memory_dir, &memory)?;
|
|
|
|
info!(name, "memory saved");
|
|
Ok(format!("Memory '{}' saved", name))
|
|
}
|
|
}
|