From 99c32714f1b4f9d9495b94c2a08b39d318490bd2 Mon Sep 17 00:00:00 2001 From: mrbeandev Date: Tue, 17 Feb 2026 11:29:29 +0530 Subject: [PATCH] fix(antigravity): sanitize invalid tool-call history ordering --- pkg/agent/context.go | 63 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 14 deletions(-) diff --git a/pkg/agent/context.go b/pkg/agent/context.go index cf5ce2913..27e3ef9dc 100644 --- a/pkg/agent/context.go +++ b/pkg/agent/context.go @@ -189,16 +189,7 @@ func (cb *ContextBuilder) BuildMessages(history []providers.Message, summary str systemPrompt += "\n\n## Summary of Previous Conversation\n\n" + summary } - //This fix prevents the session memory from LLM failure due to elimination of toolu_IDs required from LLM - // --- INICIO DEL FIX --- - //Diegox-17 - for len(history) > 0 && (history[0].Role == "tool") { - logger.DebugCF("agent", "Removing orphaned tool message from history to prevent LLM error", - map[string]interface{}{"role": history[0].Role}) - history = history[1:] - } - //Diegox-17 - // --- FIN DEL FIX --- + history = sanitizeHistoryForProvider(history) messages = append(messages, providers.Message{ Role: "system", @@ -207,14 +198,58 @@ func (cb *ContextBuilder) BuildMessages(history []providers.Message, summary str messages = append(messages, history...) - messages = append(messages, providers.Message{ - Role: "user", - Content: currentMessage, - }) + if strings.TrimSpace(currentMessage) != "" { + messages = append(messages, providers.Message{ + Role: "user", + Content: currentMessage, + }) + } return messages } +func sanitizeHistoryForProvider(history []providers.Message) []providers.Message { + if len(history) == 0 { + return history + } + + sanitized := make([]providers.Message, 0, len(history)) + for _, msg := range history { + switch msg.Role { + case "tool": + if len(sanitized) == 0 { + logger.DebugCF("agent", "Dropping orphaned leading tool message", map[string]interface{}{}) + continue + } + last := sanitized[len(sanitized)-1] + if last.Role != "assistant" || len(last.ToolCalls) == 0 { + logger.DebugCF("agent", "Dropping orphaned tool message", map[string]interface{}{}) + continue + } + sanitized = append(sanitized, msg) + + case "assistant": + if len(msg.ToolCalls) > 0 { + if len(sanitized) == 0 { + logger.DebugCF("agent", "Dropping assistant tool-call turn at history start", map[string]interface{}{}) + continue + } + prev := sanitized[len(sanitized)-1] + if prev.Role != "user" && prev.Role != "tool" { + logger.DebugCF("agent", "Dropping assistant tool-call turn with invalid predecessor", map[string]interface{}{"prev_role": prev.Role}) + continue + } + } + sanitized = append(sanitized, msg) + + default: + sanitized = append(sanitized, msg) + } + } + + return sanitized +} + func (cb *ContextBuilder) AddToolResult(messages []providers.Message, toolCallID, toolName, result string) []providers.Message { messages = append(messages, providers.Message{ Role: "tool",