UNPKG

@rocketnew/llm-sdk

Version:

Universal LLM SDK for JavaScript/TypeScript - OpenAI, Anthropic, Gemini, Perplexity and more

188 lines (184 loc) 6.02 kB
import { __esm, __privateAdd, __privateGet, __privateSet } from "./chunk-DDRQKMV4.mjs"; // src/types/responses/binary.ts var _cached, BinaryResponseContent; var init_binary = __esm({ "src/types/responses/binary.ts"() { "use strict"; BinaryResponseContent = class { constructor(response) { /** * Free-form metadata bag used to attach attribution fields (model, * custom_llm_provider, etc.) that downstream tooling may read. Mutable * by design — callers are expected to append to it. */ this.hiddenParams = {}; /** * Cached body. Populated on first `content()` call so multiple call * sites can consume `content()` / `text()` / `json()` after streaming * has already started. */ __privateAdd(this, _cached, null); this.response = response; } get status() { return this.response.status; } get headers() { return this.response.headers; } /** * Charset parsed from the `content-type` header (e.g. `utf-8` for * `text/plain; charset=utf-8`). Null if no charset is present. */ get encoding() { const ct = this.response.headers.get("content-type") ?? ""; const match = /charset=([^;]+)/i.exec(ct); return match ? match[1].trim() : null; } get charsetEncoding() { return this.encoding; } /** * Read the full body as a `Uint8Array`. Caches the result so repeat * calls do not attempt to drain an already-consumed body stream. */ async content() { if (__privateGet(this, _cached)) return __privateGet(this, _cached); const buf = new Uint8Array(await this.response.arrayBuffer()); __privateSet(this, _cached, buf); return buf; } /** * Alias of `content()` for API symmetry with common binary-response * wrappers in other HTTP clients. */ read() { return this.content(); } /** * Decode the full body using the response's charset (defaults to * `utf-8`). */ async text() { const bytes = await this.content(); return new TextDecoder(this.encoding ?? "utf-8").decode(bytes); } async json() { return JSON.parse(await this.text()); } /** * Async byte iterator. If `content()` has already been called, yields * slices of the cached buffer sized by `chunkSize`. Otherwise streams * directly from the live response body — which is drained as a side * effect, so subsequent `content()` calls on the same instance will * return an empty cache. */ async *iterBytes(chunkSize) { if (__privateGet(this, _cached)) { const size = __privateGet(this, _cached).length; const step = chunkSize && chunkSize > 0 ? chunkSize : size; for (let i = 0; i < size; i += step) { yield __privateGet(this, _cached).subarray(i, Math.min(i + step, size)); } return; } const body = this.response.body; if (!body) return; const reader = body.getReader(); try { for (; ; ) { const { value, done } = await reader.read(); if (done) break; if (value) yield value; } } finally { reader.releaseLock(); } } /** * Iterate decoded text chunks. Uses a streaming TextDecoder so * multi-byte sequences that straddle chunk boundaries are handled * correctly. */ async *iterText(chunkSize) { const decoder = new TextDecoder(this.encoding ?? "utf-8", { fatal: false }); for await (const chunk of this.iterBytes(chunkSize)) { yield decoder.decode(chunk, { stream: true }); } const final = decoder.decode(); if (final) yield final; } /** * Iterate decoded lines. Splits on `\n` and strips trailing `\r` for * CR-LF inputs. The last partial line (no trailing newline) is yielded * on stream end. */ async *iterLines() { let buffer = ""; for await (const chunk of this.iterText()) { buffer += chunk; let idx; while ((idx = buffer.indexOf("\n")) !== -1) { let line = buffer.slice(0, idx); if (line.endsWith("\r")) line = line.slice(0, -1); yield line; buffer = buffer.slice(idx + 1); } } if (buffer.length > 0) { if (buffer.endsWith("\r")) buffer = buffer.slice(0, -1); yield buffer; } } /** * Buffer the entire body and write it to disk in one shot. */ async writeToFile(path) { const { writeFile } = await import("fs/promises"); await writeFile(path, await this.content()); } /** * Stream body chunks to disk. Preferred over `writeToFile()` for large * outputs where materializing the full buffer in memory is undesirable. */ async streamToFile(path, opts) { const { open } = await import("fs/promises"); const handle = await open(path, "w"); try { for await (const chunk of this.iterBytes(opts?.chunkSize)) { await handle.write(chunk); } } finally { await handle.close(); } } /** * Cancel the underlying stream. Safe to call multiple times; swallows * any error thrown by the already-consumed or already-aborted stream. */ async close() { try { await this.response.body?.cancel(); } catch { } } }; _cached = new WeakMap(); } }); // src/types/responses/index.ts var init_responses = __esm({ "src/types/responses/index.ts"() { "use strict"; init_binary(); } }); export { BinaryResponseContent, init_responses };