mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-03 04:50:52 +08:00
feat(antigravity): add function ID to FunctionCall and FunctionResponse models
This commit is contained in:
@@ -85,6 +85,9 @@ type InlineData struct {
|
|||||||
// FunctionCall represents a tool call requested by the model.
|
// FunctionCall represents a tool call requested by the model.
|
||||||
// It includes the function name and its arguments that the model wants to execute.
|
// It includes the function name and its arguments that the model wants to execute.
|
||||||
type FunctionCall struct {
|
type FunctionCall struct {
|
||||||
|
// ID is the identifier of the function to be called.
|
||||||
|
ID string `json:"id,omitempty"`
|
||||||
|
|
||||||
// Name is the identifier of the function to be called.
|
// Name is the identifier of the function to be called.
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
|
||||||
@@ -95,6 +98,9 @@ type FunctionCall struct {
|
|||||||
// FunctionResponse represents the result of a tool execution.
|
// FunctionResponse represents the result of a tool execution.
|
||||||
// This is sent back to the model after a tool call has been processed.
|
// This is sent back to the model after a tool call has been processed.
|
||||||
type FunctionResponse struct {
|
type FunctionResponse struct {
|
||||||
|
// ID is the identifier of the function to be called.
|
||||||
|
ID string `json:"id,omitempty"`
|
||||||
|
|
||||||
// Name is the identifier of the function that was called.
|
// Name is the identifier of the function that was called.
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
|||||||
@@ -89,10 +89,11 @@ func ConvertClaudeRequestToAntigravity(modelName string, inputRawJSON []byte, _
|
|||||||
} else if contentTypeResult.Type == gjson.String && contentTypeResult.String() == "tool_use" {
|
} else if contentTypeResult.Type == gjson.String && contentTypeResult.String() == "tool_use" {
|
||||||
functionName := contentResult.Get("name").String()
|
functionName := contentResult.Get("name").String()
|
||||||
functionArgs := contentResult.Get("input").String()
|
functionArgs := contentResult.Get("input").String()
|
||||||
|
functionID := contentResult.Get("id").String()
|
||||||
var args map[string]any
|
var args map[string]any
|
||||||
if err := json.Unmarshal([]byte(functionArgs), &args); err == nil {
|
if err := json.Unmarshal([]byte(functionArgs), &args); err == nil {
|
||||||
clientContent.Parts = append(clientContent.Parts, client.Part{
|
clientContent.Parts = append(clientContent.Parts, client.Part{
|
||||||
FunctionCall: &client.FunctionCall{Name: functionName, Args: args},
|
FunctionCall: &client.FunctionCall{ID: functionID, Name: functionName, Args: args},
|
||||||
ThoughtSignature: geminiCLIClaudeThoughtSignature,
|
ThoughtSignature: geminiCLIClaudeThoughtSignature,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -105,7 +106,7 @@ func ConvertClaudeRequestToAntigravity(modelName string, inputRawJSON []byte, _
|
|||||||
funcName = strings.Join(toolCallIDs[0:len(toolCallIDs)-1], "-")
|
funcName = strings.Join(toolCallIDs[0:len(toolCallIDs)-1], "-")
|
||||||
}
|
}
|
||||||
responseData := contentResult.Get("content").Raw
|
responseData := contentResult.Get("content").Raw
|
||||||
functionResponse := client.FunctionResponse{Name: funcName, Response: map[string]interface{}{"result": responseData}}
|
functionResponse := client.FunctionResponse{ID: toolCallID, Name: funcName, Response: map[string]interface{}{"result": responseData}}
|
||||||
clientContent.Parts = append(clientContent.Parts, client.Part{FunctionResponse: &functionResponse})
|
clientContent.Parts = append(clientContent.Parts, client.Part{FunctionResponse: &functionResponse})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,35 +141,38 @@ func ConvertAntigravityResponseToClaude(_ context.Context, _ string, originalReq
|
|||||||
params.ResponseType = 2 // Set state to thinking
|
params.ResponseType = 2 // Set state to thinking
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Process regular text content (user-visible output)
|
finishReasonResult := gjson.GetBytes(rawJSON, "response.candidates.0.finishReason")
|
||||||
// Continue existing text block if already in content state
|
if partTextResult.String() != "" || !finishReasonResult.Exists() {
|
||||||
if params.ResponseType == 1 {
|
// Process regular text content (user-visible output)
|
||||||
output = output + "event: content_block_delta\n"
|
// Continue existing text block if already in content state
|
||||||
data, _ := sjson.Set(fmt.Sprintf(`{"type":"content_block_delta","index":%d,"delta":{"type":"text_delta","text":""}}`, params.ResponseIndex), "delta.text", partTextResult.String())
|
if params.ResponseType == 1 {
|
||||||
output = output + fmt.Sprintf("data: %s\n\n\n", data)
|
output = output + "event: content_block_delta\n"
|
||||||
} else {
|
data, _ := sjson.Set(fmt.Sprintf(`{"type":"content_block_delta","index":%d,"delta":{"type":"text_delta","text":""}}`, params.ResponseIndex), "delta.text", partTextResult.String())
|
||||||
// Transition from another state to text content
|
output = output + fmt.Sprintf("data: %s\n\n\n", data)
|
||||||
// First, close any existing content block
|
} else {
|
||||||
if params.ResponseType != 0 {
|
// Transition from another state to text content
|
||||||
if params.ResponseType == 2 {
|
// First, close any existing content block
|
||||||
// output = output + "event: content_block_delta\n"
|
if params.ResponseType != 0 {
|
||||||
// output = output + fmt.Sprintf(`data: {"type":"content_block_delta","index":%d,"delta":{"type":"signature_delta","signature":null}}`, params.ResponseIndex)
|
if params.ResponseType == 2 {
|
||||||
// output = output + "\n\n\n"
|
// output = output + "event: content_block_delta\n"
|
||||||
|
// output = output + fmt.Sprintf(`data: {"type":"content_block_delta","index":%d,"delta":{"type":"signature_delta","signature":null}}`, params.ResponseIndex)
|
||||||
|
// output = output + "\n\n\n"
|
||||||
|
}
|
||||||
|
output = output + "event: content_block_stop\n"
|
||||||
|
output = output + fmt.Sprintf(`data: {"type":"content_block_stop","index":%d}`, params.ResponseIndex)
|
||||||
|
output = output + "\n\n\n"
|
||||||
|
params.ResponseIndex++
|
||||||
}
|
}
|
||||||
output = output + "event: content_block_stop\n"
|
|
||||||
output = output + fmt.Sprintf(`data: {"type":"content_block_stop","index":%d}`, params.ResponseIndex)
|
|
||||||
output = output + "\n\n\n"
|
|
||||||
params.ResponseIndex++
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start a new text content block
|
// Start a new text content block
|
||||||
output = output + "event: content_block_start\n"
|
output = output + "event: content_block_start\n"
|
||||||
output = output + fmt.Sprintf(`data: {"type":"content_block_start","index":%d,"content_block":{"type":"text","text":""}}`, params.ResponseIndex)
|
output = output + fmt.Sprintf(`data: {"type":"content_block_start","index":%d,"content_block":{"type":"text","text":""}}`, params.ResponseIndex)
|
||||||
output = output + "\n\n\n"
|
output = output + "\n\n\n"
|
||||||
output = output + "event: content_block_delta\n"
|
output = output + "event: content_block_delta\n"
|
||||||
data, _ := sjson.Set(fmt.Sprintf(`{"type":"content_block_delta","index":%d,"delta":{"type":"text_delta","text":""}}`, params.ResponseIndex), "delta.text", partTextResult.String())
|
data, _ := sjson.Set(fmt.Sprintf(`{"type":"content_block_delta","index":%d,"delta":{"type":"text_delta","text":""}}`, params.ResponseIndex), "delta.text", partTextResult.String())
|
||||||
output = output + fmt.Sprintf("data: %s\n\n\n", data)
|
output = output + fmt.Sprintf("data: %s\n\n\n", data)
|
||||||
params.ResponseType = 1 // Set state to content
|
params.ResponseType = 1 // Set state to content
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if functionCallResult.Exists() {
|
} else if functionCallResult.Exists() {
|
||||||
|
|||||||
@@ -251,6 +251,7 @@ func ConvertOpenAIRequestToAntigravity(modelName string, inputRawJSON []byte, _
|
|||||||
fid := tc.Get("id").String()
|
fid := tc.Get("id").String()
|
||||||
fname := tc.Get("function.name").String()
|
fname := tc.Get("function.name").String()
|
||||||
fargs := tc.Get("function.arguments").String()
|
fargs := tc.Get("function.arguments").String()
|
||||||
|
node, _ = sjson.SetBytes(node, "parts."+itoa(p)+".functionCall.id", fid)
|
||||||
node, _ = sjson.SetBytes(node, "parts."+itoa(p)+".functionCall.name", fname)
|
node, _ = sjson.SetBytes(node, "parts."+itoa(p)+".functionCall.name", fname)
|
||||||
node, _ = sjson.SetRawBytes(node, "parts."+itoa(p)+".functionCall.args", []byte(fargs))
|
node, _ = sjson.SetRawBytes(node, "parts."+itoa(p)+".functionCall.args", []byte(fargs))
|
||||||
node, _ = sjson.SetBytes(node, "parts."+itoa(p)+".thoughtSignature", geminiCLIFunctionThoughtSignature)
|
node, _ = sjson.SetBytes(node, "parts."+itoa(p)+".thoughtSignature", geminiCLIFunctionThoughtSignature)
|
||||||
@@ -266,6 +267,7 @@ func ConvertOpenAIRequestToAntigravity(modelName string, inputRawJSON []byte, _
|
|||||||
pp := 0
|
pp := 0
|
||||||
for _, fid := range fIDs {
|
for _, fid := range fIDs {
|
||||||
if name, ok := tcID2Name[fid]; ok {
|
if name, ok := tcID2Name[fid]; ok {
|
||||||
|
toolNode, _ = sjson.SetBytes(toolNode, "parts."+itoa(pp)+".functionResponse.id", fid)
|
||||||
toolNode, _ = sjson.SetBytes(toolNode, "parts."+itoa(pp)+".functionResponse.name", name)
|
toolNode, _ = sjson.SetBytes(toolNode, "parts."+itoa(pp)+".functionResponse.name", name)
|
||||||
resp := toolResponses[fid]
|
resp := toolResponses[fid]
|
||||||
if resp == "" {
|
if resp == "" {
|
||||||
|
|||||||
@@ -327,7 +327,7 @@ func buildReverseMapFromGeminiOriginal(original []byte) map[string]string {
|
|||||||
func mustMarshalJSON(v interface{}) string {
|
func mustMarshalJSON(v interface{}) string {
|
||||||
data, err := json.Marshal(v)
|
data, err := json.Marshal(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return ""
|
||||||
}
|
}
|
||||||
return string(data)
|
return string(data)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -249,6 +249,7 @@ func ConvertOpenAIResponsesRequestToGemini(modelName string, inputRawJSON []byte
|
|||||||
functionCall := `{"functionCall":{"name":"","args":{}}}`
|
functionCall := `{"functionCall":{"name":"","args":{}}}`
|
||||||
functionCall, _ = sjson.Set(functionCall, "functionCall.name", name)
|
functionCall, _ = sjson.Set(functionCall, "functionCall.name", name)
|
||||||
functionCall, _ = sjson.Set(functionCall, "thoughtSignature", geminiResponsesThoughtSignature)
|
functionCall, _ = sjson.Set(functionCall, "thoughtSignature", geminiResponsesThoughtSignature)
|
||||||
|
functionCall, _ = sjson.Set(functionCall, "functionCall.id", item.Get("call_id").String())
|
||||||
|
|
||||||
// Parse arguments JSON string and set as args object
|
// Parse arguments JSON string and set as args object
|
||||||
if arguments != "" {
|
if arguments != "" {
|
||||||
@@ -285,6 +286,7 @@ func ConvertOpenAIResponsesRequestToGemini(modelName string, inputRawJSON []byte
|
|||||||
}
|
}
|
||||||
|
|
||||||
functionResponse, _ = sjson.Set(functionResponse, "functionResponse.name", functionName)
|
functionResponse, _ = sjson.Set(functionResponse, "functionResponse.name", functionName)
|
||||||
|
functionResponse, _ = sjson.Set(functionResponse, "functionResponse.id", callID)
|
||||||
|
|
||||||
// Set the raw JSON output directly (preserves string encoding)
|
// Set the raw JSON output directly (preserves string encoding)
|
||||||
if outputRaw != "" && outputRaw != "null" {
|
if outputRaw != "" && outputRaw != "null" {
|
||||||
|
|||||||
Reference in New Issue
Block a user