@voctiv/agent-sdk 0.2.7 → 0.2.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.
Files changed (38) hide show
  1. package/README.md +156 -13
  2. package/dist/define-script.d.ts +7 -334
  3. package/dist/define-script.d.ts.map +1 -1
  4. package/dist/define-script.js +4 -3
  5. package/dist/define-script.js.map +1 -1
  6. package/dist/index.d.ts +10 -5
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +1 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/types/asr-handle.d.ts +23 -10
  11. package/dist/types/asr-handle.d.ts.map +1 -1
  12. package/dist/types/errors.d.ts +19 -0
  13. package/dist/types/errors.d.ts.map +1 -0
  14. package/dist/types/errors.js +3 -0
  15. package/dist/types/errors.js.map +1 -0
  16. package/dist/types/legacy-phrase.d.ts +10 -9
  17. package/dist/types/legacy-phrase.d.ts.map +1 -1
  18. package/dist/types/llm.d.ts +78 -0
  19. package/dist/types/llm.d.ts.map +1 -0
  20. package/dist/types/llm.js +3 -0
  21. package/dist/types/llm.js.map +1 -0
  22. package/dist/types/media-channel.d.ts +32 -567
  23. package/dist/types/media-channel.d.ts.map +1 -1
  24. package/dist/types/mixer.d.ts +40 -9
  25. package/dist/types/mixer.d.ts.map +1 -1
  26. package/dist/types/platform.d.ts +164 -0
  27. package/dist/types/platform.d.ts.map +1 -0
  28. package/dist/types/platform.js +3 -0
  29. package/dist/types/platform.js.map +1 -0
  30. package/dist/types/script-context.d.ts +170 -0
  31. package/dist/types/script-context.d.ts.map +1 -0
  32. package/dist/types/script-context.js +3 -0
  33. package/dist/types/script-context.js.map +1 -0
  34. package/dist/types/sip.d.ts +485 -0
  35. package/dist/types/sip.d.ts.map +1 -0
  36. package/dist/types/sip.js +3 -0
  37. package/dist/types/sip.js.map +1 -0
  38. package/package.json +1 -1
@@ -1,9 +1,12 @@
1
- import { Observable } from 'rxjs';
2
- import { AsrConfig, AsrHandle } from './asr-handle';
3
- import { DtmfEvent, SipInfo, SipSignal, DataMessage } from './events';
4
- import { MixerQueueControl, PlayOptions } from './mixer';
1
+ import type { Observable } from 'rxjs';
2
+ import type { AsrConfig, AsrHandle } from './asr-handle';
3
+ import type { DataMessage } from './events';
4
+ import type { MixerQueueControl, PlayOptions, PresayOptions, PreloadOptions } from './mixer';
5
5
  import type { LegacyPhraseRecord } from './legacy-phrase';
6
- import { TextInput } from './text-input';
6
+ import type { TextInput } from './text-input';
7
+ import type { MediaError } from './errors';
8
+ import type { ChannelLlm } from './llm';
9
+ import type { ChannelSip } from './sip';
7
10
  /**
8
11
  * Audio playback API — TTS synthesis, file/URL playback, caching, and multi-queue mixing.
9
12
  *
@@ -44,7 +47,7 @@ export interface ChannelAudio {
44
47
  * Play audio from a URL/path string, or a {@link LegacyPhraseRecord} from the Voctiv platform phrase DB.
45
48
  *
46
49
  * The runtime decodes the full source to PCM and pushes it to the mixer. `ttsVendor`,
47
- * `ttsConfig`, `ttsStrategy`, and `legacySavePhrase` do not affect raw playback.
50
+ * `ttsConfig`, `ttsStrategy`, and `cache` do not affect raw playback.
48
51
  *
49
52
  * @param source - HTTP(S) URL, local path, or structured {@link LegacyPhraseRecord} (no TTS).
50
53
  * @param options - Queue, alias, volume, loop; **`tts*`** fields apply only if the host
@@ -57,24 +60,28 @@ export interface ChannelAudio {
57
60
  /**
58
61
  * Download/decode **`source`** through the audio player.
59
62
  *
60
- * In ScriptEngine this warms the decoder/audio-player path for `play()`;
61
- * it does not synthesize TTS and does not populate the TTS cache used by `presay()`.
62
- * @param source - URL or file path accepted by the host’s fetch layer.
63
+ * In ScriptEngine this warms the decoder/audio-player path for `play()`.
64
+ * In legacy mode the decoded PCM is always persisted into `record_phrase` /
65
+ * `record_phrase_file` (default phrase name `_cache`).
66
+ *
67
+ * @param source - URL or file path accepted by the host's fetch layer.
68
+ * @param options - Optional; only `cache` is used to override persist name/flag/language.
63
69
  */
