fix(google): send a bare turnComplete when a reply request carries no turns - #7323
Open
rosetta-livekit-bot[bot] wants to merge 1 commit into
Open
rosetta-livekit-bot[bot] wants to merge 1 commit into
rosetta-livekit-bot[bot] wants to merge 1 commit into
Conversation
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.
What
Port livekit/agents-js#2506 so Gemini Live reply requests with no turns omit the
turnsargument and send onlyturn_complete=True. The Google SDK rejects an empty turns array, which previously killed the send task before models such asgemini-3.8-livecould reply. Non-empty turns and explicitturn_complete=Falsecontinue to pass through unchanged.Source: livekit/agents-js#2506
Source diff coverage
.changeset/gemini-live-empty-turns.md: not applicable. The target does not use changesets, and its contribution policy leaves package manifest and changelog updates to maintainers.plugins/google/src/realtime/realtime_api.ts: adapted tolivekit-plugins/livekit-plugins-google/livekit/plugins/google/realtime/realtime_api.py. The TypeScript parameter normalizer is implemented with Python SDK argument names, omittingturnswhen absent or empty and defaultingturn_completetoTrue.plugins/google/src/realtime/realtime_api.test.ts: adapted totests/test_plugin_google_realtime.py. Both source helper tests are ported with PythonContentobjects and snake_case SDK arguments; no additional tests were added.Verification
uv run pytest tests/test_plugin_google_realtime.py --unit(28 passed)uv run pytest --plugin google(76 passed; one unrelated existing Gemini TTS leaked-task teardown error)make unit-tests/uv run pytest --unit(3,007 passed before a pre-existing pytest concurrency harness failure:RuntimeError: Event loop is closedintests/concurrency.py; reproduced in isolation)make checkuv build --package livekit-plugins-googleRuntime
cue-clivalidation could not be performed because this environment has noGOOGLE_API_KEYor Google application credentials. LiveKit transport credentials andcue-cliare available, but a Gemini Live session cannot be created without provider credentials. The SDK boundary behavior is covered by the two tests ported from the source PR.Ported from livekit/agents-js#2506
Original PR description
What
generateReply()on models that take no placeholder user turn (gemini-3.8-live,gemini-3.8-live-extended-thinking,gemini-3.1-flash-live-preview, since #2503) queues acontentevent withturns: [].@google/genai'sSession.sendClientContentrejects an emptyturnsarray (tContentsthrows "contents are required", surfaced asFailed to parse client content "turns"), which kills the send task and restarts the session, so the reply is never produced.This sends a bare
{ turnComplete: true }when there are no turns, which is the Live API's own way of requesting a reply, and passes non-empty turns through unchanged.How verified
gemini-3.8-livewith the agents-js 1.9.0 release: everygenerateReply()loggedError in send task: Error: Failed to parse client content "turns", type: 'object'followed byConnecting to Gemini Realtime API...; with this change the same agent opens the conversation and answersgenerateReply({ userInput })turns (opening, typed text, image viaupdateChatCtx, injection during a pending tool call).pnpm vitest run plugins/google/src/realtime/realtime_api.test.ts(12 passed, two new cases for the helper).pnpm exec prettier --checkon the two files; eslint reports only the three pre-existingno-explicit-anywarnings.Includes a patch changeset for
@livekit/agents-plugin-google.