@webex/contact-center 3.8.1 → 3.9.0-multipleLLM.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.
Files changed (102) hide show
  1. package/dist/cc.js +106 -63
  2. package/dist/cc.js.map +1 -1
  3. package/dist/index.js +13 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/logger-proxy.js +24 -1
  6. package/dist/logger-proxy.js.map +1 -1
  7. package/dist/metrics/MetricsManager.js +1 -1
  8. package/dist/metrics/MetricsManager.js.map +1 -1
  9. package/dist/metrics/behavioral-events.js +88 -0
  10. package/dist/metrics/behavioral-events.js.map +1 -1
  11. package/dist/metrics/constants.js +26 -1
  12. package/dist/metrics/constants.js.map +1 -1
  13. package/dist/services/AddressBook.js +271 -0
  14. package/dist/services/AddressBook.js.map +1 -0
  15. package/dist/services/EntryPoint.js +227 -0
  16. package/dist/services/EntryPoint.js.map +1 -0
  17. package/dist/services/Queue.js +261 -0
  18. package/dist/services/Queue.js.map +1 -0
  19. package/dist/services/config/constants.js +24 -2
  20. package/dist/services/config/constants.js.map +1 -1
  21. package/dist/services/config/index.js +1 -43
  22. package/dist/services/config/index.js.map +1 -1
  23. package/dist/services/config/types.js +22 -5
  24. package/dist/services/config/types.js.map +1 -1
  25. package/dist/services/core/GlobalTypes.js.map +1 -1
  26. package/dist/services/core/Utils.js +162 -2
  27. package/dist/services/core/Utils.js.map +1 -1
  28. package/dist/services/core/aqm-reqs.js +0 -4
  29. package/dist/services/core/aqm-reqs.js.map +1 -1
  30. package/dist/services/core/websocket/WebSocketManager.js +0 -4
  31. package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
  32. package/dist/services/task/TaskManager.js +74 -2
  33. package/dist/services/task/TaskManager.js.map +1 -1
  34. package/dist/services/task/constants.js +7 -1
  35. package/dist/services/task/constants.js.map +1 -1
  36. package/dist/services/task/contact.js +86 -0
  37. package/dist/services/task/contact.js.map +1 -1
  38. package/dist/services/task/index.js +384 -72
  39. package/dist/services/task/index.js.map +1 -1
  40. package/dist/services/task/types.js +14 -0
  41. package/dist/services/task/types.js.map +1 -1
  42. package/dist/types/cc.d.ts +77 -43
  43. package/dist/types/index.d.ts +8 -3
  44. package/dist/types/metrics/constants.d.ts +20 -0
  45. package/dist/types/services/AddressBook.d.ts +74 -0
  46. package/dist/types/services/EntryPoint.d.ts +67 -0
  47. package/dist/types/services/Queue.d.ts +76 -0
  48. package/dist/types/services/config/constants.d.ts +23 -1
  49. package/dist/types/services/config/index.d.ts +1 -14
  50. package/dist/types/services/config/types.d.ts +44 -64
  51. package/dist/types/services/core/GlobalTypes.d.ts +25 -0
  52. package/dist/types/services/core/Utils.d.ts +40 -1
  53. package/dist/types/services/task/constants.d.ts +6 -0
  54. package/dist/types/services/task/contact.d.ts +10 -0
  55. package/dist/types/services/task/index.d.ts +44 -2
  56. package/dist/types/services/task/types.d.ts +123 -1
  57. package/dist/types/types.d.ts +162 -0
  58. package/dist/types/utils/PageCache.d.ts +173 -0
  59. package/dist/types.js +17 -0
  60. package/dist/types.js.map +1 -1
  61. package/dist/utils/PageCache.js +192 -0
  62. package/dist/utils/PageCache.js.map +1 -0
  63. package/dist/webex.js +1 -1
  64. package/package.json +10 -10
  65. package/src/cc.ts +122 -81
  66. package/src/index.ts +19 -3
  67. package/src/logger-proxy.ts +24 -1
  68. package/src/metrics/MetricsManager.ts +1 -1
  69. package/src/metrics/behavioral-events.ts +92 -0
  70. package/src/metrics/constants.ts +30 -0
  71. package/src/services/AddressBook.ts +291 -0
  72. package/src/services/EntryPoint.ts +241 -0
  73. package/src/services/Queue.ts +277 -0
  74. package/src/services/config/constants.ts +26 -2
  75. package/src/services/config/index.ts +1 -55
  76. package/src/services/config/types.ts +22 -65
  77. package/src/services/core/GlobalTypes.ts +27 -0
  78. package/src/services/core/Utils.ts +199 -1
  79. package/src/services/core/aqm-reqs.ts +0 -5
  80. package/src/services/core/websocket/WebSocketManager.ts +0 -4
  81. package/src/services/task/TaskManager.ts +79 -3
  82. package/src/services/task/constants.ts +6 -0
  83. package/src/services/task/contact.ts +80 -0
  84. package/src/services/task/index.ts +457 -57
  85. package/src/services/task/types.ts +133 -0
  86. package/src/types.ts +180 -0
  87. package/src/utils/PageCache.ts +252 -0
  88. package/test/unit/spec/cc.ts +31 -82
  89. package/test/unit/spec/metrics/MetricsManager.ts +0 -1
  90. package/test/unit/spec/metrics/behavioral-events.ts +56 -0
  91. package/test/unit/spec/services/AddressBook.ts +332 -0
  92. package/test/unit/spec/services/EntryPoint.ts +259 -0
  93. package/test/unit/spec/services/Queue.ts +323 -0
  94. package/test/unit/spec/services/config/index.ts +0 -71
  95. package/test/unit/spec/services/core/Utils.ts +50 -0
  96. package/test/unit/spec/services/core/aqm-reqs.ts +1 -3
  97. package/test/unit/spec/services/core/websocket/WebSocketManager.ts +0 -4
  98. package/test/unit/spec/services/task/TaskManager.ts +145 -1
  99. package/test/unit/spec/services/task/contact.ts +31 -1
  100. package/test/unit/spec/services/task/index.ts +410 -123
  101. package/umd/contact-center.min.js +2 -2
  102. package/umd/contact-center.min.js.map +1 -1
