feat(FN-3817): fix chat delta spacing in legacy streaming API
Fixes chat streaming delta spacing to preserve proper whitespace, adding regression tests for legacy chat stream handlers and the createChatStreamHandlers factory. A changeset was created for the `@runfusion/fusion` package. Fusion-Task-Id: FN-3817
This commit is contained in:
@@ -139,6 +139,65 @@ describe("streamChatResponse SSE parser", () => {
|
||||
expect(onError).toHaveBeenCalledWith("Timed out waiting for first response event");
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it.each([
|
||||
{
|
||||
name: "leading-space second delta",
|
||||
chunks: [
|
||||
"event: text\n",
|
||||
"data: \"Hello.\"\n\n",
|
||||
"event: text\n",
|
||||
"data: \" World.\"\n\n",
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "space-trailing first delta",
|
||||
chunks: [
|
||||
"event: text\n",
|
||||
"data: \"Hello. \"\n\n",
|
||||
"event: text\n",
|
||||
"data: \"World.\"\n\n",
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "empty delta between spaced chunks",
|
||||
chunks: [
|
||||
"event: text\n",
|
||||
"data: \"Hello.\"\n\n",
|
||||
"event: text\n",
|
||||
"data: \"\"\n\n",
|
||||
"event: text\n",
|
||||
"data: \" World.\"\n\n",
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "chunk boundary mid-json of second delta",
|
||||
chunks: [
|
||||
"event: text\ndata: \"Hello.\"\n\nevent: text\ndata: \"",
|
||||
" World.\"\n\n",
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "chunk boundary inside leading space on data line",
|
||||
chunks: [
|
||||
"event: text\ndata: \"Hello.\"\n\nevent: text\ndata: \" ",
|
||||
"World.\"\n\n",
|
||||
],
|
||||
},
|
||||
])("preserves whitespace at SSE delta boundaries: $name", async ({ chunks }) => {
|
||||
vi.spyOn(globalThis, "fetch").mockResolvedValue(new Response(createChunkedStream(chunks), { status: 200 }));
|
||||
|
||||
const textChunks: string[] = [];
|
||||
|
||||
streamChatResponse("s-1", "hi", {
|
||||
onText: (data) => textChunks.push(data),
|
||||
onError: vi.fn(),
|
||||
});
|
||||
|
||||
await vi.waitFor(() => {
|
||||
expect(textChunks.join("")).toBe("Hello. World.");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("attachChatStream", () => {
|
||||
|
||||
@@ -8580,6 +8580,8 @@ export function streamChatResponse(
|
||||
currentEvent = line.slice(6).trim();
|
||||
} else if (line.startsWith("data:")) {
|
||||
const value = line.slice(5);
|
||||
// Strip only the optional SSE protocol delimiter-space after `data:`.
|
||||
// Payload whitespace (including JSON-string leading spaces) must stay verbatim.
|
||||
currentDataLines.push(value.startsWith(" ") ? value.slice(1) : value);
|
||||
} else if (line === "") {
|
||||
const currentData = currentDataLines.join("\n");
|
||||
@@ -8780,6 +8782,8 @@ export function attachChatStream(
|
||||
currentEvent = line.slice(6).trim();
|
||||
} else if (line.startsWith("data:")) {
|
||||
const value = line.slice(5);
|
||||
// Strip only the optional SSE protocol delimiter-space after `data:`.
|
||||
// Payload whitespace (including JSON-string leading spaces) must stay verbatim.
|
||||
currentDataLines.push(value.startsWith(" ") ? value.slice(1) : value);
|
||||
} else if (line === "") {
|
||||
const currentData = currentDataLines.join("\n");
|
||||
|
||||
Reference in New Issue
Block a user