From 2f0c7ce5c210f9a9d2d884273a4b14b31fc892dd Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 3 Apr 2026 21:59:14 -0400 Subject: [PATCH] src/thought -> src/agent Signed-off-by: Kent Overstreet --- src/{thought => agent}/context.rs | 0 src/{thought => agent}/mod.rs | 55 +++++------- src/{user => agent}/runner.rs | 20 ++--- src/{thought => agent/tools}/bash.rs | 0 src/{user => agent}/tools/control.rs | 0 src/{thought => agent/tools}/edit.rs | 0 .../glob_tool.rs => agent/tools/glob.rs} | 0 src/{thought => agent/tools}/grep.rs | 0 src/{thought => agent/tools}/memory.rs | 0 src/{user => agent}/tools/mod.rs | 21 +++-- src/{thought => agent/tools}/read.rs | 0 src/{user => agent}/tools/vision.rs | 0 src/{user => agent}/tools/working_stack.rs | 0 src/{thought => agent/tools}/write.rs | 0 src/{thought => agent}/training.rs | 0 src/bin/consciousness.rs | 86 +------------------ src/lib.rs | 2 +- src/subconscious/api.rs | 8 +- src/subconscious/knowledge.rs | 2 +- src/user/mod.rs | 2 - src/user/types.rs | 2 +- 21 files changed, 57 insertions(+), 141 deletions(-) rename src/{thought => agent}/context.rs (100%) rename src/{thought => agent}/mod.rs (67%) rename src/{user => agent}/runner.rs (98%) rename src/{thought => agent/tools}/bash.rs (100%) rename src/{user => agent}/tools/control.rs (100%) rename src/{thought => agent/tools}/edit.rs (100%) rename src/{thought/glob_tool.rs => agent/tools/glob.rs} (100%) rename src/{thought => agent/tools}/grep.rs (100%) rename src/{thought => agent/tools}/memory.rs (100%) rename src/{user => agent}/tools/mod.rs (81%) rename src/{thought => agent/tools}/read.rs (100%) rename src/{user => agent}/tools/vision.rs (100%) rename src/{user => agent}/tools/working_stack.rs (100%) rename src/{thought => agent/tools}/write.rs (100%) rename src/{thought => agent}/training.rs (100%) diff --git a/src/thought/context.rs b/src/agent/context.rs similarity index 100% rename from src/thought/context.rs rename to src/agent/context.rs diff --git a/src/thought/mod.rs b/src/agent/mod.rs similarity index 67% rename from src/thought/mod.rs rename to src/agent/mod.rs index bc50ecf..4cef3ec 100644 --- a/src/thought/mod.rs +++ b/src/agent/mod.rs @@ -1,24 +1,15 @@ -// thought — shared cognitive infrastructure +// agent — core agent 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. +// Tool dispatch, memory operations, file operations, context +// management, and the agent runner loop. Used by both the +// interactive consciousness binary and subconscious agents. -pub mod bash; pub mod context; -pub mod edit; -pub mod glob_tool; -pub mod grep; -pub mod memory; -pub mod read; +pub mod runner; +pub mod tools; pub mod training; -pub mod write; -pub use bash::ProcessTracker; +pub use tools::bash::ProcessTracker; // Re-export ToolDef from agent::types for convenience — // tools define their schemas using this type. @@ -78,7 +69,7 @@ pub async fn dispatch( ) -> Option { // Memory and journal tools if name.starts_with("memory_") || name.starts_with("journal_") || name == "output" { - let result = memory::dispatch(name, args, provenance); + let result = tools::memory::dispatch(name, args, provenance); return Some(match result { Ok(s) => ToolOutput::text(s), Err(e) => ToolOutput::error(e), @@ -87,12 +78,12 @@ pub async fn dispatch( // 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), + "read_file" => tools::read::read_file(args), + "write_file" => tools::write::write_file(args), + "edit_file" => tools::edit::edit_file(args), + "bash" => tools::bash::run_bash(args, tracker).await, + "grep" => tools::grep::grep(args), + "glob" => tools::glob::glob_search(args), _ => return None, }; @@ -105,26 +96,26 @@ pub async fn dispatch( /// Return all shared tool definitions. pub fn definitions() -> Vec { vec![ - read::definition(), - write::definition(), - edit::definition(), - bash::definition(), - grep::definition(), - glob_tool::definition(), + tools::read::definition(), + tools::write::definition(), + tools::edit::definition(), + tools::bash::definition(), + tools::grep::definition(), + tools::glob::definition(), ] } /// Return all shared + memory tool definitions. pub fn all_definitions() -> Vec { let mut defs = definitions(); - defs.extend(memory::definitions()); + defs.extend(tools::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()); + let mut defs = tools::memory::definitions(); + defs.extend(tools::memory::journal_definitions()); defs } diff --git a/src/user/runner.rs b/src/agent/runner.rs similarity index 98% rename from src/user/runner.rs rename to src/agent/runner.rs index f925281..e4d2835 100644 --- a/src/user/runner.rs +++ b/src/agent/runner.rs @@ -17,11 +17,11 @@ use anyhow::Result; use tiktoken_rs::CoreBPE; use crate::user::api::ApiClient; -use crate::thought::context as journal; +use crate::agent::context as journal; use crate::user::log::ConversationLog; use crate::user::api::StreamEvent; -use crate::user::tools; -use crate::user::tools::ProcessTracker; +use crate::agent::tools; +use crate::agent::tools::ProcessTracker; use crate::user::types::*; use crate::user::ui_channel::{ContextSection, SharedContextState, StatusInfo, StreamTarget, UiMessage, UiSender}; @@ -77,7 +77,7 @@ pub struct Agent { /// Agent orchestration state (surface-observe, journal, reflect). pub agent_cycles: crate::subconscious::subconscious::AgentCycleState, /// Latest memory importance scores from training scorer. - pub memory_scores: Option, + pub memory_scores: Option, /// Whether a /score task is currently running. pub scoring_in_flight: bool, } @@ -193,8 +193,8 @@ impl Agent { /// every startup/compaction. pub fn budget(&self) -> ContextBudget { let count_str = |s: &str| self.tokenizer.encode_with_special_tokens(s).len(); - let count_msg = |m: &Message| crate::thought::context::msg_token_count(&self.tokenizer, m); - let window = crate::thought::context::context_window(); + let count_msg = |m: &Message| crate::agent::context::msg_token_count(&self.tokenizer, m); + let window = crate::agent::context::context_window(); self.context.budget(&count_str, &count_msg, window) } @@ -339,7 +339,7 @@ impl Agent { // Handle stream errors with retry logic if let Some(e) = stream_error { let err = anyhow::anyhow!("{}", e); - if crate::thought::context::is_context_overflow(&err) && overflow_retries < 2 { + if crate::agent::context::is_context_overflow(&err) && overflow_retries < 2 { overflow_retries += 1; let _ = ui_tx.send(UiMessage::Info(format!( "[context overflow — compacting and retrying ({}/2)]", @@ -348,7 +348,7 @@ impl Agent { self.compact(); continue; } - if crate::thought::context::is_stream_error(&err) && empty_retries < 2 { + if crate::agent::context::is_stream_error(&err) && empty_retries < 2 { empty_retries += 1; let _ = ui_tx.send(UiMessage::Info(format!( "[stream error: {} — retrying ({}/2)]", @@ -791,7 +791,7 @@ impl Agent { // Walk backwards from cutoff, accumulating entries within 15% of context let count = |s: &str| self.tokenizer.encode_with_special_tokens(s).len(); - let context_window = crate::thought::context::context_window(); + let context_window = crate::agent::context::context_window(); let journal_budget = context_window * 15 / 100; dbg_log!("[journal] budget={} tokens ({}*15%)", journal_budget, context_window); @@ -923,7 +923,7 @@ impl Agent { // Dedup memory, trim to budget, reload journal let entries = self.context.entries.clone(); - self.context.entries = crate::thought::context::trim_entries( + self.context.entries = crate::agent::context::trim_entries( &self.context, &entries, &self.tokenizer, diff --git a/src/thought/bash.rs b/src/agent/tools/bash.rs similarity index 100% rename from src/thought/bash.rs rename to src/agent/tools/bash.rs diff --git a/src/user/tools/control.rs b/src/agent/tools/control.rs similarity index 100% rename from src/user/tools/control.rs rename to src/agent/tools/control.rs diff --git a/src/thought/edit.rs b/src/agent/tools/edit.rs similarity index 100% rename from src/thought/edit.rs rename to src/agent/tools/edit.rs diff --git a/src/thought/glob_tool.rs b/src/agent/tools/glob.rs similarity index 100% rename from src/thought/glob_tool.rs rename to src/agent/tools/glob.rs diff --git a/src/thought/grep.rs b/src/agent/tools/grep.rs similarity index 100% rename from src/thought/grep.rs rename to src/agent/tools/grep.rs diff --git a/src/thought/memory.rs b/src/agent/tools/memory.rs similarity index 100% rename from src/thought/memory.rs rename to src/agent/tools/memory.rs diff --git a/src/user/tools/mod.rs b/src/agent/tools/mod.rs similarity index 81% rename from src/user/tools/mod.rs rename to src/agent/tools/mod.rs index fea6487..ad1955c 100644 --- a/src/user/tools/mod.rs +++ b/src/agent/tools/mod.rs @@ -4,15 +4,22 @@ // This module handles agent-specific tools (control, vision, // working_stack) and delegates everything else to thought::dispatch. +// Core tools +pub mod bash; +pub mod edit; +pub mod glob; +pub mod grep; +pub mod memory; +pub mod read; +pub mod write; + +// Agent-specific tools mod control; mod vision; pub mod working_stack; -// Re-export shared infrastructure from thought -pub use crate::thought::{ToolOutput, ProcessTracker, truncate_output}; -pub use crate::thought::memory; - -use crate::user::types::ToolDef; +// Re-export +pub use crate::agent::{ToolDef, ToolOutput, ProcessTracker, truncate_output}; /// Dispatch a tool call by name. /// @@ -39,7 +46,7 @@ pub async fn dispatch( } // Delegate to shared thought layer (poc-agent uses default provenance) - if let Some(output) = crate::thought::dispatch(name, args, tracker, None).await { + if let Some(output) = crate::agent::dispatch(name, args, tracker, None).await { return output; } @@ -53,6 +60,6 @@ pub fn definitions() -> Vec { working_stack::definition(), ]; defs.extend(control::definitions()); - defs.extend(crate::thought::all_definitions()); + defs.extend(crate::agent::all_definitions()); defs } diff --git a/src/thought/read.rs b/src/agent/tools/read.rs similarity index 100% rename from src/thought/read.rs rename to src/agent/tools/read.rs diff --git a/src/user/tools/vision.rs b/src/agent/tools/vision.rs similarity index 100% rename from src/user/tools/vision.rs rename to src/agent/tools/vision.rs diff --git a/src/user/tools/working_stack.rs b/src/agent/tools/working_stack.rs similarity index 100% rename from src/user/tools/working_stack.rs rename to src/agent/tools/working_stack.rs diff --git a/src/thought/write.rs b/src/agent/tools/write.rs similarity index 100% rename from src/thought/write.rs rename to src/agent/tools/write.rs diff --git a/src/thought/training.rs b/src/agent/training.rs similarity index 100% rename from src/thought/training.rs rename to src/agent/training.rs diff --git a/src/bin/consciousness.rs b/src/bin/consciousness.rs index aa89115..39a7324 100644 --- a/src/bin/consciousness.rs +++ b/src/bin/consciousness.rs @@ -32,7 +32,7 @@ use clap::Parser; use poc_memory::dbglog; use poc_memory::user::*; -use poc_memory::user::runner::{Agent, TurnResult}; +use poc_memory::agent::{tools, runner::{Agent, TurnResult}}; use poc_memory::user::api::ApiClient; use poc_memory::user::tui::HotkeyAction; use poc_memory::config::{self, AppConfig, SessionConfig}; @@ -40,7 +40,7 @@ use poc_memory::user::ui_channel::{ContextInfo, StatusInfo, StreamTarget, UiMess /// Compaction threshold — context is rebuilt when prompt tokens exceed this. fn compaction_threshold(app: &AppConfig) -> u32 { - (poc_memory::thought::context::context_window() as u32) * app.compaction.hard_threshold_pct / 100 + (poc_memory::agent::context::context_window() as u32) * app.compaction.hard_threshold_pct / 100 } #[tokio::main] @@ -435,7 +435,7 @@ impl Session { let _ = self.ui_tx.send(UiMessage::Debug("[score] task spawning".into())); tokio::spawn(async move { let _ = ui_tx.send(UiMessage::Debug("[score] task started, calling score_memories".into())); - let result = poc_memory::thought::training::score_memories( + let result = poc_memory::agent::training::score_memories( &context, &client, &ui_tx, ).await; let _ = ui_tx.send(UiMessage::Debug("[score] score_memories returned, acquiring lock".into())); @@ -507,13 +507,6 @@ impl Session { self.update_status(); Command::Handled } - "/test" => { - let _ = self - .ui_tx - .send(UiMessage::Info("Running tool smoke tests...".into())); - run_tool_tests(&self.ui_tx, &self.process_tracker).await; - Command::Handled - } "/retry" => { if self.turn_in_progress { let _ = self @@ -1093,79 +1086,6 @@ fn drain_ui_messages(rx: &mut ui_channel::UiReceiver, app: &mut tui::App) -> boo any } -async fn run_tool_tests(ui_tx: &ui_channel::UiSender, tracker: &tools::ProcessTracker) { - use serde_json::json; - - let tests: Vec<(&str, serde_json::Value, bool)> = vec![ - ("read_file", json!({"file_path": "/etc/hostname"}), true), - ( - "read_file", - json!({"file_path": "/nonexistent/path"}), - false, - ), - ( - "write_file", - json!({"file_path": "/tmp/poc-agent-test.txt", "content": "hello from poc-agent\n"}), - true, - ), - ( - "read_file", - json!({"file_path": "/tmp/poc-agent-test.txt"}), - true, - ), - ( - "edit_file", - json!({"file_path": "/tmp/poc-agent-test.txt", "old_string": "hello", "new_string": "goodbye"}), - true, - ), - ( - "read_file", - json!({"file_path": "/tmp/poc-agent-test.txt"}), - true, - ), - ( - "bash", - json!({"command": "echo 'tool test passed'"}), - true, - ), - ("bash", json!({"command": "sleep 5", "timeout_secs": 1}), false), - ( - "grep", - json!({"pattern": "fn main", "path": "src/", "show_content": true}), - true, - ), - ("glob", json!({"pattern": "src/**/*.rs"}), true), - ("yield_to_user", json!({"message": "test yield"}), true), - ]; - - let mut pass = 0; - let mut fail = 0; - - for (name, args, should_succeed) in &tests { - let output = tools::dispatch(name, args, tracker).await; - let is_error = output.text.starts_with("Error:"); - let ok = if *should_succeed { !is_error } else { is_error }; - - if ok { - let _ = ui_tx.send(UiMessage::Info(format!(" PASS: {}", name))); - pass += 1; - } else { - let _ = ui_tx.send(UiMessage::Info(format!( - " FAIL: {} — {}", - name, - &output.text[..output.text.len().min(100)] - ))); - fail += 1; - } - } - - let _ = std::fs::remove_file("/tmp/poc-agent-test.txt"); - let _ = ui_tx.send(UiMessage::Info(format!( - " {} passed, {} failed", - pass, fail - ))); -} - /// Replay a restored session into the TUI panes so the user can see /// conversation history immediately on restart. Shows user input, /// assistant responses, and brief tool call summaries. Skips the system diff --git a/src/lib.rs b/src/lib.rs index 8d381c7..4517fe0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,7 +27,7 @@ macro_rules! dbglog { pub mod user; // Shared cognitive infrastructure — used by both agent and subconscious -pub mod thought; +pub mod agent; // Memory graph pub mod hippocampus; diff --git a/src/subconscious/api.rs b/src/subconscious/api.rs index 07f5969..d6f1363 100644 --- a/src/subconscious/api.rs +++ b/src/subconscious/api.rs @@ -9,7 +9,7 @@ use crate::user::api::ApiClient; use crate::user::types::*; -use crate::thought::{self, ProcessTracker}; +use crate::agent::{self, ProcessTracker}; use std::sync::OnceLock; @@ -46,7 +46,7 @@ pub async fn call_api_with_tools( let (ui_tx, mut ui_rx) = crate::user::ui_channel::channel(); // All available native tools for subconscious agents - let all_tools = thought::memory_and_journal_definitions(); + let all_tools = agent::memory_and_journal_definitions(); // If agent header specifies a tools whitelist, filter to only those let tool_defs: Vec<_> = if tools.is_empty() { all_tools @@ -175,9 +175,9 @@ pub async fn call_api_with_tools( }; let prov = provenance.borrow().clone(); - let output = match thought::dispatch(&call.function.name, &args, &tracker, Some(&prov)).await { + let output = match agent::dispatch(&call.function.name, &args, &tracker, Some(&prov)).await { Some(out) => out, - None => thought::ToolOutput::error(format!("Unknown tool: {}", call.function.name)), + None => agent::ToolOutput::error(format!("Unknown tool: {}", call.function.name)), }; if std::env::var("POC_AGENT_VERBOSE").is_ok() { diff --git a/src/subconscious/knowledge.rs b/src/subconscious/knowledge.rs index 8f1f7ac..bdf8e6a 100644 --- a/src/subconscious/knowledge.rs +++ b/src/subconscious/knowledge.rs @@ -295,7 +295,7 @@ fn run_one_agent_inner( _llm_tag: &str, log: &(dyn Fn(&str) + Sync), ) -> Result { - let all_tools = crate::thought::memory_and_journal_definitions(); + let all_tools = crate::agent::memory_and_journal_definitions(); let effective_tools: Vec = if def.tools.is_empty() { all_tools.iter().map(|t| t.function.name.clone()).collect() } else { diff --git a/src/user/mod.rs b/src/user/mod.rs index 300b9e0..0d0f859 100644 --- a/src/user/mod.rs +++ b/src/user/mod.rs @@ -11,9 +11,7 @@ pub mod api; pub mod types; -pub mod tools; pub mod ui_channel; -pub mod runner; pub mod cli; pub mod dmn; pub mod identity; diff --git a/src/user/types.rs b/src/user/types.rs index 0452a75..e284cb2 100644 --- a/src/user/types.rs +++ b/src/user/types.rs @@ -410,7 +410,7 @@ impl ConversationEntry { pub struct ContextState { pub system_prompt: String, pub personality: Vec<(String, String)>, - pub journal: Vec, + pub journal: Vec, pub working_stack: Vec, /// Conversation entries — messages and memory, interleaved in order. /// Does NOT include system prompt, personality, or journal.