Read a fetch response body as a stream of Server-Sent Events, invoking
onEvent with each event's data: payload — every data: line in the
event joined with \n per the SSE spec, trimmed. Does NOT parse the
payload itself (JSON or otherwise): that's entirely up to the caller,
since the payload shape is whatever the specific backend protocol defines.
This function only implements the generic SSE framing every such
backend shares:
CRLF / bare-CR → LF normalization, since servers vary in line-ending
choice and a single \n\n split is only authoritative once
normalized.
Blank-line event-boundary splitting, carrying a partial (not yet
terminated) tail event over to the next chunk instead of dropping it.
A final flush for a trailing event that was never terminated by a
blank line — some servers omit the trailing separator on the last
event before closing the connection.
Skipping SSE comment / keep-alive lines (e.g. : ping) and any event
that carries no data: field at all, per the SSE spec's "ignore
events that dispatch no data" rule.
Skipping the conventional data: [DONE] end-of-stream sentinel used
by many LLM/agent streaming APIs (not part of the SSE spec itself,
but common enough across backends to handle once here).
Cancellation is the caller's responsibility: abort the underlying
fetch (e.g. via the AbortSignal passed to it) and reader.read()
will reject, propagating out of this function same as any other stream
error.
Read a
fetchresponse body as a stream of Server-Sent Events, invokingonEventwith each event'sdata:payload — everydata:line in the event joined with\nper the SSE spec, trimmed. Does NOT parse the payload itself (JSON or otherwise): that's entirely up to the caller, since the payload shape is whatever the specific backend protocol defines. This function only implements the generic SSE framing every such backend shares:\n\nsplit is only authoritative once normalized.: ping) and any event that carries nodata:field at all, per the SSE spec's "ignore events that dispatch no data" rule.data: [DONE]end-of-stream sentinel used by many LLM/agent streaming APIs (not part of the SSE spec itself, but common enough across backends to handle once here).Cancellation is the caller's responsibility: abort the underlying
fetch(e.g. via theAbortSignalpassed to it) andreader.read()will reject, propagating out of this function same as any other stream error.