Fix chat display: restore incremental sync with change detection
sync_from_agent now detects changed entries by comparing token counts (cheap proxy for content changes during streaming). Changed entries get popped and re-pushed. Extracted push_routed/pop_routed helpers. Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
parent
31e813f57d
commit
5f5a8a807c
1 changed files with 61 additions and 25 deletions
|
|
@ -456,35 +456,7 @@ impl InteractScreen {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sync_from_agent(&mut self) {
|
fn push_routed(&mut self, node: &AstNode) {
|
||||||
for _ in 0..self.pending_display_count {
|
|
||||||
self.conversation.pop_line();
|
|
||||||
}
|
|
||||||
self.pending_display_count = 0;
|
|
||||||
|
|
||||||
let (generation, entries) = {
|
|
||||||
let st = match self.agent.state.try_lock() {
|
|
||||||
Ok(st) => st,
|
|
||||||
Err(_) => return,
|
|
||||||
};
|
|
||||||
let generation = st.generation;
|
|
||||||
drop(st);
|
|
||||||
let ctx = match self.agent.context.try_lock() {
|
|
||||||
Ok(ctx) => ctx,
|
|
||||||
Err(_) => return,
|
|
||||||
};
|
|
||||||
(generation, ctx.conversation().to_vec())
|
|
||||||
};
|
|
||||||
|
|
||||||
if generation != self.last_generation || entries.len() < self.last_entries.len() {
|
|
||||||
self.conversation = PaneState::new(true);
|
|
||||||
self.autonomous = PaneState::new(true);
|
|
||||||
self.tools = PaneState::new(false);
|
|
||||||
self.last_entries.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
let start = self.last_entries.len();
|
|
||||||
for node in entries.iter().skip(start) {
|
|
||||||
for (target, text, marker) in Self::route_node(node) {
|
for (target, text, marker) in Self::route_node(node) {
|
||||||
match target {
|
match target {
|
||||||
PaneTarget::Conversation => {
|
PaneTarget::Conversation => {
|
||||||
|
|
@ -508,6 +480,70 @@ impl InteractScreen {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pop_routed(&mut self, node: &AstNode) {
|
||||||
|
for (target, _, _) in Self::route_node(node) {
|
||||||
|
match target {
|
||||||
|
PaneTarget::Conversation | PaneTarget::ConversationAssistant
|
||||||
|
=> self.conversation.pop_line(),
|
||||||
|
PaneTarget::Tools | PaneTarget::ToolResult
|
||||||
|
=> self.tools.pop_line(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sync_from_agent(&mut self) {
|
||||||
|
for _ in 0..self.pending_display_count {
|
||||||
|
self.conversation.pop_line();
|
||||||
|
}
|
||||||
|
self.pending_display_count = 0;
|
||||||
|
|
||||||
|
let (generation, entries) = {
|
||||||
|
let st = match self.agent.state.try_lock() {
|
||||||
|
Ok(st) => st,
|
||||||
|
Err(_) => return,
|
||||||
|
};
|
||||||
|
let generation = st.generation;
|
||||||
|
drop(st);
|
||||||
|
let ctx = match self.agent.context.try_lock() {
|
||||||
|
Ok(ctx) => ctx,
|
||||||
|
Err(_) => return,
|
||||||
|
};
|
||||||
|
(generation, ctx.conversation().to_vec())
|
||||||
|
};
|
||||||
|
|
||||||
|
// Full reset on generation change
|
||||||
|
if generation != self.last_generation {
|
||||||
|
self.conversation = PaneState::new(true);
|
||||||
|
self.autonomous = PaneState::new(true);
|
||||||
|
self.tools = PaneState::new(false);
|
||||||
|
self.last_entries.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect changed entries (streaming updates mutate the last entry)
|
||||||
|
// Walk backwards from the end, pop any that differ
|
||||||
|
let mut pop_from = self.last_entries.len();
|
||||||
|
for i in (0..self.last_entries.len()).rev() {
|
||||||
|
if i >= entries.len() {
|
||||||
|
pop_from = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Compare token count as a cheap change detector
|
||||||
|
if self.last_entries[i].tokens() != entries[i].tokens() {
|
||||||
|
pop_from = i;
|
||||||
|
} else {
|
||||||
|
break; // entries before this haven't changed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while self.last_entries.len() > pop_from {
|
||||||
|
let popped = self.last_entries.pop().unwrap();
|
||||||
|
self.pop_routed(&popped);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push new/changed entries
|
||||||
|
for node in entries.iter().skip(self.last_entries.len()) {
|
||||||
|
self.push_routed(node);
|
||||||
self.last_entries.push(node.clone());
|
self.last_entries.push(node.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue