Compare commits

..

8 Commits

Author SHA1 Message Date
Luis Pater
e7e3ca1efb Merge branch 'router-for-me:main' into main 2026-02-06 05:45:21 +08:00
Luis Pater
4b00312fef Merge pull request #1435 from tianyicui/fix/haiku-4-5-thinking-support
fix: Enable extended thinking support for Claude Haiku 4.5
2026-02-06 05:44:14 +08:00
Luis Pater
c5fd3db01e Merge pull request #1446 from qyhfrank/fix-claude-opus-4-6-model-metadata
fix(registry): correct Claude Opus 4.6 model metadata
2026-02-06 05:43:32 +08:00
Luis Pater
e35ffaa925 Merge pull request #186 from taetaetae/fix/kiro-claude-compaction-empty-content
fix(kiro): handle empty content in Claude format assistant messages
2026-02-06 05:39:41 +08:00
Frank Qing
f870a9d2a7 fix(registry): correct Claude Opus 4.6 model metadata 2026-02-06 05:39:41 +08:00
taetaetae
14f044ce4f refactor: extract default assistant content to shared constants
Apply code review feedback from gemini-code-assist:
- Move fallback strings to kirocommon package as exported constants
- Update kiro_claude_request.go to use shared constants
- Update kiro_openai_request.go to use shared constants
- Improves maintainability and avoids duplication
2026-02-05 23:36:57 +09:00
taetaetae
88872baffc fix(kiro): handle empty content in Claude format assistant messages
Problem:
- PR #181 fixed empty content for OpenAI format (kiro_openai_request.go)
- But Claude format (kiro_claude_request.go) was not fixed
- OpenCode uses Claude format (/v1/messages endpoint)
- When assistant messages have only tool_use (no text), content becomes empty
- This causes 'Improperly formed request' errors from Kiro API

Example of problematic message format:
{
  "role": "assistant",
  "content": [
    {"type": "tool_use", "id": "...", "name": "todowrite", "input": {...}}
  ]
}

Solution:
- Add empty content fallback in BuildAssistantMessageStruct (Claude format)
- Same fix as PR #181 applied to kiro_openai_request.go

Fixes compaction failures for OpenCode + Quotio + CLIProxyAPIPlus + Kiro stack
2026-02-05 23:27:35 +09:00
Tianyi Cui
706590c62a fix: Enable extended thinking support for Claude Haiku 4.5
Claude Haiku 4.5 (claude-haiku-4-5-20251001) supports extended thinking
according to Anthropic's official documentation:
https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking

The model was incorrectly marked as not supporting thinking in the static
model definitions. This fix adds ThinkingSupport with the same parameters
as other Claude 4.5 models (Sonnet, Opus):
- Min: 1024 tokens
- Max: 128000 tokens
- ZeroAllowed: true
- DynamicAllowed: false
2026-02-05 19:03:23 +08:00
4 changed files with 29 additions and 11 deletions

View File

@@ -15,7 +15,7 @@ func GetClaudeModels() []*ModelInfo {
DisplayName: "Claude 4.5 Haiku",
ContextLength: 200000,
MaxCompletionTokens: 64000,
// Thinking: not supported for Haiku models
Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: false},
},
{
ID: "claude-sonnet-4-5-20250929",
@@ -29,15 +29,15 @@ func GetClaudeModels() []*ModelInfo {
Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: false},
},
{
ID: "claude-opus-4-6-20260205",
ID: "claude-opus-4-6",
Object: "model",
Created: 1770318000, // 2026-02-05
OwnedBy: "anthropic",
Type: "claude",
DisplayName: "Claude 4.6 Opus",
Description: "Premium model combining maximum intelligence with practical performance",
ContextLength: 200000,
MaxCompletionTokens: 64000,
ContextLength: 1000000,
MaxCompletionTokens: 128000,
Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: false},
},
{
@@ -866,7 +866,7 @@ func GetAntigravityModelConfig() map[string]*AntigravityModelConfig {
"gemini-3-flash": {Thinking: &ThinkingSupport{Min: 128, Max: 32768, ZeroAllowed: false, DynamicAllowed: true, Levels: []string{"minimal", "low", "medium", "high"}}},
"claude-sonnet-4-5-thinking": {Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: true}, MaxCompletionTokens: 64000},
"claude-opus-4-5-thinking": {Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: true}, MaxCompletionTokens: 64000},
"claude-opus-4-6-thinking": {Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: true}, MaxCompletionTokens: 64000},
"claude-opus-4-6-thinking": {Thinking: &ThinkingSupport{Min: 1024, Max: 128000, ZeroAllowed: true, DynamicAllowed: true}, MaxCompletionTokens: 128000},
"claude-sonnet-4-5": {MaxCompletionTokens: 64000},
"gpt-oss-120b-medium": {},
"tab_flash_lite_preview": {},

View File

@@ -883,8 +883,21 @@ func BuildAssistantMessageStruct(msg gjson.Result) KiroAssistantResponseMessage
contentBuilder.WriteString(content.String())
}
// CRITICAL FIX: Kiro API requires non-empty content for assistant messages
// This can happen with compaction requests where assistant messages have only tool_use
// (no text content). Without this fix, Kiro API returns "Improperly formed request" error.
finalContent := contentBuilder.String()
if strings.TrimSpace(finalContent) == "" {
if len(toolUses) > 0 {
finalContent = kirocommon.DefaultAssistantContentWithTools
} else {
finalContent = kirocommon.DefaultAssistantContent
}
log.Debugf("kiro: assistant content was empty, using default: %s", finalContent)
}
return KiroAssistantResponseMessage{
Content: contentBuilder.String(),
Content: finalContent,
ToolUses: toolUses,
}
}

View File

@@ -29,6 +29,14 @@ const (
// InlineCodeMarker is the markdown inline code marker (backtick).
InlineCodeMarker = "`"
// DefaultAssistantContentWithTools is the fallback content for assistant messages
// that have tool_use but no text content. Kiro API requires non-empty content.
DefaultAssistantContentWithTools = "I'll help you with that."
// DefaultAssistantContent is the fallback content for assistant messages
// that have no content at all. Kiro API requires non-empty content.
DefaultAssistantContent = "I understand."
// KiroAgenticSystemPrompt is injected only for -agentic models to prevent timeouts on large writes.
// AWS Kiro API has a 2-3 minute timeout for large file write operations.
KiroAgenticSystemPrompt = `

View File

@@ -718,13 +718,10 @@ func buildAssistantMessageFromOpenAI(msg gjson.Result) KiroAssistantResponseMess
// This can happen with compaction requests or error recovery scenarios
finalContent := contentBuilder.String()
if strings.TrimSpace(finalContent) == "" {
const defaultAssistantContentWithTools = "I'll help you with that."
const defaultAssistantContent = "I understand."
if len(toolUses) > 0 {
finalContent = defaultAssistantContentWithTools
finalContent = kirocommon.DefaultAssistantContentWithTools
} else {
finalContent = defaultAssistantContent
finalContent = kirocommon.DefaultAssistantContent
}
log.Debugf("kiro-openai: assistant content was empty, using default: %s", finalContent)
}