consciousness/src/thought/journal.rs
Kent Overstreet 01bfbc0dad move journal types from agent/journal.rs to thought/context.rs
JournalEntry, parse_journal, parse_journal_text, parse_header_timestamp,
and default_journal_path consolidated into thought/context.rs. Delete
the duplicate agent/journal.rs (235 lines). Update all references.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
2026-04-02 15:25:07 -04:00

68 lines
2.3 KiB
Rust

// tools/journal.rs — Native journal tool
//
// Appends entries directly to the journal file without spawning a
// shell. The entry is persisted to disk immediately;
// build_context_window() picks it up on the next compaction.
//
// 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<String> {
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())
}