forked from kent/consciousness
Restore context tree display with SectionView UI type
Introduced SectionView {name, tokens, content, children} as a
UI-only tree node, separate from the data ContextSection. The widget
SectionTree renders SectionView with the old recursive expand/collapse
behavior — children for sub-sections, content for text expansion.
section_to_view() converts data sections to UI views, using
ConversationEntry::label() for names and content_text() for
expandable content.
read_context_views() builds the same tree the old context_state_summary
did: System, Identity, Journal, Memory nodes (scored/unscored counts,
expandable to show content), Conversation entries.
Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
parent
613704720b
commit
07b400c95c
3 changed files with 132 additions and 105 deletions
|
|
@ -11,7 +11,7 @@ use ratatui::{
|
|||
};
|
||||
|
||||
use super::{App, ScreenView, screen_legend};
|
||||
use super::widgets::{SectionTree, pane_block, render_scrollable, tree_legend};
|
||||
use super::widgets::{SectionTree, SectionView, section_to_view, pane_block, render_scrollable, tree_legend};
|
||||
|
||||
pub(crate) struct ConsciousScreen {
|
||||
agent: std::sync::Arc<tokio::sync::Mutex<crate::agent::Agent>>,
|
||||
|
|
@ -23,42 +23,53 @@ impl ConsciousScreen {
|
|||
Self { agent, tree: SectionTree::new() }
|
||||
}
|
||||
|
||||
fn read_context_sections(&self) -> Vec<crate::agent::context::ContextSection> {
|
||||
use crate::agent::context::{ContextSection, ContextEntry, ConversationEntry};
|
||||
use crate::agent::api::Message;
|
||||
fn read_context_views(&self) -> Vec<SectionView> {
|
||||
use crate::agent::context::ConversationEntry;
|
||||
|
||||
let ag = match self.agent.try_lock() {
|
||||
Ok(ag) => ag,
|
||||
Err(_) => return Vec::new(),
|
||||
};
|
||||
|
||||
let mut sections: Vec<ContextSection> = ag.context_sections()
|
||||
.iter().map(|s| (*s).clone()).collect();
|
||||
let mut views: Vec<SectionView> = Vec::new();
|
||||
|
||||
// Build a synthetic "Memory nodes" section from conversation entries
|
||||
let mut mem_section = ContextSection::new("Memory nodes");
|
||||
// System, Identity, Journal — simple section-to-view
|
||||
views.push(section_to_view(&ag.context.system));
|
||||
views.push(section_to_view(&ag.context.identity));
|
||||
views.push(section_to_view(&ag.context.journal));
|
||||
|
||||
// Memory nodes — extracted from conversation, shown as children
|
||||
let mut mem_children: Vec<SectionView> = Vec::new();
|
||||
let mut scored = 0usize;
|
||||
let mut unscored = 0usize;
|
||||
for ce in ag.context.conversation.entries() {
|
||||
if let ConversationEntry::Memory { key, score, .. } = &ce.entry {
|
||||
let label = match score {
|
||||
Some(s) => { scored += 1; format!("{} (score:{:.2})", key, s) }
|
||||
Some(s) => { scored += 1; format!("{} (score:{:.1})", key, s) }
|
||||
None => { unscored += 1; key.clone() }
|
||||
};
|
||||
mem_section.push(ContextEntry {
|
||||
entry: ConversationEntry::Message(Message::user(&label)),
|
||||
mem_children.push(SectionView {
|
||||
name: label,
|
||||
tokens: ce.tokens,
|
||||
timestamp: ce.timestamp,
|
||||
content: ce.entry.message().content_text().to_string(),
|
||||
children: Vec::new(),
|
||||
});
|
||||
}
|
||||
}
|
||||
if !mem_section.is_empty() {
|
||||
mem_section.name = format!("Memory nodes ({} scored, {} unscored)",
|
||||
scored, unscored);
|
||||
sections.insert(sections.len() - 1, mem_section); // before conversation
|
||||
if !mem_children.is_empty() {
|
||||
let mem_tokens: usize = mem_children.iter().map(|c| c.tokens).sum();
|
||||
views.push(SectionView {
|
||||
name: format!("Memory nodes ({} scored, {} unscored)", scored, unscored),
|
||||
tokens: mem_tokens,
|
||||
content: String::new(),
|
||||
children: mem_children,
|
||||
});
|
||||
}
|
||||
|
||||
sections
|
||||
// Conversation — each entry as a child
|
||||
views.push(section_to_view(&ag.context.conversation));
|
||||
|
||||
views
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -70,7 +81,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_sections();
|
||||
let context_state = self.read_context_views();
|
||||
self.tree.handle_nav(key.code, &context_state, area.height);
|
||||
}
|
||||
}
|
||||
|
|
@ -95,9 +106,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_sections();
|
||||
let context_state = self.read_context_views();
|
||||
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)",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue