diff --git a/src/google/adk/cli/adk_web_server.py b/src/google/adk/cli/adk_web_server.py index e4c837f899..bad1ebf95d 100644 --- a/src/google/adk/cli/adk_web_server.py +++ b/src/google/adk/cli/adk_web_server.py @@ -1896,9 +1896,23 @@ async def event_generator(): "Generated event in agent run streaming: %s", sse_event ) yield f"data: {sse_event}\n\n" - except Exception as e: - logger.exception("Error in event_generator: %s", e) - yield f"data: {json.dumps({'error': str(e)})}\n\n" + + # Send termination signal after all events have been streamed + yield "data: [DONE]\n\n" + except Exception as e: + logger.exception("Error in event_generator: %s", e) + # Yield a proper Event object for the error + error_event = Event( + author="system", + content=types.Content( + role="model", parts=[types.Part(text=f"Error: {e}")] + ), + ) + yield ( + "data:" + f" {error_event.model_dump_json(by_alias=True, exclude_none=True)}\n\n" + ) + yield "data: [DONE]\n\n" # Returns a streaming response with the proper media type for SSE return StreamingResponse( diff --git a/tests/unittests/cli/test_fast_api.py b/tests/unittests/cli/test_fast_api.py index 95affeeb3e..b0a76526dc 100755 --- a/tests/unittests/cli/test_fast_api.py +++ b/tests/unittests/cli/test_fast_api.py @@ -1102,7 +1102,7 @@ async def run_async_with_artifact_delta( sse_events = [ json.loads(line.removeprefix("data: ")) for line in response.text.splitlines() - if line.startswith("data: ") + if line.startswith("data: ") and line != "data: [DONE]" ] assert len(sse_events) == 2