Skip to content

feat(ai-gemini): upgrade @google/genai to v2 + migrate Interactions API#781

Open
jherr wants to merge 13 commits into
mainfrom
gemini-upgrade
Open

feat(ai-gemini): upgrade @google/genai to v2 + migrate Interactions API#781
jherr wants to merge 13 commits into
mainfrom
gemini-upgrade

Conversation

@jherr

@jherr jherr commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Status: WIP / draft. Opening early for visibility. See open items below before review.

Summary

Upgrades @tanstack/ai-gemini to the @google/genai v2 SDK and migrates the
stateful geminiTextInteractions adapter to the SDK 2.x Interactions event
protocol
(the May-2026 Interactions breaking changes):

  • response_mime_type + flat response_format → polymorphic
    response_format: { type, mime_type, schema }.
  • Event translation reworked to route by step index and consume
    step.start / step.delta / step.stop and
    interaction.created / interaction.completed, including streamed
    function-call arguments_delta fragments.

The existing geminiTextInteractions support is carried forward, not
removed — this PR builds on PR #502 and adapts it to the new SDK.

Verification

  • Unit: packages/ai-gemini — 206 passed, incl. all 29
    text-interactions-adapter tests (rewritten to emit SDK 2.x step.* events).
  • Full pnpm test:pr: sherif, knip, docs, eslint, lib, types, build all
    green across affected packages.
  • E2E (Gemini): chat, tools, multimodal, video-gen all pass under the v2
    SDK against aimock.
  • ⏸️ E2E (Gemini stateful-interactions): quarantined — see below.

Review feedback addressed

  • Streamed function-call args now parse with partial-json instead of strict
    JSON.parse: incomplete arguments_delta fragments no longer log a parse
    error each, and a truncated buffer keeps the last good args instead of
    resetting to {}.
  • Dropped the unnecessary as Record<string, unknown> cast on step.arguments.
  • Removed accidentally-committed .agentsroom/ tooling (including a personal
    claudeSessionId).
  • Added unit coverage for multi-fragment arguments_delta accumulation, args
    stream truncation, and thought_summaryREASONING_*.

Known open item — aimock lags SDK 2.x

The stateful-interactions e2e test is marked test.fixme (skipped, not
failing). Every published @copilotkit/aimock (≤ 1.31.0, latest as of
2026-06-17) still emits the SDK 1.x Interactions events
(content.* / interaction.start / interaction.complete), which the migrated
2.x adapter doesn't consume — so the mock can't exercise this path yet. This is a
mock/adapter format mismatch, not an adapter bug; 2.x behaviour is covered by
unit tests.

The exact event shapes aimock must emit to re-enable the test are documented in
testing/e2e/tests/stateful-interactions.AIMOCK-TODO.md.

TODO before un-drafting

  • Land an aimock release that emits SDK 2.x Interactions events, bump it, and
    un-fixme the e2e test (+ open a follow-up issue to track re-enabling it).
  • Add a changeset.
  • Full pnpm test:pr pass.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Upgraded to Gemini SDK 2.x with improved step-based streaming for better control over function call execution.
    • Enhanced function-call argument streaming with lenient parsing to preserve partial arguments even when truncated.
  • Bug Fixes

    • Tool events now include complete step information rather than fragments, improving reliability.
  • Tests

    • Updated test suite for SDK 2.x event model; marked E2E stateful interactions test as pending compatibility updates.
  • Chores

    • Added dependency for lenient JSON parsing to support incomplete argument buffers.

jherr and others added 9 commits June 12, 2026 07:00
… API

Bump @google/genai from ^1.43.0 to ^2.8.0. The v2 SDK replaces the legacy
flat Interactions schema with the new step-based model, so migrate the
experimental text-interactions adapter to the renamed SSE events
(interaction.created / step.start / step.delta / step.stop /
interaction.completed) and the Step data model, switch structured output to
the polymorphic response_format, and drop the deprecated response_mime_type.
Update the 25 text-interactions tests to the new event/step schema and set
allowBuilds['@google/genai'] to false (its install scripts are no-ops for
consumers).

Co-authored-by: Cursor <cursoragent@cursor.com>
# Conflicts:
#	pnpm-workspace.yaml
… 2.x

