@webex/contact-center 3.12.0-next.8 → 3.12.0-next.81

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 (205) hide show
  1. package/AGENTS.md +438 -0
  2. package/ai-docs/README.md +131 -0
  3. package/ai-docs/RULES.md +455 -0
  4. package/ai-docs/patterns/event-driven-patterns.md +485 -0
  5. package/ai-docs/patterns/testing-patterns.md +480 -0
  6. package/ai-docs/patterns/typescript-patterns.md +365 -0
  7. package/ai-docs/templates/README.md +102 -0
  8. package/ai-docs/templates/documentation/create-agents-md.md +240 -0
  9. package/ai-docs/templates/documentation/create-architecture-md.md +295 -0
  10. package/ai-docs/templates/existing-service/bug-fix.md +254 -0
  11. package/ai-docs/templates/existing-service/feature-enhancement.md +450 -0
  12. package/ai-docs/templates/new-method/00-master.md +80 -0
  13. package/ai-docs/templates/new-method/01-requirements.md +232 -0
  14. package/ai-docs/templates/new-method/02-implementation.md +295 -0
  15. package/ai-docs/templates/new-method/03-tests.md +201 -0
  16. package/ai-docs/templates/new-method/04-validation.md +141 -0
  17. package/ai-docs/templates/new-service/00-master.md +109 -0
  18. package/ai-docs/templates/new-service/01-pre-questions.md +159 -0
  19. package/ai-docs/templates/new-service/02-code-generation.md +346 -0
  20. package/ai-docs/templates/new-service/03-integration.md +178 -0
  21. package/ai-docs/templates/new-service/04-test-generation.md +205 -0
  22. package/ai-docs/templates/new-service/05-validation.md +145 -0
  23. package/dist/cc.js +265 -29
  24. package/dist/cc.js.map +1 -1
  25. package/dist/config.js +6 -0
  26. package/dist/config.js.map +1 -1
  27. package/dist/constants.js +16 -1
  28. package/dist/constants.js.map +1 -1
  29. package/dist/index.js +20 -5
  30. package/dist/index.js.map +1 -1
  31. package/dist/metrics/behavioral-events.js +101 -0
  32. package/dist/metrics/behavioral-events.js.map +1 -1
  33. package/dist/metrics/constants.js +23 -4
  34. package/dist/metrics/constants.js.map +1 -1
  35. package/dist/services/ApiAiAssistant.js +74 -3
  36. package/dist/services/ApiAiAssistant.js.map +1 -1
  37. package/dist/services/UserPreference.js +427 -0
  38. package/dist/services/UserPreference.js.map +1 -0
  39. package/dist/services/config/Util.js +3 -3
  40. package/dist/services/config/Util.js.map +1 -1
  41. package/dist/services/config/constants.js +23 -2
  42. package/dist/services/config/constants.js.map +1 -1
  43. package/dist/services/config/types.js +49 -9
  44. package/dist/services/config/types.js.map +1 -1
  45. package/dist/services/core/Err.js.map +1 -1
  46. package/dist/services/core/Utils.js +107 -32
  47. package/dist/services/core/Utils.js.map +1 -1
  48. package/dist/services/core/websocket/WebSocketManager.js +2 -1
  49. package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
  50. package/dist/services/core/websocket/types.js.map +1 -1
  51. package/dist/services/index.js +1 -1
  52. package/dist/services/index.js.map +1 -1
  53. package/dist/services/task/Task.js +688 -0
  54. package/dist/services/task/Task.js.map +1 -0
  55. package/dist/services/task/TaskFactory.js +45 -0
  56. package/dist/services/task/TaskFactory.js.map +1 -0
  57. package/dist/services/task/TaskManager.js +725 -526
  58. package/dist/services/task/TaskManager.js.map +1 -1
  59. package/dist/services/task/TaskUtils.js +162 -26
  60. package/dist/services/task/TaskUtils.js.map +1 -1
  61. package/dist/services/task/constants.js +9 -2
  62. package/dist/services/task/constants.js.map +1 -1
  63. package/dist/services/task/dialer.js +78 -0
  64. package/dist/services/task/dialer.js.map +1 -1
  65. package/dist/services/task/digital/Digital.js +77 -0
  66. package/dist/services/task/digital/Digital.js.map +1 -0
  67. package/dist/services/task/state-machine/TaskStateMachine.js +837 -0
  68. package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -0
  69. package/dist/services/task/state-machine/actions.js +543 -0
  70. package/dist/services/task/state-machine/actions.js.map +1 -0
  71. package/dist/services/task/state-machine/constants.js +161 -0
  72. package/dist/services/task/state-machine/constants.js.map +1 -0
  73. package/dist/services/task/state-machine/guards.js +340 -0
  74. package/dist/services/task/state-machine/guards.js.map +1 -0
  75. package/dist/services/task/state-machine/index.js +53 -0
  76. package/dist/services/task/state-machine/index.js.map +1 -0
  77. package/dist/services/task/state-machine/types.js +54 -0
  78. package/dist/services/task/state-machine/types.js.map +1 -0
  79. package/dist/services/task/state-machine/uiControlsComputer.js +553 -0
  80. package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -0
  81. package/dist/services/task/taskDataNormalizer.js +99 -0
  82. package/dist/services/task/taskDataNormalizer.js.map +1 -0
  83. package/dist/services/task/types.js +212 -4
  84. package/dist/services/task/types.js.map +1 -1
  85. package/dist/services/task/voice/Voice.js +1042 -0
  86. package/dist/services/task/voice/Voice.js.map +1 -0
  87. package/dist/services/task/voice/WebRTC.js +149 -0
  88. package/dist/services/task/voice/WebRTC.js.map +1 -0
  89. package/dist/types/cc.d.ts +94 -1
  90. package/dist/types/config.d.ts +6 -0
  91. package/dist/types/constants.d.ts +16 -1
  92. package/dist/types/index.d.ts +21 -6
  93. package/dist/types/metrics/constants.d.ts +19 -1
  94. package/dist/types/services/ApiAiAssistant.d.ts +11 -3
  95. package/dist/types/services/UserPreference.d.ts +118 -0
  96. package/dist/types/services/config/constants.d.ts +21 -0
  97. package/dist/types/services/config/types.d.ts +171 -10
  98. package/dist/types/services/core/Err.d.ts +4 -0
  99. package/dist/types/services/core/Utils.d.ts +33 -13
  100. package/dist/types/services/core/websocket/WebSocketManager.d.ts +1 -0
  101. package/dist/types/services/core/websocket/types.d.ts +1 -1
  102. package/dist/types/services/index.d.ts +1 -1
  103. package/dist/types/services/task/Task.d.ts +157 -0
  104. package/dist/types/services/task/TaskFactory.d.ts +12 -0
  105. package/dist/types/services/task/TaskUtils.d.ts +46 -2
  106. package/dist/types/services/task/constants.d.ts +7 -0
  107. package/dist/types/services/task/dialer.d.ts +30 -0
  108. package/dist/types/services/task/digital/Digital.d.ts +22 -0
  109. package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +1144 -0
  110. package/dist/types/services/task/state-machine/actions.d.ts +10 -0
  111. package/dist/types/services/task/state-machine/constants.d.ts +107 -0
  112. package/dist/types/services/task/state-machine/guards.d.ts +90 -0
  113. package/dist/types/services/task/state-machine/index.d.ts +13 -0
  114. package/dist/types/services/task/state-machine/types.d.ts +267 -0
  115. package/dist/types/services/task/state-machine/uiControlsComputer.d.ts +9 -0
  116. package/dist/types/services/task/taskDataNormalizer.d.ts +10 -0
  117. package/dist/types/services/task/types.d.ts +603 -66
  118. package/dist/types/services/task/voice/Voice.d.ts +184 -0
  119. package/dist/types/services/task/voice/WebRTC.d.ts +53 -0
  120. package/dist/types/types.d.ts +94 -0
  121. package/dist/types/webex.d.ts +1 -0
  122. package/dist/types.js +85 -0
  123. package/dist/types.js.map +1 -1
  124. package/dist/webex.js +14 -2
  125. package/dist/webex.js.map +1 -1
  126. package/package.json +15 -12
  127. package/src/cc.ts +329 -30
  128. package/src/config.ts +6 -0
  129. package/src/constants.ts +16 -1
  130. package/src/index.ts +23 -5
  131. package/src/metrics/ai-docs/AGENTS.md +348 -0
  132. package/src/metrics/ai-docs/ARCHITECTURE.md +336 -0
  133. package/src/metrics/behavioral-events.ts +106 -0
  134. package/src/metrics/constants.ts +23 -4
  135. package/src/services/ApiAiAssistant.ts +104 -3
  136. package/src/services/UserPreference.ts +509 -0
  137. package/src/services/agent/ai-docs/AGENTS.md +238 -0
  138. package/src/services/agent/ai-docs/ARCHITECTURE.md +302 -0
  139. package/src/services/ai-docs/AGENTS.md +384 -0
  140. package/src/services/config/Util.ts +3 -3
  141. package/src/services/config/ai-docs/AGENTS.md +253 -0
  142. package/src/services/config/ai-docs/ARCHITECTURE.md +424 -0
  143. package/src/services/config/constants.ts +25 -1
  144. package/src/services/config/types.ts +174 -11
  145. package/src/services/core/Err.ts +2 -0
  146. package/src/services/core/Utils.ts +123 -37
  147. package/src/services/core/ai-docs/AGENTS.md +379 -0
  148. package/src/services/core/ai-docs/ARCHITECTURE.md +696 -0
  149. package/src/services/core/websocket/WebSocketManager.ts +2 -0
  150. package/src/services/core/websocket/types.ts +1 -1
  151. package/src/services/index.ts +1 -1
  152. package/src/services/task/Task.ts +837 -0
  153. package/src/services/task/TaskFactory.ts +55 -0
  154. package/src/services/task/TaskManager.ts +738 -613
  155. package/src/services/task/TaskUtils.ts +205 -25
  156. package/src/services/task/ai-docs/AGENTS.md +455 -0
  157. package/src/services/task/ai-docs/ARCHITECTURE.md +585 -0
  158. package/src/services/task/constants.ts +7 -0
  159. package/src/services/task/dialer.ts +80 -0
  160. package/src/services/task/digital/Digital.ts +95 -0
  161. package/src/services/task/state-machine/TaskStateMachine.ts +1077 -0
  162. package/src/services/task/state-machine/actions.ts +685 -0
  163. package/src/services/task/state-machine/ai-docs/AGENTS.md +495 -0
  164. package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +1135 -0
  165. package/src/services/task/state-machine/constants.ts +172 -0
  166. package/src/services/task/state-machine/guards.ts +406 -0
  167. package/src/services/task/state-machine/index.ts +28 -0
  168. package/src/services/task/state-machine/types.ts +241 -0
  169. package/src/services/task/state-machine/uiControlsComputer.ts +867 -0
  170. package/src/services/task/taskDataNormalizer.ts +137 -0
  171. package/src/services/task/types.ts +710 -71
  172. package/src/services/task/voice/Voice.ts +1267 -0
  173. package/src/services/task/voice/WebRTC.ts +187 -0
  174. package/src/types.ts +122 -2
  175. package/src/utils/AGENTS.md +276 -0
  176. package/src/webex.js +2 -0
  177. package/test/unit/spec/cc.ts +343 -23
  178. package/test/unit/spec/logger-proxy.ts +70 -0
  179. package/test/unit/spec/services/ApiAiAssistant.ts +122 -17
  180. package/test/unit/spec/services/UserPreference.ts +401 -0
  181. package/test/unit/spec/services/WebCallingService.ts +7 -1
  182. package/test/unit/spec/services/config/index.ts +30 -30
  183. package/test/unit/spec/services/core/Utils.ts +425 -8
  184. package/test/unit/spec/services/core/websocket/WebSocketManager.ts +66 -40
  185. package/test/unit/spec/services/task/AutoWrapup.ts +63 -0
  186. package/test/unit/spec/services/task/Task.ts +477 -0
  187. package/test/unit/spec/services/task/TaskFactory.ts +62 -0
  188. package/test/unit/spec/services/task/TaskManager.ts +832 -1702
  189. package/test/unit/spec/services/task/TaskUtils.ts +206 -0
  190. package/test/unit/spec/services/task/dialer.ts +190 -0
  191. package/test/unit/spec/services/task/digital/Digital.ts +105 -0
  192. package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +1825 -0
  193. package/test/unit/spec/services/task/state-machine/guards.ts +479 -0
  194. package/test/unit/spec/services/task/state-machine/types.ts +18 -0
  195. package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +2020 -0
  196. package/test/unit/spec/services/task/taskTestUtils.ts +87 -0
  197. package/test/unit/spec/services/task/voice/Voice.ts +631 -0
  198. package/test/unit/spec/services/task/voice/WebRTC.ts +235 -0
  199. package/umd/contact-center.min.js +2 -2
  200. package/umd/contact-center.min.js.map +1 -1
  201. package/dist/services/task/index.js +0 -1525
  202. package/dist/services/task/index.js.map +0 -1
  203. package/dist/types/services/task/index.d.ts +0 -650
  204. package/src/services/task/index.ts +0 -1801
  205. package/test/unit/spec/services/task/index.ts +0 -2184
