@voctiv/agent-sdk 0.2.13 → 0.2.15

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 CHANGED
@@ -70,6 +70,48 @@ export default defineScript(async ({ channel, logger, context }) => {
70
70
  });
71
71
  ```
72
72
 
73
+ ## Examples
74
+
75
+ The [`examples/`](./examples/) folder contains copy-paste-ready scripts:
76
+
77
+ | Example | Description |
78
+ |---------|-------------|
79
+ | [outbound-with-recall.ts](./examples/outbound-with-recall.ts) | Outbound with `recallCount` / `recallDelay` (automatic redial on failure) |
80
+ | [recall-routing-by-attempt.ts](./examples/recall-routing-by-attempt.ts) | Online recall: branch on `context.attempt` (`getScriptPhase` → `'online'`) |
81
+ | [schedule-call-with-defaults.ts](./examples/schedule-call-with-defaults.ts) | `platform.call()` without explicit recall — CMS defaults from `context` |
82
+ | [after-call-continuation.ts](./examples/after-call-continuation.ts) | `onSuccessCall` / `onFailedCall` vs recall (mutually exclusive) |
83
+ | [read-recall-from-params.ts](./examples/read-recall-from-params.ts) | `parseRecallDelaySeconds()` / `parseRecallCount()` on legacy params |
84
+
85
+ ### Quick recall example
86
+
87
+ ```ts
88
+ import { defineScript } from '@voctiv/agent-sdk';
89
+
90
+ export default defineScript(async ({ channel, context, platform, logger }) => {
91
+ channel.sip.answer();
92
+
93
+ if ((context.attempt ?? 0) > 0) {
94
+ logger.log('Online recall attempt', { attempt: context.attempt });
95
+ await channel.audio.say('Sorry we missed you earlier. Trying again now.');
96
+ }
97
+
98
+ // Schedule first outbound with up to 3 retries, 5 min apart (no entryPoint — same defineScript runs each leg).
99
+ await platform.call(context.msisdn!, {
100
+ recallCount: context.recallCount ?? 3,
101
+ recallDelay: context.recallDelay ?? 300,
102
+ });
103
+ });
104
+ ```
105
+
106
+ Parse legacy time strings from params when needed:
107
+
108
+ ```ts
109
+ import { parseRecallDelaySeconds, parseRecallCount } from '@voctiv/agent-sdk';
110
+
111
+ const delaySec = parseRecallDelaySeconds(context.dialogParams?.recall_delay); // "00:05:00" → 300
112
+ const maxAttempts = parseRecallCount(context.dialogParams?.recall_count);
113
+ ```
114
+
73
115
  ## What The SDK Contains
74
116
 
75
117
  `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.
