Skip to content

test(agent): pin the Gemini 3.x tool-result replay to the live wire shape - #3827

Merged
kojiwakayama merged 1 commit into
mainfrom
fix/issue-549-gemini3-tool-results
Aug 17, 2026
Merged

test(agent): pin the Gemini 3.x tool-result replay to the live wire shape#3827
kojiwakayama merged 1 commit into
mainfrom
fix/issue-549-gemini3-tool-results

Conversation

@kwakayama

Copy link
Copy Markdown
Contributor

What this is

A regression test, not a fix. The fix for the reported bug already landed on main in #3820. This pins the behaviour to the shape the live API actually returns, and records the verification.

The bug (veryfront-issue-inbox#549)

google-ai-studio/gemini-3.1-pro-preview and google-ai-studio/gemini-3.5-flash passed text runs but failed every tool call. The tool call itself succeeded; the run died on the next provider request — the one carrying the tool result back.

Captured verbatim from the provider:

{"error": {"code": 400,
 "message": "Function call is missing a thought_signature in functionCall parts. This is required for tools to work correctly, and missing thought_signature may lead to degraded model performance. Additional data, function call `default_api:get_weather` , position 2. Please refer to https://ai.google.dev/gemini-api/docs/thought-signatures for more details.",
 "status": "INVALID_ARGUMENT"}}

Replaying the model turn four ways against the live gateway isolates the cause to exactly one field:

replayed model turn 3.1-pro 3.5-flash 2.5-pro
verbatim, all parts 200 200 200
functionCall parts only, signature kept 200 200 200
trailing empty-text part dropped 200 200 200
functionCall only, signature stripped 400 400 200

Not the functionResponse shape, not part ordering, not the trailing {"text":""} part 3.x emits. Only thoughtSignature. 2.5 tolerates its absence, which is why the same round trip passed there and made this look 3.x-specific rather than replay-specific.

Why it is already fixed

ext-llm-google was correct on both ends the whole time: google-stream.ts retains the signed raw part and emits it as providerMetadata.google.rawAssistantParts, and google-request-builder.ts replays those parts verbatim. The metadata never reached the replay path, because the agent loop rebuilds the prompt from framework messages on every step and had no field to carry it. #3820 plumbed providerMetadata through that boundary.

What this test adds

The existing continuation tests drive a synthetic single-part stream. A real gemini-3.1-pro-preview response splits differently: the signature rides the functionCall part in the first chunk, and a trailing empty-text part arrives in a separate chunk alongside finishReason: STOP. Both parts are retained, and the verbatim two-part replay is what the live API accepts. This test uses that captured shape, so a future change that drops the trailing part or the signature fails here instead of in production against one model generation.

Verification

main:     [OK  ] gemini-3.1-pro-preview | requests=2 | 2nd request has thoughtSignature=true
          [OK  ] gemini-3.5-flash       | requests=2 | 2nd request has thoughtSignature=true
          [OK  ] gemini-2.5-pro         | requests=2 | 2nd request has thoughtSignature=true
          [OK  ] gemini-2.5-flash       | requests=2 | 2nd request has thoughtSignature=true

pre-fix:  [FAIL] gemini-3.1-pro-preview | Provider request failed with status 400
          [FAIL] gemini-3.5-flash       | Provider request failed with status 400
          [OK  ] gemini-2.5-pro
          [OK  ] gemini-2.5-flash
  • deno test --allow-all extensions/ext-llm-google/ — 4 passed (106 steps).
  • deno test --allow-all src/agent/runtime/provider-metadata-continuation.test.ts — 6 steps, all pass.
  • text-generation-runtime-message-converter.test.ts and runtime-bridge.test.ts — 2 passed (78 steps).

Still open: the fix is unreleased

#3820 merged after v0.1.1240 and is in no published release. Staging runs veryfront@0.1.1231. Until a release ships and is deployed, #549 still reproduces in staging and production regardless of this PR. That release is the remaining action, not more code.

Also checked and clear: reloaded multi-turn history (unsigned tool calls from earlier turns) returns 200 on 3.x. Gemini only enforces the signature on the tool call immediately preceding the tool result, so conversations resumed from persistence are unaffected by the metadata being in-memory only.

Refs veryfront-issue-inbox#549

https://claude.ai/code/session_01J2e7P4tmqYjYZQ1paDomg5

@github-actions

Copy link
Copy Markdown

📦 Client bundle boundary

Entrypoint Modules Source size Server leaks
src/index.client.ts 325 1937 KiB ✅ 0

A server module in a client graph aborts hydration in the browser. New leaks fail CI; known leaks are tracked in scripts/lint/client-bundle-baseline.json to burn down.

@coderabbitai

coderabbitai Bot commented Aug 17, 2026

Copy link
Copy Markdown

Important

Review available on request

  • 🔍 Trigger review

Reviews should be triggered manually for repositories with fewer than 10 stars. Select Trigger review above or comment @coderabbitai review to review the latest changes. For a full review, comment @coderabbitai full review.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3ac7c8a8-a96f-45d2-acf6-4ede641ebcd1


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c7f304c1f6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/agent/runtime/provider-metadata-continuation.test.ts Outdated
…hape

Gemini 3.x rejects the tool-result leg with HTTP 400 "Function call is
missing a thought_signature in functionCall parts" unless the signed
model turn is replayed verbatim. 2.5 accepts an unsigned replay, so the
regression is invisible on that generation.

The existing continuation tests use a synthetic single-part stream. Add a
case modelled on a gemini-3.1-pro-preview streamGenerateContent response,
where the signature rides the functionCall part in the first chunk and a
trailing empty-text part arrives in a separate chunk with the finish
reason. That two-chunk shape is what the live API accepts, and it is the
shape the retained raw parts must reproduce. The signature value is
opaque to the replay path, so the fixture carries a fabricated
placeholder instead of a provider-generated value.

Verified red against 5887da1 (the commit before #3820) and green on
main, plus a live round trip through the staging AI gateway on
gemini-3.1-pro-preview, gemini-3.5-flash, gemini-2.5-pro and
gemini-2.5-flash.

Refs veryfront-issue-inbox#549

Claude-Session: https://claude.ai/code/session_01J2e7P4tmqYjYZQ1paDomg5
@kwakayama
kwakayama force-pushed the fix/issue-549-gemini3-tool-results branch from c7f304c to 1511185 Compare August 17, 2026 20:27
@kojiwakayama
kojiwakayama added this pull request to the merge queue Aug 17, 2026
Merged via the queue into main with commit e875898 Aug 17, 2026
34 checks passed
@kojiwakayama
kojiwakayama deleted the fix/issue-549-gemini3-tool-results branch August 17, 2026 22:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants