import { MAX_SSE_FIELD_BYTES } from "./config"; /** * Truncates a string to at most n bytes of UTF-8 without splitting multi-byte * runes. Keeps one SSE `data:` field bounded. */ export function truncateUtf8(s: string, n: number = MAX_SSE_FIELD_BYTES): string { const buf = new TextEncoder().encode(s); if (buf.byteLength <= n) return s; let end = n; while (end > 0 && (buf[end]! & 0xc0) === 0x80) end--; return new TextDecoder().decode(buf.subarray(0, end)); } /** * A single SSE block: `event` + JSON `data`, blank-line terminated. The `id` * line is written only for logged events — an out-of-band frame carries no seq, * and an empty `id:` would clear the client's resume cursor. */ export function sseBlock(e: { id?: string; event: string; data: unknown }): string { const id = e.id ? `id: ${e.id}\n` : ""; return `event: ${e.event}\n${id}data: ${JSON.stringify(e.data)}\n\n`; }