@webex/contact-center 3.12.0-next.5 → 3.12.0-next.50
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/dist/cc.js +161 -21
- package/dist/cc.js.map +1 -1
- package/dist/constants.js +2 -0
- package/dist/constants.js.map +1 -1
- package/dist/metrics/behavioral-events.js +26 -0
- package/dist/metrics/behavioral-events.js.map +1 -1
- package/dist/metrics/constants.js +4 -0
- package/dist/metrics/constants.js.map +1 -1
- package/dist/services/config/Util.js +1 -1
- package/dist/services/config/Util.js.map +1 -1
- package/dist/services/config/constants.js +1 -1
- package/dist/services/config/constants.js.map +1 -1
- package/dist/services/config/types.js +4 -0
- package/dist/services/config/types.js.map +1 -1
- package/dist/services/core/Err.js.map +1 -1
- package/dist/services/core/Utils.js +37 -9
- package/dist/services/core/Utils.js.map +1 -1
- package/dist/services/task/TaskManager.js +90 -8
- package/dist/services/task/TaskManager.js.map +1 -1
- package/dist/services/task/constants.js +3 -1
- package/dist/services/task/constants.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/index.js +7 -2
- package/dist/services/task/index.js.map +1 -1
- package/dist/services/task/types.js +44 -0
- package/dist/services/task/types.js.map +1 -1
- package/dist/types/cc.d.ts +44 -0
- package/dist/types/constants.d.ts +2 -0
- package/dist/types/metrics/constants.d.ts +4 -0
- package/dist/types/services/config/types.d.ts +10 -1
- package/dist/types/services/core/Err.d.ts +4 -0
- package/dist/types/services/core/Utils.d.ts +10 -3
- package/dist/types/services/task/constants.d.ts +2 -0
- package/dist/types/services/task/dialer.d.ts +30 -0
- package/dist/types/services/task/types.d.ts +53 -1
- package/dist/webex.js +1 -1
- package/package.json +9 -9
- package/src/cc.ts +196 -22
- package/src/constants.ts +2 -0
- package/src/metrics/behavioral-events.ts +28 -0
- package/src/metrics/constants.ts +4 -0
- package/src/services/config/Util.ts +1 -1
- package/src/services/config/constants.ts +1 -1
- package/src/services/config/types.ts +6 -1
- package/src/services/core/Err.ts +2 -0
- package/src/services/core/Utils.ts +43 -8
- package/src/services/task/TaskManager.ts +102 -22
- package/src/services/task/constants.ts +2 -0
- package/src/services/task/dialer.ts +80 -0
- package/src/services/task/index.ts +7 -2
- package/src/services/task/types.ts +56 -0
- package/test/unit/spec/cc.ts +154 -20
- package/test/unit/spec/services/config/index.ts +3 -3
- package/test/unit/spec/services/core/Utils.ts +90 -7
- package/test/unit/spec/services/task/TaskManager.ts +238 -7
- package/test/unit/spec/services/task/dialer.ts +190 -0
- package/test/unit/spec/services/task/index.ts +21 -0
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
package/dist/cc.js
CHANGED
|
@@ -312,7 +312,6 @@ class ContactCenter extends _webexCore.WebexPlugin {
|
|
|
312
312
|
webex: this.$webex,
|
|
313
313
|
connectionConfig: this.getConnectionConfig()
|
|
314
314
|
});
|
|
315
|
-
this.services.webSocketManager.on('message', this.handleWebsocketMessage);
|
|
316
315
|
this.webCallingService = new _WebCallingService.default(this.$webex);
|
|
317
316
|
this.apiAIAssistant = new _ApiAiAssistant.ApiAIAssistant(this.$webex);
|
|
318
317
|
this.metricsManager = _MetricsManager.default.getInstance({
|
|
@@ -422,13 +421,14 @@ class ContactCenter extends _webexCore.WebexPlugin {
|
|
|
422
421
|
* ```
|
|
423
422
|
*/
|
|
424
423
|
async register() {
|
|
425
|
-
_loggerProxy.default.
|
|
424
|
+
_loggerProxy.default.log('Starting CC SDK registration', {
|
|
426
425
|
module: _constants.CC_FILE,
|
|
427
426
|
method: _constants.METHODS.REGISTER
|
|
428
427
|
});
|
|
429
428
|
try {
|
|
430
429
|
this.metricsManager.timeEvent([_constants4.METRIC_EVENT_NAMES.WEBSOCKET_REGISTER_SUCCESS, _constants4.METRIC_EVENT_NAMES.WEBSOCKET_REGISTER_FAILED]);
|
|
431
430
|
this.setupEventListeners();
|
|
431
|
+
this.services.webSocketManager.on('message', this.handleWebsocketMessage);
|
|
432
432
|
const resp = await this.connectWebsocket();
|
|
433
433
|
// Ensure 'dn' is always populated from 'defaultDn'
|
|
434
434
|
resp.dn = resp.defaultDn;
|
|
@@ -616,7 +616,7 @@ class ContactCenter extends _webexCore.WebexPlugin {
|
|
|
616
616
|
* @private
|
|
617
617
|
*/
|
|
618
618
|
async connectWebsocket() {
|
|
619
|
-
_loggerProxy.default.
|
|
619
|
+
_loggerProxy.default.log('Connecting to websocket', {
|
|
620
620
|
module: _constants.CC_FILE,
|
|
621
621
|
method: _constants.METHODS.CONNECT_WEBSOCKET
|
|
622
622
|
});
|
|
@@ -639,7 +639,7 @@ class ContactCenter extends _webexCore.WebexPlugin {
|
|
|
639
639
|
this.taskManager.setWebRtcEnabled(this.agentConfig.webRtcEnabled);
|
|
640
640
|
this.apiAIAssistant.setAIFeatureFlags(this.agentConfig.aiFeature);
|
|
641
641
|
if (this.agentConfig.aiFeature?.realtimeTranscripts?.enable) {
|
|
642
|
-
_loggerProxy.default.
|
|
642
|
+
_loggerProxy.default.log('Connecting to RTD websocket', {
|
|
643
643
|
module: _constants.CC_FILE,
|
|
644
644
|
method: _constants.METHODS.CONNECT_WEBSOCKET
|
|
645
645
|
});
|
|
@@ -675,6 +675,11 @@ class ContactCenter extends _webexCore.WebexPlugin {
|
|
|
675
675
|
}
|
|
676
676
|
if (this.$config && this.$config.allowAutomatedRelogin) {
|
|
677
677
|
await this.silentRelogin();
|
|
678
|
+
} else {
|
|
679
|
+
_loggerProxy.default.log('Skipping silent relogin: allowAutomatedRelogin is disabled', {
|
|
680
|
+
module: _constants.CC_FILE,
|
|
681
|
+
method: _constants.METHODS.CONNECT_WEBSOCKET
|
|
682
|
+
});
|
|
678
683
|
}
|
|
679
684
|
return this.agentConfig;
|
|
680
685
|
} catch (error) {
|
|
@@ -715,22 +720,27 @@ class ContactCenter extends _webexCore.WebexPlugin {
|
|
|
715
720
|
* ```
|
|
716
721
|
*/
|
|
717
722
|
async stationLogin(data) {
|
|
718
|
-
|
|
723
|
+
const loggerContext = {
|
|
719
724
|
module: _constants.CC_FILE,
|
|
720
725
|
method: _constants.METHODS.STATION_LOGIN
|
|
721
|
-
}
|
|
726
|
+
};
|
|
722
727
|
try {
|
|
728
|
+
_loggerProxy.default.log(`Starting agent station login | loginOption: ${data?.loginOption} teamId: ${data?.teamId}`, loggerContext);
|
|
723
729
|
this.metricsManager.timeEvent([_constants4.METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS, _constants4.METRIC_EVENT_NAMES.STATION_LOGIN_FAILED]);
|
|
724
730
|
const dialPlanEntries = this.agentConfig?.dialPlan?.dialPlanEntity ?? [];
|
|
725
|
-
if (data.loginOption === _types.LoginOption.AGENT_DN
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
731
|
+
if (data.loginOption === _types.LoginOption.AGENT_DN) {
|
|
732
|
+
_loggerProxy.default.log(`Validating dial number | dialPlanEnabled: ${!!this.agentConfig?.dialPlan} | dialPlanEntryCount: ${dialPlanEntries.length}`, loggerContext);
|
|
733
|
+
if (!(0, _Utils.isValidDialNumber)(data.dialNumber, dialPlanEntries)) {
|
|
734
|
+
_loggerProxy.default.log(`Dial number validation failed | dialNumber: ${data.dialNumber} | dialPlanEntryCount: ${dialPlanEntries.length}`, loggerContext);
|
|
735
|
+
const error = new Error('INVALID_DIAL_NUMBER');
|
|
736
|
+
// @ts-ignore - adding custom key to the error object
|
|
737
|
+
error.details = {
|
|
738
|
+
data: {
|
|
739
|
+
reason: 'INVALID_DIAL_NUMBER'
|
|
740
|
+
}
|
|
741
|
+
};
|
|
742
|
+
throw error;
|
|
743
|
+
}
|
|
734
744
|
}
|
|
735
745
|
const loginResponse = await this.services.agent.stationLogin({
|
|
736
746
|
data: {
|
|
@@ -1102,13 +1112,13 @@ class ContactCenter extends _webexCore.WebexPlugin {
|
|
|
1102
1112
|
async handleConnectionLost(msg) {
|
|
1103
1113
|
if (msg.isConnectionLost) {
|
|
1104
1114
|
// TODO: Emit an event saying connection is lost
|
|
1105
|
-
_loggerProxy.default.
|
|
1115
|
+
_loggerProxy.default.log('event=handleConnectionLost | Connection lost', {
|
|
1106
1116
|
module: _constants.CC_FILE,
|
|
1107
1117
|
method: _constants.METHODS.HANDLE_CONNECTION_LOST
|
|
1108
1118
|
});
|
|
1109
1119
|
} else if (msg.isSocketReconnected) {
|
|
1110
1120
|
// TODO: Emit an event saying connection is re-estabilished
|
|
1111
|
-
_loggerProxy.default.
|
|
1121
|
+
_loggerProxy.default.log('event=handleConnectionReconnect | Connection reconnected attempting to request silent relogin', {
|
|
1112
1122
|
module: _constants.CC_FILE,
|
|
1113
1123
|
method: _constants.METHODS.HANDLE_CONNECTION_LOST
|
|
1114
1124
|
});
|
|
@@ -1123,7 +1133,7 @@ class ContactCenter extends _webexCore.WebexPlugin {
|
|
|
1123
1133
|
* @private
|
|
1124
1134
|
*/
|
|
1125
1135
|
async silentRelogin() {
|
|
1126
|
-
_loggerProxy.default.
|
|
1136
|
+
_loggerProxy.default.log('Starting silent relogin process', {
|
|
1127
1137
|
module: _constants.CC_FILE,
|
|
1128
1138
|
method: _constants.METHODS.SILENT_RELOGIN
|
|
1129
1139
|
});
|
|
@@ -1145,7 +1155,7 @@ class ContactCenter extends _webexCore.WebexPlugin {
|
|
|
1145
1155
|
this.agentConfig.currentTeamId = reLoginResponse.data.teamId;
|
|
1146
1156
|
await this.handleDeviceType(deviceType, dn);
|
|
1147
1157
|
if (lastStateChangeReason === 'agent-wss-disconnect') {
|
|
1148
|
-
_loggerProxy.default.
|
|
1158
|
+
_loggerProxy.default.log('event=requestAutoStateChange | Requesting state change to available on socket reconnect', {
|
|
1149
1159
|
module: _constants.CC_FILE,
|
|
1150
1160
|
method: _constants.METHODS.SILENT_RELOGIN
|
|
1151
1161
|
});
|
|
@@ -1169,8 +1179,6 @@ class ContactCenter extends _webexCore.WebexPlugin {
|
|
|
1169
1179
|
}
|
|
1170
1180
|
this.agentConfig.lastStateAuxCodeId = auxCodeId;
|
|
1171
1181
|
this.agentConfig.isAgentLoggedIn = true;
|
|
1172
|
-
// TODO: https://jira-eng-gpk2.cisco.com/jira/browse/SPARK-626777 Implement the de-register method and close the listener there
|
|
1173
|
-
this.services.webSocketManager.on('message', this.handleWebsocketMessage);
|
|
1174
1182
|
_loggerProxy.default.log(`Silent relogin process completed successfully with login Option: ${reLoginResponse.data.deviceType} teamId: ${reLoginResponse.data.teamId}`, {
|
|
1175
1183
|
module: _constants.CC_FILE,
|
|
1176
1184
|
method: _constants.METHODS.SILENT_RELOGIN,
|
|
@@ -1444,6 +1452,138 @@ class ContactCenter extends _webexCore.WebexPlugin {
|
|
|
1444
1452
|
}
|
|
1445
1453
|
}
|
|
1446
1454
|
|
|
1455
|
+
/**
|
|
1456
|
+
* Skips a campaign preview contact, requesting the next contact from the campaign.
|
|
1457
|
+
*
|
|
1458
|
+
* When a campaign manager reserves a contact for an agent, the agent receives an
|
|
1459
|
+
* `AgentOfferCampaignReservation` event. Instead of accepting, the agent can skip the
|
|
1460
|
+
* preview contact to move to the next contact in the campaign.
|
|
1461
|
+
*
|
|
1462
|
+
* @param {PreviewContactPayload} payload - The preview contact payload containing interactionId and campaignId (campaign name, not UUID).
|
|
1463
|
+
* @returns {Promise<TaskResponse>} Promise resolving with agent contact on success.
|
|
1464
|
+
* @throws {Error} If the operation fails (network error, etc.)
|
|
1465
|
+
*
|
|
1466
|
+
* @example
|
|
1467
|
+
* ```typescript
|
|
1468
|
+
* webex.cc.on('task:campaignPreviewReservation', async (task) => {
|
|
1469
|
+
* const { interactionId } = task.data;
|
|
1470
|
+
* const campaignId = task.data.interaction.callProcessingDetails.campaignId;
|
|
1471
|
+
*
|
|
1472
|
+
* const result = await webex.cc.skipPreviewContact({ interactionId, campaignId });
|
|
1473
|
+
* });
|
|
1474
|
+
* ```
|
|
1475
|
+
*/
|
|
1476
|
+
async skipPreviewContact(payload) {
|
|
1477
|
+
const task = this.taskManager.getTask(payload.interactionId);
|
|
1478
|
+
if (task?.data?.interaction?.callProcessingDetails?.campaignPreviewSkipDisabled === 'true') {
|
|
1479
|
+
_loggerProxy.default.warn('Skip action is disabled for this campaign preview contact', {
|
|
1480
|
+
module: _constants.CC_FILE,
|
|
1481
|
+
method: _constants.METHODS.SKIP_PREVIEW_CONTACT,
|
|
1482
|
+
interactionId: payload.interactionId
|
|
1483
|
+
});
|
|
1484
|
+
throw new Error('Skip action is disabled for this campaign preview contact');
|
|
1485
|
+
}
|
|
1486
|
+
_loggerProxy.default.info('Skipping campaign preview contact', {
|
|
1487
|
+
module: _constants.CC_FILE,
|
|
1488
|
+
method: _constants.METHODS.SKIP_PREVIEW_CONTACT
|
|
1489
|
+
});
|
|
1490
|
+
try {
|
|
1491
|
+
this.metricsManager.timeEvent([_constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_SUCCESS, _constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_FAILED]);
|
|
1492
|
+
const result = await this.services.dialer.skipPreviewContact({
|
|
1493
|
+
data: payload
|
|
1494
|
+
});
|
|
1495
|
+
this.metricsManager.trackEvent(_constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_SUCCESS, {
|
|
1496
|
+
..._MetricsManager.default.getCommonTrackingFieldForAQMResponse(result),
|
|
1497
|
+
interactionId: payload.interactionId,
|
|
1498
|
+
campaignId: payload.campaignId
|
|
1499
|
+
}, ['behavioral', 'business', 'operational']);
|
|
1500
|
+
_loggerProxy.default.log('Campaign preview contact skipped successfully', {
|
|
1501
|
+
module: _constants.CC_FILE,
|
|
1502
|
+
method: _constants.METHODS.SKIP_PREVIEW_CONTACT,
|
|
1503
|
+
trackingId: result.trackingId,
|
|
1504
|
+
interactionId: payload.interactionId
|
|
1505
|
+
});
|
|
1506
|
+
return result;
|
|
1507
|
+
} catch (error) {
|
|
1508
|
+
const failure = error.details;
|
|
1509
|
+
this.metricsManager.trackEvent(_constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_SKIP_FAILED, {
|
|
1510
|
+
..._MetricsManager.default.getCommonTrackingFieldForAQMResponseFailed(failure),
|
|
1511
|
+
interactionId: payload.interactionId,
|
|
1512
|
+
campaignId: payload.campaignId
|
|
1513
|
+
}, ['behavioral', 'business', 'operational']);
|
|
1514
|
+
const {
|
|
1515
|
+
error: detailedError
|
|
1516
|
+
} = (0, _Utils.getErrorDetails)(error, _constants.METHODS.SKIP_PREVIEW_CONTACT, _constants.CC_FILE);
|
|
1517
|
+
throw detailedError;
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
/**
|
|
1522
|
+
* Removes a campaign preview contact from the campaign list entirely.
|
|
1523
|
+
*
|
|
1524
|
+
* When a campaign manager reserves a contact for an agent, the agent receives an
|
|
1525
|
+
* `AgentOfferCampaignReservation` event. Instead of accepting or skipping, the agent can
|
|
1526
|
+
* remove the preview contact to permanently take it out of the campaign contact list.
|
|
1527
|
+
*
|
|
1528
|
+
* @param {PreviewContactPayload} payload - The preview contact payload containing interactionId and campaignId (campaign name, not UUID).
|
|
1529
|
+
* @returns {Promise<TaskResponse>} Promise resolving with agent contact on success.
|
|
1530
|
+
* @throws {Error} If the operation fails (network error, etc.)
|
|
1531
|
+
*
|
|
1532
|
+
* @example
|
|
1533
|
+
* ```typescript
|
|
1534
|
+
* webex.cc.on('task:campaignPreviewReservation', async (task) => {
|
|
1535
|
+
* const { interactionId } = task.data;
|
|
1536
|
+
* const campaignId = task.data.interaction.callProcessingDetails.campaignId;
|
|
1537
|
+
*
|
|
1538
|
+
* const result = await webex.cc.removePreviewContact({ interactionId, campaignId });
|
|
1539
|
+
* });
|
|
1540
|
+
* ```
|
|
1541
|
+
*/
|
|
1542
|
+
async removePreviewContact(payload) {
|
|
1543
|
+
const task = this.taskManager.getTask(payload.interactionId);
|
|
1544
|
+
if (task?.data?.interaction?.callProcessingDetails?.campaignPreviewRemoveDisabled === 'true') {
|
|
1545
|
+
_loggerProxy.default.warn('Remove action is disabled for this campaign preview contact', {
|
|
1546
|
+
module: _constants.CC_FILE,
|
|
1547
|
+
method: _constants.METHODS.REMOVE_PREVIEW_CONTACT,
|
|
1548
|
+
interactionId: payload.interactionId
|
|
1549
|
+
});
|
|
1550
|
+
throw new Error('Remove action is disabled for this campaign preview contact');
|
|
1551
|
+
}
|
|
1552
|
+
_loggerProxy.default.info('Removing campaign preview contact', {
|
|
1553
|
+
module: _constants.CC_FILE,
|
|
1554
|
+
method: _constants.METHODS.REMOVE_PREVIEW_CONTACT
|
|
1555
|
+
});
|
|
1556
|
+
try {
|
|
1557
|
+
this.metricsManager.timeEvent([_constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_SUCCESS, _constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_FAILED]);
|
|
1558
|
+
const result = await this.services.dialer.removePreviewContact({
|
|
1559
|
+
data: payload
|
|
1560
|
+
});
|
|
1561
|
+
this.metricsManager.trackEvent(_constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_SUCCESS, {
|
|
1562
|
+
..._MetricsManager.default.getCommonTrackingFieldForAQMResponse(result),
|
|
1563
|
+
interactionId: payload.interactionId,
|
|
1564
|
+
campaignId: payload.campaignId
|
|
1565
|
+
}, ['behavioral', 'business', 'operational']);
|
|
1566
|
+
_loggerProxy.default.log('Campaign preview contact removed successfully', {
|
|
1567
|
+
module: _constants.CC_FILE,
|
|
1568
|
+
method: _constants.METHODS.REMOVE_PREVIEW_CONTACT,
|
|
1569
|
+
trackingId: result.trackingId,
|
|
1570
|
+
interactionId: payload.interactionId
|
|
1571
|
+
});
|
|
1572
|
+
return result;
|
|
1573
|
+
} catch (error) {
|
|
1574
|
+
const failure = error.details;
|
|
1575
|
+
this.metricsManager.trackEvent(_constants4.METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_REMOVE_FAILED, {
|
|
1576
|
+
..._MetricsManager.default.getCommonTrackingFieldForAQMResponseFailed(failure),
|
|
1577
|
+
interactionId: payload.interactionId,
|
|
1578
|
+
campaignId: payload.campaignId
|
|
1579
|
+
}, ['behavioral', 'business', 'operational']);
|
|
1580
|
+
const {
|
|
1581
|
+
error: detailedError
|
|
1582
|
+
} = (0, _Utils.getErrorDetails)(error, _constants.METHODS.REMOVE_PREVIEW_CONTACT, _constants.CC_FILE);
|
|
1583
|
+
throw detailedError;
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1447
1587
|
/**
|
|
1448
1588
|
* Fetches outdial ANI (Automatic Number Identification) entries for an outdial ANI ID.
|
|
1449
1589
|
*
|