mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-03 04:50:52 +08:00
**feat(translator): improve content processing and Antigravity request conversion**
- Refactored response translation logic to support mixed content types (`input_text`, `output_text`, `input_image`) with better role assignments and part handling. - Added image processing logic for embedding inline data with MIME type and base64 encoded content. - Updated Antigravity request conversion to replace Gemini CLI references for consistency.
This commit is contained in:
@@ -3,12 +3,12 @@ package responses
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
||||||
. "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/gemini-cli/gemini"
|
. "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/antigravity/gemini"
|
||||||
. "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/gemini/openai/responses"
|
. "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/gemini/openai/responses"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ConvertOpenAIResponsesRequestToAntigravity(modelName string, inputRawJSON []byte, stream bool) []byte {
|
func ConvertOpenAIResponsesRequestToAntigravity(modelName string, inputRawJSON []byte, stream bool) []byte {
|
||||||
rawJSON := bytes.Clone(inputRawJSON)
|
rawJSON := bytes.Clone(inputRawJSON)
|
||||||
rawJSON = ConvertOpenAIResponsesRequestToGemini(modelName, rawJSON, stream)
|
rawJSON = ConvertOpenAIResponsesRequestToGemini(modelName, rawJSON, stream)
|
||||||
return ConvertGeminiRequestToGeminiCLI(modelName, rawJSON, stream)
|
return ConvertGeminiRequestToAntigravity(modelName, rawJSON, stream)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,39 +67,101 @@ func ConvertOpenAIResponsesRequestToGemini(modelName string, inputRawJSON []byte
|
|||||||
// even when the message.role is "user". We split such items into distinct Gemini messages
|
// even when the message.role is "user". We split such items into distinct Gemini messages
|
||||||
// with roles derived from the content type to match docs/convert-2.md.
|
// with roles derived from the content type to match docs/convert-2.md.
|
||||||
if contentArray := item.Get("content"); contentArray.Exists() && contentArray.IsArray() {
|
if contentArray := item.Get("content"); contentArray.Exists() && contentArray.IsArray() {
|
||||||
|
currentRole := ""
|
||||||
|
var currentParts []string
|
||||||
|
|
||||||
|
flush := func() {
|
||||||
|
if currentRole == "" || len(currentParts) == 0 {
|
||||||
|
currentParts = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
one := `{"role":"","parts":[]}`
|
||||||
|
one, _ = sjson.Set(one, "role", currentRole)
|
||||||
|
for _, part := range currentParts {
|
||||||
|
one, _ = sjson.SetRaw(one, "parts.-1", part)
|
||||||
|
}
|
||||||
|
out, _ = sjson.SetRaw(out, "contents.-1", one)
|
||||||
|
currentParts = nil
|
||||||
|
}
|
||||||
|
|
||||||
contentArray.ForEach(func(_, contentItem gjson.Result) bool {
|
contentArray.ForEach(func(_, contentItem gjson.Result) bool {
|
||||||
contentType := contentItem.Get("type").String()
|
contentType := contentItem.Get("type").String()
|
||||||
if contentType == "" {
|
if contentType == "" {
|
||||||
contentType = "input_text"
|
contentType = "input_text"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
effRole := "user"
|
||||||
|
if itemRole != "" {
|
||||||
|
switch strings.ToLower(itemRole) {
|
||||||
|
case "assistant", "model":
|
||||||
|
effRole = "model"
|
||||||
|
default:
|
||||||
|
effRole = strings.ToLower(itemRole)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if contentType == "output_text" {
|
||||||
|
effRole = "model"
|
||||||
|
}
|
||||||
|
if effRole == "assistant" {
|
||||||
|
effRole = "model"
|
||||||
|
}
|
||||||
|
|
||||||
|
if currentRole != "" && effRole != currentRole {
|
||||||
|
flush()
|
||||||
|
currentRole = ""
|
||||||
|
}
|
||||||
|
if currentRole == "" {
|
||||||
|
currentRole = effRole
|
||||||
|
}
|
||||||
|
|
||||||
|
var partJSON string
|
||||||
switch contentType {
|
switch contentType {
|
||||||
case "input_text", "output_text":
|
case "input_text", "output_text":
|
||||||
if text := contentItem.Get("text"); text.Exists() {
|
if text := contentItem.Get("text"); text.Exists() {
|
||||||
effRole := "user"
|
partJSON = `{"text":""}`
|
||||||
if itemRole != "" {
|
partJSON, _ = sjson.Set(partJSON, "text", text.String())
|
||||||
switch strings.ToLower(itemRole) {
|
}
|
||||||
case "assistant", "model":
|
case "input_image":
|
||||||
effRole = "model"
|
imageURL := contentItem.Get("image_url").String()
|
||||||
default:
|
if imageURL == "" {
|
||||||
effRole = strings.ToLower(itemRole)
|
imageURL = contentItem.Get("url").String()
|
||||||
|
}
|
||||||
|
if imageURL != "" {
|
||||||
|
mimeType := "application/octet-stream"
|
||||||
|
data := ""
|
||||||
|
if strings.HasPrefix(imageURL, "data:") {
|
||||||
|
trimmed := strings.TrimPrefix(imageURL, "data:")
|
||||||
|
mediaAndData := strings.SplitN(trimmed, ";base64,", 2)
|
||||||
|
if len(mediaAndData) == 2 {
|
||||||
|
if mediaAndData[0] != "" {
|
||||||
|
mimeType = mediaAndData[0]
|
||||||
|
}
|
||||||
|
data = mediaAndData[1]
|
||||||
|
} else {
|
||||||
|
mediaAndData = strings.SplitN(trimmed, ",", 2)
|
||||||
|
if len(mediaAndData) == 2 {
|
||||||
|
if mediaAndData[0] != "" {
|
||||||
|
mimeType = mediaAndData[0]
|
||||||
|
}
|
||||||
|
data = mediaAndData[1]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if contentType == "output_text" {
|
if data != "" {
|
||||||
effRole = "model"
|
partJSON = `{"inline_data":{"mime_type":"","data":""}}`
|
||||||
|
partJSON, _ = sjson.Set(partJSON, "inline_data.mime_type", mimeType)
|
||||||
|
partJSON, _ = sjson.Set(partJSON, "inline_data.data", data)
|
||||||
}
|
}
|
||||||
if effRole == "assistant" {
|
|
||||||
effRole = "model"
|
|
||||||
}
|
|
||||||
one := `{"role":"","parts":[]}`
|
|
||||||
one, _ = sjson.Set(one, "role", effRole)
|
|
||||||
textPart := `{"text":""}`
|
|
||||||
textPart, _ = sjson.Set(textPart, "text", text.String())
|
|
||||||
one, _ = sjson.SetRaw(one, "parts.-1", textPart)
|
|
||||||
out, _ = sjson.SetRaw(out, "contents.-1", one)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if partJSON != "" {
|
||||||
|
currentParts = append(currentParts, partJSON)
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
case "function_call":
|
case "function_call":
|
||||||
|
|||||||
Reference in New Issue
Block a user