use crate::{Env, host::Host};
use serde::Deserialize;
use wcore::{
agent::{AsTool, ToolDescription},
model::Tool,
};
#[derive(Deserialize, schemars::JsonSchema)]
pub struct Recall {
pub query: String,
pub limit: Option<usize>,
}
impl ToolDescription for Recall {
const DESCRIPTION: &'static str =
"Search your memory entries by keyword. Returns ranked results.";
}
#[derive(Deserialize, schemars::JsonSchema)]
pub struct Remember {
pub name: String,
pub description: String,
pub content: String,
}
impl ToolDescription for Remember {
const DESCRIPTION: &'static str = "Save or update a memory entry. Creates a persistent file with the given name, description, and content.";
}
#[derive(Deserialize, schemars::JsonSchema)]
pub struct Forget {
pub name: String,
}
impl ToolDescription for Forget {
const DESCRIPTION: &'static str = "Delete a memory entry by name.";
}
#[derive(Deserialize, schemars::JsonSchema)]
pub struct MemoryTool {
pub content: String,
}
impl ToolDescription for MemoryTool {
const DESCRIPTION: &'static str = "Overwrite MEMORY.md — your curated overview injected every session. Read it before overwriting.";
}
pub fn tools() -> Vec<Tool> {
vec![
Recall::as_tool(),
Remember::as_tool(),
Forget::as_tool(),
MemoryTool::as_tool(),
]
}
impl<H: Host> Env<H> {
pub async fn dispatch_recall(&self, args: &str) -> String {
let input: Recall = match serde_json::from_str(args) {
Ok(v) => v,
Err(e) => return format!("invalid arguments: {e}"),
};
match self.memory {
Some(ref mem) => mem.recall(&input.query, input.limit.unwrap_or(5)),
None => "memory not available".to_owned(),
}
}
pub async fn dispatch_remember(&self, args: &str) -> String {
let input: Remember = match serde_json::from_str(args) {
Ok(v) => v,
Err(e) => return format!("invalid arguments: {e}"),
};
match self.memory {
Some(ref mem) => mem.remember(input.name, input.description, input.content),
None => "memory not available".to_owned(),
}
}
pub async fn dispatch_forget(&self, args: &str) -> String {
let input: Forget = match serde_json::from_str(args) {
Ok(v) => v,
Err(e) => return format!("invalid arguments: {e}"),
};
match self.memory {
Some(ref mem) => mem.forget(&input.name),
None => "memory not available".to_owned(),
}
}
pub async fn dispatch_memory(&self, args: &str) -> String {
let input: MemoryTool = match serde_json::from_str(args) {
Ok(v) => v,
Err(e) => return format!("invalid arguments: {e}"),
};
match self.memory {
Some(ref mem) => mem.write_index(&input.content),
None => "memory not available".to_owned(),
}
}
}