What happened?
parse_sse_stream in src/a2a/client/transports/http_helpers.py only yields an event when it sees a blank line. If the peer closes the connection after data: {...} with no trailing blank line, leftover payload_chunks are thrown away.
WHATWG SSE says a pending event must be dispatched when the connection closes. JsonRpcTransport and RestTransport both use this parser, so a completed Task/Message can vanish and the client sits there as if the stream is still open.
Repro
- Feed
parse_sse_stream a response whose last lines are data: {"task":{...}} with no following empty line.
- Exhaust the generator.
Observed: zero events.
Expected: one ("message", "{...}") event.
Existing tests always send a trailing \n, so this path is untested.
Relevant log output
n/a. Unit-reproducible in tests/client/transports/test_http_helpers.py.
Code of Conduct
What happened?
parse_sse_streaminsrc/a2a/client/transports/http_helpers.pyonly yields an event when it sees a blank line. If the peer closes the connection afterdata: {...}with no trailing blank line, leftoverpayload_chunksare thrown away.WHATWG SSE says a pending event must be dispatched when the connection closes.
JsonRpcTransportandRestTransportboth use this parser, so a completed Task/Message can vanish and the client sits there as if the stream is still open.Repro
parse_sse_streama response whose last lines aredata: {"task":{...}}with no following empty line.Observed: zero events.
Expected: one
("message", "{...}")event.Existing tests always send a trailing
\n, so this path is untested.Relevant log output
n/a. Unit-reproducible in
tests/client/transports/test_http_helpers.py.Code of Conduct