|
|
@@ -1355,20 +1355,50 @@ func GeminiChatHandler(c *gin.Context, info *relaycommon.RelayInfo, resp *http.R
|
|
|
return nil, types.NewOpenAIError(err, types.ErrorCodeBadResponseBody, http.StatusInternalServerError)
|
|
|
}
|
|
|
if len(geminiResponse.Candidates) == 0 {
|
|
|
- // [FIX] Return meaningful error when Candidates is empty
|
|
|
+ usage := dto.Usage{
|
|
|
+ PromptTokens: geminiResponse.UsageMetadata.PromptTokenCount,
|
|
|
+ }
|
|
|
+ usage.CompletionTokenDetails.ReasoningTokens = geminiResponse.UsageMetadata.ThoughtsTokenCount
|
|
|
+ for _, detail := range geminiResponse.UsageMetadata.PromptTokensDetails {
|
|
|
+ if detail.Modality == "AUDIO" {
|
|
|
+ usage.PromptTokensDetails.AudioTokens = detail.TokenCount
|
|
|
+ } else if detail.Modality == "TEXT" {
|
|
|
+ usage.PromptTokensDetails.TextTokens = detail.TokenCount
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if usage.PromptTokens <= 0 {
|
|
|
+ usage.PromptTokens = info.GetEstimatePromptTokens()
|
|
|
+ }
|
|
|
+
|
|
|
+ var newAPIError *types.NewAPIError
|
|
|
if geminiResponse.PromptFeedback != nil && geminiResponse.PromptFeedback.BlockReason != nil {
|
|
|
- return nil, types.NewOpenAIError(
|
|
|
+ newAPIError = types.NewOpenAIError(
|
|
|
errors.New("request blocked by Gemini API: "+*geminiResponse.PromptFeedback.BlockReason),
|
|
|
types.ErrorCodePromptBlocked,
|
|
|
http.StatusBadRequest,
|
|
|
)
|
|
|
} else {
|
|
|
- return nil, types.NewOpenAIError(
|
|
|
+ newAPIError = types.NewOpenAIError(
|
|
|
errors.New("empty response from Gemini API"),
|
|
|
types.ErrorCodeEmptyResponse,
|
|
|
http.StatusInternalServerError,
|
|
|
)
|
|
|
}
|
|
|
+
|
|
|
+ service.ResetStatusCode(newAPIError, c.GetString("status_code_mapping"))
|
|
|
+
|
|
|
+ switch info.RelayFormat {
|
|
|
+ case types.RelayFormatClaude:
|
|
|
+ c.JSON(newAPIError.StatusCode, gin.H{
|
|
|
+ "type": "error",
|
|
|
+ "error": newAPIError.ToClaudeError(),
|
|
|
+ })
|
|
|
+ default:
|
|
|
+ c.JSON(newAPIError.StatusCode, gin.H{
|
|
|
+ "error": newAPIError.ToOpenAIError(),
|
|
|
+ })
|
|
|
+ }
|
|
|
+ return &usage, nil
|
|
|
}
|
|
|
fullTextResponse := responseGeminiChat2OpenAI(c, &geminiResponse)
|
|
|
fullTextResponse.Model = info.UpstreamModelName
|
|
|
@@ -1643,4 +1673,3 @@ func convertToolChoiceToGeminiConfig(toolChoice any) *dto.ToolConfig {
|
|
|
// Unsupported type, return nil
|
|
|
return nil
|
|
|
}
|
|
|
-
|