From 42f1e888c4ba73a5a595227d6bc8f76fe5750b80 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Thu, 2 Apr 2026 02:00:14 -0400 Subject: [PATCH] Journal: flat 5% context window budget, skip plan_context Render journal entries directly with ## headers instead of going through the plan_context/render_journal_text pipeline. 5% of model context window (~6500 tokens for Qwen 128K). Simpler and predictable. Co-Authored-By: Proof of Concept --- src/agent/runner.rs | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/agent/runner.rs b/src/agent/runner.rs index dd22d66..8823b95 100644 --- a/src/agent/runner.rs +++ b/src/agent/runner.rs @@ -816,15 +816,17 @@ impl Agent { journal_nodes.len() }; - // Walk backwards from cutoff, accumulating entries within token budget + // Walk backwards from cutoff, accumulating entries within 5% of context let count = |s: &str| self.tokenizer.encode_with_special_tokens(s).len(); - let journal_budget_tokens = 10_000; // ~8% of 128K context + let context_window = crate::agent::context::model_context_window(&self.client.model); + let journal_budget = context_window * 5 / 100; + let mut entries = Vec::new(); let mut total_tokens = 0; for node in journal_nodes[..cutoff_idx].iter().rev() { let tokens = count(&node.content); - if total_tokens + tokens > journal_budget_tokens && !entries.is_empty() { + if total_tokens + tokens > journal_budget && !entries.is_empty() { break; } entries.push(journal::JournalEntry { @@ -834,23 +836,19 @@ impl Agent { }); total_tokens += tokens; } - entries.reverse(); // chronological order + entries.reverse(); if entries.is_empty() { return; } - let context_message = self.context.render_context_message(); - let plan = crate::agent::context::plan_context( - &self.context.system_prompt, - &context_message, - &[], - &entries, - &self.client.model, - &count, - ); - - self.context.journal = crate::agent::context::render_journal_text(&entries, &plan); + // Render directly — no plan_context needed + let mut text = String::from("[Earlier — from your journal]\n\n"); + for entry in &entries { + use std::fmt::Write; + writeln!(text, "## {}\n{}\n", entry.timestamp.format("%Y-%m-%dT%H:%M"), entry.content).ok(); + } + self.context.journal = text; } /// Re-render the context message in self.messages from live ContextState.