From 89cd95432207e2391bac43242d6eedfef8792ea4 Mon Sep 17 00:00:00 2001 From: Raxxoor Date: Thu, 18 Jun 2026 18:16:59 +0100 Subject: [PATCH] fix(antigravity): default includeThoughts for modern Gemini models (#4180) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Integrated into release/v3.8.29 — default includeThoughts for modern Gemini (2.5+) in the openai->gemini translator, so the model's reasoning is marked thought:true and routed to reasoning_content instead of leaking into visible content (#4170). Thanks @dhaern! On review we regenerated the gemini golden snapshots (basic-chat/with-system) and committed the new modern-gemini-default-thinking snapshot. 61/61 translator + golden tests pass; eslint clean. Respects explicit client thinking config (only applies when none is set) and excludes gemini-1.x / non-thinking 2.0. --- .../translator/request/openai-to-gemini.ts | 20 +++++++++ .../translation/openai-to-gemini.json | 31 ++++++++++++-- .../openai-to-gemini/basic-chat.json | 6 ++- .../modern-gemini-default-thinking.json | 42 +++++++++++++++++++ .../openai-to-gemini/with-system.json | 6 ++- 5 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 tests/snapshots/translation/openai-to-gemini/modern-gemini-default-thinking.json diff --git a/open-sse/translator/request/openai-to-gemini.ts b/open-sse/translator/request/openai-to-gemini.ts index c1453aafef..39e2016da6 100644 --- a/open-sse/translator/request/openai-to-gemini.ts +++ b/open-sse/translator/request/openai-to-gemini.ts @@ -307,6 +307,26 @@ function openaiToGeminiBase( }; } + // 3. Default: all modern Gemini models (2.5+) have thinking capability. + // If the client didn't explicitly request thinking (via reasoning_effort or + // thinking.type), still set includeThoughts so the upstream marks thought + // parts with thought:true. Without this, the model's reasoning leaks into + // visible content instead of being routed to reasoning_content by the + // response translator. (#4170) + if (!result.generationConfig.thinkingConfig) { + const modelLower = model.toLowerCase(); + if ( + modelLower.includes("gemini") && + !modelLower.includes("gemini-1") && + (!modelLower.includes("gemini-2.0") || modelLower.includes("thinking")) + ) { + result.generationConfig.thinkingConfig = { + thinkingBudget: getDefaultThinkingBudget(model) || capThinkingBudget(model, 24576), + includeThoughts: true, + }; + } + } + // Build tool_call_id -> name map const tcID2Name: Record = {}; const messages = body.messages as Array> | undefined; diff --git a/tests/fixtures/translation/openai-to-gemini.json b/tests/fixtures/translation/openai-to-gemini.json index 3c91b8cd4f..f9a60593a4 100644 --- a/tests/fixtures/translation/openai-to-gemini.json +++ b/tests/fixtures/translation/openai-to-gemini.json @@ -5,7 +5,12 @@ "targetFormat": "gemini", "input": { "model": "gemini-2.5-flash", - "messages": [{ "role": "user", "content": "Hello Gemini!" }] + "messages": [ + { + "role": "user", + "content": "Hello Gemini!" + } + ] } }, { @@ -15,10 +20,30 @@ "input": { "model": "gemini-2.5-pro", "messages": [ - { "role": "system", "content": "You are a helpful assistant." }, - { "role": "user", "content": "Tell me a joke." } + { + "role": "system", + "content": "You are a helpful assistant." + }, + { + "role": "user", + "content": "Tell me a joke." + } ], "temperature": 0.7 } + }, + { + "name": "openai-to-gemini/modern-gemini-default-thinking", + "sourceFormat": "openai", + "targetFormat": "gemini", + "input": { + "model": "gemini-2.5-flash", + "messages": [ + { + "role": "user", + "content": "Hello Gemini!" + } + ] + } } ] diff --git a/tests/snapshots/translation/openai-to-gemini/basic-chat.json b/tests/snapshots/translation/openai-to-gemini/basic-chat.json index 7c03dfa908..78877bfee7 100644 --- a/tests/snapshots/translation/openai-to-gemini/basic-chat.json +++ b/tests/snapshots/translation/openai-to-gemini/basic-chat.json @@ -10,7 +10,11 @@ } ], "generationConfig": { - "maxOutputTokens": 65536 + "maxOutputTokens": 65536, + "thinkingConfig": { + "includeThoughts": true, + "thinkingBudget": 24576 + } }, "model": "gemini-2.5-flash", "safetySettings": [ diff --git a/tests/snapshots/translation/openai-to-gemini/modern-gemini-default-thinking.json b/tests/snapshots/translation/openai-to-gemini/modern-gemini-default-thinking.json new file mode 100644 index 0000000000..78877bfee7 --- /dev/null +++ b/tests/snapshots/translation/openai-to-gemini/modern-gemini-default-thinking.json @@ -0,0 +1,42 @@ +{ + "contents": [ + { + "parts": [ + { + "text": "Hello Gemini!" + } + ], + "role": "user" + } + ], + "generationConfig": { + "maxOutputTokens": 65536, + "thinkingConfig": { + "includeThoughts": true, + "thinkingBudget": 24576 + } + }, + "model": "gemini-2.5-flash", + "safetySettings": [ + { + "category": "HARM_CATEGORY_HATE_SPEECH", + "threshold": "OFF" + }, + { + "category": "HARM_CATEGORY_DANGEROUS_CONTENT", + "threshold": "OFF" + }, + { + "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", + "threshold": "OFF" + }, + { + "category": "HARM_CATEGORY_HARASSMENT", + "threshold": "OFF" + }, + { + "category": "HARM_CATEGORY_CIVIC_INTEGRITY", + "threshold": "OFF" + } + ] +} diff --git a/tests/snapshots/translation/openai-to-gemini/with-system.json b/tests/snapshots/translation/openai-to-gemini/with-system.json index 4306e1f464..01b0a2af5f 100644 --- a/tests/snapshots/translation/openai-to-gemini/with-system.json +++ b/tests/snapshots/translation/openai-to-gemini/with-system.json @@ -11,7 +11,11 @@ ], "generationConfig": { "maxOutputTokens": 8192, - "temperature": 0.7 + "temperature": 0.7, + "thinkingConfig": { + "includeThoughts": true, + "thinkingBudget": 24576 + } }, "model": "gemini-2.5-pro", "safetySettings": [