@unboundcx/sdk 4.13.95 → 4.13.96

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.95",
3
+ "version": "4.13.96",
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",
@@ -80,9 +80,9 @@ export class AssistService {
80
80
  * @example
81
81
  * const { suggestions } = await sdk.ai.assist.listSuggestions({ queueId: 'queue_123', limit: 50 });
82
82
  */
83
- async listSuggestions({ queueId, limit } = {}) {
83
+ async listSuggestions({ queueId, limit, actorKind } = {}) {
84
84
  const result = await internalRequest(this.sdk, '/ai/assist/suggestions', 'GET', {
85
- query: { queueId, limit },
85
+ query: { queueId, limit, actorKind },
86
86
  });
87
87
  return result;
88
88
  }
@@ -97,9 +97,9 @@ export class AssistService {
97
97
  * @example
98
98
  * const stats = await sdk.ai.assist.suggestionStats({ queueId: 'queue_123' });
99
99
  */
100
- async suggestionStats({ queueId } = {}) {
100
+ async suggestionStats({ queueId, actorKind } = {}) {
101
101
  const result = await internalRequest(this.sdk, '/ai/assist/suggestions/stats', 'GET', {
102
- query: { queueId },
102
+ query: { queueId, actorKind },
103
103
  });
104
104
  return result;
105
105
  }
package/services/ai.js CHANGED
@@ -964,14 +964,16 @@ export class SpeechToTextService {
964
964
  * @param {Object} message - Message data
965
965
  * @param {string} message.text - Transcribed text
966
966
  * @param {Object} [message.transcriptionJson] - Full transcription metadata
967
+ * @param {string} [message.transcriptionJson.source] - 'tts' for synthetic bot ingest
967
968
  * @param {number} [message.duration] - Duration of this segment in seconds
968
- * @param {number} [message.confidence] - Confidence score (0-1)
969
+ * @param {number} [message.confidence] - Confidence score (0-1). Omit for TTS.
969
970
  * @param {string} [message.languageCode] - Language code for this segment
970
971
  * @param {string} [message.userId] - User associated with this message
971
972
  * @param {string} [message.role] - Speaker role
972
973
  * @param {string} [message.sipCallId] - SIP call identifier
973
974
  * @param {string} [message.side] - Stream side ('send' or 'recv')
974
975
  * @param {string} [message.bridgeId] - bridge id
976
+ * @param {string} [message.taskId] - Task id (stamped on the transcription session)
975
977
  * @param {Object} [message.sentiment] - Sentiment analysis data
976
978
  * @param {number} [message.sentiment.score] - Overall sentiment score (-100 to +100)
977
979
  * @param {number} [message.sentiment.previousScore] - Previous sentiment score (-100 to +100)
@@ -999,13 +1001,14 @@ export class SpeechToTextService {
999
1001
  sipCallId,
1000
1002
  side,
1001
1003
  bridgeId,
1004
+ taskId,
1002
1005
  sentiment,
1003
1006
  videoRoomId,
1004
1007
  videoParticipantId,
1005
1008
  },
1006
1009
  ) {
1007
1010
  this.sdk.validateParams(
1008
- { messageId, sessionId, text, bridgeId },
1011
+ { messageId, sessionId, text, bridgeId, taskId },
1009
1012
  {
1010
1013
  sessionId: { type: 'string', required: true },
1011
1014
  messageId: { type: 'string', required: false },
@@ -1020,6 +1023,7 @@ export class SpeechToTextService {
1020
1023
  sipCallId: { type: 'string', required: false },
1021
1024
  side: { type: 'string', required: false },
1022
1025
  bridgeId: { type: 'string', required: false },
1026
+ taskId: { type: 'string', required: false },
1023
1027
  sentiment: { type: 'object', required: false },
1024
1028
  videoRoomId: { type: 'string', required: false },
1025
1029
  videoParticipantId: { type: 'string', required: false },
@@ -1040,6 +1044,7 @@ export class SpeechToTextService {
1040
1044
  sipCallId,
1041
1045
  side,
1042
1046
  bridgeId,
1047
+ taskId,
1043
1048
  sentiment,
1044
1049
  videoRoomId,
1045
1050
  videoParticipantId,
@@ -19,19 +19,19 @@ export class ReportingAgentsService {
19
19
 
20
20
  /**
21
21
  * Agent summary rows (§6 metrics), grouped by agent, queue, or team.
22
- * @param {Object} params - { from, to, userIds, queueIds, teamIds, groupBy }
22
+ * @param {Object} params - { from, to, userIds, queueIds, teamIds, groupBy, agentKind }
23
23
  * @returns {Promise<Object>} { columns, rows, definitions, meta }
24
24
  * @example
25
25
  * await sdk.reporting.agents.summary({ from, to, groupBy: 'team' });
26
26
  */
27
- async summary({ from, to, userIds, queueIds, teamIds, groupBy } = {}) {
27
+ async summary({ from, to, userIds, queueIds, teamIds, groupBy, agentKind } = {}) {
28
28
  this.sdk.validateParams(
29
29
  { from, to },
30
30
  { from: { type: 'string', required: true }, to: { type: 'string', required: true } },
31
31
  );
32
32
  return internalRequest(
33
33
  this.sdk,
34
- `/reporting/agents/summary${queryString({ from, to, userIds, queueIds, teamIds, groupBy })}`,
34
+ `/reporting/agents/summary${queryString({ from, to, userIds, queueIds, teamIds, groupBy, agentKind })}`,
35
35
  'GET',
36
36
  );
37
37
  }
@@ -90,19 +90,19 @@ export class ReportingAgentsService {
90
90
  /**
91
91
  * Per-agent per-local-day timesheet rows (net paid hours), plus one
92
92
  * additive-sum row per agent (`agents`) for grouped totals.
93
- * @param {Object} params - { from, to, userIds, teamIds }
93
+ * @param {Object} params - { from, to, userIds, teamIds, agentKind }
94
94
  * @returns {Promise<Object>} { columns, rows, agents }
95
95
  * @example
96
96
  * await sdk.reporting.agents.timesheet({ from, to, userIds: ['u1'] });
97
97
  */
98
- async timesheet({ from, to, userIds, teamIds } = {}) {
98
+ async timesheet({ from, to, userIds, teamIds, agentKind } = {}) {
99
99
  this.sdk.validateParams(
100
100
  { from, to },
101
101
  { from: { type: 'string', required: true }, to: { type: 'string', required: true } },
102
102
  );
103
103
  return internalRequest(
104
104
  this.sdk,
105
- `/reporting/agents/timesheet${queryString({ from, to, userIds, teamIds })}`,
105
+ `/reporting/agents/timesheet${queryString({ from, to, userIds, teamIds, agentKind })}`,
106
106
  'GET',
107
107
  );
108
108
  }
@@ -111,7 +111,7 @@ export class ReportingAgentsService {
111
111
  * CSV export of any of the four views above. For view: 'timesheet', pass
112
112
  * `totals: true` to get one additive-sum row per agent instead of the
113
113
  * flat per-agent-per-day rows.
114
- * @param {Object} params - { view: 'summary'|'states'|'interactions'|'timesheet', from, to, userId, userIds, queueIds, teamIds, groupBy, totals }
114
+ * @param {Object} params - { view: 'summary'|'states'|'interactions'|'timesheet', from, to, userId, userIds, queueIds, teamIds, groupBy, agentKind, totals }
115
115
  * @returns {Promise<Object>} raw CSV response (transport-dependent)
116
116
  * @example
117
117
  * await sdk.reporting.agents.export({ view: 'timesheet', from, to });
@@ -126,6 +126,7 @@ export class ReportingAgentsService {
126
126
  queueIds,
127
127
  teamIds,
128
128
  groupBy,
129
+ agentKind,
129
130
  totals,
130
131
  } = {}) {
131
132
  this.sdk.validateParams(
@@ -141,6 +142,7 @@ export class ReportingAgentsService {
141
142
  queueIds,
142
143
  teamIds,
143
144
  groupBy,
145
+ agentKind,
144
146
  totals: totals ? '1' : undefined,
145
147
  format: 'csv',
146
148
  });
@@ -0,0 +1,242 @@
1
+ import { internalRequest } from '../../base.js';
2
+
3
+ /**
4
+ * CC worker bots — Setup → Bots (K21). Not Graham /chat/bots.
5
+ */
6
+ export class CcBotsService {
7
+ constructor(sdk) {
8
+ this.sdk = sdk;
9
+ }
10
+
11
+ /**
12
+ * Platform defaults for When to get help + model pickers.
13
+ * @returns {Promise<Object>}
14
+ */
15
+ async defaults() {
16
+ return internalRequest(this.sdk, '/taskRouter/ccBots/defaults', 'GET');
17
+ }
18
+
19
+ /**
20
+ * List CC worker bots for the account.
21
+ * @returns {Promise<Object>} { results }
22
+ */
23
+ async list() {
24
+ return internalRequest(this.sdk, '/taskRouter/ccBots', 'GET');
25
+ }
26
+
27
+ /**
28
+ * Create a named CC worker bot (user + worker, capacity 1).
29
+ * @param {Object} params
30
+ * @param {string} params.name
31
+ * @param {string} params.slug
32
+ * @param {string} [params.soulMd]
33
+ * @param {string} [params.provider]
34
+ * @param {string} [params.model]
35
+ * @param {string} [params.queueId]
36
+ * @param {string} [params.mailboxId]
37
+ * @returns {Promise<Object>}
38
+ */
39
+ async create({
40
+ name,
41
+ slug,
42
+ soulMd,
43
+ provider,
44
+ model,
45
+ queueId,
46
+ mailboxId,
47
+ } = {}) {
48
+ this.sdk.validateParams(
49
+ { name, slug },
50
+ {
51
+ name: { type: 'string', required: true },
52
+ slug: { type: 'string', required: true },
53
+ },
54
+ );
55
+ const body = { name, slug };
56
+ if (soulMd !== undefined) body.soulMd = soulMd;
57
+ if (provider !== undefined) body.provider = provider;
58
+ if (model !== undefined) body.model = model;
59
+ if (queueId !== undefined) body.queueId = queueId;
60
+ if (mailboxId !== undefined) body.mailboxId = mailboxId;
61
+ return internalRequest(this.sdk, '/taskRouter/ccBots', 'POST', { body });
62
+ }
63
+
64
+ /**
65
+ * Get one CC worker bot.
66
+ * @param {string} id
67
+ * @returns {Promise<Object>}
68
+ */
69
+ async get(id) {
70
+ this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
71
+ return internalRequest(this.sdk, `/taskRouter/ccBots/${id}`, 'GET');
72
+ }
73
+
74
+ /**
75
+ * Patch name / soul / model / pause kill-switch.
76
+ * @param {string} id
77
+ * @param {Object} [params]
78
+ * @returns {Promise<Object>}
79
+ */
80
+ async update(id, params = {}) {
81
+ this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
82
+ const body = {};
83
+ for (const key of [
84
+ 'name',
85
+ 'soulMd',
86
+ 'additionalDetails',
87
+ 'provider',
88
+ 'model',
89
+ 'mediaProvider',
90
+ 'mediaModel',
91
+ 'voiceId',
92
+ 'profilePhoto',
93
+ 'paused',
94
+ 'acceptChannels',
95
+ 'useChannels',
96
+ 'groupId',
97
+ 'groupOverrides',
98
+ 'inherit',
99
+ ]) {
100
+ if (key in params) body[key] = params[key];
101
+ }
102
+ return internalRequest(this.sdk, `/taskRouter/ccBots/${id}`, 'PATCH', {
103
+ body,
104
+ });
105
+ }
106
+
107
+ /**
108
+ * Clone a CC worker bot (new user + worker, copied config).
109
+ * @param {string} id
110
+ * @param {Object} [params]
111
+ * @param {string} [params.name]
112
+ * @returns {Promise<Object>}
113
+ */
114
+ async clone(id, { name } = {}) {
115
+ this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
116
+ const body = {};
117
+ if (name !== undefined) body.name = name;
118
+ return internalRequest(this.sdk, `/taskRouter/ccBots/${id}/clone`, 'POST', {
119
+ body,
120
+ });
121
+ }
122
+
123
+ /**
124
+ * Enable or disable many CC bots.
125
+ * @param {Object} params
126
+ * @param {string[]} params.ids
127
+ * @param {boolean} params.paused
128
+ * @returns {Promise<Object>}
129
+ */
130
+ async bulkPaused({ ids, paused } = {}) {
131
+ this.sdk.validateParams(
132
+ { ids, paused },
133
+ {
134
+ ids: { type: 'object', required: true },
135
+ paused: { type: 'boolean', required: true },
136
+ },
137
+ );
138
+ return internalRequest(this.sdk, '/taskRouter/ccBots/bulkPaused', 'POST', {
139
+ body: { ids, paused },
140
+ });
141
+ }
142
+
143
+ /**
144
+ * List bot groups.
145
+ * @returns {Promise<Object>}
146
+ */
147
+ async listGroups() {
148
+ return internalRequest(this.sdk, '/taskRouter/ccBotGroups', 'GET');
149
+ }
150
+
151
+ /**
152
+ * Create a bot group.
153
+ * @param {Object} params
154
+ * @returns {Promise<Object>}
155
+ */
156
+ async createGroup(params = {}) {
157
+ this.sdk.validateParams(
158
+ { name: params.name },
159
+ { name: { type: 'string', required: true } },
160
+ );
161
+ return internalRequest(this.sdk, '/taskRouter/ccBotGroups', 'POST', {
162
+ body: params,
163
+ });
164
+ }
165
+
166
+ /**
167
+ * Get one bot group.
168
+ * @param {string} id
169
+ * @returns {Promise<Object>}
170
+ */
171
+ async getGroup(id) {
172
+ this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
173
+ return internalRequest(this.sdk, `/taskRouter/ccBotGroups/${id}`, 'GET');
174
+ }
175
+
176
+ /**
177
+ * Patch a bot group (propagates inherited fields to member bots).
178
+ * @param {string} id
179
+ * @param {Object} [params]
180
+ * @returns {Promise<Object>}
181
+ */
182
+ async updateGroup(id, params = {}) {
183
+ this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
184
+ const body = {};
185
+ for (const key of [
186
+ 'name',
187
+ 'soulMd',
188
+ 'provider',
189
+ 'model',
190
+ 'mediaProvider',
191
+ 'mediaModel',
192
+ 'voiceId',
193
+ 'paused',
194
+ 'acceptChannels',
195
+ 'useChannels',
196
+ 'queueIds',
197
+ 'skillIds',
198
+ ]) {
199
+ if (key in params) body[key] = params[key];
200
+ }
201
+ return internalRequest(this.sdk, `/taskRouter/ccBotGroups/${id}`, 'PATCH', {
202
+ body,
203
+ });
204
+ }
205
+
206
+ /**
207
+ * Soft-delete a bot group and detach members.
208
+ * @param {string} id
209
+ * @returns {Promise<Object>}
210
+ */
211
+ async deleteGroup(id) {
212
+ this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
213
+ return internalRequest(
214
+ this.sdk,
215
+ `/taskRouter/ccBotGroups/${id}`,
216
+ 'DELETE',
217
+ );
218
+ }
219
+
220
+ /**
221
+ * Login a CC bot into a queue (queueUsers + worker addQueues).
222
+ * @param {string} id
223
+ * @param {Object} params
224
+ * @param {string} params.queueId
225
+ * @returns {Promise<Object>}
226
+ */
227
+ async addToQueue(id, { queueId } = {}) {
228
+ this.sdk.validateParams(
229
+ { id, queueId },
230
+ {
231
+ id: { type: 'string', required: true },
232
+ queueId: { type: 'string', required: true },
233
+ },
234
+ );
235
+ return internalRequest(
236
+ this.sdk,
237
+ `/taskRouter/ccBots/${id}/queues`,
238
+ 'POST',
239
+ { body: { queueId } },
240
+ );
241
+ }
242
+ }
@@ -4,6 +4,7 @@ import { MetricsService } from './MetricsService.js';
4
4
  import { CCService } from './CCService.js';
5
5
  import { OfferService } from './OfferService.js';
6
6
  import { ParticipantService } from './ParticipantService.js';
7
+ import { CcBotsService } from './CcBotsService.js';
7
8
 
8
9
  export class TaskRouterService {
9
10
  constructor(sdk) {
@@ -14,5 +15,6 @@ export class TaskRouterService {
14
15
  this.cc = new CCService(sdk);
15
16
  this.offer = new OfferService(sdk);
16
17
  this.participants = new ParticipantService(sdk);
18
+ this.ccBots = new CcBotsService(sdk);
17
19
  }
18
20
  }
@@ -409,6 +409,64 @@ export class TaskService {
409
409
  return result;
410
410
  }
411
411
 
412
+ /**
413
+ * Unassign a task back to pending (worker unlinked). Used by CC bot
414
+ * drain for short-lived connected tasks — not park.
415
+ *
416
+ * @param {Object} options
417
+ * @param {string} options.taskId
418
+ * @returns {Promise<Object>}
419
+ */
420
+ async unassign(options = {}) {
421
+ const { taskId, userId } = options;
422
+
423
+ this.sdk.validateParams(
424
+ { taskId, userId },
425
+ {
426
+ taskId: { type: 'string', required: true },
427
+ userId: { type: 'string', required: false },
428
+ },
429
+ );
430
+
431
+ const params = { body: { taskId } };
432
+ if (userId) params.body.userId = userId;
433
+
434
+ return internalRequest(
435
+ this.sdk,
436
+ '/taskRouter/tasks/unassign',
437
+ 'PUT',
438
+ params,
439
+ );
440
+ }
441
+
442
+ /**
443
+ * Staff-only internal note on a task (webchat/SMS/voice feed, or
444
+ * timeline). Never sent to the customer.
445
+ *
446
+ * @param {Object} options
447
+ * @param {string} options.taskId
448
+ * @param {string} options.message
449
+ * @returns {Promise<Object>}
450
+ */
451
+ async note(options = {}) {
452
+ const { taskId, message } = options;
453
+
454
+ this.sdk.validateParams(
455
+ { taskId, message },
456
+ {
457
+ taskId: { type: 'string', required: true },
458
+ message: { type: 'string', required: true },
459
+ },
460
+ );
461
+
462
+ return internalRequest(
463
+ this.sdk,
464
+ `/taskRouter/tasks/${taskId}/notes`,
465
+ 'POST',
466
+ { body: { message } },
467
+ );
468
+ }
469
+
412
470
  /**
413
471
  * Change task priority
414
472
  * Modify the priority of a task to increase or decrease its routing priority.
@@ -730,12 +788,13 @@ export class TaskService {
730
788
  * console.log(result.taskId); // "task456"
731
789
  */
732
790
  async complete(options = {}) {
733
- const { taskId } = options;
791
+ const { taskId, completedReason } = options;
734
792
 
735
793
  this.sdk.validateParams(
736
- { taskId },
794
+ { taskId, completedReason },
737
795
  {
738
796
  taskId: { type: 'string', required: true },
797
+ completedReason: { type: 'string', required: false },
739
798
  },
740
799
  );
741
800
 
@@ -745,6 +804,10 @@ export class TaskService {
745
804
  },
746
805
  };
747
806
 
807
+ if (completedReason) {
808
+ params.body.completedReason = completedReason;
809
+ }
810
+
748
811
  const result = await internalRequest(this.sdk,
749
812
  '/taskRouter/tasks/complete',
750
813
  'PUT',
@@ -281,4 +281,98 @@ export class WebchatService {
281
281
  // instance with just `{namespace}` and uses only this namespace.
282
282
  this.visitor = new WebchatVisitorService(sdk);
283
283
  }
284
+
285
+ /**
286
+ * Send an agent webchat message on a task. The server resolves the
287
+ * widget + engagement from the task — callers must not UOQL
288
+ * webchatConversations for widgetId.
289
+ *
290
+ * @param {Object} options
291
+ * @param {string} options.taskId
292
+ * @param {string} [options.message]
293
+ * @param {Object} [options.media]
294
+ * @param {Object|Array} [options.card]
295
+ * @returns {Promise<Object>}
296
+ */
297
+ async sendOnTask(options = {}) {
298
+ const { taskId, message, media, card } = options;
299
+
300
+ this.sdk.validateParams(
301
+ { taskId, message, media, card },
302
+ {
303
+ taskId: { type: 'string', required: true },
304
+ message: { type: 'string', required: false },
305
+ media: { type: 'object', required: false },
306
+ card: { type: 'object', required: false },
307
+ },
308
+ );
309
+
310
+ const body = {};
311
+ if (message !== undefined) body.message = message;
312
+ if (media !== undefined) body.media = media;
313
+ if (card !== undefined) body.card = card;
314
+
315
+ return internalRequest(
316
+ this.sdk,
317
+ `/webchat/tasks/${taskId}/messages`,
318
+ 'POST',
319
+ { body },
320
+ );
321
+ }
322
+
323
+ /**
324
+ * Agent/bot typing indicator on a task's webchat. Server resolves the
325
+ * engagement from the task — callers must not UOQL widgetId.
326
+ *
327
+ * @param {Object} options
328
+ * @param {string} options.taskId
329
+ * @param {boolean} options.isTyping
330
+ * @returns {Promise<Object>}
331
+ */
332
+ async typingOnTask(options = {}) {
333
+ const { taskId, isTyping } = options;
334
+
335
+ this.sdk.validateParams(
336
+ { taskId, isTyping },
337
+ {
338
+ taskId: { type: 'string', required: true },
339
+ isTyping: { type: 'boolean', required: true },
340
+ },
341
+ );
342
+
343
+ return internalRequest(
344
+ this.sdk,
345
+ `/webchat/tasks/${taskId}/typing`,
346
+ 'POST',
347
+ { body: { isTyping } },
348
+ );
349
+ }
350
+
351
+ /**
352
+ * Staff-only system note on a task's webchat feed (visibility=internal).
353
+ * Not sent to the visitor. Server resolves engagement from the task.
354
+ *
355
+ * @param {Object} options
356
+ * @param {string} options.taskId
357
+ * @param {string} options.message
358
+ * @returns {Promise<Object>}
359
+ */
360
+ async noteOnTask(options = {}) {
361
+ const { taskId, message } = options;
362
+
363
+ this.sdk.validateParams(
364
+ { taskId, message },
365
+ {
366
+ taskId: { type: 'string', required: true },
367
+ message: { type: 'string', required: true },
368
+ },
369
+ );
370
+
371
+ return internalRequest(
372
+ this.sdk,
373
+ `/webchat/tasks/${taskId}/notes`,
374
+ 'POST',
375
+ { body: { message } },
376
+ );
377
+ }
284
378
  }