@webex/contact-center 3.8.1 → 3.9.0-multi-llms.1
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 +196 -47
- package/dist/cc.js.map +1 -1
- package/dist/constants.js +1 -0
- package/dist/constants.js.map +1 -1
- package/dist/index.js +13 -1
- package/dist/index.js.map +1 -1
- package/dist/logger-proxy.js +24 -1
- package/dist/logger-proxy.js.map +1 -1
- package/dist/metrics/MetricsManager.js +1 -1
- package/dist/metrics/MetricsManager.js.map +1 -1
- package/dist/metrics/behavioral-events.js +88 -0
- package/dist/metrics/behavioral-events.js.map +1 -1
- package/dist/metrics/constants.js +32 -2
- package/dist/metrics/constants.js.map +1 -1
- package/dist/services/AddressBook.js +271 -0
- package/dist/services/AddressBook.js.map +1 -0
- package/dist/services/EntryPoint.js +227 -0
- package/dist/services/EntryPoint.js.map +1 -0
- package/dist/services/Queue.js +261 -0
- package/dist/services/Queue.js.map +1 -0
- package/dist/services/config/constants.js +36 -2
- package/dist/services/config/constants.js.map +1 -1
- package/dist/services/config/index.js +29 -21
- package/dist/services/config/index.js.map +1 -1
- package/dist/services/config/types.js +33 -1
- package/dist/services/config/types.js.map +1 -1
- package/dist/services/core/GlobalTypes.js.map +1 -1
- package/dist/services/core/Utils.js +162 -2
- package/dist/services/core/Utils.js.map +1 -1
- package/dist/services/core/aqm-reqs.js +0 -4
- package/dist/services/core/aqm-reqs.js.map +1 -1
- package/dist/services/core/websocket/WebSocketManager.js +0 -4
- package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
- package/dist/services/task/TaskManager.js +74 -2
- package/dist/services/task/TaskManager.js.map +1 -1
- package/dist/services/task/constants.js +7 -1
- package/dist/services/task/constants.js.map +1 -1
- package/dist/services/task/contact.js +86 -0
- package/dist/services/task/contact.js.map +1 -1
- package/dist/services/task/index.js +384 -72
- package/dist/services/task/index.js.map +1 -1
- package/dist/services/task/types.js +14 -0
- package/dist/services/task/types.js.map +1 -1
- package/dist/types/cc.d.ts +115 -35
- package/dist/types/constants.d.ts +1 -0
- package/dist/types/index.d.ts +8 -3
- package/dist/types/metrics/constants.d.ts +25 -1
- package/dist/types/services/AddressBook.d.ts +74 -0
- package/dist/types/services/EntryPoint.d.ts +67 -0
- package/dist/types/services/Queue.d.ts +76 -0
- package/dist/types/services/config/constants.d.ts +35 -1
- package/dist/types/services/config/index.d.ts +6 -9
- package/dist/types/services/config/types.d.ts +79 -58
- package/dist/types/services/core/GlobalTypes.d.ts +25 -0
- package/dist/types/services/core/Utils.d.ts +40 -1
- package/dist/types/services/task/constants.d.ts +6 -0
- package/dist/types/services/task/contact.d.ts +10 -0
- package/dist/types/services/task/index.d.ts +44 -2
- package/dist/types/services/task/types.d.ts +125 -1
- package/dist/types/types.d.ts +162 -0
- package/dist/types/utils/PageCache.d.ts +173 -0
- package/dist/types.js +17 -0
- package/dist/types.js.map +1 -1
- package/dist/utils/PageCache.js +192 -0
- package/dist/utils/PageCache.js.map +1 -0
- package/dist/webex.js +1 -1
- package/package.json +11 -10
- package/src/cc.ts +221 -52
- package/src/constants.ts +1 -0
- package/src/index.ts +19 -3
- package/src/logger-proxy.ts +24 -1
- package/src/metrics/MetricsManager.ts +1 -1
- package/src/metrics/behavioral-events.ts +92 -0
- package/src/metrics/constants.ts +37 -1
- package/src/services/AddressBook.ts +291 -0
- package/src/services/EntryPoint.ts +241 -0
- package/src/services/Queue.ts +277 -0
- package/src/services/config/constants.ts +42 -2
- package/src/services/config/index.ts +30 -30
- package/src/services/config/types.ts +59 -58
- package/src/services/core/GlobalTypes.ts +27 -0
- package/src/services/core/Utils.ts +199 -1
- package/src/services/core/aqm-reqs.ts +0 -5
- package/src/services/core/websocket/WebSocketManager.ts +0 -4
- package/src/services/task/TaskManager.ts +79 -3
- package/src/services/task/constants.ts +6 -0
- package/src/services/task/contact.ts +80 -0
- package/src/services/task/index.ts +457 -57
- package/src/services/task/types.ts +135 -0
- package/src/types.ts +180 -0
- package/src/utils/PageCache.ts +252 -0
- package/test/unit/spec/cc.ts +77 -84
- package/test/unit/spec/metrics/MetricsManager.ts +0 -1
- package/test/unit/spec/metrics/behavioral-events.ts +56 -0
- package/test/unit/spec/services/AddressBook.ts +332 -0
- package/test/unit/spec/services/EntryPoint.ts +259 -0
- package/test/unit/spec/services/Queue.ts +323 -0
- package/test/unit/spec/services/config/index.ts +279 -65
- package/test/unit/spec/services/core/Utils.ts +50 -0
- package/test/unit/spec/services/core/aqm-reqs.ts +1 -3
- package/test/unit/spec/services/core/websocket/WebSocketManager.ts +0 -4
- package/test/unit/spec/services/task/TaskManager.ts +145 -1
- package/test/unit/spec/services/task/contact.ts +31 -1
- package/test/unit/spec/services/task/index.ts +410 -123
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import {HTTP_METHODS, WebexSDK} from '../types';
|
|
2
|
+
import type {EntryPointRecord, EntryPointListResponse, EntryPointSearchParams} from '../types';
|
|
3
|
+
import LoggerProxy from '../logger-proxy';
|
|
4
|
+
import WebexRequest from './core/WebexRequest';
|
|
5
|
+
import PageCache, {PAGINATION_DEFAULTS} from '../utils/PageCache';
|
|
6
|
+
import MetricsManager from '../metrics/MetricsManager';
|
|
7
|
+
import {WCC_API_GATEWAY} from './constants';
|
|
8
|
+
import {endPointMap} from './config/constants';
|
|
9
|
+
import {METRIC_EVENT_NAMES} from '../metrics/constants';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* EntryPoint class for managing Webex Contact Center entry points.
|
|
13
|
+
* Provides functionality to fetch, search, and paginate through entry points.
|
|
14
|
+
*
|
|
15
|
+
* @class EntryPoint
|
|
16
|
+
* @public
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* import Webex from 'webex';
|
|
20
|
+
*
|
|
21
|
+
* const webex = new Webex({ credentials: 'YOUR_ACCESS_TOKEN' });
|
|
22
|
+
* const cc = webex.cc;
|
|
23
|
+
*
|
|
24
|
+
* // Register and login first
|
|
25
|
+
* await cc.register();
|
|
26
|
+
* await cc.stationLogin({ teamId: 'team123', loginOption: 'BROWSER' });
|
|
27
|
+
*
|
|
28
|
+
* // Get EntryPoint API instance from ContactCenter
|
|
29
|
+
* const entryPointAPI = cc.entryPoint;
|
|
30
|
+
*
|
|
31
|
+
* // Get all entry points with pagination
|
|
32
|
+
* const response = await entryPointAPI.getEntryPoints({
|
|
33
|
+
* page: 0,
|
|
34
|
+
* pageSize: 50
|
|
35
|
+
* });
|
|
36
|
+
*
|
|
37
|
+
* // Search for specific entry points
|
|
38
|
+
* const searchResults = await entryPointAPI.searchEntryPoints({
|
|
39
|
+
* search: 'support',
|
|
40
|
+
* filter: 'type=="voice"'
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export class EntryPoint {
|
|
45
|
+
private webexRequest: WebexRequest;
|
|
46
|
+
private webex: WebexSDK;
|
|
47
|
+
private metricsManager: MetricsManager;
|
|
48
|
+
|
|
49
|
+
// Page cache using the common utility
|
|
50
|
+
private pageCache: PageCache<EntryPointRecord>;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Creates an instance of EntryPoint
|
|
54
|
+
* @param {WebexSDK} webex - The Webex SDK instance
|
|
55
|
+
* @public
|
|
56
|
+
*/
|
|
57
|
+
constructor(webex: WebexSDK) {
|
|
58
|
+
this.webex = webex;
|
|
59
|
+
this.webexRequest = WebexRequest.getInstance({webex});
|
|
60
|
+
this.pageCache = new PageCache<EntryPointRecord>('EntryPoint');
|
|
61
|
+
this.metricsManager = MetricsManager.getInstance({webex});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Fetches entry points for the organization with pagination support
|
|
66
|
+
* @param {EntryPointSearchParams} [params] - Search and pagination parameters
|
|
67
|
+
* @returns {Promise<EntryPointListResponse>} Promise resolving to paginated entry points
|
|
68
|
+
* @throws {Error} If the API call fails
|
|
69
|
+
* @public
|
|
70
|
+
* @example
|
|
71
|
+
* ```typescript
|
|
72
|
+
* // Get first page of entry points
|
|
73
|
+
* const response = await entryPointAPI.getEntryPoints();
|
|
74
|
+
*
|
|
75
|
+
* // Get specific page with custom page size
|
|
76
|
+
* const response = await entryPointAPI.getEntryPoints({
|
|
77
|
+
* page: 2,
|
|
78
|
+
* pageSize: 25
|
|
79
|
+
* });
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
public async getEntryPoints(
|
|
83
|
+
params: EntryPointSearchParams = {}
|
|
84
|
+
): Promise<EntryPointListResponse> {
|
|
85
|
+
const startTime = Date.now();
|
|
86
|
+
const {
|
|
87
|
+
page = PAGINATION_DEFAULTS.PAGE,
|
|
88
|
+
pageSize = PAGINATION_DEFAULTS.PAGE_SIZE,
|
|
89
|
+
search,
|
|
90
|
+
filter,
|
|
91
|
+
attributes,
|
|
92
|
+
sortBy,
|
|
93
|
+
sortOrder = 'asc',
|
|
94
|
+
} = params;
|
|
95
|
+
|
|
96
|
+
const orgId = this.webex.credentials.getOrgId();
|
|
97
|
+
const isSearchRequest = !!(search || filter || attributes || sortBy);
|
|
98
|
+
|
|
99
|
+
LoggerProxy.info(
|
|
100
|
+
`Fetching entry points - orgId: ${orgId}, page: ${page}, pageSize: ${pageSize}, isSearchRequest: ${isSearchRequest}`,
|
|
101
|
+
{
|
|
102
|
+
module: 'EntryPoint',
|
|
103
|
+
method: 'getEntryPoints',
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
// Check if we can use cache for simple pagination (no search/filter/attributes/sort)
|
|
108
|
+
if (this.pageCache.canUseCache({search, filter, attributes, sortBy})) {
|
|
109
|
+
const cacheKey = this.pageCache.buildCacheKey(orgId, page, pageSize);
|
|
110
|
+
const cachedPage = this.pageCache.getCachedPage(cacheKey);
|
|
111
|
+
|
|
112
|
+
if (cachedPage) {
|
|
113
|
+
const duration = Date.now() - startTime;
|
|
114
|
+
|
|
115
|
+
LoggerProxy.log(
|
|
116
|
+
`Returning page ${page} from cache - cacheHit: true, duration: ${duration}ms, recordCount: ${cachedPage.data.length}, pageSize: ${pageSize}`,
|
|
117
|
+
{
|
|
118
|
+
module: 'EntryPoint',
|
|
119
|
+
method: 'getEntryPoints',
|
|
120
|
+
}
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
data: cachedPage.data,
|
|
125
|
+
meta: {
|
|
126
|
+
page,
|
|
127
|
+
pageSize,
|
|
128
|
+
totalPages: cachedPage.totalMeta?.totalPages,
|
|
129
|
+
totalRecords: cachedPage.totalMeta?.totalRecords,
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Start timing only for actual API calls (not cache hits)
|
|
136
|
+
this.metricsManager.timeEvent(METRIC_EVENT_NAMES.ENTRYPOINT_FETCH_SUCCESS);
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
// Build query parameters
|
|
140
|
+
const queryParams = new URLSearchParams({
|
|
141
|
+
page: page.toString(),
|
|
142
|
+
pageSize: pageSize.toString(),
|
|
143
|
+
sortOrder,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
if (search) queryParams.append('search', search);
|
|
147
|
+
if (filter) queryParams.append('filter', filter);
|
|
148
|
+
if (attributes) queryParams.append('attributes', attributes);
|
|
149
|
+
if (sortBy) queryParams.append('sortBy', sortBy);
|
|
150
|
+
|
|
151
|
+
const resource = endPointMap.entryPointList(orgId, queryParams.toString());
|
|
152
|
+
|
|
153
|
+
LoggerProxy.log(
|
|
154
|
+
`Making API request to fetch entry points - resource: ${resource}, service: ${WCC_API_GATEWAY}`,
|
|
155
|
+
{
|
|
156
|
+
module: 'EntryPoint',
|
|
157
|
+
method: 'getEntryPoints',
|
|
158
|
+
}
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
const response = await this.webexRequest.request({
|
|
162
|
+
service: WCC_API_GATEWAY,
|
|
163
|
+
resource,
|
|
164
|
+
method: HTTP_METHODS.GET,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const duration = Date.now() - startTime;
|
|
168
|
+
|
|
169
|
+
const recordCount = response.body?.data?.length || 0;
|
|
170
|
+
const totalRecords = response.body?.meta?.totalRecords;
|
|
171
|
+
|
|
172
|
+
LoggerProxy.log(`Successfully retrieved ${recordCount} entry points`, {
|
|
173
|
+
module: 'EntryPoint',
|
|
174
|
+
method: 'getEntryPoints',
|
|
175
|
+
data: {
|
|
176
|
+
statusCode: response.statusCode,
|
|
177
|
+
duration,
|
|
178
|
+
recordCount,
|
|
179
|
+
totalRecords,
|
|
180
|
+
isSearchRequest,
|
|
181
|
+
page,
|
|
182
|
+
pageSize,
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// Only track metrics for search requests or first page loads to reduce metric volume
|
|
187
|
+
if (isSearchRequest || page === 0) {
|
|
188
|
+
this.metricsManager.trackEvent(
|
|
189
|
+
METRIC_EVENT_NAMES.ENTRYPOINT_FETCH_SUCCESS,
|
|
190
|
+
{
|
|
191
|
+
orgId,
|
|
192
|
+
statusCode: response.statusCode,
|
|
193
|
+
recordCount,
|
|
194
|
+
totalRecords,
|
|
195
|
+
isSearchRequest,
|
|
196
|
+
isFirstPage: page === 0,
|
|
197
|
+
},
|
|
198
|
+
['behavioral']
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Cache the page data for simple pagination (no search/filter/attributes/sort)
|
|
203
|
+
if (this.pageCache.canUseCache({search, filter, attributes, sortBy}) && response.body?.data) {
|
|
204
|
+
const cacheKey = this.pageCache.buildCacheKey(orgId, page, pageSize);
|
|
205
|
+
this.pageCache.cachePage(cacheKey, response.body.data, response.body.meta);
|
|
206
|
+
|
|
207
|
+
LoggerProxy.log('Cached entry points data for future requests', {
|
|
208
|
+
module: 'EntryPoint',
|
|
209
|
+
method: 'getEntryPoints',
|
|
210
|
+
data: {cacheKey, recordCount},
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return response.body;
|
|
215
|
+
} catch (error) {
|
|
216
|
+
const errorData = {
|
|
217
|
+
orgId,
|
|
218
|
+
error: error instanceof Error ? error.message : String(error),
|
|
219
|
+
isSearchRequest,
|
|
220
|
+
page,
|
|
221
|
+
pageSize,
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
LoggerProxy.error(`Failed to fetch entry points`, {
|
|
225
|
+
module: 'EntryPoint',
|
|
226
|
+
method: 'getEntryPoints',
|
|
227
|
+
data: errorData,
|
|
228
|
+
error,
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// Track all failures for troubleshooting
|
|
232
|
+
this.metricsManager.trackEvent(METRIC_EVENT_NAMES.ENTRYPOINT_FETCH_FAILED, errorData, [
|
|
233
|
+
'behavioral',
|
|
234
|
+
]);
|
|
235
|
+
|
|
236
|
+
throw error;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export default EntryPoint;
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import {HTTP_METHODS, WebexSDK} from '../types';
|
|
2
|
+
import type {
|
|
3
|
+
ContactServiceQueue,
|
|
4
|
+
ContactServiceQueuesResponse,
|
|
5
|
+
ContactServiceQueueSearchParams,
|
|
6
|
+
} from '../types';
|
|
7
|
+
import LoggerProxy from '../logger-proxy';
|
|
8
|
+
import WebexRequest from './core/WebexRequest';
|
|
9
|
+
import PageCache, {PAGINATION_DEFAULTS} from '../utils/PageCache';
|
|
10
|
+
import MetricsManager from '../metrics/MetricsManager';
|
|
11
|
+
import {WCC_API_GATEWAY} from './constants';
|
|
12
|
+
import {endPointMap} from './config/constants';
|
|
13
|
+
import {METRIC_EVENT_NAMES} from '../metrics/constants';
|
|
14
|
+
import {METHODS} from '../constants';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Queue API class for managing Webex Contact Center contact service queues.
|
|
18
|
+
* Provides functionality to fetch contact service queues using the queue API.
|
|
19
|
+
*
|
|
20
|
+
* @class Queue
|
|
21
|
+
* @public
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* import Webex from 'webex';
|
|
25
|
+
*
|
|
26
|
+
* const webex = new Webex({ credentials: 'YOUR_ACCESS_TOKEN' });
|
|
27
|
+
* const cc = webex.cc;
|
|
28
|
+
*
|
|
29
|
+
* // Register and login first
|
|
30
|
+
* await cc.register();
|
|
31
|
+
* await cc.stationLogin({ teamId: 'team123', loginOption: 'BROWSER' });
|
|
32
|
+
*
|
|
33
|
+
* // Get Queue API instance from ContactCenter
|
|
34
|
+
* const queueAPI = cc.queue;
|
|
35
|
+
*
|
|
36
|
+
* // Get all queues
|
|
37
|
+
* const queues = await queueAPI.getQueues();
|
|
38
|
+
*
|
|
39
|
+
* // Get queues with pagination
|
|
40
|
+
* const queues = await queueAPI.getQueues({
|
|
41
|
+
* page: 0,
|
|
42
|
+
* pageSize: 50
|
|
43
|
+
* });
|
|
44
|
+
*
|
|
45
|
+
* // Search for specific queues
|
|
46
|
+
* const searchResults = await queueAPI.getQueues({
|
|
47
|
+
* search: 'support',
|
|
48
|
+
* filter: 'name=="Support Queue"'
|
|
49
|
+
* });
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export class Queue {
|
|
53
|
+
private webexRequest: WebexRequest;
|
|
54
|
+
private webex: WebexSDK;
|
|
55
|
+
private metricsManager: MetricsManager;
|
|
56
|
+
|
|
57
|
+
// Page cache using the common utility
|
|
58
|
+
private pageCache: PageCache<ContactServiceQueue>;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Creates an instance of Queue
|
|
62
|
+
* @param {WebexSDK} webex - The Webex SDK instance
|
|
63
|
+
* @public
|
|
64
|
+
*/
|
|
65
|
+
constructor(webex: WebexSDK) {
|
|
66
|
+
this.webex = webex;
|
|
67
|
+
this.webexRequest = WebexRequest.getInstance({webex});
|
|
68
|
+
this.pageCache = new PageCache<ContactServiceQueue>('Queue');
|
|
69
|
+
this.metricsManager = MetricsManager.getInstance({webex});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Fetches contact service queues for the organization
|
|
74
|
+
* @param {ContactServiceQueueSearchParams} [params] - Search and pagination parameters
|
|
75
|
+
* @returns {Promise<ContactServiceQueuesResponse>} Promise resolving to contact service queues
|
|
76
|
+
* @throws {Error} If the API call fails
|
|
77
|
+
* @public
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* // Get all queues with default pagination
|
|
81
|
+
* const response = await queueAPI.getQueues();
|
|
82
|
+
*
|
|
83
|
+
* // Get queues with specific pagination
|
|
84
|
+
* const response = await queueAPI.getQueues({
|
|
85
|
+
* page: 0,
|
|
86
|
+
* pageSize: 25
|
|
87
|
+
* });
|
|
88
|
+
*
|
|
89
|
+
* // Search for queues
|
|
90
|
+
* const response = await queueAPI.getQueues({
|
|
91
|
+
* search: 'support',
|
|
92
|
+
* filter: 'queueType=="INBOUND"'
|
|
93
|
+
* });
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
public async getQueues(
|
|
97
|
+
params: ContactServiceQueueSearchParams = {}
|
|
98
|
+
): Promise<ContactServiceQueuesResponse> {
|
|
99
|
+
const startTime = Date.now();
|
|
100
|
+
const {
|
|
101
|
+
page = PAGINATION_DEFAULTS.PAGE,
|
|
102
|
+
pageSize = PAGINATION_DEFAULTS.PAGE_SIZE,
|
|
103
|
+
search,
|
|
104
|
+
filter,
|
|
105
|
+
attributes,
|
|
106
|
+
sortBy,
|
|
107
|
+
sortOrder,
|
|
108
|
+
desktopProfileFilter,
|
|
109
|
+
provisioningView,
|
|
110
|
+
singleObjectResponse,
|
|
111
|
+
} = params;
|
|
112
|
+
|
|
113
|
+
const orgId = this.webex.credentials.getOrgId();
|
|
114
|
+
const isSearchRequest = !!(search || filter || attributes || sortBy);
|
|
115
|
+
|
|
116
|
+
LoggerProxy.info('Fetching contact service queues', {
|
|
117
|
+
module: 'Queue',
|
|
118
|
+
method: METHODS.GET_QUEUES,
|
|
119
|
+
data: {
|
|
120
|
+
orgId,
|
|
121
|
+
page,
|
|
122
|
+
pageSize,
|
|
123
|
+
isSearchRequest,
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// Check if we can use cache for simple pagination (no search/filter/attributes/sort)
|
|
128
|
+
if (this.pageCache.canUseCache({search, filter, attributes, sortBy})) {
|
|
129
|
+
const cacheKey = this.pageCache.buildCacheKey(orgId, page, pageSize);
|
|
130
|
+
const cachedPage = this.pageCache.getCachedPage(cacheKey);
|
|
131
|
+
|
|
132
|
+
if (cachedPage) {
|
|
133
|
+
const duration = Date.now() - startTime;
|
|
134
|
+
|
|
135
|
+
LoggerProxy.log(`Returning page ${page} from cache`, {
|
|
136
|
+
module: 'Queue',
|
|
137
|
+
method: 'getQueues',
|
|
138
|
+
data: {
|
|
139
|
+
cacheHit: true,
|
|
140
|
+
duration,
|
|
141
|
+
recordCount: cachedPage.data.length,
|
|
142
|
+
page,
|
|
143
|
+
pageSize,
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
data: cachedPage.data,
|
|
149
|
+
meta: {
|
|
150
|
+
page,
|
|
151
|
+
pageSize,
|
|
152
|
+
totalPages: cachedPage.totalMeta?.totalPages,
|
|
153
|
+
totalRecords: cachedPage.totalMeta?.totalRecords,
|
|
154
|
+
orgid: orgId,
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Start timing only for actual API calls (not cache hits)
|
|
161
|
+
this.metricsManager.timeEvent(METRIC_EVENT_NAMES.QUEUE_FETCH_SUCCESS);
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
// Build query parameters according to spec
|
|
165
|
+
const queryParams = new URLSearchParams({
|
|
166
|
+
page: page.toString(),
|
|
167
|
+
pageSize: pageSize.toString(),
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
if (filter) queryParams.append('filter', filter);
|
|
171
|
+
if (attributes) queryParams.append('attributes', attributes);
|
|
172
|
+
if (search) queryParams.append('search', search);
|
|
173
|
+
if (sortBy) queryParams.append('sortBy', sortBy);
|
|
174
|
+
if (sortOrder) queryParams.append('sortOrder', sortOrder);
|
|
175
|
+
if (desktopProfileFilter !== undefined)
|
|
176
|
+
queryParams.append('desktopProfileFilter', desktopProfileFilter.toString());
|
|
177
|
+
if (provisioningView !== undefined)
|
|
178
|
+
queryParams.append('provisioningView', provisioningView.toString());
|
|
179
|
+
if (singleObjectResponse !== undefined)
|
|
180
|
+
queryParams.append('singleObjectResponse', singleObjectResponse.toString());
|
|
181
|
+
|
|
182
|
+
const resource = endPointMap.queueList(orgId, queryParams.toString());
|
|
183
|
+
|
|
184
|
+
LoggerProxy.log('Making API request to fetch contact service queues', {
|
|
185
|
+
module: 'Queue',
|
|
186
|
+
method: METHODS.GET_QUEUES,
|
|
187
|
+
data: {
|
|
188
|
+
resource,
|
|
189
|
+
service: WCC_API_GATEWAY,
|
|
190
|
+
},
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
const response = await this.webexRequest.request({
|
|
194
|
+
service: WCC_API_GATEWAY,
|
|
195
|
+
resource,
|
|
196
|
+
method: HTTP_METHODS.GET,
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
const duration = Date.now() - startTime;
|
|
200
|
+
|
|
201
|
+
const recordCount = response.body?.data?.length || 0;
|
|
202
|
+
const totalRecords = response.body?.meta?.totalRecords;
|
|
203
|
+
|
|
204
|
+
LoggerProxy.log(`Successfully retrieved ${recordCount} contact service queues`, {
|
|
205
|
+
module: 'Queue',
|
|
206
|
+
method: METHODS.GET_QUEUES,
|
|
207
|
+
data: {
|
|
208
|
+
statusCode: response.statusCode,
|
|
209
|
+
duration,
|
|
210
|
+
recordCount,
|
|
211
|
+
totalRecords,
|
|
212
|
+
isSearchRequest,
|
|
213
|
+
page,
|
|
214
|
+
pageSize,
|
|
215
|
+
},
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
// Only track metrics for search requests or first page loads to reduce metric volume
|
|
219
|
+
if (isSearchRequest || page === 0) {
|
|
220
|
+
this.metricsManager.trackEvent(
|
|
221
|
+
METRIC_EVENT_NAMES.QUEUE_FETCH_SUCCESS,
|
|
222
|
+
{
|
|
223
|
+
orgId,
|
|
224
|
+
statusCode: response.statusCode,
|
|
225
|
+
recordCount,
|
|
226
|
+
totalRecords,
|
|
227
|
+
isSearchRequest,
|
|
228
|
+
isFirstPage: page === 0,
|
|
229
|
+
},
|
|
230
|
+
['behavioral', 'operational']
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Cache the page data for simple pagination (no search/filter/attributes/sort)
|
|
235
|
+
if (this.pageCache.canUseCache({search, filter, attributes, sortBy}) && response.body?.data) {
|
|
236
|
+
const cacheKey = this.pageCache.buildCacheKey(orgId, page, pageSize);
|
|
237
|
+
this.pageCache.cachePage(cacheKey, response.body.data, response.body.meta);
|
|
238
|
+
|
|
239
|
+
LoggerProxy.log('Cached contact service queues for future requests', {
|
|
240
|
+
module: 'Queue',
|
|
241
|
+
method: METHODS.GET_QUEUES,
|
|
242
|
+
data: {
|
|
243
|
+
cacheKey,
|
|
244
|
+
recordCount,
|
|
245
|
+
},
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return response.body;
|
|
250
|
+
} catch (error) {
|
|
251
|
+
const errorData = {
|
|
252
|
+
orgId,
|
|
253
|
+
error: error instanceof Error ? error.message : String(error),
|
|
254
|
+
isSearchRequest,
|
|
255
|
+
page,
|
|
256
|
+
pageSize,
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
LoggerProxy.error('Failed to fetch contact service queues', {
|
|
260
|
+
module: 'Queue',
|
|
261
|
+
method: METHODS.GET_QUEUES,
|
|
262
|
+
data: errorData,
|
|
263
|
+
error,
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
// Track all failures for troubleshooting
|
|
267
|
+
this.metricsManager.trackEvent(METRIC_EVENT_NAMES.QUEUE_FETCH_FAILED, errorData, [
|
|
268
|
+
'behavioral',
|
|
269
|
+
'operational',
|
|
270
|
+
]);
|
|
271
|
+
|
|
272
|
+
throw error;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export default Queue;
|
|
@@ -67,7 +67,6 @@ export const METHODS = {
|
|
|
67
67
|
GET_TENANT_DATA: 'getTenantData',
|
|
68
68
|
GET_URL_MAPPING: 'getURLMapping',
|
|
69
69
|
GET_DIAL_PLAN_DATA: 'getDialPlanData',
|
|
70
|
-
GET_QUEUES: 'getQueues',
|
|
71
70
|
|
|
72
71
|
// Util methods
|
|
73
72
|
PARSE_AGENT_CONFIGS: 'parseAgentConfigs',
|
|
@@ -245,5 +244,46 @@ export const endPointMap = {
|
|
|
245
244
|
* @ignore
|
|
246
245
|
*/
|
|
247
246
|
queueList: (orgId: string, queryParams: string) =>
|
|
248
|
-
|
|
247
|
+
`/organization/${orgId}/v2/contact-service-queue?${queryParams}`,
|
|
248
|
+
/**
|
|
249
|
+
* Gets the endpoint for entry points list with custom query parameters.
|
|
250
|
+
* @param orgId - Organization ID.
|
|
251
|
+
* @param queryParams - Query parameters string.
|
|
252
|
+
* @returns The endpoint URL string.
|
|
253
|
+
* @public
|
|
254
|
+
* @example
|
|
255
|
+
* const url = endPointMap.entryPointList('org123', 'page=0&pageSize=10');
|
|
256
|
+
* @ignore
|
|
257
|
+
*/
|
|
258
|
+
entryPointList: (orgId: string, queryParams: string) =>
|
|
259
|
+
`/organization/${orgId}/v2/entry-point?${queryParams}`,
|
|
260
|
+
/**
|
|
261
|
+
* Gets the endpoint for address book entries with custom query parameters.
|
|
262
|
+
* @param orgId - Organization ID.
|
|
263
|
+
* @param addressBookId - Address book ID.
|
|
264
|
+
* @param queryParams - Query parameters string.
|
|
265
|
+
* @returns The endpoint URL string.
|
|
266
|
+
* @public
|
|
267
|
+
* @example
|
|
268
|
+
* const url = endPointMap.addressBookEntries('org123', 'book456', 'page=0&pageSize=10');
|
|
269
|
+
* @ignore
|
|
270
|
+
*/
|
|
271
|
+
addressBookEntries: (orgId: string, addressBookId: string, queryParams: string) =>
|
|
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
|
+
}`,
|
|
249
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,11 +20,12 @@ import {
|
|
|
20
20
|
AuxCode,
|
|
21
21
|
MultimediaProfileResponse,
|
|
22
22
|
SiteInfo,
|
|
23
|
-
|
|
23
|
+
OutdialAniEntriesResponse,
|
|
24
|
+
OutdialAniParams,
|
|
24
25
|
} from './types';
|
|
25
26
|
import WebexRequest from '../core/WebexRequest';
|
|
26
27
|
import {WCC_API_GATEWAY} from '../constants';
|
|
27
|
-
import {CONFIG_FILE_NAME} from '../../constants';
|
|
28
|
+
import {CONFIG_FILE_NAME, METHODS as MAIN_METHODS} from '../../constants';
|
|
28
29
|
import {parseAgentConfigs} from './Util';
|
|
29
30
|
import {
|
|
30
31
|
DEFAULT_AUXCODE_ATTRIBUTES,
|
|
@@ -686,56 +687,55 @@ export default class AgentConfigService {
|
|
|
686
687
|
}
|
|
687
688
|
}
|
|
688
689
|
|
|
690
|
+
// getQueues removed - use Queue instead
|
|
691
|
+
|
|
689
692
|
/**
|
|
690
|
-
* Fetches
|
|
693
|
+
* Fetches outdial ANI (Automatic Number Identification) entries for the given orgId and outdial ANI ID.
|
|
691
694
|
* @ignore
|
|
692
|
-
* @param {string} orgId - organization ID for which the
|
|
693
|
-
* @param {
|
|
694
|
-
* @
|
|
695
|
-
* @param {string} search - optional search string
|
|
696
|
-
* @param {string} filter - optional filter string
|
|
697
|
-
* @returns Promise<ContactServiceQueue[]> - A promise that resolves to the list of contact service queues.
|
|
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
698
|
* @throws {Error} - Throws an error if the API call fails or if the response status is not 200.
|
|
699
699
|
* @private
|
|
700
700
|
*/
|
|
701
|
-
public async
|
|
701
|
+
public async getOutdialAniEntries(
|
|
702
702
|
orgId: string,
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
search
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
LoggerProxy.info('Fetching queue list', {
|
|
703
|
+
params: OutdialAniParams
|
|
704
|
+
): Promise<OutdialAniEntriesResponse> {
|
|
705
|
+
const {outdialANI, page, pageSize, search, filter, attributes} = params;
|
|
706
|
+
|
|
707
|
+
LoggerProxy.info('Fetching outdial ANI entries', {
|
|
709
708
|
module: CONFIG_FILE_NAME,
|
|
710
|
-
method:
|
|
709
|
+
method: MAIN_METHODS.GET_OUTDIAL_ANI_ENTRIES,
|
|
711
710
|
});
|
|
712
711
|
|
|
713
712
|
try {
|
|
714
|
-
|
|
715
|
-
if (
|
|
716
|
-
if (
|
|
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);
|
|
717
722
|
|
|
718
|
-
const resource = endPointMap.queueList(orgId, queryParams);
|
|
719
723
|
const response = await this.webexReq.request({
|
|
720
724
|
service: WCC_API_GATEWAY,
|
|
721
725
|
resource,
|
|
722
726
|
method: HTTP_METHODS.GET,
|
|
723
727
|
});
|
|
724
728
|
|
|
725
|
-
|
|
726
|
-
throw new Error(`API call failed with ${response.statusCode}`);
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
LoggerProxy.log('getQueues API success.', {
|
|
729
|
+
LoggerProxy.log('getOutdialAniEntries API success.', {
|
|
730
730
|
module: CONFIG_FILE_NAME,
|
|
731
|
-
method:
|
|
731
|
+
method: MAIN_METHODS.GET_OUTDIAL_ANI_ENTRIES,
|
|
732
732
|
});
|
|
733
733
|
|
|
734
734
|
return response.body?.data;
|
|
735
735
|
} catch (error) {
|
|
736
|
-
LoggerProxy.error(`
|
|
736
|
+
LoggerProxy.error(`getOutdialAniEntries API call failed with ${error}`, {
|
|
737
737
|
module: CONFIG_FILE_NAME,
|
|
738
|
-
method:
|
|
738
|
+
method: MAIN_METHODS.GET_OUTDIAL_ANI_ENTRIES,
|
|
739
739
|
});
|
|
740
740
|
throw error;
|
|
741
741
|
}
|