@webex/contact-center 3.12.0-task-refactor.11 → 3.12.0-task-refactor.12

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.
Files changed (101) hide show
  1. package/dist/cc.js +297 -83
  2. package/dist/cc.js.map +1 -1
  3. package/dist/constants.js +3 -0
  4. package/dist/constants.js.map +1 -1
  5. package/dist/metrics/behavioral-events.js +39 -0
  6. package/dist/metrics/behavioral-events.js.map +1 -1
  7. package/dist/metrics/constants.js +8 -1
  8. package/dist/metrics/constants.js.map +1 -1
  9. package/dist/services/ApiAiAssistant.js +3 -0
  10. package/dist/services/ApiAiAssistant.js.map +1 -1
  11. package/dist/services/config/Util.js +1 -1
  12. package/dist/services/config/Util.js.map +1 -1
  13. package/dist/services/config/types.js +10 -0
  14. package/dist/services/config/types.js.map +1 -1
  15. package/dist/services/constants.js +1 -0
  16. package/dist/services/constants.js.map +1 -1
  17. package/dist/services/core/Err.js.map +1 -1
  18. package/dist/services/core/Utils.js +57 -6
  19. package/dist/services/core/Utils.js.map +1 -1
  20. package/dist/services/core/aqm-reqs.js +92 -17
  21. package/dist/services/core/aqm-reqs.js.map +1 -1
  22. package/dist/services/core/websocket/WebSocketManager.js +24 -3
  23. package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
  24. package/dist/services/index.js +1 -0
  25. package/dist/services/index.js.map +1 -1
  26. package/dist/services/task/Task.js +6 -0
  27. package/dist/services/task/Task.js.map +1 -1
  28. package/dist/services/task/TaskManager.js +155 -6
  29. package/dist/services/task/TaskManager.js.map +1 -1
  30. package/dist/services/task/TaskUtils.js +39 -11
  31. package/dist/services/task/TaskUtils.js.map +1 -1
  32. package/dist/services/task/constants.js +7 -1
  33. package/dist/services/task/constants.js.map +1 -1
  34. package/dist/services/task/dialer.js +129 -0
  35. package/dist/services/task/dialer.js.map +1 -1
  36. package/dist/services/task/state-machine/TaskStateMachine.js +30 -3
  37. package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -1
  38. package/dist/services/task/state-machine/actions.js +4 -0
  39. package/dist/services/task/state-machine/actions.js.map +1 -1
  40. package/dist/services/task/state-machine/constants.js +3 -0
  41. package/dist/services/task/state-machine/constants.js.map +1 -1
  42. package/dist/services/task/state-machine/guards.js +23 -0
  43. package/dist/services/task/state-machine/guards.js.map +1 -1
  44. package/dist/services/task/state-machine/types.js.map +1 -1
  45. package/dist/services/task/types.js +59 -0
  46. package/dist/services/task/types.js.map +1 -1
  47. package/dist/types/cc.d.ts +76 -2
  48. package/dist/types/constants.d.ts +3 -0
  49. package/dist/types/metrics/constants.d.ts +6 -0
  50. package/dist/types/services/config/types.d.ts +22 -1
  51. package/dist/types/services/core/Err.d.ts +6 -0
  52. package/dist/types/services/core/Utils.d.ts +20 -2
  53. package/dist/types/services/core/aqm-reqs.d.ts +49 -0
  54. package/dist/types/services/core/websocket/WebSocketManager.d.ts +1 -0
  55. package/dist/types/services/core/websocket/connection-service.d.ts +1 -0
  56. package/dist/types/services/task/Task.d.ts +1 -0
  57. package/dist/types/services/task/TaskUtils.d.ts +13 -0
  58. package/dist/types/services/task/constants.d.ts +6 -0
  59. package/dist/types/services/task/dialer.d.ts +45 -0
  60. package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +36 -8
  61. package/dist/types/services/task/state-machine/constants.d.ts +3 -0
  62. package/dist/types/services/task/state-machine/guards.d.ts +2 -0
  63. package/dist/types/services/task/state-machine/types.d.ts +11 -0
  64. package/dist/types/services/task/types.d.ts +75 -1
  65. package/dist/types.js.map +1 -1
  66. package/dist/webex.js +1 -1
  67. package/package.json +2 -2
  68. package/src/cc.ts +389 -111
  69. package/src/constants.ts +3 -0
  70. package/src/metrics/behavioral-events.ts +42 -0
  71. package/src/metrics/constants.ts +9 -1
  72. package/src/services/ApiAiAssistant.ts +3 -0
  73. package/src/services/config/Util.ts +1 -1
  74. package/src/services/config/types.ts +12 -1
  75. package/src/services/constants.ts +1 -0
  76. package/src/services/core/Err.ts +3 -0
  77. package/src/services/core/Utils.ts +68 -5
  78. package/src/services/core/aqm-reqs.ts +100 -22
  79. package/src/services/core/websocket/WebSocketManager.ts +23 -2
  80. package/src/services/index.ts +1 -0
  81. package/src/services/task/Task.ts +13 -0
  82. package/src/services/task/TaskManager.ts +171 -7
  83. package/src/services/task/TaskUtils.ts +33 -1
  84. package/src/services/task/constants.ts +6 -0
  85. package/src/services/task/dialer.ts +136 -1
  86. package/src/services/task/state-machine/TaskStateMachine.ts +37 -5
  87. package/src/services/task/state-machine/actions.ts +4 -0
  88. package/src/services/task/state-machine/constants.ts +3 -0
  89. package/src/services/task/state-machine/guards.ts +30 -0
  90. package/src/services/task/state-machine/types.ts +14 -1
  91. package/src/services/task/types.ts +80 -0
  92. package/src/types.ts +4 -1
  93. package/test/unit/spec/cc.ts +293 -26
  94. package/test/unit/spec/services/config/index.ts +30 -2
  95. package/test/unit/spec/services/core/Utils.ts +367 -1
  96. package/test/unit/spec/services/core/websocket/WebSocketManager.ts +90 -1
  97. package/test/unit/spec/services/core/websocket/connection-service.ts +4 -5
  98. package/test/unit/spec/services/task/TaskManager.ts +2325 -150
  99. package/test/unit/spec/services/task/dialer.ts +372 -96
  100. package/umd/contact-center.min.js +2 -2
  101. package/umd/contact-center.min.js.map +1 -1
