From 809679b6ce53f252e24fb6e89f7a28f6ac8c96c7 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Thu, 2 Apr 2026 15:35:56 -0400 Subject: [PATCH] delete dead flat-file journal tool and ephemeral stripping Journal entries are written to the memory graph via journal_new/ journal_update, not appended to a flat file. Remove thought/journal.rs (67 lines), strip_ephemeral_tool_calls (55 lines), default_journal_path, and all wiring. -141 lines. Co-Authored-By: Proof of Concept --- src/agent/runner.rs | 65 +--------------------------------------- src/agent/tools/mod.rs | 1 - src/thought/context.rs | 7 ----- src/thought/journal.rs | 67 ------------------------------------------ src/thought/mod.rs | 3 -- 5 files changed, 1 insertion(+), 142 deletions(-) delete mode 100644 src/thought/journal.rs diff --git a/src/agent/runner.rs b/src/agent/runner.rs index dca6e22..df70cad 100644 --- a/src/agent/runner.rs +++ b/src/agent/runner.rs @@ -362,10 +362,7 @@ impl Agent { let msg = crate::agent::api::build_response_message(content, tool_calls); - // Strip ephemeral tool calls (journal) that the API has - // now processed. They're persisted to disk; no need to keep - // them in the conversation history burning tokens. - self.strip_ephemeral_tool_calls(); + if let Some(usage) = &usage { self.last_prompt_tokens = usage.prompt_tokens; @@ -897,66 +894,6 @@ impl Agent { /// Strip ephemeral tool calls from the conversation history. /// - /// Ephemeral tools (like journal) persist their output to disk, - /// so the tool call + result don't need to stay in the context - /// window. We keep them for exactly one API round-trip (the model - /// needs to see the result was acknowledged), then strip them. - /// - /// If an assistant message contains ONLY ephemeral tool calls, - /// the entire message and its tool results are removed. If mixed - /// with non-ephemeral calls, we leave it (rare case, small cost). - fn strip_ephemeral_tool_calls(&mut self) { - // Collect IDs of tool calls to strip - let mut strip_ids: Vec = Vec::new(); - let mut strip_msg_indices: Vec = Vec::new(); - - for (i, entry) in self.context.entries.iter().enumerate() { - let msg = entry.message(); - if msg.role != Role::Assistant { - continue; - } - let calls = match &msg.tool_calls { - Some(c) if !c.is_empty() => c, - _ => continue, - }; - - let all_ephemeral = calls.iter().all(|c| { - c.function.name == tools::journal::TOOL_NAME - }); - - if all_ephemeral { - strip_msg_indices.push(i); - for call in calls { - strip_ids.push(call.id.clone()); - } - } - } - - if strip_ids.is_empty() { - return; - } - - // Remove in reverse order to preserve indices - self.context.entries.retain(|entry| { - let msg = entry.message(); - if msg.role == Role::Assistant { - if let Some(calls) = &msg.tool_calls { - if calls.iter().all(|c| strip_ids.contains(&c.id)) { - return false; - } - } - } - if msg.role == Role::Tool { - if let Some(ref id) = msg.tool_call_id { - if strip_ids.contains(id) { - return false; - } - } - } - true - }); - } - /// Last prompt token count reported by the API. pub fn last_prompt_tokens(&self) -> u32 { self.last_prompt_tokens diff --git a/src/agent/tools/mod.rs b/src/agent/tools/mod.rs index d41b5a2..e86231c 100644 --- a/src/agent/tools/mod.rs +++ b/src/agent/tools/mod.rs @@ -11,7 +11,6 @@ pub mod working_stack; // Re-export shared infrastructure from thought pub use crate::thought::{ToolOutput, ProcessTracker, truncate_output}; pub use crate::thought::memory; -pub use crate::thought::journal; use crate::agent::types::ToolDef; diff --git a/src/thought/context.rs b/src/thought/context.rs index 0dd5dc2..8c82edf 100644 --- a/src/thought/context.rs +++ b/src/thought/context.rs @@ -15,13 +15,6 @@ pub struct JournalEntry { pub content: String, } -/// Default journal file path (used by the write path only). -pub fn default_journal_path() -> std::path::PathBuf { - dirs::home_dir() - .unwrap_or_default() - .join(".consciousness/journal.md") -} - /// Look up a model's context window size in tokens. pub fn model_context_window(_model: &str) -> usize { crate::config::get().api_context_window diff --git a/src/thought/journal.rs b/src/thought/journal.rs deleted file mode 100644 index 306b286..0000000 --- a/src/thought/journal.rs +++ /dev/null @@ -1,67 +0,0 @@ -// tools/journal.rs — Native journal tool -// -// Appends entries directly to the journal file without spawning a -// shell. The entry is persisted to disk immediately. -// -// This tool is "ephemeral" — after the API processes the tool call -// and result, the agent strips them from the conversation history. -// The journal file is the durable store; keeping the tool call in -// context would just waste tokens on something already persisted. - -use anyhow::{Context, Result}; -use serde_json::json; - -use super::ToolDef; - -/// Tool name — used by the agent to identify ephemeral tool calls. -pub const TOOL_NAME: &str = "journal"; - -pub fn definition() -> ToolDef { - ToolDef::new( - TOOL_NAME, - "Write a journal entry. The entry is appended to your journal file \ - with an automatic timestamp. Use this for experiences, reflections, \ - observations — anything worth remembering across sessions. \ - This tool has zero context cost: entries are persisted to disk \ - and loaded by the context manager, not kept in conversation history.", - json!({ - "type": "object", - "properties": { - "entry": { - "type": "string", - "description": "The journal entry text. Write naturally — \ - experiences, not task logs." - } - }, - "required": ["entry"] - }), - ) -} - -pub fn write_entry(args: &serde_json::Value) -> Result { - let entry = args["entry"] - .as_str() - .context("entry is required")?; - - let journal_path = crate::thought::context::default_journal_path(); - - // Ensure parent directory exists - if let Some(parent) = journal_path.parent() { - std::fs::create_dir_all(parent).ok(); - } - - let timestamp = chrono::Utc::now().format("%Y-%m-%dT%H:%M"); - - // Append with the same format as poc-journal write - use std::io::Write; - let mut file = std::fs::OpenOptions::new() - .create(true) - .append(true) - .open(&journal_path) - .with_context(|| format!("Failed to open {}", journal_path.display()))?; - - writeln!(file, "\n## {}\n\n{}", timestamp, entry) - .with_context(|| "Failed to write journal entry")?; - - Ok("Logged.".to_string()) -} diff --git a/src/thought/mod.rs b/src/thought/mod.rs index 7c25db8..327e60d 100644 --- a/src/thought/mod.rs +++ b/src/thought/mod.rs @@ -13,7 +13,6 @@ pub mod context; pub mod edit; pub mod glob_tool; pub mod grep; -pub mod journal; pub mod memory; pub mod read; pub mod write; @@ -93,7 +92,6 @@ pub async fn dispatch( "bash" => bash::run_bash(args, tracker).await, "grep" => grep::grep(args), "glob" => glob_tool::glob_search(args), - "journal" => journal::write_entry(args), _ => return None, }; @@ -112,7 +110,6 @@ pub fn definitions() -> Vec { bash::definition(), grep::definition(), glob_tool::definition(), - journal::definition(), ] }