@unboundcx/sdk 4.13.36 → 4.13.38

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/index.js CHANGED
@@ -43,6 +43,7 @@ import { SearchService } from './services/search.js';
43
43
  import { DirectoryService } from './services/directory.js';
44
44
  import { ChatService } from './services/chat.js';
45
45
  import { DeveloperApisService } from './services/developerApis.js';
46
+ import { TextService } from './services/text.js';
46
47
  import {
47
48
  DataImportService,
48
49
  DataExportService,
@@ -120,6 +121,7 @@ class UnboundSDK extends BaseSDK {
120
121
  this.generateId = new GenerateIdService(this);
121
122
  this.engagementMetrics = new EngagementMetricsService(this);
122
123
  this.taskRouter = new TaskRouterService(this);
124
+ this.text = new TextService(this);
123
125
  this.knowledgeBase = new KnowledgeBaseService(this);
124
126
  this.fax = new FaxService(this);
125
127
  this.documents = new DocumentsService(this);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unboundcx/sdk",
3
- "version": "4.13.36",
3
+ "version": "4.13.38",
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",
@@ -0,0 +1,65 @@
1
+ import { internalRequest } from '../../base.js';
2
+
3
+ /**
4
+ * Assist Service - Live AI Assist evaluation for a task
5
+ */
6
+ export class AssistService {
7
+ constructor(sdk) {
8
+ this.sdk = sdk;
9
+ }
10
+
11
+ /**
12
+ * Evaluate utterances against assigned battle cards for a task
13
+ *
14
+ * @param {Object} options - Evaluate options
15
+ * @param {string} options.taskId - Task ID
16
+ * @param {Array} options.utterances - Utterances to evaluate
17
+ * @returns {Promise<Object>} Evaluation result
18
+ *
19
+ * @example
20
+ * const result = await sdk.ai.assist.evaluate({
21
+ * taskId: 'task_123',
22
+ * utterances: [{ speaker: 'customer', text: 'That is too expensive' }]
23
+ * });
24
+ */
25
+ async evaluate({ taskId, utterances }) {
26
+ this.sdk.validateParams(
27
+ { taskId, utterances },
28
+ {
29
+ taskId: { type: 'string', required: true },
30
+ utterances: { type: 'array', required: true },
31
+ },
32
+ );
33
+
34
+ const params = {
35
+ body: { taskId, utterances },
36
+ };
37
+
38
+ const result = await internalRequest(this.sdk, '/ai/assist/evaluate', 'POST', params);
39
+ return result;
40
+ }
41
+
42
+ /**
43
+ * Get the last AI Assist evaluation for a task
44
+ *
45
+ * @param {Object} options - Options
46
+ * @param {string} options.taskId - Task ID
47
+ * @returns {Promise<Object>} Last evaluation
48
+ *
49
+ * @example
50
+ * const last = await sdk.ai.assist.getLast({
51
+ * taskId: 'task_123'
52
+ * });
53
+ */
54
+ async getLast({ taskId }) {
55
+ this.sdk.validateParams(
56
+ { taskId },
57
+ {
58
+ taskId: { type: 'string', required: true },
59
+ },
60
+ );
61
+
62
+ const result = await internalRequest(this.sdk, `/ai/assist/last/${taskId}`, 'GET');
63
+ return result;
64
+ }
65
+ }
@@ -0,0 +1,415 @@
1
+ import { internalRequest } from '../../base.js';
2
+
3
+ /**
4
+ * Battle Cards Service - Manage AI Assist battle card packs, cards, and queue assignments
5
+ */
6
+ export class BattleCardsService {
7
+ constructor(sdk) {
8
+ this.sdk = sdk;
9
+ }
10
+
11
+ // ========================================
12
+ // Pack CRUD Methods
13
+ // ========================================
14
+
15
+ /**
16
+ * Create a battle card pack
17
+ *
18
+ * @param {Object} options - Pack creation options
19
+ * @param {string} options.name - Name of the pack
20
+ * @param {string} [options.recordTypeId] - Record type ID
21
+ * @returns {Promise<Object>} Created pack with id
22
+ *
23
+ * @example
24
+ * const pack = await sdk.ai.battleCards.createPack({
25
+ * name: 'Pricing Objection Handling'
26
+ * });
27
+ */
28
+ async createPack({ name, recordTypeId }) {
29
+ this.sdk.validateParams(
30
+ { name },
31
+ {
32
+ name: { type: 'string', required: true },
33
+ recordTypeId: { type: 'string', required: false },
34
+ },
35
+ );
36
+
37
+ const params = {
38
+ body: { name, recordTypeId },
39
+ };
40
+
41
+ const result = await internalRequest(this.sdk, '/ai/battleCards/packs', 'POST', params);
42
+ return result;
43
+ }
44
+
45
+ /**
46
+ * Get a battle card pack by ID
47
+ *
48
+ * @param {Object} options - Options
49
+ * @param {string} options.packId - The ID of the pack
50
+ * @returns {Promise<Object>} Pack object
51
+ *
52
+ * @example
53
+ * const pack = await sdk.ai.battleCards.getPack({
54
+ * packId: '251abc'
55
+ * });
56
+ */
57
+ async getPack({ packId }) {
58
+ this.sdk.validateParams(
59
+ { packId },
60
+ {
61
+ packId: { type: 'string', required: true },
62
+ },
63
+ );
64
+
65
+ const result = await internalRequest(this.sdk, `/ai/battleCards/packs/${packId}`, 'GET');
66
+ return result;
67
+ }
68
+
69
+ /**
70
+ * List battle card packs
71
+ *
72
+ * @param {Object} [options={}] - Query options
73
+ * @param {number} [options.limit] - Maximum number of results
74
+ * @param {string} [options.orderBy] - Field to order by
75
+ * @param {string} [options.orderDirection] - Order direction
76
+ * @returns {Promise<Object>} Object with results array
77
+ *
78
+ * @example
79
+ * const packs = await sdk.ai.battleCards.listPacks({
80
+ * limit: 50,
81
+ * orderBy: 'createdAt',
82
+ * orderDirection: 'DESC'
83
+ * });
84
+ */
85
+ async listPacks({
86
+ limit,
87
+ orderBy,
88
+ orderDirection,
89
+ } = {}) {
90
+ const params = {
91
+ query: { limit, orderBy, orderDirection },
92
+ };
93
+
94
+ const result = await internalRequest(this.sdk, '/ai/battleCards/packs', 'GET', params);
95
+ return result;
96
+ }
97
+
98
+ /**
99
+ * Update a battle card pack
100
+ *
101
+ * @param {Object} options - Update options
102
+ * @param {string} options.packId - The ID of the pack
103
+ * @param {string} [options.name] - New name
104
+ * @param {string} [options.recordTypeId] - Record type ID
105
+ * @returns {Promise<Object>} Updated pack object
106
+ *
107
+ * @example
108
+ * const updated = await sdk.ai.battleCards.updatePack({
109
+ * packId: '251abc',
110
+ * name: 'Updated Pricing Pack'
111
+ * });
112
+ */
113
+ async updatePack({ packId, name, recordTypeId }) {
114
+ this.sdk.validateParams(
115
+ { packId },
116
+ {
117
+ packId: { type: 'string', required: true },
118
+ name: { type: 'string', required: false },
119
+ recordTypeId: { type: 'string', required: false },
120
+ },
121
+ );
122
+
123
+ const params = {
124
+ body: { name, recordTypeId },
125
+ };
126
+
127
+ const result = await internalRequest(this.sdk,
128
+ `/ai/battleCards/packs/${packId}`,
129
+ 'PUT',
130
+ params,
131
+ );
132
+ return result;
133
+ }
134
+
135
+ /**
136
+ * Delete a battle card pack
137
+ *
138
+ * @param {Object} options - Delete options
139
+ * @param {string} options.packId - The ID of the pack
140
+ * @returns {Promise<Object>} Success response
141
+ *
142
+ * @example
143
+ * await sdk.ai.battleCards.deletePack({
144
+ * packId: '251abc'
145
+ * });
146
+ */
147
+ async deletePack({ packId }) {
148
+ this.sdk.validateParams(
149
+ { packId },
150
+ {
151
+ packId: { type: 'string', required: true },
152
+ },
153
+ );
154
+
155
+ const result = await internalRequest(this.sdk,
156
+ `/ai/battleCards/packs/${packId}`,
157
+ 'DELETE',
158
+ );
159
+ return result;
160
+ }
161
+
162
+ // ========================================
163
+ // Card CRUD Methods
164
+ // ========================================
165
+
166
+ /**
167
+ * Create a battle card in a pack
168
+ *
169
+ * @param {Object} options - Card creation options
170
+ * @param {string} options.packId - The ID of the pack
171
+ * @param {string} options.title - Card title
172
+ * @param {string} [options.body] - Card body
173
+ * @param {string} [options.reply] - Suggested reply
174
+ * @param {string} [options.dontSay] - Phrases to avoid
175
+ * @param {Array} [options.triggers] - Trigger phrases
176
+ * @param {number} [options.order] - Display order
177
+ * @param {string} [options.recordTypeId] - Record type ID
178
+ * @returns {Promise<Object>} Created card with id
179
+ *
180
+ * @example
181
+ * const card = await sdk.ai.battleCards.createCard({
182
+ * packId: '251abc',
183
+ * title: 'Too expensive',
184
+ * body: 'Acknowledge the concern, then reframe value.',
185
+ * reply: 'I hear you — let me walk through what that includes.',
186
+ * triggers: ['too expensive', 'price']
187
+ * });
188
+ */
189
+ async createCard({
190
+ packId,
191
+ title,
192
+ body,
193
+ reply,
194
+ dontSay,
195
+ triggers,
196
+ order,
197
+ recordTypeId,
198
+ }) {
199
+ this.sdk.validateParams(
200
+ { packId, title },
201
+ {
202
+ packId: { type: 'string', required: true },
203
+ title: { type: 'string', required: true },
204
+ body: { type: 'string', required: false },
205
+ reply: { type: 'string', required: false },
206
+ dontSay: { type: 'string', required: false },
207
+ triggers: { type: 'array', required: false },
208
+ order: { type: 'number', required: false },
209
+ recordTypeId: { type: 'string', required: false },
210
+ },
211
+ );
212
+
213
+ const params = {
214
+ body: { title, body, reply, dontSay, triggers, order, recordTypeId },
215
+ };
216
+
217
+ const result = await internalRequest(this.sdk,
218
+ `/ai/battleCards/packs/${packId}/cards`,
219
+ 'POST',
220
+ params,
221
+ );
222
+ return result;
223
+ }
224
+
225
+ /**
226
+ * Get a battle card by ID
227
+ *
228
+ * @param {Object} options - Options
229
+ * @param {string} options.cardId - The ID of the card
230
+ * @returns {Promise<Object>} Card object
231
+ *
232
+ * @example
233
+ * const card = await sdk.ai.battleCards.getCard({
234
+ * cardId: '252abc'
235
+ * });
236
+ */
237
+ async getCard({ cardId }) {
238
+ this.sdk.validateParams(
239
+ { cardId },
240
+ {
241
+ cardId: { type: 'string', required: true },
242
+ },
243
+ );
244
+
245
+ const result = await internalRequest(this.sdk, `/ai/battleCards/cards/${cardId}`, 'GET');
246
+ return result;
247
+ }
248
+
249
+ /**
250
+ * List battle cards in a pack
251
+ *
252
+ * @param {Object} options - Options
253
+ * @param {string} options.packId - The ID of the pack
254
+ * @returns {Promise<Object>} Object with results array
255
+ *
256
+ * @example
257
+ * const cards = await sdk.ai.battleCards.listCards({
258
+ * packId: '251abc'
259
+ * });
260
+ */
261
+ async listCards({ packId }) {
262
+ this.sdk.validateParams(
263
+ { packId },
264
+ {
265
+ packId: { type: 'string', required: true },
266
+ },
267
+ );
268
+
269
+ const result = await internalRequest(this.sdk, `/ai/battleCards/packs/${packId}/cards`, 'GET');
270
+ return result;
271
+ }
272
+
273
+ /**
274
+ * Update a battle card
275
+ *
276
+ * @param {Object} options - Update options
277
+ * @param {string} options.cardId - The ID of the card
278
+ * @param {string} [options.title] - Card title
279
+ * @param {string} [options.body] - Card body
280
+ * @param {string} [options.reply] - Suggested reply
281
+ * @param {string} [options.dontSay] - Phrases to avoid
282
+ * @param {Array} [options.triggers] - Trigger phrases
283
+ * @param {number} [options.order] - Display order
284
+ * @returns {Promise<Object>} Updated card object
285
+ *
286
+ * @example
287
+ * const updated = await sdk.ai.battleCards.updateCard({
288
+ * cardId: '252abc',
289
+ * title: 'Budget concern'
290
+ * });
291
+ */
292
+ async updateCard({
293
+ cardId,
294
+ title,
295
+ body,
296
+ reply,
297
+ dontSay,
298
+ triggers,
299
+ order,
300
+ }) {
301
+ this.sdk.validateParams(
302
+ { cardId },
303
+ {
304
+ cardId: { type: 'string', required: true },
305
+ title: { type: 'string', required: false },
306
+ body: { type: 'string', required: false },
307
+ reply: { type: 'string', required: false },
308
+ dontSay: { type: 'string', required: false },
309
+ triggers: { type: 'array', required: false },
310
+ order: { type: 'number', required: false },
311
+ },
312
+ );
313
+
314
+ const params = {
315
+ body: { title, body, reply, dontSay, triggers, order },
316
+ };
317
+
318
+ const result = await internalRequest(this.sdk,
319
+ `/ai/battleCards/cards/${cardId}`,
320
+ 'PUT',
321
+ params,
322
+ );
323
+ return result;
324
+ }
325
+
326
+ /**
327
+ * Delete a battle card
328
+ *
329
+ * @param {Object} options - Delete options
330
+ * @param {string} options.cardId - The ID of the card
331
+ * @returns {Promise<Object>} Success response
332
+ *
333
+ * @example
334
+ * await sdk.ai.battleCards.deleteCard({
335
+ * cardId: '252abc'
336
+ * });
337
+ */
338
+ async deleteCard({ cardId }) {
339
+ this.sdk.validateParams(
340
+ { cardId },
341
+ {
342
+ cardId: { type: 'string', required: true },
343
+ },
344
+ );
345
+
346
+ const result = await internalRequest(this.sdk,
347
+ `/ai/battleCards/cards/${cardId}`,
348
+ 'DELETE',
349
+ );
350
+ return result;
351
+ }
352
+
353
+ // ========================================
354
+ // Queue Pack Assignment
355
+ // ========================================
356
+
357
+ /**
358
+ * List battle card packs assigned to a queue
359
+ *
360
+ * @param {Object} options - Options
361
+ * @param {string} options.queueId - The ID of the queue
362
+ * @returns {Promise<Object>} Assigned packs
363
+ *
364
+ * @example
365
+ * const assigned = await sdk.ai.battleCards.listQueuePacks({
366
+ * queueId: 'queue_123'
367
+ * });
368
+ */
369
+ async listQueuePacks({ queueId }) {
370
+ this.sdk.validateParams(
371
+ { queueId },
372
+ {
373
+ queueId: { type: 'string', required: true },
374
+ },
375
+ );
376
+
377
+ const result = await internalRequest(this.sdk, `/ai/battleCards/queues/${queueId}`, 'GET');
378
+ return result;
379
+ }
380
+
381
+ /**
382
+ * Set battle card packs assigned to a queue
383
+ *
384
+ * @param {Object} options - Options
385
+ * @param {string} options.queueId - The ID of the queue
386
+ * @param {Array<string>} options.packIds - Pack IDs to assign
387
+ * @returns {Promise<Object>} Updated assignment
388
+ *
389
+ * @example
390
+ * await sdk.ai.battleCards.setQueuePacks({
391
+ * queueId: 'queue_123',
392
+ * packIds: ['251abc']
393
+ * });
394
+ */
395
+ async setQueuePacks({ queueId, packIds }) {
396
+ this.sdk.validateParams(
397
+ { queueId, packIds },
398
+ {
399
+ queueId: { type: 'string', required: true },
400
+ packIds: { type: 'array', required: true },
401
+ },
402
+ );
403
+
404
+ const params = {
405
+ body: { packIds },
406
+ };
407
+
408
+ const result = await internalRequest(this.sdk,
409
+ `/ai/battleCards/queues/${queueId}`,
410
+ 'PUT',
411
+ params,
412
+ );
413
+ return result;
414
+ }
415
+ }
package/services/ai.js CHANGED
@@ -1,5 +1,7 @@
1
1
  import { internalRequest } from '../base.js';
2
2
  import { PlaybooksService } from './ai/playbooks.js';
3
+ import { BattleCardsService } from './ai/battleCards.js';
4
+ import { AssistService } from './ai/assist.js';
3
5
  import { VocabularyService } from './ai/vocabulary.js';
4
6
  import { EmailService } from './ai/email.js';
5
7
  import { translate as translateItems } from './ai/translate.js';
@@ -16,6 +18,8 @@ export class AIService {
16
18
  this.stt = new SpeechToTextService(sdk);
17
19
  this.extract = new ExtractService(sdk);
18
20
  this.playbooks = new PlaybooksService(sdk);
21
+ this.battleCards = new BattleCardsService(sdk);
22
+ this.assist = new AssistService(sdk);
19
23
  this.vocabulary = new VocabularyService(sdk);
20
24
  this.email = new EmailService(sdk);
21
25
  }
@@ -112,6 +112,9 @@ export class PhoneNumbersService {
112
112
  voiceRecordTypeId,
113
113
  messagingRecordTypeId,
114
114
  recordCalls,
115
+ textApp,
116
+ textAppMetaData,
117
+ textChatVisibility,
115
118
  },
116
119
  ) {
117
120
  this.sdk.validateParams(
@@ -125,6 +128,9 @@ export class PhoneNumbersService {
125
128
  voiceRecordTypeId,
126
129
  messagingRecordTypeId,
127
130
  recordCalls,
131
+ textApp,
132
+ textAppMetaData,
133
+ textChatVisibility,
128
134
  },
129
135
  {
130
136
  id: { type: 'string', required: true },
@@ -137,6 +143,9 @@ export class PhoneNumbersService {
137
143
  voiceRecordTypeId: { type: 'string', required: false },
138
144
  messagingRecordTypeId: { type: 'string', required: false },
139
145
  recordCalls: { type: 'boolean', required: false },
146
+ textApp: { type: 'string', required: false },
147
+ textAppMetaData: { type: 'string', required: false },
148
+ textChatVisibility: { type: 'string', required: false },
140
149
  },
141
150
  );
142
151
 
@@ -155,6 +164,11 @@ export class PhoneNumbersService {
155
164
  if (messagingRecordTypeId)
156
165
  updateData.messagingRecordTypeId = messagingRecordTypeId;
157
166
  if (recordCalls !== undefined) updateData.recordCalls = recordCalls;
167
+ if (textApp !== undefined) updateData.textApp = textApp;
168
+ if (textAppMetaData !== undefined)
169
+ updateData.textAppMetaData = textAppMetaData;
170
+ if (textChatVisibility !== undefined)
171
+ updateData.textChatVisibility = textChatVisibility;
158
172
 
159
173
  const params = {
160
174
  body: updateData,
@@ -845,6 +845,67 @@ export class TaskService {
845
845
  return result;
846
846
  }
847
847
 
848
+ /**
849
+ * Park a task ("waiting for customer"). Clears the worker (freeing
850
+ * capacity) and stamps preferredWorkerId with the parking worker so
851
+ * unpark can offer the task back to them first.
852
+ *
853
+ * @param {Object} options - Parameters
854
+ * @param {string} options.taskId - The task ID to park (required)
855
+ * @returns {Promise<Object>} { taskId, status: 'parked' }
856
+ */
857
+ async park(options = {}) {
858
+ const { taskId } = options;
859
+
860
+ this.sdk.validateParams(
861
+ { taskId },
862
+ { taskId: { type: 'string', required: true } },
863
+ );
864
+
865
+ const params = { body: { taskId } };
866
+
867
+ return await internalRequest(
868
+ this.sdk,
869
+ '/taskRouter/tasks/park',
870
+ 'PUT',
871
+ params,
872
+ );
873
+ }
874
+
875
+ /**
876
+ * Transfer a task to a different queue and/or worker. Passing queueId
877
+ * moves the task back to 'pending' status for re-distribution.
878
+ *
879
+ * @param {Object} options - Parameters
880
+ * @param {string} options.taskId - The task ID to transfer (required)
881
+ * @param {string} [options.queueId] - Destination queue ID
882
+ * @param {string} [options.workerId] - Destination worker ID
883
+ * @returns {Promise<Object>} { taskId }
884
+ */
885
+ async transfer(options = {}) {
886
+ const { taskId, queueId, workerId } = options;
887
+
888
+ this.sdk.validateParams(
889
+ { taskId, queueId, workerId },
890
+ {
891
+ taskId: { type: 'string', required: true },
892
+ queueId: { type: 'string', required: false },
893
+ workerId: { type: 'string', required: false },
894
+ },
895
+ );
896
+
897
+ const params = { body: { taskId } };
898
+ if (queueId !== undefined) params.body.queueId = queueId;
899
+ if (workerId !== undefined) params.body.workerId = workerId;
900
+
901
+ return await internalRequest(
902
+ this.sdk,
903
+ '/taskRouter/tasks/transfer',
904
+ 'PUT',
905
+ params,
906
+ );
907
+ }
908
+
848
909
  /**
849
910
  * Get the voice transcript for a task, keyed by the media-manager
850
911
  * bridgeId (not sipCallId) so it works across requeue/transfer.
@@ -0,0 +1,56 @@
1
+ import { internalRequest } from '../base.js';
2
+
3
+ // Text routing (sms-routing-plan.md §2/§3.2/§3.4): read-only lookups for the
4
+ // durable textConversations row. Mutations (send, park, transfer) go through
5
+ // sdk.messaging.sms / sdk.taskRouter.task — this service is for resolving
6
+ // "what conversation is this" from the client/CC UI.
7
+ export class TextConversationsService {
8
+ constructor(sdk) {
9
+ this.sdk = sdk;
10
+ }
11
+
12
+ /**
13
+ * Get a single text conversation by id.
14
+ * @param {string} id - textConversations id (required)
15
+ * @returns {Promise<Object>}
16
+ */
17
+ async get(id) {
18
+ this.sdk.validateParams(
19
+ { id },
20
+ { id: { type: 'string', required: true } },
21
+ );
22
+
23
+ return internalRequest(this.sdk, `/text/conversations/${id}`, 'GET');
24
+ }
25
+
26
+ /**
27
+ * Resolve the currently-open conversation for an (identity, counterparty)
28
+ * pair, if any.
29
+ * @param {Object} options - Parameters
30
+ * @param {string} options.phoneNumberId - our-side identity id (required)
31
+ * @param {string} options.counterparty - external address (required)
32
+ * @returns {Promise<Object|null>} the open conversation row, or null
33
+ */
34
+ async resolve(options = {}) {
35
+ const { phoneNumberId, counterparty } = options;
36
+
37
+ this.sdk.validateParams(
38
+ { phoneNumberId, counterparty },
39
+ {
40
+ phoneNumberId: { type: 'string', required: true },
41
+ counterparty: { type: 'string', required: true },
42
+ },
43
+ );
44
+
45
+ return internalRequest(this.sdk, '/text/conversations/resolve', 'GET', {
46
+ query: { phoneNumberId, counterparty },
47
+ });
48
+ }
49
+ }
50
+
51
+ export class TextService {
52
+ constructor(sdk) {
53
+ this.sdk = sdk;
54
+ this.conversations = new TextConversationsService(sdk);
55
+ }
56
+ }