@@ -895,19 +937,74 @@ return {
895
937
  **Do not** return `env` from the script. Persist state via `context.env$`; the runtime snapshots it
896
938
  after completion into **`PersistedScriptResult.env`**.
897
939
 
898
- Use **`getScriptPhase(context)`** to branch on lifecycle (`online`, `messaging`, `recall`, etc.):
940
+ ## Script Lifecycle (`getScriptPhase`)
941
+
942
+ The host always runs your single **`defineScript` export** — there is no separate runtime entry per
943
+ name (unlike logic-executor Python `run_unit(entry_point=...)`). Use **`getScriptPhase(context)`**
944
+ to tell *why* the script is running now: live call, pre-call queue, post-call continuation,
945
+ messaging, etc.
946
+
947
+ **`context.headless === true` only means “no live SIP/media”.** It does **not** tell you whether
948
+ the run is before or after a call. For that, use `getScriptPhase`.
949
+
950
+ | Phase | `context.headless` | When | Typical `context.entryPoint` |
951
+ |-------|-------------------|------|--------------------------------|
952
+ | `before_call` | `true` | Dialog queue / bulk outbound **before** the first platform call (often schedules `platform.call`) | empty, `main`, `default` |
953
+ | `online` | `false` | Live SIP session (inbound, outbound, **and automatic recall redials**) | any (ignored for phase) |
954
+ | `after_call_success` | `true` | Headless run **after** a successful call | `on_success_call`, `after_call_success`, `on_done_call` |
955
+ | `after_call_failed` | `true` | Headless run **after** failed attempts (when `onFailedCall` was configured) | `on_failed_call`, `after_call_failed` |
956
+ | `messaging` | `true` | Inbound message triggered the run | `on_message_api_received`, or `context.inboundMessage` set |
957
+ | `recall` | `true` | Headless recall leg (legacy `entry_point`) | `on_recall`, `recall` |
958
+ | `headless_other` | `true` | Any other headless run with a custom `entry_point` | your custom name |
959
+
960
+ **Automatic recall** (`recallCount` + `recallDelay`) creates new **online** SIP legs with an
961
+ incremented `context.attempt`. Branch with `(context.attempt ?? 0) > 0`, **not** `phase === 'recall'`.
962
+ See [examples/recall-routing-by-attempt.ts](./examples/recall-routing-by-attempt.ts).
963
+
964
+ **After-call continuation** uses `onSuccessCall` / `onFailedCall` on `platform.call()`. When the call
965
+ ends, the host sets `dialog.params.entry_point` to that handler name and runs the same `defineScript`
966
+ headlessly. See [examples/after-call-continuation.ts](./examples/after-call-continuation.ts).
967
+
968
+ These two failure models are **mutually exclusive** on one scheduled outbound — see
969
+ [Failed outbound: automatic recall vs after-call continuation](#failed-outbound-automatic-recall-vs-after-call-continuation).
899
970
 
900
971
  ```ts
901
972
  import { defineScript, getScriptPhase } from '@voctiv/agent-sdk';
902
973
 
903
- export default defineScript(async ({ context }) => {
904
- switch (getScriptPhase(context)) {
905
- case 'online':
906
- // live call
907
- break;
974
+ export default defineScript(async ({ channel, context, logger, platform }) => {
975
+ const phase = getScriptPhase(context);
976
+
977
+ switch (phase) {
978
+ case 'before_call':
979
+ // Headless pre-call: queue worker, usually schedules outbound.
980
+ await platform.call(context.msisdn!, { recallCount: 3, recallDelay: 300 });
981
+ return { output: { phase } };
982
+
983
+ case 'after_call_success':
984
+ logger.log('Post-call success branch', { entryPoint: context.entryPoint });
985
+ return { output: { phase } };
986
+
987
+ case 'after_call_failed':
988
+ logger.log('Post-call failure branch', { entryPoint: context.entryPoint });
989
+ platform.dialog.result = 'done';
990
+ return { output: { phase } };
991
+
908
992
  case 'messaging':
909
- // inbound message handling
910
- break;
993
+ logger.log('Inbound message', { text: context.inboundMessage?.payload });
994
+ return { output: { phase } };
995
+
996
+ case 'online':
997
+ channel.sip.answer();
998
+ if ((context.attempt ?? 0) > 0) {
999
+ logger.log('Online recall leg', { attempt: context.attempt });
1000
+ }
1001
+ await channel.audio.say('Hello.');
1002
+ return;
1003
+
1004
+ default:
1005
+ // headless_other, recall (headless), etc.
1006
+ logger.log('Other headless run', { phase, entryPoint: context.entryPoint });
1007
+ return { output: { phase } };
911
1008
  }
912
1009
  });
913
1010
  ```
@@ -956,23 +1053,10 @@ By default, the platform schedules the call for immediate processing. Use `date`
956
1053
  ```ts
957
1054
  await platform.call('+12025551234', {
958
1055
  date: new Date(Date.now() + 15 * 60_000),
959
- entryPoint: 'on_callback',
960
1056
  });
961
1057
  ```
962
1058
 
963
- `entryPoint` is passed to the script when the scheduled call starts. Use it to route the callback into a specific branch:
964
-
965
- ```ts
966
- export default defineScript(async ({ context, channel }) => {
967
- if (context.entryPoint === 'on_callback') {
968
- channel.sip.answer();
969
- await channel.audio.say('Hello, this is your scheduled callback.');
970
- return;
971
- }
972
-
973
- await channel.audio.say('I will call you back in fifteen minutes.');
974
- });
975
- ```
1059
+ When the scheduled call connects, the host runs your **`defineScript` export** again. Branch inside that handler if needed (there is no separate runtime entry per name, unlike logic-executor Python `run_unit(entry_point=...)`).
976
1060
 
977
1061
  Use `dateEnd` to define the latest time when the call is still useful. If the platform cannot place the call before that deadline, it can skip the attempt.
978
1062
 
@@ -980,33 +1064,90 @@ Use `dateEnd` to define the latest time when the call is still useful. If the pl
980
1064
  await platform.call('+12025551234', {
981
1065
  date: new Date('2026-04-29T10:00:00Z'),
982
1066
  dateEnd: new Date('2026-04-29T10:30:00Z'),
983
- entryPoint: 'on_reminder',
984
1067
  });
985
1068
  ```
986
1069
 
987
- Retries are controlled with `recallCount` and `recallDelay`:
1070
+ Retries are controlled with `recallCount` and `recallDelay` (delay is always **seconds** in SDK options):
988
1071
 
989
1072
  ```ts
990
1073
  await platform.call('+12025551234', {
991
- entryPoint: 'on_follow_up',
992
1074
  recallCount: 3,
993
- recallDelay: 300,
1075
+ recallDelay: 300, // 5 minutes between failed outbound attempts
1076
+ });
1077
+ ```
1078
+
1079
+ This schedules automatic redials: on each **failed outbound** the host creates a new platform call
1080
+ with `date_added = now + recallDelay`. The dialer runs the script again with an incremented
1081
+ `context.attempt`. See [examples/outbound-with-recall.ts](./examples/outbound-with-recall.ts).
1082
+
1083
+ ### Failed outbound: automatic recall vs after-call continuation
1084
+
1085
+ After a failed **outbound** call the platform must choose **one** failure-handling strategy.
1086
+ `recallCount` + `recallDelay` and `onFailedCall` answer the same question in different ways, so
1087
+ they are **mutually exclusive** on `platform.call()` (logic-executor `nn.call` parity).
1088
+
1089
+ | Strategy | `platform.call()` options | What happens on failure | Next script run |
1090
+ |----------|---------------------------|-------------------------|-----------------|
1091
+ | **Automatic recall** | `recallCount` + `recallDelay` (both required on the `call` row) | Host schedules another outbound `call` after `recallDelay`; bumps `dialog.params.attempt` | **Online** SIP leg — same `defineScript`, branch on `context.attempt` |
1092
+ | **After-call continuation** | `onFailedCall` (and optionally `onSuccessCall`) | Host sets `dialog.params.entry_point` to the handler name and re-queues the dialog | **Headless** run — `getScriptPhase(context)` → `after_call_failed` |
1093
+
1094
+ **Why not both?** Recall is fully platform-driven (dialer redials without running your script between
1095
+ attempts). `onFailedCall` is script-driven (your handler decides logging, CRM, manual retry, etc.).
1096
+ If both were written to `call.params`, shutdown would be ambiguous. This host therefore **keeps
1097
+ `onFailedCall` and drops recall** at schedule time so the outbound still starts and the after-call
1098
+ branch runs on failure. (If both somehow land on an existing `call.params` row, recall still wins
1099
+ at shutdown — avoid writing both.)
1100
+
1101
+ **Do not** pass `onFailedCall` together with `recallCount` and `recallDelay` in the same
1102
+ `platform.call()` invocation. If both are present (script options, dialog params, or CMS
1103
+ defaults), the host **keeps `onFailedCall` and drops recall** so the call still schedules —
1104
+ after-call continuation wins over automatic redial. Prefer configuring only one strategy
1105
+ explicitly.
1106
+
1107
+ **Host default resolution:** when you omit recall options, the host may default them from
1108
+ `context.recallCount` / `context.recallDelay` (CMS contact-rules). That auto-fill applies only when
1109
+ the script did **not** pass explicit `onFailedCall` in `platform.call()` options.
1110
+ `onFailedCall` / `onSuccessCall` are **never** invented from `dialog.params` or Omni
1111
+ `scheduleOutbound` defaults — they are script kwargs only (LE `nn.call` parity). Stale
1112
+ `on_failed_call` left in dialog params must not block CMS recall.
1113
+
1114
+ Diagram-style legacy outbound (Megafon converter) typically uses `onFailedCall` plus
1115
+ `on_failed_call_system` (sleep + call the main block again) — **not** CMS automatic recall.
1116
+ See [examples/after-call-continuation.ts](./examples/after-call-continuation.ts).
1117
+
1118
+ Use either automatic recall **or** offline `onFailedCall` continuation — not both on one scheduled
1119
+ outbound leg.
1120
+
1121
+ Branch inside the script on recall attempts (`context.attempt`, not a separate entry function):
1122
+
1123
+ ```ts
1124
+ import { defineScript } from '@voctiv/agent-sdk';
1125
+
1126
+ export default defineScript(async ({ channel, context, logger }) => {
1127
+ channel.sip.answer();
1128
+
1129
+ if ((context.attempt ?? 0) > 0) {
1130
+ logger.log('Recall leg', { attempt: context.attempt });
1131
+ await channel.audio.say('Follow-up call. Please hold.');
1132
+ }
994
1133
  });
995
1134
  ```
996
1135
 
997
- This means the platform may retry up to three times, waiting about five minutes between attempts.
1136
+ See [examples/recall-routing-by-attempt.ts](./examples/recall-routing-by-attempt.ts).
998
1137
 
999
- When you omit these options, the host fills defaults from `context.recallCount` / `context.recallDelay`
1000
- (effective values for the current dialog). Those in turn fall back to CMS agent contact-rules
1138
+ When you omit recall options, the host fills them from `context.recallCount` / `context.recallDelay`
1139
+ (effective values for the current dialog) **only when `onFailedCall` is not configured** for that
1140
+ scheduled call. Those values fall back to CMS agent contact-rules
1001
1141
  (`context.agent?.recallCount` / `context.agent?.recallDelay`, legacy `nn.get_recall_count()` /
1002
- `nn.get_recall_delay()`).
1142
+ `nn.get_recall_delay()`). See [Failed outbound: automatic recall vs after-call continuation](#failed-outbound-automatic-recall-vs-after-call-continuation).
1003
1143
 
1004
1144
  Other scheduling options:
1005
1145
 
1006
1146
  - `priority`: higher-priority calls can be processed earlier by the dialer.
1007
1147
  - `timezone`: timezone offset used by the platform when interpreting scheduled dates.
1008
- - `onSuccessCall`: entry point to use after a successful call.
1009
- - `onFailedCall`: entry point to use after failed attempts.
1148
+ - `onSuccessCall`: headless handler name after a successful call (e.g. `'on_success_call'` → `getScriptPhase` `'after_call_success'`).
1149
+ - `onFailedCall`: headless handler name after failed attempts (mutually exclusive with recall).
1150
+ - `entryPoint` (optional): stored as `entry_point` in call params for LE DB compatibility. The host still runs the same `defineScript` export; use `context.entryPoint` only if **you** branch on it inside the handler.
1010
1151
  - `protoAdditional`: extra protocol-level parameters, such as SIP headers expected by your telephony setup.
1011
1152
 
1012
1153
  ### Messaging
@@ -1025,9 +1166,14 @@ await platform.messaging.send({
1025
1166
 
1026
1167
  Offline, or headless, sessions run a script without a live SIP call, WebSocket audio stream, RTP pipeline, ASR, or TTS playback. They are used for platform-driven background logic, queued dialog processing, and messaging events.
1027
1168
 
1028
- The script entry point is still the same `defineScript()` handler. Detect this mode with `context.headless`:
1169
+ The script entry point is still the same `defineScript()` handler. Detect offline mode with
1170
+ `context.headless`, then use **`getScriptPhase(context)`** to distinguish pre-call queue runs
1171
+ (`before_call`) from post-call continuations (`after_call_success` / `after_call_failed`). See
1172
+ [Script Lifecycle (`getScriptPhase`)](#script-lifecycle-getscriptphase).
1029
1173
 
1030
1174
  ```ts
1175
+ import { defineScript, getScriptPhase } from '@voctiv/agent-sdk';
1176
+
1031
1177
  export default defineScript(async ({ channel, context, logger, platform }) => {
1032
1178
  if (!context.headless) {
1033
1179
  channel.sip.answer();
@@ -1035,12 +1181,24 @@ export default defineScript(async ({ channel, context, logger, platform }) => {
1035
1181
  return;
1036
1182
  }
1037
1183
 
1184
+ const phase = getScriptPhase(context);
1038
1185
  logger.log('Running offline logic', {
1186
+ phase,
1039
1187
  dialogUuid: context.dialogUuid,
1040
1188
  entryPoint: context.entryPoint,
1041
1189
  });
1042
1190
 
1043
- // Offline logic usually works with text, params, env, NLU, LLM, and platform APIs.
1191
+ if (phase === 'before_call') {
1192
+ await platform.call(context.msisdn!);
1193
+ return;
1194
+ }
1195
+
1196
+ if (phase === 'after_call_success' || phase === 'after_call_failed') {
1197
+ // Post-call headless branch — see examples/after-call-continuation.ts
1198
+ return { output: { phase } };
1199
+ }
1200
+
1201
+ // messaging, headless_other, etc.
1044
1202
  });
1045
1203
  ```
1046
1204
 
@@ -1143,9 +1301,7 @@ export default defineScript(async ({ channel, context, platform }) => {
1143
1301
  const text = String(context.inboundMessage?.payload?.text ?? '');
1144
1302
 
1145
1303
  if (text.includes('call me')) {
1146
- await platform.call(context.msisdn, {
1147
- entryPoint: 'on_callback',
1148
- });
1304
+ await platform.call(context.msisdn);
1149
1305
  }
1150
1306
 
1151
1307
  return { output: { handledOffline: true } };
@@ -1182,19 +1338,25 @@ Recall behavior uses **two layers** on `context`:
1182
1338
  | Layer | Fields | Source | Use when |
1183
1339
  |-------|--------|--------|----------|
1184
1340
  | Agent defaults | `context.agent?.recallCount`, `context.agent?.recallDelay` | CMS contact-rules (`agent.recall_count`, `agent.delay` → seconds) | Compare with CMS settings; legacy `nn.get_recall_count()` / `get_recall_delay()` parity |
1185
- | Effective for this run | `context.recallCount`, `context.recallDelay` | `dialog.params` / `call.params`, then agent defaults | Schedule outbound calls, recall routing logic |
1341
+ | Effective for this run | `context.recallCount`, `context.recallDelay` | `dialog.params` / `call.params`, then agent defaults | Read in script; pass explicitly to `platform.call()` when using **automatic recall** |
1186
1342
 
1187
1343
  Precedence for effective values: **dialog/call params** (`recall_count`, `recall_delay`) **>** agent CMS defaults.
1188
1344
 
1345
+ **Important:** CMS/effective recall on `context` does **not** mean every `platform.call()` gets
1346
+ automatic recall. The host copies recall onto the scheduled `call` row only when you omit recall
1347
+ options **and** `onFailedCall` is not configured (see
1348
+ [Failed outbound: automatic recall vs after-call continuation](#failed-outbound-automatic-recall-vs-after-call-continuation)).
1349
+ Agents with both CMS contact-rules and diagram `on_failed_call` handlers use the after-call path;
1350
+ recall fields on `context` are informational unless your script passes them explicitly.
1351
+
1189
1352
  `context.attempt` is the current recall attempt counter from `dialog.params.attempt` (starts at 0).
1190
1353
  `context.entryPoint` is the routing branch for this run (e.g. after a failed call).
1191
1354
 
1192
1355
  ```ts
1193
1356
  // Use effective values when scheduling the next outbound leg
1194
- await context.platform?.call?.(msisdn, {
1357
+ await platform.call(context.msisdn!, {
1195
1358
  recallCount: context.recallCount,
1196
1359
  recallDelay: context.recallDelay,
1197
- entryPoint: 'on_follow_up',
1198
1360
  });
1199
1361
 
1200
1362
  // Log CMS defaults vs per-dialog override
@@ -1235,8 +1397,8 @@ Important fields:
1235
1397
  - `context.flag`: business flag.
1236
1398
  - `context.initialData`: shallow snapshot of params at script start.
1237
1399
  - `context.dialogParams`: live param map for the run.
1238
- - `context.entryPoint`: current routing entry point.
1239
- - `context.attempt`: current recall attempt number (`dialog.params.attempt`).
1400
+ - `context.entryPoint`: current routing entry point (see [Script Lifecycle](#script-lifecycle-getscriptphase)).
1401
+ - `context.attempt`: current recall attempt number (`dialog.params.attempt`; use with `phase === 'online'`).
1240
1402
  - `context.recallCount` / `context.recallDelay`: effective recall settings for this dialog/call.
1241
1403
  - `context.agent?.recallCount` / `context.agent?.recallDelay`: CMS agent defaults (immutable snapshot).
1242
1404
  - `context.headless`: true for offline/queue/messaging sessions without a real media channel.
@@ -1282,7 +1444,10 @@ Headless channels are for offline, queue, or messaging sessions:
1282
1444
  - `createAsr()` returns an inert handle.
1283
1445
  - LLM, NLU, messaging, platform calls, dialog state, and `env$` still work.
1284
1446
 
1285
- Use `context.headless` to branch when a script must behave differently without a real media channel. See [Offline / Headless Logic](#offline--headless-logic) for details and examples.
1447
+ Use `context.headless` plus `getScriptPhase(context)` when a script must behave differently without a
1448
+ real media channel or across pre-call / post-call headless runs. See
1449
+ [Offline / Headless Logic](#offline--headless-logic) and
1450
+ [Script Lifecycle (`getScriptPhase`)](#script-lifecycle-getscriptphase).
1286
1451
 
1287
1452
  ## Text Input For Tests
1288
1453
 
package/dist/index.d.ts CHANGED
@@ -33,6 +33,7 @@ export type { ScriptDialogContext, ScriptPhase, ScriptRunTime, ScriptResult, Per
33
33
  export { getScriptPhase } from './types/script-context';
34
34
  export type { NluScriptApi, PlatformApi, DialogApi, ScheduleCallOptions, SendMessageOptions, InboundMessage, MessagingApi, } from './types/platform';
35
35
  export type { ScriptLogger } from './types/logger';
36
+ export { TranscriptionRole } from './types/logger';
36
37
  export type { MediaChannel, ChannelAudio, ChannelEvents, } from './types/media-channel';
37
38
  export type { ChannelLlm, LlmOptions, LlmStreamChunk, ExtractOptions, PersistentLlmStreamHandle, } from './types/llm';
38
39
  export type { ChannelSip, SipState, SipProgressEvent, SipInviteHeaders, ParsedSdpDetails, } from './types/sip';
@@ -44,4 +45,5 @@ export { LEGACY_PHRASE_RECORD_BRAND, isLegacyPhraseRecord, } from './types/legac
44
45
  export type { TextInput } from './types/text-input';
45
46
  export type { DtmfEvent, SipInfo, SipSignal, DataMessage, } from './types/events';
46
47
  export type { NluExtractOptions, NluInferResult } from './types/nlu';
48
+ export { parseRecallCount, parseRecallDelaySeconds } from './recall-utils';
47
49
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE/D,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;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,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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE/D,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,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
@@ -29,12 +29,17 @@
29
29
  * and live SIP INFO ({@link import('./types/events').SipInfo} on `sipInfo$`). See **`README.md`** → SIP Signalling Metadata.
30
30
  */
31
31
  Object.defineProperty(exports, "__esModule", { value: true });
32
- exports.isLegacyPhraseRecord = exports.LEGACY_PHRASE_RECORD_BRAND = exports.getScriptPhase = exports.defineScript = void 0;
32
+ exports.parseRecallDelaySeconds = exports.parseRecallCount = exports.isLegacyPhraseRecord = exports.LEGACY_PHRASE_RECORD_BRAND = exports.TranscriptionRole = exports.getScriptPhase = exports.defineScript = void 0;
33
33
  var define_script_1 = require("./define-script");
34
34
  Object.defineProperty(exports, "defineScript", { enumerable: true, get: function () { return define_script_1.defineScript; } });
35
35
  var script_context_1 = require("./types/script-context");
36
36
  Object.defineProperty(exports, "getScriptPhase", { enumerable: true, get: function () { return script_context_1.getScriptPhase; } });
37
+ var logger_1 = require("./types/logger");
38
+ Object.defineProperty(exports, "TranscriptionRole", { enumerable: true, get: function () { return logger_1.TranscriptionRole; } });
37
39
  var legacy_phrase_1 = require("./types/legacy-phrase");
38
40
  Object.defineProperty(exports, "LEGACY_PHRASE_RECORD_BRAND", { enumerable: true, get: function () { return legacy_phrase_1.LEGACY_PHRASE_RECORD_BRAND; } });
39
41
  Object.defineProperty(exports, "isLegacyPhraseRecord", { enumerable: true, get: function () { return legacy_phrase_1.isLegacyPhraseRecord; } });
42
+ var recall_utils_1 = require("./recall-utils");
43
+ Object.defineProperty(exports, "parseRecallCount", { enumerable: true, get: function () { return recall_utils_1.parseRecallCount; } });
44
+ Object.defineProperty(exports, "parseRecallDelaySeconds", { enumerable: true, get: function () { return recall_utils_1.parseRecallDelaySeconds; } });
40
45
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;;;AAEH,iDAA+C;AAAtC,6GAAA,YAAY,OAAA;AAerB,yDAAwD;AAA/C,gHAAA,cAAc,OAAA;AA4CvB,uDAG+B;AAF7B,2HAAA,0BAA0B,OAAA;AAC1B,qHAAA,oBAAoB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;;;AAEH,iDAA+C;AAAtC,6GAAA,YAAY,OAAA;AAerB,yDAAwD;AAA/C,gHAAA,cAAc,OAAA;AAavB,yCAAmD;AAA1C,2GAAA,iBAAiB,OAAA;AAgC1B,uDAG+B;AAF7B,2HAAA,0BAA0B,OAAA;AAC1B,qHAAA,oBAAoB,OAAA;AAUtB,+CAA2E;AAAlE,gHAAA,gBAAgB,OAAA;AAAE,uHAAA,uBAAuB,OAAA"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Parse recall delay to seconds — parity with logic-executor `agent.delay` / `recall_delay`
3
+ * in call params (`HH:mm:ss`, integer seconds).
4
+ */
5
+ export declare function parseRecallDelaySeconds(value: unknown): number | undefined;
6
+ /** Parse recall attempt limit from call/dialog params. */
7
+ export declare function parseRecallCount(value: unknown): number | undefined;
8
+ //# sourceMappingURL=recall-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recall-utils.d.ts","sourceRoot":"","sources":["../src/recall-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CA4B1E;AAED,0DAA0D;AAC1D,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAWnE"}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseRecallDelaySeconds = parseRecallDelaySeconds;
4
+ exports.parseRecallCount = parseRecallCount;
5
+ /**
6
+ * Parse recall delay to seconds — parity with logic-executor `agent.delay` / `recall_delay`
7
+ * in call params (`HH:mm:ss`, integer seconds).
8
+ */
9
+ function parseRecallDelaySeconds(value) {
10
+ if (value == null)
11
+ return undefined;
12
+ if (typeof value === 'number' && Number.isFinite(value) && value >= 0) {
13
+ return Math.floor(value);
14
+ }
15
+ if (typeof value !== 'string')
16
+ return undefined;
17
+ const trimmed = value.trim();
18
+ if (!trimmed)
19
+ return undefined;
20
+ if (/^\d+$/.test(trimmed)) {
21
+ return parseInt(trimmed, 10);
22
+ }
23
+ const match = trimmed.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?$/);
24
+ if (!match)
25
+ return undefined;
26
+ const hours = parseInt(match[1], 10);
27
+ const minutes = parseInt(match[2], 10);
28
+ const seconds = match[3] ? parseInt(match[3], 10) : 0;
29
+ if (!Number.isFinite(hours) ||
30
+ !Number.isFinite(minutes) ||
31
+ !Number.isFinite(seconds)) {
32
+ return undefined;
33
+ }
34
+ return hours * 3600 + minutes * 60 + seconds;
35
+ }
36
+ /** Parse recall attempt limit from call/dialog params. */
37
+ function parseRecallCount(value) {
38
+ if (typeof value === 'number' && Number.isFinite(value) && value >= 0) {
39
+ return Math.floor(value);
40
+ }
41
+ if (typeof value === 'string') {
42
+ const trimmed = value.trim();
43
+ if (!trimmed)
44
+ return undefined;
45
+ const n = parseInt(trimmed, 10);
46
+ if (Number.isFinite(n) && n >= 0)
47
+ return n;
48
+ }
49
+ return undefined;
50
+ }
51
+ //# sourceMappingURL=recall-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recall-utils.js","sourceRoot":"","sources":["../src/recall-utils.ts"],"names":[],"mappings":";;AAIA,0DA4BC;AAGD,4CAWC;AA9CD;;;GAGG;AACH,SAAgB,uBAAuB,CAAC,KAAc;IACpD,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,SAAS,CAAC;IACpC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QACtE,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAEhD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAE/B,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1B,OAAO,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;IAChE,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAE7B,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtD,IACE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QACvB,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;QACzB,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EACzB,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,KAAK,GAAG,IAAI,GAAG,OAAO,GAAG,EAAE,GAAG,OAAO,CAAC;AAC/C,CAAC;AAED,0DAA0D;AAC1D,SAAgB,gBAAgB,CAAC,KAAc;IAC7C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QACtE,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,IAAI,CAAC,OAAO;YAAE,OAAO,SAAS,CAAC;QAC/B,MAAM,CAAC,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAChC,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -1,3 +1,13 @@
1
+ /**
2
+ * Role for {@link ScriptLogger.transcript} lines that land in the CMS call transcript.
3
+ *
4
+ * Wire values stay `'user'` / `'agent'` for dialog-consumer mapping
5
+ * (`human_phrase` / `agent_phrase`).
6
+ */
7
+ export declare enum TranscriptionRole {
8
+ User = "user",
9
+ Agent = "agent"
10
+ }
1
11
  /**
2
12
  * Structured logger available to scripts.
3
13
  *
@@ -15,6 +25,26 @@ export interface ScriptLogger {
15
25
  error(message: string, data?: Record<string, unknown>): void;
16
26
  /** Debug-level log entry; intended for process/debug stream output rather than legacy DB stats. */
17
27
  debug(message: string, data?: Record<string, unknown>): void;
28
+ /**
29
+ * Write a phrase into the CMS call transcript.
30
+ *
31
+ * In Voctiv legacy mode:
32
+ * - {@link TranscriptionRole.User} → `nv.listen` / `stop` in `dialog_stats` (Mongo `human_phrase`)
33
+ * - {@link TranscriptionRole.Agent} → `nv.synthesize` (Mongo `agent_phrase`)
34
+ *
35
+ * Also logs as `USER: …` / `AGENT: …`. Empty / whitespace-only text is ignored.
36
+ *
37
+ * Does **not** mutate the script's `call_transcript` output entity — scripts
38
+ * that keep their own transcript buffer should still update it explicitly.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * import { TranscriptionRole } from '@lib/scripting-sdk';
43
+ * logger.transcript(TranscriptionRole.User, userText);
44
+ * logger.transcript(TranscriptionRole.Agent, '¿Hola?');
45
+ * ```
46
+ */
47
+ transcript(role: TranscriptionRole, message: string): void;
18
48
  /**
19
49
  * Enable real-time log streaming to a remote debug endpoint.
20
50
  * Opens a Socket.IO connection from this API pod to the debug server.
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/types/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,4BAA4B;IAC5B,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC3D,+BAA+B;IAC/B,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5D,6BAA6B;IAC7B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,mGAAmG;IACnG,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAE7D;;;;;;OAMG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpC,kEAAkE;IAClE,YAAY,IAAI,IAAI,CAAC;IAErB;;;;;;;;;OASG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9E"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/types/logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,oBAAY,iBAAiB;IAC3B,IAAI,SAAS;IACb,KAAK,UAAU;CAChB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,4BAA4B;IAC5B,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC3D,+BAA+B;IAC/B,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5D,6BAA6B;IAC7B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,mGAAmG;IACnG,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAE7D;;;;;;;;;;;;;;;;;;OAkBG;IACH,UAAU,CAAC,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3D;;;;;;OAMG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpC,kEAAkE;IAClE,YAAY,IAAI,IAAI,CAAC;IAErB;;;;;;;;;OASG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9E"}
@@ -1,3 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TranscriptionRole = void 0;
4
+ /**
5
+ * Role for {@link ScriptLogger.transcript} lines that land in the CMS call transcript.
6
+ *
7
+ * Wire values stay `'user'` / `'agent'` for dialog-consumer mapping
8
+ * (`human_phrase` / `agent_phrase`).
9
+ */
10
+ var TranscriptionRole;
11
+ (function (TranscriptionRole) {
12
+ TranscriptionRole["User"] = "user";
13
+ TranscriptionRole["Agent"] = "agent";
14
+ })(TranscriptionRole || (exports.TranscriptionRole = TranscriptionRole = {}));
3
15
  //# sourceMappingURL=logger.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/types/logger.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/types/logger.ts"],"names":[],"mappings":";;;AAAA;;;;;GAKG;AACH,IAAY,iBAGX;AAHD,WAAY,iBAAiB;IAC3B,kCAAa,CAAA;IACb,oCAAe,CAAA;AACjB,CAAC,EAHW,iBAAiB,iCAAjB,iBAAiB,QAG5B"}
@@ -6,26 +6,63 @@
6
6
  * `intents_exclude`) are mapped to `entities_policy` / `intents_policy`.
7
7
  */
8
8
  export interface NluExtractOptions {
9
- /** Include only these entity types (e.g. `"date"`, `"phone"`); forwarded as `entities`. */
9
+ /**
10
+ * Entity names to search — always forwarded to nlu-engine as a JSON array.
11
+ * Prefer `['confirmation', 'check']`; comma-separated string is accepted for LE compat.
12
+ */
10
13
  entities?: string | string[] | null;
11
14
  /** Legacy compatibility field; mapped to exclude policy on nlu-engine. */
12
15
  entities_exclude?: string | string[] | null;
13
- /** Include only these intent names; forwarded as `intents`. */
16
+ /**
17
+ * Intent names to search — always forwarded to nlu-engine as a JSON array.
18
+ * Prefer `['balance_check']`; comma-separated string is accepted for LE compat.
19
+ */
14
20
  intents?: string | string[] | null;
15
21
  /** Legacy compatibility field; mapped to exclude policy on nlu-engine. */
16
22
  intents_exclude?: string | string[] | null;
17
23
  /**
18
24
  * Additional context for disambiguation.
19
25
  *
20
- * Objects and arrays are JSON-stringified before sending. Omitted when not set
21
- * (logic-executor default).
26
+ * Objects and arrays are JSON-stringified before sending. When omitted, the runtime
27
+ * uses dialog `flag` (logic-executor scripts usually pass the same value explicitly).
22
28
  */
23
29
  context?: string | unknown[] | Record<string, unknown> | null;
30
+ /**
31
+ * BCP-47 / LE language for this call only (e.g. `es-ES`).
32
+ * Default NLU language comes from the LE agent (`_nlu.language`), not `context.lang`.
33
+ */
34
+ language?: string;
35
+ /** Alias for {@link language}. */
36
+ lang?: string;
24
37
  /** Forwarded as `use_neuro_api`; nlu-engine may call remote NLU API when true. */
25
38
  use_neuro_api?: boolean;
26
39
  /** Forwarded as `use_synonyms`; enables synonym expansion in nlu-engine. */
27
40
  use_synonyms?: boolean;
28
41
  }
29
- /** Raw parsed JSON response from nlu-engine `/nlu_engine` endpoint. */
30
- export type NluInferResult = Record<string, unknown>;
42
+ export interface NluProbabilityValue {
43
+ value: unknown;
44
+ probability: number;
45
+ }
46
+ /**
47
+ * logic-executor `NeuroNluRecognitionResult` method surface returned from
48
+ * `platform.nlu.extract()` / `extract$()`.
49
+ */
50
+ export interface NluInferResult {
51
+ utterance(): string | null;
52
+ context(): unknown;
53
+ entity(entityName: string): unknown;
54
+ intent(intentName: string): unknown;
55
+ has_entity(entityName: string): boolean;
56
+ has_intent(intentName: string): boolean;
57
+ has_entities(): boolean;
58
+ has_intents(): boolean;
59
+ entities(): Record<string, unknown>;
60
+ intents(): Record<string, unknown>;
61
+ entity_with_probability(entityName: string): NluProbabilityValue | null;
62
+ intent_with_probability(intentName: string): NluProbabilityValue | null;
63
+ entities_with_probability(): Record<string, NluProbabilityValue>;
64
+ intents_with_probability(): Record<string, NluProbabilityValue>;
65
+ dump(): Record<string, unknown>;
66
+ dump_json(): string;
67
+ }
31
68
  //# sourceMappingURL=nlu.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"nlu.d.ts","sourceRoot":"","sources":["../../src/types/nlu.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,2FAA2F;IAC3F,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IACpC,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IAC5C,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IACnC,0EAA0E;IAC1E,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IAC3C;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9D,kFAAkF;IAClF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,4EAA4E;IAC5E,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,uEAAuE;AACvE,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC"}
1
+ {"version":3,"file":"nlu.d.ts","sourceRoot":"","sources":["../../src/types/nlu.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IACpC,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IAC5C;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IACnC,0EAA0E;IAC1E,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IAC3C;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9D;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kFAAkF;IAClF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,4EAA4E;IAC5E,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,IAAI,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,IAAI,OAAO,CAAC;IACnB,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;IACpC,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;IACpC,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;IACxC,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;IACxC,YAAY,IAAI,OAAO,CAAC;IACxB,WAAW,IAAI,OAAO,CAAC;IACvB,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI,CAAC;IACxE,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI,CAAC;IACxE,yBAAyB,IAAI,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IACjE,wBAAwB,IAAI,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAChE,IAAI,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,SAAS,IAAI,MAAM,CAAC;CACrB"}
@@ -18,13 +18,13 @@ export interface NluScriptApi {
18
18
  * Extract intents and entities from one user utterance.
19
19
  *
20
20
  * The runtime sends a logic-executor-compatible recognition request to
21
- * nlu-engine (`/nlu_engine?agent_id=…`). Context is included only when
22
- * `options.context` is set explicitly.
21
+ * nlu-engine (`/nlu_engine?agent_id=…`). Pass `options.context` explicitly when
22
+ * needed (same as LE `nlu.extract(..., context=flag)`).
23
23
  *
24
24
  * @param utterance - User input text to analyze.
25
25
  * @param options - Optional NLU filters and flags. `entities`, `intents`,
26
- * `use_neuro_api`, and `use_synonyms` are forwarded by ScriptEngine.
27
- * @returns Raw parsed JSON response from nlu-engine (recognition result dump).
26
+ * `language` / `lang`, `use_neuro_api`, and `use_synonyms` are forwarded by ScriptEngine.
27
+ * @returns logic-executor-compatible {@link NluInferResult} (`entity()`, `has_entities()`, ).
28
28
  */
29
29
  extract(utterance: string, options?: NluExtractOptions): Promise<NluInferResult>;
30
30
  /**
@@ -42,9 +42,12 @@ export interface ScheduleCallOptions {
42
42
  /** Deadline — don't call after this time. */
43
43
  dateEnd?: string | Date;
44
44
  /**
45
- * Entry point to pass to the script when the call connects.
45
+ * Optional label stored in call params as `entry_point` (LE DB compatibility).
46
46
  *
47
- * Stored in the created call params as `entry_point`.
47
+ * The host always runs your single `defineScript` export — it does **not** invoke a
48
+ * separate function by this name (unlike logic-executor Python `run_unit(entry_point=...)`).
49
+ * Use {@link import('./script-context').ScriptDialogContext.entryPoint} inside the handler
50
+ * if you branch manually (e.g. headless after-call via {@link getScriptPhase}).
48
51
  */
49
52
  entryPoint?: string;
50
53
  /**
@@ -61,18 +64,38 @@ export interface ScheduleCallOptions {
61
64
  */
62
65
  channel?: string | number;
63
66
  /**
64
- * How many times to retry on failure. Stored as `recall_count` in call params.
65
- * When omitted, the host defaults from {@link import('./script-context').ScriptDialogContext.recallCount}.
67
+ * Max failed-call retries. Stored as `recall_count` in call params.
68
+ * When omitted, the host defaults from {@link import('./script-context').ScriptDialogContext.recallCount}
69
+ * only if {@link onFailedCall} is not configured for this scheduled call.
70
+ *
71
+ * Activates **automatic recall**: on each failed outbound the dialer schedules another call after
72
+ * {@link recallDelay} and increments `context.attempt`. Mutually exclusive with {@link onFailedCall}
73
+ * — if both are present, the host keeps {@link onFailedCall} and drops recall. Requires both
74
+ * `recallCount` and `recallDelay` on the `call` row when used alone.
66
75
  */
67
76
  recallCount?: number;
68
77
  /**
69
- * Delay in seconds between retries. Stored as `recall_delay` in call params.
70
- * When omitted, the host defaults from {@link import('./script-context').ScriptDialogContext.recallDelay}.
78
+ * Delay before the next recall attempt, in **seconds**.
79
+ * Stored as `recall_delay` in call params (numeric seconds from SDK; LE may also
80
+ * use `HH:MM:SS` strings in legacy rows — the host normalizes both on schedule).
81
+ *
82
+ * When omitted, the host defaults from {@link import('./script-context').ScriptDialogContext.recallDelay}
83
+ * only if {@link onFailedCall} is not configured for this scheduled call.
84
+ *
85
+ * Mutually exclusive with {@link onFailedCall}.
71
86
  */
72
87
  recallDelay?: number;
73
88
  /** Entry point to use after a successful call. Stored as `on_success_call`. */
74
89
  onSuccessCall?: string;
75
- /** Entry point to use after a failed call. Stored as `on_failed_call`. */
90
+ /**
91
+ * Headless handler after a failed outbound. Stored as `on_failed_call`.
92
+ *
93
+ * Activates **after-call continuation**: the host sets `dialog.params.entry_point` and re-runs this
94
+ * script with `getScriptPhase` → `after_call_failed`. Mutually exclusive with automatic recall
95
+ * ({@link recallCount} + {@link recallDelay}) on the same `platform.call()`. If both are present,
96
+ * the host keeps this option and drops recall. When set (including via Omni `scheduleOutbound`
97
+ * defaults), CMS recall is not auto-copied onto the `call` row.
98
+ */
76
99
  onFailedCall?: string;
77
100
  /** Call priority (higher = processed sooner by dialer). */
78
101
  priority?: number;
@@ -100,7 +123,7 @@ export interface ScheduleCallOptions {
100
123
  * are logged. There is no awaitable setter, so do not use it for transactional flow.
101
124
  */
102
125
  export interface DialogApi {
103
- /** Current script entry point (e.g. `"on_recall"`). Set to change routing for the next call. */
126
+ /** Value from `dialog.params.entry_point` for branching inside `defineScript`, not a separate runtime entry. */
104
127
  entryPoint: string | undefined;
105
128
  /** Dialog outcome (e.g. `"done"`, `"busy"`, `"no_answer"`). Set to finalize dialog. */
106
129
  result: string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/types/platform.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/types/platform.ts"],"names":[],"mappings":"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"}
@@ -145,7 +145,7 @@ export interface ScriptDialogContext {
145
145
  * {@link import('./mixer').PlayOptions} to select **`key_storage.name`** when LE credential maps exist.
146
146
  */
147
147
  availableMediaKeys?: string[];
148
- /** Script entry point for routing (e.g. `"on_recall"`, `"on_message_api_received"`). */
148
+ /** Script routing hint from `dialog.params.entry_point` — branch inside `defineScript`; not a separate host entry. */
149
149
  entryPoint?: string;
150
150
  /** Current recall attempt number for this dialog (from `dialog.params.attempt`, starts at 0). */
151
151
  attempt?: number;
@@ -154,8 +154,9 @@ export interface ScriptDialogContext {
154
154
  *
155
155
  * Resolved at script start: `dialog.params` / `call.params` (`recall_count`) override
156
156
  * {@link AgentContext.recallCount} from CMS. Omitted when no value is configured.
157
- * Passed to {@link import('./platform').ScheduleCallOptions.recallCount} when scheduling
158
- * outbound calls without explicit options.
157
+ * The host may default {@link import('./platform').ScheduleCallOptions.recallCount} from this
158
+ * field when scheduling outbound calls without explicit recall options and without
159
+ * {@link import('./platform').ScheduleCallOptions.onFailedCall}.
159
160
  */
160
161
  recallCount?: number;
161
162
  /**
@@ -163,7 +164,9 @@ export interface ScriptDialogContext {
163
164
  *
164
165
  * Resolved at script start: `dialog.params` / `call.params` (`recall_delay`) override
165
166
  * {@link AgentContext.recallDelay} from CMS (`agent.delay` converted to seconds).
166
- * Omitted when no value is configured.
167
+ * Omitted when no value is configured. The host may default
168
+ * {@link import('./platform').ScheduleCallOptions.recallDelay} from this field under the same
169
+ * conditions as {@link recallCount}.
167
170
  */
168
171
  recallDelay?: number;
169
172
  /**
@@ -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":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"script-context.js","sourceRoot":"","sources":["../../src/types/script-context.ts"],"names":[],"mappings":";;AAoQA,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"}
1
+ {"version":3,"file":"script-context.js","sourceRoot":"","sources":["../../src/types/script-context.ts"],"names":[],"mappings":";;AAuQA,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,43 @@
1
+ # SDK usage examples
2
+
3
+ Runnable-style snippets for `@voctiv/agent-sdk`. Copy into your script project or use as reference.
4
+
5
+ Each file exports one `defineScript` handler. The host **always** invokes that single export — unlike logic-executor Python, it does **not** call separate functions by `entry_point` name.
6
+
7
+ | File | Topic |
8
+ |------|--------|
9
+ | [outbound-with-recall.ts](./outbound-with-recall.ts) | Outbound with `recallCount` / `recallDelay` |
10
+ | [recall-routing-by-attempt.ts](./recall-routing-by-attempt.ts) | Branch on `context.attempt` during online recall legs |
11
+ | [schedule-call-with-defaults.ts](./schedule-call-with-defaults.ts) | `platform.call()` using CMS defaults from `context` |
12
+ | [after-call-continuation.ts](./after-call-continuation.ts) | `onSuccessCall` / `onFailedCall` + `getScriptPhase()` |
13
+ | [read-recall-from-params.ts](./read-recall-from-params.ts) | `parseRecallDelaySeconds()` / `parseRecallCount()` |
14
+
15
+ ## Recall flow
16
+
17
+ 1. Script calls `platform.call(msisdn, { recallCount, recallDelay })`.
18
+ 2. Host stores params on the `call` row.
19
+ 3. On failed outbound, host schedules a new `call` with `date_added = now + recallDelay`.
20
+ 4. Dialer runs the **same script** again; `context.attempt` is incremented.
21
+ 5. Branch inside `defineScript` with `context.attempt`, not with a separate entry function.
22
+
23
+ Do **not** combine step 1 with `onFailedCall` on the same `platform.call()` — use one strategy per
24
+ scheduled outbound leg. See [after-call-continuation.ts](./after-call-continuation.ts) for the
25
+ script-driven failure path (`after_call_failed`).
26
+
27
+ ## Failed outbound: pick one strategy
28
+
29
+ | Need | Use | Avoid on the same `platform.call()` |
30
+ |------|-----|--------------------------------------|
31
+ | CMS-style automatic redials | `recallCount` + `recallDelay` (or omit both and let host default from `context` when no `onFailedCall`) | `onFailedCall` |
32
+ | Diagram / custom logic after failure | `onFailedCall` (+ branch on `getScriptPhase` → `after_call_failed`) | `recallCount` + `recallDelay` |
33
+
34
+ When `onFailedCall` is passed **explicitly** in `platform.call()` options, the host does
35
+ **not** auto-apply CMS `context.recallCount` / `context.recallDelay` to the new `call` row.
36
+ `on_failed_call` in dialog/Omni defaults is ignored for scheduling. If the script passes both
37
+ strategies in options, the host **drops recall** and keeps `onFailedCall`.
38
+
39
+ ## `entryPoint` vs logic-executor
40
+
41
+ In LE Python, `entry_point='main'` selects which script function runs.
42
+
43
+ In this host, `platform.call({ entryPoint })` only writes `entry_point` to DB params and sets `context.entryPoint` so **your** `defineScript` can branch (e.g. `getScriptPhase(context)` for headless after-call). Omit it when recall/online logic uses `context.attempt` only.
@@ -0,0 +1,47 @@
1
+ /**
2
+ * After-call routing with `onSuccessCall` / `onFailedCall` (headless continuation).
3
+ *
4
+ * Mutually exclusive with automatic recall (`recallCount` + `recallDelay`) on the same
5
+ * `platform.call()`. If both are passed, the host keeps `onFailedCall` and drops recall.
6
+ *
7
+ * When `onFailedCall` is set, CMS `context.recallCount` / `context.recallDelay` are not
8
+ * auto-applied to the scheduled `call` row; the after-call branch runs on failure instead.
9
+ *
10
+ * On call end the host sets `dialog.params.entry_point` to the configured handler name
11
+ * and runs the **same** `defineScript` export headlessly. Branch with
12
+ * `getScriptPhase(context)` (`after_call_success` / `after_call_failed`).
13
+ */
14
+ import { defineScript, getScriptPhase } from '@voctiv/agent-sdk';
15
+
16
+ export default defineScript(async ({ channel, context, logger, platform }) => {
17
+ const phase = getScriptPhase(context);
18
+
19
+ if (context.headless && phase === 'after_call_failed') {
20
+ logger.log('Post-call offline branch after failed outbound');
21
+ await platform.messaging.send({
22
+ src: 'bot',
23
+ destination: context.msisdn || '',
24
+ text: 'Sorry we missed you. Reply to reschedule.',
25
+ });
26
+ platform.dialog.result = 'done';
27
+ return { output: { phase } };
28
+ }
29
+
30
+ if (context.headless && phase === 'after_call_success') {
31
+ logger.log('Post-call offline branch after successful call');
32
+ return { output: { phase } };
33
+ }
34
+
35
+ channel.sip.answer();
36
+ await channel.audio.say('Starting outbound attempt.');
37
+
38
+ const msisdn = context.msisdn || context.callerId;
39
+ if (!msisdn) return;
40
+
41
+ await platform.call(msisdn, {
42
+ onSuccessCall: 'on_success_call',
43
+ onFailedCall: 'on_failed_call',
44
+ });
45
+
46
+ logger.log('Scheduled outbound with after-call headless handlers (no automatic recall)');
47
+ });
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Schedule an outbound call that the platform will retry on failure.
3
+ *
4
+ * The host runs a single `defineScript` handler — there is no separate runtime
5
+ * entry per `entry_point` like logic-executor Python `run_unit(entry_point=...)`.
6
+ * Recall legs are the same script again with an incremented `context.attempt`.
7
+ *
8
+ * Do not combine recall options with `onFailedCall` on the same `platform.call()`.
9
+ * When `onFailedCall` is configured, CMS recall is not auto-applied to the call row.
10
+ * See README § "Failed outbound: automatic recall vs after-call continuation".
11
+ */
12
+ import { defineScript } from '@voctiv/agent-sdk';
13
+
14
+ const RECALL_COUNT = 3;
15
+ /** Delay between failed attempts, in seconds (5 minutes). */
16
+ const RECALL_DELAY_SEC = 300;
17
+
18
+ export default defineScript(async ({ channel, context, logger, platform }) => {
19
+ channel.sip.answer();
20
+
21
+ const msisdn = context.msisdn || context.callerId;
22
+ if (!msisdn) {
23
+ logger.error('No msisdn on context');
24
+ return;
25
+ }
26
+
27
+ await channel.audio.say(
28
+ 'We will call you back shortly. If we cannot reach you, we will retry a few times.',
29
+ );
30
+
31
+ await platform.call(msisdn, {
32
+ recallCount: RECALL_COUNT,
33
+ recallDelay: RECALL_DELAY_SEC,
34
+ });
35
+
36
+ logger.log('Outbound scheduled with recall', {
37
+ msisdn,
38
+ recallCount: RECALL_COUNT,
39
+ recallDelaySec: RECALL_DELAY_SEC,
40
+ });
41
+
42
+ return { output: { scheduled: true } };
43
+ });
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Read recall settings from legacy dialog/call params and schedule outbound.
3
+ */
4
+ import {
5
+ defineScript,
6
+ parseRecallCount,
7
+ parseRecallDelaySeconds,
8
+ } from '@voctiv/agent-sdk';
9
+
10
+ export default defineScript(async ({ context, logger, platform }) => {
11
+ const params = context.dialogParams ?? {};
12
+
13
+ const rawCount = params.recall_count ?? params.recallCount;
14
+ const rawDelay = params.recall_delay ?? params.recallDelay;
15
+
16
+ const recallCount =
17
+ parseRecallCount(rawCount) ?? context.recallCount ?? context.agent?.recallCount;
18
+ const recallDelaySec =
19
+ parseRecallDelaySeconds(rawDelay) ??
20
+ context.recallDelay ??
21
+ context.agent?.recallDelay;
22
+
23
+ logger.log('Parsed recall from params', {
24
+ rawCount,
25
+ rawDelay,
26
+ recallCount,
27
+ recallDelaySec,
28
+ attempt: context.attempt,
29
+ });
30
+
31
+ const msisdn = context.msisdn || context.callerId;
32
+ if (!msisdn || recallCount == null || recallDelaySec == null) {
33
+ logger.warn('Missing msisdn or recall config — skipping schedule');
34
+ return;
35
+ }
36
+
37
+ await platform.call(msisdn, {
38
+ recallCount,
39
+ recallDelay: recallDelaySec,
40
+ });
41
+ });
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Handle the first outbound attempt vs automatic recall attempts.
3
+ *
4
+ * Recall calls are still **online** SIP sessions (`getScriptPhase` → `'online'`).
5
+ * Use `context.attempt` (from `dialog.params.attempt`, starts at 0) to branch inside
6
+ * your single `defineScript` handler — the host does not invoke a separate function.
7
+ */
8
+ import { defineScript, getScriptPhase } from '@voctiv/agent-sdk';
9
+
10
+ export default defineScript(async ({ channel, context, logger }) => {
11
+ const phase = getScriptPhase(context);
12
+ const attempt = context.attempt ?? 0;
13
+
14
+ logger.log('Call leg', {
15
+ phase,
16
+ attempt,
17
+ headless: context.headless,
18
+ recallCount: context.recallCount,
19
+ recallDelay: context.recallDelay,
20
+ });
21
+
22
+ channel.sip.answer();
23
+
24
+ if (!context.headless && attempt > 0) {
25
+ await channel.audio.say(
26
+ `This is follow-up attempt number ${attempt + 1}. Please stay on the line.`,
27
+ );
28
+ } else if (!context.headless) {
29
+ await channel.audio.say('Hello, this is our first call to you today.');
30
+ }
31
+
32
+ const asr = await channel.createAsr({ language: context.language || 'ru-RU' });
33
+
34
+ return new Promise((resolve) => {
35
+ asr.result$.subscribe(async (text) => {
36
+ if (!text.trim()) return;
37
+
38
+ if (/voicemail|leave a message/i.test(text)) {
39
+ logger.log('Voicemail detected — host may schedule recall', { attempt });
40
+ channel.sip.hangup();
41
+ resolve({ output: { outcome: 'voicemail', attempt } });
42
+ return;
43
+ }
44
+
45
+ await channel.audio.say('Thank you. Goodbye.');
46
+ channel.sip.hangup();
47
+ resolve({ output: { outcome: 'answered', attempt } });
48
+ });
49
+
50
+ channel.events.terminated$.subscribe(() => {
51
+ asr.destroy();
52
+ resolve({ output: { outcome: 'terminated', attempt } });
53
+ });
54
+ });
55
+ });
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Schedule outbound using CMS contact-rules defaults already resolved on `context`.
3
+ *
4
+ * When `recallCount` / `recallDelay` are omitted from `platform.call()` options, the host
5
+ * fills them from `context.recallCount` / `context.recallDelay` only when `onFailedCall` is
6
+ * not configured for that scheduled call.
7
+ */
8
+ import { defineScript } from '@voctiv/agent-sdk';
9
+
10
+ export default defineScript(async ({ channel, context, logger, platform }) => {
11
+ channel.sip.answer();
12
+
13
+ const msisdn = context.msisdn || context.callerId;
14
+ if (!msisdn) return;
15
+
16
+ logger.log('Recall configuration snapshot', {
17
+ effective: {
18
+ count: context.recallCount,
19
+ delaySec: context.recallDelay,
20
+ },
21
+ agentDefaults: {
22
+ count: context.agent?.recallCount,
23
+ delaySec: context.agent?.recallDelay,
24
+ },
25
+ attempt: context.attempt,
26
+ });
27
+
28
+ await platform.call(msisdn);
29
+
30
+ await channel.audio.say('We have scheduled a call using your agent recall settings.');
31
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voctiv/agent-sdk",
3
- "version": "0.2.13",
3
+ "version": "0.2.15",
4
4
  "description": "Voctiv TypeScript agent SDK: defineScript and platform types for the voice/dialog scripting runtime.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "",
@@ -23,7 +23,8 @@
23
23
  },
24
24
  "files": [
25
25
  "dist",
26
- "README.md"
26
+ "README.md",
27
+ "examples"
27
28
  ],
28
29
  "scripts": {
29
30
  "build": "tsc -p tsconfig.build.json",