WIP: ContextEntry/ContextSection data structures for incremental token counting

New types — not yet wired to callers:

- ContextEntry: wraps ConversationEntry with cached token count and
  timestamp
- ContextSection: named group of entries with cached token total.
  Private entries/tokens, read via entries()/tokens().
  Mutation via push(entry), set(index, entry), del(index).
- ContextState: system/identity/journal/conversation sections + working_stack
- ConversationEntry::System variant for system prompt entries

Token counting happens once at push time. Sections maintain their
totals incrementally via push/set/del. No more recomputing from
scratch on every budget check.

Does not compile — callers need updating.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
Kent Overstreet 2026-04-07 20:15:31 -04:00
parent 776ac527f1
commit 62996e27d7
10 changed files with 450 additions and 403 deletions

View file

@ -23,9 +23,9 @@ impl ConsciousScreen {
Self { agent, tree: SectionTree::new() }
}
fn read_context_state(&self) -> Vec<crate::agent::context::ContextSection> {
fn read_context_sections(&self) -> Vec<crate::agent::context::ContextSection> {
match self.agent.try_lock() {
Ok(ag) => ag.context_state_summary(),
Ok(ag) => ag.context_sections().iter().map(|s| (*s).clone()).collect(),
Err(_) => Vec::new(),
}
}
@ -39,7 +39,7 @@ impl ScreenView for ConsciousScreen {
for event in events {
if let ratatui::crossterm::event::Event::Key(key) = event {
if key.kind != ratatui::crossterm::event::KeyEventKind::Press { continue; }
let context_state = self.read_context_state();
let context_state = self.read_context_sections();
self.tree.handle_nav(key.code, &context_state, area.height);
}
}
@ -64,9 +64,9 @@ impl ScreenView for ConsciousScreen {
if !app.status.context_budget.is_empty() {
lines.push(Line::raw(format!(" Budget: {}", app.status.context_budget)));
}
let context_state = self.read_context_state();
let context_state = self.read_context_sections();
if !context_state.is_empty() {
let total: usize = context_state.iter().map(|s| s.tokens).sum();
let total: usize = context_state.iter().map(|s| s.tokens()).sum();
lines.push(Line::raw(""));
lines.push(Line::styled(
" (↑/↓ select, →/Enter expand, ← collapse, PgUp/PgDn scroll)",