diff --git a/internal/translator/kiro/openai/kiro_openai_request.go b/internal/translator/kiro/openai/kiro_openai_request.go index 93914c6d..a621eebc 100644 --- a/internal/translator/kiro/openai/kiro_openai_request.go +++ b/internal/translator/kiro/openai/kiro_openai_request.go @@ -576,9 +576,23 @@ func processOpenAIMessages(messages gjson.Result, modelID, origin string) ([]Kir } } + // Truncate history if too long to prevent Kiro API errors + history = truncateHistoryIfNeeded(history) + return history, currentUserMsg, currentToolResults } +const kiroMaxHistoryMessages = 50 + +func truncateHistoryIfNeeded(history []KiroHistoryMessage) []KiroHistoryMessage { + if len(history) <= kiroMaxHistoryMessages { + return history + } + + log.Debugf("kiro-openai: truncating history from %d to %d messages", len(history), kiroMaxHistoryMessages) + return history[len(history)-kiroMaxHistoryMessages:] +} + // buildUserMessageFromOpenAI builds a user message from OpenAI format and extracts tool results func buildUserMessageFromOpenAI(msg gjson.Result, modelID, origin string) (KiroUserInputMessage, []KiroToolResult) { content := msg.Get("content") @@ -677,8 +691,20 @@ func buildAssistantMessageFromOpenAI(msg gjson.Result) KiroAssistantResponseMess } } + // CRITICAL FIX: Kiro API requires non-empty content for assistant messages + // This can happen with compaction requests or error recovery scenarios + finalContent := contentBuilder.String() + if strings.TrimSpace(finalContent) == "" { + if len(toolUses) > 0 { + finalContent = "I'll help you with that." + } else { + finalContent = "I understand." + } + log.Debugf("kiro-openai: assistant content was empty, using default: %s", finalContent) + } + return KiroAssistantResponseMessage{ - Content: contentBuilder.String(), + Content: finalContent, ToolUses: toolUses, } }