@pyai/sdk 0.2.3 → 0.4.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.
- package/README.md +65 -19
- package/dist/index.d.ts +292 -60
- package/dist/index.js +189 -81
- package/package.json +18 -3
- package/src/index.ts +447 -121
package/dist/index.d.ts
CHANGED
|
@@ -24,10 +24,27 @@ export declare class PyAIError extends Error {
|
|
|
24
24
|
constructor(status: number, message: string, code?: string, type?: string, requestId?: string);
|
|
25
25
|
}
|
|
26
26
|
export interface Voice {
|
|
27
|
+
/** Canonical catalog identifier returned by GET /v1/voices. */
|
|
28
|
+
voice_id: string;
|
|
29
|
+
/** SDK compatibility alias, always equal to voice_id. */
|
|
27
30
|
id: string;
|
|
28
31
|
name?: string;
|
|
29
32
|
gender?: string;
|
|
30
33
|
region?: string;
|
|
34
|
+
language?: string;
|
|
35
|
+
/** Customer-facing quality tier. */
|
|
36
|
+
tier?: "standard" | "natural";
|
|
37
|
+
/** Permanent convenience inputs accepted on the advertised surfaces. */
|
|
38
|
+
aliases?: string[];
|
|
39
|
+
/** Product surfaces on which this stock voice can be selected. */
|
|
40
|
+
available_on?: Array<"speak" | "omni">;
|
|
41
|
+
/** Accepted Speak delivery modes. Empty means the voice has no Speak surface. */
|
|
42
|
+
synthesis_modes?: Array<"streaming" | "async">;
|
|
43
|
+
/** Voice-specific amount on top of the selected product's base rate. */
|
|
44
|
+
pricing?: {
|
|
45
|
+
included_in_base_price: boolean;
|
|
46
|
+
additional_price_usd_per_minute: number;
|
|
47
|
+
};
|
|
31
48
|
[k: string]: unknown;
|
|
32
49
|
}
|
|
33
50
|
export interface ListResponse<T> {
|
|
@@ -49,13 +66,13 @@ export interface TranscriptionJob {
|
|
|
49
66
|
* Output container/codec for `audio.speech`. This is the **exact** set the
|
|
50
67
|
* server accepts on `POST /v1/audio/speech`, any other value is rejected with
|
|
51
68
|
* `400 unsupported_format`. The default (when `response_format` is omitted) is
|
|
52
|
-
* `
|
|
69
|
+
* `wav`. Omit `sample_rate` for the engine's native 24 kHz (`g711_*` is always
|
|
53
70
|
* 8 kHz).
|
|
54
71
|
*
|
|
55
72
|
* | format | rates (Hz) | Content-Type |
|
|
56
73
|
* |---|---|---|
|
|
57
|
-
* | `
|
|
58
|
-
* | `
|
|
74
|
+
* | `wav` (default) | 8000/16000/24000/48000 | `audio/wav` |
|
|
75
|
+
* | `mp3` | 8000/16000/24000/48000 | `audio/mpeg` |
|
|
59
76
|
* | `opus` | 8000/16000/24000/48000 | `audio/ogg` |
|
|
60
77
|
* | `aac` | 8000/16000/24000/48000 | `audio/aac` |
|
|
61
78
|
* | `flac` | 8000/16000/24000/48000 | `audio/flac` |
|
|
@@ -73,14 +90,23 @@ export declare const SPEECH_FORMATS: readonly ["wav", "mp3", "opus", "aac", "fla
|
|
|
73
90
|
/** Sample rates (Hz) the server accepts for `audio.speech` (`g711_*` is always 8 kHz). */
|
|
74
91
|
export declare const SPEECH_SAMPLE_RATES: readonly [8000, 16000, 24000, 48000];
|
|
75
92
|
export type SpeechSampleRate = (typeof SPEECH_SAMPLE_RATES)[number];
|
|
93
|
+
/** Canonical Speak model plus the intentional OpenAI drop-in aliases. */
|
|
94
|
+
export type SpeakModel = "pyai-speak" | "tts-1" | "tts-1-hd";
|
|
76
95
|
export interface SpeechParams {
|
|
77
96
|
input: string;
|
|
78
97
|
voice?: string;
|
|
79
|
-
model?:
|
|
98
|
+
model?: SpeakModel;
|
|
99
|
+
/**
|
|
100
|
+
* Delivery mode. The API defaults to true and every catalog voice accepts
|
|
101
|
+
* both values. Set false when you want one complete buffered body with a
|
|
102
|
+
* `Content-Length`. A voice whose serving fleet has no streaming lane is
|
|
103
|
+
* rendered buffered either way and says so with `x-pyai-stream: buffered`.
|
|
104
|
+
*/
|
|
105
|
+
stream?: boolean;
|
|
80
106
|
/**
|
|
81
107
|
* Output container/codec, resampled+encoded server-side. One of
|
|
82
108
|
* {@link SpeechFormat}, anything else is a `400 unsupported_format`. Omit for
|
|
83
|
-
* the default of `
|
|
109
|
+
* the default of `wav`.
|
|
84
110
|
*
|
|
85
111
|
* `g711_ulaw`/`g711_alaw` return raw 8 kHz mono G.711, the bytes Twilio/SIP
|
|
86
112
|
* media streams expect, so you can hand the response straight to a telephony
|
|
@@ -97,15 +123,14 @@ export interface SpeechParams {
|
|
|
97
123
|
* telephony pipelines, most often with `response_format: "pcm"`.
|
|
98
124
|
*/
|
|
99
125
|
sample_rate?: SpeechSampleRate;
|
|
126
|
+
/** Reserved; currently returns `400 unsupported_parameter` when provided. */
|
|
100
127
|
speed?: number;
|
|
101
128
|
/**
|
|
102
|
-
*
|
|
103
|
-
* honored once the engine supports it (otherwise ignored server-side), so it's
|
|
104
|
-
* always safe to send.
|
|
129
|
+
* Reserved; currently returns `400 unsupported_parameter` when provided.
|
|
105
130
|
*/
|
|
106
131
|
seed?: number;
|
|
107
132
|
/**
|
|
108
|
-
*
|
|
133
|
+
* Reserved; currently returns `400 unsupported_parameter` when provided.
|
|
109
134
|
*/
|
|
110
135
|
temperature?: number;
|
|
111
136
|
}
|
|
@@ -115,12 +140,59 @@ export interface CreateJobParams {
|
|
|
115
140
|
diarize?: boolean;
|
|
116
141
|
channel?: boolean;
|
|
117
142
|
numerals?: boolean;
|
|
143
|
+
smart_format?: boolean;
|
|
144
|
+
dictation?: boolean;
|
|
145
|
+
drop_fillers?: boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Per-job names, brands, products, or distinctive terms. PyAI keeps up to
|
|
148
|
+
* five valid entries after trimming, deduplication, and common-word
|
|
149
|
+
* filtering.
|
|
150
|
+
*/
|
|
151
|
+
vocabulary?: string[];
|
|
118
152
|
output_formats?: Array<"json" | "srt" | "vtt">;
|
|
119
153
|
webhook_url?: string;
|
|
154
|
+
call_id?: string;
|
|
155
|
+
pack_id?: string;
|
|
156
|
+
call_direction?: "inbound" | "outbound";
|
|
157
|
+
customer_name?: string;
|
|
158
|
+
}
|
|
159
|
+
export type HearVocabularyProfile = "batch" | "hear_stream";
|
|
160
|
+
export interface HearVocabularyInput {
|
|
161
|
+
/** Organization-owned names, brands, products, or distinctive terms. */
|
|
162
|
+
terms: string[];
|
|
163
|
+
/** Stored terms remain inert unless a use case is selected here. */
|
|
164
|
+
enabledFor: HearVocabularyProfile[];
|
|
165
|
+
}
|
|
166
|
+
export interface HearVocabulary {
|
|
167
|
+
object: "hear.vocabulary";
|
|
168
|
+
/** Sanitized stored list, at most five terms. */
|
|
169
|
+
terms: string[];
|
|
170
|
+
/** Use cases that may add stored suggestions. */
|
|
171
|
+
enabled_for: HearVocabularyProfile[];
|
|
172
|
+
/** Unix milliseconds, or null before the first save. */
|
|
173
|
+
updated_at: number | null;
|
|
174
|
+
}
|
|
175
|
+
export interface AgentConfig {
|
|
176
|
+
name?: string;
|
|
177
|
+
persona_system_prompt?: string | null;
|
|
178
|
+
greeting?: string | null;
|
|
179
|
+
voice_id?: string | null;
|
|
180
|
+
language?: "en" | "fr" | "es" | "de" | "hi" | null;
|
|
181
|
+
/**
|
|
182
|
+
* Opt-in speech-recognition vocabulary. PyAI sanitizes and keeps at most
|
|
183
|
+
* five terms. An empty list or null turns it off.
|
|
184
|
+
*/
|
|
185
|
+
vocabulary?: string[] | null;
|
|
186
|
+
[key: string]: unknown;
|
|
187
|
+
}
|
|
188
|
+
export interface Agent {
|
|
189
|
+
object: "agent";
|
|
190
|
+
agent_id: string;
|
|
191
|
+
name: string;
|
|
192
|
+
vocabulary: string[];
|
|
193
|
+
[key: string]: unknown;
|
|
120
194
|
}
|
|
121
195
|
export interface RealtimeOptions {
|
|
122
|
-
/** "omni" (agentic voice) or "flow" (legacy voice duplex). Default "omni". */
|
|
123
|
-
product?: "omni" | "flow";
|
|
124
196
|
/**
|
|
125
197
|
* Optional opaque tag echoed to your `kb_endpoint` and recorded on the call.
|
|
126
198
|
* Omni is zero-state: the session is authorized by the key's org, so there is
|
|
@@ -128,12 +200,10 @@ export interface RealtimeOptions {
|
|
|
128
200
|
*/
|
|
129
201
|
sessionLabel?: string;
|
|
130
202
|
/**
|
|
131
|
-
*
|
|
132
|
-
* `
|
|
133
|
-
*
|
|
203
|
+
* Extra canonical query params (`format`, `rate`, or the intentional
|
|
204
|
+
* server-side `api_key` auth option). Retired connect aliases and model/token
|
|
205
|
+
* selectors are rejected.
|
|
134
206
|
*/
|
|
135
|
-
agentId?: string;
|
|
136
|
-
/** Extra query params (e.g. format, rate). */
|
|
137
207
|
query?: Record<string, string>;
|
|
138
208
|
}
|
|
139
209
|
/** Parameters for minting an ephemeral browser Omni session token (server-side). */
|
|
@@ -167,6 +237,8 @@ export interface OmniSession {
|
|
|
167
237
|
}
|
|
168
238
|
/** Frame `type`s emitted by the Hear streaming-STT WebSocket. */
|
|
169
239
|
export declare const HearFrameType: {
|
|
240
|
+
/** Applied endpointing configuration and validation warnings. */
|
|
241
|
+
readonly ConfigAck: "config_ack";
|
|
170
242
|
/** Eager live hypothesis for the current utterance. */
|
|
171
243
|
readonly Partial: "partial";
|
|
172
244
|
/** Partial whose prefix has stabilized (won't be revised). */
|
|
@@ -181,10 +253,16 @@ export declare const HearFrameType: {
|
|
|
181
253
|
readonly Error: "error";
|
|
182
254
|
};
|
|
183
255
|
export type HearFrameType = (typeof HearFrameType)[keyof typeof HearFrameType];
|
|
184
|
-
/**
|
|
256
|
+
/**
|
|
257
|
+
* WebSocket close codes used across the PyAI realtime/streaming surfaces.
|
|
258
|
+
* Browser callers may initiate only Normal or values in 3000-4999; the
|
|
259
|
+
* standards-reserved values below are server close observations.
|
|
260
|
+
*/
|
|
185
261
|
export declare const WSCloseCode: {
|
|
186
262
|
/** Normal closure. */
|
|
187
263
|
readonly Normal: 1000;
|
|
264
|
+
/** Browser-safe private application code for a malformed peer protocol frame. */
|
|
265
|
+
readonly ProtocolViolation: 4002;
|
|
188
266
|
/** Auth/policy: bad key, missing scope, or revoked token. */
|
|
189
267
|
readonly PolicyViolation: 1008;
|
|
190
268
|
/** Engine/internal error. */
|
|
@@ -202,7 +280,7 @@ export declare const ErrorCode: {
|
|
|
202
280
|
readonly Unauthorized: "unauthorized";
|
|
203
281
|
readonly Forbidden: "forbidden";
|
|
204
282
|
readonly OriginNotAllowed: "origin_not_allowed";
|
|
205
|
-
readonly
|
|
283
|
+
readonly InvalidSessionLabel: "invalid_session_label";
|
|
206
284
|
readonly CreditExhausted: "credit_exhausted";
|
|
207
285
|
readonly KeyBudgetExceeded: "key_budget_exceeded";
|
|
208
286
|
readonly InsufficientQuota: "insufficient_quota";
|
|
@@ -212,6 +290,7 @@ export declare const ErrorCode: {
|
|
|
212
290
|
readonly IdempotencyConflict: "idempotency_conflict";
|
|
213
291
|
readonly NotFound: "not_found";
|
|
214
292
|
readonly NumberInUse: "number_in_use";
|
|
293
|
+
readonly UnsupportedToolTransport: "unsupported_tool_transport";
|
|
215
294
|
};
|
|
216
295
|
export type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];
|
|
217
296
|
/** A top-3 knowledge-base passage attached to Cue (grounded) finals. */
|
|
@@ -219,6 +298,22 @@ export interface HearGroundingPassage {
|
|
|
219
298
|
content: string;
|
|
220
299
|
score: number;
|
|
221
300
|
}
|
|
301
|
+
/** One endpointing validation result echoed in a `config_ack` frame. */
|
|
302
|
+
export interface HearConfigWarning {
|
|
303
|
+
field: string;
|
|
304
|
+
value: unknown;
|
|
305
|
+
effective?: number;
|
|
306
|
+
reason: "clamped_to_range" | "not_a_number" | "unknown_config_field" | (string & {});
|
|
307
|
+
}
|
|
308
|
+
/** Applied endpointing settings after connect-time or mid-session config. */
|
|
309
|
+
export interface HearConfigAckFrame {
|
|
310
|
+
type: "config_ack";
|
|
311
|
+
endpointing_ms: number;
|
|
312
|
+
effective_floor_ms: number;
|
|
313
|
+
effective_ceiling_ms: number;
|
|
314
|
+
score_interval_ms: number;
|
|
315
|
+
warnings: HearConfigWarning[];
|
|
316
|
+
}
|
|
222
317
|
/** Live hypothesis frame (`partial` / `partial_stable`). */
|
|
223
318
|
export interface HearPartialFrame {
|
|
224
319
|
type: "partial" | "partial_stable";
|
|
@@ -232,6 +327,7 @@ export interface HearPartialFrame {
|
|
|
232
327
|
t_ms: number;
|
|
233
328
|
}
|
|
234
329
|
/** Finalized-utterance frame (`speech_final` / `final`). */
|
|
330
|
+
export type HearEndpointReason = "peak_te_early" | "silence_backstop" | "commit" | (string & {});
|
|
235
331
|
export interface HearFinalFrame {
|
|
236
332
|
type: "speech_final" | "final";
|
|
237
333
|
text: string;
|
|
@@ -239,6 +335,8 @@ export interface HearFinalFrame {
|
|
|
239
335
|
t_ms: number;
|
|
240
336
|
/** Active-speech length of the utterance (the billed signal), ms. */
|
|
241
337
|
audio_ms: number;
|
|
338
|
+
/** Why the utterance ended. Log this when tuning automatic endpointing. */
|
|
339
|
+
endpoint_reason: HearEndpointReason;
|
|
242
340
|
/** Present only with Cue grounding enabled (top KB passages). */
|
|
243
341
|
grounding?: HearGroundingPassage[];
|
|
244
342
|
}
|
|
@@ -250,7 +348,7 @@ export interface HearUsageFrame {
|
|
|
250
348
|
type: "usage";
|
|
251
349
|
/** `hear` for plain streaming, `cue` when grounding was enabled. */
|
|
252
350
|
product: "hear" | "cue";
|
|
253
|
-
/** The billed meter (`hear.
|
|
351
|
+
/** The billed meter (`hear.minutes` or `cue.minutes`). */
|
|
254
352
|
meter: string;
|
|
255
353
|
/** Summed active-speech audio billed for the session, in seconds. */
|
|
256
354
|
audio_seconds: number;
|
|
@@ -263,7 +361,7 @@ export interface HearErrorFrame {
|
|
|
263
361
|
code?: string;
|
|
264
362
|
message: string;
|
|
265
363
|
}
|
|
266
|
-
export type HearFrame = HearPartialFrame | HearFinalFrame | HearUsageFrame | HearErrorFrame;
|
|
364
|
+
export type HearFrame = HearConfigAckFrame | HearPartialFrame | HearFinalFrame | HearUsageFrame | HearErrorFrame;
|
|
267
365
|
/**
|
|
268
366
|
* Minimal structural WebSocket, matches both the browser/Node global
|
|
269
367
|
* `WebSocket` and the `ws` package, and lets tests inject a mock.
|
|
@@ -282,35 +380,68 @@ export interface WebSocketLike {
|
|
|
282
380
|
reason: string;
|
|
283
381
|
}) => void) | null;
|
|
284
382
|
}
|
|
383
|
+
/**
|
|
384
|
+
* The non-secret marker every PyAI realtime client offers ALONGSIDE its
|
|
385
|
+
* `pyai-key.<KEY>` credential token.
|
|
386
|
+
*
|
|
387
|
+
* A browser cannot set `Authorization` on a WebSocket, so the key rides in
|
|
388
|
+
* `Sec-WebSocket-Protocol`. RFC 6455 makes the server echo the subprotocol it
|
|
389
|
+
* SELECTS, so a server that selects the credential publishes the credential —
|
|
390
|
+
* which api.pyai.com did until 2026-09-07. The edge now echoes only this
|
|
391
|
+
* marker. Offering it is not optional for Node clients: `ws` throws
|
|
392
|
+
* "Server sent no subprotocol" when it offered subprotocols and the 101
|
|
393
|
+
* selected none, and RFC 6455 lets the server select only a value the client
|
|
394
|
+
* actually offered.
|
|
395
|
+
*/
|
|
396
|
+
export declare const REALTIME_SUBPROTOCOL_MARKER = "pyai.v1";
|
|
285
397
|
export type WebSocketCtor = new (url: string, protocols?: string | string[]) => WebSocketLike;
|
|
286
398
|
export interface HearStreamOptions {
|
|
287
399
|
/** Streaming STT model. Server default `pyai-hear`. */
|
|
288
400
|
model?: string;
|
|
289
|
-
/**
|
|
290
|
-
language?:
|
|
401
|
+
/** Omit or use auto for automatic detection; an explicit code pins recognition. */
|
|
402
|
+
language?: "auto" | "en" | "es" | "fr" | "de" | "hi" | "it" | "pt" | "nl";
|
|
291
403
|
/** Input PCM sample rate in Hz. Default 16000 server-side. */
|
|
292
404
|
sampleRate?: number;
|
|
293
405
|
/** Audio frame encoding. Default "pcm16". */
|
|
294
|
-
encoding?: "pcm16"
|
|
406
|
+
encoding?: "pcm16";
|
|
295
407
|
/** Emit eager partial hypotheses. Default true server-side. */
|
|
296
408
|
interimResults?: boolean;
|
|
297
409
|
/**
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
*
|
|
410
|
+
* Tri-state number formatting on **final** transcripts. `true` forces digits,
|
|
411
|
+
* `false` keeps spoken form, omitted keeps the live engine default (ITN on).
|
|
412
|
+
* Never applied to interim partials. Independent of `smartFormat`.
|
|
301
413
|
*/
|
|
302
414
|
numerals?: boolean;
|
|
303
415
|
/**
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
|
|
307
|
-
|
|
416
|
+
* Opt-in English punctuation and sentence capitalization on **final**
|
|
417
|
+
* transcripts only. Interim partials are never formatted. Default false.
|
|
418
|
+
*/
|
|
419
|
+
smartFormat?: boolean;
|
|
420
|
+
/**
|
|
421
|
+
* Spoken punctuation commands (`period`, `comma`, `new paragraph`,
|
|
422
|
+
* `question mark`) on finals only. Separate from `smartFormat`. Off by default.
|
|
423
|
+
*/
|
|
424
|
+
dictation?: boolean;
|
|
425
|
+
/**
|
|
426
|
+
* Strip `um` / `uh` / `umm` / `uhh` / `er` on finals. Off by default.
|
|
427
|
+
* Do not enable on legal or compliance audio by default.
|
|
428
|
+
*/
|
|
429
|
+
dropFillers?: boolean;
|
|
430
|
+
/**
|
|
431
|
+
* Per-session names, brands, products, or other distinctive terms. PyAI
|
|
432
|
+
* sanitizes up to five effective terms. Request terms come first, then stored
|
|
433
|
+
* `hear_stream` suggestions fill remaining slots. The list is fixed at open.
|
|
434
|
+
*/
|
|
435
|
+
vocabulary?: string[];
|
|
436
|
+
/**
|
|
437
|
+
* Minimum trailing-pause length before an utterance may end (50-5000 ms).
|
|
438
|
+
* Turn detection may wait longer, bounded at `max(endpointingMs, 1500)`.
|
|
439
|
+
* The server confirms the applied value through `onConfigAck`.
|
|
308
440
|
*/
|
|
309
441
|
endpointingMs?: number;
|
|
310
442
|
/**
|
|
311
|
-
*
|
|
312
|
-
*
|
|
313
|
-
* array. Bills a single `cue.minutes` line instead of the Hear rate.
|
|
443
|
+
* Reserved Cue grounding configuration. Grounding is not active on the
|
|
444
|
+
* serving Hear stream; do not rely on grounding frames or Cue metering yet.
|
|
314
445
|
*/
|
|
315
446
|
grounding?: boolean;
|
|
316
447
|
/** Cue: number of KB passages to retrieve per turn (1-20, default 3). */
|
|
@@ -322,8 +453,11 @@ export interface HearStreamOptions {
|
|
|
322
453
|
groundingTimeoutMs?: number;
|
|
323
454
|
/** Extra query params merged onto the connect URL. */
|
|
324
455
|
query?: Record<string, string>;
|
|
325
|
-
/** Fired once the socket opens
|
|
456
|
+
/** Fired once the socket opens. */
|
|
326
457
|
onOpen?: () => void;
|
|
458
|
+
/** Fired after connect-time or mid-session endpointing config. Assert that
|
|
459
|
+
* `warnings` is empty before relying on the requested floor. */
|
|
460
|
+
onConfigAck?: (frame: HearConfigAckFrame) => void;
|
|
327
461
|
/** Fired on `partial` / `partial_stable`. */
|
|
328
462
|
onPartial?: (frame: HearPartialFrame) => void;
|
|
329
463
|
/** Fired on `speech_final` / `final`. */
|
|
@@ -340,8 +474,10 @@ export interface HearStreamOptions {
|
|
|
340
474
|
/**
|
|
341
475
|
* A live Hear streaming-STT session. Hides the frame protocol: stream audio
|
|
342
476
|
* with {@link HearStream.sendAudio}, get `onPartial`/`onFinal`/`onError`
|
|
343
|
-
* callbacks,
|
|
344
|
-
*
|
|
477
|
+
* callbacks, update the silence floor with
|
|
478
|
+
* {@link HearStream.configureEndpointing}, force-finalize with
|
|
479
|
+
* {@link HearStream.commit}, and flush+close with {@link HearStream.close}.
|
|
480
|
+
* Construct via `pyai.audio.transcriptions.stream()`.
|
|
345
481
|
*/
|
|
346
482
|
export declare class HearStream {
|
|
347
483
|
private readonly ws;
|
|
@@ -351,6 +487,8 @@ export declare class HearStream {
|
|
|
351
487
|
private handleMessage;
|
|
352
488
|
/** Send a chunk of audio (PCM16 or opus per `encoding`). */
|
|
353
489
|
sendAudio(chunk: ArrayBufferLike | ArrayBufferView | Blob): void;
|
|
490
|
+
/** Change the minimum trailing-pause floor without reconnecting. */
|
|
491
|
+
configureEndpointing(endpointingMs: number): void;
|
|
354
492
|
/** Force-finalize the current utterance (e.g. on VAD end-of-turn). */
|
|
355
493
|
commit(): void;
|
|
356
494
|
/** Close the socket; the server flushes a final for any buffered audio. */
|
|
@@ -409,6 +547,8 @@ export declare const OmniEvent: {
|
|
|
409
547
|
readonly Flush: "flush";
|
|
410
548
|
/** Engine requests a client-loop tool invocation. */
|
|
411
549
|
readonly ToolCall: "tool_call";
|
|
550
|
+
/** A write tool is waiting for the caller to confirm; it has not run. */
|
|
551
|
+
readonly ToolConfirmationRequired: "tool_confirmation_required";
|
|
412
552
|
/** Session is closing; see close code. */
|
|
413
553
|
readonly SessionEnd: "session_end";
|
|
414
554
|
/** Server fault frame. */
|
|
@@ -420,16 +560,20 @@ export interface OmniServerFrame {
|
|
|
420
560
|
event: string;
|
|
421
561
|
[k: string]: unknown;
|
|
422
562
|
}
|
|
423
|
-
/** Canonical, sanitized transcript delivered by the native Omni demux.
|
|
563
|
+
/** Canonical, sanitized transcript delivered by the native Omni demux.
|
|
564
|
+
* The live wire sends caller text deltas; the JSON fields are SDK-owned
|
|
565
|
+
* normalization so applications don't have to special-case the byte payload. */
|
|
424
566
|
export interface OmniTranscriptFrame extends OmniServerFrame {
|
|
425
567
|
event: "transcript";
|
|
426
568
|
role: "user" | "assistant";
|
|
427
569
|
text: string;
|
|
428
570
|
final: boolean;
|
|
571
|
+
/** Live text frames append; legacy JSON frames replace unless they use `delta`. */
|
|
429
572
|
mode: "delta" | "replace";
|
|
573
|
+
/** Optional ordering hint on legacy JSON frames. */
|
|
430
574
|
sequence?: number;
|
|
431
575
|
}
|
|
432
|
-
/** Normalize the live UTF-8 0x02 body and
|
|
576
|
+
/** Normalize the live UTF-8 `0x02` text body and bounded legacy JSON bodies. */
|
|
433
577
|
export declare function normalizeOmniTranscriptBody(bytes: Uint8Array): OmniTranscriptFrame | null;
|
|
434
578
|
/** A binary agent-audio chunk delivered to {@link OmniConnectOptions.onAudio}. */
|
|
435
579
|
export type OmniAudioChunk = ArrayBuffer | ArrayBufferView | Blob;
|
|
@@ -437,11 +581,9 @@ export interface OmniToolDef {
|
|
|
437
581
|
name: string;
|
|
438
582
|
description?: string;
|
|
439
583
|
parameters?: Record<string, unknown>;
|
|
440
|
-
/** When set, engine-POST mode. Omit for client-loop (default). */
|
|
441
|
-
endpoint?: string;
|
|
442
584
|
}
|
|
443
585
|
export interface OmniToolCallFrame {
|
|
444
|
-
|
|
586
|
+
event: "tool_call";
|
|
445
587
|
call_id: string;
|
|
446
588
|
name: string;
|
|
447
589
|
arguments?: Record<string, unknown>;
|
|
@@ -466,7 +608,7 @@ export interface OmniConfigure {
|
|
|
466
608
|
/**
|
|
467
609
|
* Session language, end to end (recognition, reasoning, voice). Also
|
|
468
610
|
* settable on the agent profile (`language` on `POST /v1/agents`), which
|
|
469
|
-
* applies automatically when
|
|
611
|
+
* applies automatically when `session_label` is the saved profile id;
|
|
470
612
|
* an inline value here wins for the session. Default `en`. Fail-safe: an
|
|
471
613
|
* unknown/not-yet-enabled language falls back to `en` (the `configured`
|
|
472
614
|
* ack carries `language_active` + `language_fallback: true`), the call
|
|
@@ -474,7 +616,9 @@ export interface OmniConfigure {
|
|
|
474
616
|
* staged, see the Language support reference.
|
|
475
617
|
*/
|
|
476
618
|
language?: "en" | "fr" | "es" | "de" | "hi";
|
|
477
|
-
/** Function calling
|
|
619
|
+
/** Function calling: hosted catalog names, client-loop schemas, or names of
|
|
620
|
+
* server tools already registered with POST /v1/tools. An inline `endpoint`
|
|
621
|
+
* is rejected with `unsupported_tool_transport`. */
|
|
478
622
|
tools?: OmniToolDef[];
|
|
479
623
|
/** Forward-compatible: any other key the engine honors. */
|
|
480
624
|
[k: string]: unknown;
|
|
@@ -488,7 +632,11 @@ export interface OmniConnectOptions {
|
|
|
488
632
|
* so a page never holds a secret key.
|
|
489
633
|
*/
|
|
490
634
|
token?: string;
|
|
491
|
-
/**
|
|
635
|
+
/**
|
|
636
|
+
* Caller-input sample rate. `24000` and `16000` sessions receive agent audio
|
|
637
|
+
* at 24 kHz; `8000` sessions receive 8 kHz. Read `hello.audio_out` rather than
|
|
638
|
+
* assuming output matches this value.
|
|
639
|
+
*/
|
|
492
640
|
rate?: 24000 | 16000 | 8000;
|
|
493
641
|
/** Connect-URL audio format. Default `pcm16`. */
|
|
494
642
|
format?: "pcm16";
|
|
@@ -511,7 +659,7 @@ export interface OmniConnectOptions {
|
|
|
511
659
|
onSessionStarted?: (frame: OmniServerFrame) => void;
|
|
512
660
|
/** Fired on `turn` boundaries. */
|
|
513
661
|
onTurn?: (frame: OmniServerFrame) => void;
|
|
514
|
-
/** Fired
|
|
662
|
+
/** Fired for each normalized caller-transcript delta (`0x02` plain UTF-8 live). */
|
|
515
663
|
onTranscript?: (frame: OmniServerFrame) => void;
|
|
516
664
|
/** Fired on `barge_in` / `flush` (user interrupted). */
|
|
517
665
|
onBargeIn?: (frame: OmniServerFrame) => void;
|
|
@@ -836,8 +984,45 @@ export interface RecapCallSummary {
|
|
|
836
984
|
created_at?: number;
|
|
837
985
|
completed_at?: number | null;
|
|
838
986
|
}
|
|
987
|
+
export interface RecapActionItem {
|
|
988
|
+
owner?: string | null;
|
|
989
|
+
task: string;
|
|
990
|
+
due?: string | null;
|
|
991
|
+
}
|
|
992
|
+
export interface RecapTalkRatio {
|
|
993
|
+
agent: number;
|
|
994
|
+
customer: number;
|
|
995
|
+
}
|
|
996
|
+
export interface RecapSignal {
|
|
997
|
+
kind: string;
|
|
998
|
+
text: string;
|
|
999
|
+
at_s?: number | null;
|
|
1000
|
+
}
|
|
1001
|
+
export interface RecapRecord {
|
|
1002
|
+
format: "recap.record.v1";
|
|
1003
|
+
tldr: string | null;
|
|
1004
|
+
summary: string | null;
|
|
1005
|
+
action_items: RecapActionItem[];
|
|
1006
|
+
disposition: string | null;
|
|
1007
|
+
next_steps: string | null;
|
|
1008
|
+
talk_ratio: RecapTalkRatio | null;
|
|
1009
|
+
signals: RecapSignal[];
|
|
1010
|
+
fields: Record<string, unknown>;
|
|
1011
|
+
rep?: Record<string, unknown>;
|
|
1012
|
+
manager?: Record<string, unknown>;
|
|
1013
|
+
ops?: Record<string, unknown>;
|
|
1014
|
+
}
|
|
839
1015
|
export interface RecapCall extends RecapCallSummary {
|
|
840
|
-
record?:
|
|
1016
|
+
record?: RecapRecord;
|
|
1017
|
+
transcript?: {
|
|
1018
|
+
format: "utterances.v1";
|
|
1019
|
+
utterances: Array<{
|
|
1020
|
+
speaker_role: "agent" | "customer";
|
|
1021
|
+
text: string;
|
|
1022
|
+
offset_s: number;
|
|
1023
|
+
duration_s: number;
|
|
1024
|
+
}>;
|
|
1025
|
+
};
|
|
841
1026
|
error?: string | null;
|
|
842
1027
|
crm_write_status?: string | null;
|
|
843
1028
|
}
|
|
@@ -854,8 +1039,13 @@ export interface RecapCallTriggerInput {
|
|
|
854
1039
|
customer_name?: string;
|
|
855
1040
|
crm_fields?: Record<string, unknown>;
|
|
856
1041
|
}
|
|
857
|
-
/**
|
|
858
|
-
|
|
1042
|
+
/**
|
|
1043
|
+
* The answered-by vocabulary on stored call records and the
|
|
1044
|
+
* `amd.call.completed` webhook: the routing classes plus the machine subtypes.
|
|
1045
|
+
*/
|
|
1046
|
+
export type AmdAnsweredBy = "human" | "machine" | "voicemail" | "screening" | "ivr" | "music" | "sit_invalid" | "unknown";
|
|
1047
|
+
/** The routing classes pushed on the mid-call wire event (`event: "amd"`). */
|
|
1048
|
+
export type AmdWireAnsweredBy = "human" | "machine" | "sit_invalid" | "unknown";
|
|
859
1049
|
/** Twilio's `AnsweredBy` enum, echoed for drop-in migration parity. */
|
|
860
1050
|
export type AmdTwilioAnsweredBy = "human" | "machine_start" | "machine_end_beep" | "machine_end_silence" | "machine_end_other" | "fax" | "unknown";
|
|
861
1051
|
export interface AmdConfigInput {
|
|
@@ -893,11 +1083,16 @@ export interface AmdCall extends AmdCallSummary {
|
|
|
893
1083
|
meta?: Record<string, unknown> | null;
|
|
894
1084
|
error?: string | null;
|
|
895
1085
|
}
|
|
896
|
-
/**
|
|
1086
|
+
/**
|
|
1087
|
+
* A mid-call AMD decision event pushed on the stream (and to the per-call
|
|
1088
|
+
* TwiML `webhook`). Carries the coarse routing class; the machine subtype
|
|
1089
|
+
* (`voicemail`/`ivr`/`screening`/`music`) is on the stored call record
|
|
1090
|
+
* (`AmdCall`) and the `amd.call.completed` webhook instead.
|
|
1091
|
+
*/
|
|
897
1092
|
export interface AmdDecisionEvent {
|
|
898
1093
|
event?: "amd";
|
|
899
1094
|
call_id?: string;
|
|
900
|
-
answered_by?:
|
|
1095
|
+
answered_by?: AmdWireAnsweredBy;
|
|
901
1096
|
answered_by_twilio?: string | null;
|
|
902
1097
|
confidence?: number | null;
|
|
903
1098
|
decision_ms?: number | null;
|
|
@@ -946,19 +1141,43 @@ export declare class PyAI {
|
|
|
946
1141
|
list: (params?: {
|
|
947
1142
|
gender?: string;
|
|
948
1143
|
region?: string;
|
|
1144
|
+
language?: string;
|
|
1145
|
+
tier?: "standard" | "natural";
|
|
1146
|
+
q?: string;
|
|
949
1147
|
}) => Promise<ListResponse<Voice>>;
|
|
950
1148
|
get: (id: string) => Promise<Voice>;
|
|
951
1149
|
};
|
|
1150
|
+
hear: {
|
|
1151
|
+
vocabulary: {
|
|
1152
|
+
/** Read organization-owned vocabulary. Scope `hear:configure`. */
|
|
1153
|
+
get: () => Promise<HearVocabulary>;
|
|
1154
|
+
/** Replace vocabulary and activation profiles. Scope `hear:configure`. */
|
|
1155
|
+
set: (input: HearVocabularyInput) => Promise<HearVocabulary>;
|
|
1156
|
+
};
|
|
1157
|
+
};
|
|
1158
|
+
agents: {
|
|
1159
|
+
list: () => Promise<ListResponse<Agent>>;
|
|
1160
|
+
get: (agentId: string) => Promise<Agent>;
|
|
1161
|
+
create: (input: AgentConfig & {
|
|
1162
|
+
name: string;
|
|
1163
|
+
}) => Promise<Agent>;
|
|
1164
|
+
update: (agentId: string, patch: AgentConfig) => Promise<Agent>;
|
|
1165
|
+
delete: (agentId: string) => Promise<{
|
|
1166
|
+
object: "agent.deleted";
|
|
1167
|
+
agent_id: string;
|
|
1168
|
+
deleted: boolean;
|
|
1169
|
+
}>;
|
|
1170
|
+
};
|
|
952
1171
|
audio: {
|
|
953
1172
|
/** Text-to-speech. Returns the raw audio bytes (default WAV). */
|
|
954
1173
|
speech: (params: SpeechParams) => Promise<ArrayBuffer>;
|
|
955
1174
|
/**
|
|
956
1175
|
* Text-to-speech, streamed. Resolves as soon as the response headers arrive
|
|
957
1176
|
* with the body as a `ReadableStream` of audio bytes, so you can start
|
|
958
|
-
* playback or forward the audio at the first chunk
|
|
959
|
-
*
|
|
960
|
-
*
|
|
961
|
-
*
|
|
1177
|
+
* playback or forward the audio at the first chunk. Use `pcm`, `wav`,
|
|
1178
|
+
* or G.711 for streaming; `mp3` and `opus` are buffered server-side.
|
|
1179
|
+
* Consume the stream immediately and cancel its reader when stopping early.
|
|
1180
|
+
* HTTP connection reuse and protocol negotiation are controlled by fetch.
|
|
962
1181
|
*/
|
|
963
1182
|
speechStream: (params: SpeechParams) => Promise<ReadableStream<Uint8Array>>;
|
|
964
1183
|
/** Synchronous speech-to-text (multipart upload). */
|
|
@@ -967,7 +1186,13 @@ export declare class PyAI {
|
|
|
967
1186
|
file: Blob;
|
|
968
1187
|
filename?: string;
|
|
969
1188
|
model?: string;
|
|
970
|
-
language
|
|
1189
|
+
/** Optional language hint. Omission enables automatic detection. */
|
|
1190
|
+
language?: "en" | "es" | "fr" | "de" | "hi" | "it" | "pt" | "nl";
|
|
1191
|
+
numerals?: boolean;
|
|
1192
|
+
smart_format?: boolean;
|
|
1193
|
+
dictation?: boolean;
|
|
1194
|
+
drop_fillers?: boolean;
|
|
1195
|
+
vocabulary?: string[];
|
|
971
1196
|
response_format?: "json" | "text" | "verbose_json";
|
|
972
1197
|
/**
|
|
973
1198
|
* Deterministic seed for reproducible eval runs. Forward-compatible:
|
|
@@ -1007,7 +1232,7 @@ export declare class PyAI {
|
|
|
1007
1232
|
clones: {
|
|
1008
1233
|
/** List the org's cloned voices. */
|
|
1009
1234
|
list: () => Promise<ListResponse<Voice>>;
|
|
1010
|
-
/** Enroll a custom voice from reference audio (>= ~10s). Scope `
|
|
1235
|
+
/** Enroll a custom voice from reference audio (>= ~10s). Scope `speak:clone`. */
|
|
1011
1236
|
create: (params: {
|
|
1012
1237
|
name: string;
|
|
1013
1238
|
file: Blob;
|
|
@@ -1019,7 +1244,7 @@ export declare class PyAI {
|
|
|
1019
1244
|
* when the id isn't found.
|
|
1020
1245
|
*/
|
|
1021
1246
|
get: (id: string) => Promise<Voice>;
|
|
1022
|
-
/** Delete a cloned voice (tenant-isolated). Scope `
|
|
1247
|
+
/** Delete a cloned voice (tenant-isolated). Scope `speak:clone`. */
|
|
1023
1248
|
delete: (id: string) => Promise<void>;
|
|
1024
1249
|
};
|
|
1025
1250
|
telephony: {
|
|
@@ -1148,7 +1373,7 @@ export declare class PyAI {
|
|
|
1148
1373
|
* realtime. **Call this from your server** with a secret key holding
|
|
1149
1374
|
* `omni:session`; never ship the secret key to a page. Hand the returned
|
|
1150
1375
|
* `token` to the browser, which connects with
|
|
1151
|
-
* `new WebSocket(session.url, ["pyai-key." + session.token])`. The token
|
|
1376
|
+
* `new WebSocket(session.url, ["pyai.v1", "pyai-key." + session.token])`. The token
|
|
1152
1377
|
* expires after `ttlSeconds` (default 60s) and only works from
|
|
1153
1378
|
* `allowedOrigins`. Scope `omni:session`.
|
|
1154
1379
|
*/
|
|
@@ -1164,10 +1389,17 @@ export declare class PyAI {
|
|
|
1164
1389
|
*/
|
|
1165
1390
|
connect: (opts?: OmniConnectOptions) => OmniConnection;
|
|
1166
1391
|
};
|
|
1167
|
-
/** Build the
|
|
1392
|
+
/** Build the canonical Omni WebSocket URL. */
|
|
1168
1393
|
realtimeURL(opts?: RealtimeOptions): string;
|
|
1169
|
-
/** The subprotocol that carries the key on a WS upgrade
|
|
1394
|
+
/** The subprotocol token that carries the key on a WS upgrade. */
|
|
1170
1395
|
realtimeSubprotocol(): string;
|
|
1396
|
+
/**
|
|
1397
|
+
* The full subprotocol list to open a PyAI WebSocket with:
|
|
1398
|
+
* `[marker, credential]`. Always pass BOTH — see
|
|
1399
|
+
* {@link REALTIME_SUBPROTOCOL_MARKER}. Pass `token` to use an ephemeral
|
|
1400
|
+
* session token (from `omni.createSession`) instead of the secret key.
|
|
1401
|
+
*/
|
|
1402
|
+
realtimeSubprotocols(token?: string): string[];
|
|
1171
1403
|
/** Build the Hear streaming-STT WebSocket URL (`/v1/audio/transcriptions/stream`). */
|
|
1172
1404
|
hearStreamURL(opts?: HearStreamOptions): string;
|
|
1173
1405
|
/** Build the AMD detection WebSocket URL (`/v1/amd/stream`). */
|