@runappsai/sdk 0.7.0 → 0.7.3
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/README.md +24 -2
- package/dist/audio.d.ts +3 -1
- package/dist/audio.d.ts.map +1 -1
- package/dist/audio.js +1 -1
- package/dist/audio.js.map +1 -1
- package/dist/realtime.d.ts +14 -4
- package/dist/realtime.d.ts.map +1 -1
- package/dist/realtime.js +9 -2
- package/dist/realtime.js.map +1 -1
- package/dist/sdk.umd.js +3 -3
- package/dist/sdk.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/audio.ts +5 -2
- package/src/realtime.ts +28 -5
package/package.json
CHANGED
package/src/audio.ts
CHANGED
|
@@ -90,7 +90,10 @@ export interface TranscribeParams {
|
|
|
90
90
|
*/
|
|
91
91
|
url?: string;
|
|
92
92
|
language?: string;
|
|
93
|
-
|
|
93
|
+
|
|
94
|
+
/** A vocabulary hint for the model, as text or a private prompt
|
|
95
|
+
* `{ id, vars }` (or a list; see `PromptInput`). */
|
|
96
|
+
prompt?: string | PromptInput;
|
|
94
97
|
response_format?: string;
|
|
95
98
|
timestamp_granularities?: ("segment" | "word")[];
|
|
96
99
|
user?: string;
|
|
@@ -406,7 +409,7 @@ function buildTranscribeForm(model: string, params: TranscribeParams): FormData
|
|
|
406
409
|
const form = new FormData();
|
|
407
410
|
form.set("model", model);
|
|
408
411
|
if (params.language) form.set("language", params.language);
|
|
409
|
-
if (params.prompt) form.set("prompt", params.prompt);
|
|
412
|
+
if (params.prompt) form.set("prompt", typeof params.prompt === "string" ? params.prompt : JSON.stringify(params.prompt));
|
|
410
413
|
if (params.response_format) form.set("response_format", params.response_format);
|
|
411
414
|
if (params.timestamp_granularities) {
|
|
412
415
|
for (const g of params.timestamp_granularities) {
|
package/src/realtime.ts
CHANGED
|
@@ -30,6 +30,15 @@ import type { Transport } from "./transport.js";
|
|
|
30
30
|
* Audio input must arrive at real-time pace (send ~20 ms chunks as they
|
|
31
31
|
* are captured); the model also expects a steady stream, so keep sending
|
|
32
32
|
* silence — or `mute()` — while the microphone is off.
|
|
33
|
+
*
|
|
34
|
+
* Transcription models (e.g. "Doubao ASR 2.0 Streaming") use the same
|
|
35
|
+
* session for live speech-to-text: `session.created` carries
|
|
36
|
+
* `session.mode: "transcription"`, `session.hotwords` (array or
|
|
37
|
+
* comma-separated string) favours words, and only the
|
|
38
|
+
* `…input_audio_transcription.started / .delta / .completed` events come
|
|
39
|
+
* back — `.delta` holds the sentence so far, `.completed` a finished
|
|
40
|
+
* sentence with `start_ms` / `end_ms`. `commitAudio()` or `close()` ends
|
|
41
|
+
* the audio; the last sentence settles before the session closes.
|
|
33
42
|
*/
|
|
34
43
|
|
|
35
44
|
/** One protocol event. `type` names it; the rest depends on the event. */
|
|
@@ -50,8 +59,9 @@ export interface RealtimeUsage {
|
|
|
50
59
|
|
|
51
60
|
/** How a session ended. */
|
|
52
61
|
export interface RealtimeCloseInfo {
|
|
53
|
-
/** WebSocket close code: 1000 when the session completed;
|
|
54
|
-
*
|
|
62
|
+
/** WebSocket close code: 1000 when the session completed; 4402 when the
|
|
63
|
+
* spending cap was reached (`maxCost`, or the account's balance); 4000+N
|
|
64
|
+
* for an upstream HTTP error N (e.g. 4429); 4408 idle or over-long session. */
|
|
55
65
|
code: number;
|
|
56
66
|
reason: string;
|
|
57
67
|
/** Null when the session ended before the cost could be reported. */
|
|
@@ -69,7 +79,8 @@ export interface WebSocketLike {
|
|
|
69
79
|
export type WebSocketConstructor = new (url: string, protocols?: string | string[]) => WebSocketLike;
|
|
70
80
|
|
|
71
81
|
export interface RealtimeConnectOptions {
|
|
72
|
-
/** Realtime model name (e.g. "Doubao Realtime Voice"
|
|
82
|
+
/** Realtime model name (e.g. "Doubao Realtime Voice", or "Doubao ASR 2.0
|
|
83
|
+
* Streaming" for live speech-to-text); omit for the platform default. */
|
|
73
84
|
model?: string;
|
|
74
85
|
/**
|
|
75
86
|
* Session settings sent in the opening `session.create`, e.g.
|
|
@@ -78,6 +89,12 @@ export interface RealtimeConnectOptions {
|
|
|
78
89
|
session?: Record<string, unknown>;
|
|
79
90
|
/** Model-specific extension block (Doubao: `{ asr, tts, dialog }`). */
|
|
80
91
|
extension?: Record<string, unknown>;
|
|
92
|
+
/**
|
|
93
|
+
* End the session (close code 4402) once it has cost this many USD. The
|
|
94
|
+
* account's remaining balance always caps a session; this sets a lower
|
|
95
|
+
* cap. Checked after each turn, so the last turn may go slightly over.
|
|
96
|
+
*/
|
|
97
|
+
maxCost?: number;
|
|
81
98
|
/** Extra query parameters for the handshake. */
|
|
82
99
|
query?: Record<string, string>;
|
|
83
100
|
/**
|
|
@@ -174,7 +191,9 @@ export class RealtimeSession {
|
|
|
174
191
|
this.send({ type: "input_audio_buffer.append", audio: bytesToBase64(asBytes(pcm16)) });
|
|
175
192
|
}
|
|
176
193
|
|
|
177
|
-
/** Tell the model the user has finished speaking (skips end-of-speech
|
|
194
|
+
/** Tell the model the user has finished speaking (skips end-of-speech
|
|
195
|
+
* detection). For a transcription model this ends the audio: the last
|
|
196
|
+
* sentence settles, then the session closes. */
|
|
178
197
|
commitAudio(): void {
|
|
179
198
|
this.send({ type: "input_audio_buffer.commit" });
|
|
180
199
|
}
|
|
@@ -336,7 +355,10 @@ export class RealtimeService {
|
|
|
336
355
|
ws.send(JSON.stringify(openingEvent(options)));
|
|
337
356
|
});
|
|
338
357
|
void session.closed.then((info) => {
|
|
339
|
-
|
|
358
|
+
// A refused handshake (bad key, unknown model, low balance) reaches
|
|
359
|
+
// a WebSocket client only as 1006 — the HTTP status is hidden.
|
|
360
|
+
const hint = info.code === 1006 ? " — check the API key, the model name and the account balance" : "";
|
|
361
|
+
fail(new Error(`runapps: realtime connection closed (${info.code}${info.reason ? " " + info.reason : ""})${hint}`));
|
|
340
362
|
});
|
|
341
363
|
});
|
|
342
364
|
} catch (err) {
|
|
@@ -380,6 +402,7 @@ function realtimeURL(baseURL: string, options: RealtimeConnectOptions): string {
|
|
|
380
402
|
u.protocol = u.protocol === "http:" ? "ws:" : "wss:";
|
|
381
403
|
for (const [k, v] of Object.entries(options.query ?? {})) u.searchParams.set(k, v);
|
|
382
404
|
if (options.model) u.searchParams.set("model", options.model);
|
|
405
|
+
if (options.maxCost !== undefined && options.maxCost > 0) u.searchParams.set("max_cost", String(options.maxCost));
|
|
383
406
|
return u.toString();
|
|
384
407
|
}
|
|
385
408
|
|