mirror of
https://github.com/router-for-me/CLIProxyAPIPlus.git
synced 2026-03-11 16:26:32 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a0c6cffb0d | ||
|
|
f81ff16022 | ||
|
|
68cbe20664 |
@@ -604,10 +604,22 @@ type kiroHistoryMessage struct {
|
||||
AssistantResponseMessage *kiroAssistantResponseMessage `json:"assistantResponseMessage,omitempty"`
|
||||
}
|
||||
|
||||
// kiroImage represents an image in Kiro API format
|
||||
type kiroImage struct {
|
||||
Format string `json:"format"`
|
||||
Source kiroImageSource `json:"source"`
|
||||
}
|
||||
|
||||
// kiroImageSource contains the image data
|
||||
type kiroImageSource struct {
|
||||
Bytes string `json:"bytes"` // base64 encoded image data
|
||||
}
|
||||
|
||||
type kiroUserInputMessage struct {
|
||||
Content string `json:"content"`
|
||||
ModelID string `json:"modelId"`
|
||||
Origin string `json:"origin"`
|
||||
Images []kiroImage `json:"images,omitempty"`
|
||||
UserInputMessageContext *kiroUserInputMessageContext `json:"userInputMessageContext,omitempty"`
|
||||
}
|
||||
|
||||
@@ -824,6 +836,7 @@ func (e *KiroExecutor) buildUserMessageStruct(msg gjson.Result, modelID, origin
|
||||
content := msg.Get("content")
|
||||
var contentBuilder strings.Builder
|
||||
var toolResults []kiroToolResult
|
||||
var images []kiroImage
|
||||
|
||||
if content.IsArray() {
|
||||
for _, part := range content.Array() {
|
||||
@@ -831,6 +844,25 @@ func (e *KiroExecutor) buildUserMessageStruct(msg gjson.Result, modelID, origin
|
||||
switch partType {
|
||||
case "text":
|
||||
contentBuilder.WriteString(part.Get("text").String())
|
||||
case "image":
|
||||
// Extract image data from Claude API format
|
||||
mediaType := part.Get("source.media_type").String()
|
||||
data := part.Get("source.data").String()
|
||||
|
||||
// Extract format from media_type (e.g., "image/png" -> "png")
|
||||
format := ""
|
||||
if idx := strings.LastIndex(mediaType, "/"); idx != -1 {
|
||||
format = mediaType[idx+1:]
|
||||
}
|
||||
|
||||
if format != "" && data != "" {
|
||||
images = append(images, kiroImage{
|
||||
Format: format,
|
||||
Source: kiroImageSource{
|
||||
Bytes: data,
|
||||
},
|
||||
})
|
||||
}
|
||||
case "tool_result":
|
||||
// Extract tool result for API
|
||||
toolUseID := part.Get("tool_use_id").String()
|
||||
@@ -872,11 +904,18 @@ func (e *KiroExecutor) buildUserMessageStruct(msg gjson.Result, modelID, origin
|
||||
contentBuilder.WriteString(content.String())
|
||||
}
|
||||
|
||||
return kiroUserInputMessage{
|
||||
userMsg := kiroUserInputMessage{
|
||||
Content: contentBuilder.String(),
|
||||
ModelID: modelID,
|
||||
Origin: origin,
|
||||
}, toolResults
|
||||
}
|
||||
|
||||
// Add images to message if present
|
||||
if len(images) > 0 {
|
||||
userMsg.Images = images
|
||||
}
|
||||
|
||||
return userMsg, toolResults
|
||||
}
|
||||
|
||||
// buildAssistantMessageStruct builds an assistant message with tool uses
|
||||
|
||||
@@ -4,6 +4,7 @@ package chat_completions
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
"github.com/tidwall/sjson"
|
||||
@@ -182,13 +183,43 @@ func ConvertOpenAIRequestToKiro(modelName string, inputRawJSON []byte, stream bo
|
||||
"text": part.Get("text").String(),
|
||||
})
|
||||
} else if partType == "image_url" {
|
||||
contentParts = append(contentParts, map[string]interface{}{
|
||||
"type": "image",
|
||||
"source": map[string]interface{}{
|
||||
"type": "url",
|
||||
"url": part.Get("image_url.url").String(),
|
||||
},
|
||||
})
|
||||
imageURL := part.Get("image_url.url").String()
|
||||
|
||||
// Check if it's base64 format (data:image/png;base64,xxxxx)
|
||||
if strings.HasPrefix(imageURL, "data:") {
|
||||
// Parse data URL format
|
||||
// Format: data:image/png;base64,xxxxx
|
||||
commaIdx := strings.Index(imageURL, ",")
|
||||
if commaIdx != -1 {
|
||||
// Extract media_type (e.g., "image/png")
|
||||
header := imageURL[5:commaIdx] // Remove "data:" prefix
|
||||
mediaType := header
|
||||
if semiIdx := strings.Index(header, ";"); semiIdx != -1 {
|
||||
mediaType = header[:semiIdx]
|
||||
}
|
||||
|
||||
// Extract base64 data
|
||||
base64Data := imageURL[commaIdx+1:]
|
||||
|
||||
contentParts = append(contentParts, map[string]interface{}{
|
||||
"type": "image",
|
||||
"source": map[string]interface{}{
|
||||
"type": "base64",
|
||||
"media_type": mediaType,
|
||||
"data": base64Data,
|
||||
},
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// Regular URL format - keep original logic
|
||||
contentParts = append(contentParts, map[string]interface{}{
|
||||
"type": "image",
|
||||
"source": map[string]interface{}{
|
||||
"type": "url",
|
||||
"url": imageURL,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if content.String() != "" {
|
||||
@@ -214,13 +245,43 @@ func ConvertOpenAIRequestToKiro(modelName string, inputRawJSON []byte, stream bo
|
||||
"text": part.Get("text").String(),
|
||||
})
|
||||
} else if partType == "image_url" {
|
||||
contentParts = append(contentParts, map[string]interface{}{
|
||||
"type": "image",
|
||||
"source": map[string]interface{}{
|
||||
"type": "url",
|
||||
"url": part.Get("image_url.url").String(),
|
||||
},
|
||||
})
|
||||
imageURL := part.Get("image_url.url").String()
|
||||
|
||||
// Check if it's base64 format (data:image/png;base64,xxxxx)
|
||||
if strings.HasPrefix(imageURL, "data:") {
|
||||
// Parse data URL format
|
||||
// Format: data:image/png;base64,xxxxx
|
||||
commaIdx := strings.Index(imageURL, ",")
|
||||
if commaIdx != -1 {
|
||||
// Extract media_type (e.g., "image/png")
|
||||
header := imageURL[5:commaIdx] // Remove "data:" prefix
|
||||
mediaType := header
|
||||
if semiIdx := strings.Index(header, ";"); semiIdx != -1 {
|
||||
mediaType = header[:semiIdx]
|
||||
}
|
||||
|
||||
// Extract base64 data
|
||||
base64Data := imageURL[commaIdx+1:]
|
||||
|
||||
contentParts = append(contentParts, map[string]interface{}{
|
||||
"type": "image",
|
||||
"source": map[string]interface{}{
|
||||
"type": "base64",
|
||||
"media_type": mediaType,
|
||||
"data": base64Data,
|
||||
},
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// Regular URL format - keep original logic
|
||||
contentParts = append(contentParts, map[string]interface{}{
|
||||
"type": "image",
|
||||
"source": map[string]interface{}{
|
||||
"type": "url",
|
||||
"url": imageURL,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
claudeMsg["content"] = contentParts
|
||||
|
||||
Reference in New Issue
Block a user