@@ -1,8 +1,16 @@
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
+ ConsultConferenceData,
10
+ consultConferencePayloadData,
11
+ CONSULT_TRANSFER_DESTINATION_TYPE,
12
+ Interaction,
13
+ } from '../task/types';
6
14
 
7
15
  /**
8
16
  * Extracts common error details from a Webex request payload.
@@ -19,6 +27,28 @@ const getCommonErrorDetails = (errObj: WebexRequestPayload) => {
19
27
  };
20
28
  };
21
29
 
30
+ /**
31
+ * Checks if the destination type represents an entry point variant (EPDN or ENTRYPOINT).
32
+ */
33
+ const isEntryPointOrEpdn = (destAgentType?: string): boolean => {
34
+ return destAgentType === 'EPDN' || destAgentType === 'ENTRYPOINT';
35
+ };
36
+
37
+ /**
38
+ * Determines if the task involves dialing a number based on the destination type.
39
+ * Returns 'DIAL_NUMBER' for dial-related destinations, empty string otherwise.
40
+ */
41
+ const getAgentActionTypeFromTask = (taskData?: TaskData): 'DIAL_NUMBER' | '' => {
42
+ const destAgentType = taskData?.destinationType;
43
+
44
+ // Check if destination requires dialing: direct dial number or entry point variants
45
+ const isDialNumber = destAgentType === 'DN';
46
+ const isEntryPointVariant = isEntryPointOrEpdn(destAgentType);
47
+
48
+ // If the destination type is a dial number or an entry point variant, return 'DIAL_NUMBER'
49
+ return isDialNumber || isEntryPointVariant ? 'DIAL_NUMBER' : '';
50
+ };
51
+
22
52
  export const isValidDialNumber = (input: string): boolean => {
23
53
  // This regex checks for a valid dial number format for only few countries such as US, Canada.
24
54
  const regexForDn = /1[0-9]{3}[2-9][0-9]{6}([,]{1,10}[0-9]+){0,1}/;
@@ -115,6 +145,62 @@ export const getErrorDetails = (error: any, methodName: string, moduleName: stri
115
145
  };
116
146
  };
