fix: settle only after visible stream output

This commit is contained in:
Jesse_Chen
2026-07-21 13:01:37 +08:00
parent 53dddb8b43
commit 697aac2325
3 changed files with 71 additions and 7 deletions
+12 -6
View File
@@ -161,11 +161,20 @@ export function streamTextResponse(
let firstOutputSettled = false;
async function settleFirstOutput(value: string) {
if (!value || firstOutputSettled) return;
if (!/\S/.test(value) || firstOutputSettled) return;
firstOutputSettled = true;
await options.onFirstOutput?.();
}
async function enqueueOutput(
controller: ReadableStreamDefaultController<Uint8Array>,
value: string,
) {
await settleFirstOutput(value);
controller.enqueue(encoder.encode(value));
if (/\S/.test(value)) emitted = true;
}
const body = new ReadableStream<Uint8Array>({
async pull(controller) {
try {
@@ -176,8 +185,7 @@ export function streamTextResponse(
? visibleTransformer.finish(pending)
: pending;
if (finalText) {
await settleFirstOutput(finalText);
controller.enqueue(encoder.encode(finalText));
await enqueueOutput(controller, finalText);
}
settled = true;
if (!emitted) {
@@ -190,7 +198,6 @@ export function streamTextResponse(
controller.close();
return;
}
if (/\S/.test(value)) emitted = true;
pending += value;
if (pending.length <= guardTailLength) continue;
@@ -201,8 +208,7 @@ export function streamTextResponse(
? visibleTransformer.push(stable)
: stable;
if (transformed) {
await settleFirstOutput(transformed);
controller.enqueue(encoder.encode(transformed));
await enqueueOutput(controller, transformed);
return;
}
}