fix: pass tool result content through as string in OpenAI/Claude -> Gemini translation - #11624
Merged
diegosouzapw merged 1 commit intoAug 26, 2026
Conversation
…emini translation
Tool results that are themselves valid JSON (e.g. a WebFetch payload) were
JSON.parse'd and nested into functionResponse.response.result as an object,
which Antigravity rejects with HTTP 400 'upstream error'.
Stop parsing tool result content in openai-to-gemini.ts and
claude-to-gemini.ts: the raw string is now passed through unchanged as
response.result, and a plain-text result no longer gets double-wrapped as
{ result: { result: ... } }.
diegosouzapw
merged commit Aug 26, 2026
0481f61
into
diegosouzapw:release/v3.8.51
10 of 16 checks passed
5 tasks done
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…emini translation (diegosouzapw#11624) Merged via /merge-batch (lote 2026-08-26 batch 2, v3.8.51). Boarded no worktree combinado junto com outras ~20 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e 292 testes focados (unit) + 18 (vitest) passando. Obrigado pela contribuição.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Tool results that are themselves valid JSON (e.g. a WebFetch payload
{"title": ..., "summary": ...}) wereJSON.parse'd and nested intofunctionResponse.response.resultas a structured object by both Gemini request translators. Antigravity rejects that shape with HTTP 400 "upstream error".This change stops parsing tool result content entirely: the raw string is passed through unchanged as
response.result, and plain-text results are no longer double-wrapped as{ result: { result: ... } }.open-sse/translator/request/openai-to-gemini.ts— drop thetryParseJSONdance on tool result content; emitresponse: { result: resp }.open-sse/translator/request/claude-to-gemini.ts— same fortool_resultcontent; remove the now-unusedtryParseJSONimport.openai-to-gemini.tskeeps parsingfunctioncall arguments (fn.arguments) — that path is untouched.Related Issues
Validation
Change type: other (request-translator conversion)
npm run lint— full lint runs in CI; the changed files are eslint-clean (--max-warnings 0, exit 0)release/v3.8.51tipe0ea3f9; focused checks rerun after the changeEvidence — translator suites (includes the new regression tests):
Evidence — open-sse typecheck gate and test discovery (the local runner is Windows 24 where
npx.cmdspawnSync is EINVAL — same class of issue the repo's Windows build scripts already accommodate — sotscwas invoked directly with identical flags and the same baseline diff):Tests Added Or Updated
tests/unit/translator-tool-result-json-passthrough.test.ts(new): JSON-string and plain-text tool results stay raw strings through OpenAI→Gemini, OpenAI→Antigravity (Cloud Code envelope) and Claude→Gemini request translation.tests/unit/translator-openai-to-gemini.test.ts: 3 expectations updated to the new shape ({"temp":20}stays a string;"The answer is capybara-4729."is no longer double-wrapped;'{"ok":true}'stays a string).tests/unit/translator-claude-to-gemini.test.ts: 1 expectation updated ("20C"is no longer double-wrapped).Coverage Notes
open-sse/translator/request/conversion. The two translator suites plus the new passthrough suite assert the exact emittedfunctionResponse.responseshape on both the OpenAI and Claude input paths, including the Cloud Code envelope used for Antigravity.response: { result: <string> }shape is exactly what the response-direction translators already consume (gemini-to-openai-function-response.test.tsusesresponse: { result: "b done" }), so round-trips are consistent.Reviewer Notes
functionResponse.response.resultis always the raw string now — for JSON-looking and plain-text tool results alike, on both translators.{ result: { result: "20C" } }→{ result: "20C" }) is removed intentionally; the outer{ result: ... }wrapper stays because Gemini'sFunctionResponse.responseis an object.release/v3.8.51tip (e0ea3f9, dependabot deps: bump the development group across 1 directory with 8 updates #11428, 2026-08-26) theknown-symbolsandmutation-test-coveragegates in Fast Quality Gates fail for ANY PR cut from this base: both reproduce identically on a pristinee0ea3f9checkout (verified locally, zero PR changes applied). This PR touches neither executors/providers (known-symbols) norrouteGuard/combo-quota modules (stryker testFiles); the failures are the inherited base-reds tracked by fix(ci): resolve inherited release/v3.8.51 base-red CI failures #11608, chore(ci): unblock quality gates - env-doc sync + stryker tap.testFiles registration (#9282) #11609 (merge-ready, all green) and fix(autoCombo,sse): drop vendor-retired ids from the auto-combo pool and skip leftover arena_elo (#11625) #11626. The unit-shard and docs-gates flakes on the first CI run are also environmental (missingbetter_sqlite3.nodenative binary on the runner; docs gates pass locally on the identical tree).