use anyhow::{Context, Result};
use colored::*;
use std::path::Path;
use crate::agent::Agent;
const MEMORY_FILE: &str = "memory.json";
#[derive(serde::Serialize, serde::Deserialize, Default)]
struct MemoryStore {
notes: Vec<MemoryNote>,
}
#[derive(serde::Serialize, serde::Deserialize)]
struct MemoryNote {
text: String,
added_at: String,
}
pub async fn handle(agent: &mut Agent, args: &str) -> Result<()> {
let memory_path = agent.config.session_dir.join(MEMORY_FILE);
if args.is_empty() || args == "show" {
let store = load_memory(&memory_path).await;
if store.notes.is_empty() {
println!("{}", "No memory notes saved.".dimmed());
println!(
"{}",
"Use '/memory add <text>' to add a note.".dimmed()
);
} else {
println!("{}", "\n━━━ Memory Notes ━━━".bold());
for (i, note) in store.notes.iter().enumerate() {
println!(
" {}. {} {}",
i + 1,
note.text,
format!("({})", note.added_at).dimmed()
);
}
}
} else if let Some(text) = args.strip_prefix("add ") {
let text = text.trim();
if text.is_empty() {
println!("{}", "Please provide text to remember.".yellow());
return Ok(());
}
let mut store = load_memory(&memory_path).await;
store.notes.push(MemoryNote {
text: text.to_string(),
added_at: chrono::Utc::now().format("%Y-%m-%d %H:%M").to_string(),
});
save_memory(&memory_path, &store).await?;
println!("{}", format!("✓ Remembered: {}", text).green());
} else if args == "clear" {
let store = MemoryStore::default();
save_memory(&memory_path, &store).await?;
println!("{}", "✓ All memory notes cleared.".green());
} else {
println!("{}", "Usage: /memory [show|add <text>|clear]".yellow());
}
Ok(())
}
async fn load_memory(path: &Path) -> MemoryStore {
if path.exists() {
match tokio::fs::read_to_string(path).await {
Ok(json) => serde_json::from_str(&json).unwrap_or_default(),
Err(_) => MemoryStore::default(),
}
} else {
MemoryStore::default()
}
}
async fn save_memory(path: &Path, store: &MemoryStore) -> Result<()> {
if let Some(parent) = path.parent() {
tokio::fs::create_dir_all(parent).await?;
}
let json = serde_json::to_string_pretty(store)
.context("Failed to serialize memory")?;
tokio::fs::write(path, json)
.await
.context("Failed to write memory file")?;
Ok(())
}