@webex/contact-center 3.12.0-next.12 → 3.12.0-next.121
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/.sdd/manifest.json +884 -0
- package/AGENTS.md +94 -0
- package/ai-docs/ARCHITECTURE.md +168 -0
- package/ai-docs/CONTRACTS.md +51 -0
- package/ai-docs/GETTING_STARTED.md +168 -0
- package/ai-docs/GLOSSARY.md +43 -0
- package/ai-docs/README.md +138 -0
- package/ai-docs/REVIEW_CHECKLIST.md +41 -0
- package/ai-docs/RULES.md +444 -0
- package/ai-docs/SECURITY.md +52 -0
- package/ai-docs/SERVICE_STATE.md +48 -0
- package/ai-docs/SPEC_INDEX.md +65 -0
- package/ai-docs/adr/0001-spec-source-policy.md +55 -0
- package/ai-docs/adr/README.md +8 -0
- package/ai-docs/adr/_adr-template.md +31 -0
- package/ai-docs/contact-center-spec.md +359 -0
- package/ai-docs/features/consult-transfer-list-policy/spec/feature-spec.md +362 -0
- package/ai-docs/features/generated-spec-conformance-fidelity-remediation/spec/feature-spec.md +117 -0
- package/ai-docs/features/residual-warning-coverage-completion/spec/feature-spec.md +203 -0
- package/ai-docs/features/validator-code-fidelity-drift-fix/spec/feature-spec.md +315 -0
- package/ai-docs/patterns/event-driven-patterns.md +485 -0
- package/ai-docs/patterns/testing-patterns.md +480 -0
- package/ai-docs/patterns/typescript-patterns.md +365 -0
- package/ai-docs/templates/README.md +102 -0
- package/ai-docs/templates/documentation/create-agents-md.md +240 -0
- package/ai-docs/templates/documentation/create-architecture-md.md +295 -0
- package/ai-docs/templates/existing-service/bug-fix.md +254 -0
- package/ai-docs/templates/existing-service/feature-enhancement.md +450 -0
- package/ai-docs/templates/new-method/00-master.md +80 -0
- package/ai-docs/templates/new-method/01-requirements.md +232 -0
- package/ai-docs/templates/new-method/02-implementation.md +295 -0
- package/ai-docs/templates/new-method/03-tests.md +201 -0
- package/ai-docs/templates/new-method/04-validation.md +141 -0
- package/ai-docs/templates/new-service/00-master.md +109 -0
- package/ai-docs/templates/new-service/01-pre-questions.md +159 -0
- package/ai-docs/templates/new-service/02-code-generation.md +346 -0
- package/ai-docs/templates/new-service/03-integration.md +178 -0
- package/ai-docs/templates/new-service/04-test-generation.md +205 -0
- package/ai-docs/templates/new-service/05-validation.md +145 -0
- package/dist/cc.js +808 -40
- package/dist/cc.js.map +1 -1
- package/dist/config.js +13 -0
- package/dist/config.js.map +1 -1
- package/dist/constants.js +27 -3
- package/dist/constants.js.map +1 -1
- package/dist/index.js +20 -5
- package/dist/index.js.map +1 -1
- package/dist/metrics/MetricsManager.js +16 -0
- package/dist/metrics/MetricsManager.js.map +1 -1
- package/dist/metrics/behavioral-events.js +205 -0
- package/dist/metrics/behavioral-events.js.map +1 -1
- package/dist/metrics/constants.js +43 -4
- package/dist/metrics/constants.js.map +1 -1
- package/dist/services/AddressBook.js +18 -15
- package/dist/services/AddressBook.js.map +1 -1
- package/dist/services/AnswerCallOnWebexService.js +202 -0
- package/dist/services/AnswerCallOnWebexService.js.map +1 -0
- package/dist/services/ApiAiAssistant.js +153 -8
- package/dist/services/ApiAiAssistant.js.map +1 -1
- package/dist/services/EntryPoint.js +46 -68
- package/dist/services/EntryPoint.js.map +1 -1
- package/dist/services/Queue.js +27 -22
- package/dist/services/Queue.js.map +1 -1
- package/dist/services/UserPreference.js +427 -0
- package/dist/services/UserPreference.js.map +1 -0
- package/dist/services/WebexCrossClientService.js +222 -0
- package/dist/services/WebexCrossClientService.js.map +1 -0
- package/dist/services/WxAppTelephonyMercurySync.js +108 -0
- package/dist/services/WxAppTelephonyMercurySync.js.map +1 -0
- package/dist/services/config/Util.js +6 -3
- package/dist/services/config/Util.js.map +1 -1
- package/dist/services/config/constants.js +33 -8
- package/dist/services/config/constants.js.map +1 -1
- package/dist/services/config/types.js +53 -9
- package/dist/services/config/types.js.map +1 -1
- package/dist/services/core/Err.js.map +1 -1
- package/dist/services/core/Utils.js +107 -32
- package/dist/services/core/Utils.js.map +1 -1
- package/dist/services/core/WebexRequest.js +6 -2
- package/dist/services/core/WebexRequest.js.map +1 -1
- package/dist/services/core/aqm-reqs.js +28 -14
- package/dist/services/core/aqm-reqs.js.map +1 -1
- package/dist/services/core/types.js.map +1 -1
- package/dist/services/core/websocket/WebSocketManager.js +2 -1
- package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
- package/dist/services/core/websocket/types.js.map +1 -1
- package/dist/services/index.js +1 -1
- package/dist/services/index.js.map +1 -1
- package/dist/services/task/Task.js +754 -0
- package/dist/services/task/Task.js.map +1 -0
- package/dist/services/task/TaskFactory.js +49 -0
- package/dist/services/task/TaskFactory.js.map +1 -0
- package/dist/services/task/TaskManager.js +1053 -520
- package/dist/services/task/TaskManager.js.map +1 -1
- package/dist/services/task/TaskUtils.js +211 -27
- package/dist/services/task/TaskUtils.js.map +1 -1
- package/dist/services/task/WebexCallingUtils.js +70 -0
- package/dist/services/task/WebexCallingUtils.js.map +1 -0
- package/dist/services/task/constants.js +12 -2
- package/dist/services/task/constants.js.map +1 -1
- package/dist/services/task/contact.js +29 -0
- package/dist/services/task/contact.js.map +1 -1
- package/dist/services/task/dialer.js +78 -0
- package/dist/services/task/dialer.js.map +1 -1
- package/dist/services/task/digital/Digital.js +78 -0
- package/dist/services/task/digital/Digital.js.map +1 -0
- package/dist/services/task/state-machine/TaskStateMachine.js +954 -0
- package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -0
- package/dist/services/task/state-machine/actions.js +572 -0
- package/dist/services/task/state-machine/actions.js.map +1 -0
- package/dist/services/task/state-machine/constants.js +161 -0
- package/dist/services/task/state-machine/constants.js.map +1 -0
- package/dist/services/task/state-machine/guards.js +379 -0
- package/dist/services/task/state-machine/guards.js.map +1 -0
- package/dist/services/task/state-machine/index.js +53 -0
- package/dist/services/task/state-machine/index.js.map +1 -0
- package/dist/services/task/state-machine/types.js +54 -0
- package/dist/services/task/state-machine/types.js.map +1 -0
- package/dist/services/task/state-machine/uiControlsComputer.js +703 -0
- package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -0
- package/dist/services/task/taskDataNormalizer.js +99 -0
- package/dist/services/task/taskDataNormalizer.js.map +1 -0
- package/dist/services/task/types.js +228 -5
- package/dist/services/task/types.js.map +1 -1
- package/dist/services/task/voice/Voice.js +1447 -0
- package/dist/services/task/voice/Voice.js.map +1 -0
- package/dist/services/task/voice/WebRTC.js +152 -0
- package/dist/services/task/voice/WebRTC.js.map +1 -0
- package/dist/services/task/voice/wxAppVoiceMethods.js +354 -0
- package/dist/services/task/voice/wxAppVoiceMethods.js.map +1 -0
- package/dist/services/wxAppDiagnosticLogging.js +122 -0
- package/dist/services/wxAppDiagnosticLogging.js.map +1 -0
- package/dist/services/wxAppTelephonyUtils.js +19 -0
- package/dist/services/wxAppTelephonyUtils.js.map +1 -0
- package/dist/types/cc.d.ts +172 -5
- package/dist/types/config.d.ts +13 -0
- package/dist/types/constants.d.ts +25 -1
- package/dist/types/index.d.ts +24 -7
- package/dist/types/metrics/MetricsManager.d.ts +6 -0
- package/dist/types/metrics/constants.d.ts +38 -1
- package/dist/types/services/AddressBook.d.ts +2 -1
- package/dist/types/services/AnswerCallOnWebexService.d.ts +38 -0
- package/dist/types/services/ApiAiAssistant.d.ts +22 -4
- package/dist/types/services/EntryPoint.d.ts +7 -5
- package/dist/types/services/Queue.d.ts +5 -3
- package/dist/types/services/UserPreference.d.ts +118 -0
- package/dist/types/services/WebexCrossClientService.d.ts +32 -0
- package/dist/types/services/WxAppTelephonyMercurySync.d.ts +28 -0
- package/dist/types/services/config/constants.d.ts +29 -5
- package/dist/types/services/config/types.d.ts +184 -10
- package/dist/types/services/core/Err.d.ts +6 -0
- package/dist/types/services/core/Utils.d.ts +33 -13
- package/dist/types/services/core/WebexRequest.d.ts +1 -0
- package/dist/types/services/core/types.d.ts +2 -0
- package/dist/types/services/core/websocket/WebSocketManager.d.ts +1 -0
- package/dist/types/services/core/websocket/types.d.ts +1 -1
- package/dist/types/services/index.d.ts +1 -1
- package/dist/types/services/task/Task.d.ts +175 -0
- package/dist/types/services/task/TaskFactory.d.ts +13 -0
- package/dist/types/services/task/TaskUtils.d.ts +48 -2
- package/dist/types/services/task/WebexCallingUtils.d.ts +11 -0
- package/dist/types/services/task/constants.d.ts +10 -0
- package/dist/types/services/task/contact.d.ts +4 -0
- package/dist/types/services/task/dialer.d.ts +30 -0
- package/dist/types/services/task/digital/Digital.d.ts +22 -0
- package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +1356 -0
- package/dist/types/services/task/state-machine/actions.d.ts +10 -0
- package/dist/types/services/task/state-machine/constants.d.ts +107 -0
- package/dist/types/services/task/state-machine/guards.d.ts +103 -0
- package/dist/types/services/task/state-machine/index.d.ts +13 -0
- package/dist/types/services/task/state-machine/types.d.ts +277 -0
- package/dist/types/services/task/state-machine/uiControlsComputer.d.ts +9 -0
- package/dist/types/services/task/taskDataNormalizer.d.ts +10 -0
- package/dist/types/services/task/types.d.ts +680 -66
- package/dist/types/services/task/voice/Voice.d.ts +227 -0
- package/dist/types/services/task/voice/WebRTC.d.ts +53 -0
- package/dist/types/services/task/voice/wxAppVoiceMethods.d.ts +55 -0
- package/dist/types/services/wxAppDiagnosticLogging.d.ts +51 -0
- package/dist/types/services/wxAppTelephonyUtils.d.ts +5 -0
- package/dist/types/types.d.ts +149 -8
- package/dist/types/utils/PageCache.d.ts +20 -3
- package/dist/types/webex.d.ts +1 -0
- package/dist/types.js +125 -4
- package/dist/types.js.map +1 -1
- package/dist/utils/PageCache.js +19 -5
- package/dist/utils/PageCache.js.map +1 -1
- package/dist/webex.js +14 -2
- package/dist/webex.js.map +1 -1
- package/package.json +16 -12
- package/src/cc.ts +986 -42
- package/src/config.ts +13 -0
- package/src/constants.ts +25 -1
- package/src/index.ts +25 -5
- package/src/metrics/MetricsManager.ts +16 -0
- package/src/metrics/ai-docs/AGENTS.md +350 -0
- package/src/metrics/ai-docs/ARCHITECTURE.md +338 -0
- package/src/metrics/ai-docs/metrics-spec.md +922 -0
- package/src/metrics/behavioral-events.ts +212 -0
- package/src/metrics/constants.ts +47 -4
- package/src/services/AddressBook.ts +17 -6
- package/src/services/AnswerCallOnWebexService.ts +239 -0
- package/src/services/ApiAiAssistant.ts +203 -8
- package/src/services/EntryPoint.ts +59 -60
- package/src/services/Queue.ts +29 -12
- package/src/services/UserPreference.ts +509 -0
- package/src/services/WebexCrossClientService.ts +293 -0
- package/src/services/WxAppTelephonyMercurySync.ts +142 -0
- package/src/services/agent/ai-docs/AGENTS.md +240 -0
- package/src/services/agent/ai-docs/ARCHITECTURE.md +304 -0
- package/src/services/agent/ai-docs/agent-spec.md +505 -0
- package/src/services/ai-docs/AGENTS.md +386 -0
- package/src/services/ai-docs/services-spec.md +497 -0
- package/src/services/config/Util.ts +6 -3
- package/src/services/config/ai-docs/AGENTS.md +255 -0
- package/src/services/config/ai-docs/ARCHITECTURE.md +426 -0
- package/src/services/config/ai-docs/config-spec.md +675 -0
- package/src/services/config/constants.ts +35 -7
- package/src/services/config/types.ts +186 -11
- package/src/services/core/Err.ts +3 -0
- package/src/services/core/Utils.ts +123 -37
- package/src/services/core/WebexRequest.ts +3 -1
- package/src/services/core/ai-docs/AGENTS.md +381 -0
- package/src/services/core/ai-docs/ARCHITECTURE.md +698 -0
- package/src/services/core/ai-docs/core-spec.md +787 -0
- package/src/services/core/aqm-reqs.ts +30 -15
- package/src/services/core/types.ts +2 -0
- package/src/services/core/websocket/WebSocketManager.ts +2 -0
- package/src/services/core/websocket/types.ts +1 -1
- package/src/services/index.ts +1 -1
- package/src/services/task/Task.ts +908 -0
- package/src/services/task/TaskFactory.ts +60 -0
- package/src/services/task/TaskManager.ts +1239 -608
- package/src/services/task/TaskUtils.ts +303 -25
- package/src/services/task/WebexCallingUtils.ts +136 -0
- package/src/services/task/ai-docs/AGENTS.md +457 -0
- package/src/services/task/ai-docs/ARCHITECTURE.md +595 -0
- package/src/services/task/ai-docs/task-spec.md +1470 -0
- package/src/services/task/constants.ts +10 -0
- package/src/services/task/contact.ts +30 -0
- package/src/services/task/dialer.ts +80 -0
- package/src/services/task/digital/Digital.ts +97 -0
- package/src/services/task/state-machine/TaskStateMachine.ts +1293 -0
- package/src/services/task/state-machine/actions.ts +741 -0
- package/src/services/task/state-machine/ai-docs/AGENTS.md +460 -0
- package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +1145 -0
- package/src/services/task/state-machine/ai-docs/task-state-machine-spec.md +2207 -0
- package/src/services/task/state-machine/constants.ts +172 -0
- package/src/services/task/state-machine/guards.ts +442 -0
- package/src/services/task/state-machine/index.ts +28 -0
- package/src/services/task/state-machine/types.ts +258 -0
- package/src/services/task/state-machine/uiControlsComputer.ts +1135 -0
- package/src/services/task/taskDataNormalizer.ts +137 -0
- package/src/services/task/types.ts +819 -70
- package/src/services/task/voice/Voice.ts +1809 -0
- package/src/services/task/voice/WebRTC.ts +191 -0
- package/src/services/task/voice/wxAppVoiceMethods.ts +516 -0
- package/src/services/wxAppDiagnosticLogging.ts +174 -0
- package/src/services/wxAppTelephonyUtils.ts +14 -0
- package/src/types.ts +199 -11
- package/src/utils/AGENTS.md +289 -0
- package/src/utils/PageCache.ts +38 -5
- package/src/utils/ai-docs/utils-spec.md +391 -0
- package/src/webex.js +2 -0
- package/test/unit/spec/cc.ts +1947 -124
- package/test/unit/spec/logger-proxy.ts +70 -0
- package/test/unit/spec/metrics/MetricsManager.ts +25 -0
- package/test/unit/spec/metrics/behavioral-events.ts +60 -0
- package/test/unit/spec/services/AddressBook.ts +37 -6
- package/test/unit/spec/services/AnswerCallOnWebexService.ts +264 -0
- package/test/unit/spec/services/ApiAiAssistant.ts +178 -20
- package/test/unit/spec/services/EntryPoint.ts +87 -40
- package/test/unit/spec/services/Queue.ts +123 -12
- package/test/unit/spec/services/UserPreference.ts +401 -0
- package/test/unit/spec/services/WebCallingService.ts +7 -1
- package/test/unit/spec/services/WebexCrossClientService.ts +467 -0
- package/test/unit/spec/services/WxAppTelephonyMercurySync.ts +136 -0
- package/test/unit/spec/services/config/Util.ts +85 -0
- package/test/unit/spec/services/config/index.ts +30 -30
- package/test/unit/spec/services/core/Utils.ts +425 -8
- package/test/unit/spec/services/core/WebexRequest.ts +3 -1
- package/test/unit/spec/services/core/aqm-reqs.ts +113 -1
- package/test/unit/spec/services/core/websocket/WebSocketManager.ts +66 -40
- package/test/unit/spec/services/task/AutoWrapup.ts +63 -0
- package/test/unit/spec/services/task/Task.ts +677 -0
- package/test/unit/spec/services/task/TaskFactory.ts +99 -0
- package/test/unit/spec/services/task/TaskManager.ts +1972 -1549
- package/test/unit/spec/services/task/TaskUtils.ts +235 -0
- package/test/unit/spec/services/task/WebexCallingUtils.ts +153 -0
- package/test/unit/spec/services/task/contact.ts +33 -0
- package/test/unit/spec/services/task/dialer.ts +190 -0
- package/test/unit/spec/services/task/digital/Digital.ts +105 -0
- package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +3459 -0
- package/test/unit/spec/services/task/state-machine/guards.ts +839 -0
- package/test/unit/spec/services/task/state-machine/types.ts +18 -0
- package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +3101 -0
- package/test/unit/spec/services/task/taskTestUtils.ts +87 -0
- package/test/unit/spec/services/task/voice/Voice.ts +1903 -0
- package/test/unit/spec/services/task/voice/WebRTC.ts +235 -0
- package/test/unit/spec/services/task/voice/wxAppVoiceMethods.ts +603 -0
- package/test/unit/spec/services/wxAppDiagnosticLogging.ts +143 -0
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
- package/dist/services/task/index.js +0 -1525
- package/dist/services/task/index.js.map +0 -1
- package/dist/types/services/task/index.d.ts +0 -650
- package/src/services/task/index.ts +0 -1801
- package/test/unit/spec/services/task/index.ts +0 -2184
package/src/cc.ts
CHANGED
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
UploadLogsResponse,
|
|
26
26
|
UpdateDeviceTypeResponse,
|
|
27
27
|
GenericError,
|
|
28
|
+
ConfigFlags,
|
|
28
29
|
} from './types';
|
|
29
30
|
import {
|
|
30
31
|
READY,
|
|
@@ -55,6 +56,10 @@ import {
|
|
|
55
56
|
import {ConnectionLostDetails} from './services/core/websocket/types';
|
|
56
57
|
import TaskManager from './services/task/TaskManager';
|
|
57
58
|
import WebCallingService from './services/WebCallingService';
|
|
59
|
+
import AnswerCallOnWebexService from './services/AnswerCallOnWebexService';
|
|
60
|
+
import WebexCrossClientService from './services/WebexCrossClientService';
|
|
61
|
+
import WxAppTelephonyMercurySync from './services/WxAppTelephonyMercurySync';
|
|
62
|
+
import {logWxAppSessionReadiness} from './services/wxAppDiagnosticLogging';
|
|
58
63
|
import {
|
|
59
64
|
ITask,
|
|
60
65
|
TASK_EVENTS,
|
|
@@ -69,6 +74,7 @@ import {EntryPoint} from './services/EntryPoint';
|
|
|
69
74
|
import {AddressBook} from './services/AddressBook';
|
|
70
75
|
import {Queue} from './services/Queue';
|
|
71
76
|
import {ApiAIAssistant} from './services/ApiAiAssistant';
|
|
77
|
+
import {UserPreference} from './services/UserPreference';
|
|
72
78
|
import type {
|
|
73
79
|
EntryPointListResponse,
|
|
74
80
|
EntryPointSearchParams,
|
|
@@ -230,6 +236,34 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
230
236
|
*/
|
|
231
237
|
private webCallingService: WebCallingService;
|
|
232
238
|
|
|
239
|
+
/**
|
|
240
|
+
* REST telephony for wxApp thick-client answer (WXCC-6026)
|
|
241
|
+
* @private
|
|
242
|
+
*/
|
|
243
|
+
private answerCallOnWebexService: AnswerCallOnWebexService;
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* usersub cross-client state for Webex App toast suppression
|
|
247
|
+
* @private
|
|
248
|
+
*/
|
|
249
|
+
private webexCrossClientService: WebexCrossClientService;
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Mercury telephony mute sync for wxApp thick-client answer
|
|
253
|
+
* @private
|
|
254
|
+
*/
|
|
255
|
+
private wxAppTelephonyMercurySync: WxAppTelephonyMercurySync;
|
|
256
|
+
|
|
257
|
+
/** True when wxApp mute sync opened Mercury (Extension/DN-only profiles). */
|
|
258
|
+
private wxAppMercuryConnectedByCc = false;
|
|
259
|
+
|
|
260
|
+
/** True when wxApp mute sync registered the Webex device. */
|
|
261
|
+
private wxAppDeviceRegisteredByCc = false;
|
|
262
|
+
|
|
263
|
+
private static readonly WXAPP_FALSE_PUBLISH_RETRY_DELAY_MS = 30_000;
|
|
264
|
+
private static readonly WXAPP_FALSE_PUBLISH_MAX_RETRIES = 3;
|
|
265
|
+
private wxAppFalsePublishRetryTimer?: ReturnType<typeof setTimeout>;
|
|
266
|
+
|
|
233
267
|
/**
|
|
234
268
|
* Core service managers for Contact Center operations
|
|
235
269
|
* Includes agent, connection, and configuration services
|
|
@@ -325,7 +359,38 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
325
359
|
* });
|
|
326
360
|
* ```
|
|
327
361
|
*/
|
|
328
|
-
|
|
362
|
+
public queue: Queue;
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* API instance for managing Webex Contact Center user preferences
|
|
366
|
+
* Provides functionality to get, create, update, and delete user preferences
|
|
367
|
+
* @type {UserPreference}
|
|
368
|
+
* @public
|
|
369
|
+
* @example
|
|
370
|
+
* ```typescript
|
|
371
|
+
* const cc = webex.cc;
|
|
372
|
+
* await cc.register();
|
|
373
|
+
* await cc.stationLogin({ teamId: 'team123', loginOption: 'BROWSER' });
|
|
374
|
+
*
|
|
375
|
+
* // Get user preferences for current user
|
|
376
|
+
* const preferences = await cc.userPreference.getUserPreference();
|
|
377
|
+
*
|
|
378
|
+
* // Create new user preferences
|
|
379
|
+
* const newPrefs = await cc.userPreference.createUserPreference({
|
|
380
|
+
* userId: 'user123',
|
|
381
|
+
* preferences: { e911Reminder: true }
|
|
382
|
+
* });
|
|
383
|
+
*
|
|
384
|
+
* // Update user preferences
|
|
385
|
+
* const updatedPrefs = await cc.userPreference.updateUserPreference('user123', {
|
|
386
|
+
* preferences: { e911Reminder: false }
|
|
387
|
+
* });
|
|
388
|
+
*
|
|
389
|
+
* // Delete user preferences
|
|
390
|
+
* await cc.userPreference.deleteUserPreference('user123');
|
|
391
|
+
* ```
|
|
392
|
+
*/
|
|
393
|
+
public userPreference: UserPreference;
|
|
329
394
|
|
|
330
395
|
/**
|
|
331
396
|
* API instance for AI Assistant operations such as transcript controls.
|
|
@@ -357,6 +422,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
357
422
|
this.$webex.once(READY, () => {
|
|
358
423
|
// @ts-ignore
|
|
359
424
|
this.$config = this.config;
|
|
425
|
+
this.validatePluginConfig();
|
|
360
426
|
|
|
361
427
|
/**
|
|
362
428
|
* This is used for handling the async requests by sending webex.request and wait for corresponding websocket event.
|
|
@@ -369,17 +435,21 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
369
435
|
webex: this.$webex,
|
|
370
436
|
connectionConfig: this.getConnectionConfig(),
|
|
371
437
|
});
|
|
372
|
-
this.services.webSocketManager.on('message', this.handleWebsocketMessage);
|
|
373
438
|
|
|
374
439
|
this.webCallingService = new WebCallingService(this.$webex);
|
|
440
|
+
this.answerCallOnWebexService = new AnswerCallOnWebexService(this.$webex);
|
|
441
|
+
this.webexCrossClientService = new WebexCrossClientService(this.$webex);
|
|
442
|
+
this.wxAppTelephonyMercurySync = new WxAppTelephonyMercurySync(this.$webex);
|
|
375
443
|
this.apiAIAssistant = new ApiAIAssistant(this.$webex);
|
|
376
444
|
this.metricsManager = MetricsManager.getInstance({webex: this.$webex});
|
|
377
445
|
this.taskManager = TaskManager.getTaskManager(
|
|
378
446
|
this.apiAIAssistant,
|
|
379
447
|
this.services.contact,
|
|
380
448
|
this.webCallingService,
|
|
381
|
-
this.services.webSocketManager
|
|
449
|
+
this.services.webSocketManager,
|
|
450
|
+
this.services.rtdWebSocketManager
|
|
382
451
|
);
|
|
452
|
+
this.taskManager.setAnswerCallOnWebexService(this.answerCallOnWebexService);
|
|
383
453
|
this.incomingTaskListener();
|
|
384
454
|
|
|
385
455
|
// Initialize API instances
|
|
@@ -387,6 +457,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
387
457
|
this.entryPoint = new EntryPoint(this.$webex);
|
|
388
458
|
this.addressBook = new AddressBook(this.$webex, () => this.agentConfig?.addressBookId);
|
|
389
459
|
this.queue = new Queue(this.$webex);
|
|
460
|
+
this.userPreference = new UserPreference(this.$webex, () => this.agentConfig?.agentId);
|
|
390
461
|
LoggerProxy.initialize(this.$webex.logger);
|
|
391
462
|
});
|
|
392
463
|
}
|
|
@@ -411,6 +482,16 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
411
482
|
this.trigger(TASK_EVENTS.TASK_HYDRATE, task);
|
|
412
483
|
};
|
|
413
484
|
|
|
485
|
+
/**
|
|
486
|
+
* Handles multi-login hydrate events for SDK instances without Mobius registration
|
|
487
|
+
* @private
|
|
488
|
+
* @param {ITask} task The task object associated with the multi-login hydrate
|
|
489
|
+
*/
|
|
490
|
+
private handleTaskMultiLoginHydrate = (task: ITask) => {
|
|
491
|
+
// @ts-ignore
|
|
492
|
+
this.trigger(TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE, task);
|
|
493
|
+
};
|
|
494
|
+
|
|
414
495
|
/**
|
|
415
496
|
* Handles task merged events when tasks are combined eg: EPDN merge/transfer
|
|
416
497
|
* @private
|
|
@@ -431,8 +512,8 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
431
512
|
this.trigger(TASK_EVENTS.TASK_CAMPAIGN_PREVIEW_RESERVATION, task);
|
|
432
513
|
};
|
|
433
514
|
|
|
434
|
-
private handleRTDWebsocketMessage = (
|
|
435
|
-
this.taskManager.handleRealtimeWebsocketEvent(
|
|
515
|
+
private handleRTDWebsocketMessage = (event: string) => {
|
|
516
|
+
this.taskManager.handleRealtimeWebsocketEvent(event);
|
|
436
517
|
};
|
|
437
518
|
|
|
438
519
|
/**
|
|
@@ -443,6 +524,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
443
524
|
private incomingTaskListener() {
|
|
444
525
|
this.taskManager.on(TASK_EVENTS.TASK_INCOMING, this.handleIncomingTask);
|
|
445
526
|
this.taskManager.on(TASK_EVENTS.TASK_HYDRATE, this.handleTaskHydrate);
|
|
527
|
+
this.taskManager.on(TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE, this.handleTaskMultiLoginHydrate);
|
|
446
528
|
this.taskManager.on(TASK_EVENTS.TASK_MERGED, this.handleTaskMerged);
|
|
447
529
|
this.taskManager.on(
|
|
448
530
|
TASK_EVENTS.TASK_CAMPAIGN_PREVIEW_RESERVATION,
|
|
@@ -487,7 +569,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
487
569
|
* ```
|
|
488
570
|
*/
|
|
489
571
|
public async register(): Promise<Profile> {
|
|
490
|
-
LoggerProxy.
|
|
572
|
+
LoggerProxy.log('Starting CC SDK registration', {
|
|
491
573
|
module: CC_FILE,
|
|
492
574
|
method: METHODS.REGISTER,
|
|
493
575
|
});
|
|
@@ -497,6 +579,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
497
579
|
METRIC_EVENT_NAMES.WEBSOCKET_REGISTER_FAILED,
|
|
498
580
|
]);
|
|
499
581
|
this.setupEventListeners();
|
|
582
|
+
this.services.webSocketManager.on('message', this.handleWebsocketMessage);
|
|
500
583
|
|
|
501
584
|
const resp = await this.connectWebsocket();
|
|
502
585
|
// Ensure 'dn' is always populated from 'defaultDn'
|
|
@@ -576,6 +659,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
576
659
|
|
|
577
660
|
this.taskManager.off(TASK_EVENTS.TASK_INCOMING, this.handleIncomingTask);
|
|
578
661
|
this.taskManager.off(TASK_EVENTS.TASK_HYDRATE, this.handleTaskHydrate);
|
|
662
|
+
this.taskManager.off(TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE, this.handleTaskMultiLoginHydrate);
|
|
579
663
|
this.taskManager.off(
|
|
580
664
|
TASK_EVENTS.TASK_CAMPAIGN_PREVIEW_RESERVATION,
|
|
581
665
|
this.handleCampaignPreviewReservation
|
|
@@ -586,6 +670,10 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
586
670
|
this.services.rtdWebSocketManager.off('message', this.handleRTDWebsocketMessage);
|
|
587
671
|
this.services.connectionService.off('connectionLost', this.handleConnectionLost);
|
|
588
672
|
|
|
673
|
+
const {publishError: wxAppPublishError} = await this.teardownWxAppLocalState({
|
|
674
|
+
clearInitFlag: true,
|
|
675
|
+
});
|
|
676
|
+
|
|
589
677
|
if (
|
|
590
678
|
this.agentConfig.webRtcEnabled &&
|
|
591
679
|
this.agentConfig.loginVoiceOptions.includes(LoginOption.BROWSER)
|
|
@@ -606,6 +694,9 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
606
694
|
if (!this.services.webSocketManager.isSocketClosed) {
|
|
607
695
|
this.services.webSocketManager.close(false, 'Unregistering the SDK');
|
|
608
696
|
}
|
|
697
|
+
if (this.services.rtdWebSocketManager && !this.services.rtdWebSocketManager.isSocketClosed) {
|
|
698
|
+
this.services.rtdWebSocketManager.close(false, 'Unregistering the SDK');
|
|
699
|
+
}
|
|
609
700
|
|
|
610
701
|
if (this.services.rtdWebSocketManager && !this.services.rtdWebSocketManager.isSocketClosed) {
|
|
611
702
|
this.services.rtdWebSocketManager.close(false, 'Unregistering the RTD websocket');
|
|
@@ -614,6 +705,10 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
614
705
|
// Clear any cached agent configuration
|
|
615
706
|
this.agentConfig = null;
|
|
616
707
|
|
|
708
|
+
if (wxAppPublishError) {
|
|
709
|
+
throw wxAppPublishError;
|
|
710
|
+
}
|
|
711
|
+
|
|
617
712
|
LoggerProxy.log('Deregistered successfully', {
|
|
618
713
|
module: CC_FILE,
|
|
619
714
|
method: METHODS.DEREGISTER,
|
|
@@ -676,6 +771,9 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
676
771
|
* ```
|
|
677
772
|
*/
|
|
678
773
|
public async getBuddyAgents(data: BuddyAgents): Promise<BuddyAgentsResponse> {
|
|
774
|
+
const {action, state, mediaType = 'telephony'} = data;
|
|
775
|
+
const buddyAgentState = state ?? (action === 'Transfer' ? AGENT_STATE_AVAILABLE : undefined);
|
|
776
|
+
|
|
679
777
|
LoggerProxy.info('Fetching buddy agents', {
|
|
680
778
|
module: CC_FILE,
|
|
681
779
|
method: METHODS.GET_BUDDY_AGENTS,
|
|
@@ -686,15 +784,19 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
686
784
|
METRIC_EVENT_NAMES.FETCH_BUDDY_AGENTS_FAILED,
|
|
687
785
|
]);
|
|
688
786
|
const resp = await this.services.agent.buddyAgents({
|
|
689
|
-
data: {
|
|
787
|
+
data: {
|
|
788
|
+
agentProfileId: this.agentConfig.agentProfileID,
|
|
789
|
+
mediaType,
|
|
790
|
+
...(buddyAgentState ? {state: buddyAgentState} : {}),
|
|
791
|
+
},
|
|
690
792
|
});
|
|
691
793
|
|
|
692
794
|
this.metricsManager.trackEvent(
|
|
693
795
|
METRIC_EVENT_NAMES.FETCH_BUDDY_AGENTS_SUCCESS,
|
|
694
796
|
{
|
|
695
797
|
...MetricsManager.getCommonTrackingFieldForAQMResponse(resp),
|
|
696
|
-
mediaType
|
|
697
|
-
buddyAgentState
|
|
798
|
+
mediaType,
|
|
799
|
+
buddyAgentState,
|
|
698
800
|
buddyAgentCount: resp.data.agentList.length,
|
|
699
801
|
},
|
|
700
802
|
['operational']
|
|
@@ -714,8 +816,8 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
714
816
|
METRIC_EVENT_NAMES.FETCH_BUDDY_AGENTS_FAILED,
|
|
715
817
|
{
|
|
716
818
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(failureResp),
|
|
717
|
-
mediaType
|
|
718
|
-
buddyAgentState
|
|
819
|
+
mediaType,
|
|
820
|
+
buddyAgentState,
|
|
719
821
|
},
|
|
720
822
|
['operational']
|
|
721
823
|
);
|
|
@@ -731,7 +833,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
731
833
|
* @private
|
|
732
834
|
*/
|
|
733
835
|
private async connectWebsocket() {
|
|
734
|
-
LoggerProxy.
|
|
836
|
+
LoggerProxy.log('Connecting to websocket', {
|
|
735
837
|
module: CC_FILE,
|
|
736
838
|
method: METHODS.CONNECT_WEBSOCKET,
|
|
737
839
|
});
|
|
@@ -751,19 +853,41 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
751
853
|
method: METHODS.CONNECT_WEBSOCKET,
|
|
752
854
|
});
|
|
753
855
|
|
|
856
|
+
const configFlags: ConfigFlags = {
|
|
857
|
+
isEndTaskEnabled: this.agentConfig.isEndTaskEnabled,
|
|
858
|
+
isEndConsultEnabled: this.agentConfig.isEndConsultEnabled,
|
|
859
|
+
webRtcEnabled: this.agentConfig.webRtcEnabled,
|
|
860
|
+
autoWrapup: this.agentConfig.wrapUpData?.wrapUpProps?.autoWrapup ?? false,
|
|
861
|
+
aiFeature: this.agentConfig.aiFeature,
|
|
862
|
+
consultTransfer: {
|
|
863
|
+
allowConsultToQueue: this.agentConfig.allowConsultToQueue,
|
|
864
|
+
accessQueue: this.agentConfig.accessQueue,
|
|
865
|
+
accessEntryPoint: this.agentConfig.accessEntryPoint,
|
|
866
|
+
accessBuddyTeam: this.agentConfig.accessBuddyTeam,
|
|
867
|
+
},
|
|
868
|
+
enableWxBetterTogether: this.isWxBetterTogetherEnabled(),
|
|
869
|
+
};
|
|
870
|
+
this.taskManager.setConfigFlags(configFlags);
|
|
754
871
|
// TODO: Make profile a singleton to make it available throughout app/sdk so we dont need to inject info everywhere
|
|
755
872
|
this.taskManager.setWrapupData(this.agentConfig.wrapUpData);
|
|
756
873
|
this.taskManager.setAgentId(this.agentConfig.agentId);
|
|
757
874
|
this.taskManager.setWebRtcEnabled(this.agentConfig.webRtcEnabled);
|
|
758
875
|
this.apiAIAssistant.setAIFeatureFlags(this.agentConfig.aiFeature);
|
|
759
876
|
|
|
760
|
-
|
|
877
|
+
/**
|
|
878
|
+
* RTD websocket currently supports realtime transcripts and suggested responses.
|
|
879
|
+
* Extend this condition when additional AI RTD features are introduced.
|
|
880
|
+
*/
|
|
881
|
+
if (
|
|
882
|
+
this.agentConfig.aiFeature?.realtimeTranscripts?.enable ||
|
|
883
|
+
this.agentConfig.aiFeature?.suggestedResponses?.enable
|
|
884
|
+
) {
|
|
761
885
|
LoggerProxy.info('Connecting to RTD websocket', {
|
|
762
886
|
module: CC_FILE,
|
|
763
887
|
method: METHODS.CONNECT_WEBSOCKET,
|
|
764
888
|
});
|
|
765
889
|
|
|
766
|
-
|
|
890
|
+
this.services.rtdWebSocketManager
|
|
767
891
|
.initWebSocket({
|
|
768
892
|
body: this.getConnectionConfig(),
|
|
769
893
|
resource: RTD_SUBSCRIBE_API,
|
|
@@ -776,7 +900,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
776
900
|
this.services.rtdWebSocketManager.on('message', this.handleRTDWebsocketMessage);
|
|
777
901
|
})
|
|
778
902
|
.catch((error) => {
|
|
779
|
-
LoggerProxy.error(`Error
|
|
903
|
+
LoggerProxy.error(`Error connecting to RTD websocket ${error}`, {
|
|
780
904
|
module: CC_FILE,
|
|
781
905
|
method: METHODS.CONNECT_WEBSOCKET,
|
|
782
906
|
});
|
|
@@ -785,7 +909,8 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
785
909
|
|
|
786
910
|
if (
|
|
787
911
|
this.agentConfig.webRtcEnabled &&
|
|
788
|
-
this.agentConfig.loginVoiceOptions.includes(LoginOption.BROWSER)
|
|
912
|
+
this.agentConfig.loginVoiceOptions.includes(LoginOption.BROWSER) &&
|
|
913
|
+
!this.isWebRTCRegistrationDisabled()
|
|
789
914
|
) {
|
|
790
915
|
try {
|
|
791
916
|
await this.$webex.internal.mercury.connect();
|
|
@@ -799,10 +924,23 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
799
924
|
method: METHODS.CONNECT_WEBSOCKET,
|
|
800
925
|
});
|
|
801
926
|
}
|
|
927
|
+
} else if (this.isWebRTCRegistrationDisabled()) {
|
|
928
|
+
LoggerProxy.info(
|
|
929
|
+
'Skipping Mobius registration because disableWebRTCRegistration is enabled',
|
|
930
|
+
{
|
|
931
|
+
module: CC_FILE,
|
|
932
|
+
method: METHODS.CONNECT_WEBSOCKET,
|
|
933
|
+
}
|
|
934
|
+
);
|
|
802
935
|
}
|
|
803
936
|
|
|
804
937
|
if (this.$config && this.$config.allowAutomatedRelogin) {
|
|
805
938
|
await this.silentRelogin();
|
|
939
|
+
} else {
|
|
940
|
+
LoggerProxy.log('Skipping silent relogin: allowAutomatedRelogin is disabled', {
|
|
941
|
+
module: CC_FILE,
|
|
942
|
+
method: METHODS.CONNECT_WEBSOCKET,
|
|
943
|
+
});
|
|
806
944
|
}
|
|
807
945
|
|
|
808
946
|
return this.agentConfig;
|
|
@@ -845,36 +983,48 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
845
983
|
* ```
|
|
846
984
|
*/
|
|
847
985
|
public async stationLogin(data: AgentLogin): Promise<StationLoginResponse> {
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
method: METHODS.STATION_LOGIN,
|
|
851
|
-
});
|
|
986
|
+
const loggerContext = {module: CC_FILE, method: METHODS.STATION_LOGIN};
|
|
987
|
+
|
|
852
988
|
try {
|
|
989
|
+
LoggerProxy.log(
|
|
990
|
+
`Starting agent station login | loginOption: ${data?.loginOption} teamId: ${data?.teamId}`,
|
|
991
|
+
loggerContext
|
|
992
|
+
);
|
|
853
993
|
this.metricsManager.timeEvent([
|
|
854
994
|
METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS,
|
|
855
995
|
METRIC_EVENT_NAMES.STATION_LOGIN_FAILED,
|
|
856
996
|
]);
|
|
857
997
|
|
|
858
998
|
const dialPlanEntries = this.agentConfig?.dialPlan?.dialPlanEntity ?? [];
|
|
859
|
-
if (
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
error.details = {data: {reason: 'INVALID_DIAL_NUMBER'}} as Failure;
|
|
999
|
+
if (data.loginOption === LoginOption.AGENT_DN) {
|
|
1000
|
+
LoggerProxy.log(
|
|
1001
|
+
`Validating dial number | dialPlanEnabled: ${!!this.agentConfig
|
|
1002
|
+
?.dialPlan} | dialPlanEntryCount: ${dialPlanEntries.length}`,
|
|
1003
|
+
loggerContext
|
|
1004
|
+
);
|
|
866
1005
|
|
|
867
|
-
|
|
1006
|
+
if (!isValidDialNumber(data.dialNumber, dialPlanEntries)) {
|
|
1007
|
+
LoggerProxy.log(
|
|
1008
|
+
`Dial number validation failed | dialNumber: ${data.dialNumber} | dialPlanEntryCount: ${dialPlanEntries.length}`,
|
|
1009
|
+
loggerContext
|
|
1010
|
+
);
|
|
1011
|
+
const error = new Error('INVALID_DIAL_NUMBER');
|
|
1012
|
+
// @ts-ignore - adding custom key to the error object
|
|
1013
|
+
error.details = {data: {reason: 'INVALID_DIAL_NUMBER'}} as Failure;
|
|
1014
|
+
|
|
1015
|
+
throw error;
|
|
1016
|
+
}
|
|
868
1017
|
}
|
|
869
1018
|
|
|
1019
|
+
const deviceId = this.getDeviceId(data.loginOption, data.dialNumber);
|
|
870
1020
|
const loginResponse = await this.services.agent.stationLogin({
|
|
871
1021
|
data: {
|
|
872
|
-
|
|
873
|
-
|
|
1022
|
+
// BROWSER DN must be webrtc-{agentId} so VPOP/RTMS do not treat a bare UUID as PSTN.
|
|
1023
|
+
dialNumber: data.loginOption === LoginOption.BROWSER ? deviceId : data.dialNumber,
|
|
874
1024
|
teamId: data.teamId,
|
|
875
1025
|
deviceType: data.loginOption,
|
|
876
1026
|
isExtension: data.loginOption === LoginOption.EXTENSION,
|
|
877
|
-
deviceId
|
|
1027
|
+
deviceId,
|
|
878
1028
|
roles: [AGENT],
|
|
879
1029
|
teamName: EMPTY_STRING,
|
|
880
1030
|
siteId: EMPTY_STRING,
|
|
@@ -883,8 +1033,24 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
883
1033
|
},
|
|
884
1034
|
});
|
|
885
1035
|
|
|
886
|
-
if (
|
|
1036
|
+
if (
|
|
1037
|
+
this.agentConfig.webRtcEnabled &&
|
|
1038
|
+
data.loginOption === LoginOption.BROWSER &&
|
|
1039
|
+
!this.isWebRTCRegistrationDisabled()
|
|
1040
|
+
) {
|
|
887
1041
|
await this.webCallingService.registerWebCallingLine();
|
|
1042
|
+
} else if (
|
|
1043
|
+
this.agentConfig.webRtcEnabled &&
|
|
1044
|
+
data.loginOption === LoginOption.BROWSER &&
|
|
1045
|
+
this.isWebRTCRegistrationDisabled()
|
|
1046
|
+
) {
|
|
1047
|
+
LoggerProxy.info(
|
|
1048
|
+
'Skipping web calling line registration because disableWebRTCRegistration is enabled',
|
|
1049
|
+
{
|
|
1050
|
+
module: CC_FILE,
|
|
1051
|
+
method: METHODS.STATION_LOGIN,
|
|
1052
|
+
}
|
|
1053
|
+
);
|
|
888
1054
|
}
|
|
889
1055
|
|
|
890
1056
|
const resp = await loginResponse;
|
|
@@ -902,6 +1068,16 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
902
1068
|
};
|
|
903
1069
|
|
|
904
1070
|
this.webCallingService.setLoginOption(data.loginOption);
|
|
1071
|
+
if (this.agentConfig) {
|
|
1072
|
+
this.agentConfig.deviceType = data.loginOption;
|
|
1073
|
+
if (
|
|
1074
|
+
data.loginOption === LoginOption.AGENT_DN ||
|
|
1075
|
+
data.loginOption === LoginOption.EXTENSION
|
|
1076
|
+
) {
|
|
1077
|
+
this.agentConfig.defaultDn = data.dialNumber;
|
|
1078
|
+
this.agentConfig.dn = data.dialNumber;
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
905
1081
|
this.metricsManager.trackEvent(
|
|
906
1082
|
METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS,
|
|
907
1083
|
{
|
|
@@ -923,6 +1099,8 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
923
1099
|
}
|
|
924
1100
|
);
|
|
925
1101
|
|
|
1102
|
+
await this.ensureWxAppPostStationLogin();
|
|
1103
|
+
|
|
926
1104
|
return response;
|
|
927
1105
|
} catch (error) {
|
|
928
1106
|
const failure = error.details as Failure;
|
|
@@ -991,6 +1169,8 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
991
1169
|
this.webCallingService.deregisterWebCallingLine();
|
|
992
1170
|
}
|
|
993
1171
|
|
|
1172
|
+
await this.teardownWxAppLocalState();
|
|
1173
|
+
|
|
994
1174
|
LoggerProxy.log(`Agent station logout completed successfully`, {
|
|
995
1175
|
module: CC_FILE,
|
|
996
1176
|
method: METHODS.STATION_LOGOUT,
|
|
@@ -1246,6 +1426,600 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
1246
1426
|
}
|
|
1247
1427
|
};
|
|
1248
1428
|
|
|
1429
|
+
/**
|
|
1430
|
+
* Checks whether Mobius/WebRTC registration should be skipped by config
|
|
1431
|
+
* @returns {boolean} True when browser WebRTC registration is disabled
|
|
1432
|
+
* @private
|
|
1433
|
+
*/
|
|
1434
|
+
private isWebRTCRegistrationDisabled(): boolean {
|
|
1435
|
+
return this.$config?.disableWebRTCRegistration === true;
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
/**
|
|
1439
|
+
* Validates contact-center plugin configuration before service initialization
|
|
1440
|
+
* @private
|
|
1441
|
+
*/
|
|
1442
|
+
private validatePluginConfig(): void {
|
|
1443
|
+
if (
|
|
1444
|
+
this.$config?.disableWebRTCRegistration === true &&
|
|
1445
|
+
this.$config?.allowMultiLogin === false
|
|
1446
|
+
) {
|
|
1447
|
+
throw new Error(
|
|
1448
|
+
'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.'
|
|
1449
|
+
);
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
/**
|
|
1454
|
+
* Whether wxApp thick-client answer is enabled for this SDK instance.
|
|
1455
|
+
* @public
|
|
1456
|
+
*/
|
|
1457
|
+
public isWxBetterTogetherEnabled(): boolean {
|
|
1458
|
+
return this.$config?.enableWxBetterTogether === true;
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
/**
|
|
1462
|
+
* Current station login option (Extension, Dial Number, or Browser/Desktop).
|
|
1463
|
+
* Prefer webCallingService — updated on every stationLogin before wxApp hooks run.
|
|
1464
|
+
* @private
|
|
1465
|
+
*/
|
|
1466
|
+
private getCurrentStationLoginOption(): LoginOption | undefined {
|
|
1467
|
+
return this.webCallingService?.loginOption ?? this.agentConfig?.deviceType;
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
/**
|
|
1471
|
+
* wxApp thick-client answer is supported for Extension and Dial Number station login only —
|
|
1472
|
+
* not Browser/Desktop (WebRTC) login.
|
|
1473
|
+
* @private
|
|
1474
|
+
*/
|
|
1475
|
+
private assertWxAppStationLoginSupportedForEnable(): void {
|
|
1476
|
+
const loginOption = this.getCurrentStationLoginOption();
|
|
1477
|
+
if (loginOption !== LoginOption.EXTENSION && loginOption !== LoginOption.AGENT_DN) {
|
|
1478
|
+
throw new Error(
|
|
1479
|
+
'setManageWebexCallingInWxcc requires EXTENSION or AGENT_DN station login. Complete station login before enabling.'
|
|
1480
|
+
);
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
/**
|
|
1485
|
+
* Clears runtime wxApp config after logout/deregister so stale flags do not apply on relogin.
|
|
1486
|
+
* @private
|
|
1487
|
+
*/
|
|
1488
|
+
private resetEnableWxBetterTogetherConfig(): void {
|
|
1489
|
+
if (this.$config) {
|
|
1490
|
+
this.$config.enableWxBetterTogether = false;
|
|
1491
|
+
}
|
|
1492
|
+
this.taskManager.applyEnableWxBetterTogether(false);
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
/**
|
|
1496
|
+
* Runtime enable/disable for wxApp Better Together (toast suppression + Mercury mute sync).
|
|
1497
|
+
*
|
|
1498
|
+
* **Phase 1 (WXCC-6026 / MMT): NOT part of the public host contract.**
|
|
1499
|
+
* Hosts must set `webexConfig.cc.enableWxBetterTogether` before `webex.init()` / `cc.register()`.
|
|
1500
|
+
* To change the flag after the SDK is initialized, re-init the SDK with the updated config.
|
|
1501
|
+
*
|
|
1502
|
+
* **Supported public read API:** {@link isWxBetterTogetherEnabled}.
|
|
1503
|
+
* **Supported telephony API:** unified `task.accept()`, `task.decline()`, `task.toggleMute()`,
|
|
1504
|
+
* `task.transmitDtmf()` — SDK routes wxApp calls internally when the init flag is active.
|
|
1505
|
+
*
|
|
1506
|
+
* **Production lifecycle does not call this method.** Station login, silent relogin, logout,
|
|
1507
|
+
* and deregister use {@link ensureWxAppPostStationLogin} and {@link teardownWxAppLocalState}
|
|
1508
|
+
* (usersub publish + Mercury subscribe/unsubscribe based on the init flag).
|
|
1509
|
+
*
|
|
1510
|
+
* This setter remains as a **private implementation** for Phase 2 runtime toggle and unit tests.
|
|
1511
|
+
* It updates `$config.enableWxBetterTogether`, TaskManager flags, cross-client usersub
|
|
1512
|
+
* (`answer-calls-on-wxcc`), and Mercury mute sync; rolls back config on publish/connect failure.
|
|
1513
|
+
*
|
|
1514
|
+
* @param enabled - `true` to enable wxApp answer + usersub suppression; `false` to disable and tear down.
|
|
1515
|
+
* @throws When enabling without login, on unsupported BROWSER station login, or when usersub/Mercury init fails.
|
|
1516
|
+
* @internal
|
|
1517
|
+
* @see enableWxBetterTogether (CCPluginConfig init flag)
|
|
1518
|
+
* @see ensureWxAppPostStationLogin
|
|
1519
|
+
* @see teardownWxAppLocalState
|
|
1520
|
+
*/
|
|
1521
|
+
private async setManageWebexCallingInWxcc(enabled: boolean): Promise<void> {
|
|
1522
|
+
if (enabled && !this.$webex.internal.device?.userId) {
|
|
1523
|
+
throw new Error('Cannot publish answer-calls-on-wxcc: user is not logged in');
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
if (enabled) {
|
|
1527
|
+
this.assertWxAppStationLoginSupportedForEnable();
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
const previousEnabled = this.isWxBetterTogetherEnabled();
|
|
1531
|
+
|
|
1532
|
+
if (this.$config) {
|
|
1533
|
+
this.$config.enableWxBetterTogether = enabled;
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
this.taskManager.applyEnableWxBetterTogether(enabled);
|
|
1537
|
+
|
|
1538
|
+
let publishedEnable = false;
|
|
1539
|
+
|
|
1540
|
+
try {
|
|
1541
|
+
if (enabled) {
|
|
1542
|
+
await this.ensureWxAppMercuryAndSubscribe();
|
|
1543
|
+
await this.publishAnswerOnWebexCrossClientState(true);
|
|
1544
|
+
publishedEnable = true;
|
|
1545
|
+
this.taskManager.syncWxAppMuteFromCallDetailsForAllTasks();
|
|
1546
|
+
} else {
|
|
1547
|
+
await this.publishAnswerOnWebexCrossClientState(false);
|
|
1548
|
+
this.wxAppTelephonyMercurySync.unsubscribe();
|
|
1549
|
+
await this.releaseWxAppMercuryResources();
|
|
1550
|
+
}
|
|
1551
|
+
} catch (error) {
|
|
1552
|
+
if (publishedEnable) {
|
|
1553
|
+
await this.revertWxAppCrossClientPublish();
|
|
1554
|
+
} else if (enabled) {
|
|
1555
|
+
this.wxAppTelephonyMercurySync.unsubscribe();
|
|
1556
|
+
await this.releaseWxAppMercuryResources();
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1559
|
+
if (this.$config) {
|
|
1560
|
+
this.$config.enableWxBetterTogether = previousEnabled;
|
|
1561
|
+
}
|
|
1562
|
+
this.taskManager.applyEnableWxBetterTogether(previousEnabled);
|
|
1563
|
+
throw error;
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
private getWxAppTelephonyTaskType(): 'Voice' | 'WebRTC' | 'unknown' {
|
|
1568
|
+
const loginOption = this.getCurrentStationLoginOption();
|
|
1569
|
+
|
|
1570
|
+
if (loginOption === LoginOption.BROWSER) {
|
|
1571
|
+
return 'WebRTC';
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
if (loginOption === LoginOption.EXTENSION || loginOption === LoginOption.AGENT_DN) {
|
|
1575
|
+
return 'Voice';
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
return 'unknown';
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
private async ensureWxAppPostStationLogin(): Promise<void> {
|
|
1582
|
+
const loginOption = this.getCurrentStationLoginOption();
|
|
1583
|
+
const flagEnabled = this.isWxBetterTogetherEnabled();
|
|
1584
|
+
const telephonyTaskType = this.getWxAppTelephonyTaskType();
|
|
1585
|
+
|
|
1586
|
+
if (loginOption === LoginOption.BROWSER) {
|
|
1587
|
+
if (flagEnabled) {
|
|
1588
|
+
logWxAppSessionReadiness({
|
|
1589
|
+
enableWxBetterTogether: true,
|
|
1590
|
+
loginOption,
|
|
1591
|
+
wxAppHooksApplied: false,
|
|
1592
|
+
usersubPublished: false,
|
|
1593
|
+
mercurySubscribed: false,
|
|
1594
|
+
telephonyTaskType,
|
|
1595
|
+
skipReason: 'unsupported_browser_login',
|
|
1596
|
+
});
|
|
1597
|
+
|
|
1598
|
+
this.metricsManager.trackEvent(
|
|
1599
|
+
METRIC_EVENT_NAMES.WXAPP_SESSION_SKIPPED,
|
|
1600
|
+
{
|
|
1601
|
+
loginOption,
|
|
1602
|
+
enableWxBetterTogether: true,
|
|
1603
|
+
skipReason: 'unsupported_browser_login',
|
|
1604
|
+
},
|
|
1605
|
+
['operational', 'behavioral']
|
|
1606
|
+
);
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
return;
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
let publishedEnable = false;
|
|
1613
|
+
let wxAppInitStage: 'mercury' | 'publish' = 'mercury';
|
|
1614
|
+
|
|
1615
|
+
try {
|
|
1616
|
+
if (flagEnabled) {
|
|
1617
|
+
this.metricsManager.timeEvent([
|
|
1618
|
+
METRIC_EVENT_NAMES.WXAPP_SESSION_INIT_SUCCESS,
|
|
1619
|
+
METRIC_EVENT_NAMES.WXAPP_SESSION_INIT_FAILED,
|
|
1620
|
+
]);
|
|
1621
|
+
|
|
1622
|
+
await this.ensureWxAppMercuryAndSubscribe();
|
|
1623
|
+
wxAppInitStage = 'publish';
|
|
1624
|
+
await this.publishAnswerOnWebexCrossClientState(true);
|
|
1625
|
+
publishedEnable = true;
|
|
1626
|
+
this.taskManager.syncWxAppMuteFromCallDetailsForAllTasks();
|
|
1627
|
+
|
|
1628
|
+
const mercurySubscribed = this.wxAppTelephonyMercurySync.isSubscribed();
|
|
1629
|
+
const usersubPublished = this.webexCrossClientService.isAnswerCallsStateActive();
|
|
1630
|
+
|
|
1631
|
+
logWxAppSessionReadiness({
|
|
1632
|
+
enableWxBetterTogether: true,
|
|
1633
|
+
loginOption,
|
|
1634
|
+
wxAppHooksApplied: true,
|
|
1635
|
+
usersubPublished,
|
|
1636
|
+
mercurySubscribed,
|
|
1637
|
+
telephonyTaskType,
|
|
1638
|
+
});
|
|
1639
|
+
|
|
1640
|
+
const sessionInitReady = mercurySubscribed && usersubPublished;
|
|
1641
|
+
|
|
1642
|
+
if (sessionInitReady) {
|
|
1643
|
+
this.metricsManager.trackEvent(
|
|
1644
|
+
METRIC_EVENT_NAMES.WXAPP_SESSION_INIT_SUCCESS,
|
|
1645
|
+
{loginOption, enableWxBetterTogether: true},
|
|
1646
|
+
['operational', 'behavioral']
|
|
1647
|
+
);
|
|
1648
|
+
} else {
|
|
1649
|
+
this.metricsManager.trackEvent(
|
|
1650
|
+
METRIC_EVENT_NAMES.WXAPP_SESSION_INIT_FAILED,
|
|
1651
|
+
{
|
|
1652
|
+
loginOption,
|
|
1653
|
+
enableWxBetterTogether: true,
|
|
1654
|
+
skipReason: !usersubPublished ? 'usersub_not_published' : 'mercury_not_subscribed',
|
|
1655
|
+
},
|
|
1656
|
+
['operational', 'behavioral']
|
|
1657
|
+
);
|
|
1658
|
+
}
|
|
1659
|
+
} else {
|
|
1660
|
+
await this.ensureWxAppDeviceRegistered();
|
|
1661
|
+
await this.publishAnswerOnWebexCrossClientState(false, {force: true});
|
|
1662
|
+
this.webexCrossClientService.teardown();
|
|
1663
|
+
this.wxAppTelephonyMercurySync.unsubscribe();
|
|
1664
|
+
await this.releaseWxAppMercuryResources();
|
|
1665
|
+
|
|
1666
|
+
logWxAppSessionReadiness({
|
|
1667
|
+
enableWxBetterTogether: false,
|
|
1668
|
+
loginOption,
|
|
1669
|
+
wxAppHooksApplied: true,
|
|
1670
|
+
usersubPublished: false,
|
|
1671
|
+
mercurySubscribed: false,
|
|
1672
|
+
telephonyTaskType,
|
|
1673
|
+
skipReason: 'flag_disabled',
|
|
1674
|
+
});
|
|
1675
|
+
|
|
1676
|
+
this.metricsManager.trackEvent(
|
|
1677
|
+
METRIC_EVENT_NAMES.WXAPP_SESSION_SKIPPED,
|
|
1678
|
+
{loginOption, enableWxBetterTogether: false, skipReason: 'flag_disabled'},
|
|
1679
|
+
['operational', 'behavioral']
|
|
1680
|
+
);
|
|
1681
|
+
}
|
|
1682
|
+
} catch (error) {
|
|
1683
|
+
LoggerProxy.error(`Failed to initialize wxApp post-station-login: ${error}`, {
|
|
1684
|
+
module: CC_FILE,
|
|
1685
|
+
method: METHODS.STATION_LOGIN,
|
|
1686
|
+
});
|
|
1687
|
+
|
|
1688
|
+
if (flagEnabled) {
|
|
1689
|
+
const sessionInitFailureReason =
|
|
1690
|
+
wxAppInitStage === 'mercury' ? 'mercury_subscribe_failed' : 'publish_failed';
|
|
1691
|
+
|
|
1692
|
+
this.metricsManager.trackEvent(
|
|
1693
|
+
METRIC_EVENT_NAMES.WXAPP_SESSION_INIT_FAILED,
|
|
1694
|
+
{
|
|
1695
|
+
loginOption,
|
|
1696
|
+
enableWxBetterTogether: true,
|
|
1697
|
+
skipReason: sessionInitFailureReason,
|
|
1698
|
+
error: error instanceof Error ? error.toString() : String(error),
|
|
1699
|
+
},
|
|
1700
|
+
['operational', 'behavioral']
|
|
1701
|
+
);
|
|
1702
|
+
|
|
1703
|
+
logWxAppSessionReadiness({
|
|
1704
|
+
enableWxBetterTogether: true,
|
|
1705
|
+
loginOption,
|
|
1706
|
+
wxAppHooksApplied: false,
|
|
1707
|
+
usersubPublished:
|
|
1708
|
+
publishedEnable && this.webexCrossClientService.isAnswerCallsStateActive(),
|
|
1709
|
+
mercurySubscribed: this.wxAppTelephonyMercurySync.isSubscribed(),
|
|
1710
|
+
telephonyTaskType,
|
|
1711
|
+
skipReason: sessionInitFailureReason,
|
|
1712
|
+
});
|
|
1713
|
+
|
|
1714
|
+
if (publishedEnable) {
|
|
1715
|
+
await this.revertWxAppCrossClientPublish();
|
|
1716
|
+
} else {
|
|
1717
|
+
this.wxAppTelephonyMercurySync.unsubscribe();
|
|
1718
|
+
await this.releaseWxAppMercuryResources();
|
|
1719
|
+
}
|
|
1720
|
+
this.resetEnableWxBetterTogetherConfig();
|
|
1721
|
+
} else {
|
|
1722
|
+
this.scheduleForcedFalsePublishRetry();
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
private clearWxAppFalsePublishRetryTimer(): void {
|
|
1728
|
+
if (this.wxAppFalsePublishRetryTimer) {
|
|
1729
|
+
clearTimeout(this.wxAppFalsePublishRetryTimer);
|
|
1730
|
+
this.wxAppFalsePublishRetryTimer = undefined;
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1734
|
+
private scheduleForcedFalsePublishRetry(retryAttempt = 0): void {
|
|
1735
|
+
this.scheduleFalsePublishRetry(retryAttempt, {requireDisabled: true});
|
|
1736
|
+
}
|
|
1737
|
+
|
|
1738
|
+
/**
|
|
1739
|
+
* Retries compensating false publish after rollback failure, regardless of enabled flag.
|
|
1740
|
+
* @private
|
|
1741
|
+
*/
|
|
1742
|
+
private scheduleCompensatingFalsePublishRetry(retryAttempt = 0): void {
|
|
1743
|
+
this.scheduleFalsePublishRetry(retryAttempt);
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1746
|
+
private scheduleFalsePublishRetry(
|
|
1747
|
+
retryAttempt = 0,
|
|
1748
|
+
options: {requireDisabled?: boolean} = {}
|
|
1749
|
+
): void {
|
|
1750
|
+
if (retryAttempt >= ContactCenter.WXAPP_FALSE_PUBLISH_MAX_RETRIES) {
|
|
1751
|
+
return;
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1754
|
+
if (options?.requireDisabled && this.isWxBetterTogetherEnabled()) {
|
|
1755
|
+
return;
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1758
|
+
this.clearWxAppFalsePublishRetryTimer();
|
|
1759
|
+
|
|
1760
|
+
this.wxAppFalsePublishRetryTimer = setTimeout(async () => {
|
|
1761
|
+
this.wxAppFalsePublishRetryTimer = undefined;
|
|
1762
|
+
|
|
1763
|
+
if (options?.requireDisabled && this.isWxBetterTogetherEnabled()) {
|
|
1764
|
+
return;
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
if (
|
|
1768
|
+
!options?.requireDisabled &&
|
|
1769
|
+
this.isWxBetterTogetherEnabled() &&
|
|
1770
|
+
this.webexCrossClientService.isAnswerCallsStateActive()
|
|
1771
|
+
) {
|
|
1772
|
+
return;
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
try {
|
|
1776
|
+
await this.ensureWxAppDeviceRegistered();
|
|
1777
|
+
await this.publishAnswerOnWebexCrossClientState(false, {force: true});
|
|
1778
|
+
this.webexCrossClientService.teardown();
|
|
1779
|
+
this.wxAppTelephonyMercurySync.unsubscribe();
|
|
1780
|
+
await this.releaseWxAppMercuryResources();
|
|
1781
|
+
} catch (retryError) {
|
|
1782
|
+
LoggerProxy.error(
|
|
1783
|
+
`Failed to retry forced answer-calls-on-wxcc false publish: ${retryError}`,
|
|
1784
|
+
{
|
|
1785
|
+
module: CC_FILE,
|
|
1786
|
+
method: METHODS.SET_MANAGE_WEBEX_CALLING_IN_WXCC,
|
|
1787
|
+
}
|
|
1788
|
+
);
|
|
1789
|
+
this.scheduleFalsePublishRetry(retryAttempt + 1, options);
|
|
1790
|
+
}
|
|
1791
|
+
}, ContactCenter.WXAPP_FALSE_PUBLISH_RETRY_DELAY_MS);
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1794
|
+
/**
|
|
1795
|
+
* Best-effort rollback when usersub true was published but wxApp setup did not complete.
|
|
1796
|
+
* @private
|
|
1797
|
+
*/
|
|
1798
|
+
private async revertWxAppCrossClientPublish(): Promise<void> {
|
|
1799
|
+
try {
|
|
1800
|
+
await this.publishAnswerOnWebexCrossClientState(false, {force: true});
|
|
1801
|
+
} catch (error) {
|
|
1802
|
+
LoggerProxy.error(
|
|
1803
|
+
`Failed to publish compensating answer-calls-on-wxcc false during wxApp rollback: ${error}`,
|
|
1804
|
+
{
|
|
1805
|
+
module: CC_FILE,
|
|
1806
|
+
method: METHODS.SET_MANAGE_WEBEX_CALLING_IN_WXCC,
|
|
1807
|
+
}
|
|
1808
|
+
);
|
|
1809
|
+
this.scheduleCompensatingFalsePublishRetry();
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1812
|
+
this.webexCrossClientService.teardown();
|
|
1813
|
+
this.wxAppTelephonyMercurySync.unsubscribe();
|
|
1814
|
+
await this.releaseWxAppMercuryResources();
|
|
1815
|
+
}
|
|
1816
|
+
|
|
1817
|
+
private async ensureWxAppDeviceRegistered(): Promise<void> {
|
|
1818
|
+
const device = this.$webex.internal.device;
|
|
1819
|
+
|
|
1820
|
+
if (device && !device.registered && device.register) {
|
|
1821
|
+
await device.register();
|
|
1822
|
+
this.wxAppDeviceRegisteredByCc = true;
|
|
1823
|
+
LoggerProxy.log('WxApp: device registered for cross-client publish', {
|
|
1824
|
+
module: CC_FILE,
|
|
1825
|
+
method: METHODS.ENSURE_WXAPP_MERCURY_CONNECTED,
|
|
1826
|
+
});
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1830
|
+
private async ensureWxAppMercuryConnected(): Promise<void> {
|
|
1831
|
+
const mercury = this.$webex.internal.mercury;
|
|
1832
|
+
|
|
1833
|
+
await this.ensureWxAppDeviceRegistered();
|
|
1834
|
+
|
|
1835
|
+
if (mercury && !mercury.connected) {
|
|
1836
|
+
await mercury.connect();
|
|
1837
|
+
this.wxAppMercuryConnectedByCc = true;
|
|
1838
|
+
LoggerProxy.log('WxApp mute sync: mercury connected', {
|
|
1839
|
+
module: CC_FILE,
|
|
1840
|
+
method: METHODS.ENSURE_WXAPP_MERCURY_CONNECTED,
|
|
1841
|
+
});
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
/**
|
|
1846
|
+
* Disconnects Mercury and unregisters the device when wxApp mute sync opened them.
|
|
1847
|
+
* @private
|
|
1848
|
+
*/
|
|
1849
|
+
private async releaseWxAppMercuryResources(): Promise<void> {
|
|
1850
|
+
const mercury = this.$webex.internal.mercury;
|
|
1851
|
+
const device = this.$webex.internal.device;
|
|
1852
|
+
|
|
1853
|
+
if (this.wxAppMercuryConnectedByCc && mercury?.connected) {
|
|
1854
|
+
try {
|
|
1855
|
+
await mercury.disconnect();
|
|
1856
|
+
this.wxAppMercuryConnectedByCc = false;
|
|
1857
|
+
LoggerProxy.log('WxApp mute sync: mercury disconnected', {
|
|
1858
|
+
module: CC_FILE,
|
|
1859
|
+
method: METHODS.ENSURE_WXAPP_MERCURY_CONNECTED,
|
|
1860
|
+
});
|
|
1861
|
+
} catch (error) {
|
|
1862
|
+
LoggerProxy.error(`Failed to disconnect wxApp Mercury: ${error}`, {
|
|
1863
|
+
module: CC_FILE,
|
|
1864
|
+
method: METHODS.ENSURE_WXAPP_MERCURY_CONNECTED,
|
|
1865
|
+
});
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
|
|
1869
|
+
if (this.wxAppDeviceRegisteredByCc && device?.registered && device.unregister) {
|
|
1870
|
+
try {
|
|
1871
|
+
// @ts-ignore
|
|
1872
|
+
await device.unregister();
|
|
1873
|
+
this.wxAppDeviceRegisteredByCc = false;
|
|
1874
|
+
LoggerProxy.log('WxApp mute sync: device unregistered', {
|
|
1875
|
+
module: CC_FILE,
|
|
1876
|
+
method: METHODS.ENSURE_WXAPP_MERCURY_CONNECTED,
|
|
1877
|
+
});
|
|
1878
|
+
} catch (error) {
|
|
1879
|
+
LoggerProxy.error(`Failed to unregister wxApp device: ${error}`, {
|
|
1880
|
+
module: CC_FILE,
|
|
1881
|
+
method: METHODS.ENSURE_WXAPP_MERCURY_CONNECTED,
|
|
1882
|
+
});
|
|
1883
|
+
}
|
|
1884
|
+
} else if (this.wxAppDeviceRegisteredByCc) {
|
|
1885
|
+
this.wxAppDeviceRegisteredByCc = false;
|
|
1886
|
+
}
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1889
|
+
/**
|
|
1890
|
+
* Clears wxApp runtime state and feature-owned resources. Publish failures are logged;
|
|
1891
|
+
* optional rethrow for deregister when callers need to surface usersub errors.
|
|
1892
|
+
* @private
|
|
1893
|
+
*/
|
|
1894
|
+
private async teardownWxAppLocalState(options?: {
|
|
1895
|
+
rethrowPublishError?: boolean;
|
|
1896
|
+
clearInitFlag?: boolean;
|
|
1897
|
+
}): Promise<{publishError?: unknown}> {
|
|
1898
|
+
this.clearWxAppFalsePublishRetryTimer();
|
|
1899
|
+
let publishError: unknown;
|
|
1900
|
+
|
|
1901
|
+
try {
|
|
1902
|
+
const shouldForceFalsePublish =
|
|
1903
|
+
this.isWxBetterTogetherEnabled() || this.webexCrossClientService.isAnswerCallsStateActive();
|
|
1904
|
+
|
|
1905
|
+
await this.publishAnswerOnWebexCrossClientState(false, {
|
|
1906
|
+
force: shouldForceFalsePublish,
|
|
1907
|
+
});
|
|
1908
|
+
} catch (error) {
|
|
1909
|
+
publishError = error;
|
|
1910
|
+
LoggerProxy.error(
|
|
1911
|
+
`Failed to publish answer-calls-on-wxcc false during wxApp teardown: ${error}`,
|
|
1912
|
+
{
|
|
1913
|
+
module: CC_FILE,
|
|
1914
|
+
method: METHODS.SET_MANAGE_WEBEX_CALLING_IN_WXCC,
|
|
1915
|
+
}
|
|
1916
|
+
);
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1919
|
+
this.webexCrossClientService.teardown();
|
|
1920
|
+
this.wxAppTelephonyMercurySync.unsubscribe();
|
|
1921
|
+
await this.releaseWxAppMercuryResources();
|
|
1922
|
+
|
|
1923
|
+
if (options?.clearInitFlag) {
|
|
1924
|
+
this.resetEnableWxBetterTogetherConfig();
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
if (publishError) {
|
|
1928
|
+
this.scheduleCompensatingFalsePublishRetry();
|
|
1929
|
+
}
|
|
1930
|
+
|
|
1931
|
+
if (options?.rethrowPublishError && publishError) {
|
|
1932
|
+
throw publishError;
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1935
|
+
return {publishError: publishError ?? undefined};
|
|
1936
|
+
}
|
|
1937
|
+
|
|
1938
|
+
private async ensureWxAppMercuryAndSubscribe(): Promise<void> {
|
|
1939
|
+
if (!this.isWxBetterTogetherEnabled()) {
|
|
1940
|
+
return;
|
|
1941
|
+
}
|
|
1942
|
+
|
|
1943
|
+
if (this.getCurrentStationLoginOption() === LoginOption.BROWSER) {
|
|
1944
|
+
return;
|
|
1945
|
+
}
|
|
1946
|
+
|
|
1947
|
+
const agentId = this.agentConfig?.agentId;
|
|
1948
|
+
if (!agentId) {
|
|
1949
|
+
LoggerProxy.error('Cannot subscribe wxApp mute sync: agentId unavailable', {
|
|
1950
|
+
module: CC_FILE,
|
|
1951
|
+
method: METHODS.SYNC_WXAPP_MUTE_FROM_MERCURY,
|
|
1952
|
+
});
|
|
1953
|
+
|
|
1954
|
+
this.metricsManager.trackEvent(
|
|
1955
|
+
METRIC_EVENT_NAMES.WXAPP_MERCURY_SUBSCRIBE_FAILED,
|
|
1956
|
+
{error: 'agentId unavailable'},
|
|
1957
|
+
['operational', 'behavioral']
|
|
1958
|
+
);
|
|
1959
|
+
|
|
1960
|
+
return;
|
|
1961
|
+
}
|
|
1962
|
+
|
|
1963
|
+
try {
|
|
1964
|
+
await this.ensureWxAppMercuryConnected();
|
|
1965
|
+
this.wxAppTelephonyMercurySync.subscribe(agentId, (callId, muted) => {
|
|
1966
|
+
this.taskManager.applyWxAppMuteStateFromSync(callId, muted);
|
|
1967
|
+
});
|
|
1968
|
+
} catch (error) {
|
|
1969
|
+
LoggerProxy.error(`Failed to ensure wxApp Mercury mute sync: ${error}`, {
|
|
1970
|
+
module: CC_FILE,
|
|
1971
|
+
method: METHODS.SYNC_WXAPP_MUTE_FROM_MERCURY,
|
|
1972
|
+
});
|
|
1973
|
+
this.metricsManager.trackEvent(
|
|
1974
|
+
METRIC_EVENT_NAMES.WXAPP_MERCURY_SUBSCRIBE_FAILED,
|
|
1975
|
+
{error: error instanceof Error ? error.toString() : String(error)},
|
|
1976
|
+
['operational', 'behavioral']
|
|
1977
|
+
);
|
|
1978
|
+
this.wxAppTelephonyMercurySync.unsubscribe();
|
|
1979
|
+
await this.releaseWxAppMercuryResources();
|
|
1980
|
+
throw error;
|
|
1981
|
+
}
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1984
|
+
private async publishAnswerOnWebexCrossClientState(
|
|
1985
|
+
enable: boolean,
|
|
1986
|
+
options?: {force?: boolean}
|
|
1987
|
+
): Promise<void> {
|
|
1988
|
+
if (enable && !this.isWxBetterTogetherEnabled()) {
|
|
1989
|
+
return;
|
|
1990
|
+
}
|
|
1991
|
+
|
|
1992
|
+
if (!enable && !options?.force && !this.webexCrossClientService.isAnswerCallsStateActive()) {
|
|
1993
|
+
return;
|
|
1994
|
+
}
|
|
1995
|
+
|
|
1996
|
+
const userId = this.$webex.internal.device?.userId;
|
|
1997
|
+
if (!userId) {
|
|
1998
|
+
if (enable && this.isWxBetterTogetherEnabled()) {
|
|
1999
|
+
this.metricsManager.trackEvent(
|
|
2000
|
+
METRIC_EVENT_NAMES.WXAPP_USERSUB_PUBLISH_FAILED,
|
|
2001
|
+
{
|
|
2002
|
+
enableWxBetterTogether: true,
|
|
2003
|
+
skipReason: 'user_id_unavailable',
|
|
2004
|
+
error: 'User ID is unavailable for cross-client publish',
|
|
2005
|
+
},
|
|
2006
|
+
['operational', 'behavioral']
|
|
2007
|
+
);
|
|
2008
|
+
}
|
|
2009
|
+
|
|
2010
|
+
return;
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
await this.webexCrossClientService.setManageWebexCallingInWxcc(enable, {
|
|
2014
|
+
userId,
|
|
2015
|
+
trackPublishMetrics: true,
|
|
2016
|
+
});
|
|
2017
|
+
|
|
2018
|
+
if (enable) {
|
|
2019
|
+
this.clearWxAppFalsePublishRetryTimer();
|
|
2020
|
+
}
|
|
2021
|
+
}
|
|
2022
|
+
|
|
1249
2023
|
/**
|
|
1250
2024
|
* Initializes event listeners for the Contact Center service
|
|
1251
2025
|
* Sets up handlers for connection state changes and other core events
|
|
@@ -1277,13 +2051,13 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
1277
2051
|
private async handleConnectionLost(msg: ConnectionLostDetails): Promise<void> {
|
|
1278
2052
|
if (msg.isConnectionLost) {
|
|
1279
2053
|
// TODO: Emit an event saying connection is lost
|
|
1280
|
-
LoggerProxy.
|
|
2054
|
+
LoggerProxy.log('event=handleConnectionLost | Connection lost', {
|
|
1281
2055
|
module: CC_FILE,
|
|
1282
2056
|
method: METHODS.HANDLE_CONNECTION_LOST,
|
|
1283
2057
|
});
|
|
1284
2058
|
} else if (msg.isSocketReconnected) {
|
|
1285
2059
|
// TODO: Emit an event saying connection is re-estabilished
|
|
1286
|
-
LoggerProxy.
|
|
2060
|
+
LoggerProxy.log(
|
|
1287
2061
|
'event=handleConnectionReconnect | Connection reconnected attempting to request silent relogin',
|
|
1288
2062
|
{module: CC_FILE, method: METHODS.HANDLE_CONNECTION_LOST}
|
|
1289
2063
|
);
|
|
@@ -1298,7 +2072,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
1298
2072
|
* @private
|
|
1299
2073
|
*/
|
|
1300
2074
|
private async silentRelogin(): Promise<void> {
|
|
1301
|
-
LoggerProxy.
|
|
2075
|
+
LoggerProxy.log('Starting silent relogin process', {
|
|
1302
2076
|
module: CC_FILE,
|
|
1303
2077
|
method: METHODS.SILENT_RELOGIN,
|
|
1304
2078
|
});
|
|
@@ -1320,7 +2094,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
1320
2094
|
await this.handleDeviceType(deviceType as LoginOption, dn);
|
|
1321
2095
|
|
|
1322
2096
|
if (lastStateChangeReason === 'agent-wss-disconnect') {
|
|
1323
|
-
LoggerProxy.
|
|
2097
|
+
LoggerProxy.log(
|
|
1324
2098
|
'event=requestAutoStateChange | Requesting state change to available on socket reconnect',
|
|
1325
2099
|
{module: CC_FILE, method: METHODS.SILENT_RELOGIN}
|
|
1326
2100
|
);
|
|
@@ -1349,8 +2123,8 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
1349
2123
|
}
|
|
1350
2124
|
this.agentConfig.lastStateAuxCodeId = auxCodeId;
|
|
1351
2125
|
this.agentConfig.isAgentLoggedIn = true;
|
|
1352
|
-
|
|
1353
|
-
this.
|
|
2126
|
+
|
|
2127
|
+
await this.ensureWxAppPostStationLogin();
|
|
1354
2128
|
|
|
1355
2129
|
LoggerProxy.log(
|
|
1356
2130
|
`Silent relogin process completed successfully with login Option: ${reLoginResponse.data.deviceType} teamId: ${reLoginResponse.data.teamId}`,
|
|
@@ -1391,6 +2165,16 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
1391
2165
|
this.agentConfig.deviceType = deviceType;
|
|
1392
2166
|
switch (deviceType) {
|
|
1393
2167
|
case LoginOption.BROWSER:
|
|
2168
|
+
if (this.isWebRTCRegistrationDisabled()) {
|
|
2169
|
+
LoggerProxy.info(
|
|
2170
|
+
'Skipping web calling line registration because disableWebRTCRegistration is enabled',
|
|
2171
|
+
{
|
|
2172
|
+
module: CC_FILE,
|
|
2173
|
+
method: METHODS.HANDLE_DEVICE_TYPE,
|
|
2174
|
+
}
|
|
2175
|
+
);
|
|
2176
|
+
break;
|
|
2177
|
+
}
|
|
1394
2178
|
try {
|
|
1395
2179
|
await this.webCallingService.registerWebCallingLine();
|
|
1396
2180
|
} catch (error) {
|
|
@@ -1656,6 +2440,166 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
1656
2440
|
}
|
|
1657
2441
|
}
|
|
1658
2442
|
|
|
2443
|
+
/**
|
|
2444
|
+
* Skips a campaign preview contact, requesting the next contact from the campaign.
|
|
2445
|
+
*
|
|
2446
|
+
* When a campaign manager reserves a contact for an agent, the agent receives an
|
|
2447
|
+
* `AgentOfferCampaignReservation` event. Instead of accepting, the agent can skip the
|
|
2448
|
+
* preview contact to move to the next contact in the campaign.
|
|
2449
|
+
*
|
|
2450
|
+
* @param {PreviewContactPayload} payload - The preview contact payload containing interactionId and campaignId (campaign name, not UUID).
|
|
2451
|
+
* @returns {Promise<TaskResponse>} Promise resolving with agent contact on success.
|
|
2452
|
+
* @throws {Error} If the operation fails (network error, etc.)
|
|
2453
|
+
*
|
|
2454
|
+
* @example
|
|
2455
|
+
* ```typescript
|
|
2456
|
+
* webex.cc.on('task:campaignPreviewReservation', async (task) => {
|
|
2457
|
+
* const { interactionId } = task.data;
|
|
2458
|
+
* const campaignId = task.data.interaction.callProcessingDetails.campaignId;
|
|
2459
|
+
*
|
|
2460
|
+
* const result = await webex.cc.skipPreviewContact({ interactionId, campaignId });
|
|
2461
|
+
* });
|
|
2462
|
+
* ```
|
|
2463
|
+
*/
|
|
2464
|
+
public async skipPreviewContact(payload: PreviewContactPayload): Promise<TaskResponse> {
|
|
2465
|
+
const task = this.taskManager.getTask(payload.interactionId);
|
|
2466
|
+
if (task?.data?.interaction?.callProcessingDetails?.campaignPreviewSkipDisabled === 'true') {
|
|
2467
|
+
LoggerProxy.warn('Skip action is disabled for this campaign preview contact', {
|
|
2468
|
+
module: CC_FILE,
|
|
2469
|
+
method: METHODS.SKIP_PREVIEW_CONTACT,
|
|
2470
|
+
interactionId: payload.interactionId,
|
|
2471
|
+
});
|
|
2472
|
+
throw new Error('Skip action is disabled for this campaign preview contact');
|
|
2473
|
+
}
|
|
2474
|
+
|
|
2475
|
+
LoggerProxy.info('Skipping campaign preview contact', {
|
|
2476
|
+
module: CC_FILE,
|
|
2477
|
+
method: METHODS.SKIP_PREVIEW_CONTACT,
|
|
2478
|
+
});
|
|
2479
|
+
try {
|
|
2480
|
+
this.metricsManager.timeEvent([
|
|
2481
|
+
METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_SUCCESS,
|
|
2482
|
+
METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_FAILED,
|
|
2483
|
+
]);
|
|
2484
|
+
|
|
2485
|
+
const result = await this.services.dialer.skipPreviewContact({data: payload});
|
|
2486
|
+
|
|
2487
|
+
this.metricsManager.trackEvent(
|
|
2488
|
+
METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_SUCCESS,
|
|
2489
|
+
{
|
|
2490
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponse(result),
|
|
2491
|
+
interactionId: payload.interactionId,
|
|
2492
|
+
campaignId: payload.campaignId,
|
|
2493
|
+
},
|
|
2494
|
+
['behavioral', 'business', 'operational']
|
|
2495
|
+
);
|
|
2496
|
+
|
|
2497
|
+
LoggerProxy.log('Campaign preview contact skipped successfully', {
|
|
2498
|
+
module: CC_FILE,
|
|
2499
|
+
method: METHODS.SKIP_PREVIEW_CONTACT,
|
|
2500
|
+
trackingId: result.trackingId,
|
|
2501
|
+
interactionId: payload.interactionId,
|
|
2502
|
+
});
|
|
2503
|
+
|
|
2504
|
+
return result;
|
|
2505
|
+
} catch (error) {
|
|
2506
|
+
const failure = error.details as Failure;
|
|
2507
|
+
this.metricsManager.trackEvent(
|
|
2508
|
+
METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_FAILED,
|
|
2509
|
+
{
|
|
2510
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(failure),
|
|
2511
|
+
interactionId: payload.interactionId,
|
|
2512
|
+
campaignId: payload.campaignId,
|
|
2513
|
+
},
|
|
2514
|
+
['behavioral', 'business', 'operational']
|
|
2515
|
+
);
|
|
2516
|
+
const {error: detailedError} = getErrorDetails(error, METHODS.SKIP_PREVIEW_CONTACT, CC_FILE);
|
|
2517
|
+
throw detailedError;
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2520
|
+
|
|
2521
|
+
/**
|
|
2522
|
+
* Removes a campaign preview contact from the campaign list entirely.
|
|
2523
|
+
*
|
|
2524
|
+
* When a campaign manager reserves a contact for an agent, the agent receives an
|
|
2525
|
+
* `AgentOfferCampaignReservation` event. Instead of accepting or skipping, the agent can
|
|
2526
|
+
* remove the preview contact to permanently take it out of the campaign contact list.
|
|
2527
|
+
*
|
|
2528
|
+
* @param {PreviewContactPayload} payload - The preview contact payload containing interactionId and campaignId (campaign name, not UUID).
|
|
2529
|
+
* @returns {Promise<TaskResponse>} Promise resolving with agent contact on success.
|
|
2530
|
+
* @throws {Error} If the operation fails (network error, etc.)
|
|
2531
|
+
*
|
|
2532
|
+
* @example
|
|
2533
|
+
* ```typescript
|
|
2534
|
+
* webex.cc.on('task:campaignPreviewReservation', async (task) => {
|
|
2535
|
+
* const { interactionId } = task.data;
|
|
2536
|
+
* const campaignId = task.data.interaction.callProcessingDetails.campaignId;
|
|
2537
|
+
*
|
|
2538
|
+
* const result = await webex.cc.removePreviewContact({ interactionId, campaignId });
|
|
2539
|
+
* });
|
|
2540
|
+
* ```
|
|
2541
|
+
*/
|
|
2542
|
+
public async removePreviewContact(payload: PreviewContactPayload): Promise<TaskResponse> {
|
|
2543
|
+
const task = this.taskManager.getTask(payload.interactionId);
|
|
2544
|
+
if (task?.data?.interaction?.callProcessingDetails?.campaignPreviewRemoveDisabled === 'true') {
|
|
2545
|
+
LoggerProxy.warn('Remove action is disabled for this campaign preview contact', {
|
|
2546
|
+
module: CC_FILE,
|
|
2547
|
+
method: METHODS.REMOVE_PREVIEW_CONTACT,
|
|
2548
|
+
interactionId: payload.interactionId,
|
|
2549
|
+
});
|
|
2550
|
+
throw new Error('Remove action is disabled for this campaign preview contact');
|
|
2551
|
+
}
|
|
2552
|
+
|
|
2553
|
+
LoggerProxy.info('Removing campaign preview contact', {
|
|
2554
|
+
module: CC_FILE,
|
|
2555
|
+
method: METHODS.REMOVE_PREVIEW_CONTACT,
|
|
2556
|
+
});
|
|
2557
|
+
try {
|
|
2558
|
+
this.metricsManager.timeEvent([
|
|
2559
|
+
METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_SUCCESS,
|
|
2560
|
+
METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_FAILED,
|
|
2561
|
+
]);
|
|
2562
|
+
|
|
2563
|
+
const result = await this.services.dialer.removePreviewContact({data: payload});
|
|
2564
|
+
|
|
2565
|
+
this.metricsManager.trackEvent(
|
|
2566
|
+
METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_SUCCESS,
|
|
2567
|
+
{
|
|
2568
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponse(result),
|
|
2569
|
+
interactionId: payload.interactionId,
|
|
2570
|
+
campaignId: payload.campaignId,
|
|
2571
|
+
},
|
|
2572
|
+
['behavioral', 'business', 'operational']
|
|
2573
|
+
);
|
|
2574
|
+
|
|
2575
|
+
LoggerProxy.log('Campaign preview contact removed successfully', {
|
|
2576
|
+
module: CC_FILE,
|
|
2577
|
+
method: METHODS.REMOVE_PREVIEW_CONTACT,
|
|
2578
|
+
trackingId: result.trackingId,
|
|
2579
|
+
interactionId: payload.interactionId,
|
|
2580
|
+
});
|
|
2581
|
+
|
|
2582
|
+
return result;
|
|
2583
|
+
} catch (error) {
|
|
2584
|
+
const failure = error.details as Failure;
|
|
2585
|
+
this.metricsManager.trackEvent(
|
|
2586
|
+
METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_FAILED,
|
|
2587
|
+
{
|
|
2588
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(failure),
|
|
2589
|
+
interactionId: payload.interactionId,
|
|
2590
|
+
campaignId: payload.campaignId,
|
|
2591
|
+
},
|
|
2592
|
+
['behavioral', 'business', 'operational']
|
|
2593
|
+
);
|
|
2594
|
+
const {error: detailedError} = getErrorDetails(
|
|
2595
|
+
error,
|
|
2596
|
+
METHODS.REMOVE_PREVIEW_CONTACT,
|
|
2597
|
+
CC_FILE
|
|
2598
|
+
);
|
|
2599
|
+
throw detailedError;
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
|
|
1659
2603
|
/**
|
|
1660
2604
|
* Fetches outdial ANI (Automatic Number Identification) entries for an outdial ANI ID.
|
|
1661
2605
|
*
|
|
@@ -1900,8 +2844,8 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
1900
2844
|
}
|
|
1901
2845
|
|
|
1902
2846
|
/**
|
|
1903
|
-
* Returns paginated entry points
|
|
1904
|
-
*
|
|
2847
|
+
* Returns paginated entry points using the EntryPoint service defaults.
|
|
2848
|
+
* Existing request parameters can override those defaults.
|
|
1905
2849
|
* @public
|
|
1906
2850
|
*/
|
|
1907
2851
|
public async getEntryPoints(
|
|
@@ -1911,8 +2855,8 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
1911
2855
|
}
|
|
1912
2856
|
|
|
1913
2857
|
/**
|
|
1914
|
-
* Returns paginated contact service queues
|
|
1915
|
-
*
|
|
2858
|
+
* Returns paginated contact service queues using the Queue service defaults.
|
|
2859
|
+
* Existing request parameters can override those defaults.
|
|
1916
2860
|
* @public
|
|
1917
2861
|
*/
|
|
1918
2862
|
public async getQueues(
|