Coverage for src/lilbee/server/chat_completions_api/streaming.py: 100%
13 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-08-14 11:46 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-08-14 11:46 +0000
1"""SSE encoder: ``data: {json}\\n\\n`` frames plus ``[DONE]`` terminator."""
3from __future__ import annotations
5from collections.abc import AsyncIterator
7from lilbee.server.chat_completions_api.models import CompletionsStreamChunk
8from lilbee.server.handlers.sse import frames_with_keepalive
10# Cadence for SSE comment frames emitted when no chat token has arrived. Keeps
11# clients (notably opencode) from tripping their idle-stream timeout during
12# slow first-token latency on local models.
13_KEEPALIVE_INTERVAL_S = 5.0
14_KEEPALIVE_FRAME = b": keepalive\n\n"
17async def encode_completions_sse(
18 chunks: AsyncIterator[CompletionsStreamChunk],
19) -> AsyncIterator[bytes]:
20 """Frame each chunk as an SSE ``data:`` event and append the ``[DONE]`` sentinel."""
22 async def _frames() -> AsyncIterator[bytes]:
23 async for chunk in chunks:
24 yield f"data: {chunk.model_dump_json(exclude_none=True)}\n\n".encode()
26 async for frame in frames_with_keepalive(
27 _frames(), keepalive=_KEEPALIVE_FRAME, interval_s=_KEEPALIVE_INTERVAL_S
28 ):
29 yield frame
30 yield b"data: [DONE]\n\n"