diff --git a/pkg/agent/context.go b/pkg/agent/context.go index a9db5afdd..661fc0a04 100644 --- a/pkg/agent/context.go +++ b/pkg/agent/context.go @@ -221,6 +221,9 @@ func sanitizeHistoryForProvider(history []providers.Message) []providers.Message return history } + // Repair orphaned tool_use/tool_result pairs before further sanitization. + history = repairOrphanedToolPairs(history) + sanitized := make([]providers.Message, 0, len(history)) for _, msg := range history { switch msg.Role { diff --git a/pkg/agent/sanitize_test.go b/pkg/agent/sanitize_test.go index 151c35936..6a848b7d9 100644 --- a/pkg/agent/sanitize_test.go +++ b/pkg/agent/sanitize_test.go @@ -78,6 +78,25 @@ func TestRepairOrphanedToolPairs_OrphanToolResultDropped(t *testing.T) { } } +func TestSanitizeHistoryForProvider_OrphanToolUseRepaired(t *testing.T) { + history := []providers.Message{ + {Role: "user", Content: "do something"}, + { + Role: "assistant", Content: "calling tool", + ToolCalls: []providers.ToolCall{{ID: "call_99", Name: "exec"}}, + }, + } + sanitized := sanitizeHistoryForProvider(history) + + if len(sanitized) != 3 { + t.Fatalf("expected 3 messages, got %d", len(sanitized)) + } + if sanitized[2].Role != "tool" || sanitized[2].ToolCallID != "call_99" { + t.Errorf("expected synthetic tool_result for call_99, got role=%q id=%q", + sanitized[2].Role, sanitized[2].ToolCallID) + } +} + func TestRepairOrphanedToolPairs_EmptyInput(t *testing.T) { repaired := repairOrphanedToolPairs(nil) if len(repaired) != 0 {