TestPackDropsDanglingAssistantToolCalls: a turn cancelled mid-tool leaves an assistant.tool_calls in history with no answering tool message (the TUI appended it on round close, then endTurn dropped the pending call on Ctrl+C). On the next request Pack must strip that dangling assistant, otherwise th
(t *testing.T)
| 283 | }}, |
| 284 | {Role: RoleTool, ToolCallID: "c1", Content: "out1"}, // c2 result never arrived |
| 285 | } |
| 286 | r := Pack(history, 300) // forces the budget walk + drops to empty, then recovery |
| 287 | for _, m := range r.Messages { |
| 288 | if m.Role == RoleAssistant && len(m.ToolCalls) > 0 { |
| 289 | t.Fatalf("dangling partial-parallel assistant reached the wire: %+v", r.Messages) |
| 290 | } |
| 291 | if m.Role == RoleTool { |
| 292 | t.Fatalf("orphaned tool survived after its assistant was dropped: %+v", r.Messages) |
| 293 | } |
| 294 | } |
| 295 | } |
| 296 | |
| 297 | // TestPackDropsDanglingAssistantToolCalls: a turn cancelled mid tool leaves an |
| 298 | // assistant.tool_calls in history with no answering tool message (the TUI |
| 299 | // appended it on round close, then endTurn dropped the pending call on Ctrl+C). |
| 300 | // On the next request Pack must strip that dangling assistant, otherwise the |
| 301 | // wire carries an unanswered tool_calls and every OpenAI compat backend 400s. |
| 302 | func TestPackDropsDanglingAssistantToolCalls(t *testing.T) { |
| 303 | history := []Message{ |
| 304 | {Role: RoleUser, Content: "run a long thing"}, |
| 305 | {Role: RoleAssistant, ToolCalls: []ToolCall{{ID: "c1", Name: "bash"}}}, |