@unboundcx/sdk 4.13.98 → 4.13.100
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unboundcx/sdk",
|
|
3
|
-
"version": "4.13.
|
|
3
|
+
"version": "4.13.100",
|
|
4
4
|
"description": "Official JavaScript SDK for the Unbound API - A comprehensive toolkit for integrating with Unbound's communication, AI, and data management services",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -439,6 +439,82 @@ export class TaskService {
|
|
|
439
439
|
);
|
|
440
440
|
}
|
|
441
441
|
|
|
442
|
+
/**
|
|
443
|
+
* Release a task back to the queue for a human (same queue, same task
|
|
444
|
+
* id) — the bot-task-lifecycle release contract. Stamps
|
|
445
|
+
* botEligible:false (when humanOnly) plus named release-reason
|
|
446
|
+
* metadata and keeps the customer's original place in line. Voice:
|
|
447
|
+
* 'live' keeps the call on hold music for the next human; 'callback'
|
|
448
|
+
* ends the call and the task's primary channel becomes whatever is still
|
|
449
|
+
* live (e.g. sms) — the human who accepts follows up like on any task.
|
|
450
|
+
* This is not the queue-wait callback feature (no auto-dial).
|
|
451
|
+
*
|
|
452
|
+
* @param {Object} options - Parameters
|
|
453
|
+
* @param {string} options.taskId - The task ID to release (required)
|
|
454
|
+
* @param {'live'|'callback'} [options.mode] - Required for a voice task (has a live call); ignored for a digital task
|
|
455
|
+
* @param {string} options.reasonCode - Release reason code (required) — e.g. 'callback_promised', 'human_requested', 'no_human_available', 'bot_cannot_resolve', 'customer_frustrated', 'review_failed', 'policy_human_only', 'other'
|
|
456
|
+
* @param {string} options.reason - One-sentence reason shown to the next agent (required)
|
|
457
|
+
* @param {string} [options.callbackNumber] - E.164 callback number ('callback' mode only; defaults to the task's `from`)
|
|
458
|
+
* @param {boolean} [options.humanOnly=true] - Stamp botEligible:false so only a human is offered this task
|
|
459
|
+
* @param {boolean} [options.hangup=true] - Hang up the customer leg ('callback' mode only)
|
|
460
|
+
* @returns {Promise<Object>} { taskId, status: 'pending', mode, humanOnly, reasonCode }
|
|
461
|
+
*
|
|
462
|
+
* @example
|
|
463
|
+
* // Caller confirmed a callback -- release and hang up
|
|
464
|
+
* await sdk.taskRouter.task.release({
|
|
465
|
+
* taskId: 'task123',
|
|
466
|
+
* mode: 'callback',
|
|
467
|
+
* reasonCode: 'callback_promised',
|
|
468
|
+
* reason: 'Caller asked for a callback once an agent frees up',
|
|
469
|
+
* });
|
|
470
|
+
*
|
|
471
|
+
* @example
|
|
472
|
+
* // Caller wants to hold for a human -- release, keep the call live
|
|
473
|
+
* await sdk.taskRouter.task.release({
|
|
474
|
+
* taskId: 'task123',
|
|
475
|
+
* mode: 'live',
|
|
476
|
+
* reasonCode: 'no_human_available',
|
|
477
|
+
* reason: 'No agents available, caller chose to hold',
|
|
478
|
+
* });
|
|
479
|
+
*/
|
|
480
|
+
async release(options = {}) {
|
|
481
|
+
const {
|
|
482
|
+
taskId,
|
|
483
|
+
mode,
|
|
484
|
+
reasonCode,
|
|
485
|
+
reason,
|
|
486
|
+
callbackNumber,
|
|
487
|
+
humanOnly,
|
|
488
|
+
hangup,
|
|
489
|
+
} = options;
|
|
490
|
+
|
|
491
|
+
this.sdk.validateParams(
|
|
492
|
+
{ taskId, mode, reasonCode, reason, callbackNumber, humanOnly, hangup },
|
|
493
|
+
{
|
|
494
|
+
taskId: { type: 'string', required: true },
|
|
495
|
+
mode: { type: 'string', required: false },
|
|
496
|
+
reasonCode: { type: 'string', required: true },
|
|
497
|
+
reason: { type: 'string', required: true },
|
|
498
|
+
callbackNumber: { type: 'string', required: false },
|
|
499
|
+
humanOnly: { type: 'boolean', required: false },
|
|
500
|
+
hangup: { type: 'boolean', required: false },
|
|
501
|
+
},
|
|
502
|
+
);
|
|
503
|
+
|
|
504
|
+
const params = { body: { taskId, reasonCode, reason } };
|
|
505
|
+
if (mode !== undefined) params.body.mode = mode;
|
|
506
|
+
if (callbackNumber !== undefined) params.body.callbackNumber = callbackNumber;
|
|
507
|
+
if (humanOnly !== undefined) params.body.humanOnly = humanOnly;
|
|
508
|
+
if (hangup !== undefined) params.body.hangup = hangup;
|
|
509
|
+
|
|
510
|
+
return await internalRequest(
|
|
511
|
+
this.sdk,
|
|
512
|
+
'/taskRouter/tasks/release',
|
|
513
|
+
'PUT',
|
|
514
|
+
params,
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
|
|
442
518
|
/**
|
|
443
519
|
* Staff-only internal note on a task (webchat/SMS/voice feed, or
|
|
444
520
|
* timeline). Never sent to the customer.
|
|
@@ -871,6 +947,8 @@ export class TaskService {
|
|
|
871
947
|
* @param {string} [options.subject] - The new subject/title for the task
|
|
872
948
|
* @param {string} [options.summary] - The overall summary for the task
|
|
873
949
|
* @param {string} [options.disposition] - The disposition code or outcome for the task (e.g., 'resolved', 'escalated', 'callback-scheduled')
|
|
950
|
+
* @param {boolean} [options.botEligible] - Routing flag. `false` = never offer this task to bot workers (human only); `true` re-allows bots
|
|
951
|
+
* @param {?string} [options.humanFollowUp] - What a human still owes this customer: 'callback' | 'message' | 'dispatch' | 'quote' | 'other', or null to clear. Read by the caller-hangup safety net so an abandoned call with this set releases to the queue instead of completing.
|
|
874
952
|
* @returns {Promise<Object>} Object containing the task ID
|
|
875
953
|
* @returns {string} result.taskId - The task ID that was updated
|
|
876
954
|
*
|
|
@@ -898,6 +976,10 @@ export class TaskService {
|
|
|
898
976
|
* disposition: 'escalated'
|
|
899
977
|
* });
|
|
900
978
|
* console.log(result.taskId); // "task789"
|
|
979
|
+
*
|
|
980
|
+
* @example
|
|
981
|
+
* // Human-only routing: bot workers are no longer offered this task
|
|
982
|
+
* await sdk.taskRouter.task.update({ taskId: 'task789', botEligible: false });
|
|
901
983
|
*/
|
|
902
984
|
async update(options = {}) {
|
|
903
985
|
const {
|
|
@@ -908,10 +990,22 @@ export class TaskService {
|
|
|
908
990
|
cdrId,
|
|
909
991
|
summary,
|
|
910
992
|
sentiment,
|
|
993
|
+
botEligible,
|
|
994
|
+
humanFollowUp,
|
|
911
995
|
} = options;
|
|
912
996
|
|
|
913
997
|
this.sdk.validateParams(
|
|
914
|
-
{
|
|
998
|
+
{
|
|
999
|
+
taskId,
|
|
1000
|
+
subject,
|
|
1001
|
+
disposition,
|
|
1002
|
+
sipCallId,
|
|
1003
|
+
cdrId,
|
|
1004
|
+
summary,
|
|
1005
|
+
sentiment,
|
|
1006
|
+
botEligible,
|
|
1007
|
+
humanFollowUp,
|
|
1008
|
+
},
|
|
915
1009
|
{
|
|
916
1010
|
taskId: { type: 'string', required: true },
|
|
917
1011
|
subject: { type: 'string', required: false },
|
|
@@ -920,6 +1014,10 @@ export class TaskService {
|
|
|
920
1014
|
sipCallId: { type: 'string', required: false },
|
|
921
1015
|
summary: { type: 'string', required: false },
|
|
922
1016
|
sentiment: { type: 'object', required: false },
|
|
1017
|
+
botEligible: { type: 'boolean', required: false },
|
|
1018
|
+
// validateParams already skips type-checking a null value (see
|
|
1019
|
+
// base.js) -- 'string' here only constrains the non-null case.
|
|
1020
|
+
humanFollowUp: { type: 'string', required: false },
|
|
923
1021
|
},
|
|
924
1022
|
);
|
|
925
1023
|
|
|
@@ -929,6 +1027,14 @@ export class TaskService {
|
|
|
929
1027
|
},
|
|
930
1028
|
};
|
|
931
1029
|
|
|
1030
|
+
if (botEligible !== undefined) {
|
|
1031
|
+
params.body.botEligible = botEligible;
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
if (humanFollowUp !== undefined) {
|
|
1035
|
+
params.body.humanFollowUp = humanFollowUp;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
932
1038
|
if (subject !== undefined) {
|
|
933
1039
|
params.body.subject = subject;
|
|
934
1040
|
}
|
|
@@ -1141,22 +1247,37 @@ export class TaskService {
|
|
|
1141
1247
|
* @param {string} [options.target.queueId] - Destination queue ID
|
|
1142
1248
|
* @param {string} [options.target.workerId] - Destination worker ID
|
|
1143
1249
|
* @param {string} [options.note] - Optional note for the receiving agent
|
|
1250
|
+
* @param {string} [options.reasonCode] - Transfer reason code — e.g. 'wrong_department', 'customer_requested', 'out_of_scope', 'policy_never_bot', 'language', 'other'. Required when the caller's worker is a bot.
|
|
1251
|
+
* @param {string} [options.reason] - One-sentence transfer reason. Required when the caller's worker is a bot.
|
|
1144
1252
|
* @returns {Promise<Object>} { taskId, newTaskId }
|
|
1253
|
+
*
|
|
1254
|
+
* @example
|
|
1255
|
+
* // Bot transferring to a configured queue target
|
|
1256
|
+
* await sdk.taskRouter.task.transfer({
|
|
1257
|
+
* taskId: 'task123',
|
|
1258
|
+
* target: { queueId: 'billingQueue1' },
|
|
1259
|
+
* reasonCode: 'wrong_department',
|
|
1260
|
+
* reason: 'Caller has a billing question',
|
|
1261
|
+
* });
|
|
1145
1262
|
*/
|
|
1146
1263
|
async transfer(options = {}) {
|
|
1147
|
-
const { taskId, target, note } = options;
|
|
1264
|
+
const { taskId, target, note, reasonCode, reason } = options;
|
|
1148
1265
|
|
|
1149
1266
|
this.sdk.validateParams(
|
|
1150
|
-
{ taskId, target, note },
|
|
1267
|
+
{ taskId, target, note, reasonCode, reason },
|
|
1151
1268
|
{
|
|
1152
1269
|
taskId: { type: 'string', required: true },
|
|
1153
1270
|
target: { type: 'object', required: true },
|
|
1154
1271
|
note: { type: 'string', required: false },
|
|
1272
|
+
reasonCode: { type: 'string', required: false },
|
|
1273
|
+
reason: { type: 'string', required: false },
|
|
1155
1274
|
},
|
|
1156
1275
|
);
|
|
1157
1276
|
|
|
1158
1277
|
const params = { body: { taskId, target } };
|
|
1159
1278
|
if (note !== undefined) params.body.note = note;
|
|
1279
|
+
if (reasonCode !== undefined) params.body.reasonCode = reasonCode;
|
|
1280
|
+
if (reason !== undefined) params.body.reason = reason;
|
|
1160
1281
|
|
|
1161
1282
|
return await internalRequest(
|
|
1162
1283
|
this.sdk,
|