@runappsai/sdk 0.6.9 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,137 @@
1
+ import { type SDKEvents } from "./events.js";
2
+ import type { Transport } from "./transport.js";
3
+ /** One protocol event. `type` names it; the rest depends on the event. */
4
+ export interface RealtimeEvent {
5
+ type: string;
6
+ [key: string]: unknown;
7
+ }
8
+ /** What a realtime session cost, from the closing `gateway.usage` event. */
9
+ export interface RealtimeUsage {
10
+ input_tokens?: number;
11
+ output_tokens?: number;
12
+ /** Session length in seconds. */
13
+ seconds?: number;
14
+ /** USD. */
15
+ total_cost?: number;
16
+ }
17
+ /** How a session ended. */
18
+ export interface RealtimeCloseInfo {
19
+ /** WebSocket close code: 1000 when the session completed; 4000+N for an
20
+ * upstream HTTP error N (e.g. 4429); 4408 idle or over-long session. */
21
+ code: number;
22
+ reason: string;
23
+ /** Null when the session ended before the cost could be reported. */
24
+ usage: RealtimeUsage | null;
25
+ }
26
+ /** The subset of the WHATWG WebSocket the SDK uses (also what `ws` provides). */
27
+ export interface WebSocketLike {
28
+ readonly readyState: number;
29
+ send(data: string): void;
30
+ close(code?: number, reason?: string): void;
31
+ addEventListener(type: string, listener: (ev: any) => void): void;
32
+ }
33
+ export type WebSocketConstructor = new (url: string, protocols?: string | string[]) => WebSocketLike;
34
+ export interface RealtimeConnectOptions {
35
+ /** Realtime model name (e.g. "Doubao Realtime Voice"); omit for the platform default. */
36
+ model?: string;
37
+ /**
38
+ * Session settings sent in the opening `session.create`, e.g.
39
+ * `{ instructions: "...", audio: { output: { voice: "zh_female_vv_jupiter_bigtts" } } }`.
40
+ */
41
+ session?: Record<string, unknown>;
42
+ /** Model-specific extension block (Doubao: `{ asr, tts, dialog }`). */
43
+ extension?: Record<string, unknown>;
44
+ /** Extra query parameters for the handshake. */
45
+ query?: Record<string, string>;
46
+ /**
47
+ * WebSocket implementation. Defaults to the global `WebSocket` (browsers,
48
+ * Node 22+, Deno, Bun); on older Node pass the `ws` package's export.
49
+ */
50
+ WebSocket?: WebSocketConstructor;
51
+ /** Give up if the session isn't open within this long (default 15 s). */
52
+ timeoutMs?: number;
53
+ signal?: AbortSignal;
54
+ }
55
+ type Handler = (event: RealtimeEvent) => void;
56
+ /**
57
+ * A live realtime session. Listen with `on(type, handler)` (or iterate
58
+ * it with `for await`), talk with `appendAudio()` / `say()`, and end it
59
+ * with `close()`.
60
+ */
61
+ export declare class RealtimeSession {
62
+ private readonly ws;
63
+ /** The upstream session id (from `session.created`); pass it as
64
+ * `session.id` to a later session to continue the conversation. */
65
+ sessionId: string;
66
+ /** Settles when the socket closes, however that happens. */
67
+ readonly closed: Promise<RealtimeCloseInfo>;
68
+ private readonly handlers;
69
+ private usage;
70
+ private resolveClosed;
71
+ private isClosed;
72
+ private queue;
73
+ private waiters;
74
+ private iterating;
75
+ /** @internal */
76
+ constructor(ws: WebSocketLike);
77
+ /**
78
+ * Subscribe to events of one type, or `"*"` for all of them. Returns
79
+ * the unsubscribe function.
80
+ */
81
+ on(type: string, handler: Handler): () => void;
82
+ /** Send a raw protocol event. */
83
+ send(event: RealtimeEvent): void;
84
+ /**
85
+ * Stream a chunk of microphone audio: 16-bit little-endian PCM, 16 kHz
86
+ * mono (`pcm16FromFloat32` converts Web Audio samples). Send ~20 ms
87
+ * (640 bytes) at a time, as it is captured.
88
+ */
89
+ appendAudio(pcm16: Int16Array | Uint8Array | ArrayBuffer): void;
90
+ /** Tell the model the user has finished speaking (skips end-of-speech detection). */
91
+ commitAudio(): void;
92
+ /** The microphone is off: stops the model waiting on audio. */
93
+ mute(): void;
94
+ /** The microphone is back on. */
95
+ unmute(): void;
96
+ /** Have the model speak `text` (a greeting, or a scripted line). */
97
+ say(text: string): void;
98
+ /** Interrupt the model's current reply. */
99
+ cancelResponse(): void;
100
+ /** Change session settings mid-session (instructions, voice, tools, …). */
101
+ update(session: Record<string, unknown>): void;
102
+ /** Answer a `response.function_call_arguments.done` tool call. */
103
+ sendFunctionResult(callId: string, output: string): void;
104
+ /**
105
+ * End the session: asks the model to close, waits for the server to
106
+ * hang up (so the closing `gateway.usage` arrives), and resolves with
107
+ * how it ended, including the cost.
108
+ */
109
+ close(): Promise<RealtimeCloseInfo>;
110
+ /** Iterate events until the session closes. */
111
+ [Symbol.asyncIterator](): AsyncIterator<RealtimeEvent>;
112
+ private dispatch;
113
+ }
114
+ export declare class RealtimeService {
115
+ private readonly transport;
116
+ private readonly events;
117
+ constructor(transport: Transport, events: SDKEvents);
118
+ /**
119
+ * Open a realtime voice session. Resolves once the model has accepted
120
+ * it (`session.created`); rejects if the connection fails first.
121
+ */
122
+ connect(options?: RealtimeConnectOptions): Promise<RealtimeSession>;
123
+ }
124
+ /**
125
+ * Convert Web Audio samples (Float32, -1…1) at `sampleRate` to 16-bit PCM
126
+ * at `targetRate` (16 kHz, what realtime input expects), resampling
127
+ * linearly when the rates differ.
128
+ */
129
+ export declare function pcm16FromFloat32(samples: Float32Array, sampleRate: number, targetRate?: number): Int16Array;
130
+ /** Convert 16-bit little-endian PCM bytes (e.g. a decoded audio delta) to Float32 samples for Web Audio. */
131
+ export declare function float32FromPCM16(bytes: Uint8Array): Float32Array;
132
+ /** Base64-encode bytes (audio for `input_audio_buffer.append`). */
133
+ export declare function bytesToBase64(bytes: Uint8Array): string;
134
+ /** Decode base64 (e.g. `response.output_audio.delta`'s `delta`) to bytes. */
135
+ export declare function base64ToBytes(b64: string): Uint8Array;
136
+ export {};
137
+ //# sourceMappingURL=realtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime.d.ts","sourceRoot":"","sources":["../src/realtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,359 @@
1
+ import { newRequestId } from "./events.js";
2
+ const OPEN = 1;
3
+ const CLOSE_TIMEOUT_MS = 10_000;
4
+ /**
5
+ * A live realtime session. Listen with `on(type, handler)` (or iterate
6
+ * it with `for await`), talk with `appendAudio()` / `say()`, and end it
7
+ * with `close()`.
8
+ */
9
+ export class RealtimeSession {
10
+ ws;
11
+ /** The upstream session id (from `session.created`); pass it as
12
+ * `session.id` to a later session to continue the conversation. */
13
+ sessionId = "";
14
+ /** Settles when the socket closes, however that happens. */
15
+ closed;
16
+ handlers = new Map();
17
+ usage = null;
18
+ resolveClosed;
19
+ isClosed = false;
20
+ queue = [];
21
+ waiters = [];
22
+ iterating = false;
23
+ /** @internal */
24
+ constructor(ws) {
25
+ this.ws = ws;
26
+ this.closed = new Promise((resolve) => {
27
+ this.resolveClosed = resolve;
28
+ });
29
+ ws.addEventListener("message", (ev) => {
30
+ if (typeof ev.data !== "string")
31
+ return;
32
+ let event;
33
+ try {
34
+ event = JSON.parse(ev.data);
35
+ }
36
+ catch {
37
+ return;
38
+ }
39
+ if (!event || typeof event.type !== "string")
40
+ return;
41
+ if (event.type === "session.created") {
42
+ const id = event.session?.id;
43
+ if (typeof id === "string")
44
+ this.sessionId = id;
45
+ }
46
+ else if (event.type === "gateway.usage") {
47
+ this.usage = event.usage ?? null;
48
+ }
49
+ this.dispatch(event);
50
+ });
51
+ ws.addEventListener("close", (ev) => {
52
+ if (this.isClosed)
53
+ return;
54
+ this.isClosed = true;
55
+ for (const w of this.waiters.splice(0))
56
+ w({ value: undefined, done: true });
57
+ this.resolveClosed({ code: ev.code ?? 1006, reason: ev.reason ?? "", usage: this.usage });
58
+ });
59
+ }
60
+ /**
61
+ * Subscribe to events of one type, or `"*"` for all of them. Returns
62
+ * the unsubscribe function.
63
+ */
64
+ on(type, handler) {
65
+ let set = this.handlers.get(type);
66
+ if (!set) {
67
+ set = new Set();
68
+ this.handlers.set(type, set);
69
+ }
70
+ set.add(handler);
71
+ return () => set.delete(handler);
72
+ }
73
+ /** Send a raw protocol event. */
74
+ send(event) {
75
+ if (this.ws.readyState !== OPEN)
76
+ throw new Error("runapps: realtime session is closed");
77
+ this.ws.send(JSON.stringify(event));
78
+ }
79
+ /**
80
+ * Stream a chunk of microphone audio: 16-bit little-endian PCM, 16 kHz
81
+ * mono (`pcm16FromFloat32` converts Web Audio samples). Send ~20 ms
82
+ * (640 bytes) at a time, as it is captured.
83
+ */
84
+ appendAudio(pcm16) {
85
+ this.send({ type: "input_audio_buffer.append", audio: bytesToBase64(asBytes(pcm16)) });
86
+ }
87
+ /** Tell the model the user has finished speaking (skips end-of-speech detection). */
88
+ commitAudio() {
89
+ this.send({ type: "input_audio_buffer.commit" });
90
+ }
91
+ /** The microphone is off: stops the model waiting on audio. */
92
+ mute() {
93
+ this.send({ type: "input_audio_mute.commit" });
94
+ }
95
+ /** The microphone is back on. */
96
+ unmute() {
97
+ this.send({ type: "input_audio_unmute.commit" });
98
+ }
99
+ /** Have the model speak `text` (a greeting, or a scripted line). */
100
+ say(text) {
101
+ this.send({ type: "speech_text_buffer.commit", text });
102
+ }
103
+ /** Interrupt the model's current reply. */
104
+ cancelResponse() {
105
+ this.send({ type: "response.cancel" });
106
+ }
107
+ /** Change session settings mid-session (instructions, voice, tools, …). */
108
+ update(session) {
109
+ this.send({ type: "session.update", session });
110
+ }
111
+ /** Answer a `response.function_call_arguments.done` tool call. */
112
+ sendFunctionResult(callId, output) {
113
+ this.send({
114
+ type: "conversation.item.create",
115
+ items: [{ call_id: callId, role: "tool", content: [{ type: "input_text", text: output }] }],
116
+ });
117
+ }
118
+ /**
119
+ * End the session: asks the model to close, waits for the server to
120
+ * hang up (so the closing `gateway.usage` arrives), and resolves with
121
+ * how it ended, including the cost.
122
+ */
123
+ async close() {
124
+ if (!this.isClosed && this.ws.readyState === OPEN) {
125
+ try {
126
+ this.send({ type: "session.close" });
127
+ }
128
+ catch {
129
+ // already closing
130
+ }
131
+ const timer = setTimeout(() => this.ws.close(1000, "client timeout"), CLOSE_TIMEOUT_MS);
132
+ try {
133
+ return await this.closed;
134
+ }
135
+ finally {
136
+ clearTimeout(timer);
137
+ }
138
+ }
139
+ if (!this.isClosed)
140
+ this.ws.close(1000);
141
+ return this.closed;
142
+ }
143
+ /** Iterate events until the session closes. */
144
+ [Symbol.asyncIterator]() {
145
+ this.iterating = true;
146
+ return {
147
+ next: () => {
148
+ const event = this.queue.shift();
149
+ if (event)
150
+ return Promise.resolve({ value: event, done: false });
151
+ if (this.isClosed)
152
+ return Promise.resolve({ value: undefined, done: true });
153
+ return new Promise((resolve) => this.waiters.push(resolve));
154
+ },
155
+ return: () => {
156
+ this.iterating = false;
157
+ this.queue = [];
158
+ return Promise.resolve({ value: undefined, done: true });
159
+ },
160
+ };
161
+ }
162
+ dispatch(event) {
163
+ for (const type of [event.type, "*"]) {
164
+ const set = this.handlers.get(type);
165
+ if (!set)
166
+ continue;
167
+ for (const h of [...set]) {
168
+ try {
169
+ h(event);
170
+ }
171
+ catch (err) {
172
+ // A broken handler must not stop the others or the session.
173
+ setTimeout(() => {
174
+ throw err;
175
+ });
176
+ }
177
+ }
178
+ }
179
+ if (this.iterating) {
180
+ const w = this.waiters.shift();
181
+ if (w)
182
+ w({ value: event, done: false });
183
+ else
184
+ this.queue.push(event);
185
+ }
186
+ }
187
+ }
188
+ export class RealtimeService {
189
+ transport;
190
+ events;
191
+ constructor(transport, events) {
192
+ this.transport = transport;
193
+ this.events = events;
194
+ }
195
+ /**
196
+ * Open a realtime voice session. Resolves once the model has accepted
197
+ * it (`session.created`); rejects if the connection fails first.
198
+ */
199
+ async connect(options = {}) {
200
+ const WS = options.WebSocket ?? globalThis.WebSocket;
201
+ if (!WS) {
202
+ throw new Error("runapps: no WebSocket available — pass `WebSocket` (e.g. from the `ws` package) on Node < 22");
203
+ }
204
+ const token = await this.transport.bearerToken();
205
+ const ws = new WS(realtimeURL(this.transport.baseURL, options), ["realtime", "runapps-key." + token]);
206
+ const session = new RealtimeSession(ws);
207
+ const model = options.model ?? "";
208
+ const id = newRequestId();
209
+ const startedAt = Date.now();
210
+ this.events.emit("request:start", { id, model, capability: "realtime", startedAt, streaming: true });
211
+ try {
212
+ await new Promise((resolve, reject) => {
213
+ const timer = setTimeout(() => {
214
+ fail(new Error("runapps: realtime session did not open in time"));
215
+ ws.close(1000, "open timeout");
216
+ }, options.timeoutMs ?? 15_000);
217
+ const onAbort = () => {
218
+ fail(new Error("runapps: realtime connect aborted"));
219
+ ws.close(1000, "aborted");
220
+ };
221
+ options.signal?.addEventListener("abort", onAbort, { once: true });
222
+ let settled = false;
223
+ function fail(err) {
224
+ if (settled)
225
+ return;
226
+ settled = true;
227
+ clearTimeout(timer);
228
+ options.signal?.removeEventListener("abort", onAbort);
229
+ reject(err);
230
+ }
231
+ const offCreated = session.on("session.created", () => {
232
+ if (settled)
233
+ return;
234
+ settled = true;
235
+ clearTimeout(timer);
236
+ options.signal?.removeEventListener("abort", onAbort);
237
+ offCreated();
238
+ offError();
239
+ resolve();
240
+ });
241
+ // An error before the session opens is fatal to connect().
242
+ const offError = session.on("error", (ev) => {
243
+ const e = (ev.error ?? {});
244
+ fail(new Error(`runapps: realtime error: ${e.message ?? JSON.stringify(ev)}`));
245
+ });
246
+ ws.addEventListener("open", () => {
247
+ ws.send(JSON.stringify(openingEvent(options)));
248
+ });
249
+ void session.closed.then((info) => {
250
+ fail(new Error(`runapps: realtime connection closed (${info.code}${info.reason ? " " + info.reason : ""})`));
251
+ });
252
+ });
253
+ }
254
+ catch (err) {
255
+ try {
256
+ ws.close(1000, "connect failed");
257
+ }
258
+ catch {
259
+ // already closed
260
+ }
261
+ this.events.emit("request:error", {
262
+ id,
263
+ model,
264
+ capability: "realtime",
265
+ latencyMs: Date.now() - startedAt,
266
+ error: err,
267
+ });
268
+ throw err;
269
+ }
270
+ void session.closed.then((info) => {
271
+ this.events.emit("request:end", {
272
+ id,
273
+ model,
274
+ capability: "realtime",
275
+ latencyMs: Date.now() - startedAt,
276
+ totalTokens: info.usage?.output_tokens ?? 0,
277
+ ...(info.usage?.total_cost !== undefined && { costUSD: info.usage.total_cost }),
278
+ });
279
+ });
280
+ return session;
281
+ }
282
+ }
283
+ function openingEvent(options) {
284
+ const event = { type: "session.create", session: options.session ?? {} };
285
+ if (options.extension)
286
+ event.extension = options.extension;
287
+ return event;
288
+ }
289
+ function realtimeURL(baseURL, options) {
290
+ const u = new URL(baseURL.replace(/\/+$/, "") + "/v1/realtime");
291
+ u.protocol = u.protocol === "http:" ? "ws:" : "wss:";
292
+ for (const [k, v] of Object.entries(options.query ?? {}))
293
+ u.searchParams.set(k, v);
294
+ if (options.model)
295
+ u.searchParams.set("model", options.model);
296
+ return u.toString();
297
+ }
298
+ /* ------------------------------------------------------------------ */
299
+ /* PCM helpers */
300
+ /* ------------------------------------------------------------------ */
301
+ /**
302
+ * Convert Web Audio samples (Float32, -1…1) at `sampleRate` to 16-bit PCM
303
+ * at `targetRate` (16 kHz, what realtime input expects), resampling
304
+ * linearly when the rates differ.
305
+ */
306
+ export function pcm16FromFloat32(samples, sampleRate, targetRate = 16000) {
307
+ const ratio = sampleRate / targetRate;
308
+ const n = ratio === 1 ? samples.length : Math.floor(samples.length / ratio);
309
+ const out = new Int16Array(n);
310
+ for (let i = 0; i < n; i++) {
311
+ let s;
312
+ if (ratio === 1) {
313
+ s = samples[i];
314
+ }
315
+ else {
316
+ const pos = i * ratio;
317
+ const j = Math.floor(pos);
318
+ const frac = pos - j;
319
+ const a = samples[j];
320
+ const b = samples[Math.min(j + 1, samples.length - 1)];
321
+ s = a + (b - a) * frac;
322
+ }
323
+ s = Math.max(-1, Math.min(1, s));
324
+ out[i] = s < 0 ? s * 0x8000 : s * 0x7fff;
325
+ }
326
+ return out;
327
+ }
328
+ /** Convert 16-bit little-endian PCM bytes (e.g. a decoded audio delta) to Float32 samples for Web Audio. */
329
+ export function float32FromPCM16(bytes) {
330
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
331
+ const out = new Float32Array(bytes.byteLength >> 1);
332
+ for (let i = 0; i < out.length; i++)
333
+ out[i] = view.getInt16(i * 2, true) / 0x8000;
334
+ return out;
335
+ }
336
+ /** Base64-encode bytes (audio for `input_audio_buffer.append`). */
337
+ export function bytesToBase64(bytes) {
338
+ let bin = "";
339
+ for (let i = 0; i < bytes.length; i += 0x8000) {
340
+ bin += String.fromCharCode(...bytes.subarray(i, i + 0x8000));
341
+ }
342
+ return btoa(bin);
343
+ }
344
+ /** Decode base64 (e.g. `response.output_audio.delta`'s `delta`) to bytes. */
345
+ export function base64ToBytes(b64) {
346
+ const bin = atob(b64);
347
+ const out = new Uint8Array(bin.length);
348
+ for (let i = 0; i < bin.length; i++)
349
+ out[i] = bin.charCodeAt(i);
350
+ return out;
351
+ }
352
+ function asBytes(v) {
353
+ if (v instanceof Uint8Array)
354
+ return v;
355
+ if (v instanceof ArrayBuffer)
356
+ return new Uint8Array(v);
357
+ return new Uint8Array(v.buffer, v.byteOffset, v.byteLength);
358
+ }
359
+ //# sourceMappingURL=realtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime.js","sourceRoot":"","sources":["../src/realtime.ts"],"names":[],"mappings":"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"}