diff --git a/internal/runtime/executor/gemini_executor.go b/internal/runtime/executor/gemini_executor.go index e4a2ce23..520d6474 100644 --- a/internal/runtime/executor/gemini_executor.go +++ b/internal/runtime/executor/gemini_executor.go @@ -257,10 +257,14 @@ func (e *GeminiExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.A line := scanner.Bytes() appendAPIResponseChunk(ctx, e.cfg, line) filtered := FilterSSEUsageMetadata(line) - if detail, ok := parseGeminiStreamUsage(filtered); ok { + payload := jsonPayload(filtered) + if len(payload) == 0 { + continue + } + if detail, ok := parseGeminiStreamUsage(payload); ok { reporter.publish(ctx, detail) } - lines := sdktranslator.TranslateStream(ctx, to, from, req.Model, bytes.Clone(opts.OriginalRequest), body, bytes.Clone(filtered), ¶m) + lines := sdktranslator.TranslateStream(ctx, to, from, req.Model, bytes.Clone(opts.OriginalRequest), body, bytes.Clone(payload), ¶m) for i := range lines { out <- cliproxyexecutor.StreamChunk{Payload: []byte(lines[i])} } diff --git a/internal/translator/gemini/openai/chat-completions/gemini_openai_response.go b/internal/translator/gemini/openai/chat-completions/gemini_openai_response.go index 4ce7f005..24112f0f 100644 --- a/internal/translator/gemini/openai/chat-completions/gemini_openai_response.go +++ b/internal/translator/gemini/openai/chat-completions/gemini_openai_response.go @@ -111,13 +111,23 @@ func ConvertGeminiResponseToOpenAI(_ context.Context, _ string, originalRequestR if !inlineDataResult.Exists() { inlineDataResult = partResult.Get("inline_data") } + thoughtSignatureResult := partResult.Get("thoughtSignature") + if !thoughtSignatureResult.Exists() { + thoughtSignatureResult = partResult.Get("thought_signature") + } + + // Skip thoughtSignature parts (encrypted reasoning not exposed downstream). + if thoughtSignatureResult.Exists() && thoughtSignatureResult.String() != "" { + continue + } if partTextResult.Exists() { + text := partTextResult.String() // Handle text content, distinguishing between regular content and reasoning/thoughts. if partResult.Get("thought").Bool() { - template, _ = sjson.Set(template, "choices.0.delta.reasoning_content", partTextResult.String()) + template, _ = sjson.Set(template, "choices.0.delta.reasoning_content", text) } else { - template, _ = sjson.Set(template, "choices.0.delta.content", partTextResult.String()) + template, _ = sjson.Set(template, "choices.0.delta.content", text) } template, _ = sjson.Set(template, "choices.0.delta.role", "assistant") } else if functionCallResult.Exists() {