From 76af4540341e227658b4e437dda7a28af6a14461 Mon Sep 17 00:00:00 2001 From: Luis Pater Date: Sun, 7 Dec 2025 13:19:12 +0800 Subject: [PATCH] **feat(antigravity): enhance handling of "thinking" content and refine Claude model response processing** --- internal/interfaces/client_models.go | 2 ++ .../claude/antigravity_claude_request.go | 24 +++++++++++++---- .../claude/antigravity_claude_response.go | 26 +++++++++++-------- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/internal/interfaces/client_models.go b/internal/interfaces/client_models.go index df8cc0b0..c6e4ff78 100644 --- a/internal/interfaces/client_models.go +++ b/internal/interfaces/client_models.go @@ -56,6 +56,8 @@ type Content struct { // Part represents a distinct piece of content within a message. // A part can be text, inline data (like an image), a function call, or a function response. type Part struct { + Thought bool `json:"thought,omitempty"` + // Text contains plain text content. Text string `json:"text,omitempty"` diff --git a/internal/translator/antigravity/claude/antigravity_claude_request.go b/internal/translator/antigravity/claude/antigravity_claude_request.go index dfc4d893..e1b73da0 100644 --- a/internal/translator/antigravity/claude/antigravity_claude_request.go +++ b/internal/translator/antigravity/claude/antigravity_claude_request.go @@ -83,7 +83,15 @@ func ConvertClaudeRequestToAntigravity(modelName string, inputRawJSON []byte, _ for j := 0; j < len(contentResults); j++ { contentResult := contentResults[j] contentTypeResult := contentResult.Get("type") - if contentTypeResult.Type == gjson.String && contentTypeResult.String() == "text" { + if contentTypeResult.Type == gjson.String && contentTypeResult.String() == "thinking" { + prompt := contentResult.Get("thinking").String() + signatureResult := contentResult.Get("signature") + signature := geminiCLIClaudeThoughtSignature + if signatureResult.Exists() { + signature = signatureResult.String() + } + clientContent.Parts = append(clientContent.Parts, client.Part{Text: prompt, Thought: true, ThoughtSignature: signature}) + } else if contentTypeResult.Type == gjson.String && contentTypeResult.String() == "text" { prompt := contentResult.Get("text").String() clientContent.Parts = append(clientContent.Parts, client.Part{Text: prompt}) } else if contentTypeResult.Type == gjson.String && contentTypeResult.String() == "tool_use" { @@ -92,10 +100,16 @@ func ConvertClaudeRequestToAntigravity(modelName string, inputRawJSON []byte, _ functionID := contentResult.Get("id").String() var args map[string]any if err := json.Unmarshal([]byte(functionArgs), &args); err == nil { - clientContent.Parts = append(clientContent.Parts, client.Part{ - FunctionCall: &client.FunctionCall{ID: functionID, Name: functionName, Args: args}, - ThoughtSignature: geminiCLIClaudeThoughtSignature, - }) + if strings.Contains(modelName, "claude") { + clientContent.Parts = append(clientContent.Parts, client.Part{ + FunctionCall: &client.FunctionCall{ID: functionID, Name: functionName, Args: args}, + }) + } else { + clientContent.Parts = append(clientContent.Parts, client.Part{ + FunctionCall: &client.FunctionCall{ID: functionID, Name: functionName, Args: args}, + ThoughtSignature: geminiCLIClaudeThoughtSignature, + }) + } } } else if contentTypeResult.Type == gjson.String && contentTypeResult.String() == "tool_result" { toolCallID := contentResult.Get("tool_use_id").String() diff --git a/internal/translator/antigravity/claude/antigravity_claude_response.go b/internal/translator/antigravity/claude/antigravity_claude_response.go index dd27a366..4073f20b 100644 --- a/internal/translator/antigravity/claude/antigravity_claude_response.go +++ b/internal/translator/antigravity/claude/antigravity_claude_response.go @@ -111,8 +111,11 @@ func ConvertAntigravityResponseToClaude(_ context.Context, _ string, originalReq if partTextResult.Exists() { // Process thinking content (internal reasoning) if partResult.Get("thought").Bool() { - // Continue existing thinking block if already in thinking state - if params.ResponseType == 2 { + if thoughtSignature := partResult.Get("thoughtSignature"); thoughtSignature.Exists() && thoughtSignature.String() != "" { + output = output + "event: content_block_delta\n" + data, _ := sjson.Set(fmt.Sprintf(`{"type":"content_block_delta","index":%d,"delta":{"type":"signature_delta","signature":""}}`, params.ResponseIndex), "delta.signature", thoughtSignature.String()) + output = output + fmt.Sprintf("data: %s\n\n\n", data) + } else if params.ResponseType == 2 { // Continue existing thinking block if already in thinking state output = output + "event: content_block_delta\n" data, _ := sjson.Set(fmt.Sprintf(`{"type":"content_block_delta","index":%d,"delta":{"type":"thinking_delta","thinking":""}}`, params.ResponseIndex), "delta.thinking", partTextResult.String()) output = output + fmt.Sprintf("data: %s\n\n\n", data) @@ -163,15 +166,16 @@ func ConvertAntigravityResponseToClaude(_ context.Context, _ string, originalReq output = output + "\n\n\n" params.ResponseIndex++ } - - // Start a new text content block - 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 + "\n\n\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()) - output = output + fmt.Sprintf("data: %s\n\n\n", data) - params.ResponseType = 1 // Set state to content + if partTextResult.String() != "" { + // Start a new text content block + 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 + "\n\n\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()) + output = output + fmt.Sprintf("data: %s\n\n\n", data) + params.ResponseType = 1 // Set state to content + } } } }