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:
parent
776ac527f1
commit
62996e27d7
10 changed files with 450 additions and 403 deletions
|
|
@ -16,7 +16,8 @@ use ratatui::{
|
|||
|
||||
use super::{App, ScreenView, screen_legend};
|
||||
use super::widgets::{SectionTree, pane_block_focused, render_scrollable, tree_legend, format_age, format_ts_age};
|
||||
use crate::agent::context::ContextSection;
|
||||
use crate::agent::context::{ContextSection, ContextEntry, ConversationEntry};
|
||||
use crate::agent::api::Message;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
enum Pane { Agents, Outputs, History, Context }
|
||||
|
|
@ -135,12 +136,13 @@ impl SubconsciousScreen {
|
|||
None => return Vec::new(),
|
||||
};
|
||||
snap.state.iter().map(|(key, val)| {
|
||||
ContextSection {
|
||||
name: key.clone(),
|
||||
let mut section = ContextSection::new(key.clone());
|
||||
section.push(ContextEntry {
|
||||
entry: ConversationEntry::Message(Message::user(val)),
|
||||
tokens: 0,
|
||||
content: val.clone(),
|
||||
children: Vec::new(),
|
||||
}
|
||||
timestamp: None,
|
||||
});
|
||||
section
|
||||
}).collect()
|
||||
}
|
||||
|
||||
|
|
@ -151,7 +153,15 @@ impl SubconsciousScreen {
|
|||
};
|
||||
snap.forked_agent.as_ref()
|
||||
.and_then(|agent| agent.try_lock().ok())
|
||||
.map(|ag| ag.conversation_sections_from(snap.fork_point))
|
||||
.map(|ag| {
|
||||
// Build a single section from the forked conversation entries
|
||||
let entries = ag.conversation_entries_from(snap.fork_point);
|
||||
let mut section = ContextSection::new("Conversation");
|
||||
for e in entries {
|
||||
section.push(e.clone());
|
||||
}
|
||||
vec![section]
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
|
|
@ -172,7 +182,7 @@ impl SubconsciousScreen {
|
|||
.unwrap_or_else(|| "—".to_string());
|
||||
let entries = snap.forked_agent.as_ref()
|
||||
.and_then(|a| a.try_lock().ok())
|
||||
.map(|ag| ag.context.entries.len().saturating_sub(snap.fork_point))
|
||||
.map(|ag| ag.context.conversation.len().saturating_sub(snap.fork_point))
|
||||
.unwrap_or(0);
|
||||
ListItem::from(Line::from(vec![
|
||||
Span::styled(&snap.name, Style::default().fg(Color::Gray)),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue