crabtalk_runtime/memory/
tool.rs1use crate::{Env, host::Host};
4use serde::Deserialize;
5use wcore::{
6 agent::{AsTool, ToolDescription},
7 model::Tool,
8};
9
10#[derive(Deserialize, schemars::JsonSchema)]
11pub struct Recall {
12 pub query: String,
14 pub limit: Option<usize>,
16}
17
18impl ToolDescription for Recall {
19 const DESCRIPTION: &'static str =
20 "Search your memory entries by keyword. Returns ranked results.";
21}
22
23#[derive(Deserialize, schemars::JsonSchema)]
24pub struct Remember {
25 pub name: String,
27 pub description: String,
29 pub content: String,
31}
32
33impl ToolDescription for Remember {
34 const DESCRIPTION: &'static str = "Save or update a memory entry. Creates a persistent file with the given name, description, and content.";
35}
36
37#[derive(Deserialize, schemars::JsonSchema)]
38pub struct Forget {
39 pub name: String,
41}
42
43impl ToolDescription for Forget {
44 const DESCRIPTION: &'static str = "Delete a memory entry by name.";
45}
46
47#[derive(Deserialize, schemars::JsonSchema)]
48pub struct MemoryTool {
49 pub content: String,
51}
52
53impl ToolDescription for MemoryTool {
54 const DESCRIPTION: &'static str = "Overwrite MEMORY.md — your curated overview injected every session. Read it before overwriting.";
55}
56
57pub fn tools() -> Vec<Tool> {
58 vec![
59 Recall::as_tool(),
60 Remember::as_tool(),
61 Forget::as_tool(),
62 MemoryTool::as_tool(),
63 ]
64}
65
66impl<H: Host> Env<H> {
67 pub async fn dispatch_recall(&self, args: &str) -> Result<String, String> {
68 let input: Recall =
69 serde_json::from_str(args).map_err(|e| format!("invalid arguments: {e}"))?;
70 let mem = self.memory.as_ref().ok_or("memory not available")?;
71 Ok(mem.recall(&input.query, input.limit.unwrap_or(5)))
72 }
73
74 pub async fn dispatch_remember(&self, args: &str) -> Result<String, String> {
75 let input: Remember =
76 serde_json::from_str(args).map_err(|e| format!("invalid arguments: {e}"))?;
77 let mem = self.memory.as_ref().ok_or("memory not available")?;
78 Ok(mem.remember(input.name, input.description, input.content))
79 }
80
81 pub async fn dispatch_forget(&self, args: &str) -> Result<String, String> {
82 let input: Forget =
83 serde_json::from_str(args).map_err(|e| format!("invalid arguments: {e}"))?;
84 let mem = self.memory.as_ref().ok_or("memory not available")?;
85 Ok(mem.forget(&input.name))
86 }
87
88 pub async fn dispatch_memory(&self, args: &str) -> Result<String, String> {
89 let input: MemoryTool =
90 serde_json::from_str(args).map_err(|e| format!("invalid arguments: {e}"))?;
91 let mem = self.memory.as_ref().ok_or("memory not available")?;
92 Ok(mem.write_index(&input.content))
93 }
94}