These libraries are experimental. APIs may change without notice. Generated from source with koruc 0.1.7 on 8/19/2026.
SSE
@korulang/sse@0.0.1Server-Sent Events line framing with a phantom-obligation stream handle — data-path v0
sse/index.kz · 3 tors
@korulang/sse — Server-Sent Events line framing for streaming HTTP. · 32 more lines
@korulang/sse — Server-Sent Events line framing for streaming HTTP.
`text/event-stream` frames records as `field: value` lines; a TCP chunk
can end mid-line, so framing needs state that survives between chunks.
That state is a `*Stream<framing!>` — a phantom obligation, same shape as
curl's Response<open!> and yyjson's Doc<open!>: the build fails if you
forget `close`, and `feed` BORROWS the live obligation so bytes cannot be
fed to a stream that was already closed.
Born in koru-examples/kopium (increment A used module-global state, which
one process-wide stream survives and two do not); lifted here with the
handle the library shape demands.
v0 scope — the `data:` path only:
• `! data` fires once per complete `data: ` line, prefix stripped.
• The payload is a FEED-SCOPED borrow into the stream's buffer (the
same convention as curl's Chunk.data and sqlite3's row text): parse
it or copy it before the arm returns.
• Protocol punctuation is consumed silently ON PURPOSE — comment
keepalives (`: OPENROUTER PROCESSING`), blank separator lines, and
the `[DONE]` sentinel OpenAI-shaped providers send are the wire
format's own plumbing, not content. `event:`/`id:`/`retry:` fields
are also skipped in v0 (Anthropic's event names are repeated inside
every data payload's "type", so nothing is lost — a `! event` arm is
the natural depth pass when a consumer needs them).
USAGE (the kopium shape):
~koru/sse:new(): s
… per curl chunk: ~koru/sse:feed(s, bytes: ch.data)
! data d |> …parse d…
| ok |> _
… at end: ~koru/sse:close(s)
Phantom lifecycles
Derived from the phantom labels in the declarations below — state! issues an
obligation the compiler will chase, !state discharges it, a bare state holds it without moving it. Nothing here is hand-drawn.
Stream 1 state framing!// new — mint the `framing` obligation
~pub tor new { allocator: ?std.mem.Allocator } -> *Stream<framing!>// feed — BORROWS the stream, fires `! data` per complete data line
~pub tor feed { s: *Stream<framing>, bytes: string }
! data string
| ok// close — discharge the obligation. A non-empty tail (bytes after the last
// newline) is normal at end-of-stream and is dropped: SSE terminates records
// with a newline, so an unterminated tail was never a complete record.
~pub tor close { s: *Stream<!framing> }