fix(web): preserve multi-byte UTF-8 split across SSE chunks in chat stream

createMessageStream decoded each network chunk with a fresh TextDecoder and no
{ stream: true }, so a multi-byte UTF-8 rune (CJK, emoji) split across a chunk
boundary was corrupted into U+FFFD before the frame buffer ever saw it. Hoist a
single persistent decoder and decode with { stream: true } so pending bytes
carry across chunks.
This commit is contained in:
Paco Cartones 2026-08-29 00:17:59 +00:00
parent 374d2dc967
commit c10bd5a380

View file

@ -145,6 +145,9 @@ export class ChatService {
return response;
};
// Persistent decoder: a multi-byte UTF-8 rune split across network chunks is
// otherwise decoded as two halves and corrupted into U+FFFD before it is buffered.
const decoder = new TextDecoder();
return new ReadableStream({
async start(controller) {
try {
@ -152,7 +155,7 @@ export class ChatService {
const { done, value } = await reader.read();
if (done) break;
buffer += new TextDecoder().decode(value);
buffer += decoder.decode(value, { stream: true });
const segments = buffer.split("\n\n");
// Last segment may be incomplete; keep it as buffer
buffer = segments.pop() || "";