From 50ef9c8c2136b6597751378be4b0bdcde12bebf3 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 22 May 2026 20:31:15 +0000 Subject: [PATCH] fix(gemini realtime): preserve original setup config on follow-up session.update Gemini Live treats a second BidiGenerateContentSetup as a full session replacement, not a partial merge. The guardrail-driven turn_detection-only session.update was emitting a setup containing only model + realtimeInputConfig, which would silently drop tools, generationConfig, inputAudioTranscription, and systemInstruction from the original setup. Carry forward the cached original setup and only override realtimeInputConfig. Co-authored-by: Yassin Kortam --- litellm/llms/gemini/realtime/transformation.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/litellm/llms/gemini/realtime/transformation.py b/litellm/llms/gemini/realtime/transformation.py index bab3431c6a6..a1b0a965db9 100644 --- a/litellm/llms/gemini/realtime/transformation.py +++ b/litellm/llms/gemini/realtime/transformation.py @@ -346,7 +346,21 @@ class GeminiRealtimeConfig(BaseRealtimeConfig): cast(OpenAIRealtimeTurnDetection, turn_detection) ) if len(transformed_audio_activity_config) > 0: + # Gemini Live treats a subsequent BidiGenerateContentSetup as a + # full session replacement rather than a partial merge. Carry + # forward the original setup (tools, generationConfig, + # inputAudioTranscription, systemInstruction, ...) and only + # override realtimeInputConfig so the guardrail-driven VAD + # change doesn't silently drop tools or other config. + try: + original_setup = cast( + BidiGenerateContentSetup, + json.loads(session_configuration_request).get("setup", {}), + ) + except (json.JSONDecodeError, AttributeError): + original_setup = {} follow_up_setup: BidiGenerateContentSetup = { + **original_setup, "model": f"models/{model}", "realtimeInputConfig": BidiGenerateContentRealtimeInputConfig( automaticActivityDetection=transformed_audio_activity_config