Frontier on Cloud

Frontier on Cloud › Tests › livekit-agents-js-2615-check

LiveKit agents-js#2615 on gemini-3.8-live: reproduction and patch check

Model
gemini-3.8-live (base model)
Endpoint
Gemini API (Google AI Studio key). No LiveKit server.
Framework
@livekit/agents 1.9.1, @livekit/agents-plugin-google 1.9.1, @livekit/rtc-node 1.1.0, @google/genai 2.27.0 (plugin dependency), zod 3.25.76; Node v26.9.0, macOS
Run
2026-10-02
Runs
10: 3 + 3 with the "call first" prompt, 2 + 2 with "speak first", unpatched then patched
Repository
frontier-on-cloud/livekit-agents-js-2615-check (MIT) at 1559574
Issue checked
livekit/agents-js#2615

Question

Issue #2615 reports that in the agents-js Google plugin, with toolBehavior unset, a content-free generationComplete after a toolCall interrupts the tool's own turn, and the tool result and FunctionToolsExecuted are lost. Does that happen on the base model gemini-3.8-live, and does the patch to isNewGeneration() proposed in the issue fix it?

Setup

Results

PromptPluginRunsPhantom generation after toolCallOwning speech interruptedFunctionToolsExecutedFunction response sentLine spoken before the call
call first1.9.133/3, +3 to +4 ms3/3 (not aborted)3/33/3none
call firstpatched30/30/33/33/3none
speak first1.9.122/2, +2 to +7 ms2/2 (aborted +2, +8 ms)0/20/2cut after 442 and 643 ms
speak firstpatched20/20/22/22/2played in full

On the base model the drop is a race: any audio before the call loses it. The result is dropped in one place, in agent_activity.ts (_realtimeGenerationTaskImpl): the if (speechHandle.interrupted) check right after waitIfNotInterrupted.

Caveats

Source and reproduce

Everything is in one commit, 1559574 (2026-10-02): the harness app/run.mjs, the runs in app/runs/, the analysis app/analyze.py, and the patch as patches/dist.diff and patches/src.diff. The unmodified plugin files kept under patches/orig/ are LiveKit's, Apache-2.0, not covered by the repository's MIT license.

This check takes more than three commands: it runs the published plugin, patches it, then runs it again.

cd app
npm ci
cp ../.env.example .env            # put GEMINI_API_KEY=... in it
LK_GOOGLE_DEBUG=1 node --env-file=.env run.mjs baseline-1 > runs/baseline-1.jsonl
VARIANT=speak_first LK_GOOGLE_DEBUG=1 node --env-file=.env run.mjs baseline-speakfirst-1 > runs/baseline-speakfirst-1.jsonl
python3 ../patches/apply_dist_patch.py .      # exact-text edit of dist/realtime/realtime_api.js and .cjs
LK_GOOGLE_DEBUG=1 node --env-file=.env run.mjs patched-1 > runs/patched-1.jsonl
VARIANT=speak_first LK_GOOGLE_DEBUG=1 node --env-file=.env run.mjs patched-speakfirst-1 > runs/patched-speakfirst-1.jsonl
python3 analyze.py runs/*.jsonl