@unboundcx/sdk 4.13.57 → 4.13.59

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.57",
3
+ "version": "4.13.59",
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,254 @@
1
+ import { internalRequest } from '../../base.js';
2
+
3
+ /**
4
+ * Participant Service - multi-party task participation: invite a user onto a
5
+ * task, request help from a queue, hold/drop/leave, and owner<->helper
6
+ * control swaps. Voice participants always dial the main bridge (P4);
7
+ * sidebar bridge, mute, and per-member bridgeRole changes arrive with the
8
+ * media update (P5).
9
+ */
10
+ export class ParticipantService {
11
+ constructor(sdk) {
12
+ this.sdk = sdk;
13
+ }
14
+
15
+ /**
16
+ * List a task's participants and any pending help requests.
17
+ *
18
+ * @param {Object} options - Options
19
+ * @param {string} options.taskId - Task ID
20
+ * @returns {Promise<Object>} { participants, helpRequests }
21
+ *
22
+ * @example
23
+ * const { participants, helpRequests } = await sdk.taskRouter.participants.list({ taskId: 'task_123' });
24
+ */
25
+ async list({ taskId }) {
26
+ this.sdk.validateParams(
27
+ { taskId },
28
+ { taskId: { type: 'string', required: true } },
29
+ );
30
+
31
+ return await internalRequest(
32
+ this.sdk,
33
+ `/taskRouter/tasks/${taskId}/participants`,
34
+ 'GET',
35
+ );
36
+ }
37
+
38
+ /**
39
+ * Add a participant to a task: invite a specific user to join, or request
40
+ * help from a queue.
41
+ *
42
+ * @param {Object} options - Options
43
+ * @param {string} options.taskId - Task ID
44
+ * @param {string} options.kind - 'user' | 'queue'
45
+ * @param {string} [options.userId] - Required when kind is 'user'
46
+ * @param {string} [options.queueId] - Required when kind is 'queue'
47
+ * @param {string} [options.note] - Optional note shown to the invitee
48
+ * @param {string} [options.bridgeRole='main'] - Voice bridge role (only 'main' is supported until the media update)
49
+ * @returns {Promise<Object>} { participant, offerId } for kind 'user'; { helpTaskId } for kind 'queue'
50
+ *
51
+ * @example
52
+ * await sdk.taskRouter.participants.add({ taskId: 'task_123', kind: 'user', userId: 'user_456', note: 'Need a hand' });
53
+ * @example
54
+ * await sdk.taskRouter.participants.add({ taskId: 'task_123', kind: 'queue', queueId: 'queue_789' });
55
+ */
56
+ async add({ taskId, kind, userId, queueId, note, bridgeRole } = {}) {
57
+ this.sdk.validateParams(
58
+ { taskId, kind, userId, queueId, note, bridgeRole },
59
+ {
60
+ taskId: { type: 'string', required: true },
61
+ kind: { type: 'string', required: true },
62
+ userId: { type: 'string', required: false },
63
+ queueId: { type: 'string', required: false },
64
+ note: { type: 'string', required: false },
65
+ bridgeRole: { type: 'string', required: false },
66
+ },
67
+ );
68
+
69
+ const params = { body: { kind } };
70
+ if (userId !== undefined) params.body.userId = userId;
71
+ if (queueId !== undefined) params.body.queueId = queueId;
72
+ if (note !== undefined) params.body.note = note;
73
+ if (bridgeRole !== undefined) params.body.bridgeRole = bridgeRole;
74
+
75
+ return await internalRequest(
76
+ this.sdk,
77
+ `/taskRouter/tasks/${taskId}/participants`,
78
+ 'POST',
79
+ params,
80
+ );
81
+ }
82
+
83
+ /**
84
+ * Cancel a pending/assigned help request before it is joined.
85
+ *
86
+ * @param {Object} options - Options
87
+ * @param {string} options.taskId - Task ID
88
+ * @param {string} options.helpTaskId - The help shell task id returned by `add({ kind: 'queue' })`
89
+ * @returns {Promise<Object>}
90
+ *
91
+ * @example
92
+ * await sdk.taskRouter.participants.cancelHelp({ taskId: 'task_123', helpTaskId: 'task_999' });
93
+ */
94
+ async cancelHelp({ taskId, helpTaskId } = {}) {
95
+ this.sdk.validateParams(
96
+ { taskId, helpTaskId },
97
+ {
98
+ taskId: { type: 'string', required: true },
99
+ helpTaskId: { type: 'string', required: true },
100
+ },
101
+ );
102
+
103
+ return await internalRequest(
104
+ this.sdk,
105
+ `/taskRouter/tasks/${taskId}/help/${helpTaskId}`,
106
+ 'DELETE',
107
+ );
108
+ }
109
+
110
+ /**
111
+ * Update a participant. Only `held` is supported until the media update —
112
+ * `muted` and `bridgeRole` are reserved for P5 and will error server-side.
113
+ *
114
+ * @param {Object} options - Options
115
+ * @param {string} options.taskId - Task ID
116
+ * @param {string} options.participantId - Participant ID
117
+ * @param {boolean} [options.held] - Put the participant's leg on/off hold
118
+ * @param {boolean} [options.muted] - Reserved (media update)
119
+ * @param {string} [options.bridgeRole] - Reserved (media update)
120
+ * @returns {Promise<Object>}
121
+ *
122
+ * @example
123
+ * await sdk.taskRouter.participants.update({ taskId: 'task_123', participantId: 'tp_456', held: true });
124
+ */
125
+ async update({ taskId, participantId, held, muted, bridgeRole } = {}) {
126
+ this.sdk.validateParams(
127
+ { taskId, participantId, held, muted, bridgeRole },
128
+ {
129
+ taskId: { type: 'string', required: true },
130
+ participantId: { type: 'string', required: true },
131
+ held: { type: 'boolean', required: false },
132
+ muted: { type: 'boolean', required: false },
133
+ bridgeRole: { type: 'string', required: false },
134
+ },
135
+ );
136
+
137
+ const params = { body: {} };
138
+ if (held !== undefined) params.body.held = held;
139
+ if (muted !== undefined) params.body.muted = muted;
140
+ if (bridgeRole !== undefined) params.body.bridgeRole = bridgeRole;
141
+
142
+ return await internalRequest(
143
+ this.sdk,
144
+ `/taskRouter/tasks/${taskId}/participants/${participantId}`,
145
+ 'PATCH',
146
+ params,
147
+ );
148
+ }
149
+
150
+ /**
151
+ * Remove a participant: drop them (owner/manager) or leave (self).
152
+ *
153
+ * @param {Object} options - Options
154
+ * @param {string} options.taskId - Task ID
155
+ * @param {string} options.participantId - Participant ID
156
+ * @returns {Promise<Object>}
157
+ *
158
+ * @example
159
+ * await sdk.taskRouter.participants.remove({ taskId: 'task_123', participantId: 'tp_456' });
160
+ */
161
+ async remove({ taskId, participantId }) {
162
+ this.sdk.validateParams(
163
+ { taskId, participantId },
164
+ {
165
+ taskId: { type: 'string', required: true },
166
+ participantId: { type: 'string', required: true },
167
+ },
168
+ );
169
+
170
+ return await internalRequest(
171
+ this.sdk,
172
+ `/taskRouter/tasks/${taskId}/participants/${participantId}`,
173
+ 'DELETE',
174
+ );
175
+ }
176
+
177
+ /**
178
+ * Swap task ownership between the current owner and a joined helper.
179
+ *
180
+ * @param {Object} options - Options
181
+ * @param {string} options.taskId - Task ID
182
+ * @param {string} options.participantId - The helper participant taking/giving control
183
+ * @param {string} options.action - 'give' | 'take'
184
+ * @returns {Promise<Object>} { taskId, workerId }
185
+ *
186
+ * @example
187
+ * await sdk.taskRouter.participants.control({ taskId: 'task_123', participantId: 'tp_456', action: 'give' });
188
+ */
189
+ async control({ taskId, participantId, action }) {
190
+ this.sdk.validateParams(
191
+ { taskId, participantId, action },
192
+ {
193
+ taskId: { type: 'string', required: true },
194
+ participantId: { type: 'string', required: true },
195
+ action: { type: 'string', required: true },
196
+ },
197
+ );
198
+
199
+ const params = { body: { action } };
200
+
201
+ return await internalRequest(
202
+ this.sdk,
203
+ `/taskRouter/tasks/${taskId}/participants/${participantId}/control`,
204
+ 'POST',
205
+ params,
206
+ );
207
+ }
208
+
209
+ /**
210
+ * Connect-all / sidebar-all. Reserved for the media update (P5) — currently
211
+ * always errors server-side.
212
+ *
213
+ * @param {Object} options - Options
214
+ * @param {string} options.taskId - Task ID
215
+ * @param {string} [options.bridgeRole] - Reserved (media update)
216
+ * @returns {Promise<Object>}
217
+ */
218
+ async all({ taskId, bridgeRole } = {}) {
219
+ this.sdk.validateParams(
220
+ { taskId, bridgeRole },
221
+ {
222
+ taskId: { type: 'string', required: true },
223
+ bridgeRole: { type: 'string', required: false },
224
+ },
225
+ );
226
+
227
+ const params = { body: {} };
228
+ if (bridgeRole !== undefined) params.body.bridgeRole = bridgeRole;
229
+
230
+ return await internalRequest(
231
+ this.sdk,
232
+ `/taskRouter/tasks/${taskId}/participants/all`,
233
+ 'POST',
234
+ params,
235
+ );
236
+ }
237
+
238
+ /**
239
+ * List tasks the caller is currently helping on (joined as a helper),
240
+ * for the mini-card strip.
241
+ *
242
+ * @returns {Promise<Array>} [{ task, participantId, role, joinedAt }]
243
+ *
244
+ * @example
245
+ * const helping = await sdk.taskRouter.participants.participating();
246
+ */
247
+ async participating() {
248
+ return await internalRequest(
249
+ this.sdk,
250
+ '/taskRouter/tasks/participating',
251
+ 'GET',
252
+ );
253
+ }
254
+ }
@@ -3,6 +3,7 @@ import { TaskService } from './TaskService.js';
3
3
  import { MetricsService } from './MetricsService.js';
