agentmux_mcp/tools/
memory.rs1use super::*;
7
8pub(super) async fn call(name: &str, arguments: &Value, cx: &ToolCtx<'_>) -> Result<String> {
9 let ToolCtx { local_url, auth_key, block_id, client, .. } = *cx;
10 match name {
11 "MemoryList" => {
12 require_agent_env(local_url, auth_key, block_id)?;
13 let agent_id = agent_slug()?;
14 let url = format!("{}/api/v1/agent/memory/list", local_url.trim_end_matches('/'));
15 let resp = client
16 .get(&url)
17 .header(AUTH_KEY_HEADER, auth_key)
18 .query(&[("agent_id", agent_id.as_str())])
19 .send()
20 .await
21 .map_err(|e| anyhow::anyhow!("request failed: {e}"))?;
22 if !resp.status().is_success() {
23 let status = resp.status();
24 let text = resp.text().await.unwrap_or_default();
25 anyhow::bail!("memory/list failed: HTTP {status} — {text}");
26 }
27 let result: Value = resp
28 .json()
29 .await
30 .map_err(|e| anyhow::anyhow!("response parse failed: {e}"))?;
31 Ok(serde_json::to_string_pretty(&result).unwrap_or_else(|_| result.to_string()))
32 }
33 "MemoryRead" => {
34 let filename = arguments
35 .get("filename")
36 .and_then(|v| v.as_str())
37 .filter(|s| !s.is_empty())
38 .ok_or_else(|| anyhow::anyhow!("missing required parameter: filename"))?;
39 require_agent_env(local_url, auth_key, block_id)?;
40 let agent_id = agent_slug()?;
41 let url = format!("{}/api/v1/agent/memory/read", local_url.trim_end_matches('/'));
42 let resp = client
43 .get(&url)
44 .header(AUTH_KEY_HEADER, auth_key)
45 .query(&[("agent_id", agent_id.as_str()), ("filename", filename)])
46 .send()
47 .await
48 .map_err(|e| anyhow::anyhow!("request failed: {e}"))?;
49 if !resp.status().is_success() {
50 let status = resp.status();
51 let text = resp.text().await.unwrap_or_default();
52 anyhow::bail!("memory/read failed: HTTP {status} — {text}");
53 }
54 let result: Value = resp
55 .json()
56 .await
57 .map_err(|e| anyhow::anyhow!("response parse failed: {e}"))?;
58 Ok(result
60 .get("content")
61 .and_then(|v| v.as_str())
62 .map(str::to_string)
63 .unwrap_or_else(|| {
64 serde_json::to_string_pretty(&result).unwrap_or_else(|_| result.to_string())
65 }))
66 }
67 "MemoryWrite" => {
68 let filename = arguments
69 .get("filename")
70 .and_then(|v| v.as_str())
71 .filter(|s| !s.is_empty())
72 .ok_or_else(|| anyhow::anyhow!("missing required parameter: filename"))?;
73 let content = arguments
74 .get("content")
75 .and_then(|v| v.as_str())
76 .ok_or_else(|| anyhow::anyhow!("missing required parameter: content"))?;
77 require_agent_env(local_url, auth_key, block_id)?;
78 let agent_id = agent_slug()?;
79 let url = format!("{}/api/v1/agent/memory/write", local_url.trim_end_matches('/'));
80 let mut body = json!({
81 "agent_id": agent_id,
82 "filename": filename,
83 "content": content,
84 });
85 if let Some(provenance) = arguments.get("provenance") {
89 body["provenance"] = provenance.clone();
90 }
91 let resp = client
92 .post(&url)
93 .header(AUTH_KEY_HEADER, auth_key)
94 .json(&body)
95 .send()
96 .await
97 .map_err(|e| anyhow::anyhow!("request failed: {e}"))?;
98 if !resp.status().is_success() {
99 let status = resp.status();
100 let text = resp.text().await.unwrap_or_default();
101 anyhow::bail!("memory/write failed: HTTP {status} — {text}");
102 }
103 Ok(format!("Wrote memory file \"{filename}\""))
104 }
105 "MemoryHistory" => {
106 let filename = arguments
107 .get("filename")
108 .and_then(|v| v.as_str())
109 .filter(|s| !s.is_empty())
110 .ok_or_else(|| anyhow::anyhow!("missing required parameter: filename"))?;
111 require_agent_env(local_url, auth_key, block_id)?;
112 let agent_id = agent_slug()?;
113 let url = format!("{}/api/v1/agent/memory/history", local_url.trim_end_matches('/'));
114 let resp = client
115 .get(&url)
116 .header(AUTH_KEY_HEADER, auth_key)
117 .query(&[("agent_id", agent_id.as_str()), ("filename", filename)])
118 .send()
119 .await
120 .map_err(|e| anyhow::anyhow!("request failed: {e}"))?;
121 if !resp.status().is_success() {
122 let status = resp.status();
123 let text = resp.text().await.unwrap_or_default();
124 anyhow::bail!("memory/history failed: HTTP {status} — {text}");
125 }
126 let result: Value = resp
127 .json()
128 .await
129 .map_err(|e| anyhow::anyhow!("response parse failed: {e}"))?;
130 Ok(serde_json::to_string_pretty(&result).unwrap_or_else(|_| result.to_string()))
131 }
132 "MemoryDiff" => {
133 let from_version_id = arguments
134 .get("from_version_id")
135 .and_then(|v| v.as_str())
136 .filter(|s| !s.is_empty())
137 .ok_or_else(|| anyhow::anyhow!("missing required parameter: from_version_id"))?;
138 let to_version_id = arguments
139 .get("to_version_id")
140 .and_then(|v| v.as_str())
141 .filter(|s| !s.is_empty())
142 .ok_or_else(|| anyhow::anyhow!("missing required parameter: to_version_id"))?;
143 require_agent_env(local_url, auth_key, block_id)?;
144 let agent_id = agent_slug()?;
145 let url = format!("{}/api/v1/agent/memory/diff", local_url.trim_end_matches('/'));
146 let resp = client
147 .get(&url)
148 .header(AUTH_KEY_HEADER, auth_key)
149 .query(&[("agent_id", agent_id.as_str()), ("from_version_id", from_version_id), ("to_version_id", to_version_id)])
150 .send()
151 .await
152 .map_err(|e| anyhow::anyhow!("request failed: {e}"))?;
153 if !resp.status().is_success() {
154 let status = resp.status();
155 let text = resp.text().await.unwrap_or_default();
156 anyhow::bail!("memory/diff failed: HTTP {status} — {text}");
157 }
158 let result: Value = resp
159 .json()
160 .await
161 .map_err(|e| anyhow::anyhow!("response parse failed: {e}"))?;
162 Ok(result
163 .get("diff")
164 .and_then(|v| v.as_str())
165 .map(str::to_string)
166 .unwrap_or_else(|| {
167 serde_json::to_string_pretty(&result).unwrap_or_else(|_| result.to_string())
168 }))
169 }
170 "MemoryRevert" => {
171 let filename = arguments
172 .get("filename")
173 .and_then(|v| v.as_str())
174 .filter(|s| !s.is_empty())
175 .ok_or_else(|| anyhow::anyhow!("missing required parameter: filename"))?;
176 let target_version_id = arguments
177 .get("target_version_id")
178 .and_then(|v| v.as_str())
179 .filter(|s| !s.is_empty())
180 .ok_or_else(|| anyhow::anyhow!("missing required parameter: target_version_id"))?;
181 require_agent_env(local_url, auth_key, block_id)?;
182 let agent_id = agent_slug()?;
183 let url = format!("{}/api/v1/agent/memory/revert", local_url.trim_end_matches('/'));
184 let body = json!({
185 "agent_id": agent_id,
186 "filename": filename,
187 "target_version_id": target_version_id,
188 });
189 let resp = client
190 .post(&url)
191 .header(AUTH_KEY_HEADER, auth_key)
192 .json(&body)
193 .send()
194 .await
195 .map_err(|e| anyhow::anyhow!("request failed: {e}"))?;
196 if !resp.status().is_success() {
197 let status = resp.status();
198 let text = resp.text().await.unwrap_or_default();
199 anyhow::bail!("memory/revert failed: HTTP {status} — {text}");
200 }
201 Ok(format!("Reverted \"{filename}\" to version {target_version_id}"))
202 }
203 _ => Err(not_in_family()),
204 }
205}