64
- preload(source: string): Promise<void>;
70
+ preload(source: string, options?: PreloadOptions): Promise<void>;
65
71
  /**
66
72
  * Run TTS ahead of time and store PCM in the host TTS cache.
67
73
  *
68
74
  * Later `say()` calls with the same resolved TTS config and text can reuse the cached
69
- * file. If the cache service is unavailable, ScriptEngine logs a warning and
70
- * resolves without throwing.
75
+ * file. In legacy mode the result is always persisted into `record_phrase`
76
+ * (default phrase name `_cache`).
77
+ *
71
78
  * @param text - Full text to synthesize.
72
- * @param options - Same TTS-related options as **`say`** (vendor, **`name`**, **`ttsConfig`**).
79
+ * @param options - TTS vendor/name/config and optional cache name/flag override.
73
80
  */
74
- presay(text: string, options?: PlayOptions): Promise<void>;
81
+ presay(text: string, options?: PresayOptions): Promise<void>;
75
82
  /**
76
83
  * @param index - Mixer queue **0–4**.
77
- * @returns Control handle for that queues volume and item lifecycle observables.
84
+ * @returns Control handle for that queue's volume and item lifecycle observables.
78
85
  */
79
86
  queue(index: number): MixerQueueControl;
80
87
  /**
@@ -110,570 +117,28 @@ export interface ChannelEvents {
110
117
  readonly terminated$: Observable<void>;
111
118
  /** Structured messages from the WS client or bridge (event + payload). */
112
119
  readonly message$: Observable<DataMessage>;