The @google/genai v2 migration moved geminiTextInteractions onto the SDK 2.x
Interactions event protocol (step.start/step.delta/step.stop,
interaction.created/completed). All published @copilotkit/aimock versions
(≤1.31.0) still emit the SDK 1.x shapes (content.* / interaction.start /
interaction.complete), so the e2e mock and adapter no longer agree on the wire
format and the assistant message comes back empty.

Mark the test test.fixme (skipped, not failing) and document the exact event
shapes aimock must emit to re-enable it. SDK 2.x adapter behaviour stays covered
by unit tests in packages/ai-gemini/tests/text-interactions-adapter.test.ts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Upgrades @google/genai from 1.x to 2.x and migrates the experimental Gemini text-interactions adapter to the SDK 2.x step-based streaming API (step.start/step.delta/step.stop). Adds partial-json for lenient function-call argument accumulation, switches structured output to a polymorphic response_format shape, updates CUSTOM event types from delta to Step objects, and aligns all unit tests to the new fixture format.

Changes

Gemini SDK 2.x Migration

Layer / File(s) Summary
SDK version bump, provider options, and workspace config
packages/ai-gemini/package.json, packages/ai-gemini/src/experimental/text-interactions/provider-options.ts, pnpm-workspace.yaml, .changeset/gemini-genai-v2-upgrade.md
@google/genai bumped to ^2.8.0, partial-json added as a dependency, response_mime_type removed and generation_config added to ExternalTextInteractionsProviderOptions, @google/genai build allowance set to false in workspace config, and changeset entry added.
CUSTOM event interface types: ContentDelta → Step objects
packages/ai-gemini/src/experimental/text-interactions/events.ts
Eight exported CUSTOM event interfaces for built-in tool pairs (google_search, code_execution, url_context, file_search) have their value payload types changed from Interactions.ContentDelta.*Delta to Interactions.*CallStep / Interactions.*ResultStep. Adapter docs updated to describe full Step forwarding via step.start.
Adapter: request building, streaming translation, and extractText rewrite
packages/ai-gemini/src/experimental/text-interactions/adapter.ts
partial-json import added. structuredOutput now sets response_format (type, mime_type, schema) instead of response_mime_type. buildInteractionsRequest drops the legacy field. parsePartialToolArguments replaces strict JSON parsing with lenient buffer accumulation. translateInteractionEvents switches from interaction.start/content.* to interaction.created/step.start/step.delta/step.stop with per-step tool-call id maps and argument buffers. Built-in tool CUSTOM events emit value: step. extractTextFromInteraction prefers interaction.output_text then iterates interaction.steps.
Unit tests updated to SDK 2.x event fixtures
packages/ai-gemini/tests/text-interactions-adapter.test.ts
All stream fixtures rewritten from interaction.start/content.* to interaction.created/interaction.completed and step.* shapes. Structured output mocks use steps: [...] instead of outputs: [...]; assertions check response_format instead of response_mime_type. New/expanded coverage for argument accumulation, mid-stream truncation, reasoning chunks, interactionId map lifecycle, and consumer abandonment.
E2E test disabled and aimock mismatch documented
testing/e2e/tests/stateful-interactions.spec.ts, testing/e2e/tests/stateful-interactions.AIMOCK-TODO.md
The two-turn stateful-interactions e2e test is changed to test.fixme with comments explaining the SDK 1.x vs 2.x aimock event-shape mismatch. A new AIMOCK-TODO.md enumerates expected SDK 2.x event_type names, required aimock emitter changes, and steps to re-enable once aimock supports SDK 2.x.

Sequence Diagram(s)

sequenceDiagram
  participant GeminiSDK as Gemini SDK 2.x Stream
  participant Adapter as GeminiTextInteractionsAdapter
  participant AGUI as AG-UI Consumer

  GeminiSDK->>Adapter: interaction.created {interactionId}
  Adapter->>AGUI: RUN_STARTED

  GeminiSDK->>Adapter: step.start {type: model_output}
  Adapter->>AGUI: TEXT_MESSAGE_START

  GeminiSDK->>Adapter: step.delta {text_delta}
  Adapter->>AGUI: TEXT_MESSAGE_CONTENT

  GeminiSDK->>Adapter: step.start {type: function_call, index, name}
  Adapter->>AGUI: TOOL_CALL_START

  loop arguments_delta fragments
    GeminiSDK->>Adapter: step.delta {arguments_delta: string fragment}
    Note over Adapter: Append to buffer, run parsePartialToolArguments
    Adapter->>AGUI: TOOL_CALL_ARGS {args: accumulated buffer}
  end

  GeminiSDK->>Adapter: step.stop
  Adapter->>AGUI: TOOL_CALL_END

  GeminiSDK->>Adapter: interaction.completed
  Adapter->>AGUI: RUN_FINISHED
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Possibly related PRs

  • TanStack/ai#502: The original geminiTextInteractions() implementation PR that established the adapter's interaction lifecycle and streaming translation logic — this PR rewrites that same translation layer for SDK 2.x.

