Add projects
This commit is contained in:
parent
2d3a9ad623
commit
8b607dd700
1802 changed files with 503346 additions and 2 deletions
|
|
@ -0,0 +1,129 @@
|
|||
// Package gemini provides request translation functionality for Gemini to Antigravity API compatibility.
|
||||
// It handles parsing and transforming Gemini API requests into Antigravity API format,
|
||||
// extracting model information, system instructions, message contents, and tool declarations.
|
||||
// The package performs JSON data transformation to ensure compatibility
|
||||
// between Gemini API format and Antigravity API's expected format.
|
||||
package gemini
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
translatorcommon "github.com/router-for-me/CLIProxyAPI/v7/internal/translator/common"
|
||||
"github.com/router-for-me/CLIProxyAPI/v7/internal/util"
|
||||
"github.com/tidwall/gjson"
|
||||
"github.com/tidwall/sjson"
|
||||
)
|
||||
|
||||
// ConvertAntigravityResponseToGemini parses and transforms a Antigravity API request into Gemini API format.
|
||||
// It extracts the model name, system instruction, message contents, and tool declarations
|
||||
// from the raw JSON request and returns them in the format expected by the Gemini API.
|
||||
// The function performs the following transformations:
|
||||
// 1. Extracts the response data from the request
|
||||
// 2. Handles alternative response formats
|
||||
// 3. Processes array responses by extracting individual response objects
|
||||
//
|
||||
// Parameters:
|
||||
// - ctx: The context for the request, used for cancellation and timeout handling
|
||||
// - modelName: The name of the model to use for the request (unused in current implementation)
|
||||
// - rawJSON: The raw JSON request data from the Antigravity API
|
||||
// - param: A pointer to a parameter object for the conversion (unused in current implementation)
|
||||
//
|
||||
// Returns:
|
||||
// - [][]byte: The transformed response data in Gemini API format.
|
||||
func ConvertAntigravityResponseToGemini(ctx context.Context, _ string, originalRequestRawJSON, requestRawJSON, rawJSON []byte, _ *any) [][]byte {
|
||||
if bytes.HasPrefix(rawJSON, []byte("data:")) {
|
||||
rawJSON = bytes.TrimSpace(rawJSON[5:])
|
||||
}
|
||||
|
||||
if alt, ok := ctx.Value("alt").(string); ok {
|
||||
var chunk []byte
|
||||
if alt == "" {
|
||||
responseResult := gjson.GetBytes(rawJSON, "response")
|
||||
if responseResult.Exists() {
|
||||
chunk = []byte(responseResult.Raw)
|
||||
chunk = restoreUsageMetadata(chunk)
|
||||
chunk = restoreGeminiFunctionNames(chunk, originalRequestRawJSON)
|
||||
}
|
||||
} else {
|
||||
chunkTemplate := []byte("[]")
|
||||
responseResult := gjson.ParseBytes(chunk)
|
||||
if responseResult.IsArray() {
|
||||
responseResultItems := responseResult.Array()
|
||||
for i := 0; i < len(responseResultItems); i++ {
|
||||
responseResultItem := responseResultItems[i]
|
||||
if responseResultItem.Get("response").Exists() {
|
||||
chunkTemplate, _ = sjson.SetRawBytes(chunkTemplate, "-1", []byte(responseResultItem.Get("response").Raw))
|
||||
}
|
||||
}
|
||||
}
|
||||
chunk = chunkTemplate
|
||||
}
|
||||
return [][]byte{chunk}
|
||||
}
|
||||
return [][]byte{}
|
||||
}
|
||||
|
||||
// ConvertAntigravityResponseToGeminiNonStream converts a non-streaming Antigravity request to a non-streaming Gemini response.
|
||||
// This function processes the complete Antigravity request and transforms it into a single Gemini-compatible
|
||||
// JSON response. It extracts the response data from the request and returns it in the expected format.
|
||||
//
|
||||
// Parameters:
|
||||
// - ctx: The context for the request, used for cancellation and timeout handling
|
||||
// - modelName: The name of the model being used for the response (unused in current implementation)
|
||||
// - rawJSON: The raw JSON request data from the Antigravity API
|
||||
// - param: A pointer to a parameter object for the conversion (unused in current implementation)
|
||||
//
|
||||
// Returns:
|
||||
// - []byte: A Gemini-compatible JSON response containing the response data.
|
||||
func ConvertAntigravityResponseToGeminiNonStream(_ context.Context, _ string, originalRequestRawJSON, requestRawJSON, rawJSON []byte, _ *any) []byte {
|
||||
responseResult := gjson.GetBytes(rawJSON, "response")
|
||||
if responseResult.Exists() {
|
||||
chunk := restoreUsageMetadata([]byte(responseResult.Raw))
|
||||
return restoreGeminiFunctionNames(chunk, originalRequestRawJSON)
|
||||
}
|
||||
return restoreGeminiFunctionNames(rawJSON, originalRequestRawJSON)
|
||||
}
|
||||
|
||||
func restoreGeminiFunctionNames(chunk, originalRequestRawJSON []byte) []byte {
|
||||
nameMap := util.DisambiguatedToolNameMap(originalRequestRawJSON)
|
||||
if len(nameMap) == 0 {
|
||||
return chunk
|
||||
}
|
||||
candidates := gjson.GetBytes(chunk, "candidates")
|
||||
for candidateIndex, candidate := range candidates.Array() {
|
||||
for partIndex, part := range candidate.Get("content.parts").Array() {
|
||||
for _, field := range []string{"functionCall", "functionResponse", "function_call", "function_response"} {
|
||||
nameResult := part.Get(field + ".name")
|
||||
name := nameResult.String()
|
||||
if name == "" {
|
||||
continue
|
||||
}
|
||||
restoredName := util.RestoreSanitizedToolName(nameMap, name)
|
||||
if nameResult.Type == gjson.String && restoredName == name {
|
||||
continue
|
||||
}
|
||||
path := fmt.Sprintf("candidates.%d.content.parts.%d.%s.name", candidateIndex, partIndex, field)
|
||||
chunk, _ = sjson.SetBytes(chunk, path, restoredName)
|
||||
}
|
||||
}
|
||||
}
|
||||
return chunk
|
||||
}
|
||||
|
||||
func GeminiTokenCount(ctx context.Context, count int64) []byte {
|
||||
return translatorcommon.GeminiTokenCountJSON(count)
|
||||
}
|
||||
|
||||
// restoreUsageMetadata renames cpaUsageMetadata back to usageMetadata.
|
||||
// The executor renames usageMetadata to cpaUsageMetadata in non-terminal chunks
|
||||
// to preserve usage data while hiding it from clients that don't expect it.
|
||||
// When returning standard Gemini API format, we must restore the original name.
|
||||
func restoreUsageMetadata(chunk []byte) []byte {
|
||||
if cpaUsage := gjson.GetBytes(chunk, "cpaUsageMetadata"); cpaUsage.Exists() {
|
||||
chunk, _ = sjson.SetRawBytes(chunk, "usageMetadata", []byte(cpaUsage.Raw))
|
||||
chunk, _ = sjson.DeleteBytes(chunk, "cpaUsageMetadata")
|
||||
}
|
||||
return chunk
|
||||
}
|
||||
Loading…
Reference in a new issue