@rimelabs/sdk 0.1.0-alpha.1

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/CHANGELOG.md ADDED
@@ -0,0 +1,16 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0-alpha.1
4
+
5
+ Initial local alpha for Node.js 22+ and ESM. Adds Coda synthesis, discovery,
6
+ API-key authentication, sentence buffering, PCM and mu-law profiles, typed errors,
7
+ deadlines, and cancellation. The Themis wire contract is assumed and needs
8
+ deployment validation.
9
+
10
+ Review fixes preserve zero-width spaces and BOM characters during sentence
11
+ mapping, distinguish token-exchange rate limits and service failures from
12
+ rejected credentials, and cancel failed HTTP response bodies.
13
+
14
+ Further review fixes stop pending reads after cancellation, preserve errors from
15
+ responses without audio metadata, handle responses with only trailers, and
16
+ collect discovery request IDs from headers and trailers.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rime
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,93 @@
1
+ # Rime SDK for Node.js
2
+
3
+ Requires Node.js 22 or later. The package uses ESM and includes TypeScript types.
4
+ Browser use is not supported. This is an alpha release.
5
+ Install it from npm using the `next` tag:
6
+
7
+ ```sh
8
+ npm install @rimelabs/sdk@next
9
+ ```
10
+
11
+ ```javascript
12
+ import { writeFile } from "node:fs/promises";
13
+ import { Rime, AudioFormat } from "@rimelabs/sdk";
14
+
15
+ const client = new Rime({ apiKey: "your-api-key" });
16
+ try {
17
+ const audio = client.tts.stream("Hello. This is Rime.", {
18
+ voice: "clementine",
19
+ audioFormat: AudioFormat.PCM_24000,
20
+ });
21
+ await writeFile("speech.pcm", audio);
22
+ console.log(audio.requestId);
23
+ } finally {
24
+ await client.close();
25
+ }
26
+ ```
27
+
28
+ Omit `apiKey` to read `RIME_API_KEY`. The default model is `coda`.
29
+ The SDK selects its standard endpoint. Only `coda` is currently supported.
30
+ For a custom deployment of that model, set `endpoint`:
31
+
32
+ ```javascript
33
+ const client = new Rime({ model: "coda", endpoint: "coda.api.customer-name.rime.ai" });
34
+ ```
35
+
36
+ Use a hostname with an optional port, such as `host:8443`. Omit the scheme and path.
37
+ Connections always use TLS; the default port is `443`.
38
+ The endpoint applies to speech, voices, and languages for this client.
39
+
40
+ The default voice is `clementine`; the default language is `en`.
41
+ `tts.stream()` also accepts `AsyncIterable<string>`. Do not await the factory.
42
+ The first iterator read starts work. A `for await` loop exit cancels the stream.
43
+ Use `await audio.cancel()` in a `finally` block if you read the iterator manually.
44
+
45
+ `await client.voices.list({ language: "en" })` returns voice names.
46
+ `await client.languages.list()` returns language codes.
47
+ Both accept an options object with `timeout` in seconds.
48
+
49
+ `new Rime({ timeout: 30 })` sets an overall timeout. An operation can replace
50
+ it with `{ timeout: 10 }` or disable it with `{ timeout: null }`.
51
+ An omitted or `undefined` option inherits the client setting. Internal connection
52
+ and progress limits still apply. An overall timeout continues during caller pauses.
53
+
54
+ `audio.format` is a read-only `AudioFormat` with `encoding`, `sampleRate`, and
55
+ `channels`. `PCM_24000` is raw signed 16-bit little-endian mono PCM at 24 kHz.
56
+ `MULAW_8000` is raw mono G.711 mu-law at 8 kHz. Neither includes a file header.
57
+ The iterator yields `Uint8Array` chunks with complete sample frames.
58
+ Chunk sizes are not fixed.
59
+
60
+ `await audio.cancel()` cancels one operation. `await client.close()` cancels all
61
+ client work. Both are idempotent. Both objects support `Symbol.asyncDispose`.
62
+ Normal iterator completion means that the final service status was successful.
63
+ Partial audio can precede a typed error. Synthesis is never replayed.
64
+
65
+ Catch `RimeError` or one of `RimeAuthenticationError`, `RimePermissionError`,
66
+ `RimeInputError`, `RimeResourceLimitError`, `RimeUnavailableError`,
67
+ `RimeTimeoutError`, `RimeAudioFormatError`, `RimeCancelledError`, or
68
+ `RimeStreamError`. Errors expose a message and optional `requestId`.
69
+ Cancellation cannot stop application code that waits on an unrelated promise.
70
+ The SDK stops its RPC and limits how long it waits for source cleanup.
71
+
72
+ The SDK sends the API key as a bearer token over TLS.
73
+
74
+ ## Development for contributors
75
+
76
+ These instructions require access to the source repository.
77
+ Run the commands from its `typescript/` directory:
78
+
79
+ ```sh
80
+ npm ci
81
+ npm run check
82
+ npm run lint
83
+ npm test
84
+ npm pack
85
+ ```
86
+
87
+ The package includes a pinned Microsoft BlingFire WASM binary and its license.
88
+ It does not download code at runtime. See [vendor provenance](vendor/README.md).
89
+
90
+ ## License
91
+
92
+ The SDK is licensed under the [MIT License](LICENSE).
93
+ BlingFire retains its [upstream license](vendor/LICENSE.blingfire).
@@ -0,0 +1,19 @@
1
+ export declare class AudioFormat {
2
+ readonly encoding: string;
3
+ readonly sampleRate: number;
4
+ readonly channels: number;
5
+ static readonly PCM_24000: Readonly<AudioFormat>;
6
+ static readonly MULAW_8000: Readonly<AudioFormat>;
7
+ private constructor();
8
+ }
9
+ export declare class Converter {
10
+ private profile;
11
+ private tail;
12
+ private samples;
13
+ private seen;
14
+ private emitted;
15
+ private inputSamples;
16
+ constructor(profile: AudioFormat);
17
+ private sample;
18
+ process(input: Uint8Array, final?: boolean): Buffer;
19
+ }
package/dist/audio.js ADDED
@@ -0,0 +1,73 @@
1
+ import { RimeAudioFormatError } from "./errors.js";
2
+ export class AudioFormat {
3
+ encoding;
4
+ sampleRate;
5
+ channels;
6
+ static PCM_24000 = Object.freeze(new AudioFormat("pcm_s16le", 24000, 1));
7
+ static MULAW_8000 = Object.freeze(new AudioFormat("mulaw", 8000, 1));
8
+ constructor(encoding, sampleRate, channels) {
9
+ this.encoding = encoding;
10
+ this.sampleRate = sampleRate;
11
+ this.channels = channels;
12
+ }
13
+ }
14
+ const raw = Array.from({ length: 63 }, (_, i) => (i === 31
15
+ ? (2 * 3400) / 24000
16
+ : Math.sin(((2 * Math.PI * 3400) / 24000) * (i - 31)) /
17
+ (Math.PI * (i - 31))) *
18
+ (0.54 - 0.46 * Math.cos((2 * Math.PI * i) / 62)));
19
+ const total = raw.reduce((a, b) => a + b, 0);
20
+ const coefficients = raw.map((x) => x / total);
21
+ function mulaw(sample) {
22
+ sample = Math.max(-32768, Math.min(32767, sample));
23
+ const sign = sample < 0 ? 128 : 0, magnitude = Math.min(Math.abs(sample), 32635) + 132;
24
+ const exponent = Math.max(0, Math.floor(Math.log2(magnitude)) - 7);
25
+ return ~(sign | (exponent << 4) | ((magnitude >> (exponent + 3)) & 15)) & 255;
26
+ }
27
+ export class Converter {
28
+ profile;
29
+ tail = Buffer.alloc(0);
30
+ samples = Array(63).fill(0);
31
+ seen = 0;
32
+ emitted = 0;
33
+ inputSamples = 0;
34
+ constructor(profile) {
35
+ this.profile = profile;
36
+ }
37
+ sample(sample) {
38
+ this.samples.pop();
39
+ this.samples.unshift(sample);
40
+ const position = this.seen++ - 31;
41
+ if (position >= 0 && position % 3 === 0) {
42
+ const value = coefficients.reduce((sum, c, i) => sum + c * this.samples[i], 0);
43
+ this.emitted++;
44
+ return mulaw(Math.floor(value + 0.5));
45
+ }
46
+ return null;
47
+ }
48
+ process(input, final = false) {
49
+ const data = Buffer.concat([this.tail, input]);
50
+ const size = Math.floor(data.length / 2) * 2;
51
+ this.tail = Buffer.from(data.subarray(size));
52
+ if (final && this.tail.length)
53
+ throw new RimeAudioFormatError("Incomplete final PCM sample frame");
54
+ if (this.profile === AudioFormat.PCM_24000)
55
+ return data.subarray(0, size);
56
+ const result = [];
57
+ for (let i = 0; i < size; i += 2) {
58
+ this.inputSamples++;
59
+ const value = this.sample(data.readInt16LE(i));
60
+ if (value !== null)
61
+ result.push(value);
62
+ }
63
+ if (final) {
64
+ const target = Math.ceil(this.inputSamples / 3);
65
+ while (this.emitted < target) {
66
+ const value = this.sample(0);
67
+ if (value !== null)
68
+ result.push(value);
69
+ }
70
+ }
71
+ return Buffer.from(result);
72
+ }
73
+ }
package/dist/auth.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ import { policy } from "./policy.js";
2
+ export interface Token {
3
+ value: string;
4
+ expiresAt: number;
5
+ audience: string;
6
+ }
7
+ export declare function exchangeKey(key: string, signal: AbortSignal, configuration?: Readonly<typeof policy>): Promise<Token>;
8
+ export declare const authentication: {
9
+ exchangeKey: typeof exchangeKey;
10
+ };
11
+ export declare class Credentials {
12
+ private key;
13
+ private readonly configuration;
14
+ private token;
15
+ private refresh;
16
+ private refreshAt;
17
+ private controller;
18
+ private closed;
19
+ constructor(key: string, configuration?: Readonly<typeof policy>);
20
+ metadata(signal: AbortSignal): Promise<string>;
21
+ themisMetadata(signal: AbortSignal): Promise<string>;
22
+ close(): Promise<void>;
23
+ }
package/dist/auth.js ADDED
@@ -0,0 +1,133 @@
1
+ import { policy, abortable } from "./policy.js";
2
+ import { RimeError, RimeAuthenticationError, RimePermissionError, RimeTimeoutError, RimeCancelledError, RimeResourceLimitError, RimeUnavailableError, } from "./errors.js";
3
+ export async function exchangeKey(key, signal, configuration = policy) {
4
+ try {
5
+ const response = await fetch(configuration.exchangeUrl, {
6
+ method: "POST",
7
+ redirect: "error",
8
+ signal,
9
+ headers: {
10
+ Authorization: `Api-Key ${key}`,
11
+ "Content-Type": "application/json",
12
+ },
13
+ body: JSON.stringify({ audience: configuration.audience }),
14
+ });
15
+ if (response.status !== 200) {
16
+ // The refresh timeout ends when this function rejects. Cancel the body
17
+ // now so an unfinished error response cannot retain the connection.
18
+ await response.body?.cancel().catch(() => { });
19
+ if (response.status === 403)
20
+ throw new RimePermissionError("Credential exchange denied permission");
21
+ if (response.status === 429)
22
+ throw new RimeResourceLimitError("Credential exchange rate limit exceeded");
23
+ if (response.status >= 500 && response.status < 600)
24
+ throw new RimeUnavailableError("Credential exchange service unavailable");
25
+ throw new RimeAuthenticationError("Credential exchange rejected the API key");
26
+ }
27
+ if (!response.body)
28
+ throw new Error("Missing response body");
29
+ const reader = response.body.getReader();
30
+ let size = 0;
31
+ const chunks = [];
32
+ try {
33
+ for (;;) {
34
+ const result = await reader.read();
35
+ if (result.done)
36
+ break;
37
+ size += result.value.length;
38
+ if (size > 65536)
39
+ throw new Error("Response too large");
40
+ chunks.push(result.value);
41
+ }
42
+ }
43
+ finally {
44
+ await reader.cancel();
45
+ reader.releaseLock();
46
+ }
47
+ const body = JSON.parse(Buffer.concat(chunks).toString("utf8"));
48
+ if (typeof body.access_token !== "string" ||
49
+ !body.access_token ||
50
+ /[^\x21-\x7e]/.test(body.access_token) ||
51
+ typeof body.expires_in !== "number" ||
52
+ !Number.isFinite(body.expires_in) ||
53
+ body.expires_in <= 0 ||
54
+ body.audience !== configuration.audience)
55
+ throw new RimeAuthenticationError("Credential exchange returned an invalid token");
56
+ return {
57
+ value: body.access_token,
58
+ expiresAt: Date.now() / 1000 + body.expires_in,
59
+ audience: body.audience,
60
+ };
61
+ }
62
+ catch (error) {
63
+ if (error instanceof RimeError)
64
+ throw error;
65
+ if (signal.aborted)
66
+ throw signal.reason;
67
+ throw new RimeAuthenticationError("Credential exchange failed");
68
+ }
69
+ }
70
+ // Private dependency seam for local conformance tests; not exported by the package.
71
+ export const authentication = { exchangeKey };
72
+ export class Credentials {
73
+ key;
74
+ configuration;
75
+ token = null;
76
+ refresh = null;
77
+ refreshAt = 0;
78
+ controller = new AbortController();
79
+ closed = false;
80
+ constructor(key, configuration = policy) {
81
+ this.key = key;
82
+ this.configuration = configuration;
83
+ }
84
+ async metadata(signal) {
85
+ // TEMPORARY until Themis is ready: replace this body with the call below.
86
+ // return this.themisMetadata(signal);
87
+ if (this.closed)
88
+ throw new RimeAuthenticationError("Credentials are closed");
89
+ signal.throwIfAborted();
90
+ return `Bearer ${this.key}`;
91
+ }
92
+ async themisMetadata(signal) {
93
+ if (this.closed)
94
+ throw new RimeAuthenticationError("Credentials are closed");
95
+ if (!this.token || Date.now() / 1000 >= this.refreshAt) {
96
+ if (!this.refresh) {
97
+ const timeoutController = new AbortController();
98
+ const timer = setTimeout(() => timeoutController.abort(new RimeTimeoutError("Credential acquisition timed out")), this.configuration.authTimeout * 1000);
99
+ const combined = AbortSignal.any([
100
+ this.controller.signal,
101
+ timeoutController.signal,
102
+ ]);
103
+ this.refresh = abortable(authentication.exchangeKey(this.key, combined, this.configuration), combined)
104
+ .then((token) => {
105
+ if (!token.value ||
106
+ token.expiresAt <= Date.now() / 1000 ||
107
+ token.audience !== this.configuration.audience)
108
+ throw new RimeAuthenticationError("Credential exchange returned an invalid token");
109
+ this.token = token;
110
+ this.refreshAt =
111
+ token.expiresAt -
112
+ Math.min(30, (token.expiresAt - Date.now() / 1000) / 10);
113
+ return token;
114
+ })
115
+ .finally(() => {
116
+ clearTimeout(timer);
117
+ this.refresh = null;
118
+ });
119
+ this.refresh.catch(() => { });
120
+ }
121
+ const token = await abortable(this.refresh, signal);
122
+ return `Bearer ${token.value}`;
123
+ }
124
+ return `Bearer ${this.token.value}`;
125
+ }
126
+ async close() {
127
+ this.closed = true;
128
+ this.controller.abort(new RimeCancelledError("Client closed"));
129
+ await this.refresh?.catch(() => { });
130
+ this.token = null;
131
+ this.key = "";
132
+ }
133
+ }
@@ -0,0 +1,46 @@
1
+ import { AudioFormat } from "./audio.js";
2
+ import { AudioStream, type TextSource } from "./stream.js";
3
+ export interface RimeOptions {
4
+ apiKey?: string | null;
5
+ model?: string;
6
+ endpoint?: string | null;
7
+ timeout?: number | null;
8
+ }
9
+ export interface SynthesisOptions {
10
+ voice?: string | null;
11
+ language?: string;
12
+ audioFormat?: AudioFormat | null;
13
+ timeout?: number | null;
14
+ }
15
+ export interface DiscoveryOptions {
16
+ timeout?: number | null;
17
+ }
18
+ export interface VoiceListOptions extends DiscoveryOptions {
19
+ language?: string | null;
20
+ }
21
+ export declare class Rime {
22
+ private readonly deployment;
23
+ private credentials;
24
+ private client;
25
+ private closed;
26
+ private streams;
27
+ private discoveryControllers;
28
+ private closing;
29
+ private defaultTimeout;
30
+ readonly tts: {
31
+ stream: (text: TextSource, options?: SynthesisOptions) => AudioStream;
32
+ };
33
+ readonly voices: {
34
+ list: (options?: VoiceListOptions) => Promise<string[]>;
35
+ };
36
+ readonly languages: {
37
+ list: (options?: DiscoveryOptions) => Promise<string[]>;
38
+ };
39
+ constructor(options?: RimeOptions);
40
+ private checkOpen;
41
+ private prepare;
42
+ private stream;
43
+ private discover;
44
+ close(): Promise<void>;
45
+ [Symbol.asyncDispose](): Promise<void>;
46
+ }
package/dist/client.js ADDED
@@ -0,0 +1,125 @@
1
+ import { AudioFormat } from "./audio.js";
2
+ import { AudioStream, constructionKey } from "./stream.js";
3
+ import { Credentials } from "./auth.js";
4
+ import { policy, resolve, timeout, nonempty, abortable } from "./policy.js";
5
+ import { transport, connect, metadata, discover, } from "./transport.js";
6
+ import { RimeAuthenticationError, RimeInputError, RimeAudioFormatError, RimeCancelledError, RimeTimeoutError, RimeUnavailableError, } from "./errors.js";
7
+ export class Rime {
8
+ deployment;
9
+ credentials;
10
+ client = null;
11
+ closed = false;
12
+ streams = new Set();
13
+ discoveryControllers = new Set();
14
+ closing = null;
15
+ defaultTimeout;
16
+ tts;
17
+ voices;
18
+ languages;
19
+ constructor(options = {}) {
20
+ const key = options.apiKey === undefined || options.apiKey === null
21
+ ? process.env.RIME_API_KEY
22
+ : options.apiKey;
23
+ if (typeof key !== "string" || !key.trim())
24
+ throw new RimeAuthenticationError("Provide apiKey or set RIME_API_KEY");
25
+ this.defaultTimeout = timeout(options.timeout);
26
+ this.deployment = resolve(options.model ?? "coda", options.endpoint);
27
+ this.credentials = new Credentials(key, this.deployment);
28
+ this.tts = { stream: (text, options = {}) => this.stream(text, options) };
29
+ this.voices = {
30
+ list: async (options = {}) => {
31
+ if (options.language !== undefined && options.language !== null)
32
+ nonempty(options.language, "language");
33
+ return this.discover("voices", options.language, options.timeout);
34
+ },
35
+ };
36
+ this.languages = {
37
+ list: (options = {}) => this.discover("languages", undefined, options.timeout),
38
+ };
39
+ }
40
+ checkOpen() {
41
+ if (this.closed)
42
+ throw new RimeInputError("The Rime client is closed");
43
+ }
44
+ async prepare(signal) {
45
+ this.checkOpen();
46
+ const auth = await this.credentials.metadata(signal);
47
+ this.checkOpen();
48
+ this.client ??= transport.makeClient(this.deployment.target);
49
+ await connect(this.client, signal);
50
+ return { client: this.client, metadata: metadata(auth) };
51
+ }
52
+ stream(text, options) {
53
+ this.checkOpen();
54
+ if (typeof text === "string") {
55
+ if (!text.trim())
56
+ throw new RimeInputError("Text must contain non-whitespace characters");
57
+ }
58
+ else if (!text || typeof text[Symbol.asyncIterator] !== "function")
59
+ throw new RimeInputError("text must be a string or an async iterable of strings");
60
+ const voice = options.voice === undefined || options.voice === null
61
+ ? "clementine"
62
+ : nonempty(options.voice, "voice");
63
+ const language = nonempty(options.language ?? "en", "language");
64
+ const format = options.audioFormat ?? AudioFormat.PCM_24000;
65
+ if (format !== AudioFormat.PCM_24000 && format !== AudioFormat.MULAW_8000)
66
+ throw new RimeAudioFormatError("Select a named AudioFormat profile");
67
+ const audio = new AudioStream(constructionKey, {
68
+ prepare: (s) => this.prepare(s),
69
+ checkOpen: () => this.checkOpen(),
70
+ forget: (s) => this.streams.delete(s),
71
+ }, text, voice, language, format, timeout(options.timeout, this.defaultTimeout));
72
+ this.streams.add(audio);
73
+ return audio;
74
+ }
75
+ async discover(kind, language, override) {
76
+ this.checkOpen();
77
+ const budget = Math.min(timeout(override, this.defaultTimeout) ?? Infinity, policy.discoveryTimeout);
78
+ const controller = new AbortController();
79
+ let requestId = null;
80
+ this.discoveryControllers.add(controller);
81
+ const timer = setTimeout(() => controller.abort(new RimeTimeoutError("Discovery deadline expired")), budget * 1000);
82
+ try {
83
+ const prepared = await this.prepare(controller.signal);
84
+ for (let attempt = 0;; attempt++) {
85
+ requestId = null;
86
+ try {
87
+ return await discover(prepared, kind, language, controller.signal);
88
+ }
89
+ catch (error) {
90
+ if (!(error instanceof RimeUnavailableError) || attempt === 2)
91
+ throw error;
92
+ requestId = error.requestId;
93
+ await abortable(new Promise((resolve) => setTimeout(resolve, 50 * 2 ** attempt)), controller.signal);
94
+ }
95
+ }
96
+ }
97
+ catch (error) {
98
+ if (error instanceof RimeTimeoutError && requestId !== null)
99
+ throw new RimeTimeoutError(error.message, requestId, {
100
+ cause: error.cause,
101
+ });
102
+ throw error;
103
+ }
104
+ finally {
105
+ clearTimeout(timer);
106
+ this.discoveryControllers.delete(controller);
107
+ }
108
+ }
109
+ async close() {
110
+ if (!this.closing) {
111
+ this.closed = true;
112
+ this.closing = (async () => {
113
+ for (const controller of this.discoveryControllers)
114
+ controller.abort(new RimeCancelledError("Client closed during discovery"));
115
+ await Promise.all([...this.streams].map((stream) => stream.cancel()));
116
+ await this.credentials.close();
117
+ this.client?.close();
118
+ })();
119
+ }
120
+ await this.closing;
121
+ }
122
+ async [Symbol.asyncDispose]() {
123
+ await this.close();
124
+ }
125
+ }
@@ -0,0 +1,22 @@
1
+ export declare class RimeError extends Error {
2
+ readonly requestId: string | null;
3
+ constructor(message: string, requestId?: string | null, options?: ErrorOptions);
4
+ }
5
+ export declare class RimeAuthenticationError extends RimeError {
6
+ }
7
+ export declare class RimePermissionError extends RimeError {
8
+ }
9
+ export declare class RimeInputError extends RimeError {
10
+ }
11
+ export declare class RimeResourceLimitError extends RimeError {
12
+ }
13
+ export declare class RimeUnavailableError extends RimeError {
14
+ }
15
+ export declare class RimeTimeoutError extends RimeError {
16
+ }
17
+ export declare class RimeAudioFormatError extends RimeError {
18
+ }
19
+ export declare class RimeCancelledError extends RimeError {
20
+ }
21
+ export declare class RimeStreamError extends RimeError {
22
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,26 @@
1
+ export class RimeError extends Error {
2
+ requestId;
3
+ constructor(message, requestId = null, options) {
4
+ super(message, options);
5
+ this.name = new.target.name;
6
+ this.requestId = requestId;
7
+ }
8
+ }
9
+ export class RimeAuthenticationError extends RimeError {
10
+ }
11
+ export class RimePermissionError extends RimeError {
12
+ }
13
+ export class RimeInputError extends RimeError {
14
+ }
15
+ export class RimeResourceLimitError extends RimeError {
16
+ }
17
+ export class RimeUnavailableError extends RimeError {
18
+ }
19
+ export class RimeTimeoutError extends RimeError {
20
+ }
21
+ export class RimeAudioFormatError extends RimeError {
22
+ }
23
+ export class RimeCancelledError extends RimeError {
24
+ }
25
+ export class RimeStreamError extends RimeError {
26
+ }
@@ -0,0 +1,4 @@
1
+ export { Rime, type RimeOptions, type SynthesisOptions, type DiscoveryOptions, type VoiceListOptions, } from "./client.js";
2
+ export { AudioStream } from "./stream.js";
3
+ export { AudioFormat } from "./audio.js";
4
+ export * from "./errors.js";
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { Rime, } from "./client.js";
2
+ export { AudioStream } from "./stream.js";
3
+ export { AudioFormat } from "./audio.js";
4
+ export * from "./errors.js";
@@ -0,0 +1,20 @@
1
+ export declare const policy: {
2
+ target: string;
3
+ audience: string;
4
+ exchangeUrl: string;
5
+ sentenceBytes: number;
6
+ sourceChars: number;
7
+ outputBytes: number;
8
+ outputChunkBytes: number;
9
+ receiveBytes: number;
10
+ authTimeout: number;
11
+ connectionTimeout: number;
12
+ firstAudioTimeout: number;
13
+ progressTimeout: number;
14
+ discoveryTimeout: number;
15
+ cleanupTimeout: number;
16
+ };
17
+ export declare function resolve(model: string, endpoint?: string | null): Readonly<typeof policy>;
18
+ export declare function timeout(value: unknown, inherited?: number | null): number | null;
19
+ export declare function nonempty(value: unknown, name: string): string;
20
+ export declare function abortable<T>(promise: PromiseLike<T>, signal: AbortSignal): Promise<T>;