From 86ecbc89bd31a80e97ee516ad40178dd4440634d Mon Sep 17 00:00:00 2001 From: "CJACK." Date: Tue, 7 Apr 2026 10:59:27 +0800 Subject: [PATCH] Preserve SSE frame delimiters when injecting Gemini usage --- internal/translatorcliproxy/stream_writer.go | 12 +++++++++++- internal/translatorcliproxy/stream_writer_test.go | 12 ++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/internal/translatorcliproxy/stream_writer.go b/internal/translatorcliproxy/stream_writer.go index b1b8747..e80ce69 100644 --- a/internal/translatorcliproxy/stream_writer.go +++ b/internal/translatorcliproxy/stream_writer.go @@ -162,6 +162,13 @@ func injectStreamUsageMetadata(chunk []byte, target sdktranslator.Format, usage if target != sdktranslator.FormatGemini { return chunk } + suffix := "" + switch { + case bytes.HasSuffix(chunk, []byte("\n\n")): + suffix = "\n\n" + case bytes.HasSuffix(chunk, []byte("\n")): + suffix = "\n" + } text := strings.TrimSpace(string(chunk)) if text == "" { return chunk @@ -194,7 +201,10 @@ func injectStreamUsageMetadata(chunk []byte, target sdktranslator.Format, usage return chunk } if hasDataPrefix { - return []byte("data: " + string(b)) + return []byte("data: " + string(b) + suffix) + } + if suffix != "" { + return append(b, []byte(suffix)...) } return b } diff --git a/internal/translatorcliproxy/stream_writer_test.go b/internal/translatorcliproxy/stream_writer_test.go index 77d2936..94d70b8 100644 --- a/internal/translatorcliproxy/stream_writer_test.go +++ b/internal/translatorcliproxy/stream_writer_test.go @@ -63,3 +63,15 @@ func TestOpenAIStreamTranslatorWriterPreservesKeepAliveComment(t *testing.T) { t.Fatalf("expected keep-alive comment passthrough, got %q", body) } } + +func TestInjectStreamUsageMetadataPreservesSSEFrameTerminator(t *testing.T) { + chunk := []byte("data: {\"candidates\":[{\"index\":0}],\"model\":\"gemini-2.5-pro\"}\n\n") + usage := openAIUsage{PromptTokens: 11, CompletionTokens: 29, TotalTokens: 40} + got := injectStreamUsageMetadata(chunk, sdktranslator.FormatGemini, usage) + if !strings.HasSuffix(string(got), "\n\n") { + t.Fatalf("expected injected chunk to preserve \\n\\n frame terminator, got %q", string(got)) + } + if !strings.Contains(string(got), `"usageMetadata"`) { + t.Fatalf("expected usageMetadata injected, got %q", string(got)) + } +}