117
147
 
148
+ /**
149
+ * Extracts error details from task API errors and logs them. Also uploads logs for the error.
150
+ * This handles the specific error format returned by task API calls.
151
+ *
152
+ * @param error - The error object from task API calls with structure: {id: string, details: {trackingId: string, msg: {...}}}
153
+ * @param methodName - The name of the method where the error occurred.
154
+ * @param moduleName - The name of the module where the error occurred.
155
+ * @returns AugmentedError containing structured error details on err.data for metrics and logging
156
+ * @public
157
+ * @example
158
+ * const taskError = generateTaskErrorObject(error, 'transfer', 'TaskModule');
159
+ * throw taskError.error;
160
+ * @ignore
161
+ */
162
+ export const generateTaskErrorObject = (
163
+ error: any,
164
+ methodName: string,
165
+ moduleName: string
166
+ ): AugmentedError => {
167
+ const trackingId = error?.details?.trackingId || error?.trackingId || '';
168
+ const errorMsg = error?.details?.msg;
169
+
170
+ const fallbackMessage =
171
+ (error && typeof error.message === 'string' && error.message) ||
172
+ `Error while performing ${methodName}`;
173
+ const errorMessage = errorMsg?.errorMessage || fallbackMessage;
174
+ const errorType =
175
+ errorMsg?.errorType ||
176
+ (error && typeof error.name === 'string' && error.name) ||
177
+ 'Unknown Error';
178
+ const errorData = errorMsg?.errorData || '';
179
+ const reasonCode = errorMsg?.reasonCode || 0;
180
+
181
+ // Log and upload for Task API formatted errors
182
+ LoggerProxy.error(`${methodName} failed: ${errorMessage} (${errorType})`, {
183
+ module: moduleName,
184
+ method: methodName,
185
+ trackingId,
186
+ });
187
+ WebexRequest.getInstance().uploadLogs({
188
+ correlationId: trackingId,
189
+ });
190
+
191
+ const reason = `${errorType}: ${errorMessage}${errorData ? ` (${errorData})` : ''}`;
192
+ const err: AugmentedError = new Error(reason);
193
+ err.data = {
194
+ message: errorMessage,
195
+ errorType,
196
+ errorData,
197
+ reasonCode,
198
+ trackingId,
199
+ };
200
+
201
+ return err;
202
+ };
203
+
118
204
  /**
119
205
  * Creates an error details object suitable for use with the Err.Details class.
120
206
  *
@@ -130,3 +216,115 @@ export const createErrDetailsObject = (errObj: WebexRequestPayload) => {
130
216
 
131
217
  return new Err.Details('Service.reqs.generic.failure', details);
132
218
  };
219
+
220
+ /**
221
+ * Derives the consult transfer destination type based on the provided task data.
222
+ *
223
+ * Logic parity with desktop behavior:
224
+ * - If agent action is dialing a number (DN/EPDN/ENTRYPOINT):
225
+ * - ENTRYPOINT/EPDN map to ENTRYPOINT
226
+ * - DN maps to DIALNUMBER
227
+ * - Otherwise defaults to AGENT
228
+ *
229
+ * @param taskData - The task data used to infer the agent action and destination type
230
+ * @returns The normalized destination type to be used for consult transfer
231
+ */
232
+ /**
233
+ * Checks if a participant type represents a non-customer participant.
234
+ * Non-customer participants include agents, dial numbers, entry point dial numbers,
235
+ * and entry points.
236
+ */
237
+ const isNonCustomerParticipant = (participantType: string): boolean => {
238
+ return (
239
+ participantType === 'Agent' ||
240
+ participantType === 'DN' ||
241
+ participantType === 'EpDn' ||
242
+ participantType === 'entryPoint'
243
+ );
244
+ };
245
+
246
+ /**
247
+ * Gets the destination agent ID from participants data by finding the first
248
+ * non-customer participant that is not the current agent and is not in wrap-up state.
249
+ *
250
+ * @param participants - The participants data from the interaction
251
+ * @param agentId - The current agent's ID to exclude from the search
252
+ * @returns The destination agent ID, or empty string if none found
253
+ */
254
+ export const getDestinationAgentId = (
255
+ participants: Interaction['participants'],
256
+ agentId: string
257
+ ): string => {
258
+ let id = '';
259
+
260
+ if (participants) {
261
+ Object.keys(participants).forEach((participant) => {
262
+ const participantData = participants[participant];
263
+ if (
264
+ isNonCustomerParticipant(participantData.type) &&
265
+ participantData.id !== agentId &&
266
+ !participantData.isWrapUp
267
+ ) {
268
+ id = participantData.id;
269
+ }
270
+ });
271
+ }
272
+
273
+ return id;
274
+ };
275
+
276
+ export const deriveConsultTransferDestinationType = (
277
+ taskData?: TaskData
278
+ ): ConsultTransferPayLoad['destinationType'] => {
279
+ const agentActionType = getAgentActionTypeFromTask(taskData);
280
+
281
+ if (agentActionType === 'DIAL_NUMBER') {
282
+ return isEntryPointOrEpdn(taskData?.destinationType)
283
+ ? CONSULT_TRANSFER_DESTINATION_TYPE.ENTRYPOINT
284
+ : CONSULT_TRANSFER_DESTINATION_TYPE.DIALNUMBER;
285
+ }
286
+
287
+ return CONSULT_TRANSFER_DESTINATION_TYPE.AGENT;
288
+ };
289
+
290
+ /**
291
+ * Builds consult conference parameter data using EXACT Agent Desktop logic.
292
+ * This matches the Agent Desktop's consultConference implementation exactly.
293
+ *
294
+ * @param dataPassed - Original consultation data from Agent Desktop format
295
+ * @param interactionIdPassed - The interaction ID for the task
296
+ * @returns Object with interactionId and ConsultConferenceData matching Agent Desktop format
297
+ * @public
298
+ */
299
+ export const buildConsultConferenceParamData = (
300
+ dataPassed: consultConferencePayloadData,
301
+ interactionIdPassed: string
302
+ ): {interactionId: string; data: ConsultConferenceData} => {
303
+ const data: ConsultConferenceData = {
304
+ // Include agentId if present in input data
305
+ ...('agentId' in dataPassed && {agentId: dataPassed.agentId}),
306
+ // Handle destAgentId from consultation data
307
+ to: dataPassed.destAgentId,
308
+ destinationType: '',
309
+ };
310
+
311
+ // Agent Desktop destination type logic
312
+ if ('destinationType' in dataPassed) {
313
+ if (dataPassed.destinationType === 'DN') {
314
+ data.destinationType = CONSULT_TRANSFER_DESTINATION_TYPE.DIALNUMBER;
315
+ } else if (dataPassed.destinationType === 'EP_DN') {
316
+ data.destinationType = CONSULT_TRANSFER_DESTINATION_TYPE.ENTRYPOINT;
317
+ } else {
318
+ // Keep the existing destinationType if it's something else (like "agent" or "Agent")
319
+ // Convert "Agent" to lowercase for consistency
320
+ data.destinationType = dataPassed.destinationType.toLowerCase();
321
+ }
322
+ } else {
323
+ data.destinationType = CONSULT_TRANSFER_DESTINATION_TYPE.AGENT;
324
+ }
325
+
326
+ return {
327
+ interactionId: interactionIdPassed,
328
+ data,
329
+ };
330
+ };
@@ -224,11 +224,6 @@ export default class AqmReqs {
224
224
  }
