tiny-army / web /sseText.js
polats's picture
Add Coding Model setting + Skill Forge sandbox
1f1908e
// Shared SSE reader for the server text-generation endpoint (/text/generate/stream).
// Parses the `event:`/`data:` wire format and dispatches each event to onEvent.
// Used by both engineServer.js (the model-bar "Server / ZeroGPU" engine) and
// codingModel.js (the Skill Forge coding-model picker) so the parser lives once.
export async function streamSse(url, body, { onEvent, signal } = {}) {
const res = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
signal,
})
if (!res.ok || !res.body) throw new Error(`HTTP ${res.status}`)
const reader = res.body.getReader()
const decoder = new TextDecoder()
let buf = ''
while (true) {
const { value, done } = await reader.read()
if (done) break
buf += decoder.decode(value, { stream: true })
const events = buf.split(/\n\n/)
buf = events.pop() ?? ''
for (const evChunk of events) {
const lines = evChunk.split('\n')
let evt = 'message'
const dataLines = []
for (const line of lines) {
if (line.startsWith('event:')) evt = line.slice(6).trim()
else if (line.startsWith('data:')) dataLines.push(line.slice(5).trimStart())
}
const data = dataLines.join('\n')
if (!data) continue
let parsed = null
try { parsed = JSON.parse(data) } catch { /* ignore */ }
if (evt === 'error') throw new Error(parsed?.error || data)
onEvent?.(evt, parsed, data)
}
}
}