113
- }
114
- /** Options for **`channel.llm.ask`** / **`stream`** / **`makePersistentStream`**. */
115
- export interface LlmOptions {
116
- /** Override dialog UUID for Omni/LLM tracing (defaults to script dialog). */
117
- dialogUuid?: string;
118
- /** Chat role sent with the message, e.g. **`"assistant"`**, **`"user"`**. */
119
- role?: string;
120
- /** When `true`, message may be hidden from user-visible transcript (host-dependent). */
121
- hidden?: boolean;
122
- /**
123
- * **LLM-only**: speaker / persona label in multi-party chat. **Not** related to
124
- * {@link PlayOptions.name} (TTS **`key_storage.name`**).
125
- */
126
- name?: string;
127
- /** Route the request to a specific Omni agent profile (UUID). */
128
- agentUuid?: string;
129
- /** Multi-agent: current alias for routing. */
130
- currentAgentAlias?: string;
131
- /** Opaque payload forwarded to the Omni LLM backend. */
132
- payload?: Record<string, any>;
133
- /** Verbose logging on the LLM path. */
134
- debug?: boolean;
135
- /** Restrict which agent aliases may handle the request. */
136
- agentAliasFilter?: string[];
137
- }
138
- /** Options for **`channel.llm.extract`**. All fields except `dialogUuid` are forwarded to Omni extract. */
139
- export interface ExtractOptions {
140
- /** Override dialog UUID for extraction context; defaults to the current script dialog. */
141
- dialogUuid?: string;
142
- /** Optional extraction prompt/instruction forwarded to Omni. */
143
- prompt?: string;
144
- /** Model name or id understood by the Omni backend. */
145
- model?: string;
146
- /** Nucleus sampling value forwarded to Omni. */
147
- topP?: number;
148
- /** Temperature forwarded to Omni. */
149
- temperature?: number;
150
- /** Custom model descriptor forwarded as-is. */
151
- customModel?: Record<string, any>;
152
- [key: string]: unknown;
153
- }
154
- /** One chunk from **`channel.llm.stream`**. */
155
- export interface LlmStreamChunk {
156
- id: string;
157
- chunkId: number;
158
- content: string;
159
- finishReason: string | null;
160
- event: any;
161
- toolMessages?: any[];
162
- raw: Record<string, any>;
163
- }
164
- /**
165
- * Long-lived LLM Socket.IO stream — amortizes connection setup across many user turns.
166
- */
167
- export interface PersistentLlmStreamHandle {
168
- readonly stream$: Observable<LlmStreamChunk>;
169
- /** Send one user/assistant turn over the existing stream; options override defaults for this send only. */
170
- send(message: string, options?: LlmOptions): void;
171
- /** Close the underlying Socket.IO stream without destroying the handle object. */
172
- disconnect(): void;
173
- /** Re-open the underlying Socket.IO stream after {@link disconnect}. */
174
- reconnect(): void;
175
- }
176
- /** LLM facade on the media channel. */
177
- export interface ChannelLlm {
178
- /** Single-shot completion for **`message`**; consumes the Omni SSE stream and returns concatenated text. */
179
- ask(message: string, options?: LlmOptions): Promise<string>;
180
- /** Token/chunk stream for **`message`** parsed from Omni SSE `data:` events. */
181
- stream(message: string, options?: LlmOptions): Observable<LlmStreamChunk>;
182
- /** Structured extraction / JSON-style fill from conversation context via Omni extract. */
183
- extract(options?: ExtractOptions): Promise<Record<string, any>>;
184
- /**
185
- * Open a persistent Omni chat stream.
186
- * @param options - Default **`agentUuid`**, **`dialogUuid`**, etc.; per-**`send`** overrides allowed.
187
- */
188
- makePersistentStream(options?: LlmOptions): PersistentLlmStreamHandle;
189
- }
190
- /**
191
- * SIP call state visible to script developers.
192
- *
193
- * ### Lifecycle
194
- *
195
- * ```
196
- * outbound 183 w/ SDP
197
- * idle ──► ringing ─────────────────► early ──► active ──► terminated
198
- * │ ▲ ▲
199
- * │ inbound │ │
200
- * │ sendProgress()───────┘ │
201
- * └───────────────────────────────────┘ (early may be skipped)
202
- * ```
203
- *
204
- * | State | Meaning | How you get here |
205
- * |---|---|---|
206
- * | **`idle`** | Call object exists but no SIP signalling has started yet. | Initial state. |
207
- * | **`ringing`** | INVITE sent (outbound) or received (inbound); remote party is ringing. No media yet. | Automatic after INVITE. |
208
- * | **`early`** | RTP pipeline is up — you can **send and receive audio**, run ASR, play TTS. This is the "pre-answer" phase before final 200 OK. | **Outbound:** remote sends 183 Session Progress with SDP. **Inbound:** your script calls `sip.sendProgress()`. |
209
- * | **`active`** | 200 OK received/sent — the call is fully established. | **Outbound:** remote answers. **Inbound:** your script calls `sip.answer()`. |
210
- * | **`holding`** | Local hold is active. | Your script calls `sip.hold()`. |
211
- * | **`terminated`** | Call ended (BYE, CANCEL, or error). No further audio is possible. | Either side hangs up, or network error. |
212
- *
213
- * > **Note:** not every call goes through every state. A fast answer may jump
214
- * > `ringing` → `active` without `early`. An unanswered outbound call may go
215
- * > `ringing` → `terminated`. Inbound calls stay in `ringing` until you call
216
- * > either `sendProgress()` (→ `early`) or `answer()` (→ `active`).
217
- */
218
- export type SipState = 'idle' | 'ringing' | 'early' | 'active' | 'holding' | 'terminated';
219
- /**
220
- * A SIP 1xx provisional response forwarded to the script.
221
- *
222
- * Provisional responses are sent by the remote party **before** the final answer (200 OK).
223
- * Common examples:
224
- *
225
- * | Code | Phrase | Typical meaning |
226
- * |------|--------|-----------------|
227
- * | 100 | Trying | Request received, processing |
228
- * | 180 | Ringing | Remote phone is ringing (may carry SDP → early media) |
229
- * | 183 | Session Progress | Early media available — SDP is present, RTP can flow |
230
- *
231
- * Subscribe to `sip.progress$` to track every provisional response. The `sdp` field
232
- * is present only when the response carries a Session Description (media offer/answer).
233
- */
234
- export interface SipProgressEvent {
235
- /** SIP status code (100–199). */
236
- statusCode: number;
237
- /** Human-readable reason phrase, e.g. `"Ringing"`, `"Session Progress"`. */
238
- statusPhrase: string;
239
- /** Raw SDP body when the provisional response carries a media description. */
240
- sdp?: string;
241
- }
242
- /**
243
- * SIP channel API — call-state observables, DTMF, INFO, hold/mute/hangup,
244
- * outbound **`makeCall`**, **`bridge`**, and **pre-answer media**.
245
- *
246
- * ---
247
- *
248
- * ### Pre-answer media (early media)
249
- *
250
- * Both **inbound** and **outbound** calls support full-duplex audio **before** the
251
- * 200 OK answer. In the `"early"` state the RTP pipeline is fully operational —
252
- * ASR, TTS, `audio.say()`, `audio.play()`, and DTMF all work **exactly the same**
253
- * as in the `"active"` state.
254
- *
255
- * #### Outbound calls
256
- *
257
- * The remote side may send **183 Session Progress** with SDP (e.g. an IVR greeting,
258
- * ringback tone, or DTMF challenge). The call enters `"early"` automatically.
259
- *
260
- * #### Inbound calls
261
- *
262
- * Call `sip.sendProgress()` to send **183 Session Progress** to the caller. The call
263
- * enters `"early"` and audio flows in both directions before final 200 OK. The API
264
- * does not mark the call answered until `sip.answer()`; external billing still depends
265
- * on carrier policy. Call `sip.answer()` later to complete the answer.
266
- *
267
- * ---
268
- *
269
- * ### Quick examples
270
- *
271
- * #### Outbound — interact with an IVR before answer
272
- *
273
- * ```ts
274
- * const call = await channel.sip.makeCall({ sipUri: 'sip:+1234@trunk.example.com' });
275
- *
276
- * // Wait until RTP is ready (early media or full answer)
277
- * await call.sip.waitForEarly();
278
- * // Audio flows — start ASR to listen to the remote IVR
279
- * const asr = await call.createAsr();
280
- * asr.result$.subscribe((text) => {
281
- * if (/press 1/i.test(text)) call.sip.sendDtmf('1');
282
- * });
283
- *
284
- * // Optionally wait for the actual answer
285
- * await call.sip.waitForAnswer();
286
- * await call.audio.say('Hello! We are calling about your order.');
287
- * ```
288
- *
289
- * #### Inbound — collect data before the final answer
290
- *
291
- * ```ts
292
- * // Inbound call arrives — state is 'ringing'
293
- * channel.sip.sendProgress();
294
- * // State is now 'early' — full duplex audio before final 200 OK
295
- *
296
- * const asr = await channel.createAsr();
297
- * await channel.audio.say('Please say your account number.');
298
- * const account = await firstValueFrom(asr.result$);
299
- *
300
- * // Now send final answer
301
- * channel.sip.answer();
302
- * await channel.audio.say(`Thank you! Looking up account ${account}…`);
303
- * ```
304
- *
305
- * #### Inbound — simple answer (no pre-answer)
306
- *
307
- * ```ts
308
- * // Inbound call — answer immediately
309
- * channel.sip.answer();
310
- * await channel.audio.say('Welcome!');
311
- * ```
312
- *
313
- * #### Audio auto-buffering
314
- *
315
- * You do **not** need to manually wait for early/answer before calling `audio.say()`
316
- * or `audio.play()`. These methods automatically defer until the RTP pipeline is ready
317
- * and resolve as no-ops if the call terminates first. The explicit `waitForEarly()` /
318
- * `waitForAnswer()` await points are useful when you need to **sequence logic** around
319
- * call state (e.g. create ASR only after media is available).
320
- */
321
- export interface ChannelSip {
322
- /**
323
- * Emits every time the remote party sends a DTMF digit (RFC 2833 in-band or SIP INFO).
324
- *
325
- * ```ts
326
- * sip.dtmf$.subscribe(({ digit, duration }) => {
327
- * console.log(`User pressed ${digit}`);
328
- * });
329
- * ```
330
- */
331
- readonly dtmf$: Observable<DtmfEvent>;
332
- /**
333
- * Raw SIP INFO messages received on this call leg.
334
- *
335
- * Useful for carrier-specific signalling (e.g. `application/dtmf-relay`). On the
336
- * current SIP runtime this stream is low-level and may not include parsed body
337
- * details for every Sofia event; prefer `dtmf$` for DTMF.
338
- */
339
- readonly sipInfo$: Observable<SipInfo>;
340
- /**
341
- * Low-level SIP state-change events from the underlying Sofia stack.
342
- *
343
- * Prefer the higher-level **`state$`**, **`progress$`**, **`early$`**, **`answered$`**
344
- * observables unless you need raw Sofia event details.
345
- */
346
- readonly sipSignal$: Observable<SipSignal>;
347
- /**
348
- * Live observable of the current call state.
349
- *
350
- * Emits the new {@link SipState} every time the call transitions. Starts with the
351
- * state the call was in when the script began (typically `"ringing"` for inbound,
352
- * `"idle"` or `"ringing"` for outbound).
353
- *
354
- * ```ts
355
- * sip.state$.subscribe((state) => {
356
- * console.log(`Call state → ${state}`);
357
- * });
358
- * ```
359
- *
360
- * > **Tip:** for one-shot checks use the synchronous `sip.state` getter instead.
361
- */
362
- readonly state$: Observable<SipState>;
363
- /**
364
- * Current call state at the moment of access (synchronous).
365
- *
366
- * Returns one of: `'idle'`, `'ringing'`, `'early'`, `'active'`, `'holding'`, `'terminated'`.
367
- *
368
- * ```ts
369
- * if (sip.state === 'active') {
370
- * await audio.say('Call is live');
371
- * }
372
- * ```
373
- */
374
- readonly state: SipState;
375
- /**
376
- * Whether the call has been answered — `true` after 200 OK is received (outbound)
377
- * or sent (inbound via `sip.answer()`).
378
- *
379
- * This is a synchronous getter. For an awaitable version use {@link waitForAnswer}.
380
- *
381
- * ```ts
382
- * if (!sip.isAnswered) {
383
- * console.log('Still waiting for answer…');
384
- * }
385
- * ```
386
- */
387
- readonly isAnswered: boolean;
388
- /**
389
- * Emits every SIP 1xx provisional response (180 Ringing, 183 Session Progress, etc.).
390
- *
391
- * Useful for tracking ringing state, ringback-tone detection, or reading SDP from
392
- * early 183 responses. Each event is a {@link SipProgressEvent} with `statusCode`,
393
- * `statusPhrase`, and optionally `sdp`.
394
- *
395
- * ```ts
396
- * sip.progress$.subscribe(({ statusCode, statusPhrase }) => {
397
- * console.log(`1xx: ${statusCode} ${statusPhrase}`);
398
- * });
399
- * ```
400
- *
401
- * > **Note:** `progress$` may emit **zero** events if the remote party answers
402
- * > immediately (200 OK without any provisional).
403
- */
404
- readonly progress$: Observable<SipProgressEvent>;
405
- /**
406
- * Emits **once** when early media becomes available — the RTP pipeline is up and
407
- * audio can be sent/received **before** the call is formally answered.
408
- *
409
- * **Outbound:** fires automatically when the remote side sends a 1xx with SDP
410
- * (typically **183 Session Progress**).
411
- *
412
- * **Inbound:** fires after your script calls `sip.sendProgress()`.
413
- *
414
- * After this event fires:
415
- * - `audio.say()` / `audio.play()` will be heard by the remote party
416
- * - `createAsr()` will receive remote audio
417
- * - `dtmf$` will deliver in-band DTMF
418
- * - The API has not marked the call answered yet; carrier billing policy may vary
419
- *
420
- * If the call is answered without any early media (outbound: no 183 with SDP;
421
- * inbound: `answer()` called directly), `early$` **may not emit at all** —
422
- * use `answered$` or `waitForAnswer()` instead.
423
- *
424
- * ```ts
425
- * sip.early$.subscribe(() => {
426
- * console.log('Early media — RTP is flowing before answer');
427
- * });
428
- * ```
429
- */
430
- readonly early$: Observable<void>;
431
- /**
432
- * Emits **once** when the call is answered (200 OK received for outbound,
433
- * or sent for inbound after `sip.answer()`).
434
- *
435
- * After this event the call state is `"active"` and the call is fully established.
436
- *
437
- * ```ts
438
- * sip.answered$.subscribe(() => {
439
- * console.log('Call answered — full duplex');
440
- * });
441
- * ```
442
- *
443
- * > For the awaitable version see {@link waitForAnswer}.
444
- */
445
- readonly answered$: Observable<void>;
446
- /**
447
- * Returns a `Promise` that resolves when the call is answered (200 OK).
448
- *
449
- * If the call is **already answered** at the time of calling, resolves immediately.
450
- *
451
- * Useful in outbound scenarios where you want to block until the remote party picks up:
452
- *
453
- * ```ts
454
- * const call = await channel.sip.makeCall({ sipUri: destination });
455
- * await call.sip.waitForAnswer();
456
- * await call.audio.say('You have picked up!');
457
- * ```
458
- *
459
- * > **Warning:** if the call is never answered (busy, timeout, rejection) and your
460
- * > script does not handle `events.terminated$`, this Promise will remain pending
461
- * > until the call terminates (at which point the script exits).
462
- */
463
- waitForAnswer(): Promise<void>;
464
- /**
465
- * Returns a `Promise` that resolves as soon as the RTP pipeline is ready —
466
- * either on **early media** or on **answer**, whichever comes first.
467
- *
468
- * If the call is already in `"early"` or `"active"` state, resolves immediately.
469
- *
470
- * #### Outbound usage
471
- *
472
- * The recommended await point when you want to start ASR / play audio
473
- * **as early as possible** (including pre-answer):
474
- *
475
- * ```ts
476
- * const call = await channel.sip.makeCall({ sipUri: destination });
477
- *
478
- * // Don't wait for full answer — start as soon as any media path exists
479
- * await call.sip.waitForEarly();
480
- *
481
- * // ASR is already receiving remote audio (IVR prompts, ringback, etc.)
482
- * const asr = await call.createAsr();
483
- * asr.result$.subscribe((text) => console.log('Heard:', text));
484
- *
485
- * // Play DTMF to navigate an IVR — works even before 200 OK
486
- * call.sip.sendDtmf('1');
487
- * ```
488
- *
489
- * #### Inbound usage
490
- *
491
- * For inbound calls you must call `sendProgress()` **first** to trigger early media,
492
- * then `waitForEarly()` resolves:
493
- *
494
- * ```ts
495
- * channel.sip.sendProgress();
496
- * await channel.sip.waitForEarly(); // resolves immediately after sendProgress()
497
- * const asr = await channel.createAsr();
498
- * ```
499
- *
500
- * > **Tip:** some carriers answer outbound calls without early media (180 without SDP).
501
- * > In that case `waitForEarly()` resolves only when the 200 OK arrives.
502
- */
503
- waitForEarly(): Promise<void>;
504
- /**
505
- * Send a DTMF digit to the remote party.
506
- *
507
- * SIP channels delegate to the telephony stack. WS channels validate one digit
508
- * and emit `dtmf-send` to the connected client. Headless channels ignore it.
509
- *
510
- * @param digit - One of `0`–`9`, `*`, `#`.
511
- * @param duration - Tone duration in milliseconds (default **250 ms**).
512
- *
513
- * ```ts
514
- * // Navigate an IVR: press 1, wait, press 3
515
- * sip.sendDtmf('1');
516
- * await new Promise((r) => setTimeout(r, 2000));
517
- * sip.sendDtmf('3');
518
- * ```
519
- */
520
- sendDtmf(digit: string, duration?: number): void;
521
- /**
522
- * Send a SIP INFO request with an arbitrary content type and body on this call leg.
523
- *
524
- * No-op on WS and headless channels.
525
- *
526
- * @param contentType - MIME type, e.g. `"application/dtmf-relay"`.
527
- * @param body - Raw text body of the INFO request.
528
- */
529
- sendInfo(contentType: string, body: string): void;
530
- /**
531
- * Put the SIP call on hold (sends re-INVITE with `a=sendonly`).
532
- *
533
- * The remote party hears silence (or hold music if your carrier supports it).
534
- * Call {@link unhold} to resume.
535
- */
536
- hold(): void;
537
- /**
538
- * Resume a held SIP call (sends re-INVITE with `a=sendrecv`).
539
- */
540
- unhold(): void;
541
- /**
542
- * Suppress outgoing SIP audio locally — the remote party hears silence,
543
- * but you still receive their audio.
544
- *
545
- * This does **not** send a re-INVITE; it simply stops feeding PCM
546
- * to the RTP encoder. Call {@link unmute} to resume.
547
- */
548
- mute(): void;
549
- /** Resume sending audio after {@link mute}. No-op on WS/headless channels. */
550
- unmute(): void;
551
- /**
552
- * Hang up the call.
553
- *
554
- * SIP channels send BYE. WS channels disconnect the socket. Headless channels destroy
555
- * the synthetic channel. After this call `events.terminated$` will emit and the session ends.
556
- */
557
- hangup(): void;
558
120
  /**
559
- * Answer an **inbound** call (sends 200 OK with SDP).
560
- *
561
- * No-op if the call is already answered or if this is an outbound call. Also no-op
562
- * on WS/headless channels. After answering, the state transitions to `"active"` and
563
- * the API records the call answer time.
564
- *
565
- * If the call is in `"early"` state (after `sendProgress()`), `answer()` promotes it
566
- * to `"active"` — audio was already flowing and the final answer is now sent.
121
+ * Unified stream of runtime media errors (ASR connector failures, TTS HTTP errors,
122
+ * missing API keys, etc.).
567
123
  *
568
- * ```ts
569
- * // Simple: answer immediately
570
- * channel.sip.answer();
571
- * await channel.audio.say('Hello, how can I help?');
572
- * ```
124
+ * Subscribing is optional — unhandled errors are always logged server-side. Use this
125
+ * when the script needs to react (e.g. fall back to a different vendor, notify the
126
+ * caller, or abort the dialog).
573
127
  *
574
128
  * ```ts
575
- * // Advanced: pre-answer → answer
576
- * channel.sip.sendProgress(); // early media before final 200 OK
577
- * await channel.audio.say('One moment…');
578
- * channel.sip.answer(); // final 200 OK
579
- * await channel.audio.say('How can I help?');
580
- * ```
581
- */
582
- answer(): void;
583
- /**
584
- * Send **183 Session Progress** with SDP on an **inbound** call, enabling
585
- * early media (full-duplex audio) **before** the 200 OK answer.
586
- *
587
- * After calling `sendProgress()`:
588
- * - The call state transitions to `"early"` and `early$` emits.
589
- * - `audio.say()`, `audio.play()`, `createAsr()`, `dtmf$` all work —
590
- * exactly the same as in the `"active"` state.
591
- * - The remote party hears your audio before the final 200 OK. The API still treats
592
- * the call as not answered; external billing depends on carrier policy.
593
- *
594
- * Call `sip.answer()` later to send the final 200 OK and transition to `"active"`.
595
- *
596
- * No-op if the call is already in `"early"` or `"active"` state, or if this is
597
- * an outbound / WS / headless channel.
598
- *
599
- * ### Typical use case: play a greeting before answering
600
- *
601
- * ```ts
602
- * // Inbound call arrives — state is 'ringing'
603
- * channel.sip.sendProgress();
604
- * // State is now 'early' — audio flows before final 200 OK
605
- *
606
- * await channel.audio.say('Please hold while we connect you…');
607
- *
608
- * // Now answer with final 200 OK
609
- * channel.sip.answer();
610
- * await channel.audio.say('Hello! How can I help?');
611
- * ```
612
- *
613
- * ### Typical use case: start ASR before answering
614
- *
615
- * ```ts
616
- * channel.sip.sendProgress();
617
- * const asr = await channel.createAsr();
618
- * await channel.audio.say('Hi! What is your account number?');
619
- * const result = await firstValueFrom(asr.result$);
620
- * // Collected account number before sending final 200 OK
621
- * channel.sip.answer();
622
- * ```
623
- */
624
- sendProgress(): void;
625
- /**
626
- * Initiate an **outbound** SIP call to the given SIP URI.
627
- *
628
- * Returns a new {@link MediaChannel} representing the B-leg. The returned channel
629
- * has its own `sip`, `audio`, `events`, etc. — use `waitForAnswer()` or
630
- * `waitForEarly()` on the B-leg before sending audio.
631
- *
632
- * Supported only by the main-thread SIP channel. Worker-isolated, WS, and headless
633
- * channels throw because the current worker bridge does not proxy nested call legs.
634
- *
635
- * @param opts.sipUri - Full SIP URI, e.g. `"sip:+12025551234@trunk.carrier.com"`.
636
- * @param opts.fromUri - Optional caller-ID override SIP URI.
637
- * @returns A new `MediaChannel` for the outbound leg.
638
- *
639
- * ```ts
640
- * const bLeg = await channel.sip.makeCall({
641
- * sipUri: 'sip:+12025551234@trunk.carrier.com',
129
+ * channel.events.error$.subscribe(err => {
130
+ * console.log(`[${err.source}] ${err.message}`);
642
131
  * });
643
- * await bLeg.sip.waitForAnswer();
644
- * // Bridge both legs so callers hear each other
645
- * const teardown = channel.sip.bridge(bLeg);
646
- * ```
647
- */
648
- makeCall(opts: {
649
- sipUri: string;
650
- fromUri?: string;
651
- }): Promise<MediaChannel>;
652
- /**
653
- * Cross-connect audio between this SIP call and another SIP call (conference bridge).
654
- *
655
- * Both parties hear each other in real time. Returns a teardown function
656
- * that disconnects the bridge when called. ScriptEngine only bridges two
657
- * `SipMediaChannel` instances directly; non-SIP channels return a no-op teardown
658
- * or throw depending on the host.
659
- *
660
- * @param other - The other `MediaChannel` (e.g. an outbound B-leg).
661
- * @returns A function to tear down the bridge.
662
- *
663
- * ```ts
664
- * const teardown = channel.sip.bridge(bLeg);
665
- * // ... later
666
- * teardown(); // disconnect the bridge
667
132
  * ```
668
133
  */
669
- bridge(other: MediaChannel): () => void;
134
+ readonly error$: Observable<MediaError>;
670
135
  }
