@webex/contact-center 3.9.0-next.15 → 3.9.0-next.17

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.
@@ -997,6 +997,8 @@ export type DialerPayload = {
997
997
  mediaType: 'telephony' | 'chat' | 'social' | 'email';
998
998
  /** The outbound type for the task */
999
999
  outboundType: 'OUTDIAL' | 'CALLBACK' | 'EXECUTE_FLOW';
1000
+ /** The Outdial ANI number that will be used while making a call to the customer. */
1001
+ origin: string;
1000
1002
  };
1001
1003
  /**
1002
1004
  * Data structure for cleaning up contact resources
package/dist/webex.js CHANGED
@@ -29,7 +29,7 @@ if (!global.Buffer) {
29
29
  */
30
30
  const Webex = _webexCore.default.extend({
31
31
  webex: true,
32
- version: `3.9.0-next.15`
32
+ version: `3.9.0-next.17`
33
33
  });
34
34
 
35
35
  /**
package/package.json CHANGED
@@ -45,7 +45,7 @@
45
45
  },
46
46
  "dependencies": {
47
47
  "@types/platform": "1.3.4",
48
- "@webex/calling": "3.9.0-next.8",
48
+ "@webex/calling": "3.9.0-next.9",
49
49
  "@webex/internal-plugin-mercury": "3.9.0-next.3",
50
50
  "@webex/internal-plugin-metrics": "3.9.0-next.3",
51
51
  "@webex/internal-plugin-support": "3.9.0-next.5",
@@ -56,6 +56,7 @@
56
56
  "lodash": "^4.17.21"
57
57
  },
58
58
  "devDependencies": {
59
+ "@babel/core": "^7.22.11",
59
60
  "@babel/preset-typescript": "7.22.11",
60
61
  "@types/jest": "27.4.1",
61
62
  "@typescript-eslint/eslint-plugin": "5.38.1",
@@ -79,5 +80,5 @@
79
80
  "typedoc": "^0.25.0",
80
81
  "typescript": "4.9.5"
81
82
  },
82
- "version": "3.9.0-next.15"
83
+ "version": "3.9.0-next.17"
83
84
  }
package/src/cc.ts CHANGED
@@ -38,14 +38,20 @@ import {
38
38
  MERCURY_DISCONNECTED_SUCCESS,
39
39
  METHODS,
40
40
  } from './constants';
41
+ import {AGENT_STATE_AVAILABLE, AGENT_STATE_AVAILABLE_ID} from './services/config/constants';
41
42
  import {AGENT, WEB_RTC_PREFIX} from './services/constants';
42
43
  import Services from './services';
43
44
  import WebexRequest from './services/core/WebexRequest';
44
45
  import LoggerProxy from './logger-proxy';
45
46
  import {StateChange, Logout, StateChangeSuccess, AGENT_EVENTS} from './services/agent/types';
46
47
  import {getErrorDetails, isValidDialNumber} from './services/core/Utils';
47
- import {Profile, WelcomeEvent, CC_EVENTS} from './services/config/types';
48
- import {AGENT_STATE_AVAILABLE, AGENT_STATE_AVAILABLE_ID} from './services/config/constants';
48
+ import {
49
+ Profile,
50
+ WelcomeEvent,
51
+ CC_EVENTS,
52
+ OutdialAniEntriesResponse,
53
+ OutdialAniParams,
54
+ } from './services/config/types';
49
55
  import {ConnectionLostDetails} from './services/core/websocket/types';
50
56
  import TaskManager from './services/task/TaskManager';
51
57
  import WebCallingService from './services/WebCallingService';
@@ -1330,6 +1336,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
1330
1336
  * Makes an outbound call to a specified phone number.
1331
1337
  *
1332
1338
  * @param {string} destination - The phone number to dial (e.g., '+1234567890').
1339
+ * @param {string} origin - The contact center number that will be used while making a call to the customer.
1333
1340
  * Should include country code and be in E.164 format.
1334
1341
  * @returns {Promise<TaskResponse>} Resolves with the task response containing:
1335
1342
  * - interactionId: Unique identifier for the outbound call
@@ -1365,7 +1372,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
1365
1372
  *
1366
1373
  * // Start the outbound call
1367
1374
  * const destination = '+1234567890';
1368
- * const task = await cc.startOutdial(destination);
1375
+ * const task = await cc.startOutdial(destination, origin);
1369
1376
  *
1370
1377
  * // Listen for all relevant task events
1371
1378
  * task.on('task:ringing', () => {
@@ -1433,7 +1440,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
1433
1440
  * }
1434
1441
  * ```
1435
1442
  */
