@voctiv/agent-sdk 0.2.16 → 0.3.1
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 +273 -4
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/types/asr-handle.d.ts +6 -2
- package/dist/types/asr-handle.d.ts.map +1 -1
- package/dist/types/media-channel.d.ts +24 -3
- package/dist/types/media-channel.d.ts.map +1 -1
- package/dist/types/media-providers.d.ts +83 -0
- package/dist/types/media-providers.d.ts.map +1 -0
- package/dist/types/media-providers.js +19 -0
- package/dist/types/media-providers.js.map +1 -0
- package/dist/types/mixer.d.ts +14 -0
- package/dist/types/mixer.d.ts.map +1 -1
- package/dist/types/script-context.d.ts +15 -0
- package/dist/types/script-context.d.ts.map +1 -1
- package/dist/types/script-context.js.map +1 -1
- package/dist/types/tts-handle.d.ts +194 -0
- package/dist/types/tts-handle.d.ts.map +1 -0
- package/dist/types/tts-handle.js +3 -0
- package/dist/types/tts-handle.js.map +1 -0
- package/examples/README.md +1 -0
- package/examples/custom-media-providers.ts +128 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -81,6 +81,7 @@ The [`examples/`](./examples/) folder contains copy-paste-ready scripts:
|
|
|
81
81
|
| [schedule-call-with-defaults.ts](./examples/schedule-call-with-defaults.ts) | `platform.call()` without explicit recall — CMS defaults from `context` |
|
|
82
82
|
| [after-call-continuation.ts](./examples/after-call-continuation.ts) | `onSuccessCall` / `onFailedCall` vs recall (mutually exclusive) |
|
|
83
83
|
| [read-recall-from-params.ts](./examples/read-recall-from-params.ts) | `parseRecallDelaySeconds()` / `parseRecallCount()` on legacy params |
|
|
84
|
+
| [custom-media-providers.ts](./examples/custom-media-providers.ts) | `defineMediaProviders` + custom ASR/TTS via `createAsr` / `createTts` |
|
|
84
85
|
|
|
85
86
|
### Quick recall example
|
|
86
87
|
|
|
@@ -116,6 +117,8 @@ const maxAttempts = parseRecallCount(context.dialogParams?.recall_count);
|
|
|
116
117
|
|
|
117
118
|
`defineScript(fn)` marks the default export as the script entry point. It returns the same function and exists to give TypeScript the correct `ScriptContext` shape.
|
|
118
119
|
|
|
120
|
+
`defineMediaProviders(def)` marks a named `mediaProviders` export for custom ASR/TTS factories (trusted packages only). See [Custom ASR / TTS Providers](#custom-asr--tts-providers).
|
|
121
|
+
|
|
119
122
|
**Three different “context” names:**
|
|
120
123
|
|
|
121
124
|
| Name | Meaning |
|
|
@@ -136,7 +139,8 @@ const maxAttempts = parseRecallCount(context.dialogParams?.recall_count);
|
|
|
136
139
|
- `channel.type` is `"sip"` for telephony and `"ws"` for WebSocket/script-manager sessions. Headless sessions currently expose a synthetic `"ws"` channel; check `context.headless` to detect them.
|
|
137
140
|
- `channel.params` is the merged runtime parameter map. Treat unknown keys as host-specific.
|
|
138
141
|
- `channel.createAsr()` creates an ASR handle.
|
|
139
|
-
- `channel.
|
|
142
|
+
- `channel.createTts()` returns a TTS handle (`tts.say` / `tts.say$` / `tts.presay`) with a reused SSL / WebSocket connection.
|
|
143
|
+
- `channel.audio` controls channel-level TTS, raw playback, pre-synthesis, and mixer queues.
|
|
140
144
|
- `channel.sip` controls SIP state, pre-answer media, DTMF, hold/mute/hangup, outbound calls, and bridging.
|
|
141
145
|
- `channel.llm` talks to the Omni LLM backend.
|
|
142
146
|
- `channel.events` exposes speech, interrupt, termination, WS data message, and media error observables.
|
|
@@ -460,7 +464,9 @@ While a bridge is active, `channel.audio.say()` still sends audio only to the A-
|
|
|
460
464
|
|
|
461
465
|
## ASR, VAD, And Smart Turn
|
|
462
466
|
|
|
463
|
-
Create ASR with `channel.createAsr(config?)`.
|
|
467
|
+
Create ASR with `channel.createAsr(config?)`. Prefer creating it once at dialog start so the
|
|
468
|
+
host can warm the ASR TCP/WebSocket (one SSL handshake). A later `createAsr` with the same
|
|
469
|
+
resolved vendor/credentials reuses that channel; `destroy()` closes it.
|
|
464
470
|
|
|
465
471
|
```ts
|
|
466
472
|
const asr = await channel.createAsr({
|
|
@@ -490,7 +496,7 @@ const asr = await channel.createAsr({
|
|
|
490
496
|
- `error$`: runtime errors from the ASR provider (see [Error Handling](#error-handling)).
|
|
491
497
|
- `pause()` / `resume()` to stop or resume forwarding new audio frames.
|
|
492
498
|
- `finalize()` to force the current utterance to flush.
|
|
493
|
-
- `destroy()` to close connector
|
|
499
|
+
- `destroy()` to close the warm TCP/WS connector and subscriptions.
|
|
494
500
|
|
|
495
501
|
SIP sessions use the call-level telephony VAD when it is available. WS sessions create one VAD/SmartTurn instance for the socket session on the first `createAsr()` call. Headless sessions return an inert ASR handle with empty observables.
|
|
496
502
|
|
|
@@ -548,8 +554,73 @@ When both `name` (platform key) and explicit `data` are provided, `data` values
|
|
|
548
554
|
All audio playback goes through **`channel.audio`** (`ChannelAudio`). There are no top-level
|
|
549
555
|
`channel.say()` / `channel.play()` shortcuts on `MediaChannel`.
|
|
550
556
|
|
|
557
|
+
Create a reusable TTS session with `channel.createTts(config?)` — same pattern as `createAsr`.
|
|
558
|
+
Call `tts.say` / `tts.say$` / `tts.presay` on the handle so synthesis reuses the warmed SSL / streaming WebSocket.
|
|
559
|
+
|
|
560
|
+
Custom engines from a logic package are documented in
|
|
561
|
+
[Custom ASR / TTS Providers](#custom-asr--tts-providers).
|
|
562
|
+
|
|
563
|
+
```ts
|
|
564
|
+
const tts = await channel.createTts({
|
|
565
|
+
vendor: 'elevenlabs',
|
|
566
|
+
name: 'elevenlabs-main',
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
await tts.say('Hello', {
|
|
570
|
+
ttsStrategy: 'streaming',
|
|
571
|
+
alias: 'greeting',
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
// Track queue / speaking / done per sentence for one say$ call:
|
|
575
|
+
tts.say$('One. Two.', { alias: 'reply', queue: 0 }).subscribe({
|
|
576
|
+
next: (e) => {
|
|
577
|
+
if (e.state === 'queued') {
|
|
578
|
+
// e.text — full utterance (string) or '' until stream tokens arrive
|
|
579
|
+
}
|
|
580
|
+
if (e.state === 'speaking') {
|
|
581
|
+
// e.sentenceText / e.sentenceIndex — sentence starting playback
|
|
582
|
+
// e.itemAlias — e.g. reply-0
|
|
583
|
+
}
|
|
584
|
+
if (e.state === 'done') {
|
|
585
|
+
// that sentence finished; e.sentenceText / e.sentenceIndex / e.itemAlias
|
|
586
|
+
}
|
|
587
|
+
if (e.state === 'cancelled') {
|
|
588
|
+
// audio.stop / destroy; e.text so far
|
|
589
|
+
}
|
|
590
|
+
},
|
|
591
|
+
complete: () => {
|
|
592
|
+
// whole say$ finished (all sentences)
|
|
593
|
+
},
|
|
594
|
+
error: (err) => {
|
|
595
|
+
// MediaError — synthesis/playback failed
|
|
596
|
+
},
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
// Later turns reuse the same WebSocket:
|
|
600
|
+
await tts.say(tokenStream, {
|
|
601
|
+
ttsStrategy: 'streaming',
|
|
602
|
+
alias: 'reply-2',
|
|
603
|
+
});
|
|
604
|
+
|
|
605
|
+
tts.destroy();
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
`tts.say()` stays a `Promise` (await until finished). `tts.say$()` returns an `Observable`
|
|
609
|
+
of utterance lifecycle events for that call only (`queued` → (`speaking` → `done`)×N /
|
|
610
|
+
`cancelled`, then complete). `done` is per sentence/phrase finishing playback; use the
|
|
611
|
+
Observable `complete` callback for the end of the whole `say$` call. Synthesis failures
|
|
612
|
+
terminate the Observable via **error** (`MediaError`), and are also mirrored on
|
|
613
|
+
`tts.error$` / `channel.events.error$`. `channel.audio.say` remains Promise-only.
|
|
614
|
+
|
|
615
|
+
You can still use `channel.audio.say(..., { tts })` if you prefer the channel API; a matching
|
|
616
|
+
pre-warmed session is also reused when vendor+config align.
|
|
617
|
+
|
|
551
618
|
| Method | Purpose |
|
|
552
619
|
| --- | --- |
|
|
620
|
+
| `channel.createTts(config?)` | Pre-warm a TTS connector / streaming socket; returns `TtsHandle` |
|
|
621
|
+
| `tts.say(textOrObservable, options?)` | Synthesize via the handle's cached connection (`Promise`) |
|
|
622
|
+
| `tts.say$(textOrObservable, options?)` | Same path with per-utterance status events (`Observable`) |
|
|
623
|
+
| `tts.presay(text, options?)` | Pre-synthesize into the host TTS cache via the handle |
|
|
553
624
|
| `channel.audio.say(textOrObservable, options?)` | Synthesize text with TTS and play on a mixer queue |
|
|
554
625
|
| `channel.audio.play(source, options?)` | Play raw audio (URL, path, or platform phrase record) |
|
|
555
626
|
| `channel.audio.presay(text, options?)` | Pre-synthesize TTS into the host cache (no playback) |
|
|
@@ -709,6 +780,202 @@ Shared by `say()`, `play()`, and (where noted) `presay()`:
|
|
|
709
780
|
|
|
710
781
|
`play()` ignores `tts*` and `cache` for raw audio. `preload()` only accepts `cache` overrides.
|
|
711
782
|
|
|
783
|
+
## Custom ASR / TTS Providers
|
|
784
|
+
|
|
785
|
+
Trusted logic packages can ship their own ASR/TTS engines next to `defineScript`. The host
|
|
786
|
+
`require`s a static **`export const mediaProviders`** **outside** the script sandbox (same
|
|
787
|
+
process privileges as the API). Use this only for packages you trust.
|
|
788
|
+
|
|
789
|
+
Mid-script `registerAsr` / `registerTts` is **not** supported — declare vendors at module load.
|
|
790
|
+
|
|
791
|
+
### Export shape
|
|
792
|
+
|
|
793
|
+
```ts
|
|
794
|
+
import {
|
|
795
|
+
defineScript,
|
|
796
|
+
defineMediaProviders,
|
|
797
|
+
type MediaConnectorContext,
|
|
798
|
+
type MediaProviderShared,
|
|
799
|
+
type ScriptAsrConnector,
|
|
800
|
+
type ScriptTtsConnector,
|
|
801
|
+
} from '@voctiv/agent-sdk';
|
|
802
|
+
import { Subject } from 'rxjs';
|
|
803
|
+
import { Readable } from 'stream';
|
|
804
|
+
|
|
805
|
+
export const mediaProviders = defineMediaProviders({
|
|
806
|
+
// Optional: one object per dialog, shared by ASR + TTS factories
|
|
807
|
+
createShared: (ctx) => ({
|
|
808
|
+
dialogUuid: ctx.dialogUuid,
|
|
809
|
+
dispose() { /* release app state */ },
|
|
810
|
+
}),
|
|
811
|
+
asr: {
|
|
812
|
+
'my-asr': (ctx, shared) => new MyAsr(ctx, shared),
|
|
813
|
+
},
|
|
814
|
+
tts: {
|
|
815
|
+
'my-tts': (ctx, shared) => new MyTts(ctx, shared),
|
|
816
|
+
},
|
|
817
|
+
});
|
|
818
|
+
|
|
819
|
+
export default defineScript(async ({ channel }) => {
|
|
820
|
+
const asr = await channel.createAsr({
|
|
821
|
+
vendor: 'my-asr',
|
|
822
|
+
language: 'ru-RU',
|
|
823
|
+
data: { api_key: process.env.MY_ASR_KEY! },
|
|
824
|
+
});
|
|
825
|
+
const tts = await channel.createTts({
|
|
826
|
+
vendor: 'my-tts',
|
|
827
|
+
data: {
|
|
828
|
+
api_key: process.env.MY_TTS_KEY!,
|
|
829
|
+
voice_id: '…',
|
|
830
|
+
output_format: 'pcm_16000', // preferred for telephony
|
|
831
|
+
},
|
|
832
|
+
});
|
|
833
|
+
|
|
834
|
+
await tts.say('Hello from a custom connector.', {
|
|
835
|
+
alias: 'greet',
|
|
836
|
+
ttsStrategy: 'streaming', // used when supportsStreaming() === true
|
|
837
|
+
});
|
|
838
|
+
|
|
839
|
+
tts.say$('One. Two.', { alias: 'reply' }).subscribe((ev) => {
|
|
840
|
+
// queued | speaking | done | cancelled — same events as builtin TTS
|
|
841
|
+
});
|
|
842
|
+
|
|
843
|
+
// Reuse the warm handle:
|
|
844
|
+
await channel.audio.say('Again', { tts });
|
|
845
|
+
|
|
846
|
+
asr.destroy();
|
|
847
|
+
tts.destroy();
|
|
848
|
+
});
|
|
849
|
+
```
|
|
850
|
+
|
|
851
|
+
`defineMediaProviders` is an identity helper for typing. The host looks up
|
|
852
|
+
`module.exports.mediaProviders` (or `default.mediaProviders`) on the script entry file.
|
|
853
|
+
|
|
854
|
+
Full stub: [`examples/custom-media-providers.ts`](./examples/custom-media-providers.ts).
|
|
855
|
+
|
|
856
|
+
### Implement ASR (`ScriptAsrConnector`)
|
|
857
|
+
|
|
858
|
+
The host pushes **PCM S16LE mono 16 kHz** frames into `send()`. Emit partials on
|
|
859
|
+
`transcription$` and finals on both `transcription$` (`isFinal: true`) and `result$`.
|
|
860
|
+
|
|
861
|
+
| Member | Role |
|
|
862
|
+
| --- | --- |
|
|
863
|
+
| `transcription$` | `{ text, isFinal }` partials and finals |
|
|
864
|
+
| `result$` | Final utterance strings (drives `AsrHandle.result$`) |
|
|
865
|
+
| `error$` | Vendor / transport failures |
|
|
866
|
+
| `send(audio)` | Accept inbound PCM (`ArrayBuffer` / `Buffer`) |
|
|
867
|
+
| `speech(active)` | Optional VAD gate from the host (`true` = utterance open) |
|
|
868
|
+
| `finalize()` | End-of-utterance nudge (flush / commit) |
|
|
869
|
+
| `isOpen()` | Whether the vendor socket is ready |
|
|
870
|
+
| `close()` | Tear down; complete Subjects |
|
|
871
|
+
|
|
872
|
+
```ts
|
|
873
|
+
class MyAsr implements ScriptAsrConnector {
|
|
874
|
+
readonly transcription$ = new Subject<{ text: string; isFinal: boolean }>();
|
|
875
|
+
readonly result$ = new Subject<string>();
|
|
876
|
+
readonly error$ = new Subject<{ message: string; code?: number }>();
|
|
877
|
+
|
|
878
|
+
constructor(
|
|
879
|
+
private readonly ctx: MediaConnectorContext,
|
|
880
|
+
private readonly shared: MediaProviderShared | undefined,
|
|
881
|
+
) {
|
|
882
|
+
// ctx.config — flattened createAsr data + channel asrConfig
|
|
883
|
+
// ctx.dialogUuid, ctx.role, ctx.debug$
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
isOpen() { return true; }
|
|
887
|
+
send(audio: ArrayBufferLike) { /* forward PCM to vendor */ }
|
|
888
|
+
speech(_active: boolean) {}
|
|
889
|
+
finalize() {
|
|
890
|
+
const text = '…';
|
|
891
|
+
this.transcription$.next({ text, isFinal: true });
|
|
892
|
+
this.result$.next(text);
|
|
893
|
+
}
|
|
894
|
+
close() {
|
|
895
|
+
this.transcription$.complete();
|
|
896
|
+
this.result$.complete();
|
|
897
|
+
this.error$.complete();
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
```
|
|
901
|
+
|
|
902
|
+
Factory `throw` during create → host degraded ASR handle (same as builtin). Prefer connecting
|
|
903
|
+
lazily in `send()`; the host does not call a separate `connect()` on custom connectors.
|
|
904
|
+
|
|
905
|
+
### Implement TTS (`ScriptTtsConnector`)
|
|
906
|
+
|
|
907
|
+
**One class per vendor** covers batch HTTP and optional streaming WebSocket. Do **not**
|
|
908
|
+
register a separate streaming map.
|
|
909
|
+
|
|
910
|
+
| Member | Role |
|
|
911
|
+
| --- | --- |
|
|
912
|
+
| `supportsStreaming()` | `true` → host may use WS path for `ttsStrategy: 'streaming'` |
|
|
913
|
+
| `textToSpeechStream(text, ctx?)` | Batch/HTTP synthesis → `Readable` of audio bytes |
|
|
914
|
+
| `audio$` / `done$` | Streaming audio chunks and end-of-generation |
|
|
915
|
+
| `open` / `startGeneration` / `sendText` / `flush` | Streaming lifecycle |
|
|
916
|
+
| `sendSeparatorFlush?()` | Optional sentence separator flush |
|
|
917
|
+
| `close()` | Soft-close sockets for **reuse** (do not complete Subjects if `open()` may run again) |
|
|
918
|
+
|
|
919
|
+
```ts
|
|
920
|
+
class MyTts implements ScriptTtsConnector {
|
|
921
|
+
readonly audio$ = new Subject<Buffer>();
|
|
922
|
+
readonly done$ = new Subject<void>();
|
|
923
|
+
|
|
924
|
+
supportsStreaming() {
|
|
925
|
+
return true; // or false for HTTP-only
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
async textToSpeechStream(rawtext: string, _ctx?: { previousText?: string; nextText?: string }) {
|
|
929
|
+
// Return PCM (preferred) or MP3/OGG. Hint format via createTts data:
|
|
930
|
+
// output_format: 'pcm_16000' | 'mp3_…' or audioFormat: 'pcm' | 'mp3'
|
|
931
|
+
return Readable.from([/* bytes */]);
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
async open() { /* open long-lived WS */ }
|
|
935
|
+
async startGeneration() { /* BOS / new utterance */ }
|
|
936
|
+
sendText(chunk: string) { /* stream tokens */ }
|
|
937
|
+
flush() { /* EOS; later emit done$ */ }
|
|
938
|
+
close() { /* close WS; keep Subjects alive for fingerprint reuse */ }
|
|
939
|
+
}
|
|
940
|
+
```
|
|
941
|
+
|
|
942
|
+
- `supportsStreaming() === false` → streaming strategy falls back to sentence/full HTTP path.
|
|
943
|
+
- Default audio assumption for custom vendors is **PCM** unless `output_format` / `audioFormat`
|
|
944
|
+
indicates a compressed format (`mp3`, `ogg`, …).
|
|
945
|
+
|
|
946
|
+
### Using custom vendors in the script
|
|
947
|
+
|
|
948
|
+
```ts
|
|
949
|
+
const asr = await channel.createAsr({ vendor: 'my-asr', data: { … } });
|
|
950
|
+
const tts = await channel.createTts({ vendor: 'my-tts', data: { … } });
|
|
951
|
+
|
|
952
|
+
await tts.say('Hi', { alias: 'greet' });
|
|
953
|
+
await tts.presay('Warm cache');
|
|
954
|
+
tts.say$('Next', { alias: 'reply', ttsStrategy: 'streaming' }).subscribe(…);
|
|
955
|
+
|
|
956
|
+
await channel.audio.say('Reuse', { tts }); // same warm session
|
|
957
|
+
```
|
|
958
|
+
|
|
959
|
+
Vendor keys must be **multi-character** names. Builtin single-letter codes
|
|
960
|
+
(`A`, `D`, `E`, `ES`, `G`, `V`, `W`, `W2`, …) **cannot** be overridden.
|
|
961
|
+
|
|
962
|
+
### Warm reuse vs `createShared` vs PCM cache
|
|
963
|
+
|
|
964
|
+
| Layer | What it caches | Scope |
|
|
965
|
+
| --- | --- | --- |
|
|
966
|
+
| Factory + session registries | One connector instance per `dialog + vendor + config fingerprint` (TCP/WS) | Host automatic |
|
|
967
|
+
| `createShared` | Your app/vendor state shared by ASR↔TTS factories | One object per dialog |
|
|
968
|
+
| `PlayOptions.cache` / `presay` | Synthesized PCM files | Host TTS file cache |
|
|
969
|
+
|
|
970
|
+
Call `createAsr` / `createTts` early to warm sockets. Repeated `say` with the same handle (or
|
|
971
|
+
matching fingerprint) must **not** open a new TCP/WS per utterance.
|
|
972
|
+
|
|
973
|
+
### Security
|
|
974
|
+
|
|
975
|
+
- Host `require` of `mediaProviders` runs with API privileges — **trusted packages only**.
|
|
976
|
+
- Entry path is restricted to the script root (path traversal denied).
|
|
977
|
+
- Optional host allowlists may further restrict which packages may export providers.
|
|
978
|
+
|
|
712
979
|
## TTS Credentials And Vendor Parameters
|
|
713
980
|
|
|
714
981
|
### Direct TTS Vendor Parameters
|
|
@@ -850,7 +1117,7 @@ channel.events.error$.subscribe((err) => {
|
|
|
850
1117
|
| --- | --- | --- |
|
|
851
1118
|
| `source` | `'asr' \| 'tts' \| 'sip' \| 'channel' \| 'llm'` | Which subsystem produced the error. |
|
|
852
1119
|
| `phase` | `'create' \| 'start' \| 'stream' \| 'playback' \| 'finalize' \| 'destroy'?` | Lifecycle phase where the error happened. |
|
|
853
|
-
| `operation` | `string?` | Public SDK operation, e.g. `createAsr`, `audio.say`, or `audio.play`. |
|
|
1120
|
+
| `operation` | `string?` | Public SDK operation, e.g. `createAsr`, `createTts`, `audio.say`, or `audio.play`. |
|
|
854
1121
|
| `recoverable` | `boolean?` | Whether the runtime can keep the session alive after this error. |
|
|
855
1122
|
| `handleId` | `string?` | ASR handle id when the error belongs to a recognizer instance. |
|
|
856
1123
|
| `queue` | `number?` | Mixer queue index when the error belongs to an audio operation. |
|
|
@@ -1476,6 +1743,7 @@ Important fields:
|
|
|
1476
1743
|
- `context.dialogUuid`: current dialog UUID.
|
|
1477
1744
|
- `context.callerId` / `context.msisdn`: caller identity.
|
|
1478
1745
|
- `context.destinationNumber`: called number.
|
|
1746
|
+
- `context.trunkId` / `context.trunkName`: LE trunk for this dialog/call (snapshot; name from `trunk` table).
|
|
1479
1747
|
- `context.language` / `context.lang`: language selected for the run.
|
|
1480
1748
|
- `context.flag`: business flag.
|
|
1481
1749
|
- `context.initialData`: shallow snapshot of params at script start.
|
|
@@ -1528,6 +1796,7 @@ Headless channels are for offline, queue, or messaging sessions:
|
|
|
1528
1796
|
- SIP methods are no-ops, except `makeCall()` and `bridge()`, which throw: there is no real leg to
|
|
1529
1797
|
create, and a silent no-op would hide the mistake.
|
|
1530
1798
|
- `createAsr()` returns an inert handle whose observables complete immediately.
|
|
1799
|
+
- `createTts()` returns an inert handle (no vendor connection is opened).
|
|
1531
1800
|
- LLM, NLU, messaging, platform calls, dialog state, and `env$` still work.
|
|
1532
1801
|
|
|
1533
1802
|
Use `context.headless` plus `getScriptPhase(context)` when a script must behave differently without a
|
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* When the host loads platform credential catalogs, **`channel.params.authentication_data`**
|
|
14
14
|
* may contain named ASR/TTS key rows for the current dialog agent and company. Use:
|
|
15
15
|
* - {@link import('./types/asr-handle').AsrConfig.name} or **`data.name`** on **`createAsr`**
|
|
16
|
+
* - {@link import('./types/tts-handle').TtsConfig.name} or **`data.name`** on **`createTts`**
|
|
16
17
|
* - {@link import('./types/mixer').PlayOptions.name} or **`ttsConfig.name`** on **`say`/`play`/`presay`**
|
|
17
18
|
*
|
|
18
19
|
* Channel defaults **`defaultAsrName`** / **`defaultTtsName`** apply when **`name`** is omitted.
|
|
@@ -29,6 +30,8 @@
|
|
|
29
30
|
*/
|
|
30
31
|
export { defineScript } from './define-script';
|
|
31
32
|
export type { ScriptContext, ScriptFn } from './define-script';
|
|
33
|
+
export { defineMediaProviders } from './types/media-providers';
|
|
34
|
+
export type { MediaProvidersDefinition, MediaConnectorContext, MediaProviderShared, AsrProviderFactory, TtsProviderFactory, ScriptAsrConnector, ScriptAsrConnectorError, ScriptTtsConnector, TtsSynthesisContext as ScriptTtsSynthesisContext, } from './types/media-providers';
|
|
32
35
|
export type { ScriptDialogContext, ScriptPhase, ScriptRunTime, ScriptResult, PersistedScriptResult, ScriptError, AgentContext, AgentEnvSetOptions, StorageContextApi, } from './types/script-context';
|
|
33
36
|
export { getScriptPhase } from './types/script-context';
|
|
34
37
|
export type { NluScriptApi, PlatformApi, DialogApi, ScheduleCallOptions, SendMessageOptions, InboundMessage, MessagingApi, } from './types/platform';
|
|
@@ -39,6 +42,7 @@ export type { ChannelLlm, LlmOptions, LlmStreamChunk, ExtractOptions, Persistent
|
|
|
39
42
|
export type { ChannelSip, SipState, SipProgressEvent, SipInviteHeaders, ParsedSdpDetails, } from './types/sip';
|
|
40
43
|
export type { MediaError } from './types/errors';
|
|
41
44
|
export type { AsrHandle, AsrConfig, AsrVadConfig, AsrSmartTurnConfig } from './types/asr-handle';
|
|
45
|
+
export type { TtsHandle, TtsConfig, TtsSayOptions, TtsPresayOptions, TtsUtteranceEvent, TtsUtteranceCancelReason, } from './types/tts-handle';
|
|
42
46
|
export type { MixerQueueControl, PlayOptions, PresayOptions, PreloadOptions, TtsStrategy, TtsVendor } from './types/mixer';
|
|
43
47
|
export type { LegacyPhraseRecord, LegacyGetRecordsParams, CacheOptions, } from './types/legacy-phrase';
|
|
44
48
|
export { LEGACY_PHRASE_RECORD_BRAND, isLegacyPhraseRecord, } from './types/legacy-phrase';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,YAAY,EACV,wBAAwB,EACxB,qBAAqB,EACrB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,IAAI,yBAAyB,GACjD,MAAM,yBAAyB,CAAC;AAEjC,YAAY,EACV,mBAAmB,EACnB,WAAW,EACX,aAAa,EACb,YAAY,EACZ,qBAAqB,EACrB,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,YAAY,EACV,YAAY,EACZ,WAAW,EACX,SAAS,EACT,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,EACd,YAAY,GACb,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,aAAa,GACd,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,UAAU,EACV,UAAU,EACV,cAAc,EACd,cAAc,EACd,yBAAyB,GAC1B,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,UAAU,EACV,QAAQ,EACR,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAErB,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACjG,YAAY,EACV,SAAS,EACT,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC3H,YAAY,EACV,kBAAkB,EAClB,sBAAsB,EACtB,YAAY,GACb,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,0BAA0B,EAC1B,oBAAoB,GACrB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EACV,SAAS,EACT,OAAO,EACP,SAAS,EACT,WAAW,GACZ,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* When the host loads platform credential catalogs, **`channel.params.authentication_data`**
|
|
15
15
|
* may contain named ASR/TTS key rows for the current dialog agent and company. Use:
|
|
16
16
|
* - {@link import('./types/asr-handle').AsrConfig.name} or **`data.name`** on **`createAsr`**
|
|
17
|
+
* - {@link import('./types/tts-handle').TtsConfig.name} or **`data.name`** on **`createTts`**
|
|
17
18
|
* - {@link import('./types/mixer').PlayOptions.name} or **`ttsConfig.name`** on **`say`/`play`/`presay`**
|
|
18
19
|
*
|
|
19
20
|
* Channel defaults **`defaultAsrName`** / **`defaultTtsName`** apply when **`name`** is omitted.
|
|
@@ -29,9 +30,11 @@
|
|
|
29
30
|
* and live SIP INFO ({@link import('./types/events').SipInfo} on `sipInfo$`). See **`README.md`** → SIP Signalling Metadata.
|
|
30
31
|
*/
|
|
31
32
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
-
exports.parseRecallDelaySeconds = exports.parseRecallCount = exports.isLegacyPhraseRecord = exports.LEGACY_PHRASE_RECORD_BRAND = exports.TranscriptionRole = exports.getScriptPhase = exports.defineScript = void 0;
|
|
33
|
+
exports.parseRecallDelaySeconds = exports.parseRecallCount = exports.isLegacyPhraseRecord = exports.LEGACY_PHRASE_RECORD_BRAND = exports.TranscriptionRole = exports.getScriptPhase = exports.defineMediaProviders = exports.defineScript = void 0;
|
|
33
34
|
var define_script_1 = require("./define-script");
|
|
34
35
|
Object.defineProperty(exports, "defineScript", { enumerable: true, get: function () { return define_script_1.defineScript; } });
|
|
36
|
+
var media_providers_1 = require("./types/media-providers");
|
|
37
|
+
Object.defineProperty(exports, "defineMediaProviders", { enumerable: true, get: function () { return media_providers_1.defineMediaProviders; } });
|
|
35
38
|
var script_context_1 = require("./types/script-context");
|
|
36
39
|
Object.defineProperty(exports, "getScriptPhase", { enumerable: true, get: function () { return script_context_1.getScriptPhase; } });
|
|
37
40
|
var logger_1 = require("./types/logger");
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;;;AAEH,iDAA+C;AAAtC,6GAAA,YAAY,OAAA;AAGrB,2DAA+D;AAAtD,uHAAA,oBAAoB,OAAA;AAyB7B,yDAAwD;AAA/C,gHAAA,cAAc,OAAA;AAavB,yCAAmD;AAA1C,2GAAA,iBAAiB,OAAA;AAwC1B,uDAG+B;AAF7B,2HAAA,0BAA0B,OAAA;AAC1B,qHAAA,oBAAoB,OAAA;AAUtB,+CAA2E;AAAlE,gHAAA,gBAAgB,OAAA;AAAE,uHAAA,uBAAuB,OAAA"}
|
|
@@ -102,9 +102,13 @@ export interface AsrConfig {
|
|
|
102
102
|
/**
|
|
103
103
|
* Live speech recognition session returned by {@link import('./media-channel').MediaChannel.createAsr}.
|
|
104
104
|
*
|
|
105
|
+
* Call **`createAsr` early** to warm the ASR TCP/WebSocket (SSL handshake once per
|
|
106
|
+
* dialog + vendor + credentials). A second `createAsr` with the same resolved config
|
|
107
|
+
* reuses that channel instead of opening another socket. Call **`destroy()`** when done
|
|
108
|
+
* (e.g. on `channel.events.terminated$`) to release the connector.
|
|
109
|
+
*
|
|
105
110
|
* Subscribe to **`partial$`** / **`result$`** for transcripts; wire **`speechStart$`** /
|
|
106
|
-
* **`speechEnd$`** / **`interrupt$`** for barge-in and UI.
|
|
107
|
-
* (e.g. on `channel.events.terminated$`) to release connector and subscriptions.
|
|
111
|
+
* **`speechEnd$`** / **`interrupt$`** for barge-in and UI.
|
|
108
112
|
*
|
|
109
113
|
* If connector creation fails, SIP/WS return a degraded handle: VAD observables still
|
|
110
114
|
* mirror the channel where possible, but `partial$` and `result$` do not emit real STT.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asr-handle.d.ts","sourceRoot":"","sources":["../../src/types/asr-handle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AACvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,4DAA4D;IAC5D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,0DAA0D;IAC1D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iEAAiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gCAAgC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6DAA6D;IAC7D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oGAAoG;IACpG,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,kBAAkB;IACjC,+EAA+E;IAC/E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oEAAoE;IACpE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4FAA4F;IAC5F,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,SAAS;IACxB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oGAAoG;IACpG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,sEAAsE;IACtE,GAAG,CAAC,EAAE,YAAY,CAAC;IACnB,mDAAmD;IACnD,SAAS,CAAC,EAAE,kBAAkB,CAAC;CAChC;AAED
|
|
1
|
+
{"version":3,"file":"asr-handle.d.ts","sourceRoot":"","sources":["../../src/types/asr-handle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AACvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,4DAA4D;IAC5D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,0DAA0D;IAC1D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iEAAiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gCAAgC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6DAA6D;IAC7D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oGAAoG;IACpG,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,kBAAkB;IACjC,+EAA+E;IAC/E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oEAAoE;IACpE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4FAA4F;IAC5F,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,SAAS;IACxB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oGAAoG;IACpG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,sEAAsE;IACtE,GAAG,CAAC,EAAE,YAAY,CAAC;IACnB,mDAAmD;IACnD,SAAS,CAAC,EAAE,kBAAkB,CAAC;CAChC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,SAAS;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IACrC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAClE,kEAAkE;IAClE,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;IACxC,wDAAwD;IACxD,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;IACtC,gFAAgF;IAChF,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;IACtC,6FAA6F;IAC7F,QAAQ,CAAC,eAAe,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAE7C;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;IAExC,0FAA0F;IAC1F,KAAK,IAAI,IAAI,CAAC;IACd,kCAAkC;IAClC,MAAM,IAAI,IAAI,CAAC;IACf,kFAAkF;IAClF,QAAQ,IAAI,IAAI,CAAC;IACjB,8FAA8F;IAC9F,OAAO,IAAI,IAAI,CAAC;CACjB"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Observable } from 'rxjs';
|
|
2
2
|
import type { AsrConfig, AsrHandle } from './asr-handle';
|
|
3
|
+
import type { TtsConfig, TtsHandle } from './tts-handle';
|
|
3
4
|
import type { DataMessage } from './events';
|
|
4
5
|
import type { MixerQueueControl, PlayOptions, PresayOptions, PreloadOptions } from './mixer';
|
|
5
6
|
import type { LegacyPhraseRecord } from './legacy-phrase';
|
|
@@ -153,7 +154,7 @@ export interface MediaChannel {
|
|
|
153
154
|
* Relevant to ASR/TTS when **Voctiv platform** compatibility is on (host-dependent keys), for example:
|
|
154
155
|
* - **`asrVendor`**, **`ttsVendor`**, **`asrConfig`**, **`ttsConfig`**
|
|
155
156
|
* - **`defaultAsrName`**, **`defaultTtsName`**: default **`key_storage.name`** when the script
|
|
156
|
-
* omits **`name`** on {@link AsrConfig} / {@link PlayOptions}
|
|
157
|
+
* omits **`name`** on {@link AsrConfig} / {@link TtsConfig} / {@link PlayOptions}
|
|
157
158
|
* - **`authentication_data`**: may include **`legacyAsrKeysByName`**, **`legacyTtsKeysByName`**
|
|
158
159
|
* (built from LE DB for this dialog's agent + company)
|
|
159
160
|
*
|
|
@@ -161,11 +162,13 @@ export interface MediaChannel {
|
|
|
161
162
|
*/
|
|
162
163
|
readonly params: Record<string, unknown>;
|
|
163
164
|
/**
|
|
164
|
-
* Create a speech recognizer for this session
|
|
165
|
+
* Create (or warm) a speech recognizer for this session so recognition can reuse one
|
|
166
|
+
* TCP/WebSocket (one SSL handshake) for the dialog + vendor + credentials.
|
|
165
167
|
*
|
|
166
168
|
* SIP channels feed remote RTP audio. WS channels feed socket `audio` frames and can
|
|
167
169
|
* create a per-session VAD on first ASR creation. Headless channels return an inert
|
|
168
|
-
* handle with empty observables.
|
|
170
|
+
* handle with empty observables. A second call with the same resolved config returns
|
|
171
|
+
* the existing warm handle.
|
|
169
172
|
*
|
|
170
173
|
* @param config - Optional {@link AsrConfig}: **`vendor`**, **`name`** (storage row), **`language`**,
|
|
171
174
|
* **`data`** overlays, VAD / smart-turn tuning.
|
|
@@ -173,6 +176,24 @@ export interface MediaChannel {
|
|
|
173
176
|
* If connector creation fails, SIP/WS return a degraded handle with VAD observables but no STT results.
|
|
174
177
|
*/
|
|
175
178
|
createAsr(config?: AsrConfig): Promise<AsrHandle>;
|
|
179
|
+
/**
|
|
180
|
+
* Create (or warm) a TTS connector for this session so later `audio.say` / `audio.presay`
|
|
181
|
+
* can reuse the SSL / WebSocket connection.
|
|
182
|
+
*
|
|
183
|
+
* For streaming-capable vendors (e.g. ElevenLabs with `ttsStrategy: 'streaming'`), the host
|
|
184
|
+
* opens the streaming socket during this call. For batch HTTP vendors, the connector instance
|
|
185
|
+
* is registered in the dialog-scoped factory (keep-alive pool).
|
|
186
|
+
*
|
|
187
|
+
* Prefer calling {@link TtsHandle.say} / {@link TtsHandle.presay} on the returned handle
|
|
188
|
+
* (same pattern as {@link AsrHandle}). You may also pass the handle as {@link PlayOptions.tts}
|
|
189
|
+
* to `channel.audio.say` / `presay`, or omit it when a later `say` resolves to the same
|
|
190
|
+
* vendor+config — the host will reuse a matching session.
|
|
191
|
+
*
|
|
192
|
+
* @param config - Optional {@link TtsConfig}: **`vendor`**, **`name`** (storage row), **`data`** overlays.
|
|
193
|
+
* @returns A handle you should {@link TtsHandle.destroy} when you no longer need the connection.
|
|
194
|
+
* If connector creation fails, SIP/WS return a degraded handle (synthesis falls back to ephemeral).
|
|
195
|
+
*/
|
|
196
|
+
createTts(config?: TtsConfig): Promise<TtsHandle>;
|
|
176
197
|
/** Push synthetic ASR results (testing / WS debug). No-op on headless channels. */
|
|
177
198
|
readonly textInput: TextInput;
|
|
178
199
|
readonly audio: ChannelAudio;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-channel.d.ts","sourceRoot":"","sources":["../../src/types/media-channel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC7F,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAExC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;;;;;;;;;;;;OAgBG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E;;;;;;;;;;;;OAYG;IACH,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,kBAAkB,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChF;;;;;;;;;OASG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE;;;;;;;;;OASG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D;;;OAGG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,iBAAiB,CAAC;IACxC;;;;;;;;;OASG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C;;;;;OAKG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,wFAAwF;IACxF,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,yGAAyG;AACzG,MAAM,WAAW,aAAa;IAC5B,8FAA8F;IAC9F,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;IACxC,uGAAuG;IACvG,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;IACtC,8FAA8F;IAC9F,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;IACtC,yFAAyF;IACzF,QAAQ,CAAC,WAAW,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;IACvC,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;IAC3C;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;CACzC;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEzC
|
|
1
|
+
{"version":3,"file":"media-channel.d.ts","sourceRoot":"","sources":["../../src/types/media-channel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { Observable, Subject } from 'rxjs';
|
|
2
|
+
import type { Readable } from 'stream';
|
|
3
|
+
/**
|
|
4
|
+
* Context passed to custom ASR/TTS factories from {@link defineMediaProviders}.
|
|
5
|
+
* Populated by the host outside the script sandbox.
|
|
6
|
+
*/
|
|
7
|
+
export interface MediaConnectorContext {
|
|
8
|
+
id: string;
|
|
9
|
+
config: Record<string, string>;
|
|
10
|
+
dialogUuid: string;
|
|
11
|
+
role?: string;
|
|
12
|
+
debug$: Subject<string>;
|
|
13
|
+
}
|
|
14
|
+
export interface ScriptAsrConnectorError {
|
|
15
|
+
message: string;
|
|
16
|
+
code?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Host ASR connector contract for custom providers (same surface as runtime AsrConnector).
|
|
20
|
+
*/
|
|
21
|
+
export interface ScriptAsrConnector {
|
|
22
|
+
transcription$: Subject<{
|
|
23
|
+
text: string;
|
|
24
|
+
isFinal: boolean;
|
|
25
|
+
}>;
|
|
26
|
+
result$: Subject<string>;
|
|
27
|
+
error$: Subject<ScriptAsrConnectorError>;
|
|
28
|
+
isOpen(): boolean;
|
|
29
|
+
send(audio: ArrayBufferLike): void;
|
|
30
|
+
speech(active: boolean): void;
|
|
31
|
+
finalize(): void;
|
|
32
|
+
close(): void;
|
|
33
|
+
}
|
|
34
|
+
export type TtsSynthesisContext = {
|
|
35
|
+
previousText?: string;
|
|
36
|
+
nextText?: string;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Unified TTS connector: batch HTTP + optional streaming WebSocket methods.
|
|
40
|
+
*/
|
|
41
|
+
export interface ScriptTtsConnector {
|
|
42
|
+
supportsStreaming(): boolean;
|
|
43
|
+
textToSpeechStream(rawtext: string, ctx?: TtsSynthesisContext): Promise<Readable>;
|
|
44
|
+
readonly audio$: Subject<Buffer>;
|
|
45
|
+
readonly done$: Subject<void>;
|
|
46
|
+
open(): Promise<void>;
|
|
47
|
+
startGeneration(): Promise<void>;
|
|
48
|
+
sendText(chunk: string): void;
|
|
49
|
+
flush(): void;
|
|
50
|
+
sendSeparatorFlush?(): void;
|
|
51
|
+
close(): void;
|
|
52
|
+
}
|
|
53
|
+
/** Optional session object shared by ASR and TTS factories for one dialog. */
|
|
54
|
+
export type MediaProviderShared = {
|
|
55
|
+
dispose?: () => void;
|
|
56
|
+
close?: () => void;
|
|
57
|
+
} & Record<string, unknown>;
|
|
58
|
+
export type AsrProviderFactory = (ctx: MediaConnectorContext, shared: MediaProviderShared | undefined) => ScriptAsrConnector;
|
|
59
|
+
export type TtsProviderFactory = (ctx: MediaConnectorContext, shared: MediaProviderShared | undefined) => ScriptTtsConnector;
|
|
60
|
+
export interface MediaProvidersDefinition {
|
|
61
|
+
createShared?: (ctx: {
|
|
62
|
+
dialogUuid: string;
|
|
63
|
+
debug$: Subject<string>;
|
|
64
|
+
}) => MediaProviderShared;
|
|
65
|
+
asr?: Record<string, AsrProviderFactory>;
|
|
66
|
+
tts?: Record<string, TtsProviderFactory>;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Mark a named export as custom media providers (identity helper).
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* export const mediaProviders = defineMediaProviders({
|
|
74
|
+
* createShared: (ctx) => new MySession(ctx),
|
|
75
|
+
* asr: { 'my-asr': (ctx, shared) => new MyAsr(ctx, shared) },
|
|
76
|
+
* tts: { 'my-tts': (ctx, shared) => new MyTts(ctx, shared) },
|
|
77
|
+
* });
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export declare function defineMediaProviders(def: MediaProvidersDefinition): MediaProvidersDefinition;
|
|
81
|
+
/** @internal helper type for hosts that mirror connector subjects */
|
|
82
|
+
export type SubjectLike<T> = Subject<T> | Observable<T>;
|
|
83
|
+
//# sourceMappingURL=media-providers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-providers.d.ts","sourceRoot":"","sources":["../../src/types/media-providers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defineMediaProviders = defineMediaProviders;
|
|
4
|
+
/**
|
|
5
|
+
* Mark a named export as custom media providers (identity helper).
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* export const mediaProviders = defineMediaProviders({
|
|
10
|
+
* createShared: (ctx) => new MySession(ctx),
|
|
11
|
+
* asr: { 'my-asr': (ctx, shared) => new MyAsr(ctx, shared) },
|
|
12
|
+
* tts: { 'my-tts': (ctx, shared) => new MyTts(ctx, shared) },
|
|
13
|
+
* });
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
function defineMediaProviders(def) {
|
|
17
|
+
return def;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=media-providers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-providers.js","sourceRoot":"","sources":["../../src/types/media-providers.ts"],"names":[],"mappings":";;AAmGA,oDAIC;AAhBD;;;;;;;;;;;GAWG;AACH,SAAgB,oBAAoB,CAClC,GAA6B;IAE7B,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/types/mixer.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Observable } from 'rxjs';
|
|
2
2
|
import type { CacheOptions } from './legacy-phrase';
|
|
3
|
+
import type { TtsHandle } from './tts-handle';
|
|
3
4
|
/**
|
|
4
5
|
* How TTS audio is chunked and fed to the mixer.
|
|
5
6
|
*
|
|
@@ -74,8 +75,16 @@ export interface PlayOptions {
|
|
|
74
75
|
/**
|
|
75
76
|
* Force a specific TTS vendor for this call, overriding **`channel.params.ttsVendor`**.
|
|
76
77
|
* Ignored for **`play()`** when the source is raw audio (no synthesis).
|
|
78
|
+
* When {@link tts} is set, the handle's resolved vendor/config take precedence.
|
|
77
79
|
*/
|
|
78
80
|
ttsVendor?: TtsVendor;
|
|
81
|
+
/**
|
|
82
|
+
* Pre-warmed TTS session from {@link import('./media-channel').MediaChannel.createTts}.
|
|
83
|
+
* Reuses the cached connector / streaming WebSocket so synthesis skips a fresh SSL handshake.
|
|
84
|
+
* When set, the handle's resolved vendor and connector config are used (overrides
|
|
85
|
+
* {@link ttsVendor} / {@link name} / {@link ttsConfig} for credential resolution).
|
|
86
|
+
*/
|
|
87
|
+
tts?: TtsHandle;
|
|
79
88
|
/**
|
|
80
89
|
* logic-executor **`key_storage.name`**: use **`authentication_data.legacyTtsKeysByName[name]`**
|
|
81
90
|
* for credentials. Overrides **`defaultTtsName`** on the channel.
|
|
@@ -107,6 +116,11 @@ export interface PlayOptions {
|
|
|
107
116
|
*/
|
|
108
117
|
export interface PresayOptions {
|
|
109
118
|
ttsVendor?: TtsVendor;
|
|
119
|
+
/**
|
|
120
|
+
* Pre-warmed TTS session from {@link import('./media-channel').MediaChannel.createTts}.
|
|
121
|
+
* Same reuse semantics as {@link PlayOptions.tts}.
|
|
122
|
+
*/
|
|
123
|
+
tts?: TtsHandle;
|
|
110
124
|
name?: string;
|
|
111
125
|
ttsConfig?: Record<string, unknown>;
|
|
112
126
|
ttsStrategy?: TtsStrategy;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mixer.d.ts","sourceRoot":"","sources":["../../src/types/mixer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAClC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"mixer.d.ts","sourceRoot":"","sources":["../../src/types/mixer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAClC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,WAAW,GAAG,MAAM,CAAC;AAE5D;;;;;;;;GAQG;AACH,MAAM,MAAM,SAAS,GACjB,YAAY,GACZ,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,MAAM,GACN,SAAS,GACT,QAAQ,GACR,OAAO,GACP,UAAU,GACV,UAAU,GACV,eAAe,GACf,aAAa,GACb,KAAK,GACL,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;AAEpC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wFAAwF;IACxF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,uEAAuE;IACvE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,IAAI,GAAG,YAAY,CAAC;CAC7B;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;OAGG;IACH,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,mFAAmF;IACnF,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,mFAAmF;IACnF,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,sFAAsF;IACtF,MAAM,EAAE,MAAM,CAAC;IAEf,mEAAmE;IACnE,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAC1C,yFAAyF;IACzF,QAAQ,CAAC,aAAa,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAC3C;oFACgF;IAChF,QAAQ,CAAC,WAAW,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;IAEvC;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,uDAAuD;IACvD,KAAK,IAAI,IAAI,CAAC;CACf"}
|
|
@@ -59,6 +59,21 @@ export interface ScriptDialogContext {
|
|
|
59
59
|
callerId: string;
|
|
60
60
|
/** Called number (DID / destination for inbound calls). */
|
|
61
61
|
destinationNumber: string;
|
|
62
|
+
/**
|
|
63
|
+
* LE trunk id for this dialog/call — snapshot at script start.
|
|
64
|
+
*
|
|
65
|
+
* Resolved from `call.trunk_id`, inbound `X-Trunk-Id`, `dialog.params.trunk_id`,
|
|
66
|
+
* then `agent.trunk_id`. Omitted when no trunk is configured.
|
|
67
|
+
*/
|
|
68
|
+
trunkId?: number;
|
|
69
|
+
/**
|
|
70
|
+
* LE `trunk.name` for {@link trunkId}, resolved by the host at script start.
|
|
71
|
+
*
|
|
72
|
+
* Available in online and headless runs when the platform trunk table is reachable.
|
|
73
|
+
* Not a SIP wire header — for inbound id-only signalling use
|
|
74
|
+
* `channel.sip.inviteSipHeaders['X-Trunk-Id']`.
|
|
75
|
+
*/
|
|
76
|
+
trunkName?: string;
|
|
62
77
|
/** Script record ID in the system. */
|
|
63
78
|
scriptId: string;
|
|
64
79
|
/** Human-readable script name. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"script-context.d.ts","sourceRoot":"","sources":["../../src/types/script-context.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"script-context.d.ts","sourceRoot":"","sources":["../../src/types/script-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,oEAAoE;AACpE,MAAM,WAAW,kBAAkB;IACjC,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,uFAAuF;AACvF,MAAM,WAAW,YAAY;IAC3B,4DAA4D;IAC5D,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,GAAG,CAAC,EAAE;QACJ,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;QACrC,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;QACnD,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC3E,CACE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAAC;KAClB,CAAC;IACF;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,iFAAiF;AACjF,MAAM,MAAM,iBAAiB,GAAG,CAC9B,GAAG,IAAI,EAAE,MAAM,EAAE,KACd,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;AAE5C;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;OAOG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB;;;OAGG;IACH,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B;;;;;;;OAOG;IACH,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC;;;;;;;;;OASG;IACH,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,4DAA4D;IAC5D,cAAc,EAAE,OAAO,CAAC;IAExB;;;;;;OAMG;IACH,QAAQ,EAAE,OAAO,CAAC;IAElB;;;;;;;;;;;;;;;OAeG;IACH,IAAI,CAAC,EAAE,eAAe,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,CAAC;IAE5D,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAErC;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE9B;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iGAAiG;IACjG,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAEhC;;;OAGG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;IAExB,yDAAyD;IACzD,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,yFAAyF;IACzF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,wEAAwE;IACxE,WAAW,IAAI,MAAM,CAAC;IACtB,4CAA4C;IAC5C,iBAAiB,IAAI,MAAM,CAAC;IAC5B;;;OAGG;IACH,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;CACrC;AAED;;;GAGG;AACH,MAAM,MAAM,WAAW,GACnB,aAAa,GACb,QAAQ,GACR,oBAAoB,GACpB,mBAAmB,GACnB,WAAW,GACX,QAAQ,GACR,gBAAgB,CAAC;AAarB;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,mBAAmB,GAAG,WAAW,CAcxE;AAED,uEAAuE;AACvE,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,uEAAuE;IACvE,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAsB,SAAQ,YAAY;IACzD,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"script-context.js","sourceRoot":"","sources":["../../src/types/script-context.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"script-context.js","sourceRoot":"","sources":["../../src/types/script-context.ts"],"names":[],"mappings":";;AA4RA,wCAcC;AApCD,MAAM,+BAA+B,GAAG,IAAI,GAAG,CAAC;IAC9C,iBAAiB;IACjB,oBAAoB;IACpB,cAAc;CACf,CAAC,CAAC;AACH,MAAM,8BAA8B,GAAG,IAAI,GAAG,CAAC;IAC7C,gBAAgB;IAChB,mBAAmB;CACpB,CAAC,CAAC;AACH,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;AAE7D;;;;;;;;;;GAUG;AACH,SAAgB,cAAc,CAAC,OAA4B;IACzD,IAAI,CAAC,OAAO,CAAC,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAEvC,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC;IAE1D,IAAI,+BAA+B,CAAC,GAAG,CAAC,EAAE,CAAC;QAAE,OAAO,oBAAoB,CAAC;IACzE,IAAI,8BAA8B,CAAC,GAAG,CAAC,EAAE,CAAC;QAAE,OAAO,mBAAmB,CAAC;IACvE,IAAI,mBAAmB,CAAC,GAAG,CAAC,EAAE,CAAC;QAAE,OAAO,QAAQ,CAAC;IACjD,IAAI,EAAE,KAAK,yBAAyB,IAAI,OAAO,CAAC,cAAc;QAC5D,OAAO,WAAW,CAAC;IAErB,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,MAAM,IAAI,EAAE,KAAK,SAAS;QAAE,OAAO,aAAa,CAAC;IAEnE,OAAO,gBAAgB,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import type { Observable } from 'rxjs';
|
|
2
|
+
import type { MediaError } from './errors';
|
|
3
|
+
import type { PlayOptions, PresayOptions } from './mixer';
|
|
4
|
+
/**
|
|
5
|
+
* Arguments for {@link import('./media-channel').MediaChannel.createTts}.
|
|
6
|
+
*
|
|
7
|
+
* Mirrors {@link import('./asr-handle').AsrConfig} credential selection for TTS:
|
|
8
|
+
* when Voctiv platform compatibility is on, **`name`** selects a row from
|
|
9
|
+
* **`authentication_data.legacyTtsKeysByName`**. You may also set the same selector
|
|
10
|
+
* as **`data.name`** (stripped before vendor params are built).
|
|
11
|
+
*
|
|
12
|
+
* Call **`createTts`** early in the dialog to open / warm the vendor connection
|
|
13
|
+
* (HTTP keep-alive pool or streaming WebSocket) so later {@link TtsHandle.say}
|
|
14
|
+
* / {@link TtsHandle.say$} / {@link TtsHandle.presay} calls reuse it instead of
|
|
15
|
+
* paying SSL handshake latency on every utterance.
|
|
16
|
+
*/
|
|
17
|
+
export interface TtsConfig {
|
|
18
|
+
/**
|
|
19
|
+
* TTS vendor / engine hint, e.g. `"elevenlabs"`, `"google"`, `"azure"`, `"voctiv"`.
|
|
20
|
+
* Resolved via ScriptEngine vendor aliases. If you set **`name`** but omit **`vendor`**,
|
|
21
|
+
* the runtime may infer vendor from the key row's **`platform`** in the catalog.
|
|
22
|
+
*/
|
|
23
|
+
vendor?: string;
|
|
24
|
+
/**
|
|
25
|
+
* logic-executor **`key_storage.name`** for this dialog's agent + company. Selects credentials
|
|
26
|
+
* from **`authentication_data.legacyTtsKeysByName[name]`** when Voctiv platform PostgreSQL key auth is enabled.
|
|
27
|
+
* Overrides channel **`defaultTtsName`**.
|
|
28
|
+
*/
|
|
29
|
+
name?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Vendor-specific connection parameters (voice id, model, `output_format`, nested JSON, …).
|
|
32
|
+
* Merged last over channel defaults and catalog credentials so the script can override
|
|
33
|
+
* per session. Primitives are stringified; objects and arrays are JSON-serialized.
|
|
34
|
+
*
|
|
35
|
+
* Do not rely on **`name`** here for third-party "model name" fields — the runtime consumes
|
|
36
|
+
* it as the storage row selector and removes it before vendor config is built.
|
|
37
|
+
*/
|
|
38
|
+
data?: Record<string, unknown>;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Playback options for {@link TtsHandle.say} / {@link TtsHandle.say$}.
|
|
42
|
+
*
|
|
43
|
+
* Vendor / credentials come from {@link import('./media-channel').MediaChannel.createTts};
|
|
44
|
+
* only mixer and strategy fields apply here.
|
|
45
|
+
*/
|
|
46
|
+
export type TtsSayOptions = Omit<PlayOptions, 'tts' | 'ttsVendor' | 'name' | 'ttsConfig'>;
|
|
47
|
+
/**
|
|
48
|
+
* Options for {@link TtsHandle.presay}.
|
|
49
|
+
*
|
|
50
|
+
* Vendor / credentials come from {@link import('./media-channel').MediaChannel.createTts}.
|
|
51
|
+
*/
|
|
52
|
+
export type TtsPresayOptions = Omit<PresayOptions, 'tts' | 'ttsVendor' | 'name' | 'ttsConfig'>;
|
|
53
|
+
/** Why a tracked utterance was cancelled before natural completion. */
|
|
54
|
+
export type TtsUtteranceCancelReason = 'stop' | 'destroy';
|
|
55
|
+
/**
|
|
56
|
+
* Lifecycle events for one {@link TtsHandle.say$} invocation.
|
|
57
|
+
*
|
|
58
|
+
* Typical sequence (sentence strategy):
|
|
59
|
+
* `queued` → (`speaking` → `done`)×N then Observable **complete**.
|
|
60
|
+
* `done` means one sentence/phrase finished playback (not the whole `say$` call).
|
|
61
|
+
* Single-item / streaming strategy: one `speaking` → one `done` then **complete**.
|
|
62
|
+
* On barge-in / `audio.stop`: `queued` → (`speaking`?) → `cancelled` then **complete**.
|
|
63
|
+
* On synthesis failure: `queued` → (`speaking`?) then the Observable **errors** with
|
|
64
|
+
* {@link MediaError} (also mirrored on {@link TtsHandle.error$} / `channel.events.error$`).
|
|
65
|
+
*/
|
|
66
|
+
export type TtsUtteranceEvent = {
|
|
67
|
+
state: 'queued';
|
|
68
|
+
alias: string;
|
|
69
|
+
queue: number;
|
|
70
|
+
/**
|
|
71
|
+
* Full utterance text known so far.
|
|
72
|
+
* Plain string input: complete text. Token stream: grows as chunks arrive
|
|
73
|
+
* (initial `queued` may have `text: ''`).
|
|
74
|
+
*/
|
|
75
|
+
text: string;
|
|
76
|
+
} | {
|
|
77
|
+
state: 'speaking';
|
|
78
|
+
alias: string;
|
|
79
|
+
queue: number;
|
|
80
|
+
/** Full utterance text accumulated so far (stream) or the whole input (string). */
|
|
81
|
+
text: string;
|
|
82
|
+
/**
|
|
83
|
+
* Text of the sentence/segment currently starting playback when the host
|
|
84
|
+
* uses sentence-split aliases (`alias-0`, `alias-1`, …).
|
|
85
|
+
* For a single-item utterance (streaming strategy / exact alias) this equals {@link text}.
|
|
86
|
+
*/
|
|
87
|
+
sentenceText: string;
|
|
88
|
+
/** Index of the sentence segment (`0` for `alias-0`), when applicable. */
|
|
89
|
+
sentenceIndex?: number;
|
|
90
|
+
/** Concrete mixer item alias (may be `alias-0` for sentence-split TTS). */
|
|
91
|
+
itemAlias?: string;
|
|
92
|
+
} | {
|
|
93
|
+
state: 'done';
|
|
94
|
+
alias: string;
|
|
95
|
+
queue: number;
|
|
96
|
+
/** Full utterance text accumulated so far (stream) or the whole input (string). */
|
|
97
|
+
text: string;
|
|
98
|
+
/**
|
|
99
|
+
* Text of the sentence/segment that just finished playback.
|
|
100
|
+
* Same rules as {@link TtsUtteranceEvent} `speaking.sentenceText`.
|
|
101
|
+
*/
|
|
102
|
+
sentenceText: string;
|
|
103
|
+
/** Index of the sentence segment (`0` for `alias-0`), when applicable. */
|
|
104
|
+
sentenceIndex?: number;
|
|
105
|
+
/** Concrete mixer item alias that finished. */
|
|
106
|
+
itemAlias?: string;
|
|
107
|
+
} | {
|
|
108
|
+
state: 'cancelled';
|
|
109
|
+
alias: string;
|
|
110
|
+
queue: number;
|
|
111
|
+
reason: TtsUtteranceCancelReason;
|
|
112
|
+
/** Accumulated text at cancel time. */
|
|
113
|
+
text: string;
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* Pre-warmed TTS session returned by {@link import('./media-channel').MediaChannel.createTts}.
|
|
117
|
+
*
|
|
118
|
+
* Use **`say`** / **`say$`** / **`presay`** on this handle (same idea as
|
|
119
|
+
* {@link import('./asr-handle').AsrHandle} methods) so synthesis reuses the cached
|
|
120
|
+
* connector / streaming WebSocket. Call **`destroy()`** when done
|
|
121
|
+
* (e.g. on `channel.events.terminated$`) to release the session.
|
|
122
|
+
*
|
|
123
|
+
* You may still pass the handle as {@link import('./mixer').PlayOptions.tts} to
|
|
124
|
+
* `channel.audio.say` / `presay` if needed.
|
|
125
|
+
*
|
|
126
|
+
* If connector creation fails, SIP/WS return a degraded handle: `say`/`say$`/`presay` fall back
|
|
127
|
+
* to an ephemeral connection, and the creation failure is reported on
|
|
128
|
+
* {@link import('./media-channel').ChannelEvents.error$}.
|
|
129
|
+
*
|
|
130
|
+
* ```ts
|
|
131
|
+
* const tts = await channel.createTts({ name: 'elevenlabs-main' });
|
|
132
|
+
* tts.error$.subscribe(err => console.log('TTS error:', err.message));
|
|
133
|
+
*
|
|
134
|
+
* await tts.say('Hello', { alias: 'greeting' });
|
|
135
|
+
*
|
|
136
|
+
* tts.say$('Next', { alias: 'reply' }).subscribe({
|
|
137
|
+
* next: (e) => { if (e.state === 'speaking') console.log('now playing', e.alias); },
|
|
138
|
+
* error: (err) => console.log('TTS failed', err.message),
|
|
139
|
+
* });
|
|
140
|
+
*
|
|
141
|
+
* tts.destroy();
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
export interface TtsHandle {
|
|
145
|
+
/** Opaque id for this pre-warmed TTS session. */
|
|
146
|
+
readonly id: string;
|
|
147
|
+
/**
|
|
148
|
+
* Runtime errors from the TTS provider for this session (auth failures, disconnects, etc.).
|
|
149
|
+
*
|
|
150
|
+
* A degraded handle (returned when connector creation itself failed) has an inert `error$`
|
|
151
|
+
* that never emits — the creation failure is reported on {@link import('./media-channel').ChannelEvents.error$} instead.
|
|
152
|
+
*/
|
|
153
|
+
readonly error$: Observable<MediaError>;
|
|
154
|
+
/**
|
|
155
|
+
* Synthesize and play text on a mixer queue, reusing this session's connector.
|
|
156
|
+
*
|
|
157
|
+
* Resolves when playback of this invocation has finished (or was aborted).
|
|
158
|
+
* For per-utterance lifecycle (`queued` / `speaking` / `done` / …) use {@link say$}.
|
|
159
|
+
*/
|
|
160
|
+
say(input: string | Observable<string>, options?: TtsSayOptions): Promise<void>;
|
|
161
|
+
/**
|
|
162
|
+
* Same synthesis path as {@link say}, but emits {@link TtsUtteranceEvent} for this utterance.
|
|
163
|
+
*
|
|
164
|
+
* Only available on handles from {@link import('./media-channel').MediaChannel.createTts}
|
|
165
|
+
* (not on `channel.audio.say`). Emits `done` per finished sentence; Observable **completes**
|
|
166
|
+
* when the whole call ends (or after `cancelled`). Synthesis failures go to the Observable
|
|
167
|
+
* **error** channel as {@link MediaError}.
|
|
168
|
+
*
|
|
169
|
+
* ```ts
|
|
170
|
+
* tts.say$('One. Two.', { alias: 'greet', queue: 0 }).subscribe({
|
|
171
|
+
* next: (e) => {
|
|
172
|
+
* switch (e.state) {
|
|
173
|
+
* case 'queued': break; // e.text — full string (or '' for live stream)
|
|
174
|
+
* case 'speaking': break; // e.sentenceText — sentence starting playback
|
|
175
|
+
* case 'done': break; // e.sentenceText — that sentence finished
|
|
176
|
+
* case 'cancelled': break; // stop / destroy
|
|
177
|
+
* }
|
|
178
|
+
* },
|
|
179
|
+
* complete: () => {}, // whole say$ finished
|
|
180
|
+
* error: (err: MediaError) => console.log('TTS failed', err.message),
|
|
181
|
+
* });
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
say$(input: string | Observable<string>, options?: TtsSayOptions): Observable<TtsUtteranceEvent>;
|
|
185
|
+
/**
|
|
186
|
+
* Pre-synthesize text into the host TTS cache using this session's connector.
|
|
187
|
+
*
|
|
188
|
+
* Same behaviour as {@link import('./media-channel').ChannelAudio.presay}.
|
|
189
|
+
*/
|
|
190
|
+
presay(text: string, options?: TtsPresayOptions): Promise<void>;
|
|
191
|
+
/** Tear down the cached connector / streaming socket. Idempotent-safe on well-behaved hosts. */
|
|
192
|
+
destroy(): void;
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=tts-handle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tts-handle.d.ts","sourceRoot":"","sources":["../../src/types/tts-handle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tts-handle.js","sourceRoot":"","sources":["../../src/types/tts-handle.ts"],"names":[],"mappings":""}
|
package/examples/README.md
CHANGED
|
@@ -11,6 +11,7 @@ Each file exports one `defineScript` handler. The host **always** invokes that s
|
|
|
11
11
|
| [schedule-call-with-defaults.ts](./schedule-call-with-defaults.ts) | `platform.call()` using CMS defaults from `context` |
|
|
12
12
|
| [after-call-continuation.ts](./after-call-continuation.ts) | `onSuccessCall` / `onFailedCall` + `getScriptPhase()` |
|
|
13
13
|
| [read-recall-from-params.ts](./read-recall-from-params.ts) | `parseRecallDelaySeconds()` / `parseRecallCount()` |
|
|
14
|
+
| [custom-media-providers.ts](./custom-media-providers.ts) | `defineMediaProviders` + `createAsr` / `createTts` / `say$` |
|
|
14
15
|
|
|
15
16
|
## Recall flow
|
|
16
17
|
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom ASR / TTS from a trusted logic package.
|
|
3
|
+
*
|
|
4
|
+
* Export `mediaProviders` next to `defineScript`. The host loads that export
|
|
5
|
+
* outside the sandbox and wires vendors into `createAsr` / `createTts` with the
|
|
6
|
+
* same warm TCP/WS reuse as built-in engines.
|
|
7
|
+
*
|
|
8
|
+
* Batch and streaming TTS share one class (`supportsStreaming()` + streaming
|
|
9
|
+
* lifecycle methods). Do not register a separate streaming map.
|
|
10
|
+
*/
|
|
11
|
+
import { Readable } from 'stream';
|
|
12
|
+
import { Subject } from 'rxjs';
|
|
13
|
+
import {
|
|
14
|
+
defineScript,
|
|
15
|
+
defineMediaProviders,
|
|
16
|
+
type MediaConnectorContext,
|
|
17
|
+
type MediaProviderShared,
|
|
18
|
+
type ScriptAsrConnector,
|
|
19
|
+
type ScriptTtsConnector,
|
|
20
|
+
} from '@voctiv/agent-sdk';
|
|
21
|
+
|
|
22
|
+
type SharedSession = MediaProviderShared & {
|
|
23
|
+
turns: number;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
class EchoAsr implements ScriptAsrConnector {
|
|
27
|
+
readonly transcription$ = new Subject<{ text: string; isFinal: boolean }>();
|
|
28
|
+
readonly result$ = new Subject<string>();
|
|
29
|
+
readonly error$ = new Subject<{ message: string; code?: number }>();
|
|
30
|
+
|
|
31
|
+
constructor(
|
|
32
|
+
private readonly ctx: MediaConnectorContext,
|
|
33
|
+
private readonly shared: SharedSession | undefined,
|
|
34
|
+
) {}
|
|
35
|
+
|
|
36
|
+
isOpen(): boolean {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
send(_audio: ArrayBufferLike): void {
|
|
41
|
+
// Forward PCM to your vendor here.
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
speech(_active: boolean): void {}
|
|
45
|
+
|
|
46
|
+
finalize(): void {
|
|
47
|
+
const text = 'heard';
|
|
48
|
+
this.transcription$.next({ text, isFinal: true });
|
|
49
|
+
this.result$.next(text);
|
|
50
|
+
if (this.shared) this.shared.turns += 1;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
close(): void {
|
|
54
|
+
this.transcription$.complete();
|
|
55
|
+
this.result$.complete();
|
|
56
|
+
this.error$.complete();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
class BatchOrStreamTts implements ScriptTtsConnector {
|
|
61
|
+
readonly audio$ = new Subject<Buffer>();
|
|
62
|
+
readonly done$ = new Subject<void>();
|
|
63
|
+
|
|
64
|
+
constructor(
|
|
65
|
+
private readonly ctx: MediaConnectorContext,
|
|
66
|
+
private readonly shared: SharedSession | undefined,
|
|
67
|
+
) {}
|
|
68
|
+
|
|
69
|
+
/** Return true when this connector also owns a long-lived streaming socket. */
|
|
70
|
+
supportsStreaming(): boolean {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async textToSpeechStream(rawtext: string): Promise<Readable> {
|
|
75
|
+
void this.ctx;
|
|
76
|
+
void this.shared;
|
|
77
|
+
// Replace with HTTP keep-alive synthesis that returns a PCM stream.
|
|
78
|
+
return Readable.from([Buffer.from(rawtext, 'utf8')]);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async open(): Promise<void> {}
|
|
82
|
+
async startGeneration(): Promise<void> {}
|
|
83
|
+
sendText(_chunk: string): void {}
|
|
84
|
+
flush(): void {}
|
|
85
|
+
close(): void {
|
|
86
|
+
// Soft-close streaming sockets for reuse; do not complete Subjects if the
|
|
87
|
+
// host may call open() again on the same fingerprint.
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export const mediaProviders = defineMediaProviders({
|
|
92
|
+
createShared: (): SharedSession => ({
|
|
93
|
+
turns: 0,
|
|
94
|
+
dispose() {
|
|
95
|
+
/* release vendor app state for this dialog */
|
|
96
|
+
},
|
|
97
|
+
}),
|
|
98
|
+
asr: {
|
|
99
|
+
'my-asr': (ctx, shared) => new EchoAsr(ctx, shared as SharedSession),
|
|
100
|
+
},
|
|
101
|
+
tts: {
|
|
102
|
+
'my-tts': (ctx, shared) =>
|
|
103
|
+
new BatchOrStreamTts(ctx, shared as SharedSession),
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
export default defineScript(async ({ channel, logger }) => {
|
|
108
|
+
channel.sip.answer();
|
|
109
|
+
|
|
110
|
+
const asr = await channel.createAsr({ vendor: 'my-asr' });
|
|
111
|
+
const tts = await channel.createTts({ vendor: 'my-tts' });
|
|
112
|
+
|
|
113
|
+
await tts.say('Hello from a custom TTS connector.');
|
|
114
|
+
|
|
115
|
+
tts.say$('One. Two.', { alias: 'reply' }).subscribe({
|
|
116
|
+
next: (ev) => {
|
|
117
|
+
logger.log('tts utterance', { state: ev.state, alias: ev.itemAlias });
|
|
118
|
+
},
|
|
119
|
+
error: (err) => logger.error('tts failed', err),
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// Same warm handle via audio.say:
|
|
123
|
+
await channel.audio.say('Reuse handle', { tts });
|
|
124
|
+
|
|
125
|
+
asr.destroy();
|
|
126
|
+
tts.destroy();
|
|
127
|
+
channel.sip.hangup();
|
|
128
|
+
});
|
package/package.json
CHANGED