From b6935af475b8e0c97f11266f00c48ecec39d36a2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 26 Jan 2026 01:58:00 +0000 Subject: [PATCH 1/3] Initial plan From ded041cc091fdfbcada5efe50c7a88fba6e90082 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 26 Jan 2026 02:04:22 +0000 Subject: [PATCH 2/3] feat: Add proactive_audio, affective_dialog, and session_resumption options to /run_live endpoint Fixes google/adk-python#4263 The /run_live WebSocket endpoint now accepts three new query parameters: - proactive_audio (bool, default=False): Enables Gemini Live's proactive audio feature - affective_dialog (bool, default=False): Enables emotional awareness in the model - session_resumption (bool, default=False): Enables session resumption mechanism These options are passed to the RunConfig and used when calling runner.run_live(). Co-authored-by: bashimr <1313979+bashimr@users.noreply.github.com> --- src/google/adk/cli/adk_web_server.py | 18 +++++++++- tests/unittests/cli/test_fast_api.py | 50 +++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/google/adk/cli/adk_web_server.py b/src/google/adk/cli/adk_web_server.py index b97932d042..29f8031240 100644 --- a/src/google/adk/cli/adk_web_server.py +++ b/src/google/adk/cli/adk_web_server.py @@ -1636,6 +1636,9 @@ async def run_agent_live( modalities: List[Literal["TEXT", "AUDIO"]] = Query( default=["AUDIO"] ), # Only allows "TEXT" or "AUDIO" + proactive_audio: bool = Query(default=False), + affective_dialog: bool = Query(default=False), + session_resumption: bool = Query(default=False), ) -> None: await websocket.accept() @@ -1652,7 +1655,20 @@ async def run_agent_live( async def forward_events(): runner = await self.get_runner_async(app_name) - run_config = RunConfig(response_modalities=modalities) + run_config = RunConfig( + response_modalities=modalities, + proactivity=( + types.ProactivityConfig(proactive_audio=proactive_audio) + if proactive_audio + else None + ), + enable_affective_dialog=( + affective_dialog if affective_dialog else None + ), + session_resumption=( + types.SessionResumptionConfig() if session_resumption else None + ), + ) async with Aclosing( runner.run_live( session=session, diff --git a/tests/unittests/cli/test_fast_api.py b/tests/unittests/cli/test_fast_api.py index 0c69605349..8f186dbdd0 100755 --- a/tests/unittests/cli/test_fast_api.py +++ b/tests/unittests/cli/test_fast_api.py @@ -113,7 +113,12 @@ def _event_state_delta(state_delta: dict[str, Any]): # Define mocked async generator functions for the Runner -async def dummy_run_live(self, session, live_request_queue): +async def dummy_run_live( + self, + session, + live_request_queue, + run_config: Optional[RunConfig] = None, +): yield _event_1() await asyncio.sleep(0) @@ -1411,5 +1416,48 @@ def test_builder_save_rejects_traversal(builder_test_client, tmp_path): assert not (tmp_path / "app" / "tmp" / "escape.yaml").exists() +def test_run_live_accepts_new_config_options(test_app, test_session_info): + """Test that /run_live endpoint accepts proactive_audio, affective_dialog, and session_resumption query parameters.""" + # First, create a session to use + session_url = ( + f"/apps/{test_session_info['app_name']}/users/" + f"{test_session_info['user_id']}/sessions/{test_session_info['session_id']}" + ) + test_app.post(session_url, json={"state": {}}) + + # The actual websocket test would require more elaborate setup. + # Here we verify that the endpoint accepts the new query parameters + # by checking FastAPI's route signature. + from fastapi import Query as FastApiQuery + + # Find the /run_live route + run_live_route = None + for route in test_app.app.routes: + if hasattr(route, "path") and route.path == "/run_live": + run_live_route = route + break + + assert run_live_route is not None, "/run_live route not found" + + # Check that the endpoint function signature includes the new parameters + import inspect + + endpoint_fn = run_live_route.endpoint + sig = inspect.signature(endpoint_fn) + params = sig.parameters + + # Verify the new parameters exist + assert "proactive_audio" in params, "proactive_audio parameter not found" + assert "affective_dialog" in params, "affective_dialog parameter not found" + assert ( + "session_resumption" in params + ), "session_resumption parameter not found" + + # Verify they have default values of False + assert params["proactive_audio"].default.default is False + assert params["affective_dialog"].default.default is False + assert params["session_resumption"].default.default is False + + if __name__ == "__main__": pytest.main(["-xvs", __file__]) From 364191c19c18417a9e04b0b6ae5621acf0584c68 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 26 Jan 2026 02:06:43 +0000 Subject: [PATCH 3/3] refactor: Simplify enable_affective_dialog assignment Use `affective_dialog or None` for cleaner code instead of redundant conditional. Co-authored-by: bashimr <1313979+bashimr@users.noreply.github.com> --- src/google/adk/cli/adk_web_server.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/google/adk/cli/adk_web_server.py b/src/google/adk/cli/adk_web_server.py index 29f8031240..0dc63140c8 100644 --- a/src/google/adk/cli/adk_web_server.py +++ b/src/google/adk/cli/adk_web_server.py @@ -1662,9 +1662,7 @@ async def forward_events(): if proactive_audio else None ), - enable_affective_dialog=( - affective_dialog if affective_dialog else None - ), + enable_affective_dialog=affective_dialog or None, session_resumption=( types.SessionResumptionConfig() if session_resumption else None ),