sse.bend checks
raw source on the hub · import bend-kit-llm@0.1.0.0/sse.bend as Sse
Server-Sent Events parser (WHATWG HTML §9.2.6), fed in pieces. Source: https://github.com/paymog/bend-kit/tree/main/llm
2 imports
import Base import 0x49814d83de8f70993a43e1002be29ecd/bytes.bend as Bytes
Types
type Message source · line 8 · raw
Type
name: the event type, "message" when the stream sets none. data: the data lines joined by LF. id: the last event ID the stream set. name and id hold one Char per octet.
Message@name:String -> @data:0x49814d83de8f70993a43e1002be29ecd/bytes.Bytes -> @id:String -> Message
type St source · line 12 · raw
Type
The event so far: its type, its data lines each ended by LF, the last event ID, and the last retry in ms.
St@name:String -> @data:0x49814d83de8f70993a43e1002be29ecd/bytes.Bytes -> @id:String -> @retry:Maybe<&2, U32> -> St
type Reader source · line 17 · raw
Type
buf from pos: bytes not yet read as lines. No CR or LF is between pos and seen. cr: the last line ended with a CR at the end of buf, so an LF first belongs to it.
Reader@buf:0x49814d83de8f70993a43e1002be29ecd/bytes.Bytes -> @pos:U32 -> @seen:U32 -> @cr:Bool -> @st:St -> Reader
type Next source · line 20 · raw
Type
Got@e:Message -> Next
WantNext
type Line source · line 183 · raw
Type
A line was read and more may follow; the bytes ran out first; or a line ended an event.
LMore@a:Array<U32> -> @pos:U32 -> @cr:Bool -> @st:St -> Line
LWant@a:Array<U32> -> @pos:U32 -> @cr:Bool -> @st:St -> Line
LGot@a:Array<U32> -> @pos:U32 -> @cr:Bool -> @st:St -> @e:Message -> Line
Definitions
def reader source · line 25 · raw
Reader
ponytail: a leading U+FEFF is not dropped; the LLM APIs never send one.
def feed.at source · line 28 · raw
@zero:Bool -> @buf:0x49814d83de8f70993a43e1002be29ecd/bytes.Bytes -> @+pos:U32 -> @+seen:U32 -> @cr:Bool -> @st:St -> @chunk:0x49814d83de8f70993a43e1002be29ecd/bytes.Bytes -> Reader
def feed source · line 36 · raw
@r:Reader -> @chunk:0x49814d83de8f70993a43e1002be29ecd/bytes.Bytes -> Reader
Drops the lines already read, then adds chunk.
def retry source · line 41 · raw
@r:Reader -> Pair(Reader, Maybe<&2, U32>)
The last retry field, in ms.
def eol source · line 46 · raw
@f:Nat -> @r:Pair(Array<U32>, U32) -> @+i:U32 -> Pair(Array<U32>, U32)
The first CR or LF at or after i, or the end. f counts the bytes from i to the end; r holds byte i.
def colon source · line 62 · raw
@f:Nat -> @r:Pair(Array<U32>, U32) -> @+i:U32 -> Pair(Array<U32>, U32)
The first colon at or after i, or the line's end. f counts the bytes from i to the line's end; r holds byte i.
def digits source · line 76 · raw
@s:String -> @+acc:U32 -> @+n:U32 -> @bad:Bool -> Maybe<&2, U32>
Base-ten digits, at most 9 of them; None for any other text.
def has_nul source · line 83 · raw
@s:String -> Bool
def lf source · line 90 · raw
0x49814d83de8f70993a43e1002be29ecd/bytes.Bytes
def kind.is source · line 93 · raw
@+k:U32 -> @r:Pair(Array<U32>, Bool) -> Pair(Array<U32>, U32)
def kind.five source · line 97 · raw
@+s:U32 -> @r:Pair(Array<U32>, Bool) -> Pair(Array<U32>, U32)
def kind source · line 106 · raw
@+n:U32 -> @a:Array<U32> -> @+s:U32 -> Pair(Array<U32>, U32)
The kind of the field whose n-byte name starts at s: 1 data, 2 event, 3 id, 4 retry, 0 any other.
def set.retry source · line 117 · raw
@m:Maybe<&2, U32> -> @old:Maybe<&2, U32> -> Maybe<&2, U32>
def set source · line 125 · raw
@+k:U32 -> @v:0x49814d83de8f70993a43e1002be29ecd/bytes.Bytes -> @st:St -> St
The event after a field of kind k with value v. An id with NUL and a retry that is not digits change nothing.
def field.put source · line 143 · raw
@+k:U32 -> @st:St -> @r:Pair(0x49814d83de8f70993a43e1002be29ecd/bytes.Bytes, 0x49814d83de8f70993a43e1002be29ecd/bytes.Bytes) -> Pair(Array<U32>, St)
def field.set source · line 147 · raw
@+len:U32 -> @+v:U32 -> @+e:U32 -> @st:St -> @r:Pair(Array<U32>, U32) -> Pair(Array<U32>, St)
def field.at source · line 152 · raw
@+s:U32 -> @+c:U32 -> @+e:U32 -> @+len:U32 -> @st:St -> @r:Pair(Array<U32>, U32) -> Pair(Array<U32>, St)
r holds the byte after the colon at c. The value starts after the colon and one space, if there is one.
def field.colon source · line 157 · raw
@+s:U32 -> @+e:U32 -> @+len:U32 -> @st:St -> @r:Pair(Array<U32>, U32) -> Pair(Array<U32>, St)
def field source · line 162 · raw
@a:Array<U32> -> @+len:U32 -> @+s:U32 -> @+e:U32 -> @st:St -> Pair(Array<U32>, St)
The line from s to e as a field: the name up to the first colon, the value after it. A comment's name is empty.
def trim source · line 166 · raw
@b:0x49814d83de8f70993a43e1002be29ecd/bytes.Bytes -> 0x49814d83de8f70993a43e1002be29ecd/bytes.Bytes
Drops the last LF. Bytes past len stay 0.
def dispatch.of source · line 170 · raw
@empty:Bool -> @+name:String -> @data:0x49814d83de8f70993a43e1002be29ecd/bytes.Bytes -> @+id:String -> @retry:Maybe<&2, U32> -> Pair(St, Maybe<&1, Message>)
def dispatch source · line 178 · raw
@st:St -> Pair(St, Maybe<&1, Message>)
A blank line: the event, when it has data. Either way the event type starts over.
def line.got source · line 188 · raw
@a:Array<U32> -> @+next:U32 -> @cr:Bool -> @r:Pair(St, Maybe<&1, Message>) -> Line
def line.set source · line 196 · raw
@+next:U32 -> @cr:Bool -> @r:Pair(Array<U32>, St) -> Line
def line.body source · line 201 · raw
@blank:Bool -> @a:Array<U32> -> @+len:U32 -> @+s:U32 -> @+e:U32 -> @+next:U32 -> @cr:Bool -> @st:St -> Line
The line from s to e; the next line starts at next.
def line.crlf source · line 208 · raw
@+len:U32 -> @+s:U32 -> @+e:U32 -> @st:St -> @r:Pair(Array<U32>, U32) -> Line
def line.cr source · line 213 · raw
@more:Bool -> @a:Array<U32> -> @+len:U32 -> @+s:U32 -> @+e:U32 -> @st:St -> Line
A CR at e. With nothing after it yet, an LF may still come.
def line.term source · line 220 · raw
@+len:U32 -> @+s:U32 -> @+e:U32 -> @st:St -> @r:Pair(Array<U32>, U32) -> Line
def line.end source · line 228 · raw
@want:Bool -> @a:Array<U32> -> @+len:U32 -> @+s:U32 -> @+e:U32 -> @cr:Bool -> @st:St -> Line
def line.eol source · line 235 · raw
@+len:U32 -> @+s:U32 -> @cr:Bool -> @st:St -> @r:Pair(Array<U32>, U32) -> Line
def line source · line 240 · raw
@a:Array<U32> -> @+len:U32 -> @+s:U32 -> @+seen:U32 -> @cr:Bool -> @st:St -> Line
The line that starts at s. No CR or LF lies between s and seen.
def stop source · line 244 · raw
@l:Line -> @+len:U32 -> Pair(Reader, Next)
def loop source · line 254 · raw
@f:Nat -> @l:Line -> @+len:U32 -> Pair(Reader, Next)
f: at least the lines left, plus one.
def skip.byte source · line 267 · raw
@+pos:U32 -> @r:Pair(Array<U32>, U32) -> Pair(Array<U32>, Pair(U32, Bool))
def skip.at source · line 271 · raw
@some:Bool -> @a:Array<U32> -> @+pos:U32 -> Pair(Array<U32>, Pair(U32, Bool))
def skip source · line 279 · raw
@cr:Bool -> @a:Array<U32> -> @+len:U32 -> @+pos:U32 -> Pair(Array<U32>, Pair(U32, Bool))
After a CR that ended the last piece, an LF first belongs to that CR.
def next.at source · line 286 · raw
@+len:U32 -> @+seen:U32 -> @st:St -> @r:Pair(Array<U32>, Pair(U32, Bool)) -> Pair(Reader, Next)
def next source · line 291 · raw
@r:Reader -> Pair(Reader, Next)
The next whole event, or Want when the bytes run out first. A blank line with no data before it gives no event.