1436
- public async startOutdial(destination: string): Promise<TaskResponse> {
1443
+ public async startOutdial(destination: string, origin: string): Promise<TaskResponse> {
1437
1444
  LoggerProxy.info('Starting outbound dial', {
1438
1445
  module: CC_FILE,
1439
1446
  method: METHODS.START_OUTDIAL,
@@ -1447,6 +1454,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
1447
1454
  // Construct the outdial payload.
1448
1455
  const outDialPayload: DialerPayload = {
1449
1456
  destination,
1457
+ origin,
1450
1458
  entryPointId: this.agentConfig.outDialEp,
1451
1459
  direction: OUTDIAL_DIRECTION,
1452
1460
  attributes: ATTRIBUTES,
@@ -1461,6 +1469,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
1461
1469
  {
1462
1470
  ...MetricsManager.getCommonTrackingFieldForAQMResponse(result),
1463
1471
  destination,
1472
+ origin,
1464
1473
  mediaType: OUTDIAL_MEDIA_TYPE,
1465
1474
  },
1466
1475
  ['behavioral', 'business', 'operational']
@@ -1481,6 +1490,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
1481
1490
  {
1482
1491
  ...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(failure),
1483
1492
  destination,
1493
+ origin,
1484
1494
  mediaType: OUTDIAL_MEDIA_TYPE,
1485
1495
  },
1486
1496
  ['behavioral', 'business', 'operational']
@@ -1490,6 +1500,124 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
1490
1500
  }
1491
1501
  }
1492
1502
 
1503
+ /**
1504
+ * Fetches outdial ANI (Automatic Number Identification) entries for an outdial ANI ID.
1505
+ *
1506
+ * This method retrieves the list of phone numbers that can be used as caller ID when making
1507
+ * outbound calls. The ANI data is associated with an outdial ANI ID and can be filtered
1508
+ * and paginated as needed.
1509
+ *
1510
+ * @param {string} outdialANI - The outdial ANI ID to fetch ANI data for
1511
+ * @param {number} [page] - Optional page number for pagination (0-based)
1512
+ * @param {number} [pageSize] - Optional number of items per page
1513
+ * @param {string} [search] - Optional search term to filter results by name or number
1514
+ * @param {string} [filter] - Optional filter string
1515
+ * @param {string} [attributes] - Optional attributes to include in response
1516
+ * @returns {Promise<OutdialAniEntriesResponse>} Promise resolving to outdial ANI response containing:
1517
+ * - data: Array of ANI entries with number and name
1518
+ * - meta: Pagination metadata
1519
+ * @throws {Error} If the operation fails or agent is not registered
1520
+ * @public
1521
+ * @example
1522
+ * ```typescript
1523
+ * const cc = webex.cc;
1524
+ * await cc.register();
1525
+ *
1526
+ * // Get agent profile to obtain outdial ANI ID
1527
+ * const agentProfile = cc.agentConfig;
1528
+ * const outdialANI = agentProfile.outdialANIId;
1529
+ *
1530
+ * // Basic usage - get all ANI data for an outdial ANI ID
1531
+ * const aniData = await cc.getOutdialAniEntries({ outdialANI });
1532
+ *
1533
+ * // With pagination and search
1534
+ * const paginatedAni = await cc.getOutdialAniEntries({
1535
+ * outdialANI,
1536
+ * page: 0,
1537
+ * pageSize: 50,
1538
+ * search: '555' // search for numbers containing '555'
1539
+ * });
1540
+ *
1541
+ * // Process the results
1542
+ * paginatedAni.forEach(ani => {
1543
+ * console.log(`ANI: ${ani.number} - ${ani.name}`);
1544
+ * });
1545
+ * ```
1546
+ */
1547
+ public async getOutdialAniEntries(params: OutdialAniParams): Promise<OutdialAniEntriesResponse> {
1548
+ const {outdialANI, page, pageSize, search, filter, attributes} = params;
1549
+
1550
+ LoggerProxy.info('Fetching outdial ANI entries', {
1551
+ module: CC_FILE,
1552
+ method: METHODS.GET_OUTDIAL_ANI_ENTRIES,
1553
+ });
1554
+
1555
+ const orgId = this.$webex.credentials.getOrgId();
1556
+
1557
+ if (!orgId) {
1558
+ LoggerProxy.error('Org ID not found.', {
1559
+ module: CC_FILE,
1560
+ method: METHODS.GET_OUTDIAL_ANI_ENTRIES,
1561
+ });
1562
+
1563
+ throw new Error('Org ID not found.');
1564
+ }
1565
+
1566
+ try {
1567
+ const result = await this.services.config.getOutdialAniEntries(orgId, {
1568
+ outdialANI,
1569
+ page,
1570
+ pageSize,
1571
+ search,
1572
+ filter,
1573
+ attributes,
1574
+ });
1575
+
1576
+ this.metricsManager.trackEvent(
1577
+ METRIC_EVENT_NAMES.OUTDIAL_ANI_EP_FETCH_SUCCESS,
1578
+ {
1579
+ outdialANI,
1580
+ resultCount: result?.length || 0,
1581
+ },
1582
+ ['behavioral', 'business', 'operational']
1583
+ );
1584
+
1585
+ LoggerProxy.log(`Successfully retrieved outdial ANI entries for ANI ID ${outdialANI}`, {
1586
+ module: CC_FILE,
1587
+ method: METHODS.GET_OUTDIAL_ANI_ENTRIES,
1588
+ });
1589
+
1590
+ return result;
1591
+ } catch (error) {
1592
+ const failure = error.details as Failure;
1593
+ this.metricsManager.trackEvent(
1594
+ METRIC_EVENT_NAMES.OUTDIAL_ANI_EP_FETCH_FAILED,
1595
+ {
1596
+ ...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(failure),
1597
+ outdialANI,
1598
+ error,
1599
+ },
1600
+ ['behavioral', 'business', 'operational']
1601
+ );
1602
+
1603
+ LoggerProxy.error(
1604
+ `Failed to fetch outdial ANI entries for ANI ID ${outdialANI} due to: ${error}`,
1605
+ {
1606
+ module: CC_FILE,
1607
+ method: METHODS.GET_OUTDIAL_ANI_ENTRIES,
1608
+ trackingId: failure.trackingId,
1609
+ }
1610
+ );
1611
+
1612
+ const {error: detailedError} = getErrorDetails(
1613
+ error,
1614
+ METHODS.GET_OUTDIAL_ANI_ENTRIES,
1615
+ CC_FILE
1616
+ );
1617
+ throw detailedError;
1618
+ }
1619
+ }
1620
+
1493
1621
  /**
1494
1622
  * Uploads logs to help troubleshoot SDK issues.
1495
1623
  *
package/src/constants.ts CHANGED
@@ -42,6 +42,7 @@ export const METHODS = {
42
42
  HANDLE_DEVICE_TYPE: 'handleDeviceType',
43
43
  START_OUTDIAL: 'startOutdial',
44
44
  GET_QUEUES: 'getQueues',
45
+ GET_OUTDIAL_ANI_ENTRIES: 'getOutdialAniEntries',
45
46
  UPLOAD_LOGS: 'uploadLogs',
46
47
  UPDATE_AGENT_PROFILE: 'updateAgentProfile',
47
48
  GET_DEVICE_ID: 'getDeviceId',
@@ -37,7 +37,6 @@ type Enum<T extends Record<string, unknown>> = T[keyof T];
37
37
  * @property {string} TASK_HOLD_FAILED - Event name for failed task hold.
38
38
  * @property {string} TASK_RESUME_SUCCESS - Event name for successful task resume.
39
39
  * @property {string} TASK_RESUME_FAILED - Event name for failed task resume.
40
- *
41
40
  * @property {string} TASK_CONSULT_START_SUCCESS - Event name for successful consult start.
42
41
  * @property {string} TASK_CONSULT_START_FAILED - Event name for failed consult start.
43
42
  * @property {string} TASK_CONSULT_END_SUCCESS - Event name for successful consult end.
@@ -69,6 +68,9 @@ type Enum<T extends Record<string, unknown>> = T[keyof T];
69
68
  * @property {string} AGENT_DEVICE_TYPE_UPDATE_SUCCESS - Event name for successful agent device type update.
70
69
  * @property {string} AGENT_DEVICE_TYPE_UPDATE_FAILED - Event name for failed agent device type update.
71
70
  *
71
+ * @property {string} OUTDIAL_ANI_EP_FETCH_SUCCESS - Event name for successful outdial ANI entries fetch.
72
+ * @property {string} OUTDIAL_ANI_EP_FETCH_FAILED - Event name for failed outdial ANI entries fetch.
73
+ *
72
74
  * @readonly
73
75
  */
74
76
  export const METRIC_EVENT_NAMES = {
@@ -149,6 +151,10 @@ export const METRIC_EVENT_NAMES = {
149
151
  // Queue API Events
150
152
  QUEUE_FETCH_SUCCESS: 'Queue Fetch Success',
151
153
  QUEUE_FETCH_FAILED: 'Queue Fetch Failed',
154
+
155
+ // Outdial ANI Entries API Events
156
+ OUTDIAL_ANI_EP_FETCH_SUCCESS: 'Outdial ANI Entries Fetch Success',
157
+ OUTDIAL_ANI_EP_FETCH_FAILED: 'Outdial ANI Entries Fetch Failed',
152
158
  } as const;
153
159
 
154
160
  /**
@@ -270,4 +270,20 @@ export const endPointMap = {
270
270
  */
271
271
  addressBookEntries: (orgId: string, addressBookId: string, queryParams: string) =>
272
272
  `/organization/${orgId}/v2/address-book/${addressBookId}/entry?${queryParams}`,
273
+
274
+ /**
275
+ * Gets the endpoint for outdial ANI entries with custom query parameters.
276
+ * @param orgId - Organization ID.
277
+ * @param outdialANI - Outdial ANI ID.
278
+ * @param queryParams - Query parameters string.
279
+ * @returns The endpoint URL string.
280
+ * @public
281
+ * @example
282
+ * const url = endPointMap.outdialAniEntries('org123', 'ani456', 'page=0&pageSize=10');
283
+ * @ignore
284
+ */
285
+ outdialAniEntries: (orgId: string, outdialANI: string, queryParams: string) =>
286
+ `organization/${orgId}/v2/outdial-ani/${outdialANI}/entry${
287
+ queryParams ? `?${queryParams}` : ''
288
+ }`,
273
289
  };
@@ -9,9 +9,9 @@ import {
9
9
  DesktopProfileResponse,
10
10
  ListAuxCodesResponse,
11
11
  AgentResponse,
12
+ TenantData,
12
13
  OrgInfo,
13
14
  OrgSettings,
14
- TenantData,
15
15
  URLMapping,
16
16
  TeamList,
17
17
  DialPlanEntity,
@@ -20,10 +20,12 @@ import {
20
20
  AuxCode,
21
21
  MultimediaProfileResponse,
22
22
  SiteInfo,
23
+ OutdialAniEntriesResponse,
24
+ OutdialAniParams,
23
25
  } from './types';
24
26
  import WebexRequest from '../core/WebexRequest';
25
27
  import {WCC_API_GATEWAY} from '../constants';
26
- import {CONFIG_FILE_NAME} from '../../constants';
28
+ import {CONFIG_FILE_NAME, METHODS as MAIN_METHODS} from '../../constants';
27
29
  import {parseAgentConfigs} from './Util';
28
30
  import {
29
31
  DEFAULT_AUXCODE_ATTRIBUTES,
@@ -686,4 +688,56 @@ export default class AgentConfigService {
686
688
  }
687
689
 
688
690
  // getQueues removed - use Queue instead
691
+
692
+ /**
693
+ * Fetches outdial ANI (Automatic Number Identification) entries for the given orgId and outdial ANI ID.
694
+ * @ignore
695
+ * @param {string} orgId - organization ID for which the outdial ANI entries are to be fetched.
696
+ * @param {OutdialAniParams} params - parameters object containing outdialANI and optional pagination/filtering options
697
+ * @returns {Promise<OutdialAniEntriesResponse>} - A promise that resolves to the outdial ANI entries response.
698
+ * @throws {Error} - Throws an error if the API call fails or if the response status is not 200.
699
+ * @private
700
+ */
701
+ public async getOutdialAniEntries(
702
+ orgId: string,
703
+ params: OutdialAniParams
704
+ ): Promise<OutdialAniEntriesResponse> {
705
+ const {outdialANI, page, pageSize, search, filter, attributes} = params;
706
+
707
+ LoggerProxy.info('Fetching outdial ANI entries', {
708
+ module: CONFIG_FILE_NAME,
709
+ method: MAIN_METHODS.GET_OUTDIAL_ANI_ENTRIES,
710
+ });
711
+
712
+ try {
713
+ const queryParams = [];
714
+ if (page !== undefined) queryParams.push(`page=${page}`);
715
+ if (pageSize !== undefined) queryParams.push(`pageSize=${pageSize}`);
716
+ if (search) queryParams.push(`search=${search}`);
717
+ if (filter) queryParams.push(`filter=${filter}`);
718
+ if (attributes) queryParams.push(`attributes=${attributes}`);
719
+
720
+ const queryString = queryParams.length > 0 ? queryParams.join('&') : '';
721
+ const resource = endPointMap.outdialAniEntries(orgId, outdialANI, queryString);
722
+
723
+ const response = await this.webexReq.request({
724
+ service: WCC_API_GATEWAY,
725
+ resource,
726
+ method: HTTP_METHODS.GET,
727
+ });
728
+
729
+ LoggerProxy.log('getOutdialAniEntries API success.', {
730
+ module: CONFIG_FILE_NAME,
731
+ method: MAIN_METHODS.GET_OUTDIAL_ANI_ENTRIES,
732
+ });
733
+
734
+ return response.body?.data;
735
+ } catch (error) {
736
+ LoggerProxy.error(`getOutdialAniEntries API call failed with ${error}`, {
737
+ module: CONFIG_FILE_NAME,
738
+ method: MAIN_METHODS.GET_OUTDIAL_ANI_ENTRIES,
739
+ });
740
+ throw error;
741
+ }
742
+ }
689
743
  }
@@ -1072,3 +1072,47 @@ export type CallDistributionGroup = {
1072
1072
  /** Distribution time duration in seconds */
1073
1073
  duration: number;
1074
1074
  };
1075
+
1076
+ /**
1077
+ * Represents a single outdial ANI (Automatic Number Identification) entry
1078
+ * @public
1079
+ */
1080
+ export type OutdialAniEntry = {
1081
+ /** Unique identifier for the ANI entry */
1082
+ id: string;
1083
+ /** Display name for the ANI entry */
1084
+ name: string;
1085
+ /** Phone number associated with this ANI entry */
1086
+ number: string;
1087
+ /** Related links for this ANI entry */
1088
+ links: string[];
1089
+ /** Timestamp when this entry was created (Unix timestamp in milliseconds) */
1090
+ createdTime: number;
1091
+ /** Timestamp when this entry was last updated (Unix timestamp in milliseconds) */
1092
+ lastUpdatedTime: number;
1093
+ };
1094
+
1095
+ /**
1096
+ * Response structure for outdial ANI entries API call
1097
+ * @public
1098
+ */
1099
+ export type OutdialAniEntriesResponse = OutdialAniEntry[];
1100
+
1101
+ /**
1102
+ * Parameters for fetching outdial ANI entries
1103
+ * @public
1104
+ */
1105
+ export type OutdialAniParams = {
1106
+ /** Outdial ANI ID from agent profile */
1107
+ outdialANI: string;
1108
+ /** Page number for pagination (optional) */
1109
+ page?: number;
1110
+ /** Number of entries per page (optional) */
1111
+ pageSize?: number;
1112
+ /** Search string to filter entries (optional) */
1113
+ search?: string;
1114
+ /** Filter expression for advanced filtering (optional) */
1115
+ filter?: string;
1116
+ /** Comma-separated list of attributes to include in response (optional) */
1117
+ attributes?: string;
1118
+ };
@@ -1064,6 +1064,8 @@ export type DialerPayload = {
1064
1064
  mediaType: 'telephony' | 'chat' | 'social' | 'email';
1065
1065
  /** The outbound type for the task */
1066
1066
  outboundType: 'OUTDIAL' | 'CALLBACK' | 'EXECUTE_FLOW';
1067
+ /** The Outdial ANI number that will be used while making a call to the customer. */
1068
+ origin: string;
1067
1069
  };
1068
1070
 
1069
1071
  /**
@@ -1316,7 +1316,7 @@ describe('webex.cc', () => {
1316
1316
  });
1317
1317
 
1318
1318
  describe('startOutdial', () => {
1319
- it('should make outdial call successfully.', async () => {
1319
+ it('should make outdial call successfully without origin.', async () => {
1320
1320
  // Setup outDialEp.
1321
1321
  webex.cc.agentConfig = {
1322
1322
  outDialEp: 'test-entry-point',
@@ -1325,9 +1325,10 @@ describe('webex.cc', () => {
1325
1325
  // destination number required for making outdial call.
1326
1326
  const destination = '1234567890';
1327
1327
 
1328
- // Construct Payload for startOutdial.
1328
+ // Construct Payload for startOutdial without origin.
1329
1329
  const newPayload = {
1330
1330
  destination,
1331
+ origin: undefined,
1331
1332
  entryPointId: 'test-entry-point',
1332
1333
  direction: OUTDIAL_DIRECTION,
1333
1334
  attributes: ATTRIBUTES,
@@ -1357,6 +1358,49 @@ describe('webex.cc', () => {
1357
1358
  expect(result).toEqual(mockResponse);
1358
1359
  });
1359
1360
 
1361
+ it('should make outdial call successfully with origin.', async () => {
1362
+ // Setup outDialEp.
1363
+ webex.cc.agentConfig = {
1364
+ outDialEp: 'test-entry-point',
1365
+ };
1366
+
1367
+ // destination number and origin for making outdial call.
1368
+ const destination = '1234567890';
1369
+ const origin = '+19403016307';
1370
+
1371
+ // Construct Payload for startOutdial with origin.
1372
+ const newPayload = {
1373
+ destination,
1374
+ origin,
1375
+ entryPointId: 'test-entry-point',
1376
+ direction: OUTDIAL_DIRECTION,
1377
+ attributes: ATTRIBUTES,
1378
+ mediaType: OUTDIAL_MEDIA_TYPE,
1379
+ outboundType: OUTBOUND_TYPE,
1380
+ } as const;
1381
+
1382
+ const mockResponse = {} as AgentContact;
1383
+
1384
+ const startOutdialMock = jest
1385
+ .spyOn(webex.cc.services.dialer, 'startOutdial')
1386
+ .mockResolvedValue(mockResponse);
1387
+
1388
+ const result = await webex.cc.startOutdial(destination, origin);
1389
+
1390
+ // Verify logging calls
1391
+ expect(LoggerProxy.info).toHaveBeenCalledWith('Starting outbound dial', {
1392
+ module: CC_FILE,
1393
+ method: 'startOutdial',
1394
+ });
1395
+ expect(LoggerProxy.log).toHaveBeenCalledWith('Outbound dial completed successfully', {
1396
+ module: CC_FILE,
1397
+ method: 'startOutdial',
1398
+ });
1399
+
1400
+ expect(startOutdialMock).toHaveBeenCalledWith({data: newPayload});
1401
+ expect(result).toEqual(mockResponse);
1402
+ });
1403
+
1360
1404
  it('should handle error during startOutdial', async () => {
1361
1405
  // Setup outDialEp.
1362
1406
  webex.cc.agentConfig = {