// thought — shared cognitive infrastructure // // The thought layer contains everything both the conscious agent // (poc-agent) and subconscious agents need to think and act: tool // dispatch, memory operations, file operations, context management. // // Named "thought" because tools are the mechanism by which the system // thinks — reading, writing, remembering, searching are all acts of // thought regardless of which layer initiates them. pub mod bash; pub mod context; pub mod edit; pub mod glob_tool; pub mod grep; pub mod memory; pub mod read; pub mod write; pub use bash::ProcessTracker; // Re-export ToolDef from agent::types for convenience — // tools define their schemas using this type. pub use crate::agent::types::ToolDef; /// Result of dispatching a tool call. pub struct ToolOutput { pub text: String, pub is_yield: bool, /// Base64 data URIs for images to attach to the next message. pub images: Vec, /// Model name to switch to (deferred to session level). pub model_switch: Option, /// Agent requested DMN pause (deferred to session level). pub dmn_pause: bool, } impl ToolOutput { pub fn error(e: impl std::fmt::Display) -> Self { Self { text: format!("Error: {}", e), is_yield: false, images: Vec::new(), model_switch: None, dmn_pause: false, } } pub fn text(s: String) -> Self { Self { text: s, is_yield: false, images: Vec::new(), model_switch: None, dmn_pause: false, } } } /// Truncate output if it exceeds max length, appending a truncation notice. pub fn truncate_output(mut s: String, max: usize) -> String { if s.len() > max { s.truncate(max); s.push_str("\n... (output truncated)"); } s } /// Dispatch a shared tool call. Handles file operations, bash, /// and memory/journal tools. Returns None for unknown tools /// (caller should check agent-specific tools). pub async fn dispatch( name: &str, args: &serde_json::Value, tracker: &ProcessTracker, provenance: Option<&str>, ) -> Option { // Memory and journal tools if name.starts_with("memory_") || name.starts_with("journal_") || name == "output" { let result = memory::dispatch(name, args, provenance); return Some(match result { Ok(s) => ToolOutput::text(s), Err(e) => ToolOutput::error(e), }); } // File and execution tools let result = match name { "read_file" => read::read_file(args), "write_file" => write::write_file(args), "edit_file" => edit::edit_file(args), "bash" => bash::run_bash(args, tracker).await, "grep" => grep::grep(args), "glob" => glob_tool::glob_search(args), _ => return None, }; Some(match result { Ok(s) => ToolOutput::text(s), Err(e) => ToolOutput::error(e), }) } /// Return all shared tool definitions. pub fn definitions() -> Vec { vec![ read::definition(), write::definition(), edit::definition(), bash::definition(), grep::definition(), glob_tool::definition(), ] } /// Return all shared + memory tool definitions. pub fn all_definitions() -> Vec { let mut defs = definitions(); defs.extend(memory::definitions()); defs } /// Return memory + journal tool definitions. /// Used by the journal agent only. pub fn memory_and_journal_definitions() -> Vec { let mut defs = memory::definitions(); defs.extend(memory::journal_definitions()); defs }