package/dist/cc.js CHANGED
@@ -85,6 +85,7 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
85
85
  * - `task:established` - Task/call has been connected
86
86
  * - `task:ended` - Task/call has ended
87
87
  * - `task:error` - An error occurred during task handling
88
+ * - `task:campaignPreviewReservation` - Campaign preview contact offered to agent
88
89
  *
89
90
  * @public
90
91
  *
@@ -312,7 +313,6 @@ class ContactCenter extends _webexCore.WebexPlugin {
312
313
  webex: this.$webex,
313
314
  connectionConfig: this.getConnectionConfig()
314
315
  });
315
- this.services.webSocketManager.on('message', this.handleWebsocketMessage);
316
316
  this.webCallingService = new _WebCallingService.default(this.$webex);
317
317
  this.apiAIAssistant = new _ApiAiAssistant.ApiAIAssistant(this.$webex);
318
318
  this.metricsManager = _MetricsManager.default.getInstance({
@@ -370,6 +370,19 @@ class ContactCenter extends _webexCore.WebexPlugin {
370
370
  this.trigger(_types4.TASK_EVENTS.TASK_MERGED, task);
371
371
  };
372
372
 
373
+ /**
374
+ * Handles campaign preview reservation events when a contact is offered to the agent
375
+ * @private
376
+ * @param {ITask} task The campaign reservation task
377
+ */
378
+ handleCampaignPreviewReservation = task => {
379
+ // @ts-ignore
380
+ this.trigger(_types4.TASK_EVENTS.TASK_CAMPAIGN_PREVIEW_RESERVATION, task);
381
+ };
382
+ handleRTDWebsocketMessage = event => {
383
+ this.taskManager.handleRealtimeWebsocketEvent(event);
384
+ };
385
+
373
386
  /**
374
387
  * Sets up event listeners for incoming tasks and task hydration
375
388
  * Subscribes to task events from the task manager
@@ -380,6 +393,7 @@ class ContactCenter extends _webexCore.WebexPlugin {
380
393
  this.taskManager.on(_types4.TASK_EVENTS.TASK_HYDRATE, this.handleTaskHydrate);
381
394
  this.taskManager.on(_types4.TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE, this.handleTaskMultiLoginHydrate);
382
395
  this.taskManager.on(_types4.TASK_EVENTS.TASK_MERGED, this.handleTaskMerged);
396
+ this.taskManager.on(_types4.TASK_EVENTS.TASK_CAMPAIGN_PREVIEW_RESERVATION, this.handleCampaignPreviewReservation);
383
397
  }
384
398
 
385
399
  /**
@@ -419,13 +433,14 @@ class ContactCenter extends _webexCore.WebexPlugin {
419
433
  * ```
420
434
  */
421
435
  async register() {
422
- _loggerProxy.default.info('Starting CC SDK registration', {
436
+ _loggerProxy.default.log('Starting CC SDK registration', {
423
437
  module: _constants.CC_FILE,
424
438
  method: _constants.METHODS.REGISTER
425
439
  });
426
440
  try {
427
441
  this.metricsManager.timeEvent([_constants4.METRIC_EVENT_NAMES.WEBSOCKET_REGISTER_SUCCESS, _constants4.METRIC_EVENT_NAMES.WEBSOCKET_REGISTER_FAILED]);
428
442
  this.setupEventListeners();
443
+ this.services.webSocketManager.on('message', this.handleWebsocketMessage);
429
444
  const resp = await this.connectWebsocket();
430
445
  // Ensure 'dn' is always populated from 'defaultDn'
431
446
  resp.dn = resp.defaultDn;
@@ -489,6 +504,7 @@ class ContactCenter extends _webexCore.WebexPlugin {
489
504
  this.taskManager.off(_types4.TASK_EVENTS.TASK_INCOMING, this.handleIncomingTask);
490
505
  this.taskManager.off(_types4.TASK_EVENTS.TASK_HYDRATE, this.handleTaskHydrate);
491
506
  this.taskManager.off(_types4.TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE, this.handleTaskMultiLoginHydrate);
507
+ this.taskManager.off(_types4.TASK_EVENTS.TASK_CAMPAIGN_PREVIEW_RESERVATION, this.handleCampaignPreviewReservation);
492
508
  this.taskManager.unregisterIncomingCallEvent();
493
509
  this.services.webSocketManager.off('message', this.handleWebsocketMessage);
494
510
  this.services.rtdWebSocketManager.off('message', this.handleRTDWebsocketMessage);
@@ -512,6 +528,9 @@ class ContactCenter extends _webexCore.WebexPlugin {
512
528
  if (this.services.rtdWebSocketManager && !this.services.rtdWebSocketManager.isSocketClosed) {
513
529
  this.services.rtdWebSocketManager.close(false, 'Unregistering the SDK');
514
530
  }
531
+ if (this.services.rtdWebSocketManager && !this.services.rtdWebSocketManager.isSocketClosed) {
532
+ this.services.rtdWebSocketManager.close(false, 'Unregistering the RTD websocket');
533
+ }
515
534
 
516
535
  // Clear any cached agent configuration
517
536
  this.agentConfig = null;
@@ -613,85 +632,89 @@ class ContactCenter extends _webexCore.WebexPlugin {
613
632
  * @private
614
633
  */
615
634
  async connectWebsocket() {
616
- _loggerProxy.default.info('Connecting to websocket', {
635
+ _loggerProxy.default.log('Connecting to websocket', {
617
636
  module: _constants.CC_FILE,
618
637
  method: _constants.METHODS.CONNECT_WEBSOCKET
619
638
  });
620
639
  try {
621
- return this.services.webSocketManager.initWebSocket({
640
+ const data = await this.services.webSocketManager.initWebSocket({
622
641
  body: this.getConnectionConfig(),
623
642
  resource: _constants3.SUBSCRIBE_API
624
- }).then(async data => {
625
- const agentId = data.agentId;
626
- const orgId = this.$webex.credentials.getOrgId();
627
- this.agentConfig = await this.services.config.getAgentConfig(orgId, agentId);
628
- _loggerProxy.default.log(`Agent config is fetched successfully`, {
643
+ });
644
+ const agentId = data.agentId;
645
+ const orgId = this.$webex.credentials.getOrgId();
646
+ this.agentConfig = await this.services.config.getAgentConfig(orgId, agentId);
647
+ _loggerProxy.default.log(`Agent config is fetched successfully`, {
648
+ module: _constants.CC_FILE,
649
+ method: _constants.METHODS.CONNECT_WEBSOCKET
650
+ });
651
+ const configFlags = {
652
+ isEndTaskEnabled: this.agentConfig.isEndTaskEnabled,
653
+ isEndConsultEnabled: this.agentConfig.isEndConsultEnabled,
654
+ webRtcEnabled: this.agentConfig.webRtcEnabled,
655
+ autoWrapup: this.agentConfig.wrapUpData?.wrapUpProps?.autoWrapup ?? false,
656
+ aiFeature: this.agentConfig.aiFeature
657
+ };
658
+ this.taskManager.setConfigFlags(configFlags);
659
+ // TODO: Make profile a singleton to make it available throughout app/sdk so we dont need to inject info everywhere
660
+ this.taskManager.setWrapupData(this.agentConfig.wrapUpData);
661
+ this.taskManager.setAgentId(this.agentConfig.agentId);
662
+ this.taskManager.setWebRtcEnabled(this.agentConfig.webRtcEnabled);
663
+ this.apiAIAssistant.setAIFeatureFlags(this.agentConfig.aiFeature);
664
+
665
+ /**
666
+ * RTD websocket currently supports realtime transcripts and suggested responses.
667
+ * Extend this condition when additional AI RTD features are introduced.
668
+ */
669
+ if (this.agentConfig.aiFeature?.realtimeTranscripts?.enable || this.agentConfig.aiFeature?.suggestedResponses?.enable) {
670
+ _loggerProxy.default.info('Connecting to RTD websocket', {
629
671
  module: _constants.CC_FILE,
630
672
  method: _constants.METHODS.CONNECT_WEBSOCKET
631
673
  });
632
- const configFlags = {
633
- isEndTaskEnabled: this.agentConfig.isEndTaskEnabled,
634
- isEndConsultEnabled: this.agentConfig.isEndConsultEnabled,
635
- webRtcEnabled: this.agentConfig.webRtcEnabled,
636
- autoWrapup: this.agentConfig.wrapUpData?.wrapUpProps?.autoWrapup ?? false,
637
- aiFeature: this.agentConfig.aiFeature
638
- };
639
- this.taskManager.setConfigFlags(configFlags);
640
- // TODO: Make profile a singleton to make it available throughout app/sdk so we dont need to inject info everywhere
641
- this.taskManager.setWrapupData(this.agentConfig.wrapUpData);
642
- this.taskManager.setAgentId(this.agentConfig.agentId);
643
- this.taskManager.setWebRtcEnabled(this.agentConfig.webRtcEnabled);
644
- this.apiAIAssistant.setAIFeatureFlags(this.agentConfig.aiFeature);
645
- /**
646
- * RTD websocket currently supports realtime transcripts and suggested responses.
647
- * Extend this condition when additional AI RTD features are introduced.
648
- */
649
- if (this.agentConfig.aiFeature?.realtimeTranscripts?.enable || this.agentConfig.aiFeature?.suggestedResponses?.enable) {
650
- _loggerProxy.default.info('Connecting to RTD websocket', {
674
+ this.services.rtdWebSocketManager.initWebSocket({
675
+ body: this.getConnectionConfig(),
676
+ resource: _constants3.RTD_SUBSCRIBE_API
677
+ }).then(() => {
678
+ _loggerProxy.default.log('RTD websocket connected successfully', {
651
679
  module: _constants.CC_FILE,
652
680
  method: _constants.METHODS.CONNECT_WEBSOCKET
653
681
  });
654
- this.services.rtdWebSocketManager.initWebSocket({
655
- body: this.getConnectionConfig(),
656
- resource: _constants3.RTD_SUBSCRIBE_API
657
- }).then(() => {
658
- _loggerProxy.default.log('RTD websocket connected successfully', {
659
- module: _constants.CC_FILE,
660
- method: _constants.METHODS.CONNECT_WEBSOCKET
661
- });
662
- this.services.rtdWebSocketManager.on('message', this.handleRTDWebsocketMessage);
663
- }).catch(error => {
664
- _loggerProxy.default.error(`Error connecting to RTD websocket ${error}`, {
665
- module: _constants.CC_FILE,
666
- method: _constants.METHODS.CONNECT_WEBSOCKET
667
- });
682
+ this.services.rtdWebSocketManager.on('message', this.handleRTDWebsocketMessage);
683
+ }).catch(error => {
684
+ _loggerProxy.default.error(`Error connecting to RTD websocket ${error}`, {
685
+ module: _constants.CC_FILE,
686
+ method: _constants.METHODS.CONNECT_WEBSOCKET
668
687
  });
669
- }
670
- if (this.agentConfig.webRtcEnabled && this.agentConfig.loginVoiceOptions.includes(_types.LoginOption.BROWSER) && !this.isWebRTCRegistrationDisabled()) {
671
- this.$webex.internal.mercury.connect().then(() => {
672
- _loggerProxy.default.log('Authentication: webex.internal.mercury.connect successful', {
673
- module: _constants.CC_FILE,
674
- method: _constants.METHODS.CONNECT_WEBSOCKET
675
- });
676
- }).catch(error => {
677
- _loggerProxy.default.error(`Error occurred during mercury.connect() ${error}`, {
678
- module: _constants.CC_FILE,
679
- method: _constants.METHODS.CONNECT_WEBSOCKET
680
- });
688
+ });
689
+ }
690
+ if (this.agentConfig.webRtcEnabled && this.agentConfig.loginVoiceOptions.includes(_types.LoginOption.BROWSER) && !this.isWebRTCRegistrationDisabled()) {
691
+ try {
692
+ await this.$webex.internal.mercury.connect();
693
+ _loggerProxy.default.log('Authentication: webex.internal.mercury.connect successful', {
694
+ module: _constants.CC_FILE,
695
+ method: _constants.METHODS.CONNECT_WEBSOCKET
681
696
  });
682
- } else if (this.isWebRTCRegistrationDisabled()) {
683
- _loggerProxy.default.info('Skipping Mobius registration because disableWebRTCRegistration is enabled', {
697
+ } catch (error) {
698
+ _loggerProxy.default.error(`Error occurred during mercury.connect() ${error}`, {
684
699
  module: _constants.CC_FILE,
685
700
  method: _constants.METHODS.CONNECT_WEBSOCKET
686
701
  });
687
702
  }
688
- if (this.$config && this.$config.allowAutomatedRelogin) {
689
- await this.silentRelogin();
690
- }
691
- return this.agentConfig;
692
- }).catch(error => {
693
- throw error;
694
- });
703
+ } else if (this.isWebRTCRegistrationDisabled()) {
704
+ _loggerProxy.default.info('Skipping Mobius registration because disableWebRTCRegistration is enabled', {
705
+ module: _constants.CC_FILE,
706
+ method: _constants.METHODS.CONNECT_WEBSOCKET
707
+ });
708
+ }
709
+ if (this.$config && this.$config.allowAutomatedRelogin) {
710
+ await this.silentRelogin();
711
+ } else {
712
+ _loggerProxy.default.log('Skipping silent relogin: allowAutomatedRelogin is disabled', {
713
+ module: _constants.CC_FILE,
714
+ method: _constants.METHODS.CONNECT_WEBSOCKET
715
+ });
716
+ }
717
+ return this.agentConfig;
695
718
  } catch (error) {
696
719
  _loggerProxy.default.error(`Error during register: ${error}`, {
697
720
  module: _constants.CC_FILE,
@@ -730,21 +753,27 @@ class ContactCenter extends _webexCore.WebexPlugin {
730
753
  * ```
731
754
  */
732
755
  async stationLogin(data) {
733
- _loggerProxy.default.info('Starting agent station login', {
756
+ const loggerContext = {
734
757
  module: _constants.CC_FILE,
735
758
  method: _constants.METHODS.STATION_LOGIN
736
- });
759
+ };
737
760
  try {
761
+ _loggerProxy.default.log(`Starting agent station login | loginOption: ${data?.loginOption} teamId: ${data?.teamId}`, loggerContext);
738
762
  this.metricsManager.timeEvent([_constants4.METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS, _constants4.METRIC_EVENT_NAMES.STATION_LOGIN_FAILED]);
739
- if (data.loginOption === _types.LoginOption.AGENT_DN && !(0, _Utils.isValidDialNumber)(data.dialNumber)) {
740
- const error = new Error('INVALID_DIAL_NUMBER');
741
- // @ts-ignore - adding custom key to the error object
742
- error.details = {
743
- data: {
744
- reason: 'INVALID_DIAL_NUMBER'
745
- }
746
- };
747
- throw error;
763
+ const dialPlanEntries = this.agentConfig?.dialPlan?.dialPlanEntity ?? [];
764
+ if (data.loginOption === _types.LoginOption.AGENT_DN) {
765
+ _loggerProxy.default.log(`Validating dial number | dialPlanEnabled: ${!!this.agentConfig?.dialPlan} | dialPlanEntryCount: ${dialPlanEntries.length}`, loggerContext);
766
+ if (!(0, _Utils.isValidDialNumber)(data.dialNumber, dialPlanEntries)) {
767
+ _loggerProxy.default.log(`Dial number validation failed | dialNumber: ${data.dialNumber} | dialPlanEntryCount: ${dialPlanEntries.length}`, loggerContext);
768
+ const error = new Error('INVALID_DIAL_NUMBER');
769
+ // @ts-ignore - adding custom key to the error object
770
+ error.details = {
771
+ data: {
772
+ reason: 'INVALID_DIAL_NUMBER'
773
+ }
774
+ };
775
+ throw error;
776
+ }
748
777
  }
749
778
  const loginResponse = await this.services.agent.stationLogin({
750
779
  data: {
@@ -1089,9 +1118,6 @@ class ContactCenter extends _webexCore.WebexPlugin {
1089
1118
  break;
1090
1119
  }
1091
1120
  };
1092
- handleRTDWebsocketMessage = event => {
1093
- this.taskManager.handleRealtimeWebsocketEvent(event);
1094
- };
1095
1121
 
1096
1122
  /**
1097
1123
  * Checks whether Mobius/WebRTC registration should be skipped by config
@@ -1143,13 +1169,13 @@ class ContactCenter extends _webexCore.WebexPlugin {
1143
1169
  async handleConnectionLost(msg) {
1144
1170
  if (msg.isConnectionLost) {
1145
1171
  // TODO: Emit an event saying connection is lost
1146
- _loggerProxy.default.info('event=handleConnectionLost | Connection lost', {
1172
+ _loggerProxy.default.log('event=handleConnectionLost | Connection lost', {
1147
1173
  module: _constants.CC_FILE,
1148
1174
  method: _constants.METHODS.HANDLE_CONNECTION_LOST
1149
1175
  });
1150
1176
  } else if (msg.isSocketReconnected) {
1151
1177
  // TODO: Emit an event saying connection is re-estabilished
1152
- _loggerProxy.default.info('event=handleConnectionReconnect | Connection reconnected attempting to request silent relogin', {
1178
+ _loggerProxy.default.log('event=handleConnectionReconnect | Connection reconnected attempting to request silent relogin', {
1153
1179
  module: _constants.CC_FILE,
1154
1180
  method: _constants.METHODS.HANDLE_CONNECTION_LOST
1155
1181
  });
@@ -1164,7 +1190,7 @@ class ContactCenter extends _webexCore.WebexPlugin {
1164
1190
  * @private
1165
1191
  */
1166
1192
  async silentRelogin() {
1167
- _loggerProxy.default.info('Starting silent relogin process', {
1193
+ _loggerProxy.default.log('Starting silent relogin process', {
1168
1194
  module: _constants.CC_FILE,
1169
1195
  method: _constants.METHODS.SILENT_RELOGIN
1170
1196
  });
@@ -1186,7 +1212,7 @@ class ContactCenter extends _webexCore.WebexPlugin {
1186
1212
  this.agentConfig.currentTeamId = reLoginResponse.data.teamId;
1187
1213
  await this.handleDeviceType(deviceType, dn);
1188
1214
  if (lastStateChangeReason === 'agent-wss-disconnect') {
1189
- _loggerProxy.default.info('event=requestAutoStateChange | Requesting state change to available on socket reconnect', {
1215
+ _loggerProxy.default.log('event=requestAutoStateChange | Requesting state change to available on socket reconnect', {
1190
1216
  module: _constants.CC_FILE,
1191
1217
  method: _constants.METHODS.SILENT_RELOGIN
1192
1218
  });
@@ -1210,8 +1236,6 @@ class ContactCenter extends _webexCore.WebexPlugin {
1210
1236
  }
1211
1237
  this.agentConfig.lastStateAuxCodeId = auxCodeId;
1212
1238
  this.agentConfig.isAgentLoggedIn = true;
1213
- // TODO: https://jira-eng-gpk2.cisco.com/jira/browse/SPARK-626777 Implement the de-register method and close the listener there
1214
- this.services.webSocketManager.on('message', this.handleWebsocketMessage);
1215
1239
  _loggerProxy.default.log(`Silent relogin process completed successfully with login Option: ${reLoginResponse.data.deviceType} teamId: ${reLoginResponse.data.teamId}`, {
1216
1240
  module: _constants.CC_FILE,
1217
1241
  method: _constants.METHODS.SILENT_RELOGIN,
@@ -1434,6 +1458,196 @@ class ContactCenter extends _webexCore.WebexPlugin {
1434
1458
  }
1435
1459
  }
1436
1460
 
1461
+ /**
1462
+ * Accepts a campaign preview contact, initiating the outbound call.
1463
+ *
1464
+ * When a campaign manager reserves a contact for an agent, the agent receives an
1465
+ * `AgentOfferCampaignReservation` event. The agent can then accept the preview contact
1466
+ * to initiate the outbound call.
1467
+ *
1468
+ * @param {PreviewContactPayload} payload - The preview contact payload containing interactionId and campaignId (campaign name, not UUID).
1469
+ * @returns {Promise<TaskResponse>} Promise resolving with agent contact on success.
1470
+ * @throws {Error} If the operation fails (network error, customer unavailable, etc.)
1471
+ *
1472
+ * @example
1473
+ * ```typescript
1474
+ * webex.cc.on('task:campaignPreviewReservation', async (task) => {
1475
+ * const { interactionId } = task.data;
1476
+ * // campaignId is the campaign name (e.g. "MyCampaign"), not a UUID
1477
+ * const campaignId = task.data.interaction.callProcessingDetails.campaignId;
1478
+ *
1479
+ * const result = await webex.cc.acceptPreviewContact({ interactionId, campaignId });
1480
+ * });
1481
+ * ```
1482
+ */
1483
+ async acceptPreviewContact(payload) {
1484
+ _loggerProxy.default.info('Accepting campaign preview contact', {
1485
+ module: _constants.CC_FILE,
1486
+ method: _constants.METHODS.ACCEPT_PREVIEW_CONTACT
1487
+ });
1488
+ try {
1489
+ this.metricsManager.timeEvent([_constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_ACCEPT_SUCCESS, _constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_ACCEPT_FAILED]);
1490
+ const result = await this.services.dialer.acceptPreviewContact({
1491
+ data: payload
1492
+ });
1493
+ this.metricsManager.trackEvent(_constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_ACCEPT_SUCCESS, {
1494
+ ..._MetricsManager.default.getCommonTrackingFieldForAQMResponse(result),
1495
+ interactionId: payload.interactionId,
1496
+ campaignId: payload.campaignId
1497
+ }, ['behavioral', 'business', 'operational']);
1498
+ _loggerProxy.default.log('Campaign preview contact accepted successfully', {
1499
+ module: _constants.CC_FILE,
1500
+ method: _constants.METHODS.ACCEPT_PREVIEW_CONTACT,
1501
+ trackingId: result.trackingId,
1502
+ interactionId: payload.interactionId
1503
+ });
1504
+ return result;
1505
+ } catch (error) {
1506
+ const failure = error.details;
1507
+ this.metricsManager.trackEvent(_constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_ACCEPT_FAILED, {
1508
+ ..._MetricsManager.default.getCommonTrackingFieldForAQMResponseFailed(failure),
1509
+ interactionId: payload.interactionId,
1510
+ campaignId: payload.campaignId
1511
+ }, ['behavioral', 'business', 'operational']);
1512
+ const {
1513
+ error: detailedError
1514
+ } = (0, _Utils.getErrorDetails)(error, _constants.METHODS.ACCEPT_PREVIEW_CONTACT, _constants.CC_FILE);
1515
+ throw detailedError;
1516
+ }
1517
+ }
1518
+
1519
+ /**
1520
+ * Skips a campaign preview contact, requesting the next contact from the campaign.
1521
+ *
1522
+ * When a campaign manager reserves a contact for an agent, the agent receives an
1523
+ * `AgentOfferCampaignReservation` event. Instead of accepting, the agent can skip the
1524
+ * preview contact to move to the next contact in the campaign.
1525
+ *
1526
+ * @param {PreviewContactPayload} payload - The preview contact payload containing interactionId and campaignId (campaign name, not UUID).
1527
+ * @returns {Promise<TaskResponse>} Promise resolving with agent contact on success.
1528
+ * @throws {Error} If the operation fails (network error, etc.)
1529
+ *
1530
+ * @example
1531
+ * ```typescript
1532
+ * webex.cc.on('task:campaignPreviewReservation', async (task) => {
1533
+ * const { interactionId } = task.data;
1534
+ * const campaignId = task.data.interaction.callProcessingDetails.campaignId;
1535
+ *
1536
+ * const result = await webex.cc.skipPreviewContact({ interactionId, campaignId });
1537
+ * });
1538
+ * ```
1539
+ */
1540
+ async skipPreviewContact(payload) {
1541
+ const task = this.taskManager.getTask(payload.interactionId);
1542
+ if (task?.data?.interaction?.callProcessingDetails?.campaignPreviewSkipDisabled === 'true') {
1543
+ _loggerProxy.default.warn('Skip action is disabled for this campaign preview contact', {
1544
+ module: _constants.CC_FILE,
1545
+ method: _constants.METHODS.SKIP_PREVIEW_CONTACT,
1546
+ interactionId: payload.interactionId
1547
+ });
1548
+ throw new Error('Skip action is disabled for this campaign preview contact');
1549
+ }
1550
+ _loggerProxy.default.info('Skipping campaign preview contact', {
1551
+ module: _constants.CC_FILE,
1552
+ method: _constants.METHODS.SKIP_PREVIEW_CONTACT
1553
+ });
1554
+ try {
1555
+ this.metricsManager.timeEvent([_constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_SUCCESS, _constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_FAILED]);
1556
+ const result = await this.services.dialer.skipPreviewContact({
1557
+ data: payload
1558
+ });
1559
+ this.metricsManager.trackEvent(_constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_SUCCESS, {
1560
+ ..._MetricsManager.default.getCommonTrackingFieldForAQMResponse(result),
1561
+ interactionId: payload.interactionId,
1562
+ campaignId: payload.campaignId
1563
+ }, ['behavioral', 'business', 'operational']);
1564
+ _loggerProxy.default.log('Campaign preview contact skipped successfully', {
1565
+ module: _constants.CC_FILE,
1566
+ method: _constants.METHODS.SKIP_PREVIEW_CONTACT,
1567
+ trackingId: result.trackingId,
1568
+ interactionId: payload.interactionId
1569
+ });
1570
+ return result;
1571
+ } catch (error) {
1572
+ const failure = error.details;
1573
+ this.metricsManager.trackEvent(_constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_FAILED, {
1574
+ ..._MetricsManager.default.getCommonTrackingFieldForAQMResponseFailed(failure),
1575
+ interactionId: payload.interactionId,
1576
+ campaignId: payload.campaignId
1577
+ }, ['behavioral', 'business', 'operational']);
1578
+ const {
1579
+ error: detailedError
1580
+ } = (0, _Utils.getErrorDetails)(error, _constants.METHODS.SKIP_PREVIEW_CONTACT, _constants.CC_FILE);
1581
+ throw detailedError;
1582
+ }
1583
+ }
1584
+
1585
+ /**
1586
+ * Removes a campaign preview contact from the campaign list entirely.
1587
+ *
1588
+ * When a campaign manager reserves a contact for an agent, the agent receives an
1589
+ * `AgentOfferCampaignReservation` event. Instead of accepting or skipping, the agent can
1590
+ * remove the preview contact to permanently take it out of the campaign contact list.
1591
+ *
1592
+ * @param {PreviewContactPayload} payload - The preview contact payload containing interactionId and campaignId (campaign name, not UUID).
1593
+ * @returns {Promise<TaskResponse>} Promise resolving with agent contact on success.
1594
+ * @throws {Error} If the operation fails (network error, etc.)
1595
+ *
1596
+ * @example
1597
+ * ```typescript
1598
+ * webex.cc.on('task:campaignPreviewReservation', async (task) => {
1599
+ * const { interactionId } = task.data;
1600
+ * const campaignId = task.data.interaction.callProcessingDetails.campaignId;
1601
+ *
1602
+ * const result = await webex.cc.removePreviewContact({ interactionId, campaignId });
1603
+ * });
1604
+ * ```
1605
+ */
1606
+ async removePreviewContact(payload) {
1607
+ const task = this.taskManager.getTask(payload.interactionId);
1608
+ if (task?.data?.interaction?.callProcessingDetails?.campaignPreviewRemoveDisabled === 'true') {
1609
+ _loggerProxy.default.warn('Remove action is disabled for this campaign preview contact', {
1610
+ module: _constants.CC_FILE,
1611
+ method: _constants.METHODS.REMOVE_PREVIEW_CONTACT,
1612
+ interactionId: payload.interactionId
1613
+ });
1614
+ throw new Error('Remove action is disabled for this campaign preview contact');
1615
+ }
1616
+ _loggerProxy.default.info('Removing campaign preview contact', {
1617
+ module: _constants.CC_FILE,
1618
+ method: _constants.METHODS.REMOVE_PREVIEW_CONTACT
1619
+ });
1620
+ try {
1621
+ this.metricsManager.timeEvent([_constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_SUCCESS, _constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_FAILED]);
1622
+ const result = await this.services.dialer.removePreviewContact({
1623
+ data: payload
1624
+ });
1625
+ this.metricsManager.trackEvent(_constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_SUCCESS, {
1626
+ ..._MetricsManager.default.getCommonTrackingFieldForAQMResponse(result),
1627
+ interactionId: payload.interactionId,
1628
+ campaignId: payload.campaignId
1629
+ }, ['behavioral', 'business', 'operational']);
1630
+ _loggerProxy.default.log('Campaign preview contact removed successfully', {
1631
+ module: _constants.CC_FILE,
1632
+ method: _constants.METHODS.REMOVE_PREVIEW_CONTACT,
1633
+ trackingId: result.trackingId,
1634
+ interactionId: payload.interactionId
1635
+ });
1636
+ return result;
1637
+ } catch (error) {
1638
+ const failure = error.details;
1639
+ this.metricsManager.trackEvent(_constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_FAILED, {
1640
+ ..._MetricsManager.default.getCommonTrackingFieldForAQMResponseFailed(failure),
1641
+ interactionId: payload.interactionId,
1642
+ campaignId: payload.campaignId
1643
+ }, ['behavioral', 'business', 'operational']);
1644
+ const {
1645
+ error: detailedError
1646
+ } = (0, _Utils.getErrorDetails)(error, _constants.METHODS.REMOVE_PREVIEW_CONTACT, _constants.CC_FILE);
1647
+ throw detailedError;
1648
+ }
1649
+ }
1650
+
1437
1651
  /**
1438
1652
  * Fetches outdial ANI (Automatic Number Identification) entries for an outdial ANI ID.
1439
1653
  *