@webex/contact-center 3.9.0 → 3.10.0-next.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.
- 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 +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 +89 -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 +114 -3
- package/dist/services/task/TaskManager.js.map +1 -1
- package/dist/services/task/TaskUtils.js +76 -0
- package/dist/services/task/TaskUtils.js.map +1 -0
- package/dist/services/task/constants.js +26 -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 +418 -87
- 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 +3 -2
- 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/TaskUtils.d.ts +28 -0
- package/dist/types/services/task/constants.d.ts +23 -0
- package/dist/types/services/task/contact.d.ts +10 -0
- package/dist/types/services/task/index.d.ts +85 -4
- package/dist/types/services/task/types.d.ts +233 -21
- 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 +10 -9
- package/src/cc.ts +221 -52
- package/src/constants.ts +1 -0
- 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 +94 -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 +123 -5
- package/src/services/task/TaskUtils.ts +81 -0
- package/src/services/task/constants.ts +25 -0
- package/src/services/task/contact.ts +80 -0
- package/src/services/task/index.ts +510 -71
- package/src/services/task/types.ts +251 -20
- package/src/types.ts +180 -0
- package/src/utils/PageCache.ts +252 -0
- package/test/unit/spec/cc.ts +282 -85
- package/test/unit/spec/metrics/MetricsManager.ts +0 -1
- package/test/unit/spec/metrics/behavioral-events.ts +42 -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 +390 -1
- package/test/unit/spec/services/task/TaskUtils.ts +131 -0
- package/test/unit/spec/services/task/contact.ts +31 -1
- package/test/unit/spec/services/task/index.ts +585 -130
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import EventEmitter from 'events';
|
|
2
2
|
import {CALL_EVENT_KEYS, LocalMicrophoneStream} from '@webex/calling';
|
|
3
3
|
import {CallId} from '@webex/calling/dist/types/common/types';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
generateTaskErrorObject,
|
|
6
|
+
deriveConsultTransferDestinationType,
|
|
7
|
+
getDestinationAgentId,
|
|
8
|
+
buildConsultConferenceParamData,
|
|
9
|
+
} from '../core/Utils';
|
|
10
|
+
import {Failure} from '../core/GlobalTypes';
|
|
5
11
|
import {LoginOption} from '../../types';
|
|
6
12
|
import {TASK_FILE} from '../../constants';
|
|
7
|
-
import {METHODS} from './constants';
|
|
13
|
+
import {METHODS, KEYS_TO_NOT_DELETE} from './constants';
|
|
8
14
|
import routingContact from './contact';
|
|
9
15
|
import LoggerProxy from '../../logger-proxy';
|
|
10
16
|
import {
|
|
@@ -19,14 +25,12 @@ import {
|
|
|
19
25
|
ConsultEndPayload,
|
|
20
26
|
TransferPayLoad,
|
|
21
27
|
DESTINATION_TYPE,
|
|
22
|
-
CONSULT_TRANSFER_DESTINATION_TYPE,
|
|
23
28
|
ConsultTransferPayLoad,
|
|
24
29
|
MEDIA_CHANNEL,
|
|
25
30
|
} from './types';
|
|
26
31
|
import WebCallingService from '../WebCallingService';
|
|
27
32
|
import MetricsManager from '../../metrics/MetricsManager';
|
|
28
33
|
import {METRIC_EVENT_NAMES} from '../../metrics/constants';
|
|
29
|
-
import {Failure} from '../core/GlobalTypes';
|
|
30
34
|
import AutoWrapup from './AutoWrapup';
|
|
31
35
|
import {WrapupData} from '../config/types';
|
|
32
36
|
|
|
@@ -135,6 +139,7 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
135
139
|
public webCallMap: Record<TaskId, CallId>;
|
|
136
140
|
private wrapupData: WrapupData;
|
|
137
141
|
public autoWrapup?: AutoWrapup;
|
|
142
|
+
private agentId: string;
|
|
138
143
|
|
|
139
144
|
/**
|
|
140
145
|
* Creates a new Task instance which provides the following features:
|
|
@@ -147,7 +152,8 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
147
152
|
contact: ReturnType<typeof routingContact>,
|
|
148
153
|
webCallingService: WebCallingService,
|
|
149
154
|
data: TaskData,
|
|
150
|
-
wrapupData: WrapupData
|
|
155
|
+
wrapupData: WrapupData,
|
|
156
|
+
agentId: string
|
|
151
157
|
) {
|
|
152
158
|
super();
|
|
153
159
|
this.contact = contact;
|
|
@@ -158,6 +164,7 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
158
164
|
this.metricsManager = MetricsManager.getInstance();
|
|
159
165
|
this.registerWebCallListeners();
|
|
160
166
|
this.setupAutoWrapupTimer();
|
|
167
|
+
this.agentId = agentId;
|
|
161
168
|
}
|
|
162
169
|
|
|
163
170
|
/**
|
|
@@ -274,9 +281,24 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
274
281
|
* @private
|
|
275
282
|
*/
|
|
276
283
|
private reconcileData(oldData: TaskData, newData: TaskData): TaskData {
|
|
284
|
+
// Remove keys from oldData that are not in newData
|
|
285
|
+
Object.keys(oldData).forEach((key) => {
|
|
286
|
+
if (!(key in newData) && !KEYS_TO_NOT_DELETE.includes(key as string)) {
|
|
287
|
+
delete oldData[key];
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
// Merge or update keys from newData
|
|
277
292
|
Object.keys(newData).forEach((key) => {
|
|
278
|
-
if (
|
|
279
|
-
|
|
293
|
+
if (
|
|
294
|
+
newData[key] &&
|
|
295
|
+
typeof newData[key] === 'object' &&
|
|
296
|
+
!Array.isArray(newData[key]) &&
|
|
297
|
+
oldData[key] &&
|
|
298
|
+
typeof oldData[key] === 'object' &&
|
|
299
|
+
!Array.isArray(oldData[key])
|
|
300
|
+
) {
|
|
301
|
+
this.reconcileData(oldData[key], newData[key]);
|
|
280
302
|
} else {
|
|
281
303
|
oldData[key] = newData[key];
|
|
282
304
|
}
|
|
@@ -373,17 +395,25 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
373
395
|
|
|
374
396
|
return Promise.resolve(); // TODO: reject for extension as part of refactor
|
|
375
397
|
} catch (error) {
|
|
376
|
-
const
|
|
398
|
+
const err = generateTaskErrorObject(error, METHODS.ACCEPT, TASK_FILE);
|
|
399
|
+
const taskErrorProps = {
|
|
400
|
+
trackingId: err.data?.trackingId,
|
|
401
|
+
errorMessage: err.data?.message,
|
|
402
|
+
errorType: err.data?.errorType,
|
|
403
|
+
errorData: err.data?.errorData,
|
|
404
|
+
reasonCode: err.data?.reasonCode,
|
|
405
|
+
};
|
|
377
406
|
this.metricsManager.trackEvent(
|
|
378
407
|
METRIC_EVENT_NAMES.TASK_ACCEPT_FAILED,
|
|
379
408
|
{
|
|
380
409
|
taskId: this.data.interactionId,
|
|
381
410
|
error: error.toString(),
|
|
411
|
+
...taskErrorProps,
|
|
382
412
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details as Failure),
|
|
383
413
|
},
|
|
384
414
|
['operational', 'behavioral', 'business']
|
|
385
415
|
);
|
|
386
|
-
throw
|
|
416
|
+
throw err;
|
|
387
417
|
}
|
|
388
418
|
}
|
|
389
419
|
|
|
@@ -422,8 +452,8 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
422
452
|
|
|
423
453
|
return Promise.resolve();
|
|
424
454
|
} catch (error) {
|
|
425
|
-
const
|
|
426
|
-
throw
|
|
455
|
+
const err = generateTaskErrorObject(error, METHODS.TOGGLE_MUTE, TASK_FILE);
|
|
456
|
+
throw err;
|
|
427
457
|
}
|
|
428
458
|
}
|
|
429
459
|
|
|
@@ -470,17 +500,25 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
470
500
|
|
|
471
501
|
return Promise.resolve();
|
|
472
502
|
} catch (error) {
|
|
473
|
-
const
|
|
503
|
+
const err = generateTaskErrorObject(error, METHODS.DECLINE, TASK_FILE);
|
|
504
|
+
const taskErrorProps = {
|
|
505
|
+
trackingId: err.data?.trackingId,
|
|
506
|
+
errorMessage: err.data?.message,
|
|
507
|
+
errorType: err.data?.errorType,
|
|
508
|
+
errorData: err.data?.errorData,
|
|
509
|
+
reasonCode: err.data?.reasonCode,
|
|
510
|
+
};
|
|
474
511
|
this.metricsManager.trackEvent(
|
|
475
512
|
METRIC_EVENT_NAMES.TASK_DECLINE_FAILED,
|
|
476
513
|
{
|
|
477
514
|
taskId: this.data.interactionId,
|
|
478
515
|
error: error.toString(),
|
|
516
|
+
...taskErrorProps,
|
|
479
517
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details || {}),
|
|
480
518
|
},
|
|
481
519
|
['operational', 'behavioral']
|
|
482
520
|
);
|
|
483
|
-
throw
|
|
521
|
+
throw err;
|
|
484
522
|
}
|
|
485
523
|
}
|
|
486
524
|
|
|
@@ -488,6 +526,7 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
488
526
|
* Puts the current task/interaction on hold.
|
|
489
527
|
* Emits task:hold event when successful. For voice tasks, this mutes the audio.
|
|
490
528
|
*
|
|
529
|
+
* @param mediaResourceId - Optional media resource ID to use for the hold operation. If not provided, uses the task's current mediaResourceId
|
|
491
530
|
* @returns Promise<TaskResponse>
|
|
492
531
|
* @throws Error if hold operation fails
|
|
493
532
|
* @example
|
|
@@ -508,9 +547,17 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
508
547
|
* console.error('Failed to place task on hold:', error);
|
|
509
548
|
* // Handle error (e.g., show error message, reset UI state)
|
|
510
549
|
* }
|
|
550
|
+
*
|
|
551
|
+
* // Place task on hold with custom mediaResourceId
|
|
552
|
+
* try {
|
|
553
|
+
* await task.hold('custom-media-resource-id');
|
|
554
|
+
* console.log('Successfully placed task on hold with custom mediaResourceId');
|
|
555
|
+
* } catch (error) {
|
|
556
|
+
* console.error('Failed to place task on hold:', error);
|
|
557
|
+
* }
|
|
511
558
|
* ```
|
|
512
559
|
*/
|
|
513
|
-
public async hold(): Promise<TaskResponse> {
|
|
560
|
+
public async hold(mediaResourceId?: string): Promise<TaskResponse> {
|
|
514
561
|
try {
|
|
515
562
|
LoggerProxy.info(`Holding task`, {
|
|
516
563
|
module: TASK_FILE,
|
|
@@ -523,9 +570,11 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
523
570
|
METRIC_EVENT_NAMES.TASK_HOLD_FAILED,
|
|
524
571
|
]);
|
|
525
572
|
|
|
573
|
+
const effectiveMediaResourceId = mediaResourceId ?? this.data.mediaResourceId;
|
|
574
|
+
|
|
526
575
|
const response = await this.contact.hold({
|
|
527
576
|
interactionId: this.data.interactionId,
|
|
528
|
-
data: {mediaResourceId:
|
|
577
|
+
data: {mediaResourceId: effectiveMediaResourceId},
|
|
529
578
|
});
|
|
530
579
|
|
|
531
580
|
this.metricsManager.trackEvent(
|
|
@@ -533,7 +582,7 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
533
582
|
{
|
|
534
583
|
...MetricsManager.getCommonTrackingFieldForAQMResponse(response),
|
|
535
584
|
taskId: this.data.interactionId,
|
|
536
|
-
mediaResourceId:
|
|
585
|
+
mediaResourceId: effectiveMediaResourceId,
|
|
537
586
|
},
|
|
538
587
|
['operational', 'behavioral']
|
|
539
588
|
);
|
|
@@ -547,18 +596,28 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
547
596
|
|
|
548
597
|
return response;
|
|
549
598
|
} catch (error) {
|
|
550
|
-
const
|
|
599
|
+
const err = generateTaskErrorObject(error, METHODS.HOLD, TASK_FILE);
|
|
600
|
+
const taskErrorProps = {
|
|
601
|
+
trackingId: err.data?.trackingId,
|
|
602
|
+
errorMessage: err.data?.message,
|
|
603
|
+
errorType: err.data?.errorType,
|
|
604
|
+
errorData: err.data?.errorData,
|
|
605
|
+
reasonCode: err.data?.reasonCode,
|
|
606
|
+
};
|
|
607
|
+
const effectiveMediaResourceId = mediaResourceId ?? this.data.mediaResourceId;
|
|
608
|
+
|
|
551
609
|
this.metricsManager.trackEvent(
|
|
552
610
|
METRIC_EVENT_NAMES.TASK_HOLD_FAILED,
|
|
553
611
|
{
|
|
554
612
|
taskId: this.data.interactionId,
|
|
555
|
-
mediaResourceId:
|
|
613
|
+
mediaResourceId: effectiveMediaResourceId,
|
|
556
614
|
error: error.toString(),
|
|
615
|
+
...taskErrorProps,
|
|
557
616
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details || {}),
|
|
558
617
|
},
|
|
559
618
|
['operational', 'behavioral']
|
|
560
619
|
);
|
|
561
|
-
throw
|
|
620
|
+
throw err;
|
|
562
621
|
}
|
|
563
622
|
}
|
|
564
623
|
|
|
@@ -566,6 +625,7 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
566
625
|
* Resumes the task/interaction that was previously put on hold.
|
|
567
626
|
* Emits task:resume event when successful. For voice tasks, this restores the audio.
|
|
568
627
|
*
|
|
628
|
+
* @param mediaResourceId - Optional media resource ID to use for the resume operation. If not provided, uses the task's current mediaResourceId from interaction media
|
|
569
629
|
* @returns Promise<TaskResponse>
|
|
570
630
|
* @throws Error if resume operation fails
|
|
571
631
|
* @example
|
|
@@ -586,9 +646,17 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
586
646
|
* console.error('Failed to resume task:', error);
|
|
587
647
|
* // Handle error (e.g., show error message)
|
|
588
648
|
* }
|
|
649
|
+
*
|
|
650
|
+
* // Resume task from hold with custom mediaResourceId
|
|
651
|
+
* try {
|
|
652
|
+
* await task.resume('custom-media-resource-id');
|
|
653
|
+
* console.log('Successfully resumed task from hold with custom mediaResourceId');
|
|
654
|
+
* } catch (error) {
|
|
655
|
+
* console.error('Failed to resume task:', error);
|
|
656
|
+
* }
|
|
589
657
|
* ```
|
|
590
658
|
*/
|
|
591
|
-
public async resume(): Promise<TaskResponse> {
|
|
659
|
+
public async resume(mediaResourceId?: string): Promise<TaskResponse> {
|
|
592
660
|
try {
|
|
593
661
|
LoggerProxy.info(`Resuming task`, {
|
|
594
662
|
module: TASK_FILE,
|
|
@@ -596,7 +664,9 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
596
664
|
interactionId: this.data.interactionId,
|
|
597
665
|
});
|
|
598
666
|
const {mainInteractionId} = this.data.interaction;
|
|
599
|
-
const
|
|
667
|
+
const defaultMediaResourceId =
|
|
668
|
+
this.data.interaction.media[mainInteractionId]?.mediaResourceId;
|
|
669
|
+
const effectiveMediaResourceId = mediaResourceId ?? defaultMediaResourceId;
|
|
600
670
|
|
|
601
671
|
this.metricsManager.timeEvent([
|
|
602
672
|
METRIC_EVENT_NAMES.TASK_RESUME_SUCCESS,
|
|
@@ -605,7 +675,7 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
605
675
|
|
|
606
676
|
const response = await this.contact.unHold({
|
|
607
677
|
interactionId: this.data.interactionId,
|
|
608
|
-
data: {mediaResourceId},
|
|
678
|
+
data: {mediaResourceId: effectiveMediaResourceId},
|
|
609
679
|
});
|
|
610
680
|
|
|
611
681
|
this.metricsManager.trackEvent(
|
|
@@ -613,7 +683,7 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
613
683
|
{
|
|
614
684
|
taskId: this.data.interactionId,
|
|
615
685
|
mainInteractionId,
|
|
616
|
-
mediaResourceId,
|
|
686
|
+
mediaResourceId: effectiveMediaResourceId,
|
|
617
687
|
...MetricsManager.getCommonTrackingFieldForAQMResponse(response),
|
|
618
688
|
},
|
|
619
689
|
['operational', 'behavioral']
|
|
@@ -628,21 +698,32 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
628
698
|
|
|
629
699
|
return response;
|
|
630
700
|
} catch (error) {
|
|
631
|
-
const
|
|
701
|
+
const err = generateTaskErrorObject(error, METHODS.RESUME, TASK_FILE);
|
|
632
702
|
const mainInteractionId = this.data.interaction?.mainInteractionId;
|
|
703
|
+
const defaultMediaResourceId = mainInteractionId
|
|
704
|
+
? this.data.interaction.media[mainInteractionId]?.mediaResourceId
|
|
705
|
+
: '';
|
|
706
|
+
const effectiveMediaResourceId = mediaResourceId ?? defaultMediaResourceId;
|
|
707
|
+
|
|
708
|
+
const taskErrorProps = {
|
|
709
|
+
trackingId: err.data?.trackingId,
|
|
710
|
+
errorMessage: err.data?.message,
|
|
711
|
+
errorType: err.data?.errorType,
|
|
712
|
+
errorData: err.data?.errorData,
|
|
713
|
+
reasonCode: err.data?.reasonCode,
|
|
714
|
+
};
|
|
633
715
|
this.metricsManager.trackEvent(
|
|
634
716
|
METRIC_EVENT_NAMES.TASK_RESUME_FAILED,
|
|
635
717
|
{
|
|
636
718
|
taskId: this.data.interactionId,
|
|
637
719
|
mainInteractionId,
|
|
638
|
-
mediaResourceId:
|
|
639
|
-
|
|
640
|
-
: '',
|
|
720
|
+
mediaResourceId: effectiveMediaResourceId,
|
|
721
|
+
...taskErrorProps,
|
|
641
722
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details || {}),
|
|
642
723
|
},
|
|
643
724
|
['operational', 'behavioral']
|
|
644
725
|
);
|
|
645
|
-
throw
|
|
726
|
+
throw err;
|
|
646
727
|
}
|
|
647
728
|
}
|
|
648
729
|
|
|
@@ -722,16 +803,24 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
722
803
|
|
|
723
804
|
return response;
|
|
724
805
|
} catch (error) {
|
|
725
|
-
const
|
|
806
|
+
const err = generateTaskErrorObject(error, METHODS.END, TASK_FILE);
|
|
807
|
+
const taskErrorProps = {
|
|
808
|
+
trackingId: err.data?.trackingId,
|
|
809
|
+
errorMessage: err.data?.message,
|
|
810
|
+
errorType: err.data?.errorType,
|
|
811
|
+
errorData: err.data?.errorData,
|
|
812
|
+
reasonCode: err.data?.reasonCode,
|
|
813
|
+
};
|
|
726
814
|
this.metricsManager.trackEvent(
|
|
727
815
|
METRIC_EVENT_NAMES.TASK_END_FAILED,
|
|
728
816
|
{
|
|
729
817
|
taskId: this.data.interactionId,
|
|
818
|
+
...taskErrorProps,
|
|
730
819
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details || {}),
|
|
731
820
|
},
|
|
732
821
|
['operational', 'behavioral', 'business']
|
|
733
822
|
);
|
|
734
|
-
throw
|
|
823
|
+
throw err;
|
|
735
824
|
}
|
|
736
825
|
}
|
|
737
826
|
|
|
@@ -826,18 +915,26 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
826
915
|
|
|
827
916
|
return response;
|
|
828
917
|
} catch (error) {
|
|
829
|
-
const
|
|
918
|
+
const err = generateTaskErrorObject(error, METHODS.WRAPUP, TASK_FILE);
|
|
919
|
+
const taskErrorProps = {
|
|
920
|
+
trackingId: err.data?.trackingId,
|
|
921
|
+
errorMessage: err.data?.message,
|
|
922
|
+
errorType: err.data?.errorType,
|
|
923
|
+
errorData: err.data?.errorData,
|
|
924
|
+
reasonCode: err.data?.reasonCode,
|
|
925
|
+
};
|
|
830
926
|
this.metricsManager.trackEvent(
|
|
831
927
|
METRIC_EVENT_NAMES.TASK_WRAPUP_FAILED,
|
|
832
928
|
{
|
|
833
929
|
taskId: this.data.interactionId,
|
|
834
930
|
wrapUpCode: wrapupPayload.auxCodeId,
|
|
835
931
|
wrapUpReason: wrapupPayload.wrapUpReason,
|
|
932
|
+
...taskErrorProps,
|
|
836
933
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details || {}),
|
|
837
934
|
},
|
|
838
935
|
['operational', 'behavioral', 'business']
|
|
839
936
|
);
|
|
840
|
-
throw
|
|
937
|
+
throw err;
|
|
841
938
|
}
|
|
842
939
|
}
|
|
843
940
|
|
|
@@ -906,17 +1003,25 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
906
1003
|
|
|
907
1004
|
return result;
|
|
908
1005
|
} catch (error) {
|
|
909
|
-
const
|
|
1006
|
+
const err = generateTaskErrorObject(error, METHODS.PAUSE_RECORDING, TASK_FILE);
|
|
1007
|
+
const taskErrorProps = {
|
|
1008
|
+
trackingId: err.data?.trackingId,
|
|
1009
|
+
errorMessage: err.data?.message,
|
|
1010
|
+
errorType: err.data?.errorType,
|
|
1011
|
+
errorData: err.data?.errorData,
|
|
1012
|
+
reasonCode: err.data?.reasonCode,
|
|
1013
|
+
};
|
|
910
1014
|
this.metricsManager.trackEvent(
|
|
911
1015
|
METRIC_EVENT_NAMES.TASK_PAUSE_RECORDING_FAILED,
|
|
912
1016
|
{
|
|
913
1017
|
taskId: this.data.interactionId,
|
|
914
1018
|
error: error.toString(),
|
|
1019
|
+
...taskErrorProps,
|
|
915
1020
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details || {}),
|
|
916
1021
|
},
|
|
917
1022
|
['operational', 'behavioral', 'business']
|
|
918
1023
|
);
|
|
919
|
-
throw
|
|
1024
|
+
throw err;
|
|
920
1025
|
}
|
|
921
1026
|
}
|
|
922
1027
|
|
|
@@ -997,17 +1102,25 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
997
1102
|
|
|
998
1103
|
return result;
|
|
999
1104
|
} catch (error) {
|
|
1000
|
-
const
|
|
1105
|
+
const err = generateTaskErrorObject(error, METHODS.RESUME_RECORDING, TASK_FILE);
|
|
1106
|
+
const taskErrorProps = {
|
|
1107
|
+
trackingId: err.data?.trackingId,
|
|
1108
|
+
errorMessage: err.data?.message,
|
|
1109
|
+
errorType: err.data?.errorType,
|
|
1110
|
+
errorData: err.data?.errorData,
|
|
1111
|
+
reasonCode: err.data?.reasonCode,
|
|
1112
|
+
};
|
|
1001
1113
|
this.metricsManager.trackEvent(
|
|
1002
1114
|
METRIC_EVENT_NAMES.TASK_RESUME_RECORDING_FAILED,
|
|
1003
1115
|
{
|
|
1004
1116
|
taskId: this.data.interactionId,
|
|
1005
1117
|
error: error.toString(),
|
|
1118
|
+
...taskErrorProps,
|
|
1006
1119
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details || {}),
|
|
1007
1120
|
},
|
|
1008
1121
|
['operational', 'behavioral', 'business']
|
|
1009
1122
|
);
|
|
1010
|
-
throw
|
|
1123
|
+
throw err;
|
|
1011
1124
|
}
|
|
1012
1125
|
}
|
|
1013
1126
|
|
|
@@ -1082,7 +1195,14 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
1082
1195
|
|
|
1083
1196
|
return result;
|
|
1084
1197
|
} catch (error) {
|
|
1085
|
-
const
|
|
1198
|
+
const err = generateTaskErrorObject(error, METHODS.CONSULT, TASK_FILE);
|
|
1199
|
+
const taskErrorProps = {
|
|
1200
|
+
trackingId: err.data?.trackingId,
|
|
1201
|
+
errorMessage: err.data?.message,
|
|
1202
|
+
errorType: err.data?.errorType,
|
|
1203
|
+
errorData: err.data?.errorData,
|
|
1204
|
+
reasonCode: err.data?.reasonCode,
|
|
1205
|
+
};
|
|
1086
1206
|
this.metricsManager.trackEvent(
|
|
1087
1207
|
METRIC_EVENT_NAMES.TASK_CONSULT_START_FAILED,
|
|
1088
1208
|
{
|
|
@@ -1090,11 +1210,12 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
1090
1210
|
destination: consultPayload.to,
|
|
1091
1211
|
destinationType: consultPayload.destinationType,
|
|
1092
1212
|
error: error.toString(),
|
|
1213
|
+
...taskErrorProps,
|
|
1093
1214
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details || {}),
|
|
1094
1215
|
},
|
|
1095
1216
|
['operational', 'behavioral', 'business']
|
|
1096
1217
|
);
|
|
1097
|
-
throw
|
|
1218
|
+
throw err;
|
|
1098
1219
|
}
|
|
1099
1220
|
}
|
|
1100
1221
|
|
|
@@ -1167,17 +1288,25 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
1167
1288
|
|
|
1168
1289
|
return result;
|
|
1169
1290
|
} catch (error) {
|
|
1170
|
-
const
|
|
1291
|
+
const err = generateTaskErrorObject(error, METHODS.END_CONSULT, TASK_FILE);
|
|
1292
|
+
const taskErrorProps = {
|
|
1293
|
+
trackingId: err.data?.trackingId,
|
|
1294
|
+
errorMessage: err.data?.message,
|
|
1295
|
+
errorType: err.data?.errorType,
|
|
1296
|
+
errorData: err.data?.errorData,
|
|
1297
|
+
reasonCode: err.data?.reasonCode,
|
|
1298
|
+
};
|
|
1171
1299
|
this.metricsManager.trackEvent(
|
|
1172
1300
|
METRIC_EVENT_NAMES.TASK_CONSULT_END_FAILED,
|
|
1173
1301
|
{
|
|
1174
1302
|
taskId: this.data.interactionId,
|
|
1175
1303
|
error: error.toString(),
|
|
1304
|
+
...taskErrorProps,
|
|
1176
1305
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details || {}),
|
|
1177
1306
|
},
|
|
1178
1307
|
['operational', 'behavioral', 'business']
|
|
1179
1308
|
);
|
|
1180
|
-
throw
|
|
1309
|
+
throw err;
|
|
1181
1310
|
}
|
|
1182
1311
|
}
|
|
1183
1312
|
|
|
@@ -1258,7 +1387,14 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
1258
1387
|
|
|
1259
1388
|
return result;
|
|
1260
1389
|
} catch (error) {
|
|
1261
|
-
const
|
|
1390
|
+
const err = generateTaskErrorObject(error, METHODS.TRANSFER, TASK_FILE);
|
|
1391
|
+
const taskErrorProps = {
|
|
1392
|
+
trackingId: err.data?.trackingId,
|
|
1393
|
+
errorMessage: err.data?.message,
|
|
1394
|
+
errorType: err.data?.errorType,
|
|
1395
|
+
errorData: err.data?.errorData,
|
|
1396
|
+
reasonCode: err.data?.reasonCode,
|
|
1397
|
+
};
|
|
1262
1398
|
this.metricsManager.trackEvent(
|
|
1263
1399
|
METRIC_EVENT_NAMES.TASK_TRANSFER_FAILED,
|
|
1264
1400
|
{
|
|
@@ -1267,11 +1403,12 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
1267
1403
|
destinationType: transferPayload.destinationType,
|
|
1268
1404
|
isConsultTransfer: false,
|
|
1269
1405
|
error: error.toString(),
|
|
1406
|
+
...taskErrorProps,
|
|
1270
1407
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details || {}),
|
|
1271
1408
|
},
|
|
1272
1409
|
['operational', 'behavioral', 'business']
|
|
1273
1410
|
);
|
|
1274
|
-
throw
|
|
1411
|
+
throw err;
|
|
1275
1412
|
}
|
|
1276
1413
|
}
|
|
1277
1414
|
|
|
@@ -1308,68 +1445,370 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
1308
1445
|
* ```
|
|
1309
1446
|
*/
|
|
1310
1447
|
public async consultTransfer(
|
|
1311
|
-
consultTransferPayload
|
|
1448
|
+
consultTransferPayload?: ConsultTransferPayLoad
|
|
1312
1449
|
): Promise<TaskResponse> {
|
|
1313
1450
|
try {
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1451
|
+
// Get the destination agent ID using custom logic from participants data
|
|
1452
|
+
const destAgentId = getDestinationAgentId(
|
|
1453
|
+
this.data.interaction?.participants,
|
|
1454
|
+
this.data.agentId
|
|
1455
|
+
);
|
|
1319
1456
|
|
|
1320
|
-
//
|
|
1321
|
-
if (
|
|
1322
|
-
|
|
1323
|
-
|
|
1457
|
+
// Resolve the target id (queue consult transfers go to the accepted agent)
|
|
1458
|
+
if (!destAgentId) {
|
|
1459
|
+
throw new Error('No agent has accepted this queue consult yet');
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
LoggerProxy.info(
|
|
1463
|
+
`Initiating consult transfer to ${consultTransferPayload?.to || destAgentId}`,
|
|
1464
|
+
{
|
|
1465
|
+
module: TASK_FILE,
|
|
1466
|
+
method: METHODS.CONSULT_TRANSFER,
|
|
1467
|
+
interactionId: this.data.interactionId,
|
|
1324
1468
|
}
|
|
1469
|
+
);
|
|
1470
|
+
// Obtain payload based on desktop logic using TaskData
|
|
1471
|
+
const finalDestinationType = deriveConsultTransferDestinationType(this.data);
|
|
1325
1472
|
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
}
|
|
1473
|
+
// By default we always use the computed destAgentId as the target id
|
|
1474
|
+
const consultTransferRequest: ConsultTransferPayLoad = {
|
|
1475
|
+
to: destAgentId,
|
|
1476
|
+
destinationType: finalDestinationType,
|
|
1477
|
+
};
|
|
1332
1478
|
|
|
1333
1479
|
const result = await this.contact.consultTransfer({
|
|
1334
1480
|
interactionId: this.data.interactionId,
|
|
1335
|
-
data:
|
|
1481
|
+
data: consultTransferRequest,
|
|
1336
1482
|
});
|
|
1337
1483
|
|
|
1338
1484
|
this.metricsManager.trackEvent(
|
|
1339
1485
|
METRIC_EVENT_NAMES.TASK_TRANSFER_SUCCESS,
|
|
1340
1486
|
{
|
|
1341
1487
|
taskId: this.data.interactionId,
|
|
1342
|
-
destination:
|
|
1343
|
-
destinationType:
|
|
1488
|
+
destination: consultTransferRequest.to,
|
|
1489
|
+
destinationType: consultTransferRequest.destinationType,
|
|
1344
1490
|
isConsultTransfer: true,
|
|
1345
1491
|
...MetricsManager.getCommonTrackingFieldForAQMResponse(result),
|
|
1346
1492
|
},
|
|
1347
1493
|
['operational', 'behavioral', 'business']
|
|
1348
1494
|
);
|
|
1349
1495
|
|
|
1350
|
-
LoggerProxy.log(
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1496
|
+
LoggerProxy.log(
|
|
1497
|
+
`Consult transfer completed successfully to ${consultTransferPayload?.to || destAgentId}`,
|
|
1498
|
+
{
|
|
1499
|
+
module: TASK_FILE,
|
|
1500
|
+
method: METHODS.CONSULT_TRANSFER,
|
|
1501
|
+
trackingId: result.trackingId,
|
|
1502
|
+
interactionId: this.data.interactionId,
|
|
1503
|
+
}
|
|
1504
|
+
);
|
|
1356
1505
|
|
|
1357
1506
|
return result;
|
|
1358
1507
|
} catch (error) {
|
|
1359
|
-
const
|
|
1508
|
+
const err = generateTaskErrorObject(error, METHODS.CONSULT_TRANSFER, TASK_FILE);
|
|
1509
|
+
const taskErrorProps = {
|
|
1510
|
+
trackingId: err.data?.trackingId,
|
|
1511
|
+
errorMessage: err.data?.message,
|
|
1512
|
+
errorType: err.data?.errorType,
|
|
1513
|
+
errorData: err.data?.errorData,
|
|
1514
|
+
reasonCode: err.data?.reasonCode,
|
|
1515
|
+
};
|
|
1516
|
+
const failedDestinationType = deriveConsultTransferDestinationType(this.data);
|
|
1517
|
+
const failedDestAgentId = getDestinationAgentId(
|
|
1518
|
+
this.data.interaction?.participants,
|
|
1519
|
+
this.data.agentId
|
|
1520
|
+
);
|
|
1360
1521
|
this.metricsManager.trackEvent(
|
|
1361
1522
|
METRIC_EVENT_NAMES.TASK_TRANSFER_FAILED,
|
|
1362
1523
|
{
|
|
1363
1524
|
taskId: this.data.interactionId,
|
|
1364
|
-
destination:
|
|
1365
|
-
destinationType:
|
|
1525
|
+
destination: failedDestAgentId || '',
|
|
1526
|
+
destinationType: failedDestinationType,
|
|
1366
1527
|
isConsultTransfer: true,
|
|
1367
1528
|
error: error.toString(),
|
|
1529
|
+
...taskErrorProps,
|
|
1530
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details || {}),
|
|
1531
|
+
},
|
|
1532
|
+
['operational', 'behavioral', 'business']
|
|
1533
|
+
);
|
|
1534
|
+
throw err;
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
/**
|
|
1539
|
+
* Starts a consultation conference by merging the consultation call with the main call
|
|
1540
|
+
*
|
|
1541
|
+
* Creates a three-way conference between the agent, customer, and consulted party
|
|
1542
|
+
* Extracts required consultation data from the current task data
|
|
1543
|
+
* On success, emits a `task:conferenceStarted` event
|
|
1544
|
+
*
|
|
1545
|
+
* @returns Promise<TaskResponse> - Response from the consultation conference API
|
|
1546
|
+
* @throws Error if the operation fails or if consultation data is invalid
|
|
1547
|
+
*
|
|
1548
|
+
* @example
|
|
1549
|
+
* ```typescript
|
|
1550
|
+
* try {
|
|
1551
|
+
* await task.consultConference();
|
|
1552
|
+
* console.log('Conference started successfully');
|
|
1553
|
+
* } catch (error) {
|
|
1554
|
+
* console.error('Failed to start conference:', error);
|
|
1555
|
+
* }
|
|
1556
|
+
* ```
|
|
1557
|
+
*/
|
|
1558
|
+
public async consultConference(): Promise<TaskResponse> {
|
|
1559
|
+
// Extract consultation conference data from task data (used in both try and catch)
|
|
1560
|
+
const consultationData = {
|
|
1561
|
+
agentId: this.agentId,
|
|
1562
|
+
destAgentId: this.data.destAgentId,
|
|
1563
|
+
destinationType: this.data.destinationType || 'agent',
|
|
1564
|
+
};
|
|
1565
|
+
|
|
1566
|
+
try {
|
|
1567
|
+
LoggerProxy.info(`Initiating consult conference to ${consultationData.destAgentId}`, {
|
|
1568
|
+
module: TASK_FILE,
|
|
1569
|
+
method: METHODS.CONSULT_CONFERENCE,
|
|
1570
|
+
interactionId: this.data.interactionId,
|
|
1571
|
+
});
|
|
1572
|
+
|
|
1573
|
+
const paramsDataForConferenceV2 = buildConsultConferenceParamData(
|
|
1574
|
+
consultationData,
|
|
1575
|
+
this.data.interactionId
|
|
1576
|
+
);
|
|
1577
|
+
|
|
1578
|
+
const response = await this.contact.consultConference({
|
|
1579
|
+
interactionId: paramsDataForConferenceV2.interactionId,
|
|
1580
|
+
data: paramsDataForConferenceV2.data,
|
|
1581
|
+
});
|
|
1582
|
+
|
|
1583
|
+
// Track success metrics (following consultTransfer pattern)
|
|
1584
|
+
this.metricsManager.trackEvent(
|
|
1585
|
+
METRIC_EVENT_NAMES.TASK_CONFERENCE_START_SUCCESS,
|
|
1586
|
+
{
|
|
1587
|
+
taskId: this.data.interactionId,
|
|
1588
|
+
destination: paramsDataForConferenceV2.data.to,
|
|
1589
|
+
destinationType: paramsDataForConferenceV2.data.destinationType,
|
|
1590
|
+
agentId: paramsDataForConferenceV2.data.agentId,
|
|
1591
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponse(response),
|
|
1592
|
+
},
|
|
1593
|
+
['operational', 'behavioral', 'business']
|
|
1594
|
+
);
|
|
1595
|
+
|
|
1596
|
+
LoggerProxy.log(`Consult conference started successfully`, {
|
|
1597
|
+
module: TASK_FILE,
|
|
1598
|
+
method: METHODS.CONSULT_CONFERENCE,
|
|
1599
|
+
interactionId: this.data.interactionId,
|
|
1600
|
+
});
|
|
1601
|
+
|
|
1602
|
+
return response;
|
|
1603
|
+
} catch (error) {
|
|
1604
|
+
const err = generateTaskErrorObject(error, METHODS.CONSULT_CONFERENCE, TASK_FILE);
|
|
1605
|
+
const taskErrorProps = {
|
|
1606
|
+
trackingId: err.data?.trackingId,
|
|
1607
|
+
errorMessage: err.data?.message,
|
|
1608
|
+
errorType: err.data?.errorType,
|
|
1609
|
+
errorData: err.data?.errorData,
|
|
1610
|
+
reasonCode: err.data?.reasonCode,
|
|
1611
|
+
};
|
|
1612
|
+
|
|
1613
|
+
// Track failure metrics (following consultTransfer pattern)
|
|
1614
|
+
// Build conference data for error tracking using extracted data
|
|
1615
|
+
const failedParamsData = buildConsultConferenceParamData(
|
|
1616
|
+
consultationData,
|
|
1617
|
+
this.data.interactionId
|
|
1618
|
+
);
|
|
1619
|
+
|
|
1620
|
+
this.metricsManager.trackEvent(
|
|
1621
|
+
METRIC_EVENT_NAMES.TASK_CONFERENCE_START_FAILED,
|
|
1622
|
+
{
|
|
1623
|
+
taskId: this.data.interactionId,
|
|
1624
|
+
destination: failedParamsData.data.to,
|
|
1625
|
+
destinationType: failedParamsData.data.destinationType,
|
|
1626
|
+
agentId: failedParamsData.data.agentId,
|
|
1627
|
+
error: error.toString(),
|
|
1628
|
+
...taskErrorProps,
|
|
1368
1629
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details || {}),
|
|
1369
1630
|
},
|
|
1370
1631
|
['operational', 'behavioral', 'business']
|
|
1371
1632
|
);
|
|
1372
|
-
|
|
1633
|
+
|
|
1634
|
+
LoggerProxy.error(`Failed to start consult conference`, {
|
|
1635
|
+
module: TASK_FILE,
|
|
1636
|
+
method: METHODS.CONSULT_CONFERENCE,
|
|
1637
|
+
interactionId: this.data.interactionId,
|
|
1638
|
+
});
|
|
1639
|
+
|
|
1640
|
+
throw err;
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1643
|
+
|
|
1644
|
+
/**
|
|
1645
|
+
* Exits the current conference by removing the agent from the conference call
|
|
1646
|
+
*
|
|
1647
|
+
* Exits the agent from the conference, leaving the customer and consulted party connected
|
|
1648
|
+
* On success, emits a `task:conferenceEnded` event
|
|
1649
|
+
*
|
|
1650
|
+
* @returns Promise<TaskResponse> - Response from the conference exit API
|
|
1651
|
+
* @throws Error if the operation fails or if no active conference exists
|
|
1652
|
+
*
|
|
1653
|
+
* @example
|
|
1654
|
+
* ```typescript
|
|
1655
|
+
* try {
|
|
1656
|
+
* await task.exitConference();
|
|
1657
|
+
* console.log('Successfully exited conference');
|
|
1658
|
+
* } catch (error) {
|
|
1659
|
+
* console.error('Failed to exit conference:', error);
|
|
1660
|
+
* }
|
|
1661
|
+
* ```
|
|
1662
|
+
*/
|
|
1663
|
+
public async exitConference(): Promise<TaskResponse> {
|
|
1664
|
+
try {
|
|
1665
|
+
LoggerProxy.info(`Exiting consult conference`, {
|
|
1666
|
+
module: TASK_FILE,
|
|
1667
|
+
method: METHODS.EXIT_CONFERENCE,
|
|
1668
|
+
interactionId: this.data.interactionId,
|
|
1669
|
+
});
|
|
1670
|
+
|
|
1671
|
+
// Validate that interaction ID exists
|
|
1672
|
+
if (!this.data.interactionId) {
|
|
1673
|
+
throw new Error('Invalid interaction ID');
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1676
|
+
const response = await this.contact.exitConference({
|
|
1677
|
+
interactionId: this.data.interactionId,
|
|
1678
|
+
});
|
|
1679
|
+
|
|
1680
|
+
// Track success metrics (following consultTransfer pattern)
|
|
1681
|
+
this.metricsManager.trackEvent(
|
|
1682
|
+
METRIC_EVENT_NAMES.TASK_CONFERENCE_END_SUCCESS,
|
|
1683
|
+
{
|
|
1684
|
+
taskId: this.data.interactionId,
|
|
1685
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponse(response),
|
|
1686
|
+
},
|
|
1687
|
+
['operational', 'behavioral', 'business']
|
|
1688
|
+
);
|
|
1689
|
+
|
|
1690
|
+
LoggerProxy.log(`Consult conference exited successfully`, {
|
|
1691
|
+
module: TASK_FILE,
|
|
1692
|
+
method: METHODS.EXIT_CONFERENCE,
|
|
1693
|
+
interactionId: this.data.interactionId,
|
|
1694
|
+
});
|
|
1695
|
+
|
|
1696
|
+
return response;
|
|
1697
|
+
} catch (error) {
|
|
1698
|
+
const err = generateTaskErrorObject(error, METHODS.EXIT_CONFERENCE, TASK_FILE);
|
|
1699
|
+
const taskErrorProps = {
|
|
1700
|
+
trackingId: err.data?.trackingId,
|
|
1701
|
+
errorMessage: err.data?.message,
|
|
1702
|
+
errorType: err.data?.errorType,
|
|
1703
|
+
errorData: err.data?.errorData,
|
|
1704
|
+
reasonCode: err.data?.reasonCode,
|
|
1705
|
+
};
|
|
1706
|
+
|
|
1707
|
+
// Track failure metrics (following consultTransfer pattern)
|
|
1708
|
+
this.metricsManager.trackEvent(
|
|
1709
|
+
METRIC_EVENT_NAMES.TASK_CONFERENCE_END_FAILED,
|
|
1710
|
+
{
|
|
1711
|
+
taskId: this.data.interactionId,
|
|
1712
|
+
error: error.toString(),
|
|
1713
|
+
...taskErrorProps,
|
|
1714
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details || {}),
|
|
1715
|
+
},
|
|
1716
|
+
['operational', 'behavioral', 'business']
|
|
1717
|
+
);
|
|
1718
|
+
|
|
1719
|
+
LoggerProxy.error(`Failed to exit consult conference`, {
|
|
1720
|
+
module: TASK_FILE,
|
|
1721
|
+
method: METHODS.EXIT_CONFERENCE,
|
|
1722
|
+
interactionId: this.data.interactionId,
|
|
1723
|
+
});
|
|
1724
|
+
|
|
1725
|
+
throw err;
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
/**
|
|
1730
|
+
* Transfers the current conference to another agent
|
|
1731
|
+
*
|
|
1732
|
+
* Moves the entire conference (including all participants) to a new agent,
|
|
1733
|
+
* while the current agent exits and goes to wrapup
|
|
1734
|
+
* On success, the current agent receives `task:conferenceEnded` event
|
|
1735
|
+
*
|
|
1736
|
+
* @returns Promise<TaskResponse> - Response from the conference transfer API
|
|
1737
|
+
* @throws Error if the operation fails or if no active conference exists
|
|
1738
|
+
*
|
|
1739
|
+
* @example
|
|
1740
|
+
* ```typescript
|
|
1741
|
+
* try {
|
|
1742
|
+
* await task.transferConference();
|
|
1743
|
+
* console.log('Conference transferred successfully');
|
|
1744
|
+
* } catch (error) {
|
|
1745
|
+
* console.error('Failed to transfer conference:', error);
|
|
1746
|
+
* }
|
|
1747
|
+
* ```
|
|
1748
|
+
*/
|
|
1749
|
+
public async transferConference(): Promise<TaskResponse> {
|
|
1750
|
+
try {
|
|
1751
|
+
LoggerProxy.info(`Transferring conference`, {
|
|
1752
|
+
module: TASK_FILE,
|
|
1753
|
+
method: METHODS.TRANSFER_CONFERENCE,
|
|
1754
|
+
interactionId: this.data.interactionId,
|
|
1755
|
+
});
|
|
1756
|
+
|
|
1757
|
+
// Validate that interaction ID exists
|
|
1758
|
+
if (!this.data.interactionId) {
|
|
1759
|
+
throw new Error('Invalid interaction ID');
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
const response = await this.contact.conferenceTransfer({
|
|
1763
|
+
interactionId: this.data.interactionId,
|
|
1764
|
+
});
|
|
1765
|
+
|
|
1766
|
+
// Track success metrics (following consultTransfer pattern)
|
|
1767
|
+
this.metricsManager.trackEvent(
|
|
1768
|
+
METRIC_EVENT_NAMES.TASK_CONFERENCE_TRANSFER_SUCCESS,
|
|
1769
|
+
{
|
|
1770
|
+
taskId: this.data.interactionId,
|
|
1771
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponse(response),
|
|
1772
|
+
},
|
|
1773
|
+
['operational', 'behavioral', 'business']
|
|
1774
|
+
);
|
|
1775
|
+
|
|
1776
|
+
LoggerProxy.log(`Conference transferred successfully`, {
|
|
1777
|
+
module: TASK_FILE,
|
|
1778
|
+
method: METHODS.TRANSFER_CONFERENCE,
|
|
1779
|
+
interactionId: this.data.interactionId,
|
|
1780
|
+
});
|
|
1781
|
+
|
|
1782
|
+
return response;
|
|
1783
|
+
} catch (error) {
|
|
1784
|
+
const err = generateTaskErrorObject(error, METHODS.TRANSFER_CONFERENCE, TASK_FILE);
|
|
1785
|
+
const taskErrorProps = {
|
|
1786
|
+
trackingId: err.data?.trackingId,
|
|
1787
|
+
errorMessage: err.data?.message,
|
|
1788
|
+
errorType: err.data?.errorType,
|
|
1789
|
+
errorData: err.data?.errorData,
|
|
1790
|
+
reasonCode: err.data?.reasonCode,
|
|
1791
|
+
};
|
|
1792
|
+
|
|
1793
|
+
// Track failure metrics (following consultTransfer pattern)
|
|
1794
|
+
this.metricsManager.trackEvent(
|
|
1795
|
+
METRIC_EVENT_NAMES.TASK_CONFERENCE_TRANSFER_FAILED,
|
|
1796
|
+
{
|
|
1797
|
+
taskId: this.data.interactionId,
|
|
1798
|
+
error: error.toString(),
|
|
1799
|
+
...taskErrorProps,
|
|
1800
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details || {}),
|
|
1801
|
+
},
|
|
1802
|
+
['operational', 'behavioral', 'business']
|
|
1803
|
+
);
|
|
1804
|
+
|
|
1805
|
+
LoggerProxy.error(`Failed to transfer conference`, {
|
|
1806
|
+
module: TASK_FILE,
|
|
1807
|
+
method: METHODS.TRANSFER_CONFERENCE,
|
|
1808
|
+
interactionId: this.data.interactionId,
|
|
1809
|
+
});
|
|
1810
|
+
|
|
1811
|
+
throw err;
|
|
1373
1812
|
}
|
|
1374
1813
|
}
|
|
1375
1814
|
}
|