UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

97 lines (96 loc) • 3.4 kB
import "./errno-jiy5vtf-.mjs"; import "./number-coercion-PJEgwXYS.mjs"; import "./errors-Qhjprk1B.mjs"; import { n as withResponseBodyTimeout, t as withResponseBodyIdleTimeout } from "./http-response-body-timeout-BtWNdgQl.mjs"; //#region packages/normalization-core/src/response-bytes.ts async function consumeResponseBytes(options) { let size = 0; while (true) { const { done, value } = await options.read(); if (done) return { size, truncated: false }; if (options.skipEmptyChunks !== false && !value?.length) continue; const remaining = options.maxBytes - size; size += value.length; if (size > options.maxBytes || options.stopAtLimit && size === options.maxBytes) { if (remaining > 0) options.onChunk(value.subarray(0, remaining)); await options.onLimit(size); return { size, truncated: true }; } options.onChunk(value); } } //#endregion //#region src/infra/http-response-body.ts /** Requests cancellation only when no consumer has started reading the body. */ async function cancelUnreadResponseBody(response) { if (response && !response.bodyUsed) response.body?.cancel().catch(() => void 0); } async function readResponsePrefix(response, maxBytes, stopAtLimit, options) { if (!Number.isFinite(maxBytes) || maxBytes < 0) throw new RangeError(`maxBytes must be a non-negative finite number: ${maxBytes}`); let timeoutMs; try { timeoutMs = typeof options?.timeoutMs === "function" ? options.timeoutMs() : options?.timeoutMs; } catch (error) { response.body?.cancel(error).catch(() => void 0); throw error; } const body = response.body; const reader = body && typeof body.getReader === "function" ? body.getReader() : void 0; try { return await withResponseBodyTimeout({ timeoutMs, onTimeout: options?.onTimeout, signal: options?.signal, cancel: async (error) => await (reader ?? body)?.cancel(error), read: async () => { if (!reader) { const fallback = Buffer.from(await response.arrayBuffer()); const truncated = fallback.length > maxBytes; return { materializeBuffer: () => truncated ? fallback.subarray(0, maxBytes) : fallback, size: fallback.length, truncated }; } const chunks = []; const result = await withResponseBodyIdleTimeout(reader, options?.chunkTimeoutMs || void 0, options?.onIdleTimeout, (refreshTimeout) => consumeResponseBytes({ maxBytes, stopAtLimit, read: () => { refreshTimeout?.(); return reader.read(); }, onChunk: (chunk) => chunks.push(chunk), onLimit: () => { reader.cancel().catch(() => void 0); } })); return { materializeBuffer: () => Buffer.concat(chunks, Math.floor(Math.min(result.size, maxBytes))), ...result }; } }); } finally { reader?.releaseLock(); } } /** Reads a response body under byte, idle, and overall timeout bounds. */ async function readResponseWithLimit(response, maxBytes, options) { const onOverflow = options?.onOverflow; const prefix = await readResponsePrefix(response, maxBytes, false, options); if (prefix.truncated) throw onOverflow ? onOverflow({ size: prefix.size, maxBytes, res: response }) : /* @__PURE__ */ new Error(`Content too large: ${prefix.size} bytes (limit: ${maxBytes} bytes)`); return prefix.materializeBuffer(); } //#endregion export { readResponseWithLimit as n, cancelUnreadResponseBody as t };