671
136
  /**
672
137
  * Primary script API for real-time voice: ASR, TTS/audio, SIP, LLM, and **`params`** from the host.
673
138
  *
674
139
  * **`type`** is **`"sip"`** for telephony or **`"ws"`** for WebSocket/script-manager sessions.
675
140
  * Headless sessions currently also expose a `"ws"` typed synthetic channel; use
676
- * {@link import('./define-script').ScriptDialogContext.headless} to distinguish them.
141
+ * {@link import('./script-context').ScriptDialogContext.headless} to distinguish them.
677
142
  * In headless mode audio/SIP/text input are mostly no-ops while **`llm`** / **`platform`**
678
143
  * still work.
679
144
  */
@@ -689,7 +154,7 @@ export interface MediaChannel {
689
154
  * - **`defaultAsrName`**, **`defaultTtsName`**: default **`key_storage.name`** when the script
690
155
  * omits **`name`** on {@link AsrConfig} / {@link PlayOptions}
691
156
  * - **`authentication_data`**: may include **`legacyAsrKeysByName`**, **`legacyTtsKeysByName`**
692
- * (built from LE DB for this dialogs agent + company)
157
+ * (built from LE DB for this dialog's agent + company)
693
158
  *
694
159
  * Treat as read-only unless your integration explicitly documents mutable keys.
695
160
  */
@@ -1 +1 @@
1
- {"version":3,"file":"media-channel.d.ts","sourceRoot":"","sources":["../../src/types/media-channel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"media-channel.d.ts","sourceRoot":"","sources":["../../src/types/media-channel.ts"],"names":[],"mappings":"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"}