Fix Thinking/Log panics: skip entries with empty token_ids

Entries with empty token_ids (Thinking, Log) are not part of the
prompt and don't have messages. Skip them in streaming_index(),
route_entry(), and sync_from_agent() instead of calling .message()
which panics.

Using token_ids.is_empty() as the guard in streaming_index means
the check is tied to the data, not the type — any entry that
doesn't produce tokens is safely skipped.

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
Kent Overstreet 2026-04-08 12:05:49 -04:00
parent cb64cdf5fe
commit 603d58e686
2 changed files with 8 additions and 3 deletions

View file

@ -370,6 +370,7 @@ impl Agent {
/// Find the index of the in-progress streaming entry (unstamped assistant message).
fn streaming_index(&self) -> Option<usize> {
self.context.conversation.entries().iter().rposition(|ce| {
if ce.token_ids.is_empty() { return false; }
let m = ce.entry.message();
m.role == Role::Assistant && m.timestamp.is_none()
})

View file

@ -417,8 +417,11 @@ impl InteractScreen {
use crate::agent::api::Role;
use crate::agent::context::ConversationEntry;
if let ConversationEntry::Memory { .. } = entry {
return vec![];
match entry {
ConversationEntry::Memory { .. }
| ConversationEntry::Thinking(_)
| ConversationEntry::Log(_) => return vec![],
_ => {}
}
let msg = entry.message();
@ -489,7 +492,8 @@ impl InteractScreen {
}
// Only stop at assistant if it matches - otherwise keep going
if matches && self.last_entries[i].entry.message().role == Role::Assistant {
if matches && !self.last_entries[i].token_ids.is_empty()
&& self.last_entries[i].entry.message().role == Role::Assistant {
break;
}
}