@flamai/finesse 0.0.0-stage → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/version.ts","../src/core.ts","../src/raw.ts","../src/realtime.ts","../src/resources/jobs.ts","../src/sse.ts","../src/resources/speech.ts","../src/resources/tokens.ts","../src/files.ts","../src/types.ts","../src/resources/voices.ts","../src/client.ts"],"sourcesContent":["export { Finesse } from \"./client.js\";\nexport type { ClientOptions, RequestOptions, LogLevel, Logger } from \"./core.js\";\nexport type { RawResponse, RawClient } from \"./raw.js\";\nexport {\n FinesseError,\n APIConnectionError,\n APITimeoutError,\n APIStatusError,\n BadRequestError,\n AuthenticationError,\n PaymentRequiredError,\n PermissionDeniedError,\n NotFoundError,\n ConflictError,\n PayloadTooLargeError,\n UnprocessableEntityError,\n RateLimitError,\n InternalServerError,\n StreamError,\n CloneFailedError,\n CloneTimeoutError,\n} from \"./errors.js\";\nexport { fileFromPath, type FileInput } from \"./files.js\";\nexport {\n RealtimeError,\n RealtimeSession,\n RealtimeContext,\n type RealtimeEvent,\n type UnknownEvent,\n type TaskStarted,\n type AudioEvent,\n type SentenceDone,\n type TaskDone,\n type TaskCancelled,\n type ContextOptions,\n type ConnectOptions,\n} from \"./realtime.js\";\nexport { VoicePage, VoicePagePromise } from \"./resources/voices.js\";\nexport type {\n ListVoicesParams,\n CreateVoiceParams,\n UpdateVoiceParams,\n CloneVoiceParams,\n EnrollVoiceParams,\n ConsentParams,\n} from \"./resources/voices.js\";\nexport type { CreateTokenParams } from \"./resources/tokens.js\";\nexport type { WaitOptions } from \"./resources/jobs.js\";\nexport { SpeechStream } from \"./resources/speech.js\";\nexport { isReady } from \"./types.js\";\nexport type {\n Voice,\n VoiceSettings,\n CloneJob,\n CloneResult,\n AccessToken,\n Audio,\n AudioChunk,\n StreamDone,\n SpeechParams,\n OutputFormat,\n} from \"./types.js\";\nexport { VERSION } from \"./version.js\";\n","/**\n * Errors thrown by the SDK. Every error extends {@link FinesseError}; HTTP errors extend\n * {@link APIStatusError} and are split by status so you can catch exactly what you handle:\n *\n * ```ts\n * try {\n * await client.speech.create({ voice_id, text: \"Hi\" });\n * } catch (e) {\n * if (e instanceof PaymentRequiredError) console.log(\"Out of credits\", e.billingRemaining);\n * }\n * ```\n */\n\nexport class FinesseError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = new.target.name;\n }\n}\n\n/** The request never got a response: DNS, TLS, connection reset, and so on. */\nexport class APIConnectionError extends FinesseError {}\n\n/** The request timed out. */\nexport class APITimeoutError extends APIConnectionError {\n constructor(options?: { cause?: unknown }) {\n super(\"Request timed out.\", options);\n }\n}\n\n/**\n * The API answered with a 4xx or 5xx status. The API's three error body shapes are normalised:\n *\n * - `{\"status\": 404, \"error\": true, \"message\": \"Voice not found\", \"code\": \"not_found\"}`\n * - `{\"error\": \"insufficient_credits\", \"unit\": \"character\", \"limit\": 100, \"used\": 100}`\n * - `{\"error\": \"plan limit reached\", \"feature\": \"max_voices\", \"limit\": 3}`\n */\nexport class APIStatusError extends FinesseError {\n /** HTTP status. */\n readonly status: number;\n /** Machine-readable code. Branch on this, never on the message. Envelope codes:\n * `invalid_request`, `unauthorized`, `key_expired`, `token_invalid`, `payment_required`,\n * `forbidden`, `insufficient_scope`, `voice_not_allowed`, `not_found`, `conflict`,\n * `idempotency_in_progress`, `payload_too_large`, `invalid_input`, `idempotency_key_reused`,\n * `rate_limited`, `concurrency_limited`, `internal_error`, `upstream_error`, `upstream_busy`,\n * `unavailable`; plan denials: `insufficient_credits`, `quota_exhausted`, `feature_disabled`,\n * `plan_limit_reached`; realtime: `too_many_sessions`. `null` when absent. */\n readonly code: string | null;\n /** The decoded JSON body, or the raw text when it is not JSON. */\n readonly body: unknown;\n readonly headers: Headers;\n /** `X-Billing-Remaining` as a number, when sent. */\n readonly billingRemaining: number | null;\n /** The service's `X-Request-Id` for the failed request; quote it to support. */\n readonly requestId: string | null;\n\n constructor(\n status: number,\n message: string,\n body: unknown,\n code: string | null,\n headers: Headers,\n ) {\n super(code && code !== message ? `${status}: ${message} (${code})` : `${status}: ${message}`);\n this.status = status;\n this.code = code;\n this.body = body;\n this.headers = headers;\n this.billingRemaining = intOrNull(headers.get(\"x-billing-remaining\"));\n const fromBody = (body as { request_id?: unknown } | null)?.request_id;\n this.requestId =\n headers.get(\"x-request-id\") ?? (typeof fromBody === \"string\" ? fromBody : null);\n }\n\n /** Seconds the server asked you to wait (`Retry-After`), when it sent one. */\n get retryAfter(): number | null {\n const v = this.headers.get(\"retry-after\");\n if (v === null) return null;\n const n = Number(v);\n return Number.isFinite(n) ? n : null;\n }\n\n /** Plan limit from an entitlement or plan-limit denial, when present. */\n get limit(): number | null {\n return numberField(this.body, \"limit\");\n }\n\n /** Amount already used, from an entitlement denial, when present. */\n get used(): number | null {\n return numberField(this.body, \"used\");\n }\n}\n\n/** 400: invalid request (missing field, text too long, voice not enrolled, ...). */\nexport class BadRequestError extends APIStatusError {}\n/** 401: the API key is missing, unknown or revoked; `key_expired`; or a short-lived token is\n * invalid, expired or already used (`token_invalid`). */\nexport class AuthenticationError extends APIStatusError {}\n/** 402: out of credits (`insufficient_credits`) or quota (`quota_exhausted`), or another\n * payment problem (`payment_required`). */\nexport class PaymentRequiredError extends APIStatusError {}\n/** 403: the key lacks the route's scope (`insufficient_scope`), a token is limited to other\n * voices (`voice_not_allowed`), the plan lacks the feature (`feature_disabled`), or a cap is\n * reached (`plan_limit_reached`). */\nexport class PermissionDeniedError extends APIStatusError {\n /** The capped feature for `plan_limit_reached`, e.g. `max_voices`. */\n get feature(): string | null {\n const b = this.body as Record<string, unknown> | null;\n return b && typeof b === \"object\" && typeof b.feature === \"string\" ? b.feature : null;\n }\n}\n/** 404: no such resource, or not visible to this workspace. */\nexport class NotFoundError extends APIStatusError {}\n/** 409: e.g. a request with the same `Idempotency-Key` is still running. */\nexport class ConflictError extends APIStatusError {}\n/** 413: the request body is over 21 MiB (`payload_too_large`). */\nexport class PayloadTooLargeError extends APIStatusError {}\n/** 422: the synthesis service could not use the input (`invalid_input`), or an\n * `Idempotency-Key` was reused for a different request (`idempotency_key_reused`). */\nexport class UnprocessableEntityError extends APIStatusError {}\n/** 429: over the plan's requests per second (`rate_limited`) or concurrent synthesis\n * (`concurrency_limited`), or (realtime) `too_many_sessions`. Wait `retryAfter` seconds. */\nexport class RateLimitError extends APIStatusError {}\n/** 5xx: a server error, or the synthesis service failing (`upstream_error`, 502) or at\n * capacity (`upstream_busy`, 503, with `retryAfter`). Usually safe to retry. */\nexport class InternalServerError extends APIStatusError {}\n\n/** A speech stream failed after it started. */\nexport class StreamError extends FinesseError {\n readonly code: string;\n constructor(code: string, message = \"\") {\n super(message ? `${message} (${code})` : code);\n this.code = code;\n }\n}\n\n/** A clone job ended without producing a ready voice. */\nexport class CloneFailedError extends FinesseError {\n readonly job: { id: string; status: string; error?: Record<string, unknown> | null };\n constructor(job: { id: string; status: string; error?: Record<string, unknown> | null }) {\n const reason = typeof job.error?.message === \"string\" ? `: ${job.error.message}` : \"\";\n super(`Clone job ${job.id} ${job.status}${reason}`);\n this.job = job;\n }\n}\n\n/** Waiting for a clone job took longer than the timeout. The job may still finish. */\nexport class CloneTimeoutError extends FinesseError {\n constructor(\n readonly jobId: string,\n readonly timeoutMs: number,\n ) {\n super(`Clone job ${jobId} did not finish within ${timeoutMs / 1000}s`);\n }\n}\n\nconst MAX_MESSAGE = 300;\n\nconst STATUS_ERRORS: Record<number, typeof APIStatusError> = {\n 400: BadRequestError,\n 401: AuthenticationError,\n 402: PaymentRequiredError,\n 403: PermissionDeniedError,\n 404: NotFoundError,\n 409: ConflictError,\n 413: PayloadTooLargeError,\n 422: UnprocessableEntityError,\n 429: RateLimitError,\n};\n\n/** Build the right {@link APIStatusError} subclass from an error status and its body text. */\nexport function makeStatusError(\n status: number,\n text: string,\n headers: Headers,\n statusText = \"\",\n): APIStatusError {\n let body: unknown = text;\n try {\n body = text ? JSON.parse(text) : text;\n } catch {\n /* not JSON */\n }\n let message: string | null = null;\n let code: string | null = null;\n if (body && typeof body === \"object\" && !Array.isArray(body)) {\n const b = body as Record<string, unknown>;\n if (typeof b.message === \"string\" && b.message) {\n message = b.message;\n // The credit check inside synthesis sends the code as the message.\n if (/^[a-z]+(_[a-z]+)+$/.test(b.message)) code = b.message;\n }\n if (typeof b.code === \"string\" && b.code) {\n // It also sends the generic `payment_required` code; keep the specific one.\n if (!(status === 402 && b.message === \"insufficient_credits\")) code = b.code;\n } else if (typeof b.error === \"string\" && b.error) {\n code = b.error === \"plan limit reached\" ? \"plan_limit_reached\" : b.error;\n message ??= b.error.replace(/_/g, \" \");\n } else if (b.error && typeof b.error === \"object\") {\n const e = b.error as Record<string, unknown>;\n if (typeof e.message === \"string\" && e.message) message = e.message;\n if (typeof e.code === \"string\" && e.code) code = e.code;\n }\n } else if (typeof body === \"string\" && body.trim()) {\n const flat = body.split(/\\s+/).join(\" \").trim();\n message = flat.length <= MAX_MESSAGE ? flat : flat.slice(0, MAX_MESSAGE - 3) + \"...\";\n }\n message ||= statusText || `HTTP ${status}`;\n const Cls = STATUS_ERRORS[status] ?? (status >= 500 ? InternalServerError : APIStatusError);\n return new Cls(status, message, body, code, headers);\n}\n\nfunction intOrNull(value: string | null): number | null {\n if (value === null) return null;\n const n = Number(value);\n return Number.isInteger(n) ? n : null;\n}\n\nfunction numberField(body: unknown, key: string): number | null {\n if (body && typeof body === \"object\") {\n const v = (body as Record<string, unknown>)[key];\n if (typeof v === \"number\") return v;\n }\n return null;\n}\n","export const VERSION = \"0.1.2\";\n","import { APIConnectionError, APITimeoutError, FinesseError, makeStatusError } from \"./errors.js\";\nimport { VERSION } from \"./version.js\";\n\nexport const DEFAULT_BASE_URL = \"https://fi.production.flamapis.com\";\nexport const API_PREFIX = \"/flam-voice-svc/api/v1/public\";\n/** Synthesis on a cold GPU can take tens of seconds before the first byte. */\nexport const DEFAULT_TIMEOUT_MS = 120_000;\nexport const DEFAULT_MAX_RETRIES = 2;\nexport const CLIENT_NAME = `flam-finesse-node/${VERSION}`;\n\n// GET/PATCH/DELETE are safe to repeat: retry timeouts, 429 (the engine's rate limit) and 5xx.\nconst RETRY_STATUSES = new Set([408, 429, 500, 502, 503, 504]);\n// POSTs create voices and bill synthesis. Only retry when the server certainly did no work:\n// 429, 502 (engine unavailable or warming up; failed synthesis is refunded) and 503, or when\n// the connection never opened. A timeout after the request was sent is not retried.\nconst POST_RETRY_STATUSES = new Set([429, 502, 503]);\n// A short-lived token is spent just before the handler runs, so any later failure leaves it\n// used and a retry would only get 401 token_invalid. Only 429 is refused before the spend.\nconst TOKEN_RETRY_STATUSES = new Set([429]);\nconst UNSENT_CODES = new Set([\"ECONNREFUSED\", \"ENOTFOUND\", \"EAI_AGAIN\", \"UND_ERR_CONNECT_TIMEOUT\"]);\nconst MAX_BACKOFF_MS = 8_000;\n\nexport type Fetch = typeof globalThis.fetch;\n\nexport interface ClientOptions {\n /** Workspace API key (`flv_...`). Defaults to `FINESSE_API_KEY`. Keep it on your server. */\n apiKey?: string;\n /** A short-lived token (`fin_tok_...`) from `tokens.create`, instead of an API key. It is\n * safe in a browser: it carries the `tts` scope only and is good for one `speech.create` /\n * `speech.stream` call or one realtime session. Sent as `Authorization: Bearer`. */\n accessToken?: string;\n /** API host. Defaults to `FINESSE_BASE_URL`, then production. */\n baseURL?: string;\n /** Per-request timeout in ms. Default 120 000. */\n timeout?: number;\n /** Retries for transient failures. Default 2. Reads, updates and deletes retry on network\n * errors, timeouts, 408, 429 and 5xx. Creates, uploads and synthesis retry only when the\n * server did no work: the connection never opened, 429, 502 or 503. With an `accessToken`\n * only 429 and a connection that never opened are retried, since the token is single use. */\n maxRetries?: number;\n /** Extra headers sent on every request. */\n defaultHeaders?: Record<string, string>;\n /** A custom `fetch` (proxies, tests). */\n fetch?: Fetch;\n /** Allow an API key in a browser. The key would be visible to anyone using the page, so\n * only do this for internal tools; otherwise use an `accessToken`. */\n dangerouslyAllowBrowser?: boolean;\n /** Log requests and retries: `\"debug\"`, `\"info\"` or `\"off\"`. Defaults to `FINESSE_LOG`, then\n * `\"off\"`. The API key, bodies and audio are never logged. */\n logLevel?: LogLevel;\n /** Where log lines go. Defaults to `console`. */\n logger?: Logger;\n}\n\nexport type LogLevel = \"debug\" | \"info\" | \"off\";\n\nexport interface Logger {\n debug(message: string): void;\n info(message: string): void;\n}\n\n/** Per-call overrides that every request method accepts as its last argument. */\nexport interface RequestOptions {\n /** Abort the request, its retries and any waiting. Rejects with the signal's reason. */\n signal?: AbortSignal;\n /** Timeout in ms for this call (for streams, the longest wait between chunks). */\n timeout?: number;\n /** Retries for this call. */\n maxRetries?: number;\n /** Extra headers for this call; they override the client's. */\n headers?: Record<string, string>;\n}\n\ninterface CallOptions extends RequestOptions {\n /** Send one Idempotency-Key for every attempt, so the call can be retried like a read. */\n idempotent?: boolean;\n query?: Record<string, string | number>;\n json?: unknown;\n form?: () => FormData;\n stream?: boolean;\n}\n\nfunction env(name: string): string | undefined {\n const proc = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process;\n return proc?.env?.[name];\n}\n\nexport function isBrowser(): boolean {\n return (\n typeof (globalThis as { window?: unknown }).window !== \"undefined\" &&\n typeof (globalThis as { document?: unknown }).document !== \"undefined\"\n );\n}\n\nexport class Core {\n readonly apiKey: string | null;\n readonly accessToken: string | null;\n readonly baseURL: string;\n readonly timeout: number;\n readonly maxRetries: number;\n readonly headers: Record<string, string>;\n readonly fetch: Fetch;\n readonly logLevel: LogLevel;\n readonly logger: Logger;\n /** @internal What this client learned about the server; shared by `withOptions` copies. */\n readonly server = { honoursIdempotencyKeys: false };\n /** @internal Called with each successful response (used by `withRawResponse`). */\n onResponse: ((response: Response) => void) | null = null;\n\n constructor(options: ClientOptions = {}) {\n if (options.apiKey && options.accessToken) {\n throw new FinesseError(\"Pass { apiKey } or { accessToken }, not both.\");\n }\n const accessToken = options.accessToken || null;\n const apiKey = accessToken ? null : (options.apiKey ?? env(\"FINESSE_API_KEY\") ?? null);\n if (!accessToken && !apiKey) {\n throw new FinesseError(\n \"No API key. Pass { apiKey } or set the FINESSE_API_KEY environment variable \" +\n \"(or pass { accessToken } for a short-lived token).\",\n );\n }\n if (apiKey && isBrowser() && !options.dangerouslyAllowBrowser) {\n throw new FinesseError(\n \"Running in a browser would expose your API key. Mint a short-lived token on your \" +\n \"server (tokens.create) and pass { accessToken }, or pass \" +\n \"{ dangerouslyAllowBrowser: true } for internal tools.\",\n );\n }\n this.apiKey = apiKey;\n this.accessToken = accessToken;\n this.baseURL = (options.baseURL || env(\"FINESSE_BASE_URL\") || DEFAULT_BASE_URL).replace(\n /\\/+$/,\n \"\",\n );\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;\n this.maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;\n this.headers = {\n ...(accessToken ? { Authorization: `Bearer ${accessToken}` } : { \"X-API-Key\": apiKey! }),\n \"X-Finesse-Client\": CLIENT_NAME,\n Accept: \"application/json\",\n ...(isBrowser() ? {} : { \"User-Agent\": CLIENT_NAME }),\n ...options.defaultHeaders,\n };\n const f = options.fetch ?? globalThis.fetch;\n if (!f)\n throw new FinesseError(\"No fetch available. Pass { fetch } (Node 18+ has one built in).\");\n this.fetch = f.bind(globalThis);\n const level = (options.logLevel ?? env(\"FINESSE_LOG\")?.toLowerCase() ?? \"off\") as LogLevel;\n this.logLevel = level === \"debug\" || level === \"info\" ? level : \"off\";\n this.logger = options.logger ?? console;\n }\n\n /** @internal A view of this core with other defaults, sharing everything else. */\n withOptions(overrides: {\n timeout?: number;\n maxRetries?: number;\n headers?: Record<string, string>;\n }): Core {\n const view = Object.create(Object.getPrototypeOf(this)) as Core;\n Object.assign(view, this, {\n timeout: overrides.timeout ?? this.timeout,\n maxRetries: overrides.maxRetries ?? this.maxRetries,\n headers: { ...this.headers, ...overrides.headers },\n });\n return view;\n }\n\n private debug(message: string): void {\n if (this.logLevel === \"debug\") this.logger.debug(`[finesse] ${message}`);\n }\n\n private info(message: string): void {\n if (this.logLevel !== \"off\") this.logger.info(`[finesse] ${message}`);\n }\n\n url(path: string, query?: Record<string, string | number>): string {\n const url = new URL(`${this.baseURL}${API_PREFIX}${path}`);\n for (const [k, v] of Object.entries(query ?? {})) url.searchParams.set(k, String(v));\n return url.toString();\n }\n\n get wsBaseURL(): string {\n return this.baseURL.replace(/^http(s?):\\/\\//, \"ws$1://\");\n }\n\n /** Send a request, retrying transient failures, and throw on an error status. With\n * `stream: true` the caller owns the response body. A caller `signal` stops the request and\n * any further retries, and rejects with the signal's reason. */\n async request(method: string, path: string, opts: CallOptions = {}): Promise<Response> {\n const { signal } = opts;\n const timeout = opts.timeout ?? this.timeout;\n const maxRetries = opts.maxRetries ?? this.maxRetries;\n // An idempotent call carries one key for all of its attempts (the caller's, if they set\n // one), so the server runs it at most once and every failure is safe to retry.\n const baseHeaders: Record<string, string> = { ...this.headers, ...opts.headers };\n let key: string | null = null;\n if (opts.idempotent && method === \"POST\") {\n const own = Object.keys(baseHeaders).find((k) => k.toLowerCase() === \"idempotency-key\");\n key = own ? baseHeaders[own]! : randomUUID();\n if (!own) baseHeaders[\"Idempotency-Key\"] = key;\n }\n // A keyed POST is retried like a read only once the server has shown it honours keys by\n // echoing one back; until then (an older server) it keeps the cautious POST rules.\n const retryAs = (response: Response | null): string => {\n if (key === null) return method;\n if (response?.headers.get(\"idempotency-key\") === key)\n this.server.honoursIdempotencyKeys = true;\n return this.server.honoursIdempotencyKeys ? \"GET\" : method;\n };\n let inProgressUntil: number | null = null;\n for (let attempt = 0; ; attempt++) {\n throwIfAborted(signal);\n const headers: Record<string, string> = { ...baseHeaders };\n let body: BodyInit | undefined;\n if (opts.json !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n body = JSON.stringify(opts.json);\n } else if (opts.form) {\n body = opts.form(); // rebuilt per attempt; fetch sets the multipart boundary\n }\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(new TimeoutSignal()), timeout);\n const onAbort = () => controller.abort(signal?.reason);\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n const release = () => {\n clearTimeout(timer);\n signal?.removeEventListener(\"abort\", onAbort);\n };\n // Returns when the failed attempt should be retried; throws otherwise.\n const retryAfterError = async (err: unknown, sent: boolean): Promise<void> => {\n throwIfAborted(signal);\n const timedOut = controller.signal.reason instanceof TimeoutSignal;\n const cautious = this.accessToken !== null || retryAs(null) === \"POST\";\n const retry = !cautious || (!sent && !timedOut && isUnsent(err));\n if (attempt < maxRetries && retry) {\n await sleep(retryDelay(attempt, null), signal);\n return;\n }\n if (timedOut) throw new APITimeoutError({ cause: err });\n throw new APIConnectionError(errorMessage(err), { cause: err });\n };\n\n const url = this.url(path, opts.query);\n const where = `${method} ${url.split(\"?\")[0]}`;\n const started = Date.now();\n let response: Response;\n try {\n response = await this.fetch(url, {\n method,\n headers,\n body,\n signal: controller.signal,\n });\n } catch (err) {\n release();\n await retryAfterError(err, false);\n this.info(`retrying ${where} (attempt ${attempt + 1} failed: ${errorMessage(err)})`);\n continue;\n }\n retryAs(response); // learn whether this server honours keys\n this.debug(\n `${where} -> ${response.status} in ${Date.now() - started} ms` +\n (attempt ? `, attempt ${attempt + 1}` : \"\") +\n ` (request id ${response.headers.get(\"x-request-id\") ?? \"-\"})`,\n );\n\n if (response.ok && opts.stream) {\n // From here the stream reader applies the timeout between chunks instead, so a long\n // stream is not cut off. The caller's signal still aborts it until it is released.\n clearTimeout(timer);\n streamCleanups.set(response, () => signal?.removeEventListener(\"abort\", onAbort));\n this.onResponse?.(response);\n return response;\n }\n // Read the whole body while the timeout still applies.\n let buffer: ArrayBuffer;\n try {\n buffer = await response.arrayBuffer();\n } catch (err) {\n release();\n await retryAfterError(err, true);\n this.info(`retrying ${where} (attempt ${attempt + 1} failed: ${errorMessage(err)})`);\n continue;\n }\n release();\n if (response.ok) {\n const empty = response.status === 204 || response.status === 205 || response.status === 304;\n const buffered = new Response(empty ? null : buffer, {\n status: response.status,\n headers: response.headers,\n });\n this.onResponse?.(buffered);\n return buffered;\n }\n const text = new TextDecoder().decode(buffer);\n\n if (key !== null && response.status === 409 && isInProgress(text)) {\n // The first attempt is still running on the server: wait for it, for as long as a\n // single request may take, without spending a retry.\n inProgressUntil ??= Date.now() + timeout;\n if (Date.now() < inProgressUntil) {\n const delay = retryDelay(0, response);\n this.info(`waiting for ${where}: the first attempt is still running`);\n await sleep(delay, signal);\n attempt--;\n continue;\n }\n }\n const statuses =\n this.accessToken !== null\n ? TOKEN_RETRY_STATUSES\n : retryAs(response) === \"POST\"\n ? POST_RETRY_STATUSES\n : RETRY_STATUSES;\n if (attempt < maxRetries && statuses.has(response.status)) {\n const delay = retryDelay(attempt, response);\n this.info(\n `retrying ${where} in ${Math.round(delay)} ms (attempt ${attempt + 1} failed: HTTP ${response.status})`,\n );\n await sleep(delay, signal);\n continue;\n }\n throw makeStatusError(response.status, text, response.headers, response.statusText);\n }\n }\n\n /** Request and decode a JSON success body, stripping the `{status, error, data}` envelope. */\n async json<T>(method: string, path: string, opts: CallOptions = {}): Promise<T> {\n const response = await this.request(method, path, opts);\n return unwrap(await response.json()) as T;\n }\n}\n\n/** Called by stream readers once they finish with a streamed response. */\nexport const streamCleanups = new WeakMap<Response, () => void>();\n\nexport function releaseStream(response: Response): void {\n streamCleanups.get(response)?.();\n streamCleanups.delete(response);\n}\n\nclass TimeoutSignal extends Error {}\n\nfunction isInProgress(text: string): boolean {\n try {\n return (JSON.parse(text) as { code?: unknown })?.code === \"idempotency_in_progress\";\n } catch {\n return false;\n }\n}\n\nfunction randomUUID(): string {\n const c = (globalThis as { crypto?: Crypto }).crypto;\n if (c?.randomUUID) return c.randomUUID();\n const b = new Uint8Array(16);\n if (c?.getRandomValues) c.getRandomValues(b);\n else for (let i = 0; i < 16; i++) b[i] = Math.floor(Math.random() * 256);\n b[6] = (b[6]! & 0x0f) | 0x40;\n b[8] = (b[8]! & 0x3f) | 0x80;\n const h = Array.from(b, (x) => x.toString(16).padStart(2, \"0\")).join(\"\");\n return `${h.slice(0, 8)}-${h.slice(8, 12)}-${h.slice(12, 16)}-${h.slice(16, 20)}-${h.slice(20)}`;\n}\n\nexport function unwrap(body: unknown): unknown {\n if (\n body &&\n typeof body === \"object\" &&\n \"data\" in body &&\n (body as { error?: unknown }).error === false\n ) {\n return (body as { data: unknown }).data;\n }\n return body;\n}\n\nfunction isUnsent(err: unknown): boolean {\n let e: unknown = err;\n for (let i = 0; i < 4 && e; i++) {\n const code = (e as { code?: unknown }).code;\n if (typeof code === \"string\" && UNSENT_CODES.has(code)) return true;\n e = (e as { cause?: unknown }).cause;\n }\n return false;\n}\n\nfunction errorMessage(err: unknown): string {\n const cause = (err as { cause?: { message?: string } })?.cause?.message;\n return cause || (err instanceof Error ? err.message : \"\") || \"Connection error.\";\n}\n\nexport function retryDelay(attempt: number, response: Response | null): number {\n const retryAfter = response?.headers.get(\"retry-after\");\n if (retryAfter) {\n let ms = Number(retryAfter) * 1000;\n if (Number.isNaN(ms)) ms = Date.parse(retryAfter) - Date.now();\n if (ms >= 0 && ms <= 60_000) return ms;\n }\n const base = Math.min(500 * 2 ** attempt, MAX_BACKOFF_MS);\n return base * (1 - 0.25 * Math.random());\n}\n\nlet wait = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\n/** Sleep `ms`, rejecting with the signal's reason if it aborts first. */\nexport async function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n throwIfAborted(signal);\n if (!signal) return wait(ms);\n let onAbort: () => void = () => undefined;\n const aborted = new Promise<never>((_, reject) => {\n onAbort = () => reject(abortReason(signal));\n signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n try {\n await Promise.race([wait(ms), aborted]);\n } finally {\n signal.removeEventListener(\"abort\", onAbort);\n }\n}\n\n/** Test seam: replace the backoff wait. */\nexport function _setSleep(fn: (ms: number) => Promise<void>): void {\n wait = fn;\n}\n\nexport function abortReason(signal: AbortSignal): unknown {\n return signal.reason ?? new DOMException(\"This operation was aborted.\", \"AbortError\");\n}\n\nexport function throwIfAborted(signal?: AbortSignal): void {\n if (signal?.aborted) throw abortReason(signal);\n}\n\n/** Escape an id for use as one URL path segment, so it cannot change the route. */\nexport function pathId(value: string): string {\n if (value === \"\" || value === \".\" || value === \"..\") {\n throw new FinesseError(`Invalid id: ${JSON.stringify(value)}`);\n }\n return encodeURIComponent(value);\n}\n","import type { Core } from \"./core.js\";\nimport { FinesseError } from \"./errors.js\";\n\n/** The parsed result of a call plus the HTTP response it came from. For calls that make several\n * requests (`voices.list` walking pages, `cloneAndWait` polling), `response` is the first one. */\nexport interface RawResponse<T> {\n data: T;\n response: Response;\n status: number;\n headers: Headers;\n /** The service's `X-Request-Id` for this request, when sent. */\n requestId: string | null;\n}\n\ntype Fn = (...args: never[]) => unknown;\ntype RawMethods<R> = {\n [M in keyof R as R[M] extends Fn ? (M extends \"stream\" ? never : M) : never]: R[M] extends (\n ...args: infer A\n ) => infer Ret\n ? (...args: A) => Promise<RawResponse<Awaited<Ret>>>\n : never;\n};\n\nexport interface Resources {\n voices: object;\n jobs: object;\n speech: object;\n}\n\n/** `client.withRawResponse`: the same methods, each resolving to a {@link RawResponse}. */\nexport type RawClient<R extends Resources> = { [K in keyof R]: RawMethods<R[K]> };\n\nexport function rawClient<R extends Resources>(core: Core, build: (core: Core) => R): RawClient<R> {\n const namespace = (name: keyof R) =>\n new Proxy(\n {},\n {\n get(_target, method) {\n if (typeof method !== \"string\") return undefined;\n if (method === \"stream\") {\n throw new FinesseError(\n \"speech.stream has no raw form: read headers from the stream itself \" +\n \"(stream.billingRemaining, stream.done) instead.\",\n );\n }\n return async (...args: unknown[]) => {\n const seen: Response[] = [];\n const view = core.withOptions({});\n view.onResponse = (r) => seen.push(r);\n const resource = build(view)[name] as Record<string, (...a: unknown[]) => unknown>;\n const fn = resource[method];\n if (typeof fn !== \"function\")\n throw new FinesseError(`No method ${String(name)}.${method}`);\n const data = await fn.apply(resource, args);\n const response = seen[0];\n if (!response) throw new FinesseError(\"This call made no HTTP request.\");\n return {\n data,\n response,\n status: response.status,\n headers: response.headers,\n requestId: response.headers.get(\"x-request-id\"),\n };\n };\n },\n },\n );\n // One namespace per resource the client builds, so a new resource gets a raw form for free.\n const names = Object.keys(build(core)) as (keyof R)[];\n return Object.fromEntries(names.map((name) => [name, namespace(name)])) as RawClient<R>;\n}\n","/**\n * Realtime speech over one WebSocket. One session is one socket; each turn of speech runs in a\n * *context*, and a socket can run several contexts at once (up to 4). Audio arrives as raw PCM,\n * `s16le` at 24 kHz unless you ask for something else.\n *\n * ```ts\n * const rt = await client.realtime.connect();\n * for await (const event of rt.say({ voice_id, text: \"Hello there.\" })) {\n * if (event.type === \"audio\") play(event.pcm);\n * }\n * await rt.close();\n * ```\n *\n * In Node this needs the `ws` package (`npm i ws`), which sends the API key as a header. Bun's\n * built-in WebSocket does too, and so does Deno's from 2.5.\n *\n * In a browser, never use the API key: mint a short-lived token on your server\n * (`tokens.create`) and connect with `{ accessToken }` or `{ getAccessToken }`. The token rides\n * in the WebSocket subprotocol list (`[\"finesse.v1\", token]`), the one place a browser can put\n * a credential on a handshake. (With a key, browsers and Deno before 2.5 fall back to a\n * deprecated URL parameter, and the SDK logs a warning once.)\n */\n\nimport { API_PREFIX, isBrowser, type Core, type Logger } from \"./core.js\";\nimport { APIConnectionError, APITimeoutError, FinesseError, makeStatusError } from \"./errors.js\";\n\nexport const DEFAULT_OPEN_TIMEOUT_MS = 60_000;\n/** The protocol the service selects. A short-lived token travels as a second subprotocol. */\nexport const SUBPROTOCOL = \"finesse.v1\";\nconst CLOSE_TIMEOUT_MS = 5_000;\n/** The service closes the socket (1009) on a client frame over 1 MiB, ending every context. */\nexport const MAX_FRAME_BYTES = 1 << 20;\n\n// Going Away, abnormal closure, internal error, service restart, try again later, engine busy.\nconst RETRYABLE_CLOSES = new Set([1001, 1006, 1011, 1012, 1013, 4429]);\nconst RETRYABLE_CODES = new Set([\n \"upstream_closed\",\n \"upstream_error\",\n \"upstream_busy\",\n \"upstream_unavailable\",\n \"connection_lost\",\n \"service_busy\",\n \"stream_billing_error\",\n]);\n\n/** A realtime context or session failed. */\nexport class RealtimeError extends FinesseError {\n /** Per context: `voice_not_found`, `voice_not_allowed` (the token is limited to other\n * voices), `invalid_request` (a parameter out of range), a `task_failed` code. Whole session:\n * `insufficient_credits`, `upstream_unavailable` (the engine could not be reached),\n * `upstream_busy` (it is at capacity), `upstream_error`, `upstream_closed`,\n * `connection_lost`, `token_spent`, ... */\n readonly code: string;\n /** The context it applies to, or `null` for the whole session. */\n readonly contextId: string | null;\n /** The WebSocket close code, when the socket closed. */\n closeCode: number | null;\n\n constructor(\n code: string,\n message = \"\",\n options: { contextId?: string | null; closeCode?: number | null } = {},\n ) {\n super(message && message !== code ? `${message} (${code})` : code);\n this.code = code;\n this.contextId = options.contextId ?? null;\n this.closeCode = options.closeCode ?? null;\n }\n\n /** Whether reconnecting and trying again can succeed. */\n get retryable(): boolean {\n return (\n RETRYABLE_CODES.has(this.code) ||\n (this.closeCode !== null && RETRYABLE_CLOSES.has(this.closeCode))\n );\n }\n}\n\nfunction closeError(code: number | null, reason: string): RealtimeError | null {\n const c = { closeCode: code };\n if (code === 1000) return null;\n if (code === 1008) return new RealtimeError(reason || \"policy_violation\", reason, c);\n if (code === 1009) return new RealtimeError(\"message_too_big\", \"A message was too large.\", c);\n // reason: upstream_error, upstream_closed or stream_billing_error\n if (code === 1011) return new RealtimeError(reason || \"upstream_closed\", reason, c);\n if (code === 1013 && (reason === \"upstream_busy\" || reason === \"upstream_unavailable\")) {\n return new RealtimeError(\n reason,\n reason === \"upstream_busy\"\n ? \"The synthesis service is at capacity.\"\n : \"The synthesis service could not be reached.\",\n c,\n );\n }\n // 4401 / 4429 come only from older services; current ones map them to 1011 / 1013.\n if (code === 4401) {\n return new RealtimeError(\n \"service_auth_failed\",\n \"The service could not start the session (a problem on our side).\",\n c,\n );\n }\n if (code === 4429) {\n return new RealtimeError(\n \"service_busy\",\n \"The service is at its connection limit. Try again shortly.\",\n c,\n );\n }\n if (code === null || code === 1005 || code === 1006) {\n return new RealtimeError(\"connection_lost\", \"The connection dropped.\", { closeCode: 1006 });\n }\n if (code === 1001 || code === 1012 || code === 1013) {\n return new RealtimeError(\n \"connection_lost\",\n \"The service closed the connection (restart or overload).\",\n c,\n );\n }\n return new RealtimeError(reason || \"connection_closed\", reason, c);\n}\n\nexport interface TaskStarted {\n type: \"task_started\";\n context_id: string;\n sample_rate?: number;\n audio_format?: string;\n}\nexport interface AudioEvent {\n type: \"audio\";\n context_id: string;\n /** Raw PCM in the context's `audio_format` / `sample_rate`. */\n pcm: Uint8Array;\n sample_rate: number | null;\n audio_format: string | null;\n sentence_index?: number;\n chunk_index?: number;\n audio_duration_s?: number;\n}\nexport interface SentenceDone {\n type: \"sentence_done\";\n context_id: string;\n sentence_index?: number;\n text?: string;\n audio_duration_s?: number;\n}\n/** The context finished. Last event of a context. */\nexport interface TaskDone {\n type: \"task_done\";\n context_id: string;\n num_sentences?: number;\n total_audio_duration_s?: number;\n profile?: Record<string, unknown>;\n trace_id?: string;\n}\n/** The context was cancelled. Last event of a cancelled context. */\nexport interface TaskCancelled {\n type: \"task_cancelled\";\n context_id: string;\n sentences_completed?: number;\n sentences_dropped?: number;\n trace_id?: string;\n}\n/** An engine event this SDK version does not know yet. `event_type` is its `type` on the wire\n * and `data` the whole frame. */\nexport interface UnknownEvent {\n type: \"unknown\";\n context_id: string;\n event_type: string;\n data: Record<string, unknown>;\n}\n/** Every event a context yields. Narrow it on `type`. */\nexport type RealtimeEvent =\n TaskStarted | AudioEvent | SentenceDone | TaskDone | TaskCancelled | UnknownEvent;\n\nexport interface ContextOptions {\n /** One of your voices or a public platform voice. */\n voice_id: string;\n context_id?: string;\n language?: string;\n /** `s16le` (default), `s24le`, `s32le`, `f32le`, `f64le`, `opus`, or `mulaw` (G.711 µ-law\n * for telephony, with `sample_rate: 8000`). */\n output_format?: \"s16le\" | \"s24le\" | \"s32le\" | \"f32le\" | \"f64le\" | \"opus\" | \"mulaw\";\n /** Output rate in Hz, 8000-48000; the native rate is 24000. 8000 is produced as asked, other\n * lower values still produce 24000. */\n sample_rate?: number;\n /** Generation steps, 1-32 (default 32); fewer is faster. Values over 32 are capped. */\n num_step?: number;\n guidance_scale?: number;\n /** Speaking rate. */\n length_scale?: number;\n /** Speak a pending sentence after this many ms without new text. */\n idle_flush_ms?: number;\n}\n\nexport interface ConnectOptions {\n /** Reconnect on the next context after a retryable drop. Default true. */\n autoReconnect?: boolean;\n /** Ms to open the socket. Default 60 000. */\n openTimeout?: number;\n /** A short-lived token (`fin_tok_...`) for this session instead of the API key (defaults to\n * the client's `accessToken`). Single use: the handshake spends it, so pass\n * `getAccessToken` too if the session should reconnect. */\n accessToken?: string;\n /** Returns a fresh token, e.g. from your own backend running `tokens.create`. Used for the\n * first handshake when there is no `accessToken`, and for every reconnect. */\n getAccessToken?: () => string | Promise<string>;\n /** A WebSocket implementation (defaults to the `ws` package in Node, the global elsewhere). */\n WebSocket?: unknown;\n}\n\nconst END = Symbol(\"end\");\nconst KNOWN_EVENTS = new Set([\"task_started\", \"sentence_done\", \"task_done\", \"task_cancelled\"]);\ntype Item = RealtimeEvent | RealtimeError | typeof END;\n\n/**\n * One turn of speech. Create it with {@link RealtimeSession.context}. `send` text (the first\n * call opens the context), `finish` when the turn's text is complete, and iterate it for its\n * events. Iteration ends after `task_done` or `task_cancelled`, and throws\n * {@link RealtimeError} if the context fails.\n *\n * Events are buffered without limit so that one slow context never stalls the others on the\n * same socket. Iterate every context you start, or `cancel()` the ones you abandon. Iterate a\n * context from one place only: events are consumed as they are read.\n */\nexport class RealtimeContext implements AsyncIterable<RealtimeEvent> {\n readonly id: string;\n cancelled = false;\n sampleRate: number | null = null;\n audioFormat: string | null = null;\n /** @internal */ started = false;\n /** @internal The socket this context runs on. */ socket: unknown = null;\n /** @internal */ ended = false;\n private finished = false;\n private readonly items: Item[] = [];\n private waiter: (() => void) | null = null;\n private sending: Promise<unknown> = Promise.resolve();\n\n constructor(\n private readonly session: RealtimeSession,\n /** @internal */ readonly options: Record<string, unknown>,\n id: string,\n ) {\n this.id = id;\n }\n\n /** Send text. Text is billed per character as it is sent. Pass `{ finalize: true }` with the\n * turn's last text (or call {@link finish}). */\n send(text: string, options: { finalize?: boolean } = {}): Promise<void> {\n return this.serial(async () => {\n if (this.cancelled) {\n throw new RealtimeError(\"context_cancelled\", \"This context was cancelled.\", {\n contextId: this.id,\n });\n }\n if (this.finished) {\n throw new RealtimeError(\"context_finished\", \"This context was already finalized.\", {\n contextId: this.id,\n });\n }\n const finalize = options.finalize ?? false;\n if (!this.started) {\n this.started = true;\n try {\n await this.session._start(this, text, finalize);\n } catch (err) {\n this.started = false; // nothing was sent; the context can be retried\n throw err;\n }\n } else {\n this.session._sendText({ type: \"task_continue\", context_id: this.id }, text, finalize);\n }\n if (finalize) this.finished = true;\n });\n }\n\n /** No more text for this turn: speak what is buffered, then end the context. */\n finish(): Promise<void> {\n return this.serial(async () => {\n if (!this.started) {\n throw new RealtimeError(\"context_not_started\", \"Send text before finishing.\", {\n contextId: this.id,\n });\n }\n if (!this.finished) {\n this.session._send({ type: \"task_continue\", context_id: this.id, finalize: true });\n this.finished = true;\n }\n });\n }\n\n /** Stop this context now. Audio still in flight for it is dropped; iterating it ends with\n * `task_cancelled`. */\n async cancel(): Promise<void> {\n if (this.ended || this.cancelled) return;\n this.cancelled = true; // from now on, audio for this context is dropped\n this.finished = true; // and no more text is accepted\n // Runs after any send already queued, so a start that is in flight is cancelled too.\n await this.serial(async () => {\n if (!this.started) {\n this._end(); // nothing reached the server: just end the context\n return;\n }\n try {\n this.session._send({ type: \"task_cancel\", context_id: this.id });\n } catch {\n /* the socket is gone, which ends the context anyway */\n }\n });\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<RealtimeEvent> {\n for (;;) {\n while (this.items.length === 0) {\n await new Promise<void>((resolve) => (this.waiter = resolve));\n }\n const item = this.items.shift()!;\n if (item === END) return;\n if (item instanceof RealtimeError) throw item;\n yield item;\n }\n }\n\n /** Iterate only the PCM of this context. */\n async *audio(): AsyncGenerator<Uint8Array> {\n for await (const event of this) if (event.type === \"audio\") yield event.pcm;\n }\n\n /** @internal */\n _put(event: RealtimeEvent): void {\n if (event.type === \"task_started\") {\n this.sampleRate = typeof event.sample_rate === \"number\" ? event.sample_rate : null;\n this.audioFormat = typeof event.audio_format === \"string\" ? event.audio_format : null;\n }\n this.push(event);\n if (event.type === \"task_done\" || event.type === \"task_cancelled\") this._end();\n }\n\n /** @internal */\n _fail(error: RealtimeError): void {\n if (this.ended) return;\n this.push(error);\n this._end();\n }\n\n /** @internal */\n _end(): void {\n if (this.ended) return;\n this.ended = true;\n this.push(END);\n this.session._forget(this);\n }\n\n private push(item: Item): void {\n this.items.push(item);\n const w = this.waiter;\n this.waiter = null;\n w?.();\n }\n\n private serial<T>(fn: () => Promise<T>): Promise<T> {\n const run = this.sending.then(fn, fn);\n this.sending = run.catch(() => undefined);\n return run;\n }\n}\n\ninterface Socket {\n readyState: number;\n binaryType: string;\n send(data: string): void;\n close(code?: number, reason?: string): void;\n onopen: ((ev: unknown) => void) | null;\n onmessage: ((ev: { data: unknown }) => void) | null;\n onclose: ((ev: { code: number; reason: string }) => void) | null;\n onerror: ((ev: unknown) => void) | null;\n on?: (event: string, listener: (...args: unknown[]) => void) => void;\n}\ntype SocketCtor = new (url: string, protocols?: unknown, options?: unknown) => Socket;\n\nconst OPEN = 1;\n\ninterface Dialer {\n /** Open a socket; `headers` is null when the key must go in the URL instead. `protocols` is\n * set only for a token session. */\n open(\n url: string,\n headers: Record<string, string> | null,\n timeoutMs: number,\n protocols?: string[],\n ): Socket;\n headers: boolean;\n}\n\nfunction versions(): Record<string, string | undefined> {\n return (\n (globalThis as { process?: { versions?: Record<string, string | undefined> } }).process\n ?.versions ?? {}\n );\n}\n\nfunction globalDialer(headers: boolean): Dialer {\n const G = (globalThis as { WebSocket?: unknown }).WebSocket as SocketCtor | undefined;\n if (!G) throw new FinesseError(\"No WebSocket implementation available.\");\n return {\n headers,\n // Bun's WebSocket takes headers as a second-argument option. A token session needs no\n // headers, so it can use the standard protocols argument everywhere.\n open: (url, h, _t, protocols) =>\n protocols ? new G(url, protocols) : h ? new G(url, { headers: h }) : new G(url),\n };\n}\n\n/** Deno's WebSocket takes handshake headers from 2.5; older versions reject the option. */\nfunction denoHasHeaders(version: string | undefined): boolean {\n const [major = 0, minor = 0] = (version ?? \"\").split(\".\").map(Number);\n return major > 2 || (major === 2 && minor >= 5);\n}\n\nasync function defaultDialer(): Promise<Dialer> {\n if (isBrowser()) return globalDialer(false); // browsers cannot set handshake headers\n const v = versions();\n if (v.bun) return globalDialer(true);\n const deno = (globalThis as { Deno?: { version?: { deno?: string } } }).Deno;\n if (deno) return globalDialer(denoHasHeaders(deno.version?.deno));\n if (!v.node) return globalDialer(false);\n let mod: { default?: unknown; WebSocket?: unknown };\n try {\n mod = (await import(\"ws\")) as typeof mod;\n } catch (err) {\n const code = (err as { code?: string }).code;\n if (code === \"ERR_MODULE_NOT_FOUND\" || code === \"MODULE_NOT_FOUND\") {\n throw new FinesseError(\"Realtime in Node needs the `ws` package: npm install ws\");\n }\n throw err;\n }\n const WS = (mod.default ?? mod.WebSocket) as SocketCtor;\n return {\n headers: true,\n open: (url, h, timeoutMs, protocols) =>\n new WS(url, protocols, { headers: h, handshakeTimeout: timeoutMs }),\n };\n}\n\n/**\n * A realtime session. Get one with `await client.realtime.connect()` and `close()` it when done.\n * After a retryable drop the next context reconnects automatically (unless\n * `autoReconnect: false`); contexts running at the time fail with {@link RealtimeError}.\n */\nexport class RealtimeSession {\n private ws: Socket | null = null;\n private opening: Promise<void> | null = null;\n private readonly contexts = new Map<string, RealtimeContext>();\n private pendingAudio: Record<string, unknown> | null = null;\n private fatal: RealtimeError | null = null;\n private error: RealtimeError | null = null;\n private openedOnce = false;\n private closed = false;\n private closedWaiters: (() => void)[] = [];\n private readonly staticToken: string | null;\n private tokenSpent = false;\n\n constructor(\n private readonly core: Core,\n private readonly options: ConnectOptions = {},\n ) {\n this.staticToken = options.accessToken ?? core.accessToken;\n }\n\n get url(): string {\n return `${this.core.wsBaseURL}${API_PREFIX}/stream`;\n }\n\n get isOpen(): boolean {\n return this.ws !== null && this.ws.readyState === OPEN;\n }\n\n /**\n * Open the socket (no-op when open). Throws `AuthenticationError`, `PaymentRequiredError` or\n * `PermissionDeniedError` when the handshake is refused, `RateLimitError` with\n * `code === \"too_many_sessions\"` when the workspace already has its maximum of sessions,\n * and `APIConnectionError` / `APITimeoutError` when the service can't be reached.\n */\n open(): Promise<void> {\n if (this.isOpen) return Promise.resolve();\n if (this.closed)\n return Promise.reject(new RealtimeError(\"session_closed\", \"This session was closed.\"));\n if (this.openedOnce && this.options.autoReconnect === false) {\n return Promise.reject(\n this.error ?? new RealtimeError(\"connection_closed\", \"The session is closed.\"),\n );\n }\n this.opening ??= this.dial().finally(() => (this.opening = null));\n return this.opening;\n }\n\n /** Create a context. Nothing is sent until its first `send`. */\n context(options: ContextOptions): RealtimeContext {\n const { context_id, ...rest } = options;\n const opts: Record<string, unknown> = { output_format: \"s16le\" };\n for (const [k, v] of Object.entries(rest)) if (v !== undefined) opts[k] = v;\n return new RealtimeContext(this, opts, context_id ?? randomId());\n }\n\n /** Speak `text` as one complete turn and yield its events. Breaking out of the loop cancels\n * the turn. */\n async *say(options: ContextOptions & { text: string }): AsyncGenerator<RealtimeEvent> {\n const { text, ...rest } = options;\n const ctx = this.context(rest);\n await ctx.send(text, { finalize: true });\n try {\n yield* ctx;\n } finally {\n if (!ctx.ended) await ctx.cancel();\n }\n }\n\n /** End the session: tell the service, then close the socket. */\n async close(): Promise<void> {\n this.closed = true;\n await this.opening?.catch(() => undefined); // an in-flight open tears itself down\n const ws = this.ws;\n if (ws && ws.readyState === OPEN) {\n try {\n ws.send(JSON.stringify({ type: \"session_end\" }));\n } catch {\n /* already closing */\n }\n await new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, CLOSE_TIMEOUT_MS);\n this.closedWaiters.push(() => {\n clearTimeout(timer);\n resolve();\n });\n });\n }\n if (this.ws && this.ws.readyState <= OPEN) this.ws.close(1000);\n }\n\n // -- internals --\n\n /** @internal */\n async _start(ctx: RealtimeContext, text: string, finalize: boolean): Promise<void> {\n await this.open();\n const live = this.contexts.get(ctx.id);\n if (live && live !== ctx) {\n throw new RealtimeError(\"context_already_exists\", \"A running context already uses this id.\", {\n contextId: ctx.id,\n });\n }\n // Register before sending so no reply can arrive for an unknown context.\n this.contexts.set(ctx.id, ctx);\n ctx.socket = this.ws;\n try {\n this._sendText({ type: \"task_start\", context_id: ctx.id, ...ctx.options }, text, finalize);\n } catch (err) {\n this.contexts.delete(ctx.id);\n throw err;\n }\n }\n\n /** @internal */\n _send(msg: Record<string, unknown>): void {\n if (!this.ws || !this.isOpen) {\n throw this.error ?? new RealtimeError(\"connection_closed\", \"The session is not open.\");\n }\n this.ws.send(JSON.stringify(msg));\n }\n\n /** @internal Send a `task_start` / `task_continue` frame with `text`. Text that would make\n * the frame larger than {@link MAX_FRAME_BYTES} is split across `task_continue` frames for\n * the same context; only the last one carries `finalize`. */\n _sendText(msg: Record<string, unknown>, text: string, finalize: boolean): void {\n const frame = { ...msg, text, finalize };\n const json = JSON.stringify(frame);\n // Each UTF-16 unit is at most 3 bytes of UTF-8, so most frames need no encoding to check.\n if (json.length * 3 <= MAX_FRAME_BYTES || utf8Bytes(json) <= MAX_FRAME_BYTES) {\n this._send(frame);\n return;\n }\n const next = { type: \"task_continue\", context_id: msg.context_id };\n const overhead = Math.max(\n utf8Bytes(JSON.stringify({ ...msg, text: \"\", finalize: false })),\n utf8Bytes(JSON.stringify({ ...next, text: \"\", finalize: false })),\n );\n const pieces = splitText(text, MAX_FRAME_BYTES - overhead);\n pieces.forEach((piece, i) =>\n this._send({\n ...(i ? next : msg),\n text: piece,\n finalize: finalize && i === pieces.length - 1,\n }),\n );\n }\n\n /** @internal */\n _forget(ctx: RealtimeContext): void {\n if (this.contexts.get(ctx.id) === ctx) this.contexts.delete(ctx.id);\n }\n\n /** The token for the next handshake, or `null` to use the API key. A static token is used\n * first; once a handshake has spent it, `getAccessToken` supplies one per reconnect. */\n private async nextToken(): Promise<string | null> {\n if (this.staticToken && !this.tokenSpent) return this.staticToken;\n if (this.options.getAccessToken) {\n const token = await this.options.getAccessToken();\n if (typeof token !== \"string\" || !token) {\n throw new FinesseError(\"getAccessToken must return a non-empty token string.\");\n }\n return token;\n }\n if (this.staticToken) {\n throw new RealtimeError(\n \"token_spent\",\n \"This session's access token was used by an earlier connection. Pass \" +\n \"{ getAccessToken } so a reconnect can fetch a fresh one.\",\n );\n }\n return null;\n }\n\n private async dial(): Promise<void> {\n const timeout = this.options.openTimeout ?? DEFAULT_OPEN_TIMEOUT_MS;\n const custom = this.options.WebSocket as SocketCtor | undefined;\n const dialer: Dialer = custom\n ? {\n headers: !isBrowser(),\n open: (url, h, t, protocols) =>\n h\n ? new custom(url, protocols, { headers: h, handshakeTimeout: t })\n : new custom(url, protocols),\n }\n : await defaultDialer();\n const token = await this.nextToken();\n // Offered only with a token: a server that predates tokens selects no subprotocol, which\n // the `ws` package treats as a failed handshake.\n const protocols = token ? [SUBPROTOCOL, token] : undefined;\n let url = this.url;\n let headers: Record<string, string> | null = null;\n if (token) {\n // The token replaces the key; it rides in the subprotocol list, never in a header or URL.\n if (dialer.headers) {\n headers = { ...this.core.headers };\n delete headers.Accept;\n delete headers[\"X-API-Key\"];\n delete headers.Authorization;\n }\n const u = new URL(url);\n u.searchParams.set(\"client\", this.core.headers[\"X-Finesse-Client\"] ?? \"\");\n url = u.toString();\n } else if (dialer.headers) {\n headers = { ...this.core.headers };\n delete headers.Accept;\n } else {\n // No handshake headers here (browsers, Deno before 2.5): the service also accepts the key\n // and the client name as query parameters, but marks that deprecated.\n if (this.core.logLevel !== \"off\") warnQueryKey(this.core.logger);\n const u = new URL(url);\n u.searchParams.set(\"api_key\", this.core.apiKey ?? \"\");\n u.searchParams.set(\"client\", this.core.headers[\"X-Finesse-Client\"] ?? \"\");\n url = u.toString();\n }\n const ws = dialer.open(url, headers, timeout, protocols);\n ws.binaryType = \"arraybuffer\";\n\n await new Promise<void>((resolve, reject) => {\n let settled = false;\n const done = (err?: Error) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n if (err) {\n ws.onopen = ws.onclose = null;\n // Closing a socket that is still connecting emits one more error; swallow it.\n ws.onerror = () => undefined;\n try {\n ws.close();\n } catch {\n /* ignore */\n }\n reject(err);\n } else resolve();\n };\n const timer = setTimeout(() => done(new APITimeoutError()), timeout);\n ws.on?.(\"unexpected-response\", (_req: unknown, res: unknown) => {\n readResponse(res).then(\n ({ status, text, headers }) => done(makeStatusError(status, text, headers)),\n () => done(new APIConnectionError(\"The service refused the connection.\")),\n );\n });\n ws.onopen = () => done();\n let lastError = \"\";\n ws.onerror = (ev) => {\n const e = ev as { message?: string; error?: { message?: string } };\n lastError = e?.error?.message || e?.message || \"\";\n setTimeout(() => done(new APIConnectionError(lastError || \"Connection error.\")), 0);\n };\n ws.onclose = (ev) =>\n done(new APIConnectionError(lastError || `Connection closed (${ev.code}).`));\n });\n\n if (this.closed) {\n ws.close(1000);\n throw new RealtimeError(\"session_closed\", \"This session was closed.\");\n }\n if (token && token === this.staticToken) this.tokenSpent = true; // the handshake spent it\n this.ws = ws;\n this.pendingAudio = null;\n this.fatal = null;\n this.error = null;\n this.openedOnce = true;\n ws.onerror = () => undefined; // onclose follows and carries the reason\n ws.onmessage = (ev) => {\n if (this.ws !== ws) return; // a replaced socket\n try {\n if (typeof ev.data === \"string\") this.onMessage(ev.data);\n else this.onAudio(toBytes(ev.data));\n } catch {\n /* a frame we cannot parse must not end the session */\n }\n };\n ws.onclose = (ev) => this.onClose(ws, ev.code, ev.reason);\n }\n\n private onClose(ws: Socket, code: number, reason: string): void {\n if (this.ws !== null && this.ws !== ws) {\n // A replaced socket closed late: end only the contexts that ran on it.\n const err = closeError(code, reason ?? \"\") ?? new RealtimeError(\"connection_closed\");\n for (const ctx of [...this.contexts.values()]) if (ctx.socket === ws) ctx._fail(err);\n return;\n }\n this.ws = null;\n let error = this.fatal;\n if (error) error.closeCode ??= code;\n else error = closeError(code, reason ?? \"\");\n if (!error && this.contexts.size) {\n error = new RealtimeError(\"connection_closed\", \"The session ended.\", { closeCode: code });\n }\n this.error = error;\n for (const ctx of [...this.contexts.values()]) {\n ctx._fail(error ?? new RealtimeError(\"connection_closed\"));\n }\n for (const w of this.closedWaiters.splice(0)) w();\n }\n\n private onAudio(frame: Uint8Array): void {\n const header = this.pendingAudio;\n this.pendingAudio = null;\n if (!header) return;\n const ctx = this.contexts.get(String(header.context_id));\n if (!ctx || ctx.cancelled) return;\n ctx._put({\n type: \"audio\",\n context_id: ctx.id,\n pcm: frame,\n sample_rate: ctx.sampleRate,\n audio_format: ctx.audioFormat,\n ...numbers(header, [\"sentence_index\", \"chunk_index\", \"audio_duration_s\"]),\n });\n }\n\n private onMessage(frame: string): void {\n let data: unknown;\n try {\n data = JSON.parse(frame);\n } catch {\n return;\n }\n if (!data || typeof data !== \"object\" || Array.isArray(data)) return;\n const d = data as Record<string, unknown>;\n const kind = d.type;\n if (kind === \"audio_chunk\") {\n this.pendingAudio = d;\n return;\n }\n const cid = typeof d.context_id === \"string\" ? d.context_id : null;\n const ctx = cid ? this.contexts.get(cid) : undefined;\n if (kind === \"error\") {\n const err = new RealtimeError(String(d.code || \"error\"), String(d.message ?? \"\"), {\n contextId: cid,\n });\n if (d.fatal) this.fatal ??= err;\n else ctx?._fail(err); // a non-fatal error for a finished context is stale: dropped\n return;\n }\n if (kind === \"session_ended\") {\n this.fatal ??= new RealtimeError(\"session_ended\", String(d.reason || \"The session ended.\"));\n return;\n }\n if (!ctx || typeof kind !== \"string\") return;\n if (kind === \"task_failed\") {\n ctx._fail(\n new RealtimeError(String(d.code || \"task_failed\"), String(d.message ?? \"\"), {\n contextId: ctx.id,\n }),\n );\n return;\n }\n ctx._put(\n KNOWN_EVENTS.has(kind)\n ? ({ ...d, type: kind, context_id: ctx.id } as RealtimeEvent)\n : { type: \"unknown\", context_id: ctx.id, event_type: kind, data: d },\n );\n }\n}\n\n/** `client.realtime`: open realtime sessions. */\nexport class Realtime {\n constructor(private readonly core: Core) {}\n\n /** Open a session. */\n async connect(options: ConnectOptions = {}): Promise<RealtimeSession> {\n const session = new RealtimeSession(this.core, options);\n await session.open();\n return session;\n }\n\n /** Create a session without opening it; it opens on first use. */\n session(options: ConnectOptions = {}): RealtimeSession {\n return new RealtimeSession(this.core, options);\n }\n}\n\nconst warnedLoggers = new WeakSet<Logger>();\n\n/** Logged once per logger unless logging is off: the key in the URL is deprecated. */\nfunction warnQueryKey(logger: Logger): void {\n if (warnedLoggers.has(logger)) return;\n warnedLoggers.add(logger);\n logger.info(\n \"[finesse] This runtime cannot send WebSocket headers, so the API key goes in the URL \" +\n \"(?api_key=), which the service has deprecated. Mint a short-lived token on your server \" +\n \"(tokens.create) and connect with { accessToken } or { getAccessToken } instead.\",\n );\n}\n\nfunction utf8Bytes(s: string): number {\n return new TextEncoder().encode(s).length;\n}\n\n/** Split `text` into pieces of at most `budget` bytes once JSON-escaped and UTF-8 encoded,\n * never inside a code point or a surrogate pair. Every piece holds at least one code point. */\nexport function splitText(text: string, budget: number): string[] {\n const pieces: string[] = [];\n let start = 0;\n let size = 0;\n for (let i = 0; i < text.length;) {\n const c = text.charCodeAt(i);\n const pair = c >= 0xd800 && c <= 0xdbff && (text.charCodeAt(i + 1) & 0xfc00) === 0xdc00 ? 2 : 1;\n const bytes = pair === 2 ? 4 : escapedBytes(c);\n if (size + bytes > budget && i > start) {\n pieces.push(text.slice(start, i));\n start = i;\n size = 0;\n }\n size += bytes;\n i += pair;\n }\n pieces.push(text.slice(start));\n return pieces;\n}\n\n/** UTF-8 bytes of one UTF-16 unit as `JSON.stringify` writes it (surrogate pairs aside). */\nfunction escapedBytes(c: number): number {\n if (c === 0x22 || c === 0x5c) return 2; // \\\" and \\\\\n if (c < 0x20) return c === 8 || c === 9 || c === 10 || c === 12 || c === 13 ? 2 : 6;\n if (c < 0x80) return 1;\n if (c < 0x800) return 2;\n if (c >= 0xd800 && c <= 0xdfff) return 6; // a lone surrogate is escaped as \\uXXXX\n return 3;\n}\n\nfunction randomId(): string {\n const c = (globalThis as { crypto?: Crypto }).crypto;\n if (c?.randomUUID) return c.randomUUID().replace(/-/g, \"\");\n const bytes = new Uint8Array(16);\n if (c?.getRandomValues) c.getRandomValues(bytes);\n else for (let i = 0; i < 16; i++) bytes[i] = Math.floor(Math.random() * 256);\n return Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nfunction toBytes(data: unknown): Uint8Array {\n if (data instanceof ArrayBuffer) return new Uint8Array(data);\n if (ArrayBuffer.isView(data))\n return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n if (Array.isArray(data)) {\n // ws can deliver fragmented messages as Buffer[]\n const parts = data.map(toBytes);\n const out = new Uint8Array(parts.reduce((n, p) => n + p.length, 0));\n let o = 0;\n for (const p of parts) {\n out.set(p, o);\n o += p.length;\n }\n return out;\n }\n throw new TypeError(\"unexpected frame\");\n}\n\nfunction numbers(obj: Record<string, unknown>, keys: string[]): Record<string, number> {\n const out: Record<string, number> = {};\n for (const k of keys) if (typeof obj[k] === \"number\") out[k] = obj[k] as number;\n return out;\n}\n\nasync function readResponse(\n res: unknown,\n): Promise<{ status: number; text: string; headers: Headers }> {\n const r = res as {\n statusCode: number;\n headers: Record<string, string | string[] | undefined>;\n on(event: string, cb: (chunk?: unknown) => void): void;\n };\n const headers = new Headers();\n for (const [k, v] of Object.entries(r.headers)) {\n if (v !== undefined) headers.set(k, Array.isArray(v) ? v.join(\", \") : v);\n }\n const chunks: Uint8Array[] = [];\n await new Promise<void>((resolve, reject) => {\n r.on(\"data\", (c) => chunks.push(c as Uint8Array));\n r.on(\"end\", () => resolve());\n r.on(\"error\", (e) => reject(e));\n });\n const text = new TextDecoder().decode(toBytes(chunks));\n return { status: r.statusCode, text, headers };\n}\n","import { pathId, sleep, type Core, type RequestOptions } from \"../core.js\";\nimport { CloneFailedError, CloneTimeoutError } from \"../errors.js\";\nimport type { CloneJob } from \"../types.js\";\n\nexport const DEFAULT_WAIT_TIMEOUT_MS = 300_000;\nexport const DEFAULT_POLL_INTERVAL_MS = 2_000;\n\nexport interface WaitOptions {\n /** Give up after this many ms. Default 300 000 (the first clone after the cloner has been\n * idle can take a couple of minutes). */\n timeout?: number;\n /** Poll every this many ms. Default 2 000. */\n pollInterval?: number;\n /** Called with the job after every poll. */\n onUpdate?: (job: CloneJob) => void;\n /** Stop waiting (rejects with the signal's reason). The job itself keeps running. */\n signal?: AbortSignal;\n}\n\nconst FINISHED = new Set([\"succeeded\", \"failed\", \"cancelled\", \"expired\"]);\n\n/** Clone jobs started by `voices.clone` and `voices.enroll`. */\nexport class Jobs {\n constructor(private readonly core: Core) {}\n\n get(jobId: string, options: RequestOptions = {}): Promise<CloneJob> {\n return this.core.json<CloneJob>(\"GET\", `/jobs/${pathId(jobId)}`, options);\n }\n\n /** Poll until the job finishes and return it. Throws {@link CloneFailedError} if it ends\n * `failed`, `cancelled` or `expired`, and {@link CloneTimeoutError} on timeout. */\n async wait(jobId: string, options: WaitOptions = {}): Promise<CloneJob> {\n const timeout = options.timeout ?? DEFAULT_WAIT_TIMEOUT_MS;\n const interval = options.pollInterval ?? DEFAULT_POLL_INTERVAL_MS;\n const deadline = Date.now() + timeout;\n for (;;) {\n const job = await this.get(jobId, { signal: options.signal });\n options.onUpdate?.(job);\n if (FINISHED.has(job.status)) {\n if (job.status !== \"succeeded\") throw new CloneFailedError(job);\n return job;\n }\n const remaining = deadline - Date.now();\n if (remaining <= 0) throw new CloneTimeoutError(jobId, timeout);\n await sleep(Math.min(interval, remaining), options.signal);\n }\n }\n}\n","import { APITimeoutError } from \"./errors.js\";\n\n/** A minimal Server-Sent Events parser (only what `speech.stream` needs). */\n\nexport interface SSEEvent {\n event: string;\n data: string;\n}\n\n/** Parse an SSE body. A read that waits longer than `idleTimeoutMs` throws `APITimeoutError`. */\nexport async function* iterSSE(\n body: ReadableStream<Uint8Array>,\n idleTimeoutMs: number,\n): AsyncGenerator<SSEEvent> {\n const decoder = new TextDecoder();\n const reader = body.getReader();\n let buffer = \"\";\n let event: string | null = null;\n let data: string[] = [];\n\n function* feed(line: string): Generator<SSEEvent> {\n if (line.endsWith(\"\\r\")) line = line.slice(0, -1);\n if (line === \"\") {\n if (data.length || event !== null) yield { event: event ?? \"message\", data: data.join(\"\\n\") };\n event = null;\n data = [];\n return;\n }\n if (line.startsWith(\":\")) return;\n const i = line.indexOf(\":\");\n const field = i === -1 ? line : line.slice(0, i);\n let value = i === -1 ? \"\" : line.slice(i + 1);\n if (value.startsWith(\" \")) value = value.slice(1);\n if (field === \"event\") event = value;\n else if (field === \"data\") data.push(value);\n }\n\n try {\n for (;;) {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const idle = new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new APITimeoutError()), idleTimeoutMs);\n });\n let result: ReadableStreamReadResult<Uint8Array>;\n try {\n result = await Promise.race([reader.read(), idle]);\n } finally {\n clearTimeout(timer);\n }\n const { done, value } = result;\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n let nl: number;\n while ((nl = buffer.indexOf(\"\\n\")) !== -1) {\n const line = buffer.slice(0, nl);\n buffer = buffer.slice(nl + 1);\n yield* feed(line);\n }\n }\n buffer += decoder.decode();\n if (buffer) yield* feed(buffer);\n yield* feed(\"\");\n } finally {\n await reader.cancel().catch(() => undefined);\n reader.releaseLock();\n }\n}\n","import { pathId, releaseStream, throwIfAborted, type Core, type RequestOptions } from \"../core.js\";\nimport { APIConnectionError, FinesseError, StreamError } from \"../errors.js\";\nimport { iterSSE } from \"../sse.js\";\nimport type { Audio, AudioChunk, SpeechParams, StreamDone } from \"../types.js\";\n\nfunction body(params: SpeechParams): Record<string, unknown> {\n const { voice_id: _ignored, ...rest } = params;\n return Object.fromEntries(Object.entries(rest).filter(([, v]) => v !== undefined));\n}\n\nfunction intHeader(headers: Headers, name: string): number | null {\n const v = headers.get(name);\n if (v === null) return null;\n const n = Number(v);\n return Number.isInteger(n) ? n : null;\n}\n\nfunction base64ToBytes(b64: string): Uint8Array {\n if (!/^[A-Za-z0-9+/]*={0,2}$/.test(b64) || b64.length % 4 === 1) {\n throw new StreamError(\"bad_chunk\", \"The stream sent an undecodable audio chunk.\");\n }\n const bin = atob(b64);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\n/** Speech streamed as raw PCM chunks: `for await (const chunk of stream)`. `done` is set once\n * it finishes. The request is sent when iteration starts. Errors before the stream starts\n * throw the usual `APIStatusError`; failures after it throw {@link StreamError}. */\nexport class SpeechStream implements AsyncIterable<AudioChunk> {\n sampleRate: number | null = null;\n audioFormat: string | null = null;\n /** Final event (duration, generation id, stored clip URL), once the stream finished. */\n done: StreamDone | null = null;\n billingRemaining: number | null = null;\n private consumed = false;\n\n constructor(\n private readonly core: Core,\n private readonly path: string,\n private readonly json: Record<string, unknown>,\n private readonly options: RequestOptions = {},\n ) {}\n\n async *[Symbol.asyncIterator](): AsyncIterator<AudioChunk> {\n if (this.consumed) throw new FinesseError(\"This stream was already consumed; start a new one.\");\n this.consumed = true;\n const response = await this.core.request(\"POST\", this.path, {\n ...this.options,\n json: this.json,\n stream: true,\n });\n this.billingRemaining = intHeader(response.headers, \"x-billing-remaining\");\n try {\n if (!response.body) throw new StreamError(\"stream_incomplete\", \"The response had no body.\");\n const idle = this.options.timeout ?? this.core.timeout;\n for await (const ev of iterSSE(response.body, idle)) {\n const chunk = this.handle(ev.event, ev.data);\n if (chunk) yield chunk;\n }\n if (!this.done) {\n throw new StreamError(\"stream_incomplete\", \"The stream ended before it finished.\");\n }\n } catch (err) {\n throwIfAborted(this.options.signal);\n if (err instanceof FinesseError) throw err;\n throw new APIConnectionError(\n err instanceof Error ? err.message : \"The stream was interrupted.\",\n { cause: err },\n );\n } finally {\n releaseStream(response);\n }\n }\n\n /** Consume the stream and return all PCM joined together. */\n async readAll(): Promise<Uint8Array> {\n const parts: Uint8Array[] = [];\n for await (const chunk of this) parts.push(chunk.pcm);\n const out = new Uint8Array(parts.reduce((n, p) => n + p.length, 0));\n let offset = 0;\n for (const p of parts) {\n out.set(p, offset);\n offset += p.length;\n }\n return out;\n }\n\n private handle(event: string, data: string): AudioChunk | null {\n let payload: unknown;\n try {\n payload = data ? JSON.parse(data) : {};\n } catch {\n return null;\n }\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) return null;\n const p = payload as Record<string, unknown>;\n const kind = (typeof p.type === \"string\" && p.type) || event;\n if (kind === \"start\") {\n if (typeof p.sample_rate === \"number\") this.sampleRate = p.sample_rate;\n if (typeof p.audio_format === \"string\") this.audioFormat = p.audio_format;\n } else if (kind === \"chunk\") {\n return {\n pcm: base64ToBytes(typeof p.audio_b64 === \"string\" ? p.audio_b64 : \"\"),\n sampleRate: typeof p.sample_rate === \"number\" ? p.sample_rate : this.sampleRate,\n audioFormat: typeof p.audio_format === \"string\" ? p.audio_format : this.audioFormat,\n index: typeof p.index === \"number\" ? p.index : null,\n };\n } else if (kind === \"done\") {\n this.done = p as StreamDone;\n } else if (kind === \"error\") {\n throw new StreamError(\n typeof p.code === \"string\" && p.code ? p.code : \"stream_error\",\n typeof p.message === \"string\" ? p.message : \"\",\n );\n }\n return null;\n }\n}\n\n/** Text-to-speech. */\nexport class Speech {\n constructor(private readonly core: Core) {}\n\n /** Synthesize `text` and return the whole clip (`wav` unless `output_format` says otherwise). */\n async create(params: SpeechParams, options: RequestOptions = {}): Promise<Audio> {\n const response = await this.core.request(\"POST\", `/voices/${pathId(params.voice_id)}/speak`, {\n ...options,\n idempotent: true,\n json: body(params),\n });\n const h = response.headers;\n return {\n data: new Uint8Array(await response.arrayBuffer()),\n contentType: h.get(\"content-type\") ?? \"audio/wav\",\n sampleRate: intHeader(h, \"x-sample-rate\"),\n generationId: h.get(\"x-generation-id\") || null,\n audioURL: h.get(\"x-audio-url\") || null,\n billingRemaining: intHeader(h, \"x-billing-remaining\"),\n };\n }\n\n /** Stream speech as raw PCM chunks (`s16le` unless `output_format` says otherwise):\n *\n * ```ts\n * for await (const chunk of client.speech.stream({ voice_id, text: \"Hello\" })) play(chunk.pcm);\n * ```\n */\n stream(params: SpeechParams, options: RequestOptions = {}): SpeechStream {\n return new SpeechStream(\n this.core,\n `/voices/${pathId(params.voice_id)}/stream`,\n body(params),\n options,\n );\n }\n}\n","import type { Core, RequestOptions } from \"../core.js\";\nimport type { AccessToken } from \"../types.js\";\n\nexport interface CreateTokenParams {\n /** How long the token stays valid if unused, 10-3600 seconds. Default 300. */\n ttl_seconds?: number;\n /** Limit the token to these voices (yours or public platform voices). */\n voice_ids?: string[];\n}\n\n/** Short-lived tokens, so a browser or device can synthesize without your API key. */\nexport class Tokens {\n constructor(private readonly core: Core) {}\n\n /** Mint a single-use token. Call this on your server with an API key that has the `tts`\n * scope, and send only the token to the client:\n *\n * ```ts\n * const { token } = await client.tokens.create({ ttl_seconds: 60, voice_ids: [voiceId] });\n * ```\n */\n async create(params: CreateTokenParams = {}, options: RequestOptions = {}): Promise<AccessToken> {\n const json: Record<string, unknown> = {};\n if (params.ttl_seconds !== undefined) json.ttl_seconds = params.ttl_seconds;\n if (params.voice_ids !== undefined) json.voice_ids = params.voice_ids;\n return this.core.json<AccessToken>(\"POST\", \"/tokens\", { ...options, json });\n }\n}\n","/** A reference clip: a `Blob`/`File`, raw bytes, or `{ data, filename, contentType }`.\n * In Node, `await fileFromPath(\"ref.wav\")` reads a file from disk. */\nexport type FileInput =\n | Blob\n | Uint8Array\n | ArrayBuffer\n | { data: Blob | Uint8Array | ArrayBuffer; filename?: string; contentType?: string };\n\nconst TYPES: Record<string, string> = {\n wav: \"audio/wav\",\n mp3: \"audio/mpeg\",\n m4a: \"audio/mp4\",\n ogg: \"audio/ogg\",\n flac: \"audio/flac\",\n webm: \"audio/webm\",\n};\n\nfunction guessType(name: string): string {\n return TYPES[name.split(\".\").pop()?.toLowerCase() ?? \"\"] ?? \"application/octet-stream\";\n}\n\n/** Normalise a file input to a Blob and filename. The Blob can be reused on retries. */\nexport function toBlob(file: FileInput): { blob: Blob; filename: string } {\n if (typeof Blob !== \"undefined\" && file instanceof Blob) {\n const name = (file as { name?: unknown }).name;\n return { blob: file, filename: typeof name === \"string\" && name ? name : \"audio.wav\" };\n }\n if (file instanceof Uint8Array || file instanceof ArrayBuffer) {\n return { blob: new Blob([file as BlobPart]), filename: \"audio.wav\" };\n }\n const { data, filename = \"audio.wav\" } = file as Exclude<\n FileInput,\n Blob | Uint8Array | ArrayBuffer\n >;\n const contentType = (file as { contentType?: string }).contentType ?? guessType(filename);\n // Keep a Blob's own type; give untyped data the one guessed from the filename.\n const blob =\n data instanceof Blob && data.type ? data : new Blob([data as BlobPart], { type: contentType });\n return { blob, filename };\n}\n\n/** Node only: read a file from disk into a {@link FileInput}. */\nexport async function fileFromPath(path: string): Promise<FileInput> {\n const { readFile } = await import(\"node:fs/promises\");\n const { basename } = await import(\"node:path\");\n const data = await readFile(path);\n const filename = basename(path);\n return { data: new Uint8Array(data), filename, contentType: guessType(filename) };\n}\n","/** Response shapes. Field names match the API (snake_case); timestamps are Unix milliseconds.\n * Media URLs (`original_audio_url`, `sample_audio_url`, `avatar_url`, `audio_url`) may be\n * short-lived signed URLs: download them promptly, or fetch the object again for a fresh one. */\n\nexport interface VoiceSettings {\n stability?: number;\n similarity?: number;\n style?: number;\n speed?: number;\n pitch?: number;\n volume?: number;\n use_speaker_boost?: boolean;\n emotion?: string;\n engine_params?: Record<string, unknown>;\n}\n\n/** A voice. It can synthesize once `status === \"ready\"`. */\nexport interface Voice {\n id: string;\n org_id: string;\n name: string;\n /** `draft`, `processing`, `ready`, `failed`, ... */\n status: string;\n clone_method: string;\n /** `private` for your voices, `public` for platform catalog voices. */\n visibility: string;\n primary_language: string;\n description?: string;\n model?: string;\n /** Human-friendly handle, also usable as `voice` on the OpenAI-compatible endpoint. */\n alias?: string;\n source?: string;\n language?: string;\n gender?: string;\n /** Labels as a plain object (the API sends `[{key, value}]`; the SDK converts it). */\n labels: Record<string, string>;\n settings?: VoiceSettings;\n external_ref?: string;\n original_audio_url?: string;\n sample_audio_url?: string;\n avatar_url?: string;\n base_voice_id?: string;\n created_at?: number;\n updated_at?: number;\n last_used_at?: number;\n expires_at?: number;\n /** Prefix of the API key that created the voice; only on your own voices. */\n created_via_key_prefix?: string;\n [key: string]: unknown;\n}\n\n/** An asynchronous clone job. */\nexport interface CloneJob {\n id: string;\n org_id: string;\n /** `pending`, `running`, `succeeded`, `failed`, `cancelled` or `expired`. */\n status: string;\n job_type: string;\n voice_id?: string;\n /** Percent complete. Not updated while running; 100 once succeeded. */\n progress: number;\n attempts: number;\n /** Failure detail, `{message, status_code}`. */\n error?: Record<string, unknown> | null;\n started_at?: number;\n finished_at?: number;\n created_at?: number;\n [key: string]: unknown;\n}\n\n/** What `voices.clone` / `voices.enroll` return: the voice (`processing`) and its job id. */\nexport interface CloneResult {\n voice: Voice;\n job_id: string;\n}\n\n/** A synthesized clip from `speech.create`. */\nexport interface Audio {\n data: Uint8Array;\n /** `audio/wav` for WAV, `application/octet-stream` for raw PCM. */\n contentType: string;\n sampleRate: number | null;\n /** Id of the generation history record (when object storage is enabled). */\n generationId: string | null;\n /** The stored clip, when object storage is enabled; may be a short-lived signed URL. */\n audioURL: string | null;\n billingRemaining: number | null;\n}\n\n/** One chunk of raw PCM from `speech.stream`. */\nexport interface AudioChunk {\n pcm: Uint8Array;\n sampleRate: number | null;\n /** PCM encoding, e.g. `s16le`. */\n audioFormat: string | null;\n index: number | null;\n}\n\n/** The final event of `speech.stream`. */\nexport interface StreamDone {\n audio_duration_s?: number;\n generation_id?: string;\n audio_url?: string;\n}\n\n/** `wav` (one-shot default) or raw little-endian PCM. */\n/** A short-lived, single-use token from `tokens.create`. Hand `token` to a browser or device:\n * it is good for one `speech.create` / `speech.stream` call or one realtime session, carries\n * the `tts` scope only, and dies when the key that minted it is revoked or expires. */\nexport interface AccessToken {\n token: string;\n /** Unix epoch ms. */\n expires_at: number;\n ttl_seconds: number;\n}\n\n/** `mulaw` is raw G.711 µ-law for telephony and needs `sample_rate: 8000`. */\nexport type OutputFormat = \"wav\" | \"s16le\" | \"s24le\" | \"s32le\" | \"f32le\" | \"f64le\" | \"mulaw\";\n\nexport interface SpeechParams {\n /** One of your voices or a public platform voice; it must be ready. */\n voice_id: string;\n /** At most 10,000 characters. Billed per character. */\n text: string;\n language?: string;\n output_format?: OutputFormat;\n /** Output rate in Hz, 8000-48000. The native rate is 24000; 8000 is produced as asked, other\n * lower values still return 24000. */\n sample_rate?: number;\n /** Generation steps, 1-32 (default and maximum 32; over 32 is a 400); fewer is faster. */\n num_step?: number;\n}\n\nexport function toVoice(raw: unknown): Voice {\n const v = { ...(raw as Record<string, unknown>) };\n const labels = v.labels;\n if (Array.isArray(labels)) {\n const map: Record<string, string> = {};\n for (const item of labels) {\n if (item && typeof item === \"object\" && \"key\" in item) {\n map[String((item as { key: unknown }).key)] = String(\n (item as { value?: unknown }).value ?? \"\",\n );\n }\n }\n v.labels = map;\n } else if (!labels || typeof labels !== \"object\") {\n v.labels = {};\n }\n return v as Voice;\n}\n\nexport const isReady = (voice: Voice): boolean => voice.status === \"ready\";\n","import { pathId, type Core, type RequestOptions } from \"../core.js\";\nimport { FinesseError } from \"../errors.js\";\nimport { toBlob, type FileInput } from \"../files.js\";\nimport { toVoice, type CloneResult, type Voice } from \"../types.js\";\nimport { Jobs, type WaitOptions } from \"./jobs.js\";\n\nexport interface ListVoicesParams {\n /** 1-based page. Default 1. */\n page?: number;\n /** Voices per page, at most 100. Default 50. */\n page_size?: number;\n}\n\nexport interface CreateVoiceParams {\n name: string;\n description?: string;\n language?: string;\n labels?: Record<string, string>;\n model?: string;\n}\n\nexport interface UpdateVoiceParams {\n name?: string;\n description?: string;\n language?: string;\n /** Replaces the whole label set (`{}` clears it). */\n labels?: Record<string, string>;\n}\n\n/** Cloning requires `consent: true`: you attest that you are the speaker or hold their explicit\n * permission to clone their voice. The attestation is recorded on the voice. */\nexport interface ConsentParams {\n consent: true;\n}\n\nexport interface CloneVoiceParams extends ConsentParams {\n name: string;\n /** Reference clip, at most 20 MiB: at least 10 s of clear speech (10-30 s works best). */\n file: FileInput;\n description?: string;\n language?: string;\n labels?: Record<string, string>;\n /** Transcript of the reference clip, at most 4000 characters. */\n ref_text?: string;\n remove_background_noise?: boolean;\n}\n\nexport interface EnrollVoiceParams extends ConsentParams {\n /** Reference clip, at most 20 MiB: at least 10 s of clear speech (10-30 s works best). */\n file: FileInput;\n /** Transcript of the reference clip, at most 4000 characters. */\n ref_text?: string;\n language?: string;\n}\n\n/** One page of voices. `for await (const voice of page)` walks this page and every page after\n * it, fetching as needed. */\nexport class VoicePage implements AsyncIterable<Voice> {\n readonly voices: Voice[];\n readonly page: number;\n readonly page_size: number;\n readonly total: number;\n readonly has_more: boolean;\n\n constructor(\n data: Record<string, unknown>,\n private readonly fetchPage: (page: number) => Promise<VoicePage>,\n ) {\n this.voices = ((data.voices as unknown[]) ?? []).map(toVoice);\n this.page = Number(data.page ?? 1);\n this.page_size = Number(data.page_size ?? this.voices.length);\n this.total = Number(data.total ?? this.voices.length);\n this.has_more = Boolean(data.has_more);\n }\n\n nextPage(): Promise<VoicePage> {\n return this.fetchPage(this.page + 1);\n }\n\n async *iterPages(): AsyncGenerator<VoicePage> {\n let page: VoicePage = this;\n for (;;) {\n yield page;\n if (!page.has_more || page.voices.length === 0) return;\n page = await page.nextPage();\n }\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<Voice> {\n for await (const page of this.iterPages()) yield* page.voices;\n }\n}\n\nfunction consent(params: { consent?: unknown }): string {\n if (params.consent !== true) {\n throw new FinesseError(\n \"Cloning requires consent: true: you attest that you are the speaker or hold their \" +\n \"explicit permission to clone their voice.\",\n );\n }\n return \"true\";\n}\n\nfunction defined<T extends Record<string, unknown>>(obj: T): Partial<T> {\n return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined)) as Partial<T>;\n}\n\nfunction form(fields: Record<string, string | undefined>, file: FileInput): () => FormData {\n const { blob, filename } = toBlob(file);\n return () => {\n const fd = new FormData();\n for (const [k, v] of Object.entries(fields)) if (v !== undefined) fd.append(k, v);\n fd.append(\"file\", blob, filename);\n return fd;\n };\n}\n\n/** What `voices.list()` returns: `await` it for the first page, or iterate it directly with\n * `for await` to walk every voice. The first page is fetched once, on first use. */\nexport class VoicePagePromise implements PromiseLike<VoicePage>, AsyncIterable<Voice> {\n private first: Promise<VoicePage> | null = null;\n\n constructor(private readonly load: () => Promise<VoicePage>) {}\n\n private page(): Promise<VoicePage> {\n return (this.first ??= this.load());\n }\n\n then<A = VoicePage, B = never>(\n onfulfilled?: ((value: VoicePage) => A | PromiseLike<A>) | null,\n onrejected?: ((reason: unknown) => B | PromiseLike<B>) | null,\n ): Promise<A | B> {\n return this.page().then(onfulfilled, onrejected);\n }\n\n catch<B = never>(\n onrejected?: ((reason: unknown) => B | PromiseLike<B>) | null,\n ): Promise<VoicePage | B> {\n return this.page().catch(onrejected);\n }\n\n finally(onfinally?: (() => void) | null): Promise<VoicePage> {\n return this.page().finally(onfinally);\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<Voice> {\n yield* await this.page();\n }\n}\n\n/** Create, list, clone and manage voices. */\nexport class Voices {\n constructor(\n private readonly core: Core,\n private readonly jobs: Jobs,\n ) {}\n\n /** Your voices (newest first), then the public platform voices.\n * `for await (const voice of client.voices.list())` walks every page;\n * `await client.voices.list()` returns just the first page. */\n list(params: ListVoicesParams = {}, options: RequestOptions = {}): VoicePagePromise {\n const pageSize = params.page_size ?? 50;\n const fetchPage = async (page: number): Promise<VoicePage> => {\n const data = await this.core.json<Record<string, unknown>>(\"GET\", \"/voices\", {\n ...options,\n query: { page, page_size: pageSize },\n });\n return new VoicePage(data, fetchPage);\n };\n return new VoicePagePromise(() => fetchPage(params.page ?? 1));\n }\n\n /** One of your voices or a public platform voice. */\n async get(voiceId: string, options: RequestOptions = {}): Promise<Voice> {\n return toVoice(await this.core.json(\"GET\", `/voices/${pathId(voiceId)}`, options));\n }\n\n /** Create an empty `draft` voice. Give it a clip with {@link enroll}, or use {@link clone}. */\n async create(params: CreateVoiceParams, options: RequestOptions = {}): Promise<Voice> {\n const json = defined({ ...params });\n return toVoice(await this.core.json(\"POST\", \"/voices\", { ...options, json, idempotent: true }));\n }\n\n /** Change a voice's metadata. Only the fields you pass change. */\n async update(\n voiceId: string,\n params: UpdateVoiceParams,\n options: RequestOptions = {},\n ): Promise<Voice> {\n const json = defined({ ...params });\n return toVoice(\n await this.core.json(\"PATCH\", `/voices/${pathId(voiceId)}`, { ...options, json }),\n );\n }\n\n /** Delete one of your voices. */\n async delete(voiceId: string, options: RequestOptions = {}): Promise<void> {\n await this.core.request(\"DELETE\", `/voices/${pathId(voiceId)}`, options);\n }\n\n /** Create a voice from a reference clip. Returns at once with the voice in `processing` and a\n * `job_id`; see {@link waitUntilReady} or {@link cloneAndWait}. Requires `consent: true`. */\n async clone(params: CloneVoiceParams, options: RequestOptions = {}): Promise<CloneResult> {\n const fields = {\n consent: consent(params),\n name: params.name,\n description: params.description,\n language: params.language,\n ref_text: params.ref_text,\n labels: params.labels ? JSON.stringify(params.labels) : undefined,\n remove_background_noise:\n params.remove_background_noise === undefined\n ? undefined\n : String(params.remove_background_noise),\n };\n const result = await this.core.json<CloneResult>(\"POST\", \"/voices/clone\", {\n ...options,\n idempotent: true,\n form: form(fields, params.file),\n });\n return { ...result, voice: toVoice(result.voice) };\n }\n\n /** Clone a reference clip into an existing voice of yours. Returns at once. Requires\n * `consent: true`. */\n async enroll(\n voiceId: string,\n params: EnrollVoiceParams,\n options: RequestOptions = {},\n ): Promise<CloneResult> {\n const fields = {\n consent: consent(params),\n ref_text: params.ref_text,\n language: params.language,\n };\n const result = await this.core.json<CloneResult>(\"POST\", `/voices/${pathId(voiceId)}/enroll`, {\n ...options,\n idempotent: true,\n form: form(fields, params.file),\n });\n return { ...result, voice: toVoice(result.voice) };\n }\n\n /** Wait for a clone job to finish and return the voice, now `ready`. */\n async waitUntilReady(clone: CloneResult, options: WaitOptions = {}): Promise<Voice> {\n await this.jobs.wait(clone.job_id, options);\n return this.get(clone.voice.id, { signal: options.signal });\n }\n\n /** {@link clone}, then {@link waitUntilReady}. Returns the ready voice. */\n async cloneAndWait(params: CloneVoiceParams, options: WaitOptions = {}): Promise<Voice> {\n return this.waitUntilReady(await this.clone(params), options);\n }\n}\n","import { Core, type ClientOptions } from \"./core.js\";\nimport { rawClient, type RawClient } from \"./raw.js\";\nimport { Realtime } from \"./realtime.js\";\nimport { Jobs } from \"./resources/jobs.js\";\nimport { Speech } from \"./resources/speech.js\";\nimport { Tokens } from \"./resources/tokens.js\";\nimport { Voices } from \"./resources/voices.js\";\n\ninterface FinesseResources {\n voices: Voices;\n jobs: Jobs;\n speech: Speech;\n tokens: Tokens;\n}\n\nfunction resources(core: Core): FinesseResources {\n const jobs = new Jobs(core);\n return {\n jobs,\n voices: new Voices(core, jobs),\n speech: new Speech(core),\n tokens: new Tokens(core),\n };\n}\n\n/**\n * Client for the Finesse API.\n *\n * ```ts\n * import { Finesse } from \"@flamai/finesse\";\n *\n * const client = new Finesse(); // reads FINESSE_API_KEY\n * const audio = await client.speech.create({ voice_id: \"665f1a2b3c4d5e6f7a8b9c0d\", text: \"Hello!\" });\n * ```\n */\nexport class Finesse {\n readonly voices: Voices;\n readonly jobs: Jobs;\n readonly speech: Speech;\n readonly tokens: Tokens;\n readonly realtime: Realtime;\n /** @internal */\n readonly _core: Core;\n\n constructor(options: ClientOptions | { _core: Core } = {}) {\n this._core = \"_core\" in options ? options._core : new Core(options);\n const r = resources(this._core);\n this.jobs = r.jobs;\n this.voices = r.voices;\n this.speech = r.speech;\n this.tokens = r.tokens;\n this.realtime = new Realtime(this._core);\n }\n\n get baseURL(): string {\n return this._core.baseURL;\n }\n\n /** A copy of this client with different defaults. Cheap: it shares everything else. */\n withOptions(options: {\n timeout?: number;\n maxRetries?: number;\n defaultHeaders?: Record<string, string>;\n }): Finesse {\n return new Finesse({\n _core: this._core.withOptions({\n timeout: options.timeout,\n maxRetries: options.maxRetries,\n headers: options.defaultHeaders,\n }),\n });\n }\n\n /** The same calls, each resolving to `{ data, response, status, headers, requestId }`:\n *\n * ```ts\n * const { data: voice, requestId } = await client.withRawResponse.voices.get(id);\n * ```\n */\n get withRawResponse(): RawClient<FinesseResources> {\n return rawClient(this._core, resources);\n }\n}\n"],"mappings":"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","names":["body","body","url","protocols","headers","body"]}