@imgly/plugin-ai-text-generation-web
Version:
AI text generation plugin for the CE.SDK editor
4 lines • 391 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/version.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/_shims/registry.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/_shims/MultipartBody.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/_shims/web-runtime.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/_shims/index.mjs", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/error.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/internal/decoders/line.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/internal/stream-utils.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/streaming.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/uploads.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/core.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/pagination.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/resource.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/resources/beta/models.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/internal/decoders/jsonl.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/resources/beta/messages/batches.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/_vendor/partial-json-parser/parser.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/lib/BetaMessageStream.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/resources/beta/messages/messages.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/resources/beta/beta.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/resources/completions.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/resources/messages/batches.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/lib/MessageStream.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/resources/messages/messages.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/resources/models.ts", "../../../../node_modules/.pnpm/@anthropic-ai+sdk@0.39.0/node_modules/@anthropic-ai/sdk/src/index.ts", "../../src/anthropic/sendPrompt.ts", "../../src/anthropic/prompts/improve.ts", "../../src/anthropic/prompts/shorter.ts", "../../src/anthropic/prompts/longer.ts", "../../src/anthropic/prompts/fix.ts", "../../src/anthropic/prompts/generateTextForSpeech.ts", "../../src/anthropic/prompts/translate.ts", "../../src/anthropic/prompts/changeTone.ts", "../../src/anthropic/prompts/changeTextTo.ts", "../../src/anthropic/AnthropicProvider.ts", "../../src/anthropic/index.ts"],
"sourcesContent": ["export const VERSION = '0.39.0'; // x-release-please-version\n", "/**\n * Disclaimer: modules in _shims aren't intended to be imported by SDK users.\n */\nimport { type RequestOptions } from \"../core.js\";\n\nexport interface Shims {\n kind: string;\n fetch: any;\n Request: any;\n Response: any;\n Headers: any;\n FormData: any;\n Blob: any;\n File: any;\n ReadableStream: any;\n getMultipartRequestOptions: <T = Record<string, unknown>>(\n form: Shims['FormData'],\n opts: RequestOptions<T>,\n ) => Promise<RequestOptions<T>>;\n getDefaultAgent: (url: string) => any;\n fileFromPath:\n | ((path: string, filename?: string, options?: {}) => Promise<Shims['File']>)\n | ((path: string, options?: {}) => Promise<Shims['File']>);\n isFsReadStream: (value: any) => boolean;\n}\n\nexport let auto = false;\nexport let kind: Shims['kind'] | undefined = undefined;\nexport let fetch: Shims['fetch'] | undefined = undefined;\nexport let Request: Shims['Request'] | undefined = undefined;\nexport let Response: Shims['Response'] | undefined = undefined;\nexport let Headers: Shims['Headers'] | undefined = undefined;\nexport let FormData: Shims['FormData'] | undefined = undefined;\nexport let Blob: Shims['Blob'] | undefined = undefined;\nexport let File: Shims['File'] | undefined = undefined;\nexport let ReadableStream: Shims['ReadableStream'] | undefined = undefined;\nexport let getMultipartRequestOptions: Shims['getMultipartRequestOptions'] | undefined = undefined;\nexport let getDefaultAgent: Shims['getDefaultAgent'] | undefined = undefined;\nexport let fileFromPath: Shims['fileFromPath'] | undefined = undefined;\nexport let isFsReadStream: Shims['isFsReadStream'] | undefined = undefined;\n\nexport function setShims(shims: Shims, options: { auto: boolean } = { auto: false }) {\n if (auto) {\n throw new Error(\n `you must \\`import '@anthropic-ai/sdk/shims/${shims.kind}'\\` before importing anything else from @anthropic-ai/sdk`,\n );\n }\n if (kind) {\n throw new Error(\n `can't \\`import '@anthropic-ai/sdk/shims/${shims.kind}'\\` after \\`import '@anthropic-ai/sdk/shims/${kind}'\\``,\n );\n }\n auto = options.auto;\n kind = shims.kind;\n fetch = shims.fetch;\n Request = shims.Request;\n Response = shims.Response;\n Headers = shims.Headers;\n FormData = shims.FormData;\n Blob = shims.Blob;\n File = shims.File;\n ReadableStream = shims.ReadableStream;\n getMultipartRequestOptions = shims.getMultipartRequestOptions;\n getDefaultAgent = shims.getDefaultAgent;\n fileFromPath = shims.fileFromPath;\n isFsReadStream = shims.isFsReadStream;\n}\n", "/**\n * Disclaimer: modules in _shims aren't intended to be imported by SDK users.\n */\nexport class MultipartBody {\n constructor(public body: any) {}\n get [Symbol.toStringTag](): string {\n return 'MultipartBody';\n }\n}\n", "/**\n * Disclaimer: modules in _shims aren't intended to be imported by SDK users.\n */\nimport { MultipartBody } from \"./MultipartBody.js\";\nimport { type RequestOptions } from \"../core.js\";\nimport { type Shims } from \"./registry.js\";\n\nexport function getRuntime({ manuallyImported }: { manuallyImported?: boolean } = {}): Shims {\n const recommendation =\n manuallyImported ?\n `You may need to use polyfills`\n : `Add one of these imports before your first \\`import \u2026 from '@anthropic-ai/sdk'\\`:\n- \\`import '@anthropic-ai/sdk/shims/node'\\` (if you're running on Node)\n- \\`import '@anthropic-ai/sdk/shims/web'\\` (otherwise)\n`;\n\n let _fetch, _Request, _Response, _Headers;\n try {\n // @ts-ignore\n _fetch = fetch;\n // @ts-ignore\n _Request = Request;\n // @ts-ignore\n _Response = Response;\n // @ts-ignore\n _Headers = Headers;\n } catch (error) {\n throw new Error(\n `this environment is missing the following Web Fetch API type: ${\n (error as any).message\n }. ${recommendation}`,\n );\n }\n\n return {\n kind: 'web',\n fetch: _fetch,\n Request: _Request,\n Response: _Response,\n Headers: _Headers,\n FormData:\n // @ts-ignore\n typeof FormData !== 'undefined' ? FormData : (\n class FormData {\n // @ts-ignore\n constructor() {\n throw new Error(\n `file uploads aren't supported in this environment yet as 'FormData' is undefined. ${recommendation}`,\n );\n }\n }\n ),\n Blob:\n typeof Blob !== 'undefined' ? Blob : (\n class Blob {\n constructor() {\n throw new Error(\n `file uploads aren't supported in this environment yet as 'Blob' is undefined. ${recommendation}`,\n );\n }\n }\n ),\n File:\n // @ts-ignore\n typeof File !== 'undefined' ? File : (\n class File {\n // @ts-ignore\n constructor() {\n throw new Error(\n `file uploads aren't supported in this environment yet as 'File' is undefined. ${recommendation}`,\n );\n }\n }\n ),\n ReadableStream:\n // @ts-ignore\n typeof ReadableStream !== 'undefined' ? ReadableStream : (\n class ReadableStream {\n // @ts-ignore\n constructor() {\n throw new Error(\n `streaming isn't supported in this environment yet as 'ReadableStream' is undefined. ${recommendation}`,\n );\n }\n }\n ),\n getMultipartRequestOptions: async <T = Record<string, unknown>>(\n // @ts-ignore\n form: FormData,\n opts: RequestOptions<T>,\n ): Promise<RequestOptions<T>> => ({\n ...opts,\n body: new MultipartBody(form) as any,\n }),\n getDefaultAgent: (url: string) => undefined,\n fileFromPath: () => {\n throw new Error(\n 'The `fileFromPath` function is only supported in Node. See the README for more details: https://www.github.com/anthropics/anthropic-sdk-typescript#file-uploads',\n );\n },\n isFsReadStream: (value: any) => false,\n };\n}\n", "/**\n * Disclaimer: modules in _shims aren't intended to be imported by SDK users.\n */\nimport * as shims from './registry.mjs';\nimport * as auto from '@anthropic-ai/sdk/_shims/auto/runtime';\nif (!shims.kind) shims.setShims(auto.getRuntime(), { auto: true });\nexport * from './registry.mjs';\n", "// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\n\nimport { castToError, Headers } from \"./core.js\";\n\nexport class AnthropicError extends Error {}\n\nexport class APIError<\n TStatus extends number | undefined = number | undefined,\n THeaders extends Headers | undefined = Headers | undefined,\n TError extends Object | undefined = Object | undefined,\n> extends AnthropicError {\n /** HTTP status for the response that caused the error */\n readonly status: TStatus;\n /** HTTP headers for the response that caused the error */\n readonly headers: THeaders;\n /** JSON body of the response that caused the error */\n readonly error: TError;\n\n readonly request_id: string | null | undefined;\n\n constructor(status: TStatus, error: TError, message: string | undefined, headers: THeaders) {\n super(`${APIError.makeMessage(status, error, message)}`);\n this.status = status;\n this.headers = headers;\n this.request_id = headers?.['request-id'];\n this.error = error;\n }\n\n private static makeMessage(status: number | undefined, error: any, message: string | undefined) {\n const msg =\n error?.message ?\n typeof error.message === 'string' ?\n error.message\n : JSON.stringify(error.message)\n : error ? JSON.stringify(error)\n : message;\n\n if (status && msg) {\n return `${status} ${msg}`;\n }\n if (status) {\n return `${status} status code (no body)`;\n }\n if (msg) {\n return msg;\n }\n return '(no status code or body)';\n }\n\n static generate(\n status: number | undefined,\n errorResponse: Object | undefined,\n message: string | undefined,\n headers: Headers | undefined,\n ): APIError {\n if (!status || !headers) {\n return new APIConnectionError({ message, cause: castToError(errorResponse) });\n }\n\n const error = errorResponse as Record<string, any>;\n\n if (status === 400) {\n return new BadRequestError(status, error, message, headers);\n }\n\n if (status === 401) {\n return new AuthenticationError(status, error, message, headers);\n }\n\n if (status === 403) {\n return new PermissionDeniedError(status, error, message, headers);\n }\n\n if (status === 404) {\n return new NotFoundError(status, error, message, headers);\n }\n\n if (status === 409) {\n return new ConflictError(status, error, message, headers);\n }\n\n if (status === 422) {\n return new UnprocessableEntityError(status, error, message, headers);\n }\n\n if (status === 429) {\n return new RateLimitError(status, error, message, headers);\n }\n\n if (status >= 500) {\n return new InternalServerError(status, error, message, headers);\n }\n\n return new APIError(status, error, message, headers);\n }\n}\n\nexport class APIUserAbortError extends APIError<undefined, undefined, undefined> {\n constructor({ message }: { message?: string } = {}) {\n super(undefined, undefined, message || 'Request was aborted.', undefined);\n }\n}\n\nexport class APIConnectionError extends APIError<undefined, undefined, undefined> {\n constructor({ message, cause }: { message?: string | undefined; cause?: Error | undefined }) {\n super(undefined, undefined, message || 'Connection error.', undefined);\n // in some environments the 'cause' property is already declared\n // @ts-ignore\n if (cause) this.cause = cause;\n }\n}\n\nexport class APIConnectionTimeoutError extends APIConnectionError {\n constructor({ message }: { message?: string } = {}) {\n super({ message: message ?? 'Request timed out.' });\n }\n}\n\nexport class BadRequestError extends APIError<400, Headers> {}\n\nexport class AuthenticationError extends APIError<401, Headers> {}\n\nexport class PermissionDeniedError extends APIError<403, Headers> {}\n\nexport class NotFoundError extends APIError<404, Headers> {}\n\nexport class ConflictError extends APIError<409, Headers> {}\n\nexport class UnprocessableEntityError extends APIError<422, Headers> {}\n\nexport class RateLimitError extends APIError<429, Headers> {}\n\nexport class InternalServerError extends APIError<number, Headers> {}\n", "import { AnthropicError } from \"../../error.js\";\n\nexport type Bytes = string | ArrayBuffer | Uint8Array | Buffer | null | undefined;\n\n/**\n * A re-implementation of httpx's `LineDecoder` in Python that handles incrementally\n * reading lines from text.\n *\n * https://github.com/encode/httpx/blob/920333ea98118e9cf617f246905d7b202510941c/httpx/_decoders.py#L258\n */\nexport class LineDecoder {\n // prettier-ignore\n static NEWLINE_CHARS = new Set(['\\n', '\\r']);\n static NEWLINE_REGEXP = /\\r\\n|[\\n\\r]/g;\n\n buffer: Uint8Array;\n #carriageReturnIndex: number | null;\n textDecoder: any; // TextDecoder found in browsers; not typed to avoid pulling in either \"dom\" or \"node\" types.\n\n constructor() {\n this.buffer = new Uint8Array();\n this.#carriageReturnIndex = null;\n }\n\n decode(chunk: Bytes): string[] {\n if (chunk == null) {\n return [];\n }\n\n const binaryChunk =\n chunk instanceof ArrayBuffer ? new Uint8Array(chunk)\n : typeof chunk === 'string' ? new TextEncoder().encode(chunk)\n : chunk;\n\n let newData = new Uint8Array(this.buffer.length + binaryChunk.length);\n newData.set(this.buffer);\n newData.set(binaryChunk, this.buffer.length);\n this.buffer = newData;\n\n const lines: string[] = [];\n let patternIndex;\n while ((patternIndex = findNewlineIndex(this.buffer, this.#carriageReturnIndex)) != null) {\n if (patternIndex.carriage && this.#carriageReturnIndex == null) {\n // skip until we either get a corresponding `\\n`, a new `\\r` or nothing\n this.#carriageReturnIndex = patternIndex.index;\n continue;\n }\n\n // we got double \\r or \\rtext\\n\n if (\n this.#carriageReturnIndex != null &&\n (patternIndex.index !== this.#carriageReturnIndex + 1 || patternIndex.carriage)\n ) {\n lines.push(this.decodeText(this.buffer.slice(0, this.#carriageReturnIndex - 1)));\n this.buffer = this.buffer.slice(this.#carriageReturnIndex);\n this.#carriageReturnIndex = null;\n continue;\n }\n\n const endIndex =\n this.#carriageReturnIndex !== null ? patternIndex.preceding - 1 : patternIndex.preceding;\n\n const line = this.decodeText(this.buffer.slice(0, endIndex));\n lines.push(line);\n\n this.buffer = this.buffer.slice(patternIndex.index);\n this.#carriageReturnIndex = null;\n }\n\n return lines;\n }\n\n decodeText(bytes: Bytes): string {\n if (bytes == null) return '';\n if (typeof bytes === 'string') return bytes;\n\n // Node:\n if (typeof Buffer !== 'undefined') {\n if (bytes instanceof Buffer) {\n return bytes.toString();\n }\n if (bytes instanceof Uint8Array) {\n return Buffer.from(bytes).toString();\n }\n\n throw new AnthropicError(\n `Unexpected: received non-Uint8Array (${bytes.constructor.name}) stream chunk in an environment with a global \"Buffer\" defined, which this library assumes to be Node. Please report this error.`,\n );\n }\n\n // Browser\n if (typeof TextDecoder !== 'undefined') {\n if (bytes instanceof Uint8Array || bytes instanceof ArrayBuffer) {\n this.textDecoder ??= new TextDecoder('utf8');\n return this.textDecoder.decode(bytes);\n }\n\n throw new AnthropicError(\n `Unexpected: received non-Uint8Array/ArrayBuffer (${\n (bytes as any).constructor.name\n }) in a web platform. Please report this error.`,\n );\n }\n\n throw new AnthropicError(\n `Unexpected: neither Buffer nor TextDecoder are available as globals. Please report this error.`,\n );\n }\n\n flush(): string[] {\n if (!this.buffer.length) {\n return [];\n }\n return this.decode('\\n');\n }\n}\n\n/**\n * This function searches the buffer for the end patterns, (\\r or \\n)\n * and returns an object with the index preceding the matched newline and the\n * index after the newline char. `null` is returned if no new line is found.\n *\n * ```ts\n * findNewLineIndex('abc\\ndef') -> { preceding: 2, index: 3 }\n * ```\n */\nfunction findNewlineIndex(\n buffer: Uint8Array,\n startIndex: number | null,\n): { preceding: number; index: number; carriage: boolean } | null {\n const newline = 0x0a; // \\n\n const carriage = 0x0d; // \\r\n\n for (let i = startIndex ?? 0; i < buffer.length; i++) {\n if (buffer[i] === newline) {\n return { preceding: i, index: i + 1, carriage: false };\n }\n\n if (buffer[i] === carriage) {\n return { preceding: i, index: i + 1, carriage: true };\n }\n }\n\n return null;\n}\n\nexport function findDoubleNewlineIndex(buffer: Uint8Array): number {\n // This function searches the buffer for the end patterns (\\r\\r, \\n\\n, \\r\\n\\r\\n)\n // and returns the index right after the first occurrence of any pattern,\n // or -1 if none of the patterns are found.\n const newline = 0x0a; // \\n\n const carriage = 0x0d; // \\r\n\n for (let i = 0; i < buffer.length - 1; i++) {\n if (buffer[i] === newline && buffer[i + 1] === newline) {\n // \\n\\n\n return i + 2;\n }\n if (buffer[i] === carriage && buffer[i + 1] === carriage) {\n // \\r\\r\n return i + 2;\n }\n if (\n buffer[i] === carriage &&\n buffer[i + 1] === newline &&\n i + 3 < buffer.length &&\n buffer[i + 2] === carriage &&\n buffer[i + 3] === newline\n ) {\n // \\r\\n\\r\\n\n return i + 4;\n }\n }\n\n return -1;\n}\n", "/**\n * Most browsers don't yet have async iterable support for ReadableStream,\n * and Node has a very different way of reading bytes from its \"ReadableStream\".\n *\n * This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490\n */\nexport function ReadableStreamToAsyncIterable<T>(stream: any): AsyncIterableIterator<T> {\n if (stream[Symbol.asyncIterator]) return stream;\n\n const reader = stream.getReader();\n return {\n async next() {\n try {\n const result = await reader.read();\n if (result?.done) reader.releaseLock(); // release lock when stream becomes closed\n return result;\n } catch (e) {\n reader.releaseLock(); // release lock when stream becomes errored\n throw e;\n }\n },\n async return() {\n const cancelPromise = reader.cancel();\n reader.releaseLock();\n await cancelPromise;\n return { done: true, value: undefined };\n },\n [Symbol.asyncIterator]() {\n return this;\n },\n };\n}\n", "import { ReadableStream, type Response } from \"./_shims/index.js\";\nimport { AnthropicError } from \"./error.js\";\nimport { findDoubleNewlineIndex, LineDecoder } from \"./internal/decoders/line.js\";\nimport { ReadableStreamToAsyncIterable } from \"./internal/stream-utils.js\";\n\nimport { createResponseHeaders } from \"./core.js\";\nimport { APIError } from \"./error.js\";\n\ntype Bytes = string | ArrayBuffer | Uint8Array | Buffer | null | undefined;\n\nexport type ServerSentEvent = {\n event: string | null;\n data: string;\n raw: string[];\n};\n\nexport class Stream<Item> implements AsyncIterable<Item> {\n controller: AbortController;\n\n constructor(\n private iterator: () => AsyncIterator<Item>,\n controller: AbortController,\n ) {\n this.controller = controller;\n }\n\n static fromSSEResponse<Item>(response: Response, controller: AbortController): Stream<Item> {\n let consumed = false;\n\n async function* iterator(): AsyncIterator<Item, any, undefined> {\n if (consumed) {\n throw new Error('Cannot iterate over a consumed stream, use `.tee()` to split the stream.');\n }\n consumed = true;\n let done = false;\n try {\n for await (const sse of _iterSSEMessages(response, controller)) {\n if (sse.event === 'completion') {\n try {\n yield JSON.parse(sse.data);\n } catch (e) {\n console.error(`Could not parse message into JSON:`, sse.data);\n console.error(`From chunk:`, sse.raw);\n throw e;\n }\n }\n\n if (\n sse.event === 'message_start' ||\n sse.event === 'message_delta' ||\n sse.event === 'message_stop' ||\n sse.event === 'content_block_start' ||\n sse.event === 'content_block_delta' ||\n sse.event === 'content_block_stop'\n ) {\n try {\n yield JSON.parse(sse.data);\n } catch (e) {\n console.error(`Could not parse message into JSON:`, sse.data);\n console.error(`From chunk:`, sse.raw);\n throw e;\n }\n }\n\n if (sse.event === 'ping') {\n continue;\n }\n\n if (sse.event === 'error') {\n throw APIError.generate(\n undefined,\n `SSE Error: ${sse.data}`,\n sse.data,\n createResponseHeaders(response.headers),\n );\n }\n }\n done = true;\n } catch (e) {\n // If the user calls `stream.controller.abort()`, we should exit without throwing.\n if (e instanceof Error && e.name === 'AbortError') return;\n throw e;\n } finally {\n // If the user `break`s, abort the ongoing request.\n if (!done) controller.abort();\n }\n }\n\n return new Stream(iterator, controller);\n }\n\n /**\n * Generates a Stream from a newline-separated ReadableStream\n * where each item is a JSON value.\n */\n static fromReadableStream<Item>(readableStream: ReadableStream, controller: AbortController): Stream<Item> {\n let consumed = false;\n\n async function* iterLines(): AsyncGenerator<string, void, unknown> {\n const lineDecoder = new LineDecoder();\n\n const iter = ReadableStreamToAsyncIterable<Bytes>(readableStream);\n for await (const chunk of iter) {\n for (const line of lineDecoder.decode(chunk)) {\n yield line;\n }\n }\n\n for (const line of lineDecoder.flush()) {\n yield line;\n }\n }\n\n async function* iterator(): AsyncIterator<Item, any, undefined> {\n if (consumed) {\n throw new Error('Cannot iterate over a consumed stream, use `.tee()` to split the stream.');\n }\n consumed = true;\n let done = false;\n try {\n for await (const line of iterLines()) {\n if (done) continue;\n if (line) yield JSON.parse(line);\n }\n done = true;\n } catch (e) {\n // If the user calls `stream.controller.abort()`, we should exit without throwing.\n if (e instanceof Error && e.name === 'AbortError') return;\n throw e;\n } finally {\n // If the user `break`s, abort the ongoing request.\n if (!done) controller.abort();\n }\n }\n\n return new Stream(iterator, controller);\n }\n\n [Symbol.asyncIterator](): AsyncIterator<Item> {\n return this.iterator();\n }\n\n /**\n * Splits the stream into two streams which can be\n * independently read from at different speeds.\n */\n tee(): [Stream<Item>, Stream<Item>] {\n const left: Array<Promise<IteratorResult<Item>>> = [];\n const right: Array<Promise<IteratorResult<Item>>> = [];\n const iterator = this.iterator();\n\n const teeIterator = (queue: Array<Promise<IteratorResult<Item>>>): AsyncIterator<Item> => {\n return {\n next: () => {\n if (queue.length === 0) {\n const result = iterator.next();\n left.push(result);\n right.push(result);\n }\n return queue.shift()!;\n },\n };\n };\n\n return [\n new Stream(() => teeIterator(left), this.controller),\n new Stream(() => teeIterator(right), this.controller),\n ];\n }\n\n /**\n * Converts this stream to a newline-separated ReadableStream of\n * JSON stringified values in the stream\n * which can be turned back into a Stream with `Stream.fromReadableStream()`.\n */\n toReadableStream(): ReadableStream {\n const self = this;\n let iter: AsyncIterator<Item>;\n const encoder = new TextEncoder();\n\n return new ReadableStream({\n async start() {\n iter = self[Symbol.asyncIterator]();\n },\n async pull(ctrl: any) {\n try {\n const { value, done } = await iter.next();\n if (done) return ctrl.close();\n\n const bytes = encoder.encode(JSON.stringify(value) + '\\n');\n\n ctrl.enqueue(bytes);\n } catch (err) {\n ctrl.error(err);\n }\n },\n async cancel() {\n await iter.return?.();\n },\n });\n }\n}\n\nexport async function* _iterSSEMessages(\n response: Response,\n controller: AbortController,\n): AsyncGenerator<ServerSentEvent, void, unknown> {\n if (!response.body) {\n controller.abort();\n throw new AnthropicError(`Attempted to iterate over a response with no body`);\n }\n\n const sseDecoder = new SSEDecoder();\n const lineDecoder = new LineDecoder();\n\n const iter = ReadableStreamToAsyncIterable<Bytes>(response.body);\n for await (const sseChunk of iterSSEChunks(iter)) {\n for (const line of lineDecoder.decode(sseChunk)) {\n const sse = sseDecoder.decode(line);\n if (sse) yield sse;\n }\n }\n\n for (const line of lineDecoder.flush()) {\n const sse = sseDecoder.decode(line);\n if (sse) yield sse;\n }\n}\n\n/**\n * Given an async iterable iterator, iterates over it and yields full\n * SSE chunks, i.e. yields when a double new-line is encountered.\n */\nasync function* iterSSEChunks(iterator: AsyncIterableIterator<Bytes>): AsyncGenerator<Uint8Array> {\n let data = new Uint8Array();\n\n for await (const chunk of iterator) {\n if (chunk == null) {\n continue;\n }\n\n const binaryChunk =\n chunk instanceof ArrayBuffer ? new Uint8Array(chunk)\n : typeof chunk === 'string' ? new TextEncoder().encode(chunk)\n : chunk;\n\n let newData = new Uint8Array(data.length + binaryChunk.length);\n newData.set(data);\n newData.set(binaryChunk, data.length);\n data = newData;\n\n let patternIndex;\n while ((patternIndex = findDoubleNewlineIndex(data)) !== -1) {\n yield data.slice(0, patternIndex);\n data = data.slice(patternIndex);\n }\n }\n\n if (data.length > 0) {\n yield data;\n }\n}\n\nclass SSEDecoder {\n private data: string[];\n private event: string | null;\n private chunks: string[];\n\n constructor() {\n this.event = null;\n this.data = [];\n this.chunks = [];\n }\n\n decode(line: string) {\n if (line.endsWith('\\r')) {\n line = line.substring(0, line.length - 1);\n }\n\n if (!line) {\n // empty line and we didn't previously encounter any messages\n if (!this.event && !this.data.length) return null;\n\n const sse: ServerSentEvent = {\n event: this.event,\n data: this.data.join('\\n'),\n raw: this.chunks,\n };\n\n this.event = null;\n this.data = [];\n this.chunks = [];\n\n return sse;\n }\n\n this.chunks.push(line);\n\n if (line.startsWith(':')) {\n return null;\n }\n\n let [fieldname, _, value] = partition(line, ':');\n\n if (value.startsWith(' ')) {\n value = value.substring(1);\n }\n\n if (fieldname === 'event') {\n this.event = value;\n } else if (fieldname === 'data') {\n this.data.push(value);\n }\n\n return null;\n }\n}\n\nfunction partition(str: string, delimiter: string): [string, string, string] {\n const index = str.indexOf(delimiter);\n if (index !== -1) {\n return [str.substring(0, index), delimiter, str.substring(index + delimiter.length)];\n }\n\n return [str, '', ''];\n}\n", "import { type RequestOptions } from \"./core.js\";\nimport {\n FormData,\n File,\n type Blob,\n type FilePropertyBag,\n getMultipartRequestOptions,\n type FsReadStream,\n isFsReadStream,\n} from \"./_shims/index.js\";\nimport { MultipartBody } from \"./_shims/MultipartBody.js\";\nexport { fileFromPath } from \"./_shims/index.js\";\n\ntype BlobLikePart = string | ArrayBuffer | ArrayBufferView | BlobLike | Uint8Array | DataView;\nexport type BlobPart = string | ArrayBuffer | ArrayBufferView | Blob | Uint8Array | DataView;\n\n/**\n * Typically, this is a native \"File\" class.\n *\n * We provide the {@link toFile} utility to convert a variety of objects\n * into the File class.\n *\n * For convenience, you can also pass a fetch Response, or in Node,\n * the result of fs.createReadStream().\n */\nexport type Uploadable = FileLike | ResponseLike | FsReadStream;\n\n/**\n * Intended to match web.Blob, node.Blob, node-fetch.Blob, etc.\n */\nexport interface BlobLike {\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/size) */\n readonly size: number;\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/type) */\n readonly type: string;\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/text) */\n text(): Promise<string>;\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/slice) */\n slice(start?: number, end?: number): BlobLike;\n // unfortunately @types/node-fetch@^2.6.4 doesn't type the arrayBuffer method\n}\n\n/**\n * Intended to match web.File, node.File, node-fetch.File, etc.\n */\nexport interface FileLike extends BlobLike {\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/lastModified) */\n readonly lastModified: number;\n /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/name) */\n readonly name: string;\n}\n\n/**\n * Intended to match web.Response, node.Response, node-fetch.Response, etc.\n */\nexport interface ResponseLike {\n url: string;\n blob(): Promise<BlobLike>;\n}\n\nexport const isResponseLike = (value: any): value is ResponseLike =>\n value != null &&\n typeof value === 'object' &&\n typeof value.url === 'string' &&\n typeof value.blob === 'function';\n\nexport const isFileLike = (value: any): value is FileLike =>\n value != null &&\n typeof value === 'object' &&\n typeof value.name === 'string' &&\n typeof value.lastModified === 'number' &&\n isBlobLike(value);\n\n/**\n * The BlobLike type omits arrayBuffer() because @types/node-fetch@^2.6.4 lacks it; but this check\n * adds the arrayBuffer() method type because it is available and used at runtime\n */\nexport const isBlobLike = (value: any): value is BlobLike & { arrayBuffer(): Promise<ArrayBuffer> } =>\n value != null &&\n typeof value === 'object' &&\n typeof value.size === 'number' &&\n typeof value.type === 'string' &&\n typeof value.text === 'function' &&\n typeof value.slice === 'function' &&\n typeof value.arrayBuffer === 'function';\n\nexport const isUploadable = (value: any): value is Uploadable => {\n return isFileLike(value) || isResponseLike(value) || isFsReadStream(value);\n};\n\nexport type ToFileInput = Uploadable | Exclude<BlobLikePart, string> | AsyncIterable<BlobLikePart>;\n\n/**\n * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats\n * @param value the raw content of the file. Can be an {@link Uploadable}, {@link BlobLikePart}, or {@link AsyncIterable} of {@link BlobLikePart}s\n * @param {string=} name the name of the file. If omitted, toFile will try to determine a file name from bits if possible\n * @param {Object=} options additional properties\n * @param {string=} options.type the MIME type of the content\n * @param {number=} options.lastModified the last modified timestamp\n * @returns a {@link File} with the given properties\n */\nexport async function toFile(\n value: ToFileInput | PromiseLike<ToFileInput>,\n name?: string | null | undefined,\n options?: FilePropertyBag | undefined,\n): Promise<FileLike> {\n // If it's a promise, resolve it.\n value = await value;\n\n // If we've been given a `File` we don't need to do anything\n if (isFileLike(value)) {\n return value;\n }\n\n if (isResponseLike(value)) {\n const blob = await value.blob();\n name ||= new URL(value.url).pathname.split(/[\\\\/]/).pop() ?? 'unknown_file';\n\n // we need to convert the `Blob` into an array buffer because the `Blob` class\n // that `node-fetch` defines is incompatible with the web standard which results\n // in `new File` interpreting it as a string instead of binary data.\n const data = isBlobLike(blob) ? [(await blob.arrayBuffer()) as any] : [blob];\n\n return new File(data, name, options);\n }\n\n const bits = await getBytes(value);\n\n name ||= getName(value) ?? 'unknown_file';\n\n if (!options?.type) {\n const type = (bits[0] as any)?.type;\n if (typeof type === 'string') {\n options = { ...options, type };\n }\n }\n\n return new File(bits, name, options);\n}\n\nasync function getBytes(value: ToFileInput): Promise<Array<BlobPart>> {\n let parts: Array<BlobPart> = [];\n if (\n typeof value === 'string' ||\n ArrayBuffer.isView(value) || // includes Uint8Array, Buffer, etc.\n value instanceof ArrayBuffer\n ) {\n parts.push(value);\n } else if (isBlobLike(value)) {\n parts.push(await value.arrayBuffer());\n } else if (\n isAsyncIterableIterator(value) // includes Readable, ReadableStream, etc.\n ) {\n for await (const chunk of value) {\n parts.push(chunk as BlobPart); // TODO, consider validating?\n }\n } else {\n throw new Error(\n `Unexpected data type: ${typeof value}; constructor: ${value?.constructor\n ?.name}; props: ${propsForError(value)}`,\n );\n }\n\n return parts;\n}\n\nfunction propsForError(value: any): string {\n const props = Object.getOwnPropertyNames(value);\n return `[${props.map((p) => `\"${p}\"`).join(', ')}]`;\n}\n\nfunction getName(value: any): string | undefined {\n return (\n getStringFromMaybeBuffer(value.name) ||\n getStringFromMaybeBuffer(value.filename) ||\n // For fs.ReadStream\n getStringFromMaybeBuffer(value.path)?.split(/[\\\\/]/).pop()\n );\n}\n\nconst getStringFromMaybeBuffer = (x: string | Buffer | unknown): string | undefined => {\n if (typeof x === 'string') return x;\n if (typeof Buffer !== 'undefined' && x instanceof Buffer) return String(x);\n return undefined;\n};\n\nconst isAsyncIterableIterator = (value: any): value is AsyncIterableIterator<unknown> =>\n value != null && typeof value === 'object' && typeof value[Symbol.asyncIterator] === 'function';\n\nexport const isMultipartBody = (body: any): body is MultipartBody =>\n body && typeof body === 'object' && body.body && body[Symbol.toStringTag] === 'MultipartBody';\n\n/**\n * Returns a multipart/form-data request if any part of the given request body contains a File / Blob value.\n * Otherwise returns the request as is.\n */\nexport const maybeMultipartFormRequestOptions = async <T = Record<string, unknown>>(\n opts: RequestOptions<T>,\n): Promise<RequestOptions<T | MultipartBody>> => {\n if (!hasUploadableValue(opts.body)) return opts;\n\n const form = await createForm(opts.body);\n return getMultipartRequestOptions(form, opts);\n};\n\nexport const multipartFormRequestOptions = async <T = Record<string, unknown>>(\n opts: RequestOptions<T>,\n): Promise<RequestOptions<T | MultipartBody>> => {\n const form = await createForm(opts.body);\n return getMultipartRequestOptions(form, opts);\n};\n\nexport const createForm = async <T = Record<string, unknown>>(body: T | undefined): Promise<FormData> => {\n const form = new FormData();\n await Promise.all(Object.entries(body || {}).map(([key, value]) => addFormValue(form, key, value)));\n return form;\n};\n\nconst hasUploadableValue = (value: unknown): boolean => {\n if (isUploadable(value)) return true;\n if (Array.isArray(value)) return value.some(hasUploadableValue);\n if (value && typeof value === 'object') {\n for (const k in value) {\n if (hasUploadableValue((value as any)[k])) return true;\n }\n }\n return false;\n};\n\nconst addFormValue = async (form: FormData, key: string, value: unknown): Promise<void> => {\n if (value === undefined) return;\n if (value == null) {\n throw new TypeError(\n `Received null for \"${key}\"; to pass null in FormData, you must use the string 'null'`,\n );\n }\n\n // TODO: make nested formats configurable\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n form.append(key, String(value));\n } else if (isUploadable(value)) {\n const file = await toFile(value);\n form.append(key, file as File);\n } else if (Array.isArray(value)) {\n await Promise.all(value.map((entry) => addFormValue(form, key + '[]', entry)));\n } else if (typeof value === 'object') {\n await Promise.all(\n Object.entries(value).map(([name, prop]) => addFormValue(form, `${key}[${name}]`, prop)),\n );\n } else {\n throw new TypeError(\n `Invalid value given to form, expected a string, number, boolean, object, Array, File or Blob but got ${value} instead`,\n );\n }\n};\n", "import { VERSION } from \"./version.js\";\nimport { Stream } from \"./streaming.js\";\nimport {\n AnthropicError,\n APIError,\n APIConnectionError,\n APIConnectionTimeoutError,\n APIUserAbortError,\n} from \"./error.js\";\nimport {\n kind as shimsKind,\n type Readable,\n getDefaultAgent,\n type Agent,\n fetch,\n type RequestInfo,\n type RequestInit,\n type Response,\n type HeadersInit,\n} from \"./_shims/index.js\";\nexport { type Response };\nimport { BlobLike, isBlobLike, isMultipartBody } from \"./uploads.js\";\nexport {\n maybeMultipartFormRequestOptions,\n multipartFormRequestOptions,\n createForm,\n type Uploadable,\n} from \"./uploads.js\";\n\nexport type Fetch = (url: RequestInfo, init?: RequestInit) => Promise<Response>;\n\ntype PromiseOrValue<T> = T | Promise<T>;\n\ntype APIResponseProps = {\n response: Response;\n options: FinalRequestOptions;\n controller: AbortController;\n};\n\nasync function defaultParseResponse<T>(props: APIResponseProps): Promise<WithRequestID<T>> {\n const { response } = props;\n if (props.options.stream) {\n debug('response', response.status, response.url, response.headers, response.body);\n\n // Note: there is an invariant here that isn't represented in the type system\n // that if you set `stream: true` the response type must also be `Stream<T>`\n\n if (props.options.__streamClass) {\n return props.options.__streamClass.fromSSEResponse(response, props.controller) as any;\n }\n\n return Stream.fromSSEResponse(response, props.controller) as any;\n }\n\n // fetch refuses to read the body when the status code is 204.\n if (response.status === 204) {\n return null as WithRequestID<T>;\n }\n\n if (props.options.__binaryResponse) {\n return response as unknown as WithRequestID<T>;\n }\n\n const contentType = response.headers.get('content-type');\n const isJSON =\n contentType?.includes('application/json') || contentType?.includes('application/vnd.api+json');\n if (isJSON) {\n const json = await response.json();\n\n debug('response', response.status, response.url, response.headers, json);\n\n return _addRequestID(json as T, response);\n }\n\n const text = await response.text();\n debug('response', response.status, response.url, response.headers, text);\n\n // TODO handle blob, arraybuffer, other content types, etc.\n return text as unknown as WithRequestID<T>;\n}\n\ntype WithRequestID<T> =\n T extends Array<any> | Response | AbstractPage<any> ? T\n : T extends Record<string, any> ? T & { _request_id?: string | null }\n : T;\n\nfunction _addRequestID<T>(value: T, response: Response): WithRequestID<T> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return value as WithRequestID<T>;\n }\n\n return Object.defineProperty(value, '_request_id', {\n value: response.headers.get('request-id'),\n enumerable: false,\n }) as WithRequestID<T>;\n}\n\n/**\n * A subclass of `Promise` providing additional helper methods\n * for interacting with the SDK.\n */\nexport class APIPromise<T> extends Promise<WithRequestID<T>> {\n private parsedPromise: Promise<WithRequestID<T>> | undefined;\n\n constructor(\n private responsePromise: Promise<APIResponseProps>,\n private parseResponse: (\n props: APIResponseProps,\n ) => PromiseOrValue<WithRequestID<T>> = defaultParseResponse,\n ) {\n super((resolve) => {\n // this is maybe a bit weird but this has to be a no-op to not implicitly\n // parse the response body; instead .then, .catch, .finally are overridden\n // to parse the response\n resolve(null as any);\n });\n }\n\n _thenUnwrap<U>(transform: (data: T, props: APIResponseProps) => U): APIPromise<U> {\n return new APIPromise(this.responsePromise, async (props) =>\n _addRequestID(transform(await this.parseResponse(props), props), props.response),\n );\n }\n\n /**\n * Gets the raw `Response` instance instead of parsing the response\n * data.\n *\n * If you want to parse the response body but still get the `Response`\n * instance, you can use {@link withResponse()}.\n *\n * \uD83D\uDC4B Getting the wrong TypeScript type for `Response`?\n * Try setting `\"moduleResolution\": \"NodeNext\"` if you can,\n * or add one of these imports before your first `import \u2026 from '@anthropic-ai/sdk'`:\n * - `import '@anthropic-ai/sdk/shims/node'` (if you're running on Node)\n * - `import '@anthropic-ai/sdk/shims/web'` (otherwise)\n */\n asResponse(): Promise<Response> {\n return this.responsePromise.then((p) => p.response);\n }\n\n /**\n * Gets the parsed response data, the raw `Response` instance and the ID of the request,\n * returned vie the `request-id` header which is useful for debugging requests and resporting\n * issues to Anthropic.\n *\n * If you just want to get the raw `Response` instance without parsing it,\n * you can use {@link asResponse()}.\n *\n * \uD83D\uDC4B Getting the wrong TypeScript type for `Response`?\n * Try setting `\"moduleResolution\": \"NodeNext\"` if you can,\n * or add one of these imports before your first `import \u2026 from '@anthropic-ai/sdk'`:\n * - `import '@anthropic-ai/sdk/shims/node'` (if you're running on Node)\n * - `import '@anthropic-ai/sdk/shims/web'` (otherwise)\n */\n async withResponse(): Promise<{ data: T; response: Response; request_id: string | null | undefined }> {\n const [data, response] = await Promise.all([this.parse(), this.asResponse()]);\n return { data, response, request_id: response.headers.get('request-id') };\n }\n\n private parse(): Promise<WithRequestID<T>> {\n if (!this.parsedPromise) {\n this.parsedPromise = this.responsePromise.then(this.parseResponse) as any as Promise<WithRequestID<T>>;\n }\n return this.parsedPromise;\n }\n\n override then<TResult1 = WithRequestID<T>, TResult2 = never>(\n onfulfilled?: ((value: WithRequestID<T>) => TResult1 | PromiseLike<TResult1>) | undefined | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null,\n ): Promise<TResult1 | TResult2> {\n return this.parse().then(onfulfilled, onrejected);\n }\n\n override catch<TResult = never>(\n onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null,\n ): Promise<WithRequestID<T> | TResult> {\n return this.parse().catch(onrejected);\n }\n\n override finally(onfinally?: (() => void) | undefined | null): Promise<WithRequestID<T>> {\n return this.parse().finally(onfinally);\n }\n}\n\nexport abstract class APIClient {\n baseURL: string;\n maxRetries: number;\n timeout: number;\n httpAgent: Agent | undefined;\n\n private fetch: Fetch;\n protected idempotencyHeader?: string;\n\n constructor({\n baseURL,\n maxRetries = 2,\n timeout = 600000, // 10 minutes\n httpAgent,\n fetch: overriddenFetch,\n }: {\n baseURL: string;\n maxRetries?: number | undefined;\n timeout: number | undefined;\n httpAgent: Agent | undefined;\n fetch: Fetch | undefined;\n }) {\n this.baseURL = baseURL;\n this.maxRetries = validatePositiveInteger('maxRetries', maxRetries);\n this.timeout = validatePositiveInteger('timeout', timeout);\n this.httpAgent = httpAgent;\n\n this.fetch = overriddenFetch ?? fetch;\n }\n\n protected authHeaders(opts: FinalRequestOptions): Headers {\n return {};\n }\n\n /**\n * Override this to add your own default headers, for example:\n *\n * {\n * ...super.defaultHeaders(),\n * Authorization: 'Bearer 123',\n * }\n */\n protected defaultHeaders(opts: FinalRequestOptions): Headers {\n return {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n 'User-Agent': this.getUserAgent(),\n ...getPlatformHeaders(),\n ...this.authHeaders(opts),\n };\n }\n\n protected abstract defaultQuery(): DefaultQuery | undefined;\n\n /**\n * Override this to add your own headers validation:\n */\n protected validateHeaders(headers: Headers, customHeaders: Headers) {}\n\n protected defaultIdempotencyKey(): string {\n return `stainless-node-retry-${uuid4()}`;\n }\n\n get<Req, Rsp>(path: string, opts?: PromiseOrValue<RequestOptions<Req>>): APIPromise<Rsp> {\n return this.methodRequest('get', path, opts);\n }\n\n post<Req, Rsp>(path: string, opts?: PromiseOrValue<RequestOptions<Req>>): APIPromise<Rsp> {\n return this.methodRequest('post', path, opts);\n }\n\n patch<Req, Rsp>(path: string, opts?: PromiseOrValue<RequestOptions<Req>>): APIPromise<Rsp> {\n return this.methodRequest('patch', path, opts);\n }\n\n put<Req, Rsp>(path: string, opts?: PromiseOrValue<RequestOptions<Req>>): APIPromise<Rsp> {\n return this.methodRequest('put', path, opts);\n }\n\n delete<Req, Rsp>(path: string, opts?: PromiseOrValue<RequestOptions<Req>>): APIPromise<Rsp> {\n return this.methodRequest('delete', path, opts);\n }\n\n private methodRequest<Req, Rsp>(\n method: HTTPMethod,\n path: string,\n opts?: PromiseOrValue<RequestOptions<Req>>,\n ): APIPromise<Rsp> {\n return this.request(\n Promise.resolve(opts).then(async (opts) => {\n const body =\n opts && isBlobLike(opts?.body) ? new DataView(await opts.body.arrayBuffer())\n : opts?.body instanceof DataView ? opts.body\n : opts?.body instanceof ArrayBuffer ? new DataView(opts.body)\n : opts && ArrayBuffer.isView(opts?.body) ? new DataView(opts.body.buffer)\n : opts?.body;\n return { method, path, ...opts, body };\n }),\n );\n }\n\n getAPIList<Item, PageClass extends AbstractPage<Item> = AbstractPage<Item>>(\n path: string,\n Page: new (...args: any[]) => PageClass,\n opts?: RequestOptions<any>,\n ): PagePromise<PageClass, Item> {\n return this.requestAPIList(Page, { method: 'get', path, ...opts });\n }\n\n private calculateContentLength(body: unknown): string | null {\n if (typeof body === 'string') {\n if (typeof Buffer !== 'undefined') {\n return Buffer.byteLength(body, 'utf8').toString();\n }\n\n if (typeof TextEncoder !== 'undefined') {\n const encoder = new TextEncoder();\n const encoded = encoder.encode(body);\n return encoded.length.toString();\n }\n } else if (ArrayBuffer.isView(body)) {\n return body.byteLength.toString();\n }\n\n return null;\n }\n\n buildRequest<Req>(\n options: FinalRequestOptions<Req>,\n { retryCount = 0 }: { retryCount?: number } = {},\n ): { req: RequestInit; url: stri