package/dist/cc.js CHANGED
@@ -26,6 +26,7 @@ var _EntryPoint = require("./services/EntryPoint");
26
26
  var _AddressBook = require("./services/AddressBook");
27
27
  var _Queue = require("./services/Queue");
28
28
  var _ApiAiAssistant = require("./services/ApiAiAssistant");
29
+ var _UserPreference = require("./services/UserPreference");
29
30
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
30
31
  /**
31
32
  * @module CCPlugin
@@ -274,6 +275,36 @@ class ContactCenter extends _webexCore.WebexPlugin {
274
275
  * ```
275
276
  */
276
277
 
278
+ /**
279
+ * API instance for managing Webex Contact Center user preferences
280
+ * Provides functionality to get, create, update, and delete user preferences
281
+ * @type {UserPreference}
282
+ * @public
283
+ * @example
284
+ * ```typescript
285
+ * const cc = webex.cc;
286
+ * await cc.register();
287
+ * await cc.stationLogin({ teamId: 'team123', loginOption: 'BROWSER' });
288
+ *
289
+ * // Get user preferences for current user
290
+ * const preferences = await cc.userPreference.getUserPreference();
291
+ *
292
+ * // Create new user preferences
293
+ * const newPrefs = await cc.userPreference.createUserPreference({
294
+ * userId: 'user123',
295
+ * preferences: { e911Reminder: true }
296
+ * });
297
+ *
298
+ * // Update user preferences
299
+ * const updatedPrefs = await cc.userPreference.updateUserPreference('user123', {
300
+ * preferences: { e911Reminder: false }
301
+ * });
302
+ *
303
+ * // Delete user preferences
304
+ * await cc.userPreference.deleteUserPreference('user123');
305
+ * ```
306
+ */
307
+
277
308
  /**
278
309
  * API instance for AI Assistant operations such as transcript controls.
279
310
  * @type {ApiAIAssistant}
@@ -301,6 +332,7 @@ class ContactCenter extends _webexCore.WebexPlugin {
301
332
  this.$webex.once(_constants.READY, () => {
302
333
  // @ts-ignore
303
334
  this.$config = this.config;
335
+ this.validatePluginConfig();
304
336
 
305
337
  /**
306
338
  * This is used for handling the async requests by sending webex.request and wait for corresponding websocket event.
@@ -312,13 +344,12 @@ class ContactCenter extends _webexCore.WebexPlugin {
312
344
  webex: this.$webex,
313
345
  connectionConfig: this.getConnectionConfig()
314
346
  });
315
- this.services.webSocketManager.on('message', this.handleWebsocketMessage);
316
347
  this.webCallingService = new _WebCallingService.default(this.$webex);
317
348
  this.apiAIAssistant = new _ApiAiAssistant.ApiAIAssistant(this.$webex);
318
349
  this.metricsManager = _MetricsManager.default.getInstance({
319
350
  webex: this.$webex
320
351
  });
321
- this.taskManager = _TaskManager.default.getTaskManager(this.apiAIAssistant, this.services.contact, this.webCallingService, this.services.webSocketManager);
352
+ this.taskManager = _TaskManager.default.getTaskManager(this.apiAIAssistant, this.services.contact, this.webCallingService, this.services.webSocketManager, this.services.rtdWebSocketManager);
322
353
  this.incomingTaskListener();
323
354
 
324
355
  // Initialize API instances
@@ -326,6 +357,7 @@ class ContactCenter extends _webexCore.WebexPlugin {
326
357
  this.entryPoint = new _EntryPoint.EntryPoint(this.$webex);
327
358
  this.addressBook = new _AddressBook.AddressBook(this.$webex, () => this.agentConfig?.addressBookId);
328
359
  this.queue = new _Queue.Queue(this.$webex);
360
+ this.userPreference = new _UserPreference.UserPreference(this.$webex, () => this.agentConfig?.agentId);
329
361
  _loggerProxy.default.initialize(this.$webex.logger);
330
362
  });
331
363
  }
@@ -350,6 +382,16 @@ class ContactCenter extends _webexCore.WebexPlugin {
350
382
  this.trigger(_types4.TASK_EVENTS.TASK_HYDRATE, task);
351
383
  };
352
384
 
385
+ /**
386
+ * Handles multi-login hydrate events for SDK instances without Mobius registration
387
+ * @private
388
+ * @param {ITask} task The task object associated with the multi-login hydrate
389
+ */
390
+ handleTaskMultiLoginHydrate = task => {
391
+ // @ts-ignore
392
+ this.trigger(_types4.TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE, task);
393
+ };
394
+
353
395
  /**
354
396
  * Handles task merged events when tasks are combined eg: EPDN merge/transfer
355
397
  * @private
@@ -369,8 +411,8 @@ class ContactCenter extends _webexCore.WebexPlugin {
369
411
  // @ts-ignore
370
412
  this.trigger(_types4.TASK_EVENTS.TASK_CAMPAIGN_PREVIEW_RESERVATION, task);
371
413
  };
372
- handleRTDWebsocketMessage = payload => {
373
- this.taskManager.handleRealtimeWebsocketEvent(payload);
414
+ handleRTDWebsocketMessage = event => {
415
+ this.taskManager.handleRealtimeWebsocketEvent(event);
374
416
  };
375
417
 
376
418
  /**
@@ -381,6 +423,7 @@ class ContactCenter extends _webexCore.WebexPlugin {
381
423
  incomingTaskListener() {
382
424
  this.taskManager.on(_types4.TASK_EVENTS.TASK_INCOMING, this.handleIncomingTask);
383
425
  this.taskManager.on(_types4.TASK_EVENTS.TASK_HYDRATE, this.handleTaskHydrate);
426
+ this.taskManager.on(_types4.TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE, this.handleTaskMultiLoginHydrate);
384
427
  this.taskManager.on(_types4.TASK_EVENTS.TASK_MERGED, this.handleTaskMerged);
385
428
  this.taskManager.on(_types4.TASK_EVENTS.TASK_CAMPAIGN_PREVIEW_RESERVATION, this.handleCampaignPreviewReservation);
386
429
  }
@@ -422,13 +465,14 @@ class ContactCenter extends _webexCore.WebexPlugin {
422
465
  * ```
423
466
  */