225
225
 
226
226
  if (event.keepalive === 'true') {
227
- LoggerProxy.info(`Keepalive from web socket`, {
228
- module: AQM_REQS_FILE,
229
- method: METHODS.ON_MESSAGE,
230
- });
231
-
232
227
  return;
233
228
  }
234
229
 
@@ -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';
@@ -28,6 +28,7 @@ export default class TaskManager extends EventEmitter {
28
28
  private metricsManager: MetricsManager;
29
29
  private static taskManager;
30
30
  private wrapupData: WrapupData;
31
+ private agentId: string;
31
32
  /**
32
33
  * @param contact - Routing Contact layer. Talks to AQMReq layer to convert events to promises
33
34
  * @param webCallingService - Webrtc Service Layer
@@ -52,6 +53,19 @@ export default class TaskManager extends EventEmitter {
52
53
  this.wrapupData = wrapupData;
53
54
  }
54
55
 
56
+ public setAgentId(agentId: string) {
57
+ this.agentId = agentId;
58
+ }
59
+
60
+ /**
61
+ * Gets the current agent ID
62
+ * @returns {string} The agent ID set for this task manager instance
63
+ * @public
64
+ */
65
+ public getAgentId(): string {
66
+ return this.agentId;
67
+ }
68
+
55
69
  private handleIncomingWebCall = (call: ICall) => {
56
70
  const currentTask = Object.values(this.taskCollection).find(
57
71
  (task) => task.data.interaction.mediaType === 'telephony'
@@ -117,7 +131,8 @@ export default class TaskManager extends EventEmitter {
117
131
  payload.data.interaction?.participants?.[payload.data.agentId]?.isWrapUp ||
118
132
  false,
119
133
  },
120
- this.wrapupData
134
+ this.wrapupData,
135
+ this.agentId
121
136
  );
122
137
  this.taskCollection[payload.data.interactionId] = task;
123
138
  // Condition 1: The state is=new i.e it is a incoming task
@@ -153,8 +168,9 @@ export default class TaskManager extends EventEmitter {
153
168
  ...payload.data,
154
169
  isConsulted: false,
155
170
  },
156
- this.wrapupData
157
- ); // Ensure isConsulted prop exists
171
+ this.wrapupData,
172
+ this.agentId
173
+ );
158
174
  this.taskCollection[payload.data.interactionId] = task;
