From a602ae859bc6cd19d44dd4f7fde4efafc99db692 Mon Sep 17 00:00:00 2001 From: hkfires <10558748+hkfires@users.noreply.github.com> Date: Thu, 9 Oct 2025 15:47:06 +0800 Subject: [PATCH] feat(translator): Add support for openrouter image_config --- .../openai/chat-completions/cli_openai_request.go | 8 ++++++++ .../openai/chat-completions/gemini_openai_request.go | 8 ++++++++ .../openai/responses/gemini_openai-responses_request.go | 7 +++++++ 3 files changed, 23 insertions(+) diff --git a/internal/translator/gemini-cli/openai/chat-completions/cli_openai_request.go b/internal/translator/gemini-cli/openai/chat-completions/cli_openai_request.go index c69ecf30..62231662 100644 --- a/internal/translator/gemini-cli/openai/chat-completions/cli_openai_request.go +++ b/internal/translator/gemini-cli/openai/chat-completions/cli_openai_request.go @@ -85,6 +85,14 @@ func ConvertOpenAIRequestToGeminiCLI(modelName string, inputRawJSON []byte, _ bo out, _ = sjson.SetRawBytes(out, "request.generationConfig.imageConfig", []byte(imgCfg.Raw)) } + // OpenRouter-style image_config (snake_case) support + // If the input uses top-level image_config.aspect_ratio, map it into request.generationConfig.imageConfig.aspectRatio. + + if imgCfg := gjson.GetBytes(rawJSON, "image_config"); imgCfg.Exists() && imgCfg.IsObject() { + if ar := imgCfg.Get("aspect_ratio"); ar.Exists() && ar.Type == gjson.String { + out, _ = sjson.SetBytes(out, "request.generationConfig.imageConfig.aspectRatio", ar.Str) + } + } // messages -> systemInstruction + contents messages := gjson.GetBytes(rawJSON, "messages") if messages.IsArray() { diff --git a/internal/translator/gemini/openai/chat-completions/gemini_openai_request.go b/internal/translator/gemini/openai/chat-completions/gemini_openai_request.go index 4c5111e7..77ef7dfa 100644 --- a/internal/translator/gemini/openai/chat-completions/gemini_openai_request.go +++ b/internal/translator/gemini/openai/chat-completions/gemini_openai_request.go @@ -85,6 +85,14 @@ func ConvertOpenAIRequestToGemini(modelName string, inputRawJSON []byte, _ bool) out, _ = sjson.SetRawBytes(out, "generationConfig.imageConfig", []byte(imgCfg.Raw)) } + // OpenRouter-style image_config (snake_case) support + // If the input uses top-level image_config.aspect_ratio, map it into generationConfig.imageConfig.aspectRatio. + if imgCfg := gjson.GetBytes(rawJSON, "image_config"); imgCfg.Exists() && imgCfg.IsObject() { + if ar := imgCfg.Get("aspect_ratio"); ar.Exists() && ar.Type == gjson.String { + out, _ = sjson.SetBytes(out, "generationConfig.imageConfig.aspectRatio", ar.Str) + } + } + // messages -> systemInstruction + contents messages := gjson.GetBytes(rawJSON, "messages") if messages.IsArray() { diff --git a/internal/translator/gemini/openai/responses/gemini_openai-responses_request.go b/internal/translator/gemini/openai/responses/gemini_openai-responses_request.go index 9ed23bc5..3bc2ec98 100644 --- a/internal/translator/gemini/openai/responses/gemini_openai-responses_request.go +++ b/internal/translator/gemini/openai/responses/gemini_openai-responses_request.go @@ -268,5 +268,12 @@ func ConvertOpenAIResponsesRequestToGemini(modelName string, inputRawJSON []byte out, _ = sjson.SetRaw(out, "generationConfig.imageConfig", imgCfg.Raw) } + // OpenRouter-style image_config (snake_case) support at top-level + if imgCfg := root.Get("image_config"); imgCfg.Exists() && imgCfg.IsObject() { + if ar := imgCfg.Get("aspect_ratio"); ar.Exists() && ar.Type == gjson.String { + out, _ = sjson.Set(out, "generationConfig.imageConfig.aspectRatio", ar.String()) + } + } + return []byte(out) }