424
467
  async register() {
425
- _loggerProxy.default.info('Starting CC SDK registration', {
468
+ _loggerProxy.default.log('Starting CC SDK registration', {
426
469
  module: _constants.CC_FILE,
427
470
  method: _constants.METHODS.REGISTER
428
471
  });
429
472
  try {
430
473
  this.metricsManager.timeEvent([_constants4.METRIC_EVENT_NAMES.WEBSOCKET_REGISTER_SUCCESS, _constants4.METRIC_EVENT_NAMES.WEBSOCKET_REGISTER_FAILED]);
431
474
  this.setupEventListeners();
475
+ this.services.webSocketManager.on('message', this.handleWebsocketMessage);
432
476
  const resp = await this.connectWebsocket();
433
477
  // Ensure 'dn' is always populated from 'defaultDn'
434
478
  resp.dn = resp.defaultDn;
@@ -491,6 +535,7 @@ class ContactCenter extends _webexCore.WebexPlugin {
491
535
  this.metricsManager.timeEvent([_constants4.METRIC_EVENT_NAMES.WEBSOCKET_DEREGISTER_SUCCESS, _constants4.METRIC_EVENT_NAMES.WEBSOCKET_DEREGISTER_FAIL]);
492
536
  this.taskManager.off(_types4.TASK_EVENTS.TASK_INCOMING, this.handleIncomingTask);
493
537
  this.taskManager.off(_types4.TASK_EVENTS.TASK_HYDRATE, this.handleTaskHydrate);
538
+ this.taskManager.off(_types4.TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE, this.handleTaskMultiLoginHydrate);
494
539
  this.taskManager.off(_types4.TASK_EVENTS.TASK_CAMPAIGN_PREVIEW_RESERVATION, this.handleCampaignPreviewReservation);
495
540
  this.taskManager.unregisterIncomingCallEvent();
496
541
  this.services.webSocketManager.off('message', this.handleWebsocketMessage);
@@ -512,6 +557,9 @@ class ContactCenter extends _webexCore.WebexPlugin {
512
557
  if (!this.services.webSocketManager.isSocketClosed) {
513
558
  this.services.webSocketManager.close(false, 'Unregistering the SDK');
514
559
  }
560
+ if (this.services.rtdWebSocketManager && !this.services.rtdWebSocketManager.isSocketClosed) {
561
+ this.services.rtdWebSocketManager.close(false, 'Unregistering the SDK');
562
+ }
515
563
  if (this.services.rtdWebSocketManager && !this.services.rtdWebSocketManager.isSocketClosed) {
516
564
  this.services.rtdWebSocketManager.close(false, 'Unregistering the RTD websocket');
517
565
  }
@@ -616,7 +664,7 @@ class ContactCenter extends _webexCore.WebexPlugin {
616
664
  * @private
617
665
  */
618
666
  async connectWebsocket() {
619
- _loggerProxy.default.info('Connecting to websocket', {
667
+ _loggerProxy.default.log('Connecting to websocket', {
620
668
  module: _constants.CC_FILE,
621
669
  method: _constants.METHODS.CONNECT_WEBSOCKET
622
670
  });
@@ -632,18 +680,30 @@ class ContactCenter extends _webexCore.WebexPlugin {
632
680
  module: _constants.CC_FILE,
633
681
  method: _constants.METHODS.CONNECT_WEBSOCKET
634
682
  });
635
-
683
+ const configFlags = {
684
+ isEndTaskEnabled: this.agentConfig.isEndTaskEnabled,
685
+ isEndConsultEnabled: this.agentConfig.isEndConsultEnabled,
686
+ webRtcEnabled: this.agentConfig.webRtcEnabled,
687
+ autoWrapup: this.agentConfig.wrapUpData?.wrapUpProps?.autoWrapup ?? false,
688
+ aiFeature: this.agentConfig.aiFeature
689
+ };
690
+ this.taskManager.setConfigFlags(configFlags);
636
691
  // TODO: Make profile a singleton to make it available throughout app/sdk so we dont need to inject info everywhere
637
692
  this.taskManager.setWrapupData(this.agentConfig.wrapUpData);
638
693
  this.taskManager.setAgentId(this.agentConfig.agentId);
639
694
  this.taskManager.setWebRtcEnabled(this.agentConfig.webRtcEnabled);
640
695
  this.apiAIAssistant.setAIFeatureFlags(this.agentConfig.aiFeature);
641
- if (this.agentConfig.aiFeature?.realtimeTranscripts?.enable) {
696
+
697
+ /**
698
+ * RTD websocket currently supports realtime transcripts and suggested responses.
699
+ * Extend this condition when additional AI RTD features are introduced.
700
+ */
701
+ if (this.agentConfig.aiFeature?.realtimeTranscripts?.enable || this.agentConfig.aiFeature?.suggestedResponses?.enable) {
642
702
  _loggerProxy.default.info('Connecting to RTD websocket', {
643
703
  module: _constants.CC_FILE,
644
704
  method: _constants.METHODS.CONNECT_WEBSOCKET
645
705
  });
646
- await this.services.rtdWebSocketManager.initWebSocket({
706
+ this.services.rtdWebSocketManager.initWebSocket({
647
707
  body: this.getConnectionConfig(),
648
708
  resource: _constants3.RTD_SUBSCRIBE_API
649
709
  }).then(() => {
@@ -653,13 +713,13 @@ class ContactCenter extends _webexCore.WebexPlugin {
653
713
  });
654
714
  this.services.rtdWebSocketManager.on('message', this.handleRTDWebsocketMessage);
655
715
  }).catch(error => {
656
- _loggerProxy.default.error(`Error during RTD websocket setup: ${error}`, {
716
+ _loggerProxy.default.error(`Error connecting to RTD websocket ${error}`, {
657
717
  module: _constants.CC_FILE,
658
718
  method: _constants.METHODS.CONNECT_WEBSOCKET
659
719
  });
660
720
  });
661
721
  }
662
- if (this.agentConfig.webRtcEnabled && this.agentConfig.loginVoiceOptions.includes(_types.LoginOption.BROWSER)) {
722
+ if (this.agentConfig.webRtcEnabled && this.agentConfig.loginVoiceOptions.includes(_types.LoginOption.BROWSER) && !this.isWebRTCRegistrationDisabled()) {
663
723
  try {
664
724
  await this.$webex.internal.mercury.connect();
665
725
  _loggerProxy.default.log('Authentication: webex.internal.mercury.connect successful', {
@@ -672,9 +732,19 @@ class ContactCenter extends _webexCore.WebexPlugin {
672
732
  method: _constants.METHODS.CONNECT_WEBSOCKET
673
733
  });
674
734
  }
735
+ } else if (this.isWebRTCRegistrationDisabled()) {
736
+ _loggerProxy.default.info('Skipping Mobius registration because disableWebRTCRegistration is enabled', {
737
+ module: _constants.CC_FILE,
738
+ method: _constants.METHODS.CONNECT_WEBSOCKET
739
+ });
675
740
  }
676
741
  if (this.$config && this.$config.allowAutomatedRelogin) {
677
742
  await this.silentRelogin();
743
+ } else {
744
+ _loggerProxy.default.log('Skipping silent relogin: allowAutomatedRelogin is disabled', {
745
+ module: _constants.CC_FILE,
746
+ method: _constants.METHODS.CONNECT_WEBSOCKET
747
+ });
678
748
  }
679
749
  return this.agentConfig;
680
750
  } catch (error) {
@@ -715,22 +785,27 @@ class ContactCenter extends _webexCore.WebexPlugin {
715
785
  * ```
716
786
  */
717
787
  async stationLogin(data) {
718
- _loggerProxy.default.info('Starting agent station login', {
788
+ const loggerContext = {
719
789
  module: _constants.CC_FILE,
720
790
  method: _constants.METHODS.STATION_LOGIN
721
- });
791
+ };
722
792
  try {
793
+ _loggerProxy.default.log(`Starting agent station login | loginOption: ${data?.loginOption} teamId: ${data?.teamId}`, loggerContext);
723
794
  this.metricsManager.timeEvent([_constants4.METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS, _constants4.METRIC_EVENT_NAMES.STATION_LOGIN_FAILED]);
724
795
  const dialPlanEntries = this.agentConfig?.dialPlan?.dialPlanEntity ?? [];
725
- if (data.loginOption === _types.LoginOption.AGENT_DN && !(0, _Utils.isValidDialNumber)(data.dialNumber, dialPlanEntries)) {
726
- const error = new Error('INVALID_DIAL_NUMBER');
727
- // @ts-ignore - adding custom key to the error object
728
- error.details = {
729
- data: {
730
- reason: 'INVALID_DIAL_NUMBER'
731
- }
732
- };
733
- throw error;
796
+ if (data.loginOption === _types.LoginOption.AGENT_DN) {
797
+ _loggerProxy.default.log(`Validating dial number | dialPlanEnabled: ${!!this.agentConfig?.dialPlan} | dialPlanEntryCount: ${dialPlanEntries.length}`, loggerContext);
798
+ if (!(0, _Utils.isValidDialNumber)(data.dialNumber, dialPlanEntries)) {
799
+ _loggerProxy.default.log(`Dial number validation failed | dialNumber: ${data.dialNumber} | dialPlanEntryCount: ${dialPlanEntries.length}`, loggerContext);
800
+ const error = new Error('INVALID_DIAL_NUMBER');
801
+ // @ts-ignore - adding custom key to the error object
802
+ error.details = {
803
+ data: {
804
+ reason: 'INVALID_DIAL_NUMBER'
805
+ }
806
+ };
807
+ throw error;
808
+ }
734
809
  }
735
810
  const loginResponse = await this.services.agent.stationLogin({
736
811
  data: {
@@ -746,8 +821,13 @@ class ContactCenter extends _webexCore.WebexPlugin {
746
821
  auxCodeId: _constants.EMPTY_STRING
747
822
  }
748
823
  });
749
- if (this.agentConfig.webRtcEnabled && data.loginOption === _types.LoginOption.BROWSER) {
824
+ if (this.agentConfig.webRtcEnabled && data.loginOption === _types.LoginOption.BROWSER && !this.isWebRTCRegistrationDisabled()) {
750
825
  await this.webCallingService.registerWebCallingLine();
826
+ } else if (this.agentConfig.webRtcEnabled && data.loginOption === _types.LoginOption.BROWSER && this.isWebRTCRegistrationDisabled()) {
827
+ _loggerProxy.default.info('Skipping web calling line registration because disableWebRTCRegistration is enabled', {
828
+ module: _constants.CC_FILE,
829
+ method: _constants.METHODS.STATION_LOGIN
830
+ });
751
831
  }
752
832
  const resp = await loginResponse;
753
833
  const {
@@ -1071,6 +1151,25 @@ class ContactCenter extends _webexCore.WebexPlugin {
1071
1151
  }
1072
1152
  };
1073
1153
 
1154
+ /**
1155
+ * Checks whether Mobius/WebRTC registration should be skipped by config
1156
+ * @returns {boolean} True when browser WebRTC registration is disabled
1157
+ * @private
1158
+ */
1159
+ isWebRTCRegistrationDisabled() {
1160
+ return this.$config?.disableWebRTCRegistration === true;
1161
+ }
1162
+
1163
+ /**
1164
+ * Validates contact-center plugin configuration before service initialization
1165
+ * @private
1166
+ */
1167
+ validatePluginConfig() {
1168
+ if (this.$config?.disableWebRTCRegistration === true && this.$config?.allowMultiLogin === false) {
1169
+ throw new Error('Invalid Contact Center configuration: disableWebRTCRegistration cannot be true when allowMultiLogin is false. Enable allowMultiLogin or allow WebRTC registration so an SDK instance can receive Mobius/WebRTC task events.');
1170
+ }
1171
+ }
1172
+
1074
1173
  /**
1075
1174
  * Initializes event listeners for the Contact Center service
1076
1175
  * Sets up handlers for connection state changes and other core events
@@ -1102,13 +1201,13 @@ class ContactCenter extends _webexCore.WebexPlugin {
1102
1201
  async handleConnectionLost(msg) {
1103
1202
  if (msg.isConnectionLost) {
1104
1203
  // TODO: Emit an event saying connection is lost
1105
- _loggerProxy.default.info('event=handleConnectionLost | Connection lost', {
1204
+ _loggerProxy.default.log('event=handleConnectionLost | Connection lost', {
1106
1205
  module: _constants.CC_FILE,
1107
1206
  method: _constants.METHODS.HANDLE_CONNECTION_LOST
1108
1207
  });
1109
1208
  } else if (msg.isSocketReconnected) {
1110
1209
  // TODO: Emit an event saying connection is re-estabilished
1111
- _loggerProxy.default.info('event=handleConnectionReconnect | Connection reconnected attempting to request silent relogin', {
1210
+ _loggerProxy.default.log('event=handleConnectionReconnect | Connection reconnected attempting to request silent relogin', {
1112
1211
  module: _constants.CC_FILE,
1113
1212
  method: _constants.METHODS.HANDLE_CONNECTION_LOST
1114
1213
  });
@@ -1123,7 +1222,7 @@ class ContactCenter extends _webexCore.WebexPlugin {
1123
1222
  * @private
1124
1223
  */
1125
1224
  async silentRelogin() {
1126
- _loggerProxy.default.info('Starting silent relogin process', {
1225
+ _loggerProxy.default.log('Starting silent relogin process', {
1127
1226
  module: _constants.CC_FILE,
1128
1227
  method: _constants.METHODS.SILENT_RELOGIN
1129
1228
  });
@@ -1145,7 +1244,7 @@ class ContactCenter extends _webexCore.WebexPlugin {
1145
1244
  this.agentConfig.currentTeamId = reLoginResponse.data.teamId;
1146
1245
  await this.handleDeviceType(deviceType, dn);
1147
1246
  if (lastStateChangeReason === 'agent-wss-disconnect') {
1148
- _loggerProxy.default.info('event=requestAutoStateChange | Requesting state change to available on socket reconnect', {
1247
+ _loggerProxy.default.log('event=requestAutoStateChange | Requesting state change to available on socket reconnect', {
1149
1248
  module: _constants.CC_FILE,
1150
1249
  method: _constants.METHODS.SILENT_RELOGIN
1151
1250
  });
@@ -1169,8 +1268,6 @@ class ContactCenter extends _webexCore.WebexPlugin {
1169
1268
  }
1170
1269
  this.agentConfig.lastStateAuxCodeId = auxCodeId;
1171
1270
  this.agentConfig.isAgentLoggedIn = true;
1172
- // TODO: https://jira-eng-gpk2.cisco.com/jira/browse/SPARK-626777 Implement the de-register method and close the listener there
1173
- this.services.webSocketManager.on('message', this.handleWebsocketMessage);
1174
1271
  _loggerProxy.default.log(`Silent relogin process completed successfully with login Option: ${reLoginResponse.data.deviceType} teamId: ${reLoginResponse.data.teamId}`, {
1175
1272
  module: _constants.CC_FILE,
1176
1273
  method: _constants.METHODS.SILENT_RELOGIN,
@@ -1205,6 +1302,13 @@ class ContactCenter extends _webexCore.WebexPlugin {
1205
1302
  this.agentConfig.deviceType = deviceType;
1206
1303
  switch (deviceType) {
1207
1304
  case _types.LoginOption.BROWSER:
1305
+ if (this.isWebRTCRegistrationDisabled()) {
1306
+ _loggerProxy.default.info('Skipping web calling line registration because disableWebRTCRegistration is enabled', {
1307
+ module: _constants.CC_FILE,
1308
+ method: _constants.METHODS.HANDLE_DEVICE_TYPE
1309
+ });
1310
+ break;
1311
+ }
1208
1312
  try {
1209
1313
  await this.webCallingService.registerWebCallingLine();
1210
1314
  } catch (error) {
@@ -1444,6 +1548,138 @@ class ContactCenter extends _webexCore.WebexPlugin {
1444
1548
  }
1445
1549
  }
1446
1550
 
1551
+ /**
1552
+ * Skips a campaign preview contact, requesting the next contact from the campaign.
1553
+ *
1554
+ * When a campaign manager reserves a contact for an agent, the agent receives an
1555
+ * `AgentOfferCampaignReservation` event. Instead of accepting, the agent can skip the
1556
+ * preview contact to move to the next contact in the campaign.
1557
+ *
1558
+ * @param {PreviewContactPayload} payload - The preview contact payload containing interactionId and campaignId (campaign name, not UUID).
1559
+ * @returns {Promise<TaskResponse>} Promise resolving with agent contact on success.
1560
+ * @throws {Error} If the operation fails (network error, etc.)
1561
+ *
1562
+ * @example
1563
+ * ```typescript
1564
+ * webex.cc.on('task:campaignPreviewReservation', async (task) => {
1565
+ * const { interactionId } = task.data;
1566
+ * const campaignId = task.data.interaction.callProcessingDetails.campaignId;
1567
+ *
1568
+ * const result = await webex.cc.skipPreviewContact({ interactionId, campaignId });
1569
+ * });
1570
+ * ```
1571
+ */
1572
+ async skipPreviewContact(payload) {
1573
+ const task = this.taskManager.getTask(payload.interactionId);
1574
+ if (task?.data?.interaction?.callProcessingDetails?.campaignPreviewSkipDisabled === 'true') {
1575
+ _loggerProxy.default.warn('Skip action is disabled for this campaign preview contact', {
1576
+ module: _constants.CC_FILE,
1577
+ method: _constants.METHODS.SKIP_PREVIEW_CONTACT,
1578
+ interactionId: payload.interactionId
1579
+ });
1580
+ throw new Error('Skip action is disabled for this campaign preview contact');
1581
+ }
1582
+ _loggerProxy.default.info('Skipping campaign preview contact', {
1583
+ module: _constants.CC_FILE,
1584
+ method: _constants.METHODS.SKIP_PREVIEW_CONTACT
1585
+ });
1586
+ try {
1587
+ this.metricsManager.timeEvent([_constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_SUCCESS, _constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_FAILED]);
1588
+ const result = await this.services.dialer.skipPreviewContact({
1589
+ data: payload
1590
+ });
1591
+ this.metricsManager.trackEvent(_constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_SUCCESS, {
1592
+ ..._MetricsManager.default.getCommonTrackingFieldForAQMResponse(result),
1593
+ interactionId: payload.interactionId,
1594
+ campaignId: payload.campaignId
1595
+ }, ['behavioral', 'business', 'operational']);
1596
+ _loggerProxy.default.log('Campaign preview contact skipped successfully', {
1597
+ module: _constants.CC_FILE,
1598
+ method: _constants.METHODS.SKIP_PREVIEW_CONTACT,
1599
+ trackingId: result.trackingId,
1600
+ interactionId: payload.interactionId
1601
+ });
1602
+ return result;
1603
+ } catch (error) {
1604
+ const failure = error.details;
1605
+ this.metricsManager.trackEvent(_constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_FAILED, {
1606
+ ..._MetricsManager.default.getCommonTrackingFieldForAQMResponseFailed(failure),
1607
+ interactionId: payload.interactionId,
1608
+ campaignId: payload.campaignId
1609
+ }, ['behavioral', 'business', 'operational']);
1610
+ const {
1611
+ error: detailedError
1612
+ } = (0, _Utils.getErrorDetails)(error, _constants.METHODS.SKIP_PREVIEW_CONTACT, _constants.CC_FILE);
1613
+ throw detailedError;
1614
+ }
1615
+ }
1616
+
1617
+ /**
1618
+ * Removes a campaign preview contact from the campaign list entirely.
1619
+ *
1620
+ * When a campaign manager reserves a contact for an agent, the agent receives an
1621
+ * `AgentOfferCampaignReservation` event. Instead of accepting or skipping, the agent can
1622
+ * remove the preview contact to permanently take it out of the campaign contact list.
1623
+ *
1624
+ * @param {PreviewContactPayload} payload - The preview contact payload containing interactionId and campaignId (campaign name, not UUID).
1625
+ * @returns {Promise<TaskResponse>} Promise resolving with agent contact on success.
1626
+ * @throws {Error} If the operation fails (network error, etc.)
1627
+ *
1628
+ * @example
1629
+ * ```typescript
1630
+ * webex.cc.on('task:campaignPreviewReservation', async (task) => {
1631
+ * const { interactionId } = task.data;
1632
+ * const campaignId = task.data.interaction.callProcessingDetails.campaignId;
1633
+ *
1634
+ * const result = await webex.cc.removePreviewContact({ interactionId, campaignId });
1635
+ * });
1636
+ * ```
1637
+ */
1638
+ async removePreviewContact(payload) {
1639
+ const task = this.taskManager.getTask(payload.interactionId);
1640
+ if (task?.data?.interaction?.callProcessingDetails?.campaignPreviewRemoveDisabled === 'true') {
1641
+ _loggerProxy.default.warn('Remove action is disabled for this campaign preview contact', {
1642
+ module: _constants.CC_FILE,
1643
+ method: _constants.METHODS.REMOVE_PREVIEW_CONTACT,
1644
+ interactionId: payload.interactionId
1645
+ });
1646
+ throw new Error('Remove action is disabled for this campaign preview contact');
1647
+ }
1648
+ _loggerProxy.default.info('Removing campaign preview contact', {
1649
+ module: _constants.CC_FILE,
1650
+ method: _constants.METHODS.REMOVE_PREVIEW_CONTACT
1651
+ });
1652
+ try {
1653
+ this.metricsManager.timeEvent([_constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_SUCCESS, _constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_FAILED]);
1654
+ const result = await this.services.dialer.removePreviewContact({
1655
+ data: payload
1656
+ });
1657
+ this.metricsManager.trackEvent(_constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_SUCCESS, {
1658
+ ..._MetricsManager.default.getCommonTrackingFieldForAQMResponse(result),
1659
+ interactionId: payload.interactionId,
1660
+ campaignId: payload.campaignId
1661
+ }, ['behavioral', 'business', 'operational']);
1662
+ _loggerProxy.default.log('Campaign preview contact removed successfully', {
1663
+ module: _constants.CC_FILE,
1664
+ method: _constants.METHODS.REMOVE_PREVIEW_CONTACT,
1665
+ trackingId: result.trackingId,
1666
+ interactionId: payload.interactionId
1667
+ });
1668
+ return result;
1669
+ } catch (error) {
1670
+ const failure = error.details;
1671
+ this.metricsManager.trackEvent(_constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_FAILED, {
1672
+ ..._MetricsManager.default.getCommonTrackingFieldForAQMResponseFailed(failure),
1673
+ interactionId: payload.interactionId,
1674
+ campaignId: payload.campaignId
1675
+ }, ['behavioral', 'business', 'operational']);
1676
+ const {
1677
+ error: detailedError
1678
+ } = (0, _Utils.getErrorDetails)(error, _constants.METHODS.REMOVE_PREVIEW_CONTACT, _constants.CC_FILE);
1679
+ throw detailedError;
1680
+ }
1681
+ }
1682
+
1447
1683
  /**
1448
1684
  * Fetches outdial ANI (Automatic Number Identification) entries for an outdial ANI ID.
1449
1685
  *