@voctiv/agent-sdk 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,22 +1,25 @@
1
1
  /**
2
- * Custom ASR / TTS from a trusted logic package.
2
+ * Host-only custom ASR / TTS module.
3
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.
4
+ * Ship as `dist/media-providers/index.js` next to the sandboxed script entry.
5
+ * The host `require`s this file outside the script VM (full Node: `ws`, `process`, …).
6
+ *
7
+ * Do **not** re-export `mediaProviders` from `dist/index.js` — the sandbox has no
8
+ * `process`, so loading `ws` there fails. Keep `defineScript` in a separate file
9
+ * (see `custom-media-providers-script.ts`).
7
10
  *
8
11
  * Batch and streaming TTS share one class (`supportsStreaming()` + streaming
9
- * lifecycle methods). Do not register a separate streaming map.
12
+ * lifecycle). Do not register a separate streaming map.
10
13
  */
11
14
  import { Readable } from 'stream';
12
15
  import { Subject } from 'rxjs';
13
16
  import {
14
- defineScript,
15
17
  defineMediaProviders,
16
18
  type MediaConnectorContext,
17
19
  type MediaProviderShared,
18
20
  type ScriptAsrConnector,
19
21
  type ScriptTtsConnector,
22
+ type ScriptTtsSynthesisContext,
20
23
  } from '@voctiv/agent-sdk';
21
24
 
22
25
  type SharedSession = MediaProviderShared & {
@@ -38,7 +41,8 @@ class EchoAsr implements ScriptAsrConnector {
38
41
  }
39
42
 
40
43
  send(_audio: ArrayBufferLike): void {
41
- // Forward PCM to your vendor here.
44
+ // Forward PCM (S16LE mono 16 kHz) to your vendor here.
45
+ void this.ctx;
42
46
  }
43
47
 
44
48
  speech(_active: boolean): void {}
@@ -71,7 +75,10 @@ class BatchOrStreamTts implements ScriptTtsConnector {
71
75
  return false;
72
76
  }
73
77
 
74
- async textToSpeechStream(rawtext: string): Promise<Readable> {
78
+ async textToSpeechStream(
79
+ rawtext: string,
80
+ _ctx?: ScriptTtsSynthesisContext,
81
+ ): Promise<Readable> {
75
82
  void this.ctx;
76
83
  void this.shared;
77
84
  // Replace with HTTP keep-alive synthesis that returns a PCM stream.
@@ -103,26 +110,3 @@ export const mediaProviders = defineMediaProviders({
103
110
  new BatchOrStreamTts(ctx, shared as SharedSession),
104
111
  },
105
112
  });
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
- });
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Campaign outbound that starts at INVITE (`outboundCallMode: 'from_invite'`).
3
+ *
4
+ * The host raises the script first, then dials the campaign number on the same
5
+ * `channel`. 1xx lands on `progress$`; a 4xx/5xx rejects `waitForAnswer()`.
6
+ * Gate the greeting on the answer so it does not play into ringback.
7
+ *
8
+ * `getScriptPhase` stays `'early'` for the whole live run. Read
9
+ * `channel.sip.isAnswered` for the live state. Billing stays on the 200 OK.
10
+ */
11
+ import { defineScript, getScriptPhase } from '@voctiv/agent-sdk';
12
+
13
+ export default defineScript(
14
+ async ({ channel, logger, context }) => {
15
+ if (getScriptPhase(context) === 'early') {
16
+ channel.sip.progress$.subscribe(({ statusCode }) => {
17
+ logger.log('progress', { statusCode });
18
+ });
19
+ try {
20
+ await channel.sip.waitForAnswer();
21
+ } catch (err) {
22
+ logger.warn('outbound failed', { err });
23
+ return;
24
+ }
25
+ }
26
+
27
+ await channel.audio.say('Hello!');
28
+ },
29
+ { outboundCallMode: 'from_invite' },
30
+ );
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Campaign outbound that starts on the 200 OK (`outboundCallMode: 'on_answer'`).
3
+ *
4
+ * This is the default: omit the second argument of `defineScript` and you get
5
+ * the same timing. The host dials first and holds the script until answer.
6
+ * Busy / no-answer / 4xx never reach this handler.
7
+ *
8
+ * Talk on `channel`. Do not `makeCall()` the campaign number — the host
9
+ * already did. Billing stays on the 200 OK.
10
+ */
11
+ import { defineScript, getScriptPhase } from '@voctiv/agent-sdk';
12
+
13
+ export default defineScript(async ({ channel, context }) => {
14
+ // Live outbound: always 'online'. Headless before_call / after_call_* still apply.
15
+ if (getScriptPhase(context) !== 'online') return;
16
+
17
+ await channel.audio.say('Hello!');
18
+ });
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Campaign outbound where the script opens the leg (`outboundCallMode: 'script_dial'`).
3
+ *
4
+ * The host does not send an INVITE. Phase is `'dialing'`; the starting `channel`
5
+ * can only dial. Conversation is on the channel `makeCall()` returns.
6
+ * `makeCall({})` uses the campaign msisdn + the call row's trunk.
7
+ *
8
+ * The first successful dial is the campaign row (result, `answer_date`, recording).
9
+ */
10
+ import { defineScript, getScriptPhase } from '@voctiv/agent-sdk';
11
+
12
+ export default defineScript(
13
+ async (ctx) => {
14
+ const phase = getScriptPhase(ctx.context);
15
+ const channel =
16
+ phase === 'dialing' ? await ctx.channel.sip.makeCall({}) : ctx.channel;
17
+ await channel.audio.say('Hello!');
18
+ },
19
+ { outboundCallMode: 'script_dial' },
20
+ );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voctiv/agent-sdk",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Voctiv TypeScript agent SDK: defineScript and platform types for the voice/dialog scripting runtime.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "",