@webex/contact-center 3.9.0-next.1 → 3.9.0-next.10
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 +104 -62
- package/dist/cc.js.map +1 -1
- package/dist/index.js +9 -0
- 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 +39 -0
- package/dist/metrics/behavioral-events.js.map +1 -1
- package/dist/metrics/constants.js +12 -1
- 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 +24 -2
- package/dist/services/config/constants.js.map +1 -1
- package/dist/services/config/index.js +1 -43
- package/dist/services/config/index.js.map +1 -1
- package/dist/services/config/types.js +0 -5
- package/dist/services/config/types.js.map +1 -1
- package/dist/services/core/GlobalTypes.js.map +1 -1
- package/dist/services/core/Utils.js +121 -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 +1 -0
- package/dist/services/task/TaskManager.js.map +1 -1
- package/dist/services/task/index.js +145 -71
- package/dist/services/task/index.js.map +1 -1
- package/dist/types/cc.d.ts +77 -43
- package/dist/types/index.d.ts +3 -2
- package/dist/types/metrics/constants.d.ts +7 -0
- 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 +23 -1
- package/dist/types/services/config/index.d.ts +1 -14
- package/dist/types/services/config/types.d.ts +0 -64
- package/dist/types/services/core/GlobalTypes.d.ts +25 -0
- package/dist/types/services/core/Utils.d.ts +27 -1
- package/dist/types/services/task/index.d.ts +1 -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 +8 -8
- package/src/cc.ts +120 -80
- package/src/index.ts +16 -2
- package/src/logger-proxy.ts +24 -1
- package/src/metrics/MetricsManager.ts +1 -1
- package/src/metrics/behavioral-events.ts +42 -0
- package/src/metrics/constants.ts +15 -0
- 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 +26 -2
- package/src/services/config/index.ts +1 -55
- package/src/services/config/types.ts +0 -65
- package/src/services/core/GlobalTypes.ts +27 -0
- package/src/services/core/Utils.ts +155 -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 +1 -0
- package/src/services/task/index.ts +172 -56
- package/src/types.ts +180 -0
- package/src/utils/PageCache.ts +252 -0
- package/test/unit/spec/cc.ts +30 -82
- package/test/unit/spec/metrics/MetricsManager.ts +0 -1
- 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 +0 -71
- 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 +8 -1
- package/test/unit/spec/services/task/index.ts +226 -122
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
|
@@ -32,3 +32,30 @@ export type Failure = Msg<{
|
|
|
32
32
|
/** Human-readable description of the failure reason */
|
|
33
33
|
reason: string;
|
|
34
34
|
}>;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Represents task API error details in a structured format
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
40
|
+
export interface TaskError {
|
|
41
|
+
/** Original error object for throwing */
|
|
42
|
+
error: Error;
|
|
43
|
+
/** Unique tracking identifier for correlation */
|
|
44
|
+
trackingId: string;
|
|
45
|
+
/** Detailed error message from the API */
|
|
46
|
+
errorMessage: string;
|
|
47
|
+
/** Type/category of the error (e.g., "Bad Request") */
|
|
48
|
+
errorType: string;
|
|
49
|
+
/** Additional error context data */
|
|
50
|
+
errorData: string;
|
|
51
|
+
/** Numeric reason code */
|
|
52
|
+
reasonCode: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* An Error object augmented with a flexible data field for additional context.
|
|
57
|
+
* Use this to attach structured data to thrown errors without ts-ignore.
|
|
58
|
+
*/
|
|
59
|
+
export interface AugmentedError extends Error {
|
|
60
|
+
data?: Record<string, any>;
|
|
61
|
+
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import * as Err from './Err';
|
|
2
2
|
import {LoginOption, WebexRequestPayload} from '../../types';
|
|
3
|
-
import {Failure} from './GlobalTypes';
|
|
3
|
+
import {Failure, AugmentedError} from './GlobalTypes';
|
|
4
4
|
import LoggerProxy from '../../logger-proxy';
|
|
5
5
|
import WebexRequest from './WebexRequest';
|
|
6
|
+
import {
|
|
7
|
+
TaskData,
|
|
8
|
+
ConsultTransferPayLoad,
|
|
9
|
+
CONSULT_TRANSFER_DESTINATION_TYPE,
|
|
10
|
+
Interaction,
|
|
11
|
+
} from '../task/types';
|
|
6
12
|
|
|
7
13
|
/**
|
|
8
14
|
* Extracts common error details from a Webex request payload.
|
|
@@ -19,6 +25,28 @@ const getCommonErrorDetails = (errObj: WebexRequestPayload) => {
|
|
|
19
25
|
};
|
|
20
26
|
};
|
|
21
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Checks if the destination type represents an entry point variant (EPDN or ENTRYPOINT).
|
|
30
|
+
*/
|
|
31
|
+
const isEntryPointOrEpdn = (destAgentType?: string): boolean => {
|
|
32
|
+
return destAgentType === 'EPDN' || destAgentType === 'ENTRYPOINT';
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Determines if the task involves dialing a number based on the destination type.
|
|
37
|
+
* Returns 'DIAL_NUMBER' for dial-related destinations, empty string otherwise.
|
|
38
|
+
*/
|
|
39
|
+
const getAgentActionTypeFromTask = (taskData?: TaskData): 'DIAL_NUMBER' | '' => {
|
|
40
|
+
const destAgentType = taskData?.destinationType;
|
|
41
|
+
|
|
42
|
+
// Check if destination requires dialing: direct dial number or entry point variants
|
|
43
|
+
const isDialNumber = destAgentType === 'DN';
|
|
44
|
+
const isEntryPointVariant = isEntryPointOrEpdn(destAgentType);
|
|
45
|
+
|
|
46
|
+
// If the destination type is a dial number or an entry point variant, return 'DIAL_NUMBER'
|
|
47
|
+
return isDialNumber || isEntryPointVariant ? 'DIAL_NUMBER' : '';
|
|
48
|
+
};
|
|
49
|
+
|
|
22
50
|
export const isValidDialNumber = (input: string): boolean => {
|
|
23
51
|
// This regex checks for a valid dial number format for only few countries such as US, Canada.
|
|
24
52
|
const regexForDn = /1[0-9]{3}[2-9][0-9]{6}([,]{1,10}[0-9]+){0,1}/;
|
|
@@ -115,6 +143,62 @@ export const getErrorDetails = (error: any, methodName: string, moduleName: stri
|
|
|
115
143
|
};
|
|
116
144
|
};
|
|
117
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Extracts error details from task API errors and logs them. Also uploads logs for the error.
|
|
148
|
+
* This handles the specific error format returned by task API calls.
|
|
149
|
+
*
|
|
150
|
+
* @param error - The error object from task API calls with structure: {id: string, details: {trackingId: string, msg: {...}}}
|
|
151
|
+
* @param methodName - The name of the method where the error occurred.
|
|
152
|
+
* @param moduleName - The name of the module where the error occurred.
|
|
153
|
+
* @returns AugmentedError containing structured error details on err.data for metrics and logging
|
|
154
|
+
* @public
|
|
155
|
+
* @example
|
|
156
|
+
* const taskError = generateTaskErrorObject(error, 'transfer', 'TaskModule');
|
|
157
|
+
* throw taskError.error;
|
|
158
|
+
* @ignore
|
|
159
|
+
*/
|
|
160
|
+
export const generateTaskErrorObject = (
|
|
161
|
+
error: any,
|
|
162
|
+
methodName: string,
|
|
163
|
+
moduleName: string
|
|
164
|
+
): AugmentedError => {
|
|
165
|
+
const trackingId = error?.details?.trackingId || error?.trackingId || '';
|
|
166
|
+
const errorMsg = error?.details?.msg;
|
|
167
|
+
|
|
168
|
+
const fallbackMessage =
|
|
169
|
+
(error && typeof error.message === 'string' && error.message) ||
|
|
170
|
+
`Error while performing ${methodName}`;
|
|
171
|
+
const errorMessage = errorMsg?.errorMessage || fallbackMessage;
|
|
172
|
+
const errorType =
|
|
173
|
+
errorMsg?.errorType ||
|
|
174
|
+
(error && typeof error.name === 'string' && error.name) ||
|
|
175
|
+
'Unknown Error';
|
|
176
|
+
const errorData = errorMsg?.errorData || '';
|
|
177
|
+
const reasonCode = errorMsg?.reasonCode || 0;
|
|
178
|
+
|
|
179
|
+
// Log and upload for Task API formatted errors
|
|
180
|
+
LoggerProxy.error(`${methodName} failed: ${errorMessage} (${errorType})`, {
|
|
181
|
+
module: moduleName,
|
|
182
|
+
method: methodName,
|
|
183
|
+
trackingId,
|
|
184
|
+
});
|
|
185
|
+
WebexRequest.getInstance().uploadLogs({
|
|
186
|
+
correlationId: trackingId,
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
const reason = `${errorType}: ${errorMessage}${errorData ? ` (${errorData})` : ''}`;
|
|
190
|
+
const err: AugmentedError = new Error(reason);
|
|
191
|
+
err.data = {
|
|
192
|
+
message: errorMessage,
|
|
193
|
+
errorType,
|
|
194
|
+
errorData,
|
|
195
|
+
reasonCode,
|
|
196
|
+
trackingId,
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
return err;
|
|
200
|
+
};
|
|
201
|
+
|
|
118
202
|
/**
|
|
119
203
|
* Creates an error details object suitable for use with the Err.Details class.
|
|
120
204
|
*
|
|
@@ -130,3 +214,73 @@ export const createErrDetailsObject = (errObj: WebexRequestPayload) => {
|
|
|
130
214
|
|
|
131
215
|
return new Err.Details('Service.reqs.generic.failure', details);
|
|
132
216
|
};
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Derives the consult transfer destination type based on the provided task data.
|
|
220
|
+
*
|
|
221
|
+
* Logic parity with desktop behavior:
|
|
222
|
+
* - If agent action is dialing a number (DN/EPDN/ENTRYPOINT):
|
|
223
|
+
* - ENTRYPOINT/EPDN map to ENTRYPOINT
|
|
224
|
+
* - DN maps to DIALNUMBER
|
|
225
|
+
* - Otherwise defaults to AGENT
|
|
226
|
+
*
|
|
227
|
+
* @param taskData - The task data used to infer the agent action and destination type
|
|
228
|
+
* @returns The normalized destination type to be used for consult transfer
|
|
229
|
+
*/
|
|
230
|
+
/**
|
|
231
|
+
* Checks if a participant type represents a non-customer participant.
|
|
232
|
+
* Non-customer participants include agents, dial numbers, entry point dial numbers,
|
|
233
|
+
* and entry points.
|
|
234
|
+
*/
|
|
235
|
+
const isNonCustomerParticipant = (participantType: string): boolean => {
|
|
236
|
+
return (
|
|
237
|
+
participantType === 'Agent' ||
|
|
238
|
+
participantType === 'DN' ||
|
|
239
|
+
participantType === 'EpDn' ||
|
|
240
|
+
participantType === 'entryPoint'
|
|
241
|
+
);
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Gets the destination agent ID from participants data by finding the first
|
|
246
|
+
* non-customer participant that is not the current agent and is not in wrap-up state.
|
|
247
|
+
*
|
|
248
|
+
* @param participants - The participants data from the interaction
|
|
249
|
+
* @param agentId - The current agent's ID to exclude from the search
|
|
250
|
+
* @returns The destination agent ID, or empty string if none found
|
|
251
|
+
*/
|
|
252
|
+
export const getDestinationAgentId = (
|
|
253
|
+
participants: Interaction['participants'],
|
|
254
|
+
agentId: string
|
|
255
|
+
): string => {
|
|
256
|
+
let id = '';
|
|
257
|
+
|
|
258
|
+
if (participants) {
|
|
259
|
+
Object.keys(participants).forEach((participant) => {
|
|
260
|
+
const participantData = participants[participant];
|
|
261
|
+
if (
|
|
262
|
+
isNonCustomerParticipant(participantData.type) &&
|
|
263
|
+
participantData.id !== agentId &&
|
|
264
|
+
!participantData.isWrapUp
|
|
265
|
+
) {
|
|
266
|
+
id = participantData.id;
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return id;
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
export const deriveConsultTransferDestinationType = (
|
|
275
|
+
taskData?: TaskData
|
|
276
|
+
): ConsultTransferPayLoad['destinationType'] => {
|
|
277
|
+
const agentActionType = getAgentActionTypeFromTask(taskData);
|
|
278
|
+
|
|
279
|
+
if (agentActionType === 'DIAL_NUMBER') {
|
|
280
|
+
return isEntryPointOrEpdn(taskData?.destinationType)
|
|
281
|
+
? CONSULT_TRANSFER_DESTINATION_TYPE.ENTRYPOINT
|
|
282
|
+
: CONSULT_TRANSFER_DESTINATION_TYPE.DIALNUMBER;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return CONSULT_TRANSFER_DESTINATION_TYPE.AGENT;
|
|
286
|
+
};
|
|
@@ -178,10 +178,6 @@ export class WebSocketManager extends EventEmitter {
|
|
|
178
178
|
issueReason = 'WebSocket auto close timed out. Forcefully closed websocket.';
|
|
179
179
|
} else {
|
|
180
180
|
const onlineStatus = navigator.onLine;
|
|
181
|
-
LoggerProxy.info(`[WebSocketStatus] | desktop online status is ${onlineStatus}`, {
|
|
182
|
-
module: WEB_SOCKET_MANAGER_FILE,
|
|
183
|
-
method: METHODS.WEB_SOCKET_ON_CLOSE_HANDLER,
|
|
184
|
-
});
|
|
185
181
|
issueReason = !onlineStatus
|
|
186
182
|
? 'network issue'
|
|
187
183
|
: 'missing keepalive from either desktop or notif service';
|
|
@@ -270,6 +270,7 @@ export default class TaskManager extends EventEmitter {
|
|
|
270
270
|
break;
|
|
271
271
|
case CC_EVENTS.AGENT_CONSULTING:
|
|
272
272
|
// Received when agent is in an active consult state
|
|
273
|
+
// TODO: Check if we can use backend consult state instead of isConsulted
|
|
273
274
|
task = this.updateTaskData(task, payload.data);
|
|
274
275
|
if (task.data.isConsulted) {
|
|
275
276
|
// Fire only if you are the agent who received the consult request
|