@webex/contact-center 3.9.0-next.9 → 3.10.0-next.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 +182 -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/behavioral-events.js +89 -0
- package/dist/metrics/behavioral-events.js.map +1 -1
- package/dist/metrics/constants.js +30 -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/Utils.js +42 -1
- package/dist/services/core/Utils.js.map +1 -1
- package/dist/services/task/TaskManager.js +113 -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 +273 -16
- 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 +24 -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/Utils.d.ts +14 -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 +84 -3
- 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 +9 -8
- package/src/cc.ts +206 -52
- package/src/constants.ts +1 -0
- package/src/index.ts +16 -2
- package/src/logger-proxy.ts +24 -1
- package/src/metrics/behavioral-events.ts +94 -0
- package/src/metrics/constants.ts +34 -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/Utils.ts +44 -0
- package/src/services/task/TaskManager.ts +122 -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 +338 -15
- 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/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/task/TaskManager.ts +382 -0
- 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 +359 -8
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
|
@@ -5,11 +5,12 @@ import {
|
|
|
5
5
|
generateTaskErrorObject,
|
|
6
6
|
deriveConsultTransferDestinationType,
|
|
7
7
|
getDestinationAgentId,
|
|
8
|
+
buildConsultConferenceParamData,
|
|
8
9
|
} from '../core/Utils';
|
|
9
10
|
import {Failure} from '../core/GlobalTypes';
|
|
10
11
|
import {LoginOption} from '../../types';
|
|
11
12
|
import {TASK_FILE} from '../../constants';
|
|
12
|
-
import {METHODS} from './constants';
|
|
13
|
+
import {METHODS, KEYS_TO_NOT_DELETE} from './constants';
|
|
13
14
|
import routingContact from './contact';
|
|
14
15
|
import LoggerProxy from '../../logger-proxy';
|
|
15
16
|
import {
|
|
@@ -138,6 +139,7 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
138
139
|
public webCallMap: Record<TaskId, CallId>;
|
|
139
140
|
private wrapupData: WrapupData;
|
|
140
141
|
public autoWrapup?: AutoWrapup;
|
|
142
|
+
private agentId: string;
|
|
141
143
|
|
|
142
144
|
/**
|
|
143
145
|
* Creates a new Task instance which provides the following features:
|
|
@@ -150,7 +152,8 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
150
152
|
contact: ReturnType<typeof routingContact>,
|
|
151
153
|
webCallingService: WebCallingService,
|
|
152
154
|
data: TaskData,
|
|
153
|
-
wrapupData: WrapupData
|
|
155
|
+
wrapupData: WrapupData,
|
|
156
|
+
agentId: string
|
|
154
157
|
) {
|
|
155
158
|
super();
|
|
156
159
|
this.contact = contact;
|
|
@@ -161,6 +164,7 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
161
164
|
this.metricsManager = MetricsManager.getInstance();
|
|
162
165
|
this.registerWebCallListeners();
|
|
163
166
|
this.setupAutoWrapupTimer();
|
|
167
|
+
this.agentId = agentId;
|
|
164
168
|
}
|
|
165
169
|
|
|
166
170
|
/**
|
|
@@ -277,9 +281,24 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
277
281
|
* @private
|
|
278
282
|
*/
|
|
279
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
|
|
280
292
|
Object.keys(newData).forEach((key) => {
|
|
281
|
-
if (
|
|
282
|
-
|
|
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]);
|
|
283
302
|
} else {
|
|
284
303
|
oldData[key] = newData[key];
|
|
285
304
|
}
|
|
@@ -507,6 +526,7 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
507
526
|
* Puts the current task/interaction on hold.
|
|
508
527
|
* Emits task:hold event when successful. For voice tasks, this mutes the audio.
|
|
509
528
|
*
|
|
529
|
+
* @param mediaResourceId - Optional media resource ID to use for the hold operation. If not provided, uses the task's current mediaResourceId
|
|
510
530
|
* @returns Promise<TaskResponse>
|
|
511
531
|
* @throws Error if hold operation fails
|
|
512
532
|
* @example
|
|
@@ -527,9 +547,17 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
527
547
|
* console.error('Failed to place task on hold:', error);
|
|
528
548
|
* // Handle error (e.g., show error message, reset UI state)
|
|
529
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
|
+
* }
|
|
530
558
|
* ```
|
|
531
559
|
*/
|
|
532
|
-
public async hold(): Promise<TaskResponse> {
|
|
560
|
+
public async hold(mediaResourceId?: string): Promise<TaskResponse> {
|
|
533
561
|
try {
|
|
534
562
|
LoggerProxy.info(`Holding task`, {
|
|
535
563
|
module: TASK_FILE,
|
|
@@ -542,9 +570,11 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
542
570
|
METRIC_EVENT_NAMES.TASK_HOLD_FAILED,
|
|
543
571
|
]);
|
|
544
572
|
|
|
573
|
+
const effectiveMediaResourceId = mediaResourceId ?? this.data.mediaResourceId;
|
|
574
|
+
|
|
545
575
|
const response = await this.contact.hold({
|
|
546
576
|
interactionId: this.data.interactionId,
|
|
547
|
-
data: {mediaResourceId:
|
|
577
|
+
data: {mediaResourceId: effectiveMediaResourceId},
|
|
548
578
|
});
|
|
549
579
|
|
|
550
580
|
this.metricsManager.trackEvent(
|
|
@@ -552,7 +582,7 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
552
582
|
{
|
|
553
583
|
...MetricsManager.getCommonTrackingFieldForAQMResponse(response),
|
|
554
584
|
taskId: this.data.interactionId,
|
|
555
|
-
mediaResourceId:
|
|
585
|
+
mediaResourceId: effectiveMediaResourceId,
|
|
556
586
|
},
|
|
557
587
|
['operational', 'behavioral']
|
|
558
588
|
);
|
|
@@ -574,11 +604,13 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
574
604
|
errorData: err.data?.errorData,
|
|
575
605
|
reasonCode: err.data?.reasonCode,
|
|
576
606
|
};
|
|
607
|
+
const effectiveMediaResourceId = mediaResourceId ?? this.data.mediaResourceId;
|
|
608
|
+
|
|
577
609
|
this.metricsManager.trackEvent(
|
|
578
610
|
METRIC_EVENT_NAMES.TASK_HOLD_FAILED,
|
|
579
611
|
{
|
|
580
612
|
taskId: this.data.interactionId,
|
|
581
|
-
mediaResourceId:
|
|
613
|
+
mediaResourceId: effectiveMediaResourceId,
|
|
582
614
|
error: error.toString(),
|
|
583
615
|
...taskErrorProps,
|
|
584
616
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details || {}),
|
|
@@ -593,6 +625,7 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
593
625
|
* Resumes the task/interaction that was previously put on hold.
|
|
594
626
|
* Emits task:resume event when successful. For voice tasks, this restores the audio.
|
|
595
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
|
|
596
629
|
* @returns Promise<TaskResponse>
|
|
597
630
|
* @throws Error if resume operation fails
|
|
598
631
|
* @example
|
|
@@ -613,9 +646,17 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
613
646
|
* console.error('Failed to resume task:', error);
|
|
614
647
|
* // Handle error (e.g., show error message)
|
|
615
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
|
+
* }
|
|
616
657
|
* ```
|
|
617
658
|
*/
|
|
618
|
-
public async resume(): Promise<TaskResponse> {
|
|
659
|
+
public async resume(mediaResourceId?: string): Promise<TaskResponse> {
|
|
619
660
|
try {
|
|
620
661
|
LoggerProxy.info(`Resuming task`, {
|
|
621
662
|
module: TASK_FILE,
|
|
@@ -623,7 +664,9 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
623
664
|
interactionId: this.data.interactionId,
|
|
624
665
|
});
|
|
625
666
|
const {mainInteractionId} = this.data.interaction;
|
|
626
|
-
const
|
|
667
|
+
const defaultMediaResourceId =
|
|
668
|
+
this.data.interaction.media[mainInteractionId]?.mediaResourceId;
|
|
669
|
+
const effectiveMediaResourceId = mediaResourceId ?? defaultMediaResourceId;
|
|
627
670
|
|
|
628
671
|
this.metricsManager.timeEvent([
|
|
629
672
|
METRIC_EVENT_NAMES.TASK_RESUME_SUCCESS,
|
|
@@ -632,7 +675,7 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
632
675
|
|
|
633
676
|
const response = await this.contact.unHold({
|
|
634
677
|
interactionId: this.data.interactionId,
|
|
635
|
-
data: {mediaResourceId},
|
|
678
|
+
data: {mediaResourceId: effectiveMediaResourceId},
|
|
636
679
|
});
|
|
637
680
|
|
|
638
681
|
this.metricsManager.trackEvent(
|
|
@@ -640,7 +683,7 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
640
683
|
{
|
|
641
684
|
taskId: this.data.interactionId,
|
|
642
685
|
mainInteractionId,
|
|
643
|
-
mediaResourceId,
|
|
686
|
+
mediaResourceId: effectiveMediaResourceId,
|
|
644
687
|
...MetricsManager.getCommonTrackingFieldForAQMResponse(response),
|
|
645
688
|
},
|
|
646
689
|
['operational', 'behavioral']
|
|
@@ -657,6 +700,11 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
657
700
|
} catch (error) {
|
|
658
701
|
const err = generateTaskErrorObject(error, METHODS.RESUME, TASK_FILE);
|
|
659
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
|
+
|
|
660
708
|
const taskErrorProps = {
|
|
661
709
|
trackingId: err.data?.trackingId,
|
|
662
710
|
errorMessage: err.data?.message,
|
|
@@ -669,9 +717,7 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
669
717
|
{
|
|
670
718
|
taskId: this.data.interactionId,
|
|
671
719
|
mainInteractionId,
|
|
672
|
-
mediaResourceId:
|
|
673
|
-
? this.data.interaction.media[mainInteractionId].mediaResourceId
|
|
674
|
-
: '',
|
|
720
|
+
mediaResourceId: effectiveMediaResourceId,
|
|
675
721
|
...taskErrorProps,
|
|
676
722
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details || {}),
|
|
677
723
|
},
|
|
@@ -1488,4 +1534,281 @@ export default class Task extends EventEmitter implements ITask {
|
|
|
1488
1534
|
throw err;
|
|
1489
1535
|
}
|
|
1490
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,
|
|
1629
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details || {}),
|
|
1630
|
+
},
|
|
1631
|
+
['operational', 'behavioral', 'business']
|
|
1632
|
+
);
|
|
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;
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1491
1814
|
}
|