Streaming (SSE)
ngx-prompt-kit original — not part of ibelick/prompt-kit
Transport helpers for consuming Server-Sent-Event chat streams. consumeSseFrames() is a pure frame splitter; readSseHttpEvents() adapts an Angular HttpClient event stream into per-frame callbacks. The caller owns interpreting each frame.
Examples
Frame parser playground
consumeSseFrames() splits a raw SSE body into the data payload of each complete frame, returning any partial tail. Paste raw frames below and parse them.
import { consumeSseFrames } from 'ngx-prompt-kit/streaming';
const frames: string[] = [];
const tail = consumeSseFrames(rawBuffer, (data) => frames.push(data));
// `tail` is any incomplete trailing frame — prepend it to the next chunk.Installation
Add the SSE streaming helpers to your project.
ng generate ngx-prompt-kit:streamingHTTP usage
readSseHttpEvents() handles the cumulative partialText / frame buffering; your callback parses each frame and decides what is a result or an error.
import { readSseHttpEvents } from 'ngx-prompt-kit/streaming';
let result: SendResult | null = null;
await readSseHttpEvents(
http.post('/api/chat', body, { observe: 'events', reportProgress: true, responseType: 'text' }),
(data) => {
const payload = JSON.parse(data);
if (payload.type === 'chunk') appendToken(payload.text);
else if (payload.type === 'done') result = payload.result;
},
);Stopping a stream
Pass an AbortSignal as the third argument. Aborting it unsubscribes, which cancels the HTTP request, and rejects the promise with an AbortError DOMException. isAbortError() tells that apart from a real failure, so a stop button doesn't show an error.
import { isAbortError, readSseHttpEvents } from 'ngx-prompt-kit/streaming';
private controller: AbortController | null = null;
async send(body: ChatRequest) {
this.controller = new AbortController();
try {
await readSseHttpEvents(events$, (data) => handle(data), this.controller.signal);
} catch (error) {
if (isAbortError(error)) return; // the user pressed stop
throw error;
} finally {
this.controller = null;
}
}
stop() {
this.controller?.abort();
}