mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-20 21:30:50 +08:00
Improve thinking/tool signature handling for Claude and Gemini requests
Prefer cached signatures and avoid injecting dummy thinking blocks; instead remove unsigned thinking blocks and add a skip sentinel for tool calls without a valid signature. Generate stable session IDs from the first user message, apply schema cleaning only for Claude models, and reorder thinking parts so thinking appears first. For Gemini, remove thinking blocks and attach a skip sentinel to function calls. Simplify response handling by passing raw function args through (remove special Bash conversion). Update and add tests to reflect the new behavior. These changes prevent rejected dummy signatures, improve compatibility with Antigravity’s signature validation, provide more stable session IDs for conversation grouping, and make request/response translation more robust.
This commit is contained in:
@@ -253,13 +253,8 @@ func ConvertAntigravityResponseToClaude(_ context.Context, _ string, originalReq
|
||||
output = output + fmt.Sprintf("data: %s\n\n\n", data)
|
||||
|
||||
if fcArgsResult := functionCallResult.Get("args"); fcArgsResult.Exists() {
|
||||
argsRaw := fcArgsResult.Raw
|
||||
// Convert command → cmd for Bash tools using proper JSON parsing
|
||||
if fcName == "Bash" || fcName == "bash" || fcName == "bash_20241022" {
|
||||
argsRaw = convertBashCommandToCmdField(argsRaw)
|
||||
}
|
||||
output = output + "event: content_block_delta\n"
|
||||
data, _ = sjson.Set(fmt.Sprintf(`{"type":"content_block_delta","index":%d,"delta":{"type":"input_json_delta","partial_json":""}}`, params.ResponseIndex), "delta.partial_json", argsRaw)
|
||||
data, _ = sjson.Set(fmt.Sprintf(`{"type":"content_block_delta","index":%d,"delta":{"type":"input_json_delta","partial_json":""}}`, params.ResponseIndex), "delta.partial_json", fcArgsResult.Raw)
|
||||
output = output + fmt.Sprintf("data: %s\n\n\n", data)
|
||||
}
|
||||
params.ResponseType = 3
|
||||
@@ -347,36 +342,6 @@ func resolveStopReason(params *Params) string {
|
||||
return "end_turn"
|
||||
}
|
||||
|
||||
// convertBashCommandToCmdField converts "command" field to "cmd" field for Bash tools.
|
||||
// Amp expects "cmd" but Gemini sends "command". This uses proper JSON parsing
|
||||
// to avoid accidentally replacing "command" that appears in values.
|
||||
func convertBashCommandToCmdField(argsRaw string) string {
|
||||
// Only process valid JSON
|
||||
if !gjson.Valid(argsRaw) {
|
||||
return argsRaw
|
||||
}
|
||||
|
||||
// Check if "command" key exists and "cmd" doesn't
|
||||
commandVal := gjson.Get(argsRaw, "command")
|
||||
cmdVal := gjson.Get(argsRaw, "cmd")
|
||||
|
||||
if commandVal.Exists() && !cmdVal.Exists() {
|
||||
// Set "cmd" to the value of "command", preserve the raw value type
|
||||
result, err := sjson.SetRaw(argsRaw, "cmd", commandVal.Raw)
|
||||
if err != nil {
|
||||
return argsRaw
|
||||
}
|
||||
// Delete "command" key
|
||||
result, err = sjson.Delete(result, "command")
|
||||
if err != nil {
|
||||
return argsRaw
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
return argsRaw
|
||||
}
|
||||
|
||||
// ConvertAntigravityResponseToClaudeNonStream converts a non-streaming Gemini CLI response to a non-streaming Claude response.
|
||||
//
|
||||
// Parameters:
|
||||
@@ -488,12 +453,7 @@ func ConvertAntigravityResponseToClaudeNonStream(_ context.Context, _ string, or
|
||||
toolBlock, _ = sjson.Set(toolBlock, "name", name)
|
||||
|
||||
if args := functionCall.Get("args"); args.Exists() && args.Raw != "" && gjson.Valid(args.Raw) {
|
||||
argsRaw := args.Raw
|
||||
// Convert command → cmd for Bash tools
|
||||
if name == "Bash" || name == "bash" || name == "bash_20241022" {
|
||||
argsRaw = convertBashCommandToCmdField(argsRaw)
|
||||
}
|
||||
toolBlock, _ = sjson.SetRaw(toolBlock, "input", argsRaw)
|
||||
toolBlock, _ = sjson.SetRaw(toolBlock, "input", args.Raw)
|
||||
}
|
||||
|
||||
ensureContentArray()
|
||||
|
||||
Reference in New Issue
Block a user