Suggested reviewers

  • tombeckenham

Poem

🐇 Hop hop, the SDK has grown,
From content deltas, seeds are sown,
Now steps start, delta, stop with grace,
partial-json fills each partial space,
The rabbit cheers the response_format day,
While e2e tests wait for aimock's way! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description provides a comprehensive overview of changes, verification results, and open items, addressing all key aspects. Both checklist items are accounted for with a changeset added and testing completed.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title directly and concisely summarizes the main changes: upgrading @google/genai to v2 and migrating the Interactions API to the new SDK version.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch gemini-upgrade

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.

@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

🚀 Changeset Version Preview

2 package(s) bumped directly, 0 bumped as dependents.

🟨 Minor bumps

Package Version Reason
@tanstack/ai-gemini 0.17.2 → 0.18.0 Changeset

🟩 Patch bumps

Package Version Reason
@tanstack/ai-mcp 0.1.6 → 0.1.7 Changeset

@socket-security

socket-security Bot commented Jun 17, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​google/​genai@​2.8.09410010098100

View full report

@nx-cloud

nx-cloud Bot commented Jun 17, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit 9feeca7

Command Status Duration Result
nx run-many --targets=build --exclude=examples/... ✅ Succeeded 2s View ↗

☁️ Nx Cloud last updated this comment at 2026-06-23 23:39:34 UTC

@pkg-pr-new

pkg-pr-new Bot commented Jun 17, 2026

Copy link
Copy Markdown

Open in StackBlitz

@tanstack/ai

npm i https://pkg.pr.new/@tanstack/ai@781

@tanstack/ai-angular

npm i https://pkg.pr.new/@tanstack/ai-angular@781

@tanstack/ai-anthropic

npm i https://pkg.pr.new/@tanstack/ai-anthropic@781

@tanstack/ai-client

npm i https://pkg.pr.new/@tanstack/ai-client@781

@tanstack/ai-code-mode

npm i https://pkg.pr.new/@tanstack/ai-code-mode@781

@tanstack/ai-code-mode-skills

npm i https://pkg.pr.new/@tanstack/ai-code-mode-skills@781

@tanstack/ai-devtools-core

npm i https://pkg.pr.new/@tanstack/ai-devtools-core@781

@tanstack/ai-elevenlabs

npm i https://pkg.pr.new/@tanstack/ai-elevenlabs@781

@tanstack/ai-event-client

npm i https://pkg.pr.new/@tanstack/ai-event-client@781

@tanstack/ai-fal

npm i https://pkg.pr.new/@tanstack/ai-fal@781

@tanstack/ai-gemini

npm i https://pkg.pr.new/@tanstack/ai-gemini@781

@tanstack/ai-grok

npm i https://pkg.pr.new/@tanstack/ai-grok@781

@tanstack/ai-groq

npm i https://pkg.pr.new/@tanstack/ai-groq@781

@tanstack/ai-isolate-cloudflare

npm i https://pkg.pr.new/@tanstack/ai-isolate-cloudflare@781

@tanstack/ai-isolate-node

npm i https://pkg.pr.new/@tanstack/ai-isolate-node@781

@tanstack/ai-isolate-quickjs

npm i https://pkg.pr.new/@tanstack/ai-isolate-quickjs@781

@tanstack/ai-mcp

npm i https://pkg.pr.new/@tanstack/ai-mcp@781

@tanstack/ai-ollama

npm i https://pkg.pr.new/@tanstack/ai-ollama@781

@tanstack/ai-openai

npm i https://pkg.pr.new/@tanstack/ai-openai@781

@tanstack/ai-openrouter

npm i https://pkg.pr.new/@tanstack/ai-openrouter@781

@tanstack/ai-preact

npm i https://pkg.pr.new/@tanstack/ai-preact@781

@tanstack/ai-react

