@maroonedsoftware/rhapsode-sdk 0.1.22 → 0.1.23

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.
package/dist/index.d.ts CHANGED
@@ -9,6 +9,10 @@
9
9
  * One operation it cannot serve is `installJobEvents`: the generated method reads the whole body,
10
10
  * and a job's event stream does not end on its own. Read it with an `EventSource` on
11
11
  * `/installs/{job}/events` instead. protocol.md § 10.
12
+ *
13
+ * `speakStream` is written by hand beside them, because `/speak/stream` is a WebSocket conversation
14
+ * rather than a request and a response. protocol.md § 6.
12
15
  */
13
16
  export * from './generated/index.js';
17
+ export * from './speak.stream.js';
14
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,cAAc,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -956,10 +956,115 @@ var RhapsodeSdk = class {
956
956
  this.public = new PublicClient(sdkFetch);
957
957
  }
958
958
  };
959
+
960
+ // src/speak.stream.ts
961
+ var SpeakStreamError = class extends Error {
962
+ static {
963
+ __name(this, "SpeakStreamError");
964
+ }
965
+ code;
966
+ retryable;
967
+ constructor(code, message, retryable) {
968
+ super(message), this.code = code, this.retryable = retryable;
969
+ this.name = "SpeakStreamError";
970
+ }
971
+ };
972
+ function speakStream(baseUrl, start) {
973
+ const socket = new WebSocket(`${baseUrl.replace(/^http/, "ws").replace(/\/$/, "")}/speak/stream`);
974
+ socket.binaryType = "arraybuffer";
975
+ const pending = [
976
+ JSON.stringify({
977
+ type: "start",
978
+ ...start
979
+ })
980
+ ];
981
+ const send = /* @__PURE__ */ __name((frame) => {
982
+ const text = JSON.stringify(frame);
983
+ if (socket.readyState === WebSocket.OPEN) socket.send(text);
984
+ else pending.push(text);
985
+ }, "send");
986
+ socket.addEventListener("open", () => pending.splice(0).forEach((text) => socket.send(text)));
987
+ const events = new Inbox();
988
+ socket.addEventListener("message", (message) => {
989
+ if (typeof message.data !== "string") {
990
+ events.put({
991
+ type: "audio",
992
+ data: new Uint8Array(message.data)
993
+ });
994
+ return;
995
+ }
996
+ const frame = JSON.parse(message.data);
997
+ if (frame.type === "done") events.finish();
998
+ else if (frame.type === "error" && frame.error) events.fail(new SpeakStreamError(frame.error.code, frame.error.message, frame.error.retryable));
999
+ else events.put(frame);
1000
+ });
1001
+ socket.addEventListener("close", (close) => {
1002
+ events.fail(new SpeakStreamError("internal", `the server closed the session (${close.code}) before it was done`, true));
1003
+ });
1004
+ socket.addEventListener("error", () => {
1005
+ events.fail(new SpeakStreamError("internal", "the session could not be opened or failed", true));
1006
+ });
1007
+ return {
1008
+ push: /* @__PURE__ */ __name((text) => send({
1009
+ type: "text",
1010
+ text
1011
+ }), "push"),
1012
+ flush: /* @__PURE__ */ __name(() => send({
1013
+ type: "flush"
1014
+ }), "flush"),
1015
+ end: /* @__PURE__ */ __name(() => send({
1016
+ type: "end"
1017
+ }), "end"),
1018
+ close: /* @__PURE__ */ __name(() => {
1019
+ events.finish();
1020
+ socket.close();
1021
+ }, "close"),
1022
+ events
1023
+ };
1024
+ }
1025
+ __name(speakStream, "speakStream");
1026
+ var Inbox = class Inbox2 {
1027
+ static {
1028
+ __name(this, "Inbox");
1029
+ }
1030
+ #items = [];
1031
+ #ended;
1032
+ #wake;
1033
+ put(item) {
1034
+ if (this.#ended) return;
1035
+ this.#items.push(item);
1036
+ this.#wake?.();
1037
+ }
1038
+ finish() {
1039
+ this.#ended ??= {};
1040
+ this.#wake?.();
1041
+ }
1042
+ fail(error) {
1043
+ this.#ended ??= {
1044
+ error
1045
+ };
1046
+ this.#wake?.();
1047
+ }
1048
+ async *[Symbol.asyncIterator]() {
1049
+ for (; ; ) {
1050
+ if (this.#items.length > 0) {
1051
+ yield this.#items.shift();
1052
+ continue;
1053
+ }
1054
+ if (this.#ended) {
1055
+ if (this.#ended.error) throw this.#ended.error;
1056
+ return;
1057
+ }
1058
+ await new Promise((wake) => this.#wake = wake);
1059
+ this.#wake = void 0;
1060
+ }
1061
+ }
1062
+ };
959
1063
  export {
960
1064
  PublicClient,
961
1065
  RhapsodeSdk,
962
1066
  SdkError,
1067
+ SpeakStreamError,
963
1068
  bigIntReplacer,
964
1069
  bigIntReviver,
965
1070
  buildHeaders,
@@ -968,6 +1073,7 @@ export {
968
1073
  parseBigIntHeader,
969
1074
  parseJson,
970
1075
  parseJsonWithBigInt,
971
- readContentType
1076
+ readContentType,
1077
+ speakStream
972
1078
  };
973
1079
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/generated/sdk-options.ts","../src/generated/public/public.client.ts","../src/generated/rhapsode.sdk.ts"],"sourcesContent":["export class SdkError<TBody = unknown> extends Error {\n constructor(\n public readonly status: number,\n public readonly statusText: string,\n public readonly body: TBody,\n public readonly headers: Headers,\n ) {\n super(`${status} ${statusText}`);\n this.name = 'SdkError';\n }\n}\n\nexport interface SdkRequestInit extends RequestInit {\n /**\n * Statuses this operation declares as values rather than errors — a 304 from\n * conditional-GET middleware, or an error status the service returns deliberately.\n * Anything else at or above 400 still throws SdkError.\n */\n expectStatuses?: number[];\n}\n\nexport type SdkFetch = (url: string, init: SdkRequestInit) => Promise<Response>;\n\nexport interface SdkOptions {\n baseUrl: string;\n headers?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>);\n fetch?: SdkFetch;\n /** Called once per request to produce a unique X-Request-ID header value */\n requestIdFactory?: () => string;\n}\n\nexport const bigIntReplacer = (_: string, value: any): any => {\n if (typeof value === 'bigint') {\n return value.toString() + 'n';\n }\n return value;\n};\n\nexport const bigIntReviver = (_: string, value: any): any => {\n if (typeof value === 'string' && /^-?\\d+n$/.test(value)) {\n return BigInt(value.slice(0, -1));\n }\n return value;\n};\n\nexport type JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue };\n\nexport function readContentType(res: Response): string {\n return res.headers.get('content-type')?.split(';')[0]?.trim() ?? '';\n}\n\n/** A v4 UUID. `crypto.randomUUID` exists only in a secure context, so plain HTTP builds one by hand. */\nfunction randomRequestId(): string {\n if (typeof crypto.randomUUID === 'function') return crypto.randomUUID();\n const bytes = crypto.getRandomValues(new Uint8Array(16));\n bytes[6] = (bytes[6]! & 0x0f) | 0x40;\n bytes[8] = (bytes[8]! & 0x3f) | 0x80;\n const hex = Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\nexport function createSdkFetch(options: SdkOptions): SdkFetch {\n const getRequestId = options.requestIdFactory ?? randomRequestId;\n return async (url: string, init: SdkRequestInit): Promise<Response> => {\n const baseHeaders = typeof options.headers === 'function' ? await options.headers() : (options.headers ?? {});\n const res = await fetch(`${options.baseUrl}${url}`, {\n ...init,\n headers: { ...baseHeaders, 'X-Request-ID': getRequestId(), ...(init.headers as Record<string, string>) },\n });\n if (!res.ok && !(init.expectStatuses ?? []).includes(res.status)) {\n const text = await res.text();\n let body: unknown;\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n throw new SdkError(res.status, res.statusText, body, res.headers);\n }\n return res;\n };\n}\n\nexport function buildQueryString(query: object | undefined): string {\n const searchParams = new URLSearchParams();\n if (query) {\n for (const [k, v] of Object.entries(query)) {\n if (v === undefined || v === null) continue;\n if (Array.isArray(v)) {\n for (const item of v) searchParams.append(k, String(item));\n } else searchParams.set(k, String(v));\n }\n }\n const qs = searchParams.toString();\n return qs ? `?${qs}` : '';\n}\n\nexport function buildHeaders(headers: object | undefined): Record<string, string> {\n const out: Record<string, string> = {};\n if (headers) {\n for (const [k, v] of Object.entries(headers)) {\n if (v === undefined || v === null) continue;\n out[k] = Array.isArray(v) ? v.map(String).join(', ') : String(v);\n }\n }\n return out;\n}\n\nexport function parseBigIntHeader(name: string, value: string): bigint {\n if (/^-?\\d+n?$/.test(value)) return BigInt(value.replace(/n$/, ''));\n throw new Error(`Response header '${name}' is not a bigint: ${JSON.stringify(value)}`);\n}\n\n/**\n * Read a JSON response body.\n *\n * No reviver: `bigIntReviver` matches any string of the form `123n` anywhere in the\n * document, so a contract with no bigint field would still have a legitimate string like\n * \"123n\" silently turned into a BigInt. Clients whose contracts do use bigint import\n * `parseJsonWithBigInt` under this name instead.\n */\nexport async function parseJson<T>(res: Response): Promise<T> {\n return JSON.parse(await res.text()) as T;\n}\n\n/** `parseJson` for contracts that declare a bigint, applying the `123n` reviver. */\nexport async function parseJsonWithBigInt<T>(res: Response): Promise<T> {\n return JSON.parse(await res.text(), bigIntReviver) as T;\n}\n","import type { SdkFetch } from '../sdk-options.js';\nimport { bigIntReplacer, parseJson, buildQueryString, readContentType } from '../sdk-options.js';\nimport type {\n Capabilities,\n CatalogEntry,\n CoreHealth,\n EngineDialogueRequest,\n EngineSpeakRequest,\n EngineSummary,\n ErrorBody,\n InstallJob,\n PullRequest,\n ReinstallOutdated,\n ResidencyDetail,\n UpdateStatus,\n Voice,\n WarmRequest,\n} from '../rhapsode/types/rhapsode.types.js';\nimport type { OpenApiDocument, Settings, SettingsPatch } from './types/rhapsode.public.js';\n\nexport class PublicClient {\n constructor(private fetch: SdkFetch) {}\n\n /**\n * @name Health\n * @description The core's own health, which answers even while every worker is down.\n */\n async health(): Promise<CoreHealth> {\n const result = await this.fetch(`/health`, { method: 'GET' });\n return await parseJson<CoreHealth>(result);\n }\n\n /**\n * @name Update status\n * @description Whether a newer rhapsode has been released, from a check made at most once a day.\n */\n async updateStatus(): Promise<UpdateStatus> {\n const result = await this.fetch(`/update`, { method: 'GET' });\n return await parseJson<UpdateStatus>(result);\n }\n\n /**\n * @name Check for an update\n * @description Asks GitHub for the latest release now, and answers once it has.\n */\n async checkForUpdate(): Promise<UpdateStatus> {\n const result = await this.fetch(`/update/check`, { method: 'POST' });\n return await parseJson<UpdateStatus>(result);\n }\n\n /**\n * @name Residency\n * @description What each engine holds in memory, how big it is and when it expires.\n */\n async residency(): Promise<ResidencyDetail> {\n const result = await this.fetch(`/residency`, { method: 'GET' });\n return await parseJson<ResidencyDetail>(result);\n }\n\n /**\n * @name OpenAPI document\n * @description This API as an OpenAPI 3.1 document, describing the core that serves it.\n */\n async openapi(): Promise<OpenApiDocument> {\n const result = await this.fetch(`/openapi.json`, { method: 'GET' });\n return await parseJson<OpenApiDocument>(result);\n }\n\n /**\n * @name Engines\n * @description Every declared engine, running or not, with its code and weights licences.\n */\n async engines(): Promise<EngineSummary[]> {\n const result = await this.fetch(`/engines`, { method: 'GET' });\n return await parseJson<EngineSummary[]>(result);\n }\n\n /**\n * @name Engine capabilities\n * @description What the engine can do with the variant it has loaded, and what its other variants could.\n */\n async engineCapabilities(\n engine: string,\n ): Promise<\n | { status: 200; contentType: 'application/json'; data: Capabilities }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 503; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}/capabilities`, {\n method: 'GET',\n expectStatuses: [404, 503],\n });\n switch (result.status) {\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 503:\n return { status: 503, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 200, contentType: 'application/json', data: await parseJson<Capabilities>(result) };\n }\n }\n\n /**\n * @name Voices\n * @description The engine's voices, built in and cloned.\n */\n async engineVoices(\n engine: string,\n ): Promise<{ status: 200; contentType: 'application/json'; data: Voice[] } | { status: 404; contentType: 'application/json'; data: ErrorBody }> {\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}/voices`, {\n method: 'GET',\n expectStatuses: [404],\n });\n switch (result.status) {\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 200, contentType: 'application/json', data: await parseJson<Voice[]>(result) };\n }\n }\n\n /**\n * @name Create a voice\n * @description Creates a voice from a reference, such as a clip to clone, or from a blend of voices the engine has.\n */\n async createVoice(\n engine: string,\n body: FormData,\n ): Promise<\n | { status: 201; contentType: 'application/json'; data: Voice }\n | { status: 400; contentType: 'application/json'; data: ErrorBody }\n | { status: 403; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 422; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}/voices`, {\n method: 'POST',\n body: body,\n expectStatuses: [400, 403, 404, 422],\n });\n switch (result.status) {\n case 400:\n return { status: 400, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 422:\n return { status: 422, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 201, contentType: 'application/json', data: await parseJson<Voice>(result) };\n }\n }\n\n /**\n * @name Delete a voice\n * @description Deletes a voice.\n */\n async deleteVoice(\n engine: string,\n voice: string,\n ): Promise<\n | { status: 204 }\n | { status: 400; contentType: 'application/json'; data: ErrorBody }\n | { status: 403; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 422; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}/voices/${encodeURIComponent(voice)}`, {\n method: 'DELETE',\n expectStatuses: [400, 403, 404, 422],\n });\n switch (result.status) {\n case 400:\n return { status: 400, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 422:\n return { status: 422, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 204 };\n }\n }\n\n /**\n * @name Voice preview\n * @description A short sample of the voice.\n */\n async voicePreview(\n engine: string,\n voice: string,\n ): Promise<{ status: 200; contentType: 'audio/wav'; data: Blob } | { status: 404; contentType: 'application/json'; data: ErrorBody }> {\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}/voices/${encodeURIComponent(voice)}/preview`, {\n method: 'GET',\n expectStatuses: [404],\n });\n switch (result.status) {\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 200, contentType: 'audio/wav', data: await result.blob() };\n }\n }\n\n /**\n * @name Speak\n * @description Speaks a line with one engine, streamed or as a finished file.\n */\n async speak(\n body: EngineSpeakRequest,\n ): Promise<\n | { status: 200; contentType: 'audio/wav' | 'audio/mpeg' | 'audio/opus' | 'audio/flac' | 'audio/l16'; data: Blob }\n | { status: 400; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 422; contentType: 'application/json'; data: ErrorBody }\n | { status: 429; contentType: 'application/json'; data: ErrorBody }\n | { status: 503; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/speak`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body, bigIntReplacer),\n expectStatuses: [400, 404, 422, 429, 503],\n });\n switch (result.status) {\n case 400:\n return { status: 400, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 422:\n return { status: 422, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 429:\n return { status: 429, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 503:\n return { status: 503, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return {\n status: 200,\n contentType: readContentType(result) as 'audio/wav' | 'audio/mpeg' | 'audio/opus' | 'audio/flac' | 'audio/l16',\n data: await result.blob(),\n };\n }\n }\n\n /**\n * @name Dialogue\n * @description A conversation between speakers in one take, on a variant that declares dialogue.\n */\n async dialogue(\n engine: string,\n body: EngineDialogueRequest,\n ): Promise<\n | { status: 200; contentType: 'audio/wav' | 'audio/mpeg' | 'audio/opus' | 'audio/flac' | 'audio/l16'; data: Blob }\n | { status: 400; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 422; contentType: 'application/json'; data: ErrorBody }\n | { status: 429; contentType: 'application/json'; data: ErrorBody }\n | { status: 503; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}/dialogue`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body, bigIntReplacer),\n expectStatuses: [400, 404, 422, 429, 503],\n });\n switch (result.status) {\n case 400:\n return { status: 400, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 422:\n return { status: 422, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 429:\n return { status: 429, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 503:\n return { status: 503, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return {\n status: 200,\n contentType: readContentType(result) as 'audio/wav' | 'audio/mpeg' | 'audio/opus' | 'audio/flac' | 'audio/l16',\n data: await result.blob(),\n };\n }\n }\n\n /**\n * @name Catalog\n * @description Every engine this core knows how to install, with both licences, before anything is installed.\n */\n async catalog(): Promise<CatalogEntry[]> {\n const result = await this.fetch(`/catalog`, { method: 'GET' });\n return await parseJson<CatalogEntry[]>(result);\n }\n\n /**\n * @name Uninstall an engine\n * @description Removes an engine this API installed.\n */\n async uninstallEngine(\n engine: string,\n ): Promise<\n | { status: 204 }\n | { status: 403; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 409; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}`, {\n method: 'DELETE',\n expectStatuses: [403, 404, 409],\n });\n switch (result.status) {\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 409:\n return { status: 409, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 204 };\n }\n }\n\n /**\n * @name Unload an engine\n * @description Frees the engine's model now, rather than waiting out its keep-alive.\n */\n async unloadEngine(\n engine: string,\n query?: { mode?: 'terminate' | 'unload' },\n ): Promise<\n | { status: 200; contentType: 'application/json'; data: EngineSummary }\n | { status: 403; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 409; contentType: 'application/json'; data: ErrorBody }\n > {\n const qs = buildQueryString(query);\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}/unload${qs}`, {\n method: 'POST',\n expectStatuses: [403, 404, 409],\n });\n switch (result.status) {\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 409:\n return { status: 409, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 200, contentType: 'application/json', data: await parseJson<EngineSummary>(result) };\n }\n }\n\n /**\n * @name Install an engine\n * @description Installs an engine from the catalog, as a job to follow.\n */\n async installEngine(\n engine: string,\n query?: { pull?: string; accept?: string },\n ): Promise<\n | { status: 202; contentType: 'application/json'; data: InstallJob }\n | { status: 400; contentType: 'application/json'; data: ErrorBody }\n | { status: 403; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 409; contentType: 'application/json'; data: ErrorBody }\n > {\n const qs = buildQueryString(query);\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}/install${qs}`, {\n method: 'POST',\n expectStatuses: [400, 403, 404, 409],\n });\n switch (result.status) {\n case 400:\n return { status: 400, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 409:\n return { status: 409, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 202, contentType: 'application/json', data: await parseJson<InstallJob>(result) };\n }\n }\n\n /**\n * @name Reinstall an engine\n * @description Rebuilds an installed engine beside the old one and swaps it in once it works.\n */\n async reinstallEngine(\n engine: string,\n query?: { accept?: string },\n ): Promise<\n | { status: 202; contentType: 'application/json'; data: InstallJob }\n | { status: 400; contentType: 'application/json'; data: ErrorBody }\n | { status: 403; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 409; contentType: 'application/json'; data: ErrorBody }\n > {\n const qs = buildQueryString(query);\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}/reinstall${qs}`, {\n method: 'POST',\n expectStatuses: [400, 403, 404, 409],\n });\n switch (result.status) {\n case 400:\n return { status: 400, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 409:\n return { status: 409, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 202, contentType: 'application/json', data: await parseJson<InstallJob>(result) };\n }\n }\n\n /**\n * @name Pull weights\n * @description Downloads a variant's weights ahead of its first load, as a job to follow.\n */\n async pullEngine(\n engine: string,\n body: PullRequest,\n ): Promise<\n | { status: 202; contentType: 'application/json'; data: InstallJob }\n | { status: 403; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 409; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}/pull`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body, bigIntReplacer),\n expectStatuses: [403, 404, 409],\n });\n switch (result.status) {\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 409:\n return { status: 409, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 202, contentType: 'application/json', data: await parseJson<InstallJob>(result) };\n }\n }\n\n /**\n * @name Warm a variant\n * @description Loads a variant that compiles and unloads it, so its first request does not compile.\n */\n async warmEngine(\n engine: string,\n body: WarmRequest,\n ): Promise<\n | { status: 202; contentType: 'application/json'; data: InstallJob }\n | { status: 403; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 409; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}/warm`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body, bigIntReplacer),\n expectStatuses: [403, 404, 409],\n });\n switch (result.status) {\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 409:\n return { status: 409, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 202, contentType: 'application/json', data: await parseJson<InstallJob>(result) };\n }\n }\n\n /**\n * @name Install jobs\n * @description Every install job, running and finished.\n */\n async installJobs(): Promise<\n { status: 200; contentType: 'application/json'; data: InstallJob[] } | { status: 403; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/installs`, {\n method: 'GET',\n expectStatuses: [403],\n });\n switch (result.status) {\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 200, contentType: 'application/json', data: await parseJson<InstallJob[]>(result) };\n }\n }\n\n /**\n * @name Reinstall outdated engines\n * @description Reinstalls every engine an upgrade left behind.\n */\n async reinstallOutdated(): Promise<\n { status: 202; contentType: 'application/json'; data: ReinstallOutdated } | { status: 403; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/installs/outdated`, {\n method: 'POST',\n expectStatuses: [403],\n });\n switch (result.status) {\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 202, contentType: 'application/json', data: await parseJson<ReinstallOutdated>(result) };\n }\n }\n\n /**\n * @name Install job\n * @description One install job and where it has got to.\n */\n async installJob(\n job: string,\n ): Promise<\n | { status: 200; contentType: 'application/json'; data: InstallJob }\n | { status: 403; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/installs/${encodeURIComponent(job)}`, {\n method: 'GET',\n expectStatuses: [403, 404],\n });\n switch (result.status) {\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 200, contentType: 'application/json', data: await parseJson<InstallJob>(result) };\n }\n }\n\n /**\n * @name Install job events\n * @description An install job's progress and output as server-sent events.\n */\n async installJobEvents(\n job: string,\n ): Promise<\n | { status: 200; contentType: 'text/event-stream'; data: string }\n | { status: 403; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/installs/${encodeURIComponent(job)}/events`, {\n method: 'GET',\n expectStatuses: [403, 404],\n });\n switch (result.status) {\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 200, contentType: 'text/event-stream', data: await result.text() };\n }\n }\n\n /**\n * @name Settings\n * @description Every setting, its value, where the value came from and whether a change applies now.\n */\n async settings(): Promise<\n { status: 200; contentType: 'application/json'; data: Settings } | { status: 403; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/settings`, {\n method: 'GET',\n expectStatuses: [403],\n });\n switch (result.status) {\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 200, contentType: 'application/json', data: await parseJson<Settings>(result) };\n }\n }\n\n /**\n * @name Update settings\n * @description Changes settings in one transaction, and answers the whole document after the write.\n */\n async updateSettings(\n body: SettingsPatch,\n ): Promise<\n | { status: 200; contentType: 'application/json'; data: Settings }\n | { status: 400; contentType: 'application/json'; data: ErrorBody }\n | { status: 403; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 409; contentType: 'application/json'; data: ErrorBody }\n | { status: 422; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/settings`, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body, bigIntReplacer),\n expectStatuses: [400, 403, 404, 409, 422],\n });\n switch (result.status) {\n case 400:\n return { status: 400, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 409:\n return { status: 409, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 422:\n return { status: 422, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 200, contentType: 'application/json', data: await parseJson<Settings>(result) };\n }\n }\n}\n","import type { SdkOptions } from './sdk-options.js';\nimport { createSdkFetch } from './sdk-options.js';\nimport { PublicClient } from './public/public.client.js';\n\nexport class RhapsodeSdk {\n readonly public: PublicClient;\n\n constructor(options: SdkOptions) {\n const sdkFetch = options.fetch ?? createSdkFetch(options);\n this.public = new PublicClient(sdkFetch);\n }\n}\n"],"mappings":"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","names":["SdkError","Error","status","statusText","body","headers","name","bigIntReplacer","_","value","toString","bigIntReviver","test","BigInt","slice","readContentType","res","get","split","trim","randomRequestId","crypto","randomUUID","bytes","getRandomValues","Uint8Array","hex","Array","from","b","padStart","join","createSdkFetch","options","getRequestId","requestIdFactory","url","init","baseHeaders","fetch","baseUrl","ok","expectStatuses","includes","text","JSON","parse","buildQueryString","query","searchParams","URLSearchParams","k","v","Object","entries","undefined","isArray","item","append","String","set","qs","buildHeaders","out","map","parseBigIntHeader","replace","stringify","parseJson","parseJsonWithBigInt","PublicClient","fetch","health","result","method","parseJson","updateStatus","checkForUpdate","residency","openapi","engines","engineCapabilities","engine","encodeURIComponent","expectStatuses","status","contentType","data","engineVoices","createVoice","body","deleteVoice","voice","voicePreview","blob","speak","headers","JSON","stringify","bigIntReplacer","readContentType","dialogue","catalog","uninstallEngine","unloadEngine","query","qs","buildQueryString","installEngine","reinstallEngine","pullEngine","warmEngine","installJobs","reinstallOutdated","installJob","job","installJobEvents","text","settings","updateSettings","RhapsodeSdk","public","options","sdkFetch","fetch","createSdkFetch","PublicClient"]}
1
+ {"version":3,"sources":["../src/generated/sdk-options.ts","../src/generated/public/public.client.ts","../src/generated/rhapsode.sdk.ts","../src/speak.stream.ts"],"sourcesContent":["export class SdkError<TBody = unknown> extends Error {\n constructor(\n public readonly status: number,\n public readonly statusText: string,\n public readonly body: TBody,\n public readonly headers: Headers,\n ) {\n super(`${status} ${statusText}`);\n this.name = 'SdkError';\n }\n}\n\nexport interface SdkRequestInit extends RequestInit {\n /**\n * Statuses this operation declares as values rather than errors — a 304 from\n * conditional-GET middleware, or an error status the service returns deliberately.\n * Anything else at or above 400 still throws SdkError.\n */\n expectStatuses?: number[];\n}\n\nexport type SdkFetch = (url: string, init: SdkRequestInit) => Promise<Response>;\n\nexport interface SdkOptions {\n baseUrl: string;\n headers?: Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>);\n fetch?: SdkFetch;\n /** Called once per request to produce a unique X-Request-ID header value */\n requestIdFactory?: () => string;\n}\n\nexport const bigIntReplacer = (_: string, value: any): any => {\n if (typeof value === 'bigint') {\n return value.toString() + 'n';\n }\n return value;\n};\n\nexport const bigIntReviver = (_: string, value: any): any => {\n if (typeof value === 'string' && /^-?\\d+n$/.test(value)) {\n return BigInt(value.slice(0, -1));\n }\n return value;\n};\n\nexport type JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue };\n\nexport function readContentType(res: Response): string {\n return res.headers.get('content-type')?.split(';')[0]?.trim() ?? '';\n}\n\n/** A v4 UUID. `crypto.randomUUID` exists only in a secure context, so plain HTTP builds one by hand. */\nfunction randomRequestId(): string {\n if (typeof crypto.randomUUID === 'function') return crypto.randomUUID();\n const bytes = crypto.getRandomValues(new Uint8Array(16));\n bytes[6] = (bytes[6]! & 0x0f) | 0x40;\n bytes[8] = (bytes[8]! & 0x3f) | 0x80;\n const hex = Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\nexport function createSdkFetch(options: SdkOptions): SdkFetch {\n const getRequestId = options.requestIdFactory ?? randomRequestId;\n return async (url: string, init: SdkRequestInit): Promise<Response> => {\n const baseHeaders = typeof options.headers === 'function' ? await options.headers() : (options.headers ?? {});\n const res = await fetch(`${options.baseUrl}${url}`, {\n ...init,\n headers: { ...baseHeaders, 'X-Request-ID': getRequestId(), ...(init.headers as Record<string, string>) },\n });\n if (!res.ok && !(init.expectStatuses ?? []).includes(res.status)) {\n const text = await res.text();\n let body: unknown;\n try {\n body = JSON.parse(text);\n } catch {\n body = text;\n }\n throw new SdkError(res.status, res.statusText, body, res.headers);\n }\n return res;\n };\n}\n\nexport function buildQueryString(query: object | undefined): string {\n const searchParams = new URLSearchParams();\n if (query) {\n for (const [k, v] of Object.entries(query)) {\n if (v === undefined || v === null) continue;\n if (Array.isArray(v)) {\n for (const item of v) searchParams.append(k, String(item));\n } else searchParams.set(k, String(v));\n }\n }\n const qs = searchParams.toString();\n return qs ? `?${qs}` : '';\n}\n\nexport function buildHeaders(headers: object | undefined): Record<string, string> {\n const out: Record<string, string> = {};\n if (headers) {\n for (const [k, v] of Object.entries(headers)) {\n if (v === undefined || v === null) continue;\n out[k] = Array.isArray(v) ? v.map(String).join(', ') : String(v);\n }\n }\n return out;\n}\n\nexport function parseBigIntHeader(name: string, value: string): bigint {\n if (/^-?\\d+n?$/.test(value)) return BigInt(value.replace(/n$/, ''));\n throw new Error(`Response header '${name}' is not a bigint: ${JSON.stringify(value)}`);\n}\n\n/**\n * Read a JSON response body.\n *\n * No reviver: `bigIntReviver` matches any string of the form `123n` anywhere in the\n * document, so a contract with no bigint field would still have a legitimate string like\n * \"123n\" silently turned into a BigInt. Clients whose contracts do use bigint import\n * `parseJsonWithBigInt` under this name instead.\n */\nexport async function parseJson<T>(res: Response): Promise<T> {\n return JSON.parse(await res.text()) as T;\n}\n\n/** `parseJson` for contracts that declare a bigint, applying the `123n` reviver. */\nexport async function parseJsonWithBigInt<T>(res: Response): Promise<T> {\n return JSON.parse(await res.text(), bigIntReviver) as T;\n}\n","import type { SdkFetch } from '../sdk-options.js';\nimport { bigIntReplacer, parseJson, buildQueryString, readContentType } from '../sdk-options.js';\nimport type {\n Capabilities,\n CatalogEntry,\n CoreHealth,\n EngineDialogueRequest,\n EngineSpeakRequest,\n EngineSummary,\n ErrorBody,\n InstallJob,\n PullRequest,\n ReinstallOutdated,\n ResidencyDetail,\n UpdateStatus,\n Voice,\n WarmRequest,\n} from '../rhapsode/types/rhapsode.types.js';\nimport type { OpenApiDocument, Settings, SettingsPatch } from './types/rhapsode.public.js';\n\nexport class PublicClient {\n constructor(private fetch: SdkFetch) {}\n\n /**\n * @name Health\n * @description The core's own health, which answers even while every worker is down.\n */\n async health(): Promise<CoreHealth> {\n const result = await this.fetch(`/health`, { method: 'GET' });\n return await parseJson<CoreHealth>(result);\n }\n\n /**\n * @name Update status\n * @description Whether a newer rhapsode has been released, from a check made at most once a day.\n */\n async updateStatus(): Promise<UpdateStatus> {\n const result = await this.fetch(`/update`, { method: 'GET' });\n return await parseJson<UpdateStatus>(result);\n }\n\n /**\n * @name Check for an update\n * @description Asks GitHub for the latest release now, and answers once it has.\n */\n async checkForUpdate(): Promise<UpdateStatus> {\n const result = await this.fetch(`/update/check`, { method: 'POST' });\n return await parseJson<UpdateStatus>(result);\n }\n\n /**\n * @name Residency\n * @description What each engine holds in memory, how big it is and when it expires.\n */\n async residency(): Promise<ResidencyDetail> {\n const result = await this.fetch(`/residency`, { method: 'GET' });\n return await parseJson<ResidencyDetail>(result);\n }\n\n /**\n * @name OpenAPI document\n * @description This API as an OpenAPI 3.1 document, describing the core that serves it.\n */\n async openapi(): Promise<OpenApiDocument> {\n const result = await this.fetch(`/openapi.json`, { method: 'GET' });\n return await parseJson<OpenApiDocument>(result);\n }\n\n /**\n * @name Engines\n * @description Every declared engine, running or not, with its code and weights licences.\n */\n async engines(): Promise<EngineSummary[]> {\n const result = await this.fetch(`/engines`, { method: 'GET' });\n return await parseJson<EngineSummary[]>(result);\n }\n\n /**\n * @name Engine capabilities\n * @description What the engine can do with the variant it has loaded, and what its other variants could.\n */\n async engineCapabilities(\n engine: string,\n ): Promise<\n | { status: 200; contentType: 'application/json'; data: Capabilities }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 503; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}/capabilities`, {\n method: 'GET',\n expectStatuses: [404, 503],\n });\n switch (result.status) {\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 503:\n return { status: 503, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 200, contentType: 'application/json', data: await parseJson<Capabilities>(result) };\n }\n }\n\n /**\n * @name Voices\n * @description The engine's voices, built in and cloned.\n */\n async engineVoices(\n engine: string,\n ): Promise<{ status: 200; contentType: 'application/json'; data: Voice[] } | { status: 404; contentType: 'application/json'; data: ErrorBody }> {\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}/voices`, {\n method: 'GET',\n expectStatuses: [404],\n });\n switch (result.status) {\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 200, contentType: 'application/json', data: await parseJson<Voice[]>(result) };\n }\n }\n\n /**\n * @name Create a voice\n * @description Creates a voice from a reference, such as a clip to clone, or from a blend of voices the engine has.\n */\n async createVoice(\n engine: string,\n body: FormData,\n ): Promise<\n | { status: 201; contentType: 'application/json'; data: Voice }\n | { status: 400; contentType: 'application/json'; data: ErrorBody }\n | { status: 403; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 422; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}/voices`, {\n method: 'POST',\n body: body,\n expectStatuses: [400, 403, 404, 422],\n });\n switch (result.status) {\n case 400:\n return { status: 400, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 422:\n return { status: 422, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 201, contentType: 'application/json', data: await parseJson<Voice>(result) };\n }\n }\n\n /**\n * @name Delete a voice\n * @description Deletes a voice.\n */\n async deleteVoice(\n engine: string,\n voice: string,\n ): Promise<\n | { status: 204 }\n | { status: 400; contentType: 'application/json'; data: ErrorBody }\n | { status: 403; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 422; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}/voices/${encodeURIComponent(voice)}`, {\n method: 'DELETE',\n expectStatuses: [400, 403, 404, 422],\n });\n switch (result.status) {\n case 400:\n return { status: 400, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 422:\n return { status: 422, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 204 };\n }\n }\n\n /**\n * @name Voice preview\n * @description A short sample of the voice.\n */\n async voicePreview(\n engine: string,\n voice: string,\n ): Promise<{ status: 200; contentType: 'audio/wav'; data: Blob } | { status: 404; contentType: 'application/json'; data: ErrorBody }> {\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}/voices/${encodeURIComponent(voice)}/preview`, {\n method: 'GET',\n expectStatuses: [404],\n });\n switch (result.status) {\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 200, contentType: 'audio/wav', data: await result.blob() };\n }\n }\n\n /**\n * @name Speak\n * @description Speaks a line with one engine, streamed or as a finished file.\n */\n async speak(\n body: EngineSpeakRequest,\n ): Promise<\n | { status: 200; contentType: 'audio/wav' | 'audio/mpeg' | 'audio/opus' | 'audio/flac' | 'audio/l16'; data: Blob }\n | { status: 400; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 422; contentType: 'application/json'; data: ErrorBody }\n | { status: 429; contentType: 'application/json'; data: ErrorBody }\n | { status: 503; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/speak`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body, bigIntReplacer),\n expectStatuses: [400, 404, 422, 429, 503],\n });\n switch (result.status) {\n case 400:\n return { status: 400, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 422:\n return { status: 422, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 429:\n return { status: 429, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 503:\n return { status: 503, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return {\n status: 200,\n contentType: readContentType(result) as 'audio/wav' | 'audio/mpeg' | 'audio/opus' | 'audio/flac' | 'audio/l16',\n data: await result.blob(),\n };\n }\n }\n\n /**\n * @name Dialogue\n * @description A conversation between speakers in one take, on a variant that declares dialogue.\n */\n async dialogue(\n engine: string,\n body: EngineDialogueRequest,\n ): Promise<\n | { status: 200; contentType: 'audio/wav' | 'audio/mpeg' | 'audio/opus' | 'audio/flac' | 'audio/l16'; data: Blob }\n | { status: 400; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 422; contentType: 'application/json'; data: ErrorBody }\n | { status: 429; contentType: 'application/json'; data: ErrorBody }\n | { status: 503; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}/dialogue`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body, bigIntReplacer),\n expectStatuses: [400, 404, 422, 429, 503],\n });\n switch (result.status) {\n case 400:\n return { status: 400, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 422:\n return { status: 422, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 429:\n return { status: 429, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 503:\n return { status: 503, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return {\n status: 200,\n contentType: readContentType(result) as 'audio/wav' | 'audio/mpeg' | 'audio/opus' | 'audio/flac' | 'audio/l16',\n data: await result.blob(),\n };\n }\n }\n\n /**\n * @name Catalog\n * @description Every engine this core knows how to install, with both licences, before anything is installed.\n */\n async catalog(): Promise<CatalogEntry[]> {\n const result = await this.fetch(`/catalog`, { method: 'GET' });\n return await parseJson<CatalogEntry[]>(result);\n }\n\n /**\n * @name Uninstall an engine\n * @description Removes an engine this API installed.\n */\n async uninstallEngine(\n engine: string,\n ): Promise<\n | { status: 204 }\n | { status: 403; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 409; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}`, {\n method: 'DELETE',\n expectStatuses: [403, 404, 409],\n });\n switch (result.status) {\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 409:\n return { status: 409, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 204 };\n }\n }\n\n /**\n * @name Unload an engine\n * @description Frees the engine's model now, rather than waiting out its keep-alive.\n */\n async unloadEngine(\n engine: string,\n query?: { mode?: 'terminate' | 'unload' },\n ): Promise<\n | { status: 200; contentType: 'application/json'; data: EngineSummary }\n | { status: 403; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 409; contentType: 'application/json'; data: ErrorBody }\n > {\n const qs = buildQueryString(query);\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}/unload${qs}`, {\n method: 'POST',\n expectStatuses: [403, 404, 409],\n });\n switch (result.status) {\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 409:\n return { status: 409, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 200, contentType: 'application/json', data: await parseJson<EngineSummary>(result) };\n }\n }\n\n /**\n * @name Install an engine\n * @description Installs an engine from the catalog, as a job to follow.\n */\n async installEngine(\n engine: string,\n query?: { pull?: string; accept?: string },\n ): Promise<\n | { status: 202; contentType: 'application/json'; data: InstallJob }\n | { status: 400; contentType: 'application/json'; data: ErrorBody }\n | { status: 403; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 409; contentType: 'application/json'; data: ErrorBody }\n > {\n const qs = buildQueryString(query);\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}/install${qs}`, {\n method: 'POST',\n expectStatuses: [400, 403, 404, 409],\n });\n switch (result.status) {\n case 400:\n return { status: 400, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 409:\n return { status: 409, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 202, contentType: 'application/json', data: await parseJson<InstallJob>(result) };\n }\n }\n\n /**\n * @name Reinstall an engine\n * @description Rebuilds an installed engine beside the old one and swaps it in once it works.\n */\n async reinstallEngine(\n engine: string,\n query?: { accept?: string },\n ): Promise<\n | { status: 202; contentType: 'application/json'; data: InstallJob }\n | { status: 400; contentType: 'application/json'; data: ErrorBody }\n | { status: 403; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 409; contentType: 'application/json'; data: ErrorBody }\n > {\n const qs = buildQueryString(query);\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}/reinstall${qs}`, {\n method: 'POST',\n expectStatuses: [400, 403, 404, 409],\n });\n switch (result.status) {\n case 400:\n return { status: 400, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 409:\n return { status: 409, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 202, contentType: 'application/json', data: await parseJson<InstallJob>(result) };\n }\n }\n\n /**\n * @name Pull weights\n * @description Downloads a variant's weights ahead of its first load, as a job to follow.\n */\n async pullEngine(\n engine: string,\n body: PullRequest,\n ): Promise<\n | { status: 202; contentType: 'application/json'; data: InstallJob }\n | { status: 403; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 409; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}/pull`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body, bigIntReplacer),\n expectStatuses: [403, 404, 409],\n });\n switch (result.status) {\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 409:\n return { status: 409, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 202, contentType: 'application/json', data: await parseJson<InstallJob>(result) };\n }\n }\n\n /**\n * @name Warm a variant\n * @description Loads a variant that compiles and unloads it, so its first request does not compile.\n */\n async warmEngine(\n engine: string,\n body: WarmRequest,\n ): Promise<\n | { status: 202; contentType: 'application/json'; data: InstallJob }\n | { status: 403; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 409; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/engines/${encodeURIComponent(engine)}/warm`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body, bigIntReplacer),\n expectStatuses: [403, 404, 409],\n });\n switch (result.status) {\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 409:\n return { status: 409, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 202, contentType: 'application/json', data: await parseJson<InstallJob>(result) };\n }\n }\n\n /**\n * @name Install jobs\n * @description Every install job, running and finished.\n */\n async installJobs(): Promise<\n { status: 200; contentType: 'application/json'; data: InstallJob[] } | { status: 403; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/installs`, {\n method: 'GET',\n expectStatuses: [403],\n });\n switch (result.status) {\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 200, contentType: 'application/json', data: await parseJson<InstallJob[]>(result) };\n }\n }\n\n /**\n * @name Reinstall outdated engines\n * @description Reinstalls every engine an upgrade left behind.\n */\n async reinstallOutdated(): Promise<\n { status: 202; contentType: 'application/json'; data: ReinstallOutdated } | { status: 403; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/installs/outdated`, {\n method: 'POST',\n expectStatuses: [403],\n });\n switch (result.status) {\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 202, contentType: 'application/json', data: await parseJson<ReinstallOutdated>(result) };\n }\n }\n\n /**\n * @name Install job\n * @description One install job and where it has got to.\n */\n async installJob(\n job: string,\n ): Promise<\n | { status: 200; contentType: 'application/json'; data: InstallJob }\n | { status: 403; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/installs/${encodeURIComponent(job)}`, {\n method: 'GET',\n expectStatuses: [403, 404],\n });\n switch (result.status) {\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 200, contentType: 'application/json', data: await parseJson<InstallJob>(result) };\n }\n }\n\n /**\n * @name Install job events\n * @description An install job's progress and output as server-sent events.\n */\n async installJobEvents(\n job: string,\n ): Promise<\n | { status: 200; contentType: 'text/event-stream'; data: string }\n | { status: 403; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/installs/${encodeURIComponent(job)}/events`, {\n method: 'GET',\n expectStatuses: [403, 404],\n });\n switch (result.status) {\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 200, contentType: 'text/event-stream', data: await result.text() };\n }\n }\n\n /**\n * @name Settings\n * @description Every setting, its value, where the value came from and whether a change applies now.\n */\n async settings(): Promise<\n { status: 200; contentType: 'application/json'; data: Settings } | { status: 403; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/settings`, {\n method: 'GET',\n expectStatuses: [403],\n });\n switch (result.status) {\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 200, contentType: 'application/json', data: await parseJson<Settings>(result) };\n }\n }\n\n /**\n * @name Update settings\n * @description Changes settings in one transaction, and answers the whole document after the write.\n */\n async updateSettings(\n body: SettingsPatch,\n ): Promise<\n | { status: 200; contentType: 'application/json'; data: Settings }\n | { status: 400; contentType: 'application/json'; data: ErrorBody }\n | { status: 403; contentType: 'application/json'; data: ErrorBody }\n | { status: 404; contentType: 'application/json'; data: ErrorBody }\n | { status: 409; contentType: 'application/json'; data: ErrorBody }\n | { status: 422; contentType: 'application/json'; data: ErrorBody }\n > {\n const result = await this.fetch(`/settings`, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body, bigIntReplacer),\n expectStatuses: [400, 403, 404, 409, 422],\n });\n switch (result.status) {\n case 400:\n return { status: 400, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 403:\n return { status: 403, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 404:\n return { status: 404, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 409:\n return { status: 409, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n case 422:\n return { status: 422, contentType: 'application/json', data: await parseJson<ErrorBody>(result) };\n default:\n return { status: 200, contentType: 'application/json', data: await parseJson<Settings>(result) };\n }\n }\n}\n","import type { SdkOptions } from './sdk-options.js';\nimport { createSdkFetch } from './sdk-options.js';\nimport { PublicClient } from './public/public.client.js';\n\nexport class RhapsodeSdk {\n readonly public: PublicClient;\n\n constructor(options: SdkOptions) {\n const sdkFetch = options.fetch ?? createSdkFetch(options);\n this.public = new PublicClient(sdkFetch);\n }\n}\n","/**\n * `GET /speak/stream`: text in as a language model writes it, audio out a sentence at a time.\n * protocol.md § 6, \"Speaking as the text arrives\".\n *\n * Written by hand, because the route is a WebSocket conversation and ContractKit describes requests\n * and responses. It uses the platform's own `WebSocket`, which browsers and Node 22 both have, so the\n * package still depends on nothing.\n */\n\n/** `/speak`'s fields without the text, which comes later, and `stream`. */\nexport interface SpeakStreamStart {\n engine: string;\n voice?: string;\n variant?: string;\n /** `pcm` is the only format a stream speaks, because pieces join by concatenation. */\n format?: 'pcm';\n language?: string;\n delivery?: string;\n params?: Record<string, number>;\n seed?: number;\n keepAliveSeconds?: number;\n}\n\n/** What the server says, in order, until it is done. */\nexport type SpeakStreamEvent =\n | { type: 'ready'; engine: string; variant: string }\n /** Once, before the first audio: the worker's `Content-Type`, which carries the rate. */\n | { type: 'format'; contentType: string }\n | { type: 'audio'; data: Uint8Array }\n /** After each piece's audio. */\n | { type: 'spoken'; index: number; characters: number; durationMs?: number };\n\n/** The protocol's error envelope, thrown from the events, which end with it. § 6. */\nexport class SpeakStreamError extends Error {\n constructor(\n readonly code: string,\n message: string,\n readonly retryable: boolean,\n ) {\n super(message);\n this.name = 'SpeakStreamError';\n }\n}\n\nexport interface SpeakStream {\n /** Add text, in whatever pieces it arrives in. */\n push(text: string): void;\n /** Speak what has arrived, finished or not. */\n flush(): void;\n /** Speak what is left, then finish. The events end once it has all been spoken. */\n end(): void;\n /** Stop now: the piece being spoken stops and nothing more is said. */\n close(): void;\n /** Everything the server says, ending at `done` and throwing a `SpeakStreamError` on an error. */\n events: AsyncIterable<SpeakStreamEvent>;\n}\n\n/**\n * Open a session. Frames sent before the socket opens are kept and sent once it does, so a caller can\n * start pushing text at once.\n *\n * @example\n * ```ts\n * const stream = speakStream('http://localhost:8080', { engine: 'kokoro', voice: 'af_bella' });\n * for await (const token of model.answer(question)) stream.push(token);\n * stream.end();\n * for await (const event of stream.events) if (event.type === 'audio') player.write(event.data);\n * ```\n */\nexport function speakStream(baseUrl: string, start: SpeakStreamStart): SpeakStream {\n const socket = new WebSocket(`${baseUrl.replace(/^http/, 'ws').replace(/\\/$/, '')}/speak/stream`);\n socket.binaryType = 'arraybuffer';\n\n const pending: string[] = [JSON.stringify({ type: 'start', ...start })];\n const send = (frame: object) => {\n const text = JSON.stringify(frame);\n if (socket.readyState === WebSocket.OPEN) socket.send(text);\n else pending.push(text);\n };\n socket.addEventListener('open', () => pending.splice(0).forEach(text => socket.send(text)));\n\n const events = new Inbox<SpeakStreamEvent>();\n socket.addEventListener('message', message => {\n if (typeof message.data !== 'string') {\n events.put({ type: 'audio', data: new Uint8Array(message.data as ArrayBuffer) });\n return;\n }\n const frame = JSON.parse(message.data) as { type: string; error?: { code: string; message: string; retryable: boolean } };\n if (frame.type === 'done') events.finish();\n else if (frame.type === 'error' && frame.error)\n events.fail(new SpeakStreamError(frame.error.code, frame.error.message, frame.error.retryable));\n else events.put(frame as SpeakStreamEvent);\n });\n socket.addEventListener('close', close => {\n events.fail(new SpeakStreamError('internal', `the server closed the session (${close.code}) before it was done`, true));\n });\n socket.addEventListener('error', () => {\n events.fail(new SpeakStreamError('internal', 'the session could not be opened or failed', true));\n });\n\n return {\n push: text => send({ type: 'text', text }),\n flush: () => send({ type: 'flush' }),\n end: () => send({ type: 'end' }),\n close: () => {\n events.finish();\n socket.close();\n },\n events,\n };\n}\n\n/** A queue read with `for await`, ending at `finish` or throwing at `fail`. The first ending wins. */\nclass Inbox<T> implements AsyncIterable<T> {\n #items: T[] = [];\n #ended?: { error?: Error };\n #wake?: () => void;\n\n put(item: T): void {\n if (this.#ended) return;\n this.#items.push(item);\n this.#wake?.();\n }\n\n finish(): void {\n this.#ended ??= {};\n this.#wake?.();\n }\n\n fail(error: Error): void {\n this.#ended ??= { error };\n this.#wake?.();\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<T> {\n for (;;) {\n if (this.#items.length > 0) {\n yield this.#items.shift()!;\n continue;\n }\n if (this.#ended) {\n if (this.#ended.error) throw this.#ended.error;\n return;\n }\n await new Promise<void>(wake => (this.#wake = wake));\n this.#wake = undefined;\n }\n }\n}\n"],"mappings":"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","names":["SdkError","Error","status","statusText","body","headers","name","bigIntReplacer","_","value","toString","bigIntReviver","test","BigInt","slice","readContentType","res","get","split","trim","randomRequestId","crypto","randomUUID","bytes","getRandomValues","Uint8Array","hex","Array","from","b","padStart","join","createSdkFetch","options","getRequestId","requestIdFactory","url","init","baseHeaders","fetch","baseUrl","ok","expectStatuses","includes","text","JSON","parse","buildQueryString","query","searchParams","URLSearchParams","k","v","Object","entries","undefined","isArray","item","append","String","set","qs","buildHeaders","out","map","parseBigIntHeader","replace","stringify","parseJson","parseJsonWithBigInt","PublicClient","fetch","health","result","method","parseJson","updateStatus","checkForUpdate","residency","openapi","engines","engineCapabilities","engine","encodeURIComponent","expectStatuses","status","contentType","data","engineVoices","createVoice","body","deleteVoice","voice","voicePreview","blob","speak","headers","JSON","stringify","bigIntReplacer","readContentType","dialogue","catalog","uninstallEngine","unloadEngine","query","qs","buildQueryString","installEngine","reinstallEngine","pullEngine","warmEngine","installJobs","reinstallOutdated","installJob","job","installJobEvents","text","settings","updateSettings","RhapsodeSdk","public","options","sdkFetch","fetch","createSdkFetch","PublicClient","SpeakStreamError","Error","code","message","retryable","name","speakStream","baseUrl","start","socket","WebSocket","replace","binaryType","pending","JSON","stringify","type","send","frame","text","readyState","OPEN","push","addEventListener","splice","forEach","events","Inbox","data","put","Uint8Array","parse","finish","error","fail","close","flush","end","item","Symbol","asyncIterator","length","shift","Promise","wake","undefined"]}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * `GET /speak/stream`: text in as a language model writes it, audio out a sentence at a time.
3
+ * protocol.md § 6, "Speaking as the text arrives".
4
+ *
5
+ * Written by hand, because the route is a WebSocket conversation and ContractKit describes requests
6
+ * and responses. It uses the platform's own `WebSocket`, which browsers and Node 22 both have, so the
7
+ * package still depends on nothing.
8
+ */
9
+ /** `/speak`'s fields without the text, which comes later, and `stream`. */
10
+ export interface SpeakStreamStart {
11
+ engine: string;
12
+ voice?: string;
13
+ variant?: string;
14
+ /** `pcm` is the only format a stream speaks, because pieces join by concatenation. */
15
+ format?: 'pcm';
16
+ language?: string;
17
+ delivery?: string;
18
+ params?: Record<string, number>;
19
+ seed?: number;
20
+ keepAliveSeconds?: number;
21
+ }
22
+ /** What the server says, in order, until it is done. */
23
+ export type SpeakStreamEvent = {
24
+ type: 'ready';
25
+ engine: string;
26
+ variant: string;
27
+ }
28
+ /** Once, before the first audio: the worker's `Content-Type`, which carries the rate. */
29
+ | {
30
+ type: 'format';
31
+ contentType: string;
32
+ } | {
33
+ type: 'audio';
34
+ data: Uint8Array;
35
+ }
36
+ /** After each piece's audio. */
37
+ | {
38
+ type: 'spoken';
39
+ index: number;
40
+ characters: number;
41
+ durationMs?: number;
42
+ };
43
+ /** The protocol's error envelope, thrown from the events, which end with it. § 6. */
44
+ export declare class SpeakStreamError extends Error {
45
+ readonly code: string;
46
+ readonly retryable: boolean;
47
+ constructor(code: string, message: string, retryable: boolean);
48
+ }
49
+ export interface SpeakStream {
50
+ /** Add text, in whatever pieces it arrives in. */
51
+ push(text: string): void;
52
+ /** Speak what has arrived, finished or not. */
53
+ flush(): void;
54
+ /** Speak what is left, then finish. The events end once it has all been spoken. */
55
+ end(): void;
56
+ /** Stop now: the piece being spoken stops and nothing more is said. */
57
+ close(): void;
58
+ /** Everything the server says, ending at `done` and throwing a `SpeakStreamError` on an error. */
59
+ events: AsyncIterable<SpeakStreamEvent>;
60
+ }
61
+ /**
62
+ * Open a session. Frames sent before the socket opens are kept and sent once it does, so a caller can
63
+ * start pushing text at once.
64
+ *
65
+ * @example
66
+ * ```ts
67
+ * const stream = speakStream('http://localhost:8080', { engine: 'kokoro', voice: 'af_bella' });
68
+ * for await (const token of model.answer(question)) stream.push(token);
69
+ * stream.end();
70
+ * for await (const event of stream.events) if (event.type === 'audio') player.write(event.data);
71
+ * ```
72
+ */
73
+ export declare function speakStream(baseUrl: string, start: SpeakStreamStart): SpeakStream;
74
+ //# sourceMappingURL=speak.stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speak.stream.d.ts","sourceRoot":"","sources":["../src/speak.stream.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,2EAA2E;AAC3E,MAAM,WAAW,gBAAgB;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sFAAsF;IACtF,MAAM,CAAC,EAAE,KAAK,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,wDAAwD;AACxD,MAAM,MAAM,gBAAgB,GACtB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AACpD,yFAAyF;GACvF;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE;AACrC,gCAAgC;GAC9B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjF,qFAAqF;AACrF,qBAAa,gBAAiB,SAAQ,KAAK;IAEnC,QAAQ,CAAC,IAAI,EAAE,MAAM;IAErB,QAAQ,CAAC,SAAS,EAAE,OAAO;gBAFlB,IAAI,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACN,SAAS,EAAE,OAAO;CAKlC;AAED,MAAM,WAAW,WAAW;IACxB,kDAAkD;IAClD,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,+CAA+C;IAC/C,KAAK,IAAI,IAAI,CAAC;IACd,mFAAmF;IACnF,GAAG,IAAI,IAAI,CAAC;IACZ,uEAAuE;IACvE,KAAK,IAAI,IAAI,CAAC;IACd,kGAAkG;IAClG,MAAM,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;CAC3C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,WAAW,CAyCjF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maroonedsoftware/rhapsode-sdk",
3
- "version": "0.1.22",
3
+ "version": "0.1.23",
4
4
  "description": "A typed client for the rhapsode public API, generated from contracts/.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -26,7 +26,7 @@
26
26
  "devDependencies": {
27
27
  "@repo/config-eslint": "0.0.0",
28
28
  "@repo/config-typescript": "0.0.0",
29
- "@rhapsode/core": "0.1.22",
29
+ "@rhapsode/core": "0.1.23",
30
30
  "vitest": "^5.0.2"
31
31
  },
32
32
  "publishConfig": {