From ef1d40f78c77b79fb5a357528b504af2abb8314f Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Wed, 10 Jun 2026 12:33:21 -0300 Subject: [PATCH] =?UTF-8?q?docs(changelog)+test:=20reconcile=20standard-Ge?= =?UTF-8?q?mini=20native=20mode=20(#3569)=20=E2=80=94=20update=20round-2?= =?UTF-8?q?=20rationale=20comment=20+=20log=20VPS=20validation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 ++- .../gemini-signatureless-text-mode.test.ts | 19 +++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20c88a54ed..8c9917732d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,8 @@ ### πŸ”§ Bug Fixes -- **fix(translator):** scope the Gemini `thoughtSignature` bypass to the Antigravity/CLI path and unwrap array-shaped Gemini error bodies β€” signature-less historical tool calls on Antigravity/CLI are emitted as native parts carrying the `skip_thought_signature_validator` sentinel (preventing upstream 400s), while the standard Gemini direct path keeps its existing text/context representation untouched. ([#3560](https://github.com/diegosouzapw/OmniRoute/pull/3560) β€” thanks @oyi77 and @Six7Day via [#3414](https://github.com/diegosouzapw/OmniRoute/pull/3414)) +- **fix(translator):** scope the Gemini `thoughtSignature` bypass to the Antigravity/CLI path and unwrap array-shaped Gemini error bodies β€” signature-less historical tool calls on Antigravity/CLI are emitted as native parts carrying the `skip_thought_signature_validator` sentinel (preventing upstream 400s). (The standard Gemini direct path was kept on text/context representation here, then switched to native by #3569 below.) ([#3560](https://github.com/diegosouzapw/OmniRoute/pull/3560) β€” thanks @oyi77 and @Six7Day via [#3414](https://github.com/diegosouzapw/OmniRoute/pull/3414)) +- **fix(translator):** the standard Gemini direct path now maps historical tool calls to **native** `functionCall`/`functionResponse` parts instead of inert text. The previous text serialization (`[tool_history_call: …]` / "Historical tool-call record only …") leaked into the model's visible output (the model echoed the annotation text). A live test against the real Gemini API confirmed thinking models accept signature-less native `functionCall` parts (`gemini-2.5-flash` returns 200 even with `tools` + `thinkingConfig`), so the text mode is no longer needed as the default and the leak is gone. The Antigravity/CLI sentinel path (#3560) is untouched. ([#3569](https://github.com/diegosouzapw/OmniRoute/pull/3569) β€” thanks @hartmark) - **fix(auto-update):** the self-update flow now resolves a stable project root instead of the launch directory β€” `resolveProjectRoot` walks up from the module's own location (`__dirname`) to the nearest `package.json`/`.git` rather than trusting `process.cwd()` (which could point anywhere the process was started from), and every `git`/`npm`/`pm2` step in `version/route.ts` runs against that `PROJECT_ROOT`. The original resolver fell through to `return cwd` on every branch, making `PROJECT_ROOT` a no-op; the walker (with TDD coverage) fixes that. ([#3561](https://github.com/diegosouzapw/OmniRoute/pull/3561) β€” thanks @oyi77; `PROJECT_ROOT` originally introduced + `version/route.ts` call sites wired in [#3423](https://github.com/diegosouzapw/OmniRoute/pull/3423) β€” thanks @ViFigueiredo) - **fix(plugins):** wire plugin lifecycle hooks (`onInstall`/`onActivate`/`onDeactivate`/`onUninstall`) in the loader so `manager.ts` can register them with `emitHook` β€” they were declared in the manifest schema and dispatched by the manager, but the loader never built the `plugin.onX` methods, leaving the lifecycle hooks declared-but-dead. Also addresses #3518 review comments (redundant `RegExp(/.../)` β†’ literals, `logs/[id]` route awaits the Next route `params`, indentation). ([#3562](https://github.com/diegosouzapw/OmniRoute/pull/3562) β€” thanks @oyi77) diff --git a/tests/unit/gemini-signatureless-text-mode.test.ts b/tests/unit/gemini-signatureless-text-mode.test.ts index 56ff8da0a6..3e6936c2ee 100644 --- a/tests/unit/gemini-signatureless-text-mode.test.ts +++ b/tests/unit/gemini-signatureless-text-mode.test.ts @@ -1,12 +1,19 @@ import test from "node:test"; import assert from "node:assert/strict"; -// Regression guard for the gating between the standard-Gemini path and the -// Antigravity/CLI bypass path (#3414/#3560 review). Standard Gemini (direct API, -// the registered FORMATS.GEMINI translator uses mode "text") rejects the -// thoughtSignature field AND signature-less native tool parts, so signature-less -// historical tool calls/responses must be represented as inert TEXT (#3358). -// Only the Antigravity/CLI bypass path emits native parts + the +// Regression guard for the per-mode behavior of the OpenAIβ†’Gemini translator +// (#3414/#3560/#3569). History of the standard-Gemini path: +// - #3560 set the registered FORMATS.GEMINI translator to mode "text" on the +// assumption that thinking Gemini models reject signature-less native tool +// parts (400 "missing thought_signature"). +// - #3569 changed the registered default to mode "native" after a live test +// against the real Gemini API (gemini-2.5-flash returns 200 for a +// signatureless historical functionCall, even with tools + thinkingConfig), +// which also removes the text-serialization leak (#3358). +// These tests still pin the *per-mode* output shape: "text" mode keeps history as +// inert text (no native parts, no sentinel β€” still available as an explicit mode), +// and "native" mode emits a native functionCall with no fake signature. The +// Antigravity/CLI bypass path is the only one that injects the // skip_thought_signature_validator sentinel. const { openaiToGeminiRequest } = await import( "../../open-sse/translator/request/openai-to-gemini.ts"