npm i https://pkg.pr.new/@tanstack/ai-react@781

@tanstack/ai-react-ui

npm i https://pkg.pr.new/@tanstack/ai-react-ui@781

@tanstack/ai-solid

npm i https://pkg.pr.new/@tanstack/ai-solid@781

@tanstack/ai-solid-ui

npm i https://pkg.pr.new/@tanstack/ai-solid-ui@781

@tanstack/ai-svelte

npm i https://pkg.pr.new/@tanstack/ai-svelte@781

@tanstack/ai-utils

npm i https://pkg.pr.new/@tanstack/ai-utils@781

@tanstack/ai-vue

npm i https://pkg.pr.new/@tanstack/ai-vue@781

@tanstack/ai-vue-ui

npm i https://pkg.pr.new/@tanstack/ai-vue-ui@781

@tanstack/openai-base

npm i https://pkg.pr.new/@tanstack/openai-base@781

@tanstack/preact-ai-devtools

npm i https://pkg.pr.new/@tanstack/preact-ai-devtools@781

@tanstack/react-ai-devtools

npm i https://pkg.pr.new/@tanstack/react-ai-devtools@781

@tanstack/solid-ai-devtools

npm i https://pkg.pr.new/@tanstack/solid-ai-devtools@781

commit: 1d80a2d

Resolve conflict in ai-gemini text-interactions adapter: the v2
Interactions migration moved function-call start handling into the
`step.start` case and streams args via a new `arguments_delta` delta,
so main's older `function_call` delta block is obsolete — kept the
PR's architecture and dropped the conflicting block.

Preserve main's #477 fix in the new architecture: emit
`parentMessageId: messageId` on TOOL_CALL_START so a tool-first
function call binds to the same assistant message id the eventual
TEXT_MESSAGE_START uses. Ported the accompanying test from the old
content.* wire shape to the v2 step.* shape.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jherr jherr marked this pull request as ready for review June 23, 2026 22:34
@tombeckenham tombeckenham self-assigned this Jun 23, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.agentsroom/agents.json:
- Line 8: The claudeSessionId property in agents.json (line 8) should not be
committed to version control, as it contradicts the project's established
pattern where agents-local.json and the sessions/ directory are explicitly
excluded in .gitignore. Remove the claudeSessionId from the committed
agents.json file and instead relocate it to agents-local.json or load it at
runtime from local/environment sources to align with the project's convention
for handling session and personal data.

In `@packages/ai-gemini/src/experimental/text-interactions/adapter.ts`:
- Around line 1306-1325: In the arguments_delta handling block where
safeParseToolArguments is called with the buffer parameter, the assignment
`state.args = parsed` unconditionally overwrites state.args with the result, but
safeParseToolArguments returns an empty object {} on parse failures for
incomplete JSON. To fix this and preserve the last-good args value for
incomplete buffers, only assign the parsed result to state.args when the buffer
actually represents a complete, valid JSON object. Add a condition to check
whether the parsed result is a successful parse before overwriting state.args,
ensuring incomplete fragments don't reset previously accumulated arguments to
{}.

In `@testing/e2e/tests/stateful-interactions.spec.ts`:
- Around line 38-52: The test 'two-turn conversation chained via
previous_interaction_id' is disabled using test.fixme due to a version mismatch
between the current gemini-upgrade adapter (which expects SDK 2.x events like
step.start, step.delta, interaction.created) and `@copilotkit/aimock` (which still
emits SDK 1.x events like content.delta, interaction.start). To fix this, update
the `@copilotkit/aimock` dependency in testing/e2e/package.json to a version that
emits SDK 2.x event shapes as documented in
stateful-interactions.AIMOCK-TODO.md, then change test.fixme back to test on the
disabled test case and verify it passes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: dcc3f577-6b3a-4a22-a393-f0471786dd1d

📥 Commits

Reviewing files that changed from the base of the PR and between df40512 and 1c5c29e.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (11)
  • .agentsroom/.gitignore
  • .agentsroom/agents.json
  • .agentsroom/prompts.json
  • packages/ai-gemini/package.json
  • packages/ai-gemini/src/experimental/text-interactions/adapter.ts
  • packages/ai-gemini/src/experimental/text-interactions/events.ts
  • packages/ai-gemini/src/experimental/text-interactions/provider-options.ts
  • packages/ai-gemini/tests/text-interactions-adapter.test.ts
  • pnpm-workspace.yaml
  • testing/e2e/tests/stateful-interactions.AIMOCK-TODO.md
  • testing/e2e/tests/stateful-interactions.spec.ts
