@rimelabs/sdk 0.1.0-alpha.7 → 0.1.0-alpha.9

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 CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.0-alpha.9](https://github.com/rimelabs/rime-sdk/compare/typescript-v0.1.0-alpha.8...typescript-v0.1.0-alpha.9) (2026-10-08)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * make package quickstarts usable without repository access ([#24](https://github.com/rimelabs/rime-sdk/issues/24)) ([3a30b83](https://github.com/rimelabs/rime-sdk/commit/3a30b83ecaad1740c84d1e8c005520522cf56d26))
9
+
10
+ ## [0.1.0-alpha.8](https://github.com/rimelabs/rime-sdk/compare/typescript-v0.1.0-alpha.7...typescript-v0.1.0-alpha.8) (2026-10-08)
11
+
12
+
13
+ ### Features
14
+
15
+ * add voice examples and automate example dependency updates ([#22](https://github.com/rimelabs/rime-sdk/issues/22)) ([dea7044](https://github.com/rimelabs/rime-sdk/commit/dea7044831058ebee9ae536e8d822a4d7fabbd3d))
16
+
3
17
  ## [0.1.0-alpha.7](https://github.com/rimelabs/rime-sdk/compare/typescript-v0.1.0-alpha.6...typescript-v0.1.0-alpha.7) (2026-10-07)
4
18
 
5
19
 
package/README.md CHANGED
@@ -1,93 +1,175 @@
1
1
  # Rime SDK for Node.js
2
2
 
3
- Stream speech from a string or async text source. The SDK handles sentence
4
- boundaries, authentication, and audio conversion; your application owns playback.
5
- Use Prism for conversations with audio input, typed turns, and tools.
3
+ Generate speech with TTS, or send speech to Prism and receive a spoken reply.
4
+ Both APIs use the `Rime` client. Your application handles audio capture and playback.
6
5
 
7
6
  ## Install
8
7
 
9
- Requires Node.js 22 or later. This alpha package uses ESM and includes TypeScript
10
- types. Browser use is not supported.
8
+ Requires Node.js 22 or later. This alpha package uses ESM and includes TypeScript types.
9
+ Run it on a server. Browser use is not supported.
11
10
 
12
11
  ```sh
13
- npm install @rimelabs/sdk
12
+ mkdir rime-quickstart
13
+ cd rime-quickstart
14
+ npm init -y
15
+ npm install @rimelabs/sdk wavefile
14
16
  export RIME_API_KEY="your-api-key"
15
17
  ```
16
18
 
17
- An explicit `new Rime({ apiKey: "..." })` overrides the environment. The SDK
18
- does not load `.env` files.
19
+ Get a TTS API key from the [Rime dashboard](https://app.rime.ai/).
20
+ An explicit `new Rime({ apiKey: "..." })` overrides `RIME_API_KEY`. The SDK does not load `.env` files.
21
+ The commands below use a macOS or Linux shell.
19
22
 
20
- ## TTS quick start
23
+ These examples use JavaScript `.mjs` files so you can run them without a TypeScript build.
24
+ The additional [wavefile package](https://github.com/rochars/wavefile) reads and writes WAV files
25
+ for the examples. It is not required by the SDK.
21
26
 
22
- Save this as `speech.mjs` and run `node speech.mjs`:
27
+ ## TTS: save speech
28
+
29
+ Save this as `tts.mjs`. It writes a playable `speech.wav` file with no audio-device dependencies.
23
30
 
24
31
  ```javascript
25
- import { writeFile } from "node:fs/promises";
32
+ import { writeFileSync } from "node:fs";
33
+ import wavefile from "wavefile";
26
34
  import { Rime } from "@rimelabs/sdk";
27
35
 
28
- const client = new Rime();
36
+ const client = new Rime({ timeout: 60 });
29
37
  try {
30
- const audio = client.tts.stream("Hello. This is Rime.");
31
- await writeFile("speech.pcm", audio);
32
- console.log(audio.requestId);
38
+ const chunks = [];
39
+ for await (const chunk of client.tts.stream(
40
+ "Your appointment is confirmed for tomorrow.",
41
+ )) {
42
+ chunks.push(Buffer.from(chunk));
43
+ }
44
+ const pcm = Buffer.concat(chunks);
45
+ const samples = Array.from({ length: pcm.length / 2 }, (_, i) =>
46
+ pcm.readInt16LE(i * 2),
47
+ );
48
+ const wav = new wavefile.WaveFile();
49
+ wav.fromScratch(1, 24000, "16", samples);
50
+ writeFileSync("speech.wav", wav.toBuffer());
51
+ console.log("Saved speech.wav");
33
52
  } finally {
34
53
  await client.close();
35
54
  }
36
55
  ```
37
56
 
38
- Output is raw mono 24 kHz signed little-endian PCM16, with no WAV header.
39
- The default model is Coda. Select Mist v3 with `new Rime({ model: "mistv3" })`.
57
+ Run `node tts.mjs`, then open `speech.wav` in your audio player.
58
+ This short example collects the audio in memory before writing the file.
59
+ For long responses, write audio chunks as they arrive.
60
+
61
+ Coda is the default model. Use `new Rime({ model: "mistv3" })` for Mist v3, or pass
62
+ `{ voice: "your-voice" }` as the second argument to `client.tts.stream(...)` to select a voice.
63
+ The default output is mono 24 kHz PCM16. The example adds its WAV header.
64
+ To supply text from an LLM, pass an async iterable of strings instead of a string.
65
+ The SDK handles sentence boundaries.
40
66
 
41
- For streamed text, voices, audio formats, and cancellation, read the
42
- [TTS guide](https://github.com/rimelabs/rime-sdk/blob/main/typescript/docs/tts.md).
43
- Runnable scripts are in the [examples](https://github.com/rimelabs/rime-sdk/blob/main/examples/README.md).
67
+ ## Prism: send recorded speech
44
68
 
45
- ## Prism quick start
69
+ Prism needs a deployment that serves its realtime API. Obtain the endpoint,
70
+ credentials, and voice from your deployment operator. The TTS endpoint does not serve Prism.
71
+ Set `RIME_API_KEY` to the credential for that deployment if it differs from your TTS key.
72
+
73
+ ```sh
74
+ export PRISM_URL="wss://your-prism-host/v1/realtime"
75
+ export PRISM_VOICE="your-deployment-voice"
76
+ ```
46
77
 
47
- Set `PRISM_URL` to your deployment's full `wss://host/v1/realtime` endpoint.
48
- Supply `PRISM_VOICE` unless the deployment has a default voice.
78
+ You can omit `PRISM_VOICE` if the deployment has a default voice.
79
+ Record a short question and export it as `question.wav`, using **16 kHz, mono, signed 16-bit PCM WAV**.
80
+ Save the following as `prism.mjs` beside that file. It sends the recording at capture speed,
81
+ then sends silence so Prism can detect the end of speech. The spoken reply goes to `reply.wav`.
49
82
 
50
83
  ```javascript
84
+ import { readFileSync, writeFileSync } from "node:fs";
85
+ import { setTimeout as sleep } from "node:timers/promises";
86
+ import wavefile from "wavefile";
51
87
  import { Rime, RimeRealtimeError } from "@rimelabs/sdk";
52
88
 
89
+ const input = new wavefile.WaveFile(readFileSync("question.wav"));
90
+ if (
91
+ input.container !== "RIFF" ||
92
+ input.fmt.audioFormat !== 1 ||
93
+ input.fmt.numChannels !== 1 ||
94
+ input.fmt.sampleRate !== 16000 ||
95
+ input.bitDepth !== "16"
96
+ ) {
97
+ throw new Error("question.wav must be 16 kHz mono PCM16");
98
+ }
99
+ const data = Buffer.from(input.data.samples);
100
+ if (!data.length || data.length % 2)
101
+ throw new Error("question.wav has no complete PCM16 audio");
102
+ const endpoint = process.env.PRISM_URL;
103
+ if (!endpoint)
104
+ throw new Error("Set PRISM_URL to your deployment's /v1/realtime URL");
105
+
53
106
  const client = new Rime();
54
- const deadline = setTimeout(() => void client.close(), 60_000);
107
+ const stop = new AbortController();
108
+ const deadline = setTimeout(() => {
109
+ stop.abort();
110
+ void client.close();
111
+ }, 60_000);
112
+ let sending;
55
113
  let reading;
56
114
  try {
57
115
  const session = await client.realtime.connect({
58
- endpoint: process.env.PRISM_URL,
116
+ endpoint,
59
117
  voice: process.env.PRISM_VOICE,
118
+ instructions: "Give short, clear answers.",
60
119
  });
120
+ sending = (async () => {
121
+ for (let offset = 0; ; offset += 1280) {
122
+ const frame = Buffer.alloc(1280);
123
+ if (offset < data.length)
124
+ data.copy(frame, 0, offset, Math.min(offset + 1280, data.length));
125
+ await session.sendAudio({ data: frame });
126
+ await sleep(40, undefined, { signal: stop.signal });
127
+ }
128
+ })();
129
+ const chunks = [];
61
130
  reading = (async () => {
62
131
  for await (const { payload } of session.events) {
63
- if (payload.kind === "text.delta") process.stdout.write(payload.delta);
132
+ if (payload.kind === "audio.delta")
133
+ chunks.push(Buffer.from(payload.audio.data));
64
134
  if (payload.kind === "error") throw new RimeRealtimeError(payload.error);
65
135
  if (payload.kind === "response.ended") {
66
- if (payload.status !== "completed")
67
- throw new Error(`Response ${payload.status}`);
136
+ if (payload.status !== "completed") {
137
+ throw new Error(`Response ${payload.status}: ${payload.reason}`);
138
+ }
68
139
  return;
69
140
  }
70
141
  }
71
- throw new Error("Session closed before the response ended");
142
+ throw new Error("Session closed before the reply ended");
72
143
  })();
73
- await Promise.all([reading, session.sendText("Hello!")]);
144
+ await Promise.race([sending, reading]);
145
+ const pcm = Buffer.concat(chunks);
146
+ const samples = Array.from({ length: pcm.length / 2 }, (_, i) =>
147
+ pcm.readInt16LE(i * 2),
148
+ );
149
+ const wav = new wavefile.WaveFile();
150
+ wav.fromScratch(1, 24000, "16", samples);
151
+ writeFileSync("reply.wav", wav.toBuffer());
152
+ console.log("Saved reply.wav");
74
153
  } finally {
154
+ stop.abort();
75
155
  clearTimeout(deadline);
76
156
  await client.close();
77
- await reading?.catch(() => {});
157
+ await Promise.allSettled([sending, reading]);
78
158
  }
79
159
  ```
80
160
 
81
- This example prints text and discards audio. The
82
- [Realtime guide](https://github.com/rimelabs/rime-sdk/blob/main/typescript/docs/realtime.md)
83
- covers audio input, tools, playback reports, and cancellation. Runnable
84
- [Prism examples](https://github.com/rimelabs/rime-sdk/blob/main/examples/README.md#nodejs)
85
- save audio and handle tools. TTS settings do not apply to Prism sessions.
161
+ Run `node prism.mjs`, then open `reply.wav`. This example has a 60-second deadline
162
+ and collects the reply in memory. It saves audio without playing it, so it sends no playback receipt.
163
+ For live conversations, your application must capture microphone audio, play replies,
164
+ stop playback on interruption, and report the actual played position to Prism.
165
+ Keep the API key on your server when you add a browser interface.
166
+ TTS settings do not configure Prism sessions.
167
+
168
+ ## Help and licenses
86
169
 
87
- ## License
170
+ See [Rime documentation](https://docs.rime.ai/) for API keys, TTS models, and deployment information.
171
+ The examples above run with the installed package. No source checkout is required.
88
172
 
89
- SDK code uses the [MIT license](https://github.com/rimelabs/rime-sdk/blob/main/typescript/LICENSE).
90
- The Prism protocol module uses the [Apache 2.0 license](https://github.com/rimelabs/rime-sdk/blob/main/typescript/LICENSE-PRISM).
91
- BlingFire retains its [upstream license](https://github.com/rimelabs/rime-sdk/blob/main/typescript/vendor/LICENSE.blingfire).
92
- Its WASM runtime ships with the package; the SDK downloads no code or models at
93
- runtime. See [vendor provenance](https://github.com/rimelabs/rime-sdk/blob/main/typescript/vendor/README.md).
173
+ SDK code uses the MIT license. The Prism protocol module uses Apache 2.0.
174
+ BlingFire retains its MIT license. License texts and notices are included in the package.
175
+ Its WASM runtime ships with the package. The SDK downloads no code or models at runtime.
package/docs/realtime.md CHANGED
@@ -4,10 +4,12 @@ Keep one event consumer running while your application sends input, runs tools,
4
4
  and plays audio. The SDK manages the protocol state. Your application owns
5
5
  microphone capture, tool execution, and playback.
6
6
 
7
- Start with the [package quick start](../README.md#prism-quick-start), or run the
8
- [typed-turn example](https://github.com/rimelabs/rime-sdk/blob/main/examples/typescript/realtime/typed-turn.mjs).
9
- The [example setup](https://github.com/rimelabs/rime-sdk/blob/main/examples/README.md#nodejs)
10
- lists the commands and environment variables. This API requires Node.js 22 or later.
7
+ Start with the [recorded-speech quick start](../README.md#prism-send-recorded-speech)
8
+ to save a spoken reply without audio hardware.
9
+
10
+ For live conversations, keep the session open after normal cancellation and
11
+ report playback from the output clock. Saving a file is not playback.
12
+ Typed turns also support mixed text and voice applications.
11
13
 
12
14
  ## Connect
13
15
 
@@ -106,10 +108,9 @@ Use `JSON.stringify(...)` for a structured result. Call
106
108
  `continueReply(payload.call)` when the assistant should answer; a tool call
107
109
  reference also carries its parent response identity.
108
110
 
109
- The [tool example](https://github.com/rimelabs/rime-sdk/blob/main/examples/typescript/realtime/tools.mjs)
110
- keeps the event consumer running while result submissions and continuation wait.
111
- It uses local order data. Slow tools need asynchronous work or a worker thread
112
- so they do not block the Node.js event loop.
111
+ Keep the event consumer running while submitting tool results and requesting
112
+ continuation. Run slow tools asynchronously or in a worker so they do not block
113
+ the event loop.
113
114
 
114
115
  A new user turn or proactive reply supersedes the old tool round. Late results
115
116
  can still be recorded. Use `requestReply({ toolCall: call })` to ask the assistant
@@ -174,8 +175,8 @@ nonnegative milliseconds. The SDK waits for generation completion and supplies
174
175
  the server's drain token.
175
176
 
176
177
  Saving audio does not establish playback. Reports are optional. If you cannot
177
- measure playback, omit them and let the server use its estimate. The examples
178
- have no player and omit these reports.
178
+ measure playback, omit them and let the server use its estimate. The recorded and typed examples have no player and omit these reports.
179
+ The voice examples report actual playback.
179
180
 
180
181
  ## Timeouts and failures
181
182
 
@@ -185,8 +186,8 @@ tool readiness, and waiting for generation to end before a playback report.
185
186
  Once a request is submitted, `requestS` bounds its write and acknowledgment.
186
187
 
187
188
  These limits do not bound the entire conversation or generation after creation.
188
- Set an application deadline and close the session when it expires. Both examples
189
- use a 60-second deadline.
189
+ Set an application deadline and close the session when it expires. The recorded and typed examples use a 60-second deadline. Voice conversations
190
+ run until stopped or the connection fails.
190
191
 
191
192
  `RealtimeAdmissionTimeout` means readiness expired with no request outstanding;
192
193
  the session remains usable. An unknown request outcome closes the connection and
@@ -215,6 +216,5 @@ Keep up with the event stream. The queue holds 256 events; incoming messages
215
216
  are limited to 1 MiB. A slow consumer ends the session. There is no automatic
216
217
  reconnect, history replay, or live configuration update.
217
218
 
218
- The [pinned contract](https://github.com/rimelabs/rime-sdk/blob/main/conformance/prism/README.md)
219
- is the local test target. The deployed gateway handshake and endpoint behavior
220
- still need validation for the deployment you use.
219
+ Local peer tests cover the SDK protocol handling. Validate the gateway handshake
220
+ and endpoint behavior for the deployment you use.
package/docs/tts.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # TTS for Node.js
2
2
 
3
3
  You supply text; the SDK handles sentence boundaries and streams audio back.
4
- Your application owns playback. Start with the [package quick start](../README.md),
5
- or run the [streaming example](https://github.com/rimelabs/rime-sdk/blob/main/examples/typescript/tts/stream.mjs).
4
+ Your application owns playback. Start with the complete WAV example in the
5
+ [package quick start](../README.md#tts-save-speech).
6
6
 
7
7
  ## Stream incoming text
8
8
 
@@ -17,7 +17,7 @@ async function* text() {
17
17
 
18
18
  Use `client.tts.stream(text())` with the same file write and cleanup.
19
19
  The SDK handles sentence boundaries. Do not await `tts.stream()`; the first
20
- iterator read starts work. `writeFile` consumes the stream for you.
20
+ iterator read starts work. The quick start collects chunks before writing a WAV file.
21
21
 
22
22
  ## Configuration
23
23
 
package/package.json CHANGED
@@ -1,13 +1,8 @@
1
1
  {
2
2
  "name": "@rimelabs/sdk",
3
- "version": "0.1.0-alpha.7",
3
+ "version": "0.1.0-alpha.9",
4
4
  "description": "Rime streaming TTS and Prism realtime SDK for Node.js",
5
5
  "license": "MIT",
6
- "repository": {
7
- "type": "git",
8
- "url": "git+https://github.com/rimelabs/rime-sdk.git",
9
- "directory": "typescript"
10
- },
11
6
  "type": "module",
12
7
  "engines": {
13
8
  "node": ">=22"
@@ -34,7 +29,7 @@
34
29
  "check": "tsc -p tsconfig.json --noEmit",
35
30
  "test": "npm run build && node --test tests/*.test.mjs",
36
31
  "prepack": "npm run build",
37
- "lint": "prettier --check src tests ../examples/typescript/tts ../examples/typescript/realtime"
32
+ "lint": "prettier --check src tests ../examples/typescript/tts ../examples/typescript/realtime ../examples/typescript/common ../examples/typescript/browser ../examples/typescript/tests"
38
33
  },
39
34
  "dependencies": {
40
35
  "@bufbuild/protobuf": "^2.11.0",
@@ -49,5 +44,6 @@
49
44
  "prettier": "3.9.8",
50
45
  "typescript": "^5.9.0",
51
46
  "yaml": "^2.9.1"
52
- }
47
+ },
48
+ "homepage": "https://docs.rime.ai/"
53
49
  }