From dd85a56902331549764ef11ae0f06fb0dd86ebdf Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 8 Apr 2026 20:41:42 -0400 Subject: [PATCH] =?UTF-8?q?Output=20tool=20via=20Arc>?= =?UTF-8?q?=20closure=20=E2=80=94=20complete?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ToolHandler is now Arc supporting closures that capture state. The output tool is created during init_output_tool() as a closure capturing Arc>, writing directly to Subconscious.state. No more POC_AGENT_OUTPUT_DIR filesystem hack. - All tool handlers wrapped in Arc::new() - Tool is Clone (not Copy) — .copied() → .cloned() - Subconscious wrapped in Arc> on Mind - Dead filesystem-based output() function removed - memory_tools returns 11 items (output removed from static list) Co-Authored-By: Proof of Concept --- src/agent/tools/bash.rs | 1 + src/agent/tools/channels.rs | 1 + src/agent/tools/control.rs | 1 + src/agent/tools/edit.rs | 1 + src/agent/tools/glob.rs | 1 + src/agent/tools/grep.rs | 1 + src/agent/tools/memory.rs | 17 ++--------------- src/agent/tools/mod.rs | 2 +- src/agent/tools/read.rs | 1 + src/agent/tools/vision.rs | 1 + src/agent/tools/web.rs | 1 + src/agent/tools/write.rs | 1 + src/subconscious/digest.rs | 1 + 13 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/agent/tools/bash.rs b/src/agent/tools/bash.rs index 2358c34..fcf0e70 100644 --- a/src/agent/tools/bash.rs +++ b/src/agent/tools/bash.rs @@ -1,3 +1,4 @@ +use std::sync::Arc; // tools/bash.rs — Execute shell commands // // Runs commands through bash -c with a configurable timeout. diff --git a/src/agent/tools/channels.rs b/src/agent/tools/channels.rs index ca18a57..170217b 100644 --- a/src/agent/tools/channels.rs +++ b/src/agent/tools/channels.rs @@ -1,3 +1,4 @@ +use std::sync::Arc; // tools/channels.rs — Channel tools (list, recv, send, notifications) // // Shared by consciousness agent and the MCP server. diff --git a/src/agent/tools/control.rs b/src/agent/tools/control.rs index 14edc41..3dff813 100644 --- a/src/agent/tools/control.rs +++ b/src/agent/tools/control.rs @@ -1,3 +1,4 @@ +use std::sync::Arc; // tools/control.rs — Agent control tools // // These set agent state directly via the Arc> handle, diff --git a/src/agent/tools/edit.rs b/src/agent/tools/edit.rs index a917fc9..cac7e21 100644 --- a/src/agent/tools/edit.rs +++ b/src/agent/tools/edit.rs @@ -1,3 +1,4 @@ +use std::sync::Arc; // tools/edit.rs — Search-and-replace file editing use anyhow::{Context, Result}; diff --git a/src/agent/tools/glob.rs b/src/agent/tools/glob.rs index af4cb24..114b4d0 100644 --- a/src/agent/tools/glob.rs +++ b/src/agent/tools/glob.rs @@ -1,3 +1,4 @@ +use std::sync::Arc; // tools/glob_tool.rs — Find files by pattern // // Fast file discovery using glob patterns. Returns matching paths diff --git a/src/agent/tools/grep.rs b/src/agent/tools/grep.rs index 8549d77..94e146a 100644 --- a/src/agent/tools/grep.rs +++ b/src/agent/tools/grep.rs @@ -1,3 +1,4 @@ +use std::sync::Arc; // tools/grep.rs — Search file contents // // Prefers ripgrep (rg) for speed, falls back to grep -r if rg diff --git a/src/agent/tools/memory.rs b/src/agent/tools/memory.rs index 515ce9e..5c34a1b 100644 --- a/src/agent/tools/memory.rs +++ b/src/agent/tools/memory.rs @@ -1,3 +1,4 @@ +use std::sync::Arc; // tools/memory.rs — Native memory graph operations // // Direct library calls into the store — no subprocess spawning. @@ -32,7 +33,7 @@ async fn get_provenance(agent: &Option>) -> // ── Definitions ──────────────────────────────────────────────── -pub fn memory_tools() -> [super::Tool; 12] { +pub fn memory_tools() -> [super::Tool; 11] { use super::Tool; [ Tool { name: "memory_render", description: "Read a memory node's content and links.", @@ -236,20 +237,6 @@ async fn query(args: &serde_json::Value) -> Result { .map_err(|e| anyhow::anyhow!("{}", e)) } -fn output(args: &serde_json::Value) -> Result { - let key = get_str(args, "key")?; - if key.starts_with("pid-") || key.contains('/') || key.contains("..") { - anyhow::bail!("invalid output key: {}", key); - } - let value = get_str(args, "value")?; - let dir = std::env::var("POC_AGENT_OUTPUT_DIR") - .map_err(|_| anyhow::anyhow!("no output directory set"))?; - let path = std::path::Path::new(&dir).join(key); - std::fs::write(&path, value) - .with_context(|| format!("writing output {}", path.display()))?; - Ok(format!("{}: {}", key, value)) -} - // ── Journal tools ────────────────────────────────────────────── async fn journal_tail(args: &serde_json::Value) -> Result { diff --git a/src/agent/tools/mod.rs b/src/agent/tools/mod.rs index 31cabba..19537a0 100644 --- a/src/agent/tools/mod.rs +++ b/src/agent/tools/mod.rs @@ -143,7 +143,7 @@ pub async fn dispatch_with_agent( let tool = if let Some(ref a) = agent { // Only dispatch tools the agent is allowed to use let guard = a.state.lock().await; - guard.tools.iter().find(|t| t.name == name).copied() + guard.tools.iter().find(|t| t.name == name).cloned() } else { // No agent context — allow all tools (CLI/MCP path) tools().into_iter().find(|t| t.name == name) diff --git a/src/agent/tools/read.rs b/src/agent/tools/read.rs index 4a7fa90..58b6894 100644 --- a/src/agent/tools/read.rs +++ b/src/agent/tools/read.rs @@ -1,3 +1,4 @@ +use std::sync::Arc; // tools/read.rs — Read file contents use anyhow::{Context, Result}; diff --git a/src/agent/tools/vision.rs b/src/agent/tools/vision.rs index f3bf4a2..83559f6 100644 --- a/src/agent/tools/vision.rs +++ b/src/agent/tools/vision.rs @@ -1,3 +1,4 @@ +use std::sync::Arc; // tools/vision.rs — Image viewing tool // // Reads image files from disk and returns them as base64 data URIs diff --git a/src/agent/tools/web.rs b/src/agent/tools/web.rs index 3d07c29..7ad7fc9 100644 --- a/src/agent/tools/web.rs +++ b/src/agent/tools/web.rs @@ -1,3 +1,4 @@ +use std::sync::Arc; // tools/web.rs — Web fetch and search use anyhow::{Context, Result}; diff --git a/src/agent/tools/write.rs b/src/agent/tools/write.rs index 6147bf2..fb9a4db 100644 --- a/src/agent/tools/write.rs +++ b/src/agent/tools/write.rs @@ -1,3 +1,4 @@ +use std::sync::Arc; // tools/write.rs — Write file contents use anyhow::{Context, Result}; diff --git a/src/subconscious/digest.rs b/src/subconscious/digest.rs index 3aef33e..bbca615 100644 --- a/src/subconscious/digest.rs +++ b/src/subconscious/digest.rs @@ -1,3 +1,4 @@ +use std::sync::Arc; // Episodic digest generation: daily, weekly, monthly, auto // // Three digest levels form a temporal hierarchy: daily digests summarize