fix: remove cancelled tool calls from assistant messages

After interrupt, tool results with cancelled status are removed but
the assistant message kept its ToolCalls referencing them, causing
'Improperly formed request' errors.

Now also strips cancelled tool call IDs from assistant messages.
Only removes the assistant message entirely if it has zero remaining
tool calls AND no text content.
This commit is contained in:
Levi Neely 2026-05-04 16:54:04 +02:00
parent e6233626bc
commit 1279f10218
1 changed files with 29 additions and 3 deletions

View File

@ -147,14 +147,40 @@ func (s *Session) update(assistant backend.Message, results []toolResult) {
}
// removeCancelledToolResults filters out tool results that were cancelled due
// to interrupt, keeping completed work (user messages, assistant, successful
// and errored tool results).
// to interrupt, keeping completed work. Also removes the corresponding tool
// calls from assistant messages to maintain a valid message sequence.
func (s *Session) removeCancelledToolResults() {
filtered := s.messages[:0]
// First pass: collect cancelled tool call IDs
cancelled := make(map[string]bool)
for _, m := range s.messages {
if m.Role == "tool" && isCancelledToolResult(m.Content) {
cancelled[m.ToolCallID] = true
}
}
if len(cancelled) == 0 {
return
}
// Second pass: filter messages and prune tool calls from assistant messages
filtered := s.messages[:0]
for _, m := range s.messages {
if m.Role == "tool" && cancelled[m.ToolCallID] {
continue
}
if m.Role == "assistant" && len(m.ToolCalls) > 0 {
// Remove cancelled tool calls from this assistant message
kept := m.ToolCalls[:0]
for _, tc := range m.ToolCalls {
if !cancelled[tc.ID] {
kept = append(kept, tc)
}
}
if len(kept) == 0 && m.Content == "" {
// All tool calls cancelled and no text content - skip message
continue
}
m.ToolCalls = kept
}
filtered = append(filtered, m)
}
s.messages = filtered