import { expect, test } from 'vitest'; import { readCreationAgentSessionFromSse } from './creationAgentSse'; function createChunkedStreamResponse(chunks: Uint8Array[]) { const stream = new ReadableStream({ start(controller) { for (const chunk of chunks) { controller.enqueue(chunk); } controller.close(); }, }); return new Response(stream, { headers: { 'Content-Type': 'text/event-stream; charset=utf-8', }, }); } test('readCreationAgentSessionFromSse flushes decoder tail and handles CRLF boundaries', async () => { const encoder = new TextEncoder(); const prefix = encoder.encode('event: reply_delta\r\ndata: {"text":"'); const replyTextBytes = encoder.encode('你好,潮雾列岛'); const suffix = encoder.encode( '"}\r\n\r\nevent: session\r\ndata: {"session":{"sessionId":"session-1","title":"世界共创"}}\r\n\r\n', ); const splitIndex = replyTextBytes.length - 1; const chunks = [ new Uint8Array([...prefix, ...replyTextBytes.slice(0, splitIndex)]), new Uint8Array([...replyTextBytes.slice(splitIndex), ...suffix]), ]; const updates: string[] = []; const session = await readCreationAgentSessionFromSse<{ sessionId: string; title: string; }>(createChunkedStreamResponse(chunks), { fallbackMessage: '发送失败', incompleteMessage: '结果不完整', onUpdate: (text) => { updates.push(text); }, }); expect(updates).toEqual(['你好,潮雾列岛']); expect(session).toEqual({ sessionId: 'session-1', title: '世界共创', }); });