159
175
  if (
160
176
  this.webCallingService.loginOption !== LoginOption.BROWSER ||
@@ -270,6 +286,7 @@ export default class TaskManager extends EventEmitter {
270
286
  break;
271
287
  case CC_EVENTS.AGENT_CONSULTING:
272
288
  // Received when agent is in an active consult state
289
+ // TODO: Check if we can use backend consult state instead of isConsulted
273
290
  task = this.updateTaskData(task, payload.data);
274
291
  if (task.data.isConsulted) {
275
292
  // Fire only if you are the agent who received the consult request
@@ -323,6 +340,65 @@ export default class TaskManager extends EventEmitter {
323
340
  task = this.updateTaskData(task, payload.data);
324
341
  task.emit(TASK_EVENTS.TASK_RECORDING_RESUME_FAILED, task);
325
342
  break;
343
+ case CC_EVENTS.AGENT_CONSULT_CONFERENCING:
344
+ // Conference is being established - update task state and emit establishing event
345
+ task = this.updateTaskData(task, payload.data);
346
+ task.emit(TASK_EVENTS.TASK_CONFERENCE_ESTABLISHING, task);
347
+ break;
348
+ case CC_EVENTS.AGENT_CONSULT_CONFERENCED:
349
+ // Conference started successfully - update task state and emit event
350
+ task = this.updateTaskData(task, payload.data);
351
+ task.emit(TASK_EVENTS.TASK_CONFERENCE_STARTED, task);
352
+ break;
353
+ case CC_EVENTS.AGENT_CONSULT_CONFERENCE_FAILED:
354
+ // Conference failed - update task state and emit failure event
355
+ task = this.updateTaskData(task, payload.data);
356
+ task.emit(TASK_EVENTS.TASK_CONFERENCE_FAILED, task);
357
+ break;
358
+ case CC_EVENTS.AGENT_CONSULT_CONFERENCE_ENDED:
359
+ // Conference ended - update task state and emit event
360
+ task = this.updateTaskData(task, payload.data);
361
+ task.emit(TASK_EVENTS.TASK_CONFERENCE_ENDED, task);
362
+ break;
363
+ case CC_EVENTS.PARTICIPANT_JOINED_CONFERENCE:
364
+ // Participant joined conference - update task state with participant information and emit event
365
+ task = this.updateTaskData(task, payload.data);
366
+ task.emit(TASK_EVENTS.TASK_PARTICIPANT_JOINED, task);
367
+ break;
368
+ case CC_EVENTS.PARTICIPANT_LEFT_CONFERENCE:
369
+ // Conference ended - update task state and emit event
370
+ task = this.updateTaskData(task, payload.data);
371
+ task.emit(TASK_EVENTS.TASK_PARTICIPANT_LEFT, task);
372
+ break;
373
+ case CC_EVENTS.PARTICIPANT_LEFT_CONFERENCE_FAILED:
374
+ // Conference exit failed - update task state and emit failure event
375
+ task = this.updateTaskData(task, payload.data);
376
+ task.emit(TASK_EVENTS.TASK_PARTICIPANT_LEFT_FAILED, task);
377
+ break;
378
+ case CC_EVENTS.AGENT_CONSULT_CONFERENCE_END_FAILED:
379
+ // Conference end failed - update task state with error details and emit failure event
380
+ task = this.updateTaskData(task, payload.data);
381
+ task.emit(TASK_EVENTS.TASK_CONFERENCE_END_FAILED, task);
382
+ break;
383
+ case CC_EVENTS.AGENT_CONFERENCE_TRANSFERRED:
384
+ // Conference was transferred - update task state and emit transfer success event
385
+ // Note: Backend should provide hasLeft and wrapUpRequired status
386
+ task = this.updateTaskData(task, payload.data);
387
+ task.emit(TASK_EVENTS.TASK_CONFERENCE_TRANSFERRED, task);
388
+ break;
389
+ case CC_EVENTS.AGENT_CONFERENCE_TRANSFER_FAILED:
390
+ // Conference transfer failed - update task state with error details and emit failure event
391
+ task = this.updateTaskData(task, payload.data);
392
+ task.emit(TASK_EVENTS.TASK_CONFERENCE_TRANSFER_FAILED, task);
393
+ break;
394
+ case CC_EVENTS.CONSULTED_PARTICIPANT_MOVING:
395
+ // Participant is being moved/transferred - update task state with movement info
396
+ task = this.updateTaskData(task, payload.data);
397
+ break;
398
+ case CC_EVENTS.PARTICIPANT_POST_CALL_ACTIVITY:
399
+ // Post-call activity for participant - update task state with activity details
400
+ task = this.updateTaskData(task, payload.data);
401
+ break;
326
402
  default:
327
403
  break;
328
404
  }
@@ -17,6 +17,9 @@ export const PAUSE = '/record/pause';
17
17
  export const RESUME = '/record/resume';
18
18
  export const WRAPUP = '/wrapup';
19
19
  export const END = '/end';
20
+ export const CONSULT_CONFERENCE = '/consult/conference';
21
+ export const CONFERENCE_EXIT = '/conference/exit';
22
+ export const CONFERENCE_TRANSFER = '/conference/transfer';
20
23
  export const TASK_MANAGER_FILE = 'taskManager';
21
24
  export const TASK_FILE = 'task';
22
25
 
@@ -36,6 +39,9 @@ export const METHODS = {
36
39
  END_CONSULT: 'endConsult',
37
40
  TRANSFER: 'transfer',
38
41
  CONSULT_TRANSFER: 'consultTransfer',
42
+ CONSULT_CONFERENCE: 'consultConference',
43
+ EXIT_CONFERENCE: 'exitConference',
44
+ TRANSFER_CONFERENCE: 'transferConference',
39
45
  UPDATE_TASK_DATA: 'updateTaskData',
40
46
  RECONCILE_DATA: 'reconcileData',
41
47
 
@@ -17,6 +17,9 @@ import {
17
17
  TRANSFER,
18
18
  UNHOLD,
19
19
  WRAPUP,
20
+ CONSULT_CONFERENCE,
21
+ CONFERENCE_EXIT,
22
+ CONFERENCE_TRANSFER,
20
23
  } from './constants';
21
24
  import * as Contact from './types';
22
25
  import {DESTINATION_TYPE} from './types';
@@ -425,5 +428,82 @@ export default function routingContact(aqm: AqmReqs) {
425
428
  errId: 'Service.aqm.task.cancelCtq',
426
429
  },
427
430
  })),
431
+
432
+ /*
433
+ * Start consult conference
434
+ */
435
+ consultConference: aqm.req(
436
+ (p: {interactionId: string; data: Contact.ConsultConferenceData}) => ({
437
+ url: `${TASK_API}${p.interactionId}${CONSULT_CONFERENCE}`,
438
+ data: p.data,
439
+ host: WCC_API_GATEWAY,
440
+ err,
441
+ notifSuccess: {
442
+ bind: {
443
+ type: TASK_MESSAGE_TYPE,
444
+ data: {
445
+ type: [CC_EVENTS.AGENT_CONSULT_CONFERENCED, CC_EVENTS.AGENT_CONSULT_CONFERENCING],
446
+ interactionId: p.interactionId,
447
+ }, // any of the two events can be received for API success event
448
+ },
449
+ msg: {} as Contact.AgentContact,
450
+ },
451
+ notifFail: {
452
+ bind: {
453
+ type: TASK_MESSAGE_TYPE,
454
+ data: {type: CC_EVENTS.AGENT_CONSULT_CONFERENCE_FAILED},
455
+ },
456
+ errId: 'Service.aqm.task.consultConference',
457
+ },
458
+ })
459
+ ),
460
+
461
+ /*
462
+ * Exit conference
463
+ */
464
+ exitConference: aqm.req((p: {interactionId: string}) => ({
465
+ url: `${TASK_API}${p.interactionId}${CONFERENCE_EXIT}`,
466
+ data: {},
467
+ host: WCC_API_GATEWAY,
468
+ err,
469
+ notifSuccess: {
470
+ bind: {
471
+ type: TASK_MESSAGE_TYPE,
472
+ data: {type: CC_EVENTS.PARTICIPANT_LEFT_CONFERENCE, interactionId: p.interactionId},
473
+ },
474
+ msg: {} as Contact.AgentContact,
475
+ },
476
+ notifFail: {
477
+ bind: {
478
+ type: TASK_MESSAGE_TYPE,
479
+ data: {type: CC_EVENTS.PARTICIPANT_LEFT_CONFERENCE_FAILED}, // to be finalized
480
+ },
481
+ errId: 'Service.aqm.task.consultConference',
482
+ },
483
+ })),
484
+
485
+ /*
486
+ * Transfer conference
487
+ */
488
+ conferenceTransfer: aqm.req((p: {interactionId: string}) => ({
489
+ url: `${TASK_API}${p.interactionId}${CONFERENCE_TRANSFER}`,
490
+ data: {},
491
+ host: WCC_API_GATEWAY,
492
+ err,
493
+ notifSuccess: {
494
+ bind: {
495
+ type: TASK_MESSAGE_TYPE,
496
+ data: {type: CC_EVENTS.PARTICIPANT_LEFT_CONFERENCE, interactionId: p.interactionId},
497
+ },
498
+ msg: {} as Contact.AgentContact,
499
+ },
500
+ notifFail: {
501
+ bind: {
502
+ type: TASK_MESSAGE_TYPE,
503
+ data: {type: CC_EVENTS.AGENT_CONFERENCE_TRANSFER_FAILED},
504
+ },
505
+ errId: 'Service.aqm.task.consultConference',
506
+ },
507
+ })),
428
508
  };
429
509
  }