diff --git a/backend/internal/service/antigravity_gateway_service.go b/backend/internal/service/antigravity_gateway_service.go index 67c60db5..6331acd8 100644 --- a/backend/internal/service/antigravity_gateway_service.go +++ b/backend/internal/service/antigravity_gateway_service.go @@ -1412,8 +1412,15 @@ func (s *AntigravityGatewayService) ForwardGemini(ctx context.Context, c *gin.Co proxyURL = account.Proxy.URL() } + // 过滤掉 parts 为空的消息(Gemini API 不接受空 parts) + filteredBody, err := filterEmptyPartsFromGeminiRequest(body) + if err != nil { + log.Printf("[Antigravity] Failed to filter empty parts: %v", err) + filteredBody = body + } + // Antigravity 上游要求必须包含身份提示词,注入到请求中 - injectedBody, err := injectIdentityPatchToGeminiRequest(body) + injectedBody, err := injectIdentityPatchToGeminiRequest(filteredBody) if err != nil { return nil, err } @@ -2778,3 +2785,55 @@ func cleanGeminiRequest(body []byte) ([]byte, error) { return json.Marshal(payload) } + +// filterEmptyPartsFromGeminiRequest 过滤 Gemini 请求中 parts 为空的消息 +// Gemini API 不接受 parts 为空数组的消息,会返回 400 错误 +func filterEmptyPartsFromGeminiRequest(body []byte) ([]byte, error) { + var payload map[string]any + if err := json.Unmarshal(body, &payload); err != nil { + return nil, err + } + + contents, ok := payload["contents"].([]any) + if !ok || len(contents) == 0 { + return body, nil + } + + filtered := make([]any, 0, len(contents)) + modified := false + + for _, c := range contents { + contentMap, ok := c.(map[string]any) + if !ok { + filtered = append(filtered, c) + continue + } + + parts, hasParts := contentMap["parts"] + if !hasParts { + filtered = append(filtered, c) + continue + } + + partsSlice, ok := parts.([]any) + if !ok { + filtered = append(filtered, c) + continue + } + + // 跳过 parts 为空数组的消息 + if len(partsSlice) == 0 { + modified = true + continue + } + + filtered = append(filtered, c) + } + + if !modified { + return body, nil + } + + payload["contents"] = filtered + return json.Marshal(payload) +} diff --git a/backend/internal/service/gemini_messages_compat_service.go b/backend/internal/service/gemini_messages_compat_service.go index 1879a94c..3833e66e 100644 --- a/backend/internal/service/gemini_messages_compat_service.go +++ b/backend/internal/service/gemini_messages_compat_service.go @@ -840,6 +840,11 @@ func (s *GeminiMessagesCompatService) ForwardNative(ctx context.Context, c *gin. return nil, s.writeGoogleError(c, http.StatusBadRequest, "Request body is empty") } + // 过滤掉 parts 为空的消息(Gemini API 不接受空 parts) + if filteredBody, err := filterEmptyPartsFromGeminiRequest(body); err == nil { + body = filteredBody + } + switch action { case "generateContent", "streamGenerateContent", "countTokens": // ok