diff --git a/src/pages/api/generate.ts b/src/pages/api/generate.ts index e5cdce80..390a8025 100644 --- a/src/pages/api/generate.ts +++ b/src/pages/api/generate.ts @@ -42,11 +42,34 @@ export const post: APIRoute = async(context) => { const responseStream = new ReadableStream({ async start(controller) { + const decoder = new TextDecoder('utf-8', { stream: true }) // Use the streaming option + let buffer = new Uint8Array() + for await (const chunk of stream) { - const text = await chunk.text() - const queue = new TextEncoder().encode(text) - controller.enqueue(queue) + const chunkAsText = await chunk.text() + const chunkAsUint8Array = new TextEncoder().encode(chunkAsText) + // Combine the buffered bytes with the new bytes + const combinedChunk = new Uint8Array(buffer.length + chunkAsUint8Array.length) + combinedChunk.set(buffer) + combinedChunk.set(chunkAsUint8Array, buffer.length) + + // Find the last complete UTF-8 character + let end = combinedChunk.length + while (end > 0 && (combinedChunk[end - 1] & 0xC0) === 0x80) + end-- + + // Decode the complete characters, and buffer the rest + const text = decoder.decode(combinedChunk.subarray(0, end), { stream: true }) + buffer = combinedChunk.subarray(end) + controller.enqueue(new TextEncoder().encode(text)) } + + // Decode any remaining bytes + if (buffer.length > 0) { + const text = decoder.decode(buffer, { stream: false }) // Flush the decoder + controller.enqueue(new TextEncoder().encode(text)) + } + controller.close() }, })