@unboundcx/sdk 4.13.44 → 4.13.48

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.44",
3
+ "version": "4.13.48",
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",
@@ -617,6 +617,18 @@ export class PortalsService {
617
617
  * portal with no login surface, e.g. `marketing`, is never included);
618
618
  * `matches` is whether this person currently passes that portal's
619
619
  * people-access filter.
620
+ * sessions: Array<{
621
+ * id: string,
622
+ * portalId: string,
623
+ * portalName: string,
624
+ * ip: string,
625
+ * browser: string,
626
+ * os: string,
627
+ * device: string,
628
+ * createdAt: string|null,
629
+ * lastSeenAt: string|null,
630
+ * expiresAt: string|null
631
+ * }>
620
632
  */
621
633
  async getPeopleAccess(peopleId) {
622
634
  this.sdk.validateParams(
@@ -737,9 +749,55 @@ export class PortalsService {
737
749
  );
738
750
  }
739
751
 
752
+ /**
753
+ * Revokes one portal login session for the person (logs that browser out).
754
+ *
755
+ * @param {string} peopleId
756
+ * @param {string} sessionId
757
+ * @returns {Promise<{ ok: true }>}
758
+ */
759
+ async revokePeoplePortalSession(peopleId, sessionId) {
760
+ this.sdk.validateParams(
761
+ { peopleId, sessionId },
762
+ {
763
+ peopleId: { type: "string", required: true },
764
+ sessionId: { type: "string", required: true },
765
+ },
766
+ );
767
+
768
+ return internalRequest(
769
+ this.sdk,
770
+ `/portals/people/${encodeURIComponent(peopleId)}/sessions/${encodeURIComponent(sessionId)}`,
771
+ "DELETE",
772
+ );
773
+ }
774
+
775
+ /**
776
+ * Revokes every active portal login session for the person (logs them
777
+ * out of all browsers). Does not delete their credential — they can
778
+ * sign in again.
779
+ *
780
+ * @param {string} peopleId
781
+ * @returns {Promise<{ ok: true }>}
782
+ */
783
+ async revokeAllPeoplePortalSessions(peopleId) {
784
+ this.sdk.validateParams(
785
+ { peopleId },
786
+ {
787
+ peopleId: { type: "string", required: true },
788
+ },
789
+ );
790
+
791
+ return internalRequest(
792
+ this.sdk,
793
+ `/portals/people/${encodeURIComponent(peopleId)}/sessions`,
794
+ "DELETE",
795
+ );
796
+ }
797
+
740
798
  /**
741
799
  * Revokes a person's portal access (soft-deletes their credential across
742
- * every portal on the account). Idempotent — revoking someone with no
800
+ * every portal on this account). Idempotent — revoking someone with no
743
801
  * credential is a no-op, not an error.
744
802
  *
745
803
  * @param {string} peopleId
@@ -300,4 +300,29 @@ export class CCService {
300
300
  );
301
301
  return result;
302
302
  }
303
+
304
+ /**
305
+ * Recover a worker stuck out of routing (ghost Redis capacity, leftover
306
+ * lock, expired wrap-up). Self or manager. Does not force offline.
307
+ *
308
+ * @param {Object} options
309
+ * @param {string} options.workerId
310
+ * @returns {Promise<Object>}
311
+ */
312
+ async unlockWorker(options = {}) {
313
+ const { workerId } = options;
314
+
315
+ this.sdk.validateParams(
316
+ { workerId },
317
+ { workerId: { type: 'string', required: true } },
318
+ );
319
+
320
+ const result = await internalRequest(
321
+ this.sdk,
322
+ `/taskRouter/cc/workers/${workerId}/unlock`,
323
+ 'POST',
324
+ {},
325
+ );
326
+ return result;
327
+ }
303
328
  }
@@ -880,6 +880,65 @@ export class TaskService {
880
880
  );
881
881
  }
882
882
 
883
+ /**
884
+ * Mark a task's inbound messages as read for one channel (or all).
885
+ * Channel ids: sms | webchat | email | whatsApp | rcs | all.
886
+ * Clearing SMS also clears whatsApp/rcs until those get their own
887
+ * timeline threads (`channel` may also be the group name `sms`).
888
+ *
889
+ * @param {Object} options
890
+ * @param {string} options.taskId
891
+ * @param {string} [options.channel='all']
892
+ * @returns {Promise<{taskId:string, unreadByChannel:object, unreadTotal:number}>}
893
+ */
894
+ async markChannelRead(options = {}) {
895
+ const { taskId, channel } = options;
896
+
897
+ this.sdk.validateParams(
898
+ { taskId, channel },
899
+ {
900
+ taskId: { type: 'string', required: true },
901
+ channel: { type: 'string', required: false },
902
+ },
903
+ );
904
+
905
+ const params = { body: { taskId } };
906
+ if (channel !== undefined) params.body.channel = channel;
907
+
908
+ return await internalRequest(
909
+ this.sdk,
910
+ '/taskRouter/tasks/unread/read',
911
+ 'PUT',
912
+ params,
913
+ );
914
+ }
915
+
916
+ /**
917
+ * Read a task's live channel mix -- whether it has an open text
918
+ * conversation, a live webchat session, or an active call, and whether
919
+ * it's currently eligible to be parked (`canPark`). Used to show/hide
920
+ * Park and webchat "End chat" without polling (task-park-webchat-endchat
921
+ * decisions, 2026-09-04).
922
+ *
923
+ * @param {Object} options
924
+ * @param {string} options.taskId
925
+ * @returns {Promise<{channelState:{hasOpenText:boolean, webchatLive:boolean, callLive:boolean, canPark:boolean}}>}
926
+ */
927
+ async channelState(options = {}) {
928
+ const { taskId } = options;
929
+
930
+ this.sdk.validateParams(
931
+ { taskId },
932
+ { taskId: { type: 'string', required: true } },
933
+ );
934
+
935
+ return await internalRequest(
936
+ this.sdk,
937
+ `/taskRouter/tasks/${taskId}/channelState`,
938
+ 'GET',
939
+ );
940
+ }
941
+
883
942
  /**
884
943
  * Transfer a task to a different queue and/or worker. Passing queueId
885
944
  * moves the task back to 'pending' status for re-distribution.
@@ -243,6 +243,32 @@ export class WebchatConversationsService {
243
243
  'GET',
244
244
  );
245
245
  }
246
+
247
+ /**
248
+ * Agent-initiated "End chat" -- ends the webchat session only (same
249
+ * completeConversation() path as visitor end / idle timeout, reason
250
+ * 'agentEnded'). Only offered client-side when another channel (open
251
+ * text conversation or a live call) is still open on the task; the task
252
+ * itself keeps running (task-park-webchat-endchat-plan.md R2).
253
+ * @param {string} widgetId
254
+ * @param {string} engagementSessionId
255
+ * @returns {Promise<Object>}
256
+ */
257
+ async end(widgetId, engagementSessionId) {
258
+ this.sdk.validateParams(
259
+ { widgetId, engagementSessionId },
260
+ {
261
+ widgetId: { type: 'string', required: true },
262
+ engagementSessionId: { type: 'string', required: true },
263
+ },
264
+ );
265
+
266
+ return internalRequest(
267
+ this.sdk,
268
+ `/webchat/widgets/${widgetId}/conversations/${engagementSessionId}/end`,
269
+ 'POST',
270
+ );
271
+ }
246
272
  }
247
273
 
248
274
  export class WebchatService {