Repository navigation
fix(gemini-live): gemini-3.1-flash-live — setup dies with affectiveDialog, session wedges on BLOCKING tool calls - #210
Conversation
…ually work Two field-debugged fixes for the *-flash-live-preview family, ported onto the 0.7.1 adapter (both proven on the Pillar demo line): 1. Drop enableAffectiveDialog/proactivity on flash-live models (with a warning): they are dated-2.5-native-audio-only setup knobs — including them makes the server never send setupComplete, so connect dies with 'session ready timeout'. 2. Opt flash-live into the Live API's async function-calling mode: behavior NON_BLOCKING on functionDeclarations + scheduling INTERRUPT on the FunctionResponse. In the default BLOCKING mode 3.1 halts audio generation at the toolCall and never resumes speech after receiving the response — no error, no socket close, just silence until the caller hangs up (reproduced 2/2 on the first call after long idle, where the model emits the tool call mid-conversation). Also log the tool round-trip at info: it was invisible in prod at default log level, which made the stall undiagnosable. Gated on the model family — 2.5 native-audio and every other model are byte-identical on the wire. TS suite: 2493 passing. Python parity pending (gemini_live.py has the same BLOCKING shape).
…s + parity The gemini-3.1-flash-live async-mode tool-call fix shipped in TypeScript only. This closes the SDK-parity gap and adds the missing test coverage: - Python: opt flash-live into NON_BLOCKING declarations + INTERRUPT scheduling on the tool response (default BLOCKING wedges 3.1 into a silent stall after the toolCall), log the tool round-trip at info, and add GeminiLiveModel.LIVE_3_1_FLASH_PREVIEW to match the TS constant. - TypeScript: fold the duplicated flash-live predicate into a single isFlashLive getter, and warn symmetrically when proactiveAudio is dropped on flash-live (previously silent, unlike affectiveDialog). - Tests: new authentic mocked coverage in both SDKs for the async-mode declaration + tool-response shaping — the post-toolResponse resume path that had no coverage. Python gemini-live had no test file at all before this. The affectiveDialog/proactivity setup fix is TS-only by nature: the Python adapter never exposed those knobs, so it never sent them.
|
Follow-up commit Python parity — Test coverage — the post-
TS cleanup — the duplicated All checks green: Python 3.11/3.12/3.13, TS 20/22, security, secret scan, pre-commit, claude-review. Local: Python 6/6, TS 15/15 (4 new + 11 existing, no regressions), |
What
Two field-debugged fixes that make
gemini-3.1-flash-live-previewactually usable, found while moving the Pillar demo line to 3.1:Setup:
enableAffectiveDialog/proactivityare dated-2.5-native-audio-only knobs. On the flash-live family the server never sendssetupCompleteif the setup includes them →Gemini Live connect: session ready timeout. Now dropped with a warning on flash-live models. (Empirically isolated with a config-ablation matrix: minimal/voice/it-IT/VAD/instructions all connect in ~300ms; adding affectiveDialog → timeout, 100% reproducible. 2.5 with the same config connects fine.)Tool calls: in the default BLOCKING function-call mode, 3.1 halts audio generation when it emits the
toolCalland never resumes speech after receiving ourtoolResponse— no error event, no socket close, just silence until the caller gives up. Hit 2/2 on real calls (first call after long idle, where the model emits the tool call mid-conversation; warm sessions batch it at end-of-call, which is why local repros never triggered it). Fix: opt flash-live into the documented async mode —behavior: 'NON_BLOCKING'on the declarations +scheduling: 'INTERRUPT'on the response. Also logs the tool round-trip at info (it was invisible at default log level, which made this stall undiagnosable in prod).Both changes are gated on
model.includes('flash-live')— 2.5 native-audio and every other model are byte-identical on the wire.Testing
qualifica_leadround-trip observed completing with the conversation continuing (toolCall received→toolResponse sent→ native lead write → clean goodbye).Notes
gemini_live.pysends the same BLOCKING-shapeFunctionResponse; the same two changes apply.function_callevent emission — the post-toolResponse resume path (where 3.1 wedges) has no coverage yet.🤖 Generated with Claude Code
https://claude.ai/code/session_019DYHvQ7uFxXVLoEEmduKso