4
4
  import { CCService } from './CCService.js';
5
5
  import { OfferService } from './OfferService.js';
6
+ import { ParticipantService } from './ParticipantService.js';
6
7
 
7
8
  export class TaskRouterService {
8
9
  constructor(sdk) {
@@ -12,5 +13,6 @@ export class TaskRouterService {
12
13
  this.metrics = new MetricsService(sdk);
13
14
  this.cc = new CCService(sdk);
14
15
  this.offer = new OfferService(sdk);
16
+ this.participants = new ParticipantService(sdk);
15
17
  }
16
18
  }
@@ -385,11 +385,60 @@ export class WorkerService {
385
385
  params.body.userId = userId;
386
386
  }
387
387
 
388
- const result = await internalRequest(this.sdk,
388
+ const result = await internalRequest(this.sdk,
389
389
  '/taskRouter/worker/queueLogout',
390
390
  'PUT',
391
391
  params,
392
392
  );
393
393
  return result;
394
394
  }
395
+
396
+ /**
397
+ * Search for workers within a queue's scope
398
+ * Finds workers a caller can act on (transfer/invite/DM) for a given queue, with optional
399
+ * name/email/extension text search and skill-match flagging.
400
+ *
401
+ * @param {Object} options - Parameters
402
+ * @param {string} options.queueId - The queue ID to scope the search to (required)
403
+ * @param {string} [options.q] - Free-text filter matching name, email, or extension
404
+ * @param {string[]} [options.skills] - Skill IDs to flag matches for (joined as a comma-separated list)
405
+ * @param {number} [options.limit] - Max rows to return (default 50, max 200)
406
+ * @returns {Promise<Object>} Object containing the matching worker rows
407
+ * @returns {Array<Object>} result.rows - Worker rows with status/capacity/skills info
408
+ * @returns {number} result.total - Total matching rows
409
+ *
410
+ * @example
411
+ * const { rows, total } = await sdk.taskRouter.worker.search({ queueId: 'queue123', q: 'sam' });
412
+ * console.log(rows.length, total);
413
+ */
414
+ async search(options = {}) {
415
+ const { queueId, q, skills, limit } = options;
416
+
417
+ this.sdk.validateParams(
418
+ { queueId, q, skills, limit },
419
+ {
420
+ queueId: { type: 'string', required: true },
421
+ q: { type: 'string', required: false },
422
+ skills: { type: 'array', required: false },
423
+ limit: { type: 'number', required: false },
424
+ },
425
+ );
426
+
427
+ const query = { queueId };
428
+
429
+ if (q) {
430
+ query.q = q;
431
+ }
432
+
433
+ if (skills && skills.length) {
434
+ query.skills = skills.join(',');
435
+ }
436
+
437
+ if (limit) {
438
+ query.limit = limit;
439
+ }
440
+
441
+ const result = await internalRequest(this.sdk, '/taskRouter/workers/search', 'GET', { query });
442
+ return result;
443
+ }
395
444
  }