Capture M16 gap execution artifacts
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled

This commit is contained in:
mes123456
2026-08-21 21:09:40 -04:00
parent e8ce4f5d0c
commit 46c9ebfcb6
339 changed files with 20028 additions and 108 deletions

View File

@@ -36,6 +36,18 @@ export interface StreamConsumerOptions {
requireCompletion?: boolean;
isComplete?: (progress: StreamProgress) => boolean;
onCheckpoint?: (checkpoint: AtomicCheckpoint) => Promise<void> | void;
/**
* Recreate the response after a transport-level read failure. The returned
* stream must start at `progress.byteCount`; already consumed bytes are
* retained and are never published twice.
*/
reconnect?: (progress: StreamProgress, error: unknown) =>
| (ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>)
| Promise<ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>>;
/** Maximum number of reconnect attempts after the initial stream. */
maxRetries?: number;
/** Optional delay between reconnect attempts. */
retryDelayMs?: number;
}
export interface StreamConsumeResult extends StreamProgress {
@@ -49,6 +61,16 @@ async function sha256Hex(bytes: Uint8Array): Promise<string> {
return [...new Uint8Array(digest)].map((value) => value.toString(16).padStart(2, "0")).join("");
}
function concatParts(parts: Uint8Array[]): Uint8Array {
const result = new Uint8Array(parts.reduce((total, part) => total + part.byteLength, 0));
let offset = 0;
for (const part of parts) {
result.set(part, offset);
offset += part.byteLength;
}
return result;
}
function asStream(source: ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>): ReadableStream<Uint8Array> {
if (typeof (source as ReadableStream<Uint8Array>).getReader === "function") return source as ReadableStream<Uint8Array>;
const iterable = source as AsyncIterable<Uint8Array>;
@@ -92,24 +114,79 @@ async function checkpoint(options: StreamConsumerOptions, state: "STREAMING" | "
catch (error) { throw new StreamConsumeError("STREAM_CHECKPOINT_FAILED", "checkpoint publication failed", byteCount, chunkCount, { cause: error }); }
}
function waitForRetry(delayMs: number, signal?: AbortSignal): Promise<boolean> {
if (delayMs <= 0) return Promise.resolve(signal?.aborted !== true);
return new Promise((resolve) => {
let timer: ReturnType<typeof setTimeout> | undefined;
const finish = (ready: boolean): void => {
if (timer !== undefined) clearTimeout(timer);
signal?.removeEventListener("abort", onAbort);
resolve(ready);
};
const onAbort = (): void => finish(false);
timer = setTimeout(() => finish(signal?.aborted !== true), delayMs);
signal?.addEventListener("abort", onAbort, { once: true });
if (signal?.aborted) finish(false);
});
}
/** Consume a UTF-8 byte stream without replacement characters or partial durable output. */
export async function consumeUtf8Stream(source: ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>, options: StreamConsumerOptions = {}): Promise<StreamConsumeResult> {
const reader = asStream(source).getReader();
const maxRetries = options.maxRetries ?? (options.reconnect ? 1 : 0);
if (!Number.isSafeInteger(maxRetries) || maxRetries < 0) {
throw new TypeError("STREAM_RETRY_INVALID: maxRetries must be a non-negative safe integer");
}
if (options.retryDelayMs !== undefined && (!Number.isFinite(options.retryDelayMs) || options.retryDelayMs < 0)) {
throw new TypeError("STREAM_RETRY_INVALID: retryDelayMs must be a non-negative number");
}
if (maxRetries && !options.reconnect) {
throw new TypeError("STREAM_RETRY_INVALID: reconnect is required when maxRetries is non-zero");
}
let reader = asStream(source).getReader();
const decoder = new TextDecoder("utf-8", { fatal: true });
const parts: Uint8Array[] = [];
let text = "";
let byteCount = 0;
let chunkCount = 0;
let completed = false;
let retryCount = 0;
let readerLockHeld = true;
const aborted = (): boolean => options.signal?.aborted === true;
const cancel = (): void => { void reader.cancel("STREAM_CANCELLED").catch(() => undefined); };
options.signal?.addEventListener("abort", cancel, { once: true });
const reconnect = async (error: unknown): Promise<boolean> => {
if (!options.reconnect || retryCount >= maxRetries || aborted()) return false;
const progress = { byteCount, chunkCount, sha256: await sha256Hex(concatParts(parts)) };
const previousReader = reader;
retryCount += 1;
await previousReader.cancel("STREAM_RECONNECT").catch(() => undefined);
previousReader.releaseLock();
readerLockHeld = false;
if (!await waitForRetry(options.retryDelayMs ?? 0, options.signal)) return false;
if (aborted()) return false;
let replacement;
try { replacement = await options.reconnect(progress, error); }
catch { return false; }
if (!replacement) return false;
try { reader = asStream(replacement).getReader(); }
catch { return false; }
if (aborted()) {
await reader.cancel("STREAM_CANCELLED").catch(() => undefined);
reader.releaseLock();
readerLockHeld = false;
return false;
}
readerLockHeld = true;
return true;
};
try {
while (true) {
if (aborted()) throw new StreamConsumeError("STREAM_CANCELLED", "stream consumption was cancelled", byteCount, chunkCount);
let next: ReadableStreamReadResult<Uint8Array>;
try { next = await reader.read(); }
catch (error) {
if (aborted()) throw new StreamConsumeError("STREAM_CANCELLED", "stream consumption was cancelled", byteCount, chunkCount, { cause: error });
if (await reconnect(error)) continue;
if (aborted()) throw new StreamConsumeError("STREAM_CANCELLED", "stream consumption was cancelled", byteCount, chunkCount, { cause: error });
throw new StreamConsumeError("STREAM_DISCONNECTED", `stream disconnected before completion: ${errorMessage(error)}`, byteCount, chunkCount, { cause: error });
}
@@ -122,21 +199,21 @@ export async function consumeUtf8Stream(source: ReadableStream<Uint8Array> | Asy
chunkCount += 1;
try { text += decoder.decode(bytes, { stream: true }); }
catch (error) { throw new StreamConsumeError("STREAM_UTF8_INVALID", "stream ended or yielded an invalid UTF-8 sequence", byteCount, chunkCount, { cause: error }); }
await checkpoint(options, "STREAMING", Uint8Array.from(parts.flatMap((part) => [...part])), byteCount, chunkCount);
await checkpoint(options, "STREAMING", concatParts(parts), byteCount, chunkCount);
}
try { text += decoder.decode(); }
catch (error) { throw new StreamConsumeError("STREAM_UTF8_INVALID", "stream ended with an incomplete UTF-8 sequence", byteCount, chunkCount, { cause: error }); }
const progress = { byteCount, chunkCount, sha256: await sha256Hex(Uint8Array.from(parts.flatMap((part) => [...part]))) };
const progress = { byteCount, chunkCount, sha256: await sha256Hex(concatParts(parts)) };
if ((options.requireCompletion && !options.isComplete) || (options.isComplete && !options.isComplete(progress))) {
throw new StreamConsumeError("STREAM_DISCONNECTED", "stream disconnected before completion", byteCount, chunkCount);
}
await checkpoint(options, "COMPLETED", Uint8Array.from(parts.flatMap((part) => [...part])), byteCount, chunkCount);
await checkpoint(options, "COMPLETED", concatParts(parts), byteCount, chunkCount);
completed = true;
return { text, ...progress };
} catch (error) {
if (!completed && error instanceof StreamConsumeError && options.onCheckpoint) {
try {
const bytes = Uint8Array.from(parts.flatMap((part) => [...part]));
const bytes = concatParts(parts);
await options.onCheckpoint(createAtomicCheckpoint({ state: "FAILED", byteCount, chunkCount, sha256: await sha256Hex(bytes) }));
} catch {
// Preserve the original transport/UTF-8 error; failed checkpoints are advisory.
@@ -146,7 +223,7 @@ export async function consumeUtf8Stream(source: ReadableStream<Uint8Array> | Asy
} finally {
options.signal?.removeEventListener("abort", cancel);
if (!completed) await reader.cancel("STREAM_CONSUMER_STOPPED").catch(() => undefined);
reader.releaseLock();
if (readerLockHeld) reader.releaseLock();
}
}