@webex/contact-center 3.11.0 → 3.12.0-llmrefactor.2
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 +882 -0
- package/AGENTS.md +94 -0
- package/ai-docs/ARCHITECTURE.md +168 -0
- package/ai-docs/CONTRACTS.md +46 -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 +341 -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 +379 -50
- package/dist/cc.js.map +1 -1
- package/dist/config.js +6 -0
- package/dist/config.js.map +1 -1
- package/dist/constants.js +22 -2
- package/dist/constants.js.map +1 -1
- package/dist/index.js +27 -5
- package/dist/index.js.map +1 -1
- package/dist/metrics/behavioral-events.js +114 -0
- package/dist/metrics/behavioral-events.js.map +1 -1
- package/dist/metrics/constants.js +32 -3
- package/dist/metrics/constants.js.map +1 -1
- package/dist/services/ApiAiAssistant.js +318 -0
- package/dist/services/ApiAiAssistant.js.map +1 -0
- package/dist/services/UserPreference.js +427 -0
- package/dist/services/UserPreference.js.map +1 -0
- package/dist/services/agent/types.js.map +1 -1
- package/dist/services/config/Util.js +8 -4
- package/dist/services/config/Util.js.map +1 -1
- package/dist/services/config/constants.js +35 -2
- package/dist/services/config/constants.js.map +1 -1
- package/dist/services/config/index.js +41 -2
- package/dist/services/config/index.js.map +1 -1
- package/dist/services/config/types.js +66 -8
- package/dist/services/config/types.js.map +1 -1
- package/dist/services/constants.js +27 -1
- package/dist/services/constants.js.map +1 -1
- package/dist/services/core/Err.js.map +1 -1
- package/dist/services/core/Utils.js +122 -25
- package/dist/services/core/Utils.js.map +1 -1
- package/dist/services/core/aqm-reqs.js +92 -17
- package/dist/services/core/aqm-reqs.js.map +1 -1
- package/dist/services/core/websocket/WebSocketManager.js +22 -6
- package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
- package/dist/services/core/websocket/connection-service.js +3 -1
- package/dist/services/core/websocket/connection-service.js.map +1 -1
- package/dist/services/core/websocket/types.js.map +1 -1
- package/dist/services/index.js +6 -0
- package/dist/services/index.js.map +1 -1
- package/dist/services/task/Task.js +688 -0
- package/dist/services/task/Task.js.map +1 -0
- package/dist/services/task/TaskFactory.js +45 -0
- package/dist/services/task/TaskFactory.js.map +1 -0
- package/dist/services/task/TaskManager.js +751 -457
- package/dist/services/task/TaskManager.js.map +1 -1
- package/dist/services/task/TaskUtils.js +220 -23
- package/dist/services/task/TaskUtils.js.map +1 -1
- package/dist/services/task/constants.js +23 -2
- package/dist/services/task/constants.js.map +1 -1
- package/dist/services/task/dialer.js +129 -0
- package/dist/services/task/dialer.js.map +1 -1
- package/dist/services/task/digital/Digital.js +77 -0
- package/dist/services/task/digital/Digital.js.map +1 -0
- package/dist/services/task/state-machine/TaskStateMachine.js +873 -0
- package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -0
- package/dist/services/task/state-machine/actions.js +567 -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 +382 -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 +603 -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 +227 -4
- package/dist/services/task/types.js.map +1 -1
- package/dist/services/task/voice/Voice.js +1044 -0
- package/dist/services/task/voice/Voice.js.map +1 -0
- package/dist/services/task/voice/WebRTC.js +149 -0
- package/dist/services/task/voice/WebRTC.js.map +1 -0
- package/dist/types/cc.d.ts +894 -0
- package/dist/types/config.d.ts +72 -0
- package/dist/types/constants.d.ts +66 -0
- package/dist/types/index.d.ts +199 -0
- package/dist/types/logger-proxy.d.ts +71 -0
- package/dist/types/metrics/MetricsManager.d.ts +223 -0
- package/dist/types/metrics/behavioral-events.d.ts +29 -0
- package/dist/types/metrics/constants.d.ts +181 -0
- package/dist/types/services/AddressBook.d.ts +74 -0
- package/dist/types/services/ApiAiAssistant.d.ts +49 -0
- package/dist/types/services/EntryPoint.d.ts +67 -0
- package/dist/types/services/Queue.d.ts +76 -0
- package/dist/types/services/UserPreference.d.ts +118 -0
- package/dist/types/services/WebCallingService.d.ts +1 -0
- package/dist/types/services/agent/index.d.ts +46 -0
- package/dist/types/services/agent/types.d.ts +413 -0
- package/dist/types/services/config/Util.d.ts +20 -0
- package/dist/types/services/config/constants.d.ts +270 -0
- package/dist/types/services/config/index.d.ts +177 -0
- package/dist/types/services/config/types.d.ts +1368 -0
- package/dist/types/services/constants.d.ts +110 -0
- package/dist/types/services/core/Err.d.ts +125 -0
- package/dist/types/services/core/GlobalTypes.d.ts +58 -0
- package/dist/types/services/core/Utils.d.ts +121 -0
- package/dist/types/services/core/WebexRequest.d.ts +22 -0
- package/dist/types/services/core/aqm-reqs.d.ts +65 -0
- package/dist/types/services/core/constants.d.ts +99 -0
- package/dist/types/services/core/types.d.ts +47 -0
- package/dist/types/services/core/websocket/WebSocketManager.d.ts +36 -0
- package/dist/types/services/core/websocket/connection-service.d.ts +27 -0
- package/dist/types/services/core/websocket/keepalive.worker.d.ts +2 -0
- package/dist/types/services/core/websocket/types.d.ts +37 -0
- package/dist/types/services/index.d.ts +54 -0
- package/dist/types/services/task/AutoWrapup.d.ts +40 -0
- package/dist/types/services/task/Task.d.ts +157 -0
- package/dist/types/services/task/TaskFactory.d.ts +12 -0
- package/dist/types/services/task/TaskManager.d.ts +1 -0
- package/dist/types/services/task/TaskUtils.d.ts +138 -0
- package/dist/types/services/task/constants.d.ts +91 -0
- package/dist/types/services/task/contact.d.ts +69 -0
- package/dist/types/services/task/dialer.d.ts +73 -0
- package/dist/types/services/task/digital/Digital.d.ts +22 -0
- package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +1194 -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 +102 -0
- package/dist/types/services/task/state-machine/index.d.ts +13 -0
- package/dist/types/services/task/state-machine/types.d.ts +269 -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 +1856 -0
- package/dist/types/services/task/voice/Voice.d.ts +184 -0
- package/dist/types/services/task/voice/WebRTC.d.ts +53 -0
- package/dist/types/types.d.ts +778 -0
- package/dist/types/utils/PageCache.d.ts +173 -0
- package/dist/types/webex-config.d.ts +53 -0
- package/dist/types/webex.d.ts +8 -0
- package/dist/types.js +130 -1
- package/dist/types.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 +477 -51
- package/src/config.ts +6 -0
- package/src/constants.ts +21 -1
- package/src/index.ts +24 -5
- 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 +854 -0
- package/src/metrics/behavioral-events.ts +120 -0
- package/src/metrics/constants.ts +37 -3
- package/src/services/ApiAiAssistant.ts +412 -0
- package/src/services/UserPreference.ts +509 -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 +504 -0
- package/src/services/agent/types.ts +1 -1
- package/src/services/ai-docs/AGENTS.md +386 -0
- package/src/services/ai-docs/services-spec.md +492 -0
- package/src/services/config/Util.ts +10 -2
- 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 +669 -0
- package/src/services/config/constants.ts +37 -1
- package/src/services/config/index.ts +45 -1
- package/src/services/config/types.ts +241 -11
- package/src/services/constants.ts +29 -0
- package/src/services/core/Err.ts +3 -0
- package/src/services/core/Utils.ts +143 -30
- 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 +783 -0
- package/src/services/core/aqm-reqs.ts +100 -22
- package/src/services/core/websocket/WebSocketManager.ts +23 -6
- package/src/services/core/websocket/connection-service.ts +5 -1
- package/src/services/core/websocket/types.ts +1 -1
- package/src/services/index.ts +4 -0
- package/src/services/task/Task.ts +837 -0
- package/src/services/task/TaskFactory.ts +55 -0
- package/src/services/task/TaskManager.ts +793 -521
- package/src/services/task/TaskUtils.ts +314 -24
- package/src/services/task/ai-docs/AGENTS.md +457 -0
- package/src/services/task/ai-docs/ARCHITECTURE.md +594 -0
- package/src/services/task/ai-docs/task-spec.md +1319 -0
- package/src/services/task/constants.ts +23 -0
- package/src/services/task/dialer.ts +136 -1
- package/src/services/task/digital/Digital.ts +95 -0
- package/src/services/task/state-machine/TaskStateMachine.ts +1166 -0
- package/src/services/task/state-machine/actions.ts +738 -0
- package/src/services/task/state-machine/ai-docs/AGENTS.md +458 -0
- package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +1137 -0
- package/src/services/task/state-machine/ai-docs/task-state-machine-spec.md +2177 -0
- package/src/services/task/state-machine/constants.ts +172 -0
- package/src/services/task/state-machine/guards.ts +445 -0
- package/src/services/task/state-machine/index.ts +28 -0
- package/src/services/task/state-machine/types.ts +243 -0
- package/src/services/task/state-machine/uiControlsComputer.ts +961 -0
- package/src/services/task/taskDataNormalizer.ts +137 -0
- package/src/services/task/types.ts +734 -71
- package/src/services/task/voice/Voice.ts +1270 -0
- package/src/services/task/voice/WebRTC.ts +187 -0
- package/src/types.ts +205 -2
- package/src/utils/AGENTS.md +278 -0
- package/src/utils/ai-docs/utils-spec.md +381 -0
- package/src/webex.js +2 -0
- package/test/unit/spec/cc.ts +503 -43
- package/test/unit/spec/logger-proxy.ts +70 -0
- package/test/unit/spec/services/ApiAiAssistant.ts +273 -0
- package/test/unit/spec/services/UserPreference.ts +401 -0
- package/test/unit/spec/services/WebCallingService.ts +7 -1
- package/test/unit/spec/services/config/index.ts +85 -29
- package/test/unit/spec/services/core/Utils.ts +481 -2
- package/test/unit/spec/services/core/websocket/WebSocketManager.ts +137 -41
- package/test/unit/spec/services/core/websocket/connection-service.ts +3 -1
- package/test/unit/spec/services/task/AutoWrapup.ts +63 -0
- package/test/unit/spec/services/task/Task.ts +477 -0
- package/test/unit/spec/services/task/TaskFactory.ts +62 -0
- package/test/unit/spec/services/task/TaskManager.ts +1001 -1003
- package/test/unit/spec/services/task/TaskUtils.ts +235 -0
- package/test/unit/spec/services/task/dialer.ts +372 -96
- package/test/unit/spec/services/task/digital/Digital.ts +105 -0
- package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +2651 -0
- package/test/unit/spec/services/task/state-machine/guards.ts +637 -0
- package/test/unit/spec/services/task/state-machine/types.ts +18 -0
- package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +2663 -0
- package/test/unit/spec/services/task/taskTestUtils.ts +87 -0
- package/test/unit/spec/services/task/voice/Voice.ts +649 -0
- package/test/unit/spec/services/task/voice/WebRTC.ts +235 -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/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,
|
|
@@ -39,7 +40,7 @@ import {
|
|
|
39
40
|
METHODS,
|
|
40
41
|
} from './constants';
|
|
41
42
|
import {AGENT_STATE_AVAILABLE, AGENT_STATE_AVAILABLE_ID} from './services/config/constants';
|
|
42
|
-
import {AGENT, WEB_RTC_PREFIX} from './services/constants';
|
|
43
|
+
import {AGENT, RTD_SUBSCRIBE_API, SUBSCRIBE_API, WEB_RTC_PREFIX} from './services/constants';
|
|
43
44
|
import Services from './services';
|
|
44
45
|
import WebexRequest from './services/core/WebexRequest';
|
|
45
46
|
import LoggerProxy from './logger-proxy';
|
|
@@ -55,13 +56,21 @@ 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';
|
|
58
|
-
import {
|
|
59
|
+
import {
|
|
60
|
+
ITask,
|
|
61
|
+
TASK_EVENTS,
|
|
62
|
+
TaskResponse,
|
|
63
|
+
DialerPayload,
|
|
64
|
+
PreviewContactPayload,
|
|
65
|
+
} from './services/task/types';
|
|
59
66
|
import MetricsManager from './metrics/MetricsManager';
|
|
60
67
|
import {METRIC_EVENT_NAMES} from './metrics/constants';
|
|
61
68
|
import {Failure} from './services/core/GlobalTypes';
|
|
62
|
-
import EntryPoint from './services/EntryPoint';
|
|
63
|
-
import AddressBook from './services/AddressBook';
|
|
64
|
-
import Queue from './services/Queue';
|
|
69
|
+
import {EntryPoint} from './services/EntryPoint';
|
|
70
|
+
import {AddressBook} from './services/AddressBook';
|
|
71
|
+
import {Queue} from './services/Queue';
|
|
72
|
+
import {ApiAIAssistant} from './services/ApiAiAssistant';
|
|
73
|
+
import {UserPreference} from './services/UserPreference';
|
|
65
74
|
import type {
|
|
66
75
|
EntryPointListResponse,
|
|
67
76
|
EntryPointSearchParams,
|
|
@@ -119,6 +128,7 @@ import type {
|
|
|
119
128
|
* - `task:established` - Task/call has been connected
|
|
120
129
|
* - `task:ended` - Task/call has ended
|
|
121
130
|
* - `task:error` - An error occurred during task handling
|
|
131
|
+
* - `task:campaignPreviewReservation` - Campaign preview contact offered to agent
|
|
122
132
|
*
|
|
123
133
|
* @public
|
|
124
134
|
*
|
|
@@ -317,7 +327,45 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
317
327
|
* });
|
|
318
328
|
* ```
|
|
319
329
|
*/
|
|
320
|
-
|
|
330
|
+
public queue: Queue;
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* API instance for managing Webex Contact Center user preferences
|
|
334
|
+
* Provides functionality to get, create, update, and delete user preferences
|
|
335
|
+
* @type {UserPreference}
|
|
336
|
+
* @public
|
|
337
|
+
* @example
|
|
338
|
+
* ```typescript
|
|
339
|
+
* const cc = webex.cc;
|
|
340
|
+
* await cc.register();
|
|
341
|
+
* await cc.stationLogin({ teamId: 'team123', loginOption: 'BROWSER' });
|
|
342
|
+
*
|
|
343
|
+
* // Get user preferences for current user
|
|
344
|
+
* const preferences = await cc.userPreference.getUserPreference();
|
|
345
|
+
*
|
|
346
|
+
* // Create new user preferences
|
|
347
|
+
* const newPrefs = await cc.userPreference.createUserPreference({
|
|
348
|
+
* userId: 'user123',
|
|
349
|
+
* preferences: { e911Reminder: true }
|
|
350
|
+
* });
|
|
351
|
+
*
|
|
352
|
+
* // Update user preferences
|
|
353
|
+
* const updatedPrefs = await cc.userPreference.updateUserPreference('user123', {
|
|
354
|
+
* preferences: { e911Reminder: false }
|
|
355
|
+
* });
|
|
356
|
+
*
|
|
357
|
+
* // Delete user preferences
|
|
358
|
+
* await cc.userPreference.deleteUserPreference('user123');
|
|
359
|
+
* ```
|
|
360
|
+
*/
|
|
361
|
+
public userPreference: UserPreference;
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* API instance for AI Assistant operations such as transcript controls.
|
|
365
|
+
* @type {ApiAIAssistant}
|
|
366
|
+
* @public
|
|
367
|
+
*/
|
|
368
|
+
public apiAIAssistant: ApiAIAssistant;
|
|
321
369
|
|
|
322
370
|
/**
|
|
323
371
|
* Logger utility for Contact Center plugin
|
|
@@ -342,6 +390,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
342
390
|
this.$webex.once(READY, () => {
|
|
343
391
|
// @ts-ignore
|
|
344
392
|
this.$config = this.config;
|
|
393
|
+
this.validatePluginConfig();
|
|
345
394
|
|
|
346
395
|
/**
|
|
347
396
|
* This is used for handling the async requests by sending webex.request and wait for corresponding websocket event.
|
|
@@ -354,14 +403,16 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
354
403
|
webex: this.$webex,
|
|
355
404
|
connectionConfig: this.getConnectionConfig(),
|
|
356
405
|
});
|
|
357
|
-
this.services.webSocketManager.on('message', this.handleWebsocketMessage);
|
|
358
406
|
|
|
359
407
|
this.webCallingService = new WebCallingService(this.$webex);
|
|
408
|
+
this.apiAIAssistant = new ApiAIAssistant(this.$webex);
|
|
360
409
|
this.metricsManager = MetricsManager.getInstance({webex: this.$webex});
|
|
361
410
|
this.taskManager = TaskManager.getTaskManager(
|
|
411
|
+
this.apiAIAssistant,
|
|
362
412
|
this.services.contact,
|
|
363
413
|
this.webCallingService,
|
|
364
|
-
this.services.webSocketManager
|
|
414
|
+
this.services.webSocketManager,
|
|
415
|
+
this.services.rtdWebSocketManager
|
|
365
416
|
);
|
|
366
417
|
this.incomingTaskListener();
|
|
367
418
|
|
|
@@ -370,8 +421,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
370
421
|
this.entryPoint = new EntryPoint(this.$webex);
|
|
371
422
|
this.addressBook = new AddressBook(this.$webex, () => this.agentConfig?.addressBookId);
|
|
372
423
|
this.queue = new Queue(this.$webex);
|
|
373
|
-
|
|
374
|
-
// Initialize logger
|
|
424
|
+
this.userPreference = new UserPreference(this.$webex, () => this.agentConfig?.agentId);
|
|
375
425
|
LoggerProxy.initialize(this.$webex.logger);
|
|
376
426
|
});
|
|
377
427
|
}
|
|
@@ -396,6 +446,16 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
396
446
|
this.trigger(TASK_EVENTS.TASK_HYDRATE, task);
|
|
397
447
|
};
|
|
398
448
|
|
|
449
|
+
/**
|
|
450
|
+
* Handles multi-login hydrate events for SDK instances without Mobius registration
|
|
451
|
+
* @private
|
|
452
|
+
* @param {ITask} task The task object associated with the multi-login hydrate
|
|
453
|
+
*/
|
|
454
|
+
private handleTaskMultiLoginHydrate = (task: ITask) => {
|
|
455
|
+
// @ts-ignore
|
|
456
|
+
this.trigger(TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE, task);
|
|
457
|
+
};
|
|
458
|
+
|
|
399
459
|
/**
|
|
400
460
|
* Handles task merged events when tasks are combined eg: EPDN merge/transfer
|
|
401
461
|
* @private
|
|
@@ -406,6 +466,20 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
406
466
|
this.trigger(TASK_EVENTS.TASK_MERGED, task);
|
|
407
467
|
};
|
|
408
468
|
|
|
469
|
+
/**
|
|
470
|
+
* Handles campaign preview reservation events when a contact is offered to the agent
|
|
471
|
+
* @private
|
|
472
|
+
* @param {ITask} task The campaign reservation task
|
|
473
|
+
*/
|
|
474
|
+
private handleCampaignPreviewReservation = (task: ITask) => {
|
|
475
|
+
// @ts-ignore
|
|
476
|
+
this.trigger(TASK_EVENTS.TASK_CAMPAIGN_PREVIEW_RESERVATION, task);
|
|
477
|
+
};
|
|
478
|
+
|
|
479
|
+
private handleRTDWebsocketMessage = (event: string) => {
|
|
480
|
+
this.taskManager.handleRealtimeWebsocketEvent(event);
|
|
481
|
+
};
|
|
482
|
+
|
|
409
483
|
/**
|
|
410
484
|
* Sets up event listeners for incoming tasks and task hydration
|
|
411
485
|
* Subscribes to task events from the task manager
|
|
@@ -414,7 +488,12 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
414
488
|
private incomingTaskListener() {
|
|
415
489
|
this.taskManager.on(TASK_EVENTS.TASK_INCOMING, this.handleIncomingTask);
|
|
416
490
|
this.taskManager.on(TASK_EVENTS.TASK_HYDRATE, this.handleTaskHydrate);
|
|
491
|
+
this.taskManager.on(TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE, this.handleTaskMultiLoginHydrate);
|
|
417
492
|
this.taskManager.on(TASK_EVENTS.TASK_MERGED, this.handleTaskMerged);
|
|
493
|
+
this.taskManager.on(
|
|
494
|
+
TASK_EVENTS.TASK_CAMPAIGN_PREVIEW_RESERVATION,
|
|
495
|
+
this.handleCampaignPreviewReservation
|
|
496
|
+
);
|
|
418
497
|
}
|
|
419
498
|
|
|
420
499
|
/**
|
|
@@ -454,7 +533,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
454
533
|
* ```
|
|
455
534
|
*/
|
|
456
535
|
public async register(): Promise<Profile> {
|
|
457
|
-
LoggerProxy.
|
|
536
|
+
LoggerProxy.log('Starting CC SDK registration', {
|
|
458
537
|
module: CC_FILE,
|
|
459
538
|
method: METHODS.REGISTER,
|
|
460
539
|
});
|
|
@@ -464,6 +543,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
464
543
|
METRIC_EVENT_NAMES.WEBSOCKET_REGISTER_FAILED,
|
|
465
544
|
]);
|
|
466
545
|
this.setupEventListeners();
|
|
546
|
+
this.services.webSocketManager.on('message', this.handleWebsocketMessage);
|
|
467
547
|
|
|
468
548
|
const resp = await this.connectWebsocket();
|
|
469
549
|
// Ensure 'dn' is always populated from 'defaultDn'
|
|
@@ -543,9 +623,15 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
543
623
|
|
|
544
624
|
this.taskManager.off(TASK_EVENTS.TASK_INCOMING, this.handleIncomingTask);
|
|
545
625
|
this.taskManager.off(TASK_EVENTS.TASK_HYDRATE, this.handleTaskHydrate);
|
|
626
|
+
this.taskManager.off(TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE, this.handleTaskMultiLoginHydrate);
|
|
627
|
+
this.taskManager.off(
|
|
628
|
+
TASK_EVENTS.TASK_CAMPAIGN_PREVIEW_RESERVATION,
|
|
629
|
+
this.handleCampaignPreviewReservation
|
|
630
|
+
);
|
|
546
631
|
this.taskManager.unregisterIncomingCallEvent();
|
|
547
632
|
|
|
548
633
|
this.services.webSocketManager.off('message', this.handleWebsocketMessage);
|
|
634
|
+
this.services.rtdWebSocketManager.off('message', this.handleRTDWebsocketMessage);
|
|
549
635
|
this.services.connectionService.off('connectionLost', this.handleConnectionLost);
|
|
550
636
|
|
|
551
637
|
if (
|
|
@@ -568,6 +654,13 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
568
654
|
if (!this.services.webSocketManager.isSocketClosed) {
|
|
569
655
|
this.services.webSocketManager.close(false, 'Unregistering the SDK');
|
|
570
656
|
}
|
|
657
|
+
if (this.services.rtdWebSocketManager && !this.services.rtdWebSocketManager.isSocketClosed) {
|
|
658
|
+
this.services.rtdWebSocketManager.close(false, 'Unregistering the SDK');
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
if (this.services.rtdWebSocketManager && !this.services.rtdWebSocketManager.isSocketClosed) {
|
|
662
|
+
this.services.rtdWebSocketManager.close(false, 'Unregistering the RTD websocket');
|
|
663
|
+
}
|
|
571
664
|
|
|
572
665
|
// Clear any cached agent configuration
|
|
573
666
|
this.agentConfig = null;
|
|
@@ -689,7 +782,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
689
782
|
* @private
|
|
690
783
|
*/
|
|
691
784
|
private async connectWebsocket() {
|
|
692
|
-
LoggerProxy.
|
|
785
|
+
LoggerProxy.log('Connecting to websocket', {
|
|
693
786
|
module: CC_FILE,
|
|
694
787
|
method: METHODS.CONNECT_WEBSOCKET,
|
|
695
788
|
});
|
|
@@ -697,6 +790,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
697
790
|
try {
|
|
698
791
|
const data = (await this.services.webSocketManager.initWebSocket({
|
|
699
792
|
body: this.getConnectionConfig(),
|
|
793
|
+
resource: SUBSCRIBE_API,
|
|
700
794
|
})) as WelcomeEvent;
|
|
701
795
|
|
|
702
796
|
const agentId = data.agentId;
|
|
@@ -708,14 +802,57 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
708
802
|
method: METHODS.CONNECT_WEBSOCKET,
|
|
709
803
|
});
|
|
710
804
|
|
|
805
|
+
const configFlags: ConfigFlags = {
|
|
806
|
+
isEndTaskEnabled: this.agentConfig.isEndTaskEnabled,
|
|
807
|
+
isEndConsultEnabled: this.agentConfig.isEndConsultEnabled,
|
|
808
|
+
webRtcEnabled: this.agentConfig.webRtcEnabled,
|
|
809
|
+
autoWrapup: this.agentConfig.wrapUpData?.wrapUpProps?.autoWrapup ?? false,
|
|
810
|
+
aiFeature: this.agentConfig.aiFeature,
|
|
811
|
+
};
|
|
812
|
+
this.taskManager.setConfigFlags(configFlags);
|
|
711
813
|
// TODO: Make profile a singleton to make it available throughout app/sdk so we dont need to inject info everywhere
|
|
712
814
|
this.taskManager.setWrapupData(this.agentConfig.wrapUpData);
|
|
713
815
|
this.taskManager.setAgentId(this.agentConfig.agentId);
|
|
714
816
|
this.taskManager.setWebRtcEnabled(this.agentConfig.webRtcEnabled);
|
|
817
|
+
this.apiAIAssistant.setAIFeatureFlags(this.agentConfig.aiFeature);
|
|
818
|
+
|
|
819
|
+
/**
|
|
820
|
+
* RTD websocket currently supports realtime transcripts and suggested responses.
|
|
821
|
+
* Extend this condition when additional AI RTD features are introduced.
|
|
822
|
+
*/
|
|
823
|
+
if (
|
|
824
|
+
this.agentConfig.aiFeature?.realtimeTranscripts?.enable ||
|
|
825
|
+
this.agentConfig.aiFeature?.suggestedResponses?.enable
|
|
826
|
+
) {
|
|
827
|
+
LoggerProxy.info('Connecting to RTD websocket', {
|
|
828
|
+
module: CC_FILE,
|
|
829
|
+
method: METHODS.CONNECT_WEBSOCKET,
|
|
830
|
+
});
|
|
831
|
+
|
|
832
|
+
this.services.rtdWebSocketManager
|
|
833
|
+
.initWebSocket({
|
|
834
|
+
body: this.getConnectionConfig(),
|
|
835
|
+
resource: RTD_SUBSCRIBE_API,
|
|
836
|
+
})
|
|
837
|
+
.then(() => {
|
|
838
|
+
LoggerProxy.log('RTD websocket connected successfully', {
|
|
839
|
+
module: CC_FILE,
|
|
840
|
+
method: METHODS.CONNECT_WEBSOCKET,
|
|
841
|
+
});
|
|
842
|
+
this.services.rtdWebSocketManager.on('message', this.handleRTDWebsocketMessage);
|
|
843
|
+
})
|
|
844
|
+
.catch((error) => {
|
|
845
|
+
LoggerProxy.error(`Error connecting to RTD websocket ${error}`, {
|
|
846
|
+
module: CC_FILE,
|
|
847
|
+
method: METHODS.CONNECT_WEBSOCKET,
|
|
848
|
+
});
|
|
849
|
+
});
|
|
850
|
+
}
|
|
715
851
|
|
|
716
852
|
if (
|
|
717
853
|
this.agentConfig.webRtcEnabled &&
|
|
718
|
-
this.agentConfig.loginVoiceOptions.includes(LoginOption.BROWSER)
|
|
854
|
+
this.agentConfig.loginVoiceOptions.includes(LoginOption.BROWSER) &&
|
|
855
|
+
!this.isWebRTCRegistrationDisabled()
|
|
719
856
|
) {
|
|
720
857
|
try {
|
|
721
858
|
await this.$webex.internal.mercury.connect();
|
|
@@ -729,10 +866,23 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
729
866
|
method: METHODS.CONNECT_WEBSOCKET,
|
|
730
867
|
});
|
|
731
868
|
}
|
|
869
|
+
} else if (this.isWebRTCRegistrationDisabled()) {
|
|
870
|
+
LoggerProxy.info(
|
|
871
|
+
'Skipping Mobius registration because disableWebRTCRegistration is enabled',
|
|
872
|
+
{
|
|
873
|
+
module: CC_FILE,
|
|
874
|
+
method: METHODS.CONNECT_WEBSOCKET,
|
|
875
|
+
}
|
|
876
|
+
);
|
|
732
877
|
}
|
|
733
878
|
|
|
734
879
|
if (this.$config && this.$config.allowAutomatedRelogin) {
|
|
735
880
|
await this.silentRelogin();
|
|
881
|
+
} else {
|
|
882
|
+
LoggerProxy.log('Skipping silent relogin: allowAutomatedRelogin is disabled', {
|
|
883
|
+
module: CC_FILE,
|
|
884
|
+
method: METHODS.CONNECT_WEBSOCKET,
|
|
885
|
+
});
|
|
736
886
|
}
|
|
737
887
|
|
|
738
888
|
return this.agentConfig;
|
|
@@ -775,22 +925,37 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
775
925
|
* ```
|
|
776
926
|
*/
|
|
777
927
|
public async stationLogin(data: AgentLogin): Promise<StationLoginResponse> {
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
method: METHODS.STATION_LOGIN,
|
|
781
|
-
});
|
|
928
|
+
const loggerContext = {module: CC_FILE, method: METHODS.STATION_LOGIN};
|
|
929
|
+
|
|
782
930
|
try {
|
|
931
|
+
LoggerProxy.log(
|
|
932
|
+
`Starting agent station login | loginOption: ${data?.loginOption} teamId: ${data?.teamId}`,
|
|
933
|
+
loggerContext
|
|
934
|
+
);
|
|
783
935
|
this.metricsManager.timeEvent([
|
|
784
936
|
METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS,
|
|
785
937
|
METRIC_EVENT_NAMES.STATION_LOGIN_FAILED,
|
|
786
938
|
]);
|
|
787
939
|
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
940
|
+
const dialPlanEntries = this.agentConfig?.dialPlan?.dialPlanEntity ?? [];
|
|
941
|
+
if (data.loginOption === LoginOption.AGENT_DN) {
|
|
942
|
+
LoggerProxy.log(
|
|
943
|
+
`Validating dial number | dialPlanEnabled: ${!!this.agentConfig
|
|
944
|
+
?.dialPlan} | dialPlanEntryCount: ${dialPlanEntries.length}`,
|
|
945
|
+
loggerContext
|
|
946
|
+
);
|
|
947
|
+
|
|
948
|
+
if (!isValidDialNumber(data.dialNumber, dialPlanEntries)) {
|
|
949
|
+
LoggerProxy.log(
|
|
950
|
+
`Dial number validation failed | dialNumber: ${data.dialNumber} | dialPlanEntryCount: ${dialPlanEntries.length}`,
|
|
951
|
+
loggerContext
|
|
952
|
+
);
|
|
953
|
+
const error = new Error('INVALID_DIAL_NUMBER');
|
|
954
|
+
// @ts-ignore - adding custom key to the error object
|
|
955
|
+
error.details = {data: {reason: 'INVALID_DIAL_NUMBER'}} as Failure;
|
|
792
956
|
|
|
793
|
-
|
|
957
|
+
throw error;
|
|
958
|
+
}
|
|
794
959
|
}
|
|
795
960
|
|
|
796
961
|
const loginResponse = await this.services.agent.stationLogin({
|
|
@@ -809,8 +974,24 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
809
974
|
},
|
|
810
975
|
});
|
|
811
976
|
|
|
812
|
-
if (
|
|
977
|
+
if (
|
|
978
|
+
this.agentConfig.webRtcEnabled &&
|
|
979
|
+
data.loginOption === LoginOption.BROWSER &&
|
|
980
|
+
!this.isWebRTCRegistrationDisabled()
|
|
981
|
+
) {
|
|
813
982
|
await this.webCallingService.registerWebCallingLine();
|
|
983
|
+
} else if (
|
|
984
|
+
this.agentConfig.webRtcEnabled &&
|
|
985
|
+
data.loginOption === LoginOption.BROWSER &&
|
|
986
|
+
this.isWebRTCRegistrationDisabled()
|
|
987
|
+
) {
|
|
988
|
+
LoggerProxy.info(
|
|
989
|
+
'Skipping web calling line registration because disableWebRTCRegistration is enabled',
|
|
990
|
+
{
|
|
991
|
+
module: CC_FILE,
|
|
992
|
+
method: METHODS.STATION_LOGIN,
|
|
993
|
+
}
|
|
994
|
+
);
|
|
814
995
|
}
|
|
815
996
|
|
|
816
997
|
const resp = await loginResponse;
|
|
@@ -1172,6 +1353,30 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
1172
1353
|
}
|
|
1173
1354
|
};
|
|
1174
1355
|
|
|
1356
|
+
/**
|
|
1357
|
+
* Checks whether Mobius/WebRTC registration should be skipped by config
|
|
1358
|
+
* @returns {boolean} True when browser WebRTC registration is disabled
|
|
1359
|
+
* @private
|
|
1360
|
+
*/
|
|
1361
|
+
private isWebRTCRegistrationDisabled(): boolean {
|
|
1362
|
+
return this.$config?.disableWebRTCRegistration === true;
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
/**
|
|
1366
|
+
* Validates contact-center plugin configuration before service initialization
|
|
1367
|
+
* @private
|
|
1368
|
+
*/
|
|
1369
|
+
private validatePluginConfig(): void {
|
|
1370
|
+
if (
|
|
1371
|
+
this.$config?.disableWebRTCRegistration === true &&
|
|
1372
|
+
this.$config?.allowMultiLogin === false
|
|
1373
|
+
) {
|
|
1374
|
+
throw new Error(
|
|
1375
|
+
'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.'
|
|
1376
|
+
);
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1175
1380
|
/**
|
|
1176
1381
|
* Initializes event listeners for the Contact Center service
|
|
1177
1382
|
* Sets up handlers for connection state changes and other core events
|
|
@@ -1203,13 +1408,13 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
1203
1408
|
private async handleConnectionLost(msg: ConnectionLostDetails): Promise<void> {
|
|
1204
1409
|
if (msg.isConnectionLost) {
|
|
1205
1410
|
// TODO: Emit an event saying connection is lost
|
|
1206
|
-
LoggerProxy.
|
|
1411
|
+
LoggerProxy.log('event=handleConnectionLost | Connection lost', {
|
|
1207
1412
|
module: CC_FILE,
|
|
1208
1413
|
method: METHODS.HANDLE_CONNECTION_LOST,
|
|
1209
1414
|
});
|
|
1210
1415
|
} else if (msg.isSocketReconnected) {
|
|
1211
1416
|
// TODO: Emit an event saying connection is re-estabilished
|
|
1212
|
-
LoggerProxy.
|
|
1417
|
+
LoggerProxy.log(
|
|
1213
1418
|
'event=handleConnectionReconnect | Connection reconnected attempting to request silent relogin',
|
|
1214
1419
|
{module: CC_FILE, method: METHODS.HANDLE_CONNECTION_LOST}
|
|
1215
1420
|
);
|
|
@@ -1224,7 +1429,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
1224
1429
|
* @private
|
|
1225
1430
|
*/
|
|
1226
1431
|
private async silentRelogin(): Promise<void> {
|
|
1227
|
-
LoggerProxy.
|
|
1432
|
+
LoggerProxy.log('Starting silent relogin process', {
|
|
1228
1433
|
module: CC_FILE,
|
|
1229
1434
|
method: METHODS.SILENT_RELOGIN,
|
|
1230
1435
|
});
|
|
@@ -1246,7 +1451,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
1246
1451
|
await this.handleDeviceType(deviceType as LoginOption, dn);
|
|
1247
1452
|
|
|
1248
1453
|
if (lastStateChangeReason === 'agent-wss-disconnect') {
|
|
1249
|
-
LoggerProxy.
|
|
1454
|
+
LoggerProxy.log(
|
|
1250
1455
|
'event=requestAutoStateChange | Requesting state change to available on socket reconnect',
|
|
1251
1456
|
{module: CC_FILE, method: METHODS.SILENT_RELOGIN}
|
|
1252
1457
|
);
|
|
@@ -1275,8 +1480,6 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
1275
1480
|
}
|
|
1276
1481
|
this.agentConfig.lastStateAuxCodeId = auxCodeId;
|
|
1277
1482
|
this.agentConfig.isAgentLoggedIn = true;
|
|
1278
|
-
// TODO: https://jira-eng-gpk2.cisco.com/jira/browse/SPARK-626777 Implement the de-register method and close the listener there
|
|
1279
|
-
this.services.webSocketManager.on('message', this.handleWebsocketMessage);
|
|
1280
1483
|
|
|
1281
1484
|
LoggerProxy.log(
|
|
1282
1485
|
`Silent relogin process completed successfully with login Option: ${reLoginResponse.data.deviceType} teamId: ${reLoginResponse.data.teamId}`,
|
|
@@ -1317,6 +1520,16 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
1317
1520
|
this.agentConfig.deviceType = deviceType;
|
|
1318
1521
|
switch (deviceType) {
|
|
1319
1522
|
case LoginOption.BROWSER:
|
|
1523
|
+
if (this.isWebRTCRegistrationDisabled()) {
|
|
1524
|
+
LoggerProxy.info(
|
|
1525
|
+
'Skipping web calling line registration because disableWebRTCRegistration is enabled',
|
|
1526
|
+
{
|
|
1527
|
+
module: CC_FILE,
|
|
1528
|
+
method: METHODS.HANDLE_DEVICE_TYPE,
|
|
1529
|
+
}
|
|
1530
|
+
);
|
|
1531
|
+
break;
|
|
1532
|
+
}
|
|
1320
1533
|
try {
|
|
1321
1534
|
await this.webCallingService.registerWebCallingLine();
|
|
1322
1535
|
} catch (error) {
|
|
@@ -1509,6 +1722,239 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
1509
1722
|
}
|
|
1510
1723
|
}
|
|
1511
1724
|
|
|
1725
|
+
/**
|
|
1726
|
+
* Accepts a campaign preview contact, initiating the outbound call.
|
|
1727
|
+
*
|
|
1728
|
+
* When a campaign manager reserves a contact for an agent, the agent receives an
|
|
1729
|
+
* `AgentOfferCampaignReservation` event. The agent can then accept the preview contact
|
|
1730
|
+
* to initiate the outbound call.
|
|
1731
|
+
*
|
|
1732
|
+
* @param {PreviewContactPayload} payload - The preview contact payload containing interactionId and campaignId (campaign name, not UUID).
|
|
1733
|
+
* @returns {Promise<TaskResponse>} Promise resolving with agent contact on success.
|
|
1734
|
+
* @throws {Error} If the operation fails (network error, customer unavailable, etc.)
|
|
1735
|
+
*
|
|
1736
|
+
* @example
|
|
1737
|
+
* ```typescript
|
|
1738
|
+
* webex.cc.on('task:campaignPreviewReservation', async (task) => {
|
|
1739
|
+
* const { interactionId } = task.data;
|
|
1740
|
+
* // campaignId is the campaign name (e.g. "MyCampaign"), not a UUID
|
|
1741
|
+
* const campaignId = task.data.interaction.callProcessingDetails.campaignId;
|
|
1742
|
+
*
|
|
1743
|
+
* const result = await webex.cc.acceptPreviewContact({ interactionId, campaignId });
|
|
1744
|
+
* });
|
|
1745
|
+
* ```
|
|
1746
|
+
*/
|
|
1747
|
+
public async acceptPreviewContact(payload: PreviewContactPayload): Promise<TaskResponse> {
|
|
1748
|
+
LoggerProxy.info('Accepting campaign preview contact', {
|
|
1749
|
+
module: CC_FILE,
|
|
1750
|
+
method: METHODS.ACCEPT_PREVIEW_CONTACT,
|
|
1751
|
+
});
|
|
1752
|
+
try {
|
|
1753
|
+
this.metricsManager.timeEvent([
|
|
1754
|
+
METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_ACCEPT_SUCCESS,
|
|
1755
|
+
METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_ACCEPT_FAILED,
|
|
1756
|
+
]);
|
|
1757
|
+
|
|
1758
|
+
const result = await this.services.dialer.acceptPreviewContact({data: payload});
|
|
1759
|
+
|
|
1760
|
+
this.metricsManager.trackEvent(
|
|
1761
|
+
METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_ACCEPT_SUCCESS,
|
|
1762
|
+
{
|
|
1763
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponse(result),
|
|
1764
|
+
interactionId: payload.interactionId,
|
|
1765
|
+
campaignId: payload.campaignId,
|
|
1766
|
+
},
|
|
1767
|
+
['behavioral', 'business', 'operational']
|
|
1768
|
+
);
|
|
1769
|
+
|
|
1770
|
+
LoggerProxy.log('Campaign preview contact accepted successfully', {
|
|
1771
|
+
module: CC_FILE,
|
|
1772
|
+
method: METHODS.ACCEPT_PREVIEW_CONTACT,
|
|
1773
|
+
trackingId: result.trackingId,
|
|
1774
|
+
interactionId: payload.interactionId,
|
|
1775
|
+
});
|
|
1776
|
+
|
|
1777
|
+
return result;
|
|
1778
|
+
} catch (error) {
|
|
1779
|
+
const failure = error.details as Failure;
|
|
1780
|
+
this.metricsManager.trackEvent(
|
|
1781
|
+
METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_ACCEPT_FAILED,
|
|
1782
|
+
{
|
|
1783
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(failure),
|
|
1784
|
+
interactionId: payload.interactionId,
|
|
1785
|
+
campaignId: payload.campaignId,
|
|
1786
|
+
},
|
|
1787
|
+
['behavioral', 'business', 'operational']
|
|
1788
|
+
);
|
|
1789
|
+
const {error: detailedError} = getErrorDetails(
|
|
1790
|
+
error,
|
|
1791
|
+
METHODS.ACCEPT_PREVIEW_CONTACT,
|
|
1792
|
+
CC_FILE
|
|
1793
|
+
);
|
|
1794
|
+
throw detailedError;
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
/**
|
|
1799
|
+
* Skips a campaign preview contact, requesting the next contact from the campaign.
|
|
1800
|
+
*
|
|
1801
|
+
* When a campaign manager reserves a contact for an agent, the agent receives an
|
|
1802
|
+
* `AgentOfferCampaignReservation` event. Instead of accepting, the agent can skip the
|
|
1803
|
+
* preview contact to move to the next contact in the campaign.
|
|
1804
|
+
*
|
|
1805
|
+
* @param {PreviewContactPayload} payload - The preview contact payload containing interactionId and campaignId (campaign name, not UUID).
|
|
1806
|
+
* @returns {Promise<TaskResponse>} Promise resolving with agent contact on success.
|
|
1807
|
+
* @throws {Error} If the operation fails (network error, etc.)
|
|
1808
|
+
*
|
|
1809
|
+
* @example
|
|
1810
|
+
* ```typescript
|
|
1811
|
+
* webex.cc.on('task:campaignPreviewReservation', async (task) => {
|
|
1812
|
+
* const { interactionId } = task.data;
|
|
1813
|
+
* const campaignId = task.data.interaction.callProcessingDetails.campaignId;
|
|
1814
|
+
*
|
|
1815
|
+
* const result = await webex.cc.skipPreviewContact({ interactionId, campaignId });
|
|
1816
|
+
* });
|
|
1817
|
+
* ```
|
|
1818
|
+
*/
|
|
1819
|
+
public async skipPreviewContact(payload: PreviewContactPayload): Promise<TaskResponse> {
|
|
1820
|
+
const task = this.taskManager.getTask(payload.interactionId);
|
|
1821
|
+
if (task?.data?.interaction?.callProcessingDetails?.campaignPreviewSkipDisabled === 'true') {
|
|
1822
|
+
LoggerProxy.warn('Skip action is disabled for this campaign preview contact', {
|
|
1823
|
+
module: CC_FILE,
|
|
1824
|
+
method: METHODS.SKIP_PREVIEW_CONTACT,
|
|
1825
|
+
interactionId: payload.interactionId,
|
|
1826
|
+
});
|
|
1827
|
+
throw new Error('Skip action is disabled for this campaign preview contact');
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1830
|
+
LoggerProxy.info('Skipping campaign preview contact', {
|
|
1831
|
+
module: CC_FILE,
|
|
1832
|
+
method: METHODS.SKIP_PREVIEW_CONTACT,
|
|
1833
|
+
});
|
|
1834
|
+
try {
|
|
1835
|
+
this.metricsManager.timeEvent([
|
|
1836
|
+
METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_SUCCESS,
|
|
1837
|
+
METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_FAILED,
|
|
1838
|
+
]);
|
|
1839
|
+
|
|
1840
|
+
const result = await this.services.dialer.skipPreviewContact({data: payload});
|
|
1841
|
+
|
|
1842
|
+
this.metricsManager.trackEvent(
|
|
1843
|
+
METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_SUCCESS,
|
|
1844
|
+
{
|
|
1845
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponse(result),
|
|
1846
|
+
interactionId: payload.interactionId,
|
|
1847
|
+
campaignId: payload.campaignId,
|
|
1848
|
+
},
|
|
1849
|
+
['behavioral', 'business', 'operational']
|
|
1850
|
+
);
|
|
1851
|
+
|
|
1852
|
+
LoggerProxy.log('Campaign preview contact skipped successfully', {
|
|
1853
|
+
module: CC_FILE,
|
|
1854
|
+
method: METHODS.SKIP_PREVIEW_CONTACT,
|
|
1855
|
+
trackingId: result.trackingId,
|
|
1856
|
+
interactionId: payload.interactionId,
|
|
1857
|
+
});
|
|
1858
|
+
|
|
1859
|
+
return result;
|
|
1860
|
+
} catch (error) {
|
|
1861
|
+
const failure = error.details as Failure;
|
|
1862
|
+
this.metricsManager.trackEvent(
|
|
1863
|
+
METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_FAILED,
|
|
1864
|
+
{
|
|
1865
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(failure),
|
|
1866
|
+
interactionId: payload.interactionId,
|
|
1867
|
+
campaignId: payload.campaignId,
|
|
1868
|
+
},
|
|
1869
|
+
['behavioral', 'business', 'operational']
|
|
1870
|
+
);
|
|
1871
|
+
const {error: detailedError} = getErrorDetails(error, METHODS.SKIP_PREVIEW_CONTACT, CC_FILE);
|
|
1872
|
+
throw detailedError;
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1876
|
+
/**
|
|
1877
|
+
* Removes a campaign preview contact from the campaign list entirely.
|
|
1878
|
+
*
|
|
1879
|
+
* When a campaign manager reserves a contact for an agent, the agent receives an
|
|
1880
|
+
* `AgentOfferCampaignReservation` event. Instead of accepting or skipping, the agent can
|
|
1881
|
+
* remove the preview contact to permanently take it out of the campaign contact list.
|
|
1882
|
+
*
|
|
1883
|
+
* @param {PreviewContactPayload} payload - The preview contact payload containing interactionId and campaignId (campaign name, not UUID).
|
|
1884
|
+
* @returns {Promise<TaskResponse>} Promise resolving with agent contact on success.
|
|
1885
|
+
* @throws {Error} If the operation fails (network error, etc.)
|
|
1886
|
+
*
|
|
1887
|
+
* @example
|
|
1888
|
+
* ```typescript
|
|
1889
|
+
* webex.cc.on('task:campaignPreviewReservation', async (task) => {
|
|
1890
|
+
* const { interactionId } = task.data;
|
|
1891
|
+
* const campaignId = task.data.interaction.callProcessingDetails.campaignId;
|
|
1892
|
+
*
|
|
1893
|
+
* const result = await webex.cc.removePreviewContact({ interactionId, campaignId });
|
|
1894
|
+
* });
|
|
1895
|
+
* ```
|
|
1896
|
+
*/
|
|
1897
|
+
public async removePreviewContact(payload: PreviewContactPayload): Promise<TaskResponse> {
|
|
1898
|
+
const task = this.taskManager.getTask(payload.interactionId);
|
|
1899
|
+
if (task?.data?.interaction?.callProcessingDetails?.campaignPreviewRemoveDisabled === 'true') {
|
|
1900
|
+
LoggerProxy.warn('Remove action is disabled for this campaign preview contact', {
|
|
1901
|
+
module: CC_FILE,
|
|
1902
|
+
method: METHODS.REMOVE_PREVIEW_CONTACT,
|
|
1903
|
+
interactionId: payload.interactionId,
|
|
1904
|
+
});
|
|
1905
|
+
throw new Error('Remove action is disabled for this campaign preview contact');
|
|
1906
|
+
}
|
|
1907
|
+
|
|
1908
|
+
LoggerProxy.info('Removing campaign preview contact', {
|
|
1909
|
+
module: CC_FILE,
|
|
1910
|
+
method: METHODS.REMOVE_PREVIEW_CONTACT,
|
|
1911
|
+
});
|
|
1912
|
+
try {
|
|
1913
|
+
this.metricsManager.timeEvent([
|
|
1914
|
+
METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_SUCCESS,
|
|
1915
|
+
METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_FAILED,
|
|
1916
|
+
]);
|
|
1917
|
+
|
|
1918
|
+
const result = await this.services.dialer.removePreviewContact({data: payload});
|
|
1919
|
+
|
|
1920
|
+
this.metricsManager.trackEvent(
|
|
1921
|
+
METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_SUCCESS,
|
|
1922
|
+
{
|
|
1923
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponse(result),
|
|
1924
|
+
interactionId: payload.interactionId,
|
|
1925
|
+
campaignId: payload.campaignId,
|
|
1926
|
+
},
|
|
1927
|
+
['behavioral', 'business', 'operational']
|
|
1928
|
+
);
|
|
1929
|
+
|
|
1930
|
+
LoggerProxy.log('Campaign preview contact removed successfully', {
|
|
1931
|
+
module: CC_FILE,
|
|
1932
|
+
method: METHODS.REMOVE_PREVIEW_CONTACT,
|
|
1933
|
+
trackingId: result.trackingId,
|
|
1934
|
+
interactionId: payload.interactionId,
|
|
1935
|
+
});
|
|
1936
|
+
|
|
1937
|
+
return result;
|
|
1938
|
+
} catch (error) {
|
|
1939
|
+
const failure = error.details as Failure;
|
|
1940
|
+
this.metricsManager.trackEvent(
|
|
1941
|
+
METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_FAILED,
|
|
1942
|
+
{
|
|
1943
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(failure),
|
|
1944
|
+
interactionId: payload.interactionId,
|
|
1945
|
+
campaignId: payload.campaignId,
|
|
1946
|
+
},
|
|
1947
|
+
['behavioral', 'business', 'operational']
|
|
1948
|
+
);
|
|
1949
|
+
const {error: detailedError} = getErrorDetails(
|
|
1950
|
+
error,
|
|
1951
|
+
METHODS.REMOVE_PREVIEW_CONTACT,
|
|
1952
|
+
CC_FILE
|
|
1953
|
+
);
|
|
1954
|
+
throw detailedError;
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
|
|
1512
1958
|
/**
|
|
1513
1959
|
* Fetches outdial ANI (Automatic Number Identification) entries for an outdial ANI ID.
|
|
1514
1960
|
*
|
|
@@ -1656,6 +2102,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
1656
2102
|
/**
|
|
1657
2103
|
* Updates the agent device type and login configuration.
|
|
1658
2104
|
* Use this method to change how an agent connects to the contact center system (e.g., switching from browser-based calling to a desk phone extension).
|
|
2105
|
+
* Change to any field of the profile is allowed;
|
|
1659
2106
|
*
|
|
1660
2107
|
* @param {AgentDeviceUpdate} data Configuration containing:
|
|
1661
2108
|
* - loginOption: New device type ('BROWSER', 'EXTENSION', 'AGENT_DN')
|
|
@@ -1695,29 +2142,8 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
1695
2142
|
});
|
|
1696
2143
|
|
|
1697
2144
|
try {
|
|
1698
|
-
// Only block if both loginOption AND teamId remain unchanged
|
|
1699
|
-
if (
|
|
1700
|
-
this.webCallingService?.loginOption === data.loginOption &&
|
|
1701
|
-
data.teamId === this.agentConfig.currentTeamId
|
|
1702
|
-
) {
|
|
1703
|
-
const message =
|
|
1704
|
-
'Will not proceed with device update as new Device type is same as current device type and teamId is same as current teamId';
|
|
1705
|
-
const err = new Error(message) as GenericError;
|
|
1706
|
-
err.details = {
|
|
1707
|
-
type: 'Identical Device Change Failure',
|
|
1708
|
-
orgId: this.$webex.credentials.getOrgId(),
|
|
1709
|
-
trackingId,
|
|
1710
|
-
data: {
|
|
1711
|
-
agentId: this.agentConfig.agentId,
|
|
1712
|
-
reasonCode: 'R002',
|
|
1713
|
-
reason: message,
|
|
1714
|
-
},
|
|
1715
|
-
};
|
|
1716
|
-
throw err;
|
|
1717
|
-
}
|
|
1718
|
-
|
|
1719
2145
|
await this.stationLogout({
|
|
1720
|
-
logoutReason: 'User requested agent
|
|
2146
|
+
logoutReason: 'User requested agent profile update',
|
|
1721
2147
|
});
|
|
1722
2148
|
|
|
1723
2149
|
const loginPayload: AgentLogin = {
|