💤 Files with no reviewable changes (1)
  • packages/ai-gemini/src/experimental/text-interactions/provider-options.ts

Comment thread .agentsroom/agents.json Outdated
Comment thread packages/ai-gemini/src/experimental/text-interactions/adapter.ts
Comment on lines +38 to +52
// DISABLED — blocked on aimock. The gemini-upgrade branch migrated
// `geminiTextInteractions` to the @google/genai v2 (SDK 2.x) Interactions
// event protocol, which streams `step.start` / `step.delta` / `step.stop`
// and `interaction.created` / `interaction.completed`. Every published
// `@copilotkit/aimock` (≤1.31.0) still emits the SDK 1.x shapes
// (`content.*` / `interaction.start` / `interaction.complete`), so the
// adapter consumes none of the mock's deltas and the assistant message
// comes back empty. This is a mock/adapter format mismatch, not an adapter
// bug — 2.x behaviour is covered by unit tests in
// packages/ai-gemini/tests/text-interactions-adapter.test.ts.
//
// Re-enable (test.fixme → test) once aimock emits SDK 2.x events. The exact
// required event shapes and migration steps are documented in
// ./stateful-interactions.AIMOCK-TODO.md
test.fixme('two-turn conversation chained via previous_interaction_id', async ({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if there's an open issue or PR tracking the aimock SDK 2.x migration

gh issue list --repo CopilotKit/aimock --search "SDK 2.x OR Interactions 2.x OR Gemini 2.x" --limit 10 --json number,title,state,url

# Also check recent aimock releases to see if 2.x support might already be available
gh release list --repo CopilotKit/aimock --limit 5

Repository: TanStack/ai

Length of output: 348


🏁 Script executed:

cat testing/e2e/package.json | grep -A 2 -B 2 aimock

Repository: TanStack/ai

Length of output: 289


🏁 Script executed:

find . -name "text-interactions-adapter.test.ts" -type f

Repository: TanStack/ai

Length of output: 210


🏁 Script executed:

rg "SDK 2\.x|2\.x.*event" --type ts --type tsx -i

Repository: TanStack/ai

Length of output: 177


🏁 Script executed:

rg "SDK 2\.x|2\.x.*event|step\.start|step\.delta" --type ts -i

Repository: TanStack/ai

Length of output: 149


🏁 Script executed:

head -50 ./packages/ai-gemini/tests/text-interactions-adapter.test.ts

Repository: TanStack/ai

Length of output: 1659


🏁 Script executed:

grep -n "step\.start\|step\.delta\|interaction\.created\|interaction\.completed\|content\." ./packages/ai-gemini/tests/text-interactions-adapter.test.ts | head -20

Repository: TanStack/ai

Length of output: 1093


🏁 Script executed:

cat ./testing/e2e/tests/stateful-interactions.AIMOCK-TODO.md 2>/dev/null || echo "TODO file not found"

Repository: TanStack/ai

Length of output: 7388


E2E test coverage is disabled, violating mandatory testing guidelines.

This test violates the requirement that "Every feature, bug fix, or behavior change MUST include E2E test coverage using Playwright + aimock." While the comments, comprehensive stateful-interactions.AIMOCK-TODO.md file, and unit tests (25 tests in packages/ai-gemini/tests/text-interactions-adapter.test.ts) provide excellent coverage of the 2.x adapter behavior, the E2E gap remains a blocker for merging.

The root cause is legitimate: @copilotkit/aimock (currently v1.33.0) still emits SDK 1.x event shapes (interaction.start, content.delta, etc.) while the adapter expects SDK 2.x shapes (interaction.created, step.delta, etc.), creating a complete format mismatch that prevents the mock from functioning with the current adapter code.

The migration path for aimock is documented in detail in ./stateful-interactions.AIMOCK-TODO.md (including exact event shape changes for buildInteractionsTextSSEEvents and buildInteractionsToolCallSSEEvents), but the work has not yet shipped. Once aimock releases SDK 2.x event support:

  1. Update @copilotkit/aimock in testing/e2e/package.json
  2. Change test.fixme back to test on line 52
  3. Verify the test passes before merging
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@testing/e2e/tests/stateful-interactions.spec.ts` around lines 38 - 52, The
test 'two-turn conversation chained via previous_interaction_id' is disabled
using test.fixme due to a version mismatch between the current gemini-upgrade
adapter (which expects SDK 2.x events like step.start, step.delta,
interaction.created) and `@copilotkit/aimock` (which still emits SDK 1.x events
like content.delta, interaction.start). To fix this, update the
`@copilotkit/aimock` dependency in testing/e2e/package.json to a version that
emits SDK 2.x event shapes as documented in
stateful-interactions.AIMOCK-TODO.md, then change test.fixme back to test on the
disabled test case and verify it passes.

Source: Coding guidelines

// be an empty `{}` placeholder when streaming, where the
// real args arrive as `arguments_delta` events. Treat both
// uniformly: stash whatever we got, stringify once.
const initialArgs = step.arguments as Record<string, unknown>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cast is unnecessary

Comment thread .agentsroom/agents.json Outdated
@@ -0,0 +1,10 @@
[

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This whole folder should be git ingnored, right?

// parse produced. The wire-level args fragments don't have
// to be individually-parseable, but the *full* string at
// step.stop will be.
const parsed = safeParseToolArguments(buffer, logger)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is going to throw for incomplete buffers and cause errors to be logged. As the new api streams function params you'll get error noise here. Maybe switch to partial json?

@tombeckenham tombeckenham left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pretty good. Nicely commented. Couple of things to resolve, but I'd say please raise an upstream issue on aimock to support the new gemini API. Alem or one of the team will add support and we can add e2e tests. Add a follow up issue to add e2e tests back for this. Also there's no unit tests for streamed arguments_delta (multi-fragment) and thought/thought_summary reasoning

- Stream function-call args via partial-json instead of strict JSON.parse:
  incomplete `arguments_delta` fragments no longer log a parse error each,
  and a truncated buffer keeps the last good args instead of resetting to {}
  (tombeckenham, CodeRabbit).
- Drop the unnecessary `as Record<string, unknown>` cast on step.arguments;
  FunctionCallStep.arguments is already an index-signature object
  (tombeckenham).
- Remove accidentally-committed `.agentsroom/` tooling (incl. a personal
  claudeSessionId), unrelated to this change (CodeRabbit).
- Add unit tests: multi-fragment arguments_delta accumulation, args-stream
  truncation preserving last good args, and thought_summary -> REASONING_*.
- Add changeset for the @google/genai v2 upgrade.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jherr

jherr commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review @tombeckenham 🙏 — addressed in 9feeca7:

Code

  • arguments_delta parsing (you @ adapter.ts:1317, CodeRabbit @ :1325): switched the streamed-args path from strict JSON.parse to partial-json. Incomplete fragments no longer throw / log an error each, and a mid-fragment truncation now keeps the last good args instead of resetting state.args to {} (so TOOL_CALL_END.input survives truncation).
  • Unnecessary cast (you @ adapter.ts:1037): removed — FunctionCallStep.arguments is already an index-signature object.
  • claudeSessionId committed (CodeRabbit @ .agentsroom/agents.json:8): removed the whole .agentsroom/ directory — it was accidentally-committed local tooling, unrelated to the SDK upgrade.

Tests (your note on missing coverage)

  • Added: multi-fragment arguments_delta accumulation, args-stream truncation (last-good preserved), and thought_summaryREASONING_*.
  • packages/ai-gemini: 206 passing; full pnpm test:pr green.

Changeset: added (minor on @tanstack/ai-gemini).

Still open (tracked in the PR's TODO, not in this push): the stateful-interactions e2e test stays test.fixme until @copilotkit/aimock emits SDK 2.x event shapes. Will raise the upstream aimock issue + a follow-up issue to re-enable the e2e test, per your suggestion.

@jherr jherr changed the title [WIP] feat(ai-gemini): upgrade @google/genai to v2 + migrate Interactions API [feat(ai-gemini): upgrade @google/genai to v2 + migrate Interactions API Jun 23, 2026
@jherr jherr changed the title [feat(ai-gemini): upgrade @google/genai to v2 + migrate Interactions API feat(ai-gemini): upgrade @google/genai to v2 + migrate Interactions API Jun 23, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/ai-gemini/tests/text-interactions-adapter.test.ts (1)

506-506: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider a more precise assertion for the number of TOOL_CALL_ARGS events.

The test emits 3 arguments_delta fragments but only asserts toBeGreaterThan(1). If the adapter emits one TOOL_CALL_ARGS event per delta fragment, you could strengthen this to toBe(3) to catch unexpected buffering/coalescing behavior.

✨ Optional stronger assertion
-    expect(argsEvents.length).toBeGreaterThan(1)
+    expect(argsEvents.length).toBe(3)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ai-gemini/tests/text-interactions-adapter.test.ts` at line 506, The
assertion for argsEvents.length in the test is too loose and does not precisely
validate the expected behavior. Change the expect statement from
toBeGreaterThan(1) to toBe(3) to match the exact number of arguments_delta
fragments that are emitted in the test, which will help catch unexpected
buffering or coalescing behavior in the adapter where TOOL_CALL_ARGS events
might be unexpectedly combined instead of emitted individually per delta
fragment.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/ai-gemini/tests/text-interactions-adapter.test.ts`:
- Around line 599-602: The test fixture is missing a step.start event for index
1 before the step.delta event that emits text content. Add a step.start event
with index 1 and appropriate start event properties before the existing
step.delta event block (which has event_type: 'step.delta' with index: 1) to
establish the SDK 2.x event model sequence of step.start → step.delta →
step.stop as followed by other fixtures in this test file.

---

Nitpick comments:
In `@packages/ai-gemini/tests/text-interactions-adapter.test.ts`:
- Line 506: The assertion for argsEvents.length in the test is too loose and
does not precisely validate the expected behavior. Change the expect statement
from toBeGreaterThan(1) to toBe(3) to match the exact number of arguments_delta
fragments that are emitted in the test, which will help catch unexpected
buffering or coalescing behavior in the adapter where TOOL_CALL_ARGS events
might be unexpectedly combined instead of emitted individually per delta
fragment.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 28cd2ae9-b604-4d83-aced-432817a342ae

📥 Commits

Reviewing files that changed from the base of the PR and between 1c5c29e and 1d80a2d.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (4)
  • .changeset/gemini-genai-v2-upgrade.md
  • packages/ai-gemini/package.json
  • packages/ai-gemini/src/experimental/text-interactions/adapter.ts
  • packages/ai-gemini/tests/text-interactions-adapter.test.ts
✅ Files skipped from review due to trivial changes (1)
  • .changeset/gemini-genai-v2-upgrade.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/ai-gemini/src/experimental/text-interactions/adapter.ts

Comment on lines +599 to +602
event_type: 'step.delta',
index: 1,
delta: { type: 'text', text: 'It is sunny.' },
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Missing step.start event for index 1.

The fixture emits step.delta for index 1 (text) without a prior step.start event for that step. All other test fixtures in this PR follow the step.startstep.deltastep.stop protocol described in the PR objectives.

The sequence should include a step.start for index 1 before line 599 to match the SDK 2.x event model.

🔧 Proposed fix to add missing step.start
         { event_type: 'step.stop', index: 0 },
+        {
+          event_type: 'step.start',
+          index: 1,
+          step: { type: 'model_output', id: 'output_1' },
+        },
         {
           event_type: 'step.delta',
           index: 1,
           delta: { type: 'text', text: 'It is sunny.' },
         },
+        { event_type: 'step.stop', index: 1 },
         {
           event_type: 'interaction.completed',
           interaction: { id: 'int_think', status: 'completed' },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
event_type: 'step.delta',
index: 1,
delta: { type: 'text', text: 'It is sunny.' },
},
{ event_type: 'step.stop', index: 0 },
{
event_type: 'step.start',
index: 1,
step: { type: 'model_output', id: 'output_1' },
},
{
event_type: 'step.delta',
index: 1,
delta: { type: 'text', text: 'It is sunny.' },
},
{ event_type: 'step.stop', index: 1 },
{
event_type: 'interaction.completed',
interaction: { id: 'int_think', status: 'completed' },
},
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ai-gemini/tests/text-interactions-adapter.test.ts` around lines 599
- 602, The test fixture is missing a step.start event for index 1 before the
step.delta event that emits text content. Add a step.start event with index 1
and appropriate start event properties before the existing step.delta event
block (which has event_type: 'step.delta' with index: 1) to establish the SDK
2.x event model sequence of step.start → step.delta → step.stop as followed by
other fixtures in this test file.

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