chat: full entry type routing in sync_from_agent

Route agent entries to correct panes:
- User messages → conversation (cyan, User marker)
- Assistant text → conversation (Assistant marker)
- Assistant tool_calls → tools pane (yellow)
- Tool results → tools pane (truncated at 20 lines)
- Memory/system-reminder entries → skipped
- System role → skipped

Two phases: detect generation change (reset panes if needed),
then route new entries. PaneState is the rendered view of agent
entries, updated incrementally.

Co-Authored-By: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2026-04-05 19:22:31 -04:00
parent 350c447ebc
commit b89bafdf6b

View file

@ -61,6 +61,8 @@ impl InteractScreen {
/// Sync conversation display from agent entries. /// Sync conversation display from agent entries.
fn sync_from_agent(&mut self) { fn sync_from_agent(&mut self) {
use crate::agent::api::types::Role;
let agent = self.agent.blocking_lock(); let agent = self.agent.blocking_lock();
let gen = agent.generation; let gen = agent.generation;
let count = agent.entries().len(); let count = agent.entries().len();
@ -74,23 +76,54 @@ impl InteractScreen {
} }
// Render new entries // Render new entries
if count > self.last_entry_count { for entry in agent.entries().iter().skip(self.last_entry_count) {
for entry in &agent.entries()[self.last_entry_count..] {
let msg = entry.message(); let msg = entry.message();
let text = msg.content_text(); let text = msg.content_text();
// Skip memory/system-reminder entries — they're context, not conversation
if let crate::agent::context::ConversationEntry::Memory { .. } = entry {
continue;
}
match msg.role { match msg.role {
crate::agent::api::types::Role::User => { Role::User => {
// Skip system-reminder injections
if text.starts_with("<system-reminder>") {
continue;
}
self.conversation.push_line_with_marker( self.conversation.push_line_with_marker(
text.to_string(), Color::Cyan, Marker::User, text.to_string(), Color::Cyan, Marker::User,
); );
} }
crate::agent::api::types::Role::Assistant => { Role::Assistant => {
// Tool calls show in tools pane
if let Some(ref calls) = msg.tool_calls {
for call in calls {
let line = format!("[{}] {}", call.function.name,
call.function.arguments.chars().take(80).collect::<String>());
self.tools.push_line(line, Color::Yellow);
}
}
// Text content to conversation
if !text.is_empty() {
self.conversation.push_line_with_marker( self.conversation.push_line_with_marker(
text.to_string(), Color::Reset, Marker::Assistant, text.to_string(), Color::Reset, Marker::Assistant,
); );
} }
_ => {}
} }
Role::Tool => {
// Tool results to tools pane
for line in text.lines().take(20) {
self.tools.push_line(format!(" {}", line), Color::DarkGray);
}
if text.lines().count() > 20 {
self.tools.push_line(
format!(" ... ({} more lines)", text.lines().count() - 20),
Color::DarkGray,
);
}
}
Role::System => {} // skip
} }
} }