@webex/contact-center 3.12.0-llmrefactor.2 → 3.12.0-llmrefactor.3
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/.sdd/manifest.json +5 -4
- package/ai-docs/ARCHITECTURE.md +1 -1
- package/ai-docs/CONTRACTS.md +5 -1
- package/ai-docs/SECURITY.md +1 -1
- package/ai-docs/contact-center-spec.md +22 -4
- package/ai-docs/features/consult-transfer-list-policy/spec/feature-spec.md +362 -0
- package/dist/cc.js +440 -10
- package/dist/cc.js.map +1 -1
- package/dist/config.js +7 -0
- package/dist/config.js.map +1 -1
- package/dist/constants.js +10 -2
- package/dist/constants.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/metrics/behavioral-events.js +13 -0
- package/dist/metrics/behavioral-events.js.map +1 -1
- package/dist/metrics/constants.js +2 -0
- package/dist/metrics/constants.js.map +1 -1
- package/dist/services/AddressBook.js +18 -15
- package/dist/services/AddressBook.js.map +1 -1
- package/dist/services/AnswerCallOnWebexService.js +174 -0
- package/dist/services/AnswerCallOnWebexService.js.map +1 -0
- package/dist/services/EntryPoint.js +46 -68
- package/dist/services/EntryPoint.js.map +1 -1
- package/dist/services/Queue.js +27 -22
- package/dist/services/Queue.js.map +1 -1
- package/dist/services/WebexCrossClientService.js +171 -0
- package/dist/services/WebexCrossClientService.js.map +1 -0
- package/dist/services/WxAppTelephonyMercurySync.js +93 -0
- package/dist/services/WxAppTelephonyMercurySync.js.map +1 -0
- package/dist/services/config/Util.js +3 -0
- package/dist/services/config/Util.js.map +1 -1
- package/dist/services/config/constants.js +10 -6
- package/dist/services/config/constants.js.map +1 -1
- package/dist/services/config/types.js +4 -0
- package/dist/services/config/types.js.map +1 -1
- package/dist/services/core/Err.js.map +1 -1
- package/dist/services/core/WebexRequest.js +6 -2
- package/dist/services/core/WebexRequest.js.map +1 -1
- package/dist/services/core/aqm-reqs.js +28 -14
- package/dist/services/core/aqm-reqs.js.map +1 -1
- package/dist/services/core/types.js.map +1 -1
- package/dist/services/task/Task.js +73 -7
- package/dist/services/task/Task.js.map +1 -1
- package/dist/services/task/TaskFactory.js +8 -4
- package/dist/services/task/TaskFactory.js.map +1 -1
- package/dist/services/task/TaskManager.js +176 -20
- package/dist/services/task/TaskManager.js.map +1 -1
- package/dist/services/task/WebexCallingUtils.js +70 -0
- package/dist/services/task/WebexCallingUtils.js.map +1 -0
- package/dist/services/task/constants.js +4 -1
- package/dist/services/task/constants.js.map +1 -1
- package/dist/services/task/contact.js +29 -0
- package/dist/services/task/contact.js.map +1 -1
- package/dist/services/task/digital/Digital.js +3 -2
- package/dist/services/task/digital/Digital.js.map +1 -1
- package/dist/services/task/state-machine/TaskStateMachine.js +135 -37
- package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -1
- package/dist/services/task/state-machine/actions.js +6 -1
- package/dist/services/task/state-machine/actions.js.map +1 -1
- package/dist/services/task/state-machine/guards.js +38 -11
- package/dist/services/task/state-machine/guards.js.map +1 -1
- package/dist/services/task/state-machine/types.js.map +1 -1
- package/dist/services/task/state-machine/uiControlsComputer.js +118 -18
- package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -1
- package/dist/services/task/types.js +16 -1
- package/dist/services/task/types.js.map +1 -1
- package/dist/services/task/voice/Voice.js +350 -14
- package/dist/services/task/voice/Voice.js.map +1 -1
- package/dist/services/task/voice/WebRTC.js +4 -1
- package/dist/services/task/voice/WebRTC.js.map +1 -1
- package/dist/services/task/voice/wxAppVoiceMethods.js +201 -0
- package/dist/services/task/voice/wxAppVoiceMethods.js.map +1 -0
- package/dist/services/wxAppTelephonyUtils.js +19 -0
- package/dist/services/wxAppTelephonyUtils.js.map +1 -0
- package/dist/types/cc.d.ts +77 -4
- package/dist/types/config.d.ts +7 -0
- package/dist/types/constants.d.ts +8 -0
- package/dist/types/index.d.ts +3 -1
- package/dist/types/metrics/constants.d.ts +2 -0
- package/dist/types/services/AddressBook.d.ts +2 -1
- package/dist/types/services/AnswerCallOnWebexService.d.ts +37 -0
- package/dist/types/services/EntryPoint.d.ts +7 -5
- package/dist/types/services/Queue.d.ts +5 -3
- package/dist/types/services/WebexCrossClientService.d.ts +28 -0
- package/dist/types/services/WxAppTelephonyMercurySync.d.ts +28 -0
- package/dist/types/services/config/constants.d.ts +8 -5
- package/dist/types/services/config/types.d.ts +17 -4
- package/dist/types/services/core/Err.d.ts +2 -0
- package/dist/types/services/core/WebexRequest.d.ts +1 -0
- package/dist/types/services/core/types.d.ts +2 -0
- package/dist/types/services/task/Task.d.ts +20 -2
- package/dist/types/services/task/TaskFactory.d.ts +2 -1
- package/dist/types/services/task/WebexCallingUtils.d.ts +11 -0
- package/dist/types/services/task/constants.d.ts +3 -0
- package/dist/types/services/task/contact.d.ts +4 -0
- package/dist/types/services/task/digital/Digital.d.ts +2 -2
- package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +260 -56
- package/dist/types/services/task/state-machine/guards.d.ts +6 -5
- package/dist/types/services/task/state-machine/types.d.ts +9 -1
- package/dist/types/services/task/types.d.ts +81 -4
- package/dist/types/services/task/voice/Voice.d.ts +48 -9
- package/dist/types/services/task/voice/WebRTC.d.ts +2 -2
- package/dist/types/services/task/voice/wxAppVoiceMethods.d.ts +52 -0
- package/dist/types/services/wxAppTelephonyUtils.d.ts +5 -0
- package/dist/types/types.d.ts +14 -8
- package/dist/types/utils/PageCache.d.ts +20 -3
- package/dist/types.js +7 -2
- package/dist/types.js.map +1 -1
- package/dist/utils/PageCache.js +19 -5
- package/dist/utils/PageCache.js.map +1 -1
- package/dist/webex.js +1 -1
- package/package.json +1 -1
- package/src/cc.ts +506 -9
- package/src/config.ts +7 -0
- package/src/constants.ts +8 -0
- package/src/index.ts +2 -0
- package/src/metrics/ai-docs/metrics-spec.md +9 -3
- package/src/metrics/behavioral-events.ts +14 -0
- package/src/metrics/constants.ts +2 -0
- package/src/services/AddressBook.ts +17 -6
- package/src/services/AnswerCallOnWebexService.ts +206 -0
- package/src/services/EntryPoint.ts +59 -60
- package/src/services/Queue.ts +29 -12
- package/src/services/WebexCrossClientService.ts +212 -0
- package/src/services/WxAppTelephonyMercurySync.ts +115 -0
- package/src/services/ai-docs/AGENTS.md +10 -10
- package/src/services/ai-docs/services-spec.md +6 -1
- package/src/services/config/Util.ts +3 -0
- package/src/services/config/ai-docs/AGENTS.md +1 -1
- package/src/services/config/ai-docs/ARCHITECTURE.md +2 -2
- package/src/services/config/ai-docs/config-spec.md +6 -0
- package/src/services/config/constants.ts +10 -6
- package/src/services/config/types.ts +16 -4
- package/src/services/core/Err.ts +1 -0
- package/src/services/core/WebexRequest.ts +3 -1
- package/src/services/core/ai-docs/core-spec.md +5 -1
- package/src/services/core/aqm-reqs.ts +30 -15
- package/src/services/core/types.ts +2 -0
- package/src/services/task/Task.ts +79 -8
- package/src/services/task/TaskFactory.ts +8 -3
- package/src/services/task/TaskManager.ts +254 -15
- package/src/services/task/WebexCallingUtils.ts +136 -0
- package/src/services/task/ai-docs/ARCHITECTURE.md +1 -0
- package/src/services/task/ai-docs/task-spec.md +117 -2
- package/src/services/task/constants.ts +3 -0
- package/src/services/task/contact.ts +30 -0
- package/src/services/task/digital/Digital.ts +4 -2
- package/src/services/task/state-machine/TaskStateMachine.ts +210 -63
- package/src/services/task/state-machine/actions.ts +5 -2
- package/src/services/task/state-machine/ai-docs/AGENTS.md +8 -4
- package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +17 -8
- package/src/services/task/state-machine/ai-docs/task-state-machine-spec.md +46 -22
- package/src/services/task/state-machine/guards.ts +64 -11
- package/src/services/task/state-machine/types.ts +16 -1
- package/src/services/task/state-machine/uiControlsComputer.ts +206 -32
- package/src/services/task/types.ts +114 -4
- package/src/services/task/voice/Voice.ts +462 -12
- package/src/services/task/voice/WebRTC.ts +5 -1
- package/src/services/task/voice/wxAppVoiceMethods.ts +307 -0
- package/src/services/wxAppTelephonyUtils.ts +14 -0
- package/src/types.ts +33 -9
- package/src/utils/AGENTS.md +21 -10
- package/src/utils/PageCache.ts +38 -5
- package/src/utils/ai-docs/utils-spec.md +21 -11
- package/test/unit/spec/cc.ts +1274 -0
- package/test/unit/spec/metrics/behavioral-events.ts +18 -0
- package/test/unit/spec/services/AddressBook.ts +37 -6
- package/test/unit/spec/services/AnswerCallOnWebexService.ts +223 -0
- package/test/unit/spec/services/EntryPoint.ts +87 -40
- package/test/unit/spec/services/Queue.ts +123 -12
- package/test/unit/spec/services/WebexCrossClientService.ts +261 -0
- package/test/unit/spec/services/WxAppTelephonyMercurySync.ts +113 -0
- package/test/unit/spec/services/config/Util.ts +85 -0
- package/test/unit/spec/services/core/WebexRequest.ts +3 -1
- package/test/unit/spec/services/core/aqm-reqs.ts +113 -1
- package/test/unit/spec/services/task/Task.ts +200 -0
- package/test/unit/spec/services/task/TaskFactory.ts +39 -2
- package/test/unit/spec/services/task/TaskManager.ts +653 -1
- package/test/unit/spec/services/task/WebexCallingUtils.ts +153 -0
- package/test/unit/spec/services/task/contact.ts +33 -0
- package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +854 -72
- package/test/unit/spec/services/task/state-machine/guards.ts +210 -8
- package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +445 -7
- package/test/unit/spec/services/task/voice/Voice.ts +874 -0
- package/test/unit/spec/services/task/voice/wxAppVoiceMethods.ts +459 -0
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
|
+
CONSULT_TRANSFER_DESTINATION_TYPE,
|
|
6
7
|
InteractionUIControls,
|
|
7
8
|
TASK_CHANNEL_TYPE,
|
|
8
9
|
TaskData,
|
|
@@ -11,6 +12,10 @@ import {
|
|
|
11
12
|
VOICE_VARIANT,
|
|
12
13
|
} from '../types';
|
|
13
14
|
import {TaskContext, UIControlConfig} from './types';
|
|
15
|
+
import {
|
|
16
|
+
getWebexCallingDeviceDetailsForAgent,
|
|
17
|
+
isWxAppEngagedForControls,
|
|
18
|
+
} from '../WebexCallingUtils';
|
|
14
19
|
import {TaskState, MAX_PARTICIPANTS_IN_MULTIPARTY_CONFERENCE, INTERACTION_STATE} from './constants';
|
|
15
20
|
import {
|
|
16
21
|
getIsCustomerInCall,
|
|
@@ -20,11 +25,41 @@ import {
|
|
|
20
25
|
getIsConsultedAgentForControls,
|
|
21
26
|
getServerHoldStateForControls,
|
|
22
27
|
} from '../TaskUtils';
|
|
28
|
+
import {INBOUND_DIRECTION, OUTDIAL_DIRECTION} from '../../../constants';
|
|
29
|
+
import {COLLABORATION_ACCESS} from '../../config/constants';
|
|
30
|
+
|
|
31
|
+
type DestinationControls = TaskUIControls['consultTransferDestinations'];
|
|
23
32
|
|
|
24
33
|
const DISABLED = {isVisible: false, isEnabled: false} as const;
|
|
25
34
|
const VISIBLE_ENABLED = {isVisible: true, isEnabled: true} as const;
|
|
26
35
|
const VISIBLE_DISABLED = {isVisible: true, isEnabled: false} as const;
|
|
27
36
|
|
|
37
|
+
/** wxApp telephony controls live on the main leg only (mute/keypad via wxApp APIs). */
|
|
38
|
+
function withWxAppTelephonyControls(
|
|
39
|
+
controls: InteractionUIControls,
|
|
40
|
+
isWxAppEngaged: boolean,
|
|
41
|
+
currentLeg: TaskUILeg,
|
|
42
|
+
isWrappingUp: boolean
|
|
43
|
+
): InteractionUIControls {
|
|
44
|
+
if (!isWxAppEngaged || isWrappingUp) {
|
|
45
|
+
return controls;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (currentLeg === 'main') {
|
|
49
|
+
return {
|
|
50
|
+
...controls,
|
|
51
|
+
mute: VISIBLE_ENABLED,
|
|
52
|
+
keypad: VISIBLE_ENABLED,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
...controls,
|
|
58
|
+
mute: DISABLED,
|
|
59
|
+
keypad: DISABLED,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
28
63
|
function getDefaultInteractionUIControls(): InteractionUIControls {
|
|
29
64
|
return {
|
|
30
65
|
accept: DISABLED,
|
|
@@ -43,18 +78,24 @@ function getDefaultInteractionUIControls(): InteractionUIControls {
|
|
|
43
78
|
transferConference: DISABLED,
|
|
44
79
|
mergeToConference: DISABLED,
|
|
45
80
|
switch: DISABLED,
|
|
81
|
+
keypad: DISABLED,
|
|
46
82
|
};
|
|
47
83
|
}
|
|
48
84
|
|
|
49
85
|
function createTaskUIControls(
|
|
50
86
|
main: InteractionUIControls,
|
|
51
87
|
consult: InteractionUIControls,
|
|
52
|
-
activeLeg: TaskUILeg
|
|
88
|
+
activeLeg: TaskUILeg,
|
|
89
|
+
consultTransferDestinations: DestinationControls = {
|
|
90
|
+
consult: [],
|
|
91
|
+
transfer: [],
|
|
92
|
+
}
|
|
53
93
|
): TaskUIControls {
|
|
54
94
|
return {
|
|
55
95
|
main,
|
|
56
96
|
consult,
|
|
57
97
|
activeLeg,
|
|
98
|
+
consultTransferDestinations,
|
|
58
99
|
};
|
|
59
100
|
}
|
|
60
101
|
|
|
@@ -66,6 +107,53 @@ export function getDefaultUIControls(): TaskUIControls {
|
|
|
66
107
|
);
|
|
67
108
|
}
|
|
68
109
|
|
|
110
|
+
function getConsultTransferDestinations(
|
|
111
|
+
config: UIControlConfig,
|
|
112
|
+
taskData?: TaskData | null
|
|
113
|
+
): DestinationControls {
|
|
114
|
+
const destinationConfig = config.consultTransferConfig;
|
|
115
|
+
if (!destinationConfig) {
|
|
116
|
+
return {consult: [], transfer: []};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const isVoice = config.channelType === TASK_CHANNEL_TYPE.VOICE;
|
|
120
|
+
const interaction = taskData?.interaction;
|
|
121
|
+
const direction = interaction?.contactDirection?.type?.toUpperCase();
|
|
122
|
+
const destinations: DestinationControls = {
|
|
123
|
+
consult: [],
|
|
124
|
+
transfer: [],
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
if (destinationConfig.accessBuddyTeam?.toUpperCase() !== COLLABORATION_ACCESS.NONE) {
|
|
128
|
+
destinations.consult.push(CONSULT_TRANSFER_DESTINATION_TYPE.AGENT);
|
|
129
|
+
destinations.transfer.push(CONSULT_TRANSFER_DESTINATION_TYPE.AGENT);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (destinationConfig.accessQueue?.toUpperCase() !== COLLABORATION_ACCESS.NONE) {
|
|
133
|
+
const canConsultQueue = !isVoice || destinationConfig.allowConsultToQueue;
|
|
134
|
+
const canTransferQueue =
|
|
135
|
+
!isVoice ||
|
|
136
|
+
direction === INBOUND_DIRECTION ||
|
|
137
|
+
(direction === OUTDIAL_DIRECTION &&
|
|
138
|
+
interaction?.callProcessingDetails?.outdialTransferToQueueEnabled === true);
|
|
139
|
+
|
|
140
|
+
if (canConsultQueue) destinations.consult.push(CONSULT_TRANSFER_DESTINATION_TYPE.QUEUE);
|
|
141
|
+
if (canTransferQueue) destinations.transfer.push(CONSULT_TRANSFER_DESTINATION_TYPE.QUEUE);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (isVoice) {
|
|
145
|
+
destinations.consult.push(CONSULT_TRANSFER_DESTINATION_TYPE.DIALNUMBER);
|
|
146
|
+
destinations.transfer.push(CONSULT_TRANSFER_DESTINATION_TYPE.DIALNUMBER);
|
|
147
|
+
|
|
148
|
+
if (destinationConfig.accessEntryPoint?.toUpperCase() !== COLLABORATION_ACCESS.NONE) {
|
|
149
|
+
destinations.consult.push(CONSULT_TRANSFER_DESTINATION_TYPE.ENTRYPOINT);
|
|
150
|
+
destinations.transfer.push(CONSULT_TRANSFER_DESTINATION_TYPE.ENTRYPOINT);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return destinations;
|
|
155
|
+
}
|
|
156
|
+
|
|
69
157
|
/** Consult media must exist on the interaction payload, not only as a stale resource id. */
|
|
70
158
|
function hasConsultMediaInInteraction(
|
|
71
159
|
interaction: TaskData['interaction'] | undefined,
|
|
@@ -134,6 +222,23 @@ function computeVoiceInteractionUIControls(
|
|
|
134
222
|
interaction && mainCallId ? getConferenceParticipantsCount(interaction, mainCallId) : 0;
|
|
135
223
|
const maxParticipants = participantCount >= MAX_PARTICIPANTS_IN_MULTIPARTY_CONFERENCE;
|
|
136
224
|
const selfAgentId = config.agentId ?? taskData?.agentId;
|
|
225
|
+
const enableWxBetterTogether = config.enableWxBetterTogether ?? false;
|
|
226
|
+
const wxAppDeviceDetails = enableWxBetterTogether
|
|
227
|
+
? getWebexCallingDeviceDetailsForAgent(selfAgentId, interaction?.participants)
|
|
228
|
+
: undefined;
|
|
229
|
+
const isWxAppParticipant = enableWxBetterTogether && wxAppDeviceDetails?.deviceType === 'wxApp';
|
|
230
|
+
const isWxAppOffer =
|
|
231
|
+
isWxAppParticipant && Boolean(wxAppDeviceDetails) && state === TaskState.OFFERED;
|
|
232
|
+
const isWxAppInboundOffer = isWxAppOffer && !isOutdial;
|
|
233
|
+
const isWxAppOutdialOffer = isWxAppOffer && isOutdial;
|
|
234
|
+
const wxAppAnswerPending = config.wxAppAnswerPending ?? false;
|
|
235
|
+
const wxAppAcceptInFlight = config.wxAppAcceptInFlight ?? false;
|
|
236
|
+
const isWxAppEngaged = isWxAppEngagedForControls(
|
|
237
|
+
enableWxBetterTogether,
|
|
238
|
+
selfAgentId,
|
|
239
|
+
interaction?.participants,
|
|
240
|
+
state
|
|
241
|
+
);
|
|
137
242
|
const consultInProgress = getIsConsultInProgressForConferenceControls(
|
|
138
243
|
interaction,
|
|
139
244
|
mainCallId,
|
|
@@ -376,37 +481,52 @@ function computeVoiceInteractionUIControls(
|
|
|
376
481
|
? VISIBLE_ENABLED
|
|
377
482
|
: DISABLED;
|
|
378
483
|
|
|
379
|
-
return
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
484
|
+
return withWxAppTelephonyControls(
|
|
485
|
+
{
|
|
486
|
+
...getDefaultInteractionUIControls(),
|
|
487
|
+
hold: VISIBLE_ENABLED,
|
|
488
|
+
transfer: VISIBLE_ENABLED,
|
|
489
|
+
consult: VISIBLE_ENABLED,
|
|
490
|
+
recording: recordingControl,
|
|
491
|
+
end: VISIBLE_DISABLED,
|
|
492
|
+
},
|
|
493
|
+
isWxAppEngaged,
|
|
494
|
+
currentLeg,
|
|
495
|
+
isWrappingUp
|
|
496
|
+
);
|
|
387
497
|
}
|
|
388
498
|
|
|
389
499
|
if (isConsultRequestedPhase && !isEpDnPendingConferenceMergeUi) {
|
|
390
500
|
if (currentLeg === 'main') {
|
|
391
|
-
return
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
501
|
+
return withWxAppTelephonyControls(
|
|
502
|
+
{
|
|
503
|
+
...getDefaultInteractionUIControls(),
|
|
504
|
+
transfer: shouldHideBlindTransferForEpDnPendingConferenceMerge
|
|
505
|
+
? DISABLED
|
|
506
|
+
: VISIBLE_DISABLED,
|
|
507
|
+
conference: VISIBLE_DISABLED,
|
|
508
|
+
end: VISIBLE_DISABLED,
|
|
509
|
+
},
|
|
510
|
+
isWxAppEngaged,
|
|
511
|
+
currentLeg,
|
|
512
|
+
isWrappingUp
|
|
513
|
+
);
|
|
399
514
|
}
|
|
400
515
|
|
|
401
516
|
if (currentLeg === 'consult') {
|
|
402
|
-
return
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
517
|
+
return withWxAppTelephonyControls(
|
|
518
|
+
{
|
|
519
|
+
...getDefaultInteractionUIControls(),
|
|
520
|
+
endConsult: VISIBLE_ENABLED,
|
|
521
|
+
switch: VISIBLE_DISABLED,
|
|
522
|
+
transfer: VISIBLE_DISABLED,
|
|
523
|
+
transferConference: inConference ? VISIBLE_DISABLED : DISABLED,
|
|
524
|
+
mergeToConference: VISIBLE_DISABLED,
|
|
525
|
+
},
|
|
526
|
+
isWxAppEngaged,
|
|
527
|
+
currentLeg,
|
|
528
|
+
isWrappingUp
|
|
529
|
+
);
|
|
410
530
|
}
|
|
411
531
|
}
|
|
412
532
|
|
|
@@ -415,11 +535,24 @@ function computeVoiceInteractionUIControls(
|
|
|
415
535
|
// Desktop/WebRTC + inbound: accept enabled (agent manually accepts)
|
|
416
536
|
// Desktop/WebRTC + outdial: accept disabled (auto-answer handles it; Widgets show "Accept" disabled)
|
|
417
537
|
// Extension mode (non-WebRTC): accept disabled (Widgets show "Ringing...")
|
|
418
|
-
accept:
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
538
|
+
accept: (() => {
|
|
539
|
+
if (isWxAppInboundOffer) {
|
|
540
|
+
return wxAppAcceptInFlight || wxAppAnswerPending ? VISIBLE_DISABLED : VISIBLE_ENABLED;
|
|
541
|
+
}
|
|
542
|
+
if (isWxAppOutdialOffer) {
|
|
543
|
+
return wxAppAcceptInFlight || wxAppAnswerPending ? VISIBLE_DISABLED : VISIBLE_ENABLED;
|
|
544
|
+
}
|
|
545
|
+
if (state === TaskState.OFFERED && !interaction?.isTerminated) {
|
|
546
|
+
return {isVisible: true, isEnabled: isWebrtc && !isOutdial};
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
return DISABLED;
|
|
550
|
+
})(),
|
|
422
551
|
decline: (() => {
|
|
552
|
+
if (wxAppAcceptInFlight) return VISIBLE_DISABLED;
|
|
553
|
+
if (wxAppAnswerPending && isWxAppInboundOffer) return VISIBLE_DISABLED;
|
|
554
|
+
if (isWxAppInboundOffer) return VISIBLE_ENABLED;
|
|
555
|
+
if (isWxAppOutdialOffer) return VISIBLE_ENABLED;
|
|
423
556
|
if (!isWebrtc || state !== TaskState.OFFERED || interaction?.isTerminated) return DISABLED;
|
|
424
557
|
|
|
425
558
|
return isOutdial ? VISIBLE_DISABLED : VISIBLE_ENABLED;
|
|
@@ -447,8 +580,11 @@ function computeVoiceInteractionUIControls(
|
|
|
447
580
|
return canHold ? VISIBLE_ENABLED : VISIBLE_DISABLED;
|
|
448
581
|
})(),
|
|
449
582
|
|
|
450
|
-
// Mute: WebRTC
|
|
583
|
+
// Mute: WebRTC or wxApp engaged calls; hidden entirely during wrapup
|
|
451
584
|
mute: (() => {
|
|
585
|
+
if (isWxAppEngaged && !isWrappingUp) {
|
|
586
|
+
return currentLeg === 'main' ? VISIBLE_ENABLED : DISABLED;
|
|
587
|
+
}
|
|
452
588
|
if (!isWebrtc) return DISABLED;
|
|
453
589
|
if (isWrappingUp) return DISABLED;
|
|
454
590
|
if (isEpDnPostCallCustomerLeft && inConference) return VISIBLE_DISABLED;
|
|
@@ -712,6 +848,14 @@ function computeVoiceInteractionUIControls(
|
|
|
712
848
|
|
|
713
849
|
return DISABLED;
|
|
714
850
|
})(),
|
|
851
|
+
|
|
852
|
+
keypad: (() => {
|
|
853
|
+
if (isWxAppEngaged && !isWrappingUp) {
|
|
854
|
+
return currentLeg === 'main' ? VISIBLE_ENABLED : DISABLED;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
return DISABLED;
|
|
858
|
+
})(),
|
|
715
859
|
};
|
|
716
860
|
}
|
|
717
861
|
|
|
@@ -743,6 +887,7 @@ function computeDigitalInteractionUIControls(
|
|
|
743
887
|
transferConference: DISABLED,
|
|
744
888
|
mergeToConference: DISABLED,
|
|
745
889
|
switch: DISABLED,
|
|
890
|
+
keypad: DISABLED,
|
|
746
891
|
};
|
|
747
892
|
}
|
|
748
893
|
|
|
@@ -896,6 +1041,11 @@ export function computeUIControls(
|
|
|
896
1041
|
return getDefaultUIControls();
|
|
897
1042
|
}
|
|
898
1043
|
|
|
1044
|
+
const consultTransferDestinations = getConsultTransferDestinations(
|
|
1045
|
+
context.uiControlConfig,
|
|
1046
|
+
fallbackTaskData ?? context.taskData
|
|
1047
|
+
);
|
|
1048
|
+
|
|
899
1049
|
switch (context.uiControlConfig.channelType) {
|
|
900
1050
|
case TASK_CHANNEL_TYPE.VOICE: {
|
|
901
1051
|
const {hasConsultLeg, activeLeg, mainState, consultState} = getVoiceLegState(
|
|
@@ -922,13 +1072,19 @@ export function computeUIControls(
|
|
|
922
1072
|
)
|
|
923
1073
|
: getDefaultInteractionUIControls();
|
|
924
1074
|
|
|
925
|
-
return createTaskUIControls(
|
|
1075
|
+
return createTaskUIControls(
|
|
1076
|
+
mainControls,
|
|
1077
|
+
consultControls,
|
|
1078
|
+
activeLeg,
|
|
1079
|
+
consultTransferDestinations
|
|
1080
|
+
);
|
|
926
1081
|
}
|
|
927
1082
|
case TASK_CHANNEL_TYPE.DIGITAL:
|
|
928
1083
|
return createTaskUIControls(
|
|
929
1084
|
computeDigitalInteractionUIControls(currentState, context, fallbackTaskData),
|
|
930
1085
|
getDefaultInteractionUIControls(),
|
|
931
|
-
'main'
|
|
1086
|
+
'main',
|
|
1087
|
+
consultTransferDestinations
|
|
932
1088
|
);
|
|
933
1089
|
default:
|
|
934
1090
|
return getDefaultUIControls();
|
|
@@ -947,6 +1103,16 @@ function haveInteractionUIControlsChanged(
|
|
|
947
1103
|
});
|
|
948
1104
|
}
|
|
949
1105
|
|
|
1106
|
+
function haveDestinationListChanged(
|
|
1107
|
+
previous: DestinationControls['consult'],
|
|
1108
|
+
next: DestinationControls['consult']
|
|
1109
|
+
): boolean {
|
|
1110
|
+
return (
|
|
1111
|
+
previous.length !== next.length ||
|
|
1112
|
+
previous.some((destination, index) => destination !== next[index])
|
|
1113
|
+
);
|
|
1114
|
+
}
|
|
1115
|
+
|
|
950
1116
|
export function haveUIControlsChanged(
|
|
951
1117
|
previous: TaskUIControls | undefined,
|
|
952
1118
|
next: TaskUIControls
|
|
@@ -955,6 +1121,14 @@ export function haveUIControlsChanged(
|
|
|
955
1121
|
|
|
956
1122
|
return (
|
|
957
1123
|
previous.activeLeg !== next.activeLeg ||
|
|
1124
|
+
haveDestinationListChanged(
|
|
1125
|
+
previous.consultTransferDestinations.consult,
|
|
1126
|
+
next.consultTransferDestinations.consult
|
|
1127
|
+
) ||
|
|
1128
|
+
haveDestinationListChanged(
|
|
1129
|
+
previous.consultTransferDestinations.transfer,
|
|
1130
|
+
next.consultTransferDestinations.transfer
|
|
1131
|
+
) ||
|
|
958
1132
|
haveInteractionUIControlsChanged(previous.main, next.main) ||
|
|
959
1133
|
haveInteractionUIControlsChanged(previous.consult, next.consult)
|
|
960
1134
|
);
|
|
@@ -3,6 +3,7 @@ import type {AnyActorRef} from 'xstate';
|
|
|
3
3
|
import {TaskEventPayload} from './state-machine';
|
|
4
4
|
import {Msg} from '../core/GlobalTypes';
|
|
5
5
|
import AutoWrapup from './AutoWrapup';
|
|
6
|
+
import type {CollaborationAccess} from '../config/types';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Unique identifier for a task in the contact center system
|
|
@@ -33,7 +34,7 @@ export const DESTINATION_TYPE = {
|
|
|
33
34
|
DIALNUMBER: 'dialNumber',
|
|
34
35
|
/** Route task to a specific agent */
|
|
35
36
|
AGENT: 'agent',
|
|
36
|
-
/** Route task to an entry point
|
|
37
|
+
/** Route task to an entry point */
|
|
37
38
|
ENTRYPOINT: 'entryPoint',
|
|
38
39
|
};
|
|
39
40
|
|
|
@@ -67,6 +68,17 @@ export const CONSULT_TRANSFER_DESTINATION_TYPE = {
|
|
|
67
68
|
*/
|
|
68
69
|
export type ConsultTransferDestinationType = Enum<typeof CONSULT_TRANSFER_DESTINATION_TYPE>;
|
|
69
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Agent-profile policy used by the task state machine to derive consult/transfer destinations.
|
|
73
|
+
* @internal
|
|
74
|
+
*/
|
|
75
|
+
export type ConsultTransferDestinationConfig = {
|
|
76
|
+
allowConsultToQueue: boolean;
|
|
77
|
+
accessQueue?: CollaborationAccess;
|
|
78
|
+
accessEntryPoint?: CollaborationAccess;
|
|
79
|
+
accessBuddyTeam?: CollaborationAccess;
|
|
80
|
+
};
|
|
81
|
+
|
|
70
82
|
/**
|
|
71
83
|
* Defines all supported media channel types for customer interactions
|
|
72
84
|
* These represent the different ways customers can communicate with agents
|
|
@@ -234,6 +246,11 @@ export enum TASK_EVENTS {
|
|
|
234
246
|
*/
|
|
235
247
|
TASK_UI_CONTROLS_UPDATED = 'task:ui-controls-updated',
|
|
236
248
|
|
|
249
|
+
/**
|
|
250
|
+
* Triggered when wxApp mute state changes from Webex App (Mercury sync or call details).
|
|
251
|
+
*/
|
|
252
|
+
TASK_WXAPP_MUTE_STATE_UPDATED = 'task:wxapp-mute-state-updated',
|
|
253
|
+
|
|
237
254
|
/**
|
|
238
255
|
* Triggered when a consultation request is accepted
|
|
239
256
|
* @example
|
|
@@ -1134,6 +1151,8 @@ export type TaskData = {
|
|
|
1134
1151
|
reservedAgentChannelId?: string;
|
|
1135
1152
|
/** Indicates if wrap-up is required for this task */
|
|
1136
1153
|
wrapUpRequired?: boolean;
|
|
1154
|
+
/** SDK-internal: skip task:outdialFailed when non-wxApp agent-terminated outdial still needs wrapup */
|
|
1155
|
+
suppressOutdialFailedPopup?: boolean;
|
|
1137
1156
|
|
|
1138
1157
|
/**
|
|
1139
1158
|
* Current consultation status derived from state machine
|
|
@@ -1215,6 +1234,19 @@ export type InteractionUIControls = {
|
|
|
1215
1234
|
mergeToConference: TaskUIControlState;
|
|
1216
1235
|
wrapup: TaskUIControlState;
|
|
1217
1236
|
switch: TaskUIControlState;
|
|
1237
|
+
keypad?: TaskUIControlState;
|
|
1238
|
+
};
|
|
1239
|
+
|
|
1240
|
+
/** Options for {@link ITask.toggleMute} — wxApp engaged calls use `muted` for target state. */
|
|
1241
|
+
export type TaskToggleMuteOptions = {
|
|
1242
|
+
muted?: boolean;
|
|
1243
|
+
lineOwnerId?: string;
|
|
1244
|
+
};
|
|
1245
|
+
|
|
1246
|
+
/** Options for {@link ITask.transmitDtmf} — wxApp engaged in-call DTMF. */
|
|
1247
|
+
export type TaskTransmitDtmfOptions = {
|
|
1248
|
+
dtmf: string;
|
|
1249
|
+
lineOwnerId?: string;
|
|
1218
1250
|
};
|
|
1219
1251
|
|
|
1220
1252
|
export type TaskUILeg = 'main' | 'consult';
|
|
@@ -1228,6 +1260,14 @@ export type TaskUIControls = {
|
|
|
1228
1260
|
main: InteractionUIControls;
|
|
1229
1261
|
consult: InteractionUIControls;
|
|
1230
1262
|
activeLeg: TaskUILeg;
|
|
1263
|
+
/**
|
|
1264
|
+
* Ordered destination categories available for each action.
|
|
1265
|
+
* The first category is the default for consumers that render a destination picker.
|
|
1266
|
+
*/
|
|
1267
|
+
consultTransferDestinations: {
|
|
1268
|
+
consult: ConsultTransferDestinationType[];
|
|
1269
|
+
transfer: ConsultTransferDestinationType[];
|
|
1270
|
+
};
|
|
1231
1271
|
};
|
|
1232
1272
|
|
|
1233
1273
|
/**
|
|
@@ -1629,6 +1669,15 @@ export type ParticipantBooleanKey =
|
|
|
1629
1669
|
*/
|
|
1630
1670
|
export type TaskResponse = AgentContact | Error | void;
|
|
1631
1671
|
|
|
1672
|
+
/**
|
|
1673
|
+
* Request payload for removing a supported participant from an active conference.
|
|
1674
|
+
* @public
|
|
1675
|
+
*/
|
|
1676
|
+
export type DropConferenceParticipantPayload = {
|
|
1677
|
+
/** Participant identifier supplied by the current task roster. */
|
|
1678
|
+
participantId: string;
|
|
1679
|
+
};
|
|
1680
|
+
|
|
1632
1681
|
/**
|
|
1633
1682
|
* Payload shape used by consult conference helper utilities.
|
|
1634
1683
|
*/
|
|
@@ -1687,6 +1736,29 @@ export interface ITask extends IEventEmitter {
|
|
|
1687
1736
|
*/
|
|
1688
1737
|
readonly uiControls: TaskUIControls;
|
|
1689
1738
|
|
|
1739
|
+
/**
|
|
1740
|
+
* Update wxApp thick-client answer flag at runtime.
|
|
1741
|
+
* Voice tasks override to refresh uiControls; other channel types no-op.
|
|
1742
|
+
* @internal
|
|
1743
|
+
*/
|
|
1744
|
+
setEnableWxBetterTogether(enabled: boolean): void;
|
|
1745
|
+
|
|
1746
|
+
/**
|
|
1747
|
+
* Apply wxApp mute state from Mercury sync or call-details fetch.
|
|
1748
|
+
* @internal
|
|
1749
|
+
*/
|
|
1750
|
+
applyWxAppMuteStateFromSync(incomingCallId: string, muted: boolean): void;
|
|
1751
|
+
|
|
1752
|
+
/**
|
|
1753
|
+
* Current wxApp mute state for engaged telephony (Voice tasks only).
|
|
1754
|
+
*/
|
|
1755
|
+
getWxAppMuted?(): boolean;
|
|
1756
|
+
|
|
1757
|
+
/**
|
|
1758
|
+
* Re-seed wxApp mute from GET telephony/calls/{callId}. Resolves to muted state when known.
|
|
1759
|
+
*/
|
|
1760
|
+
syncWxAppMuteFromCallDetails?(): Promise<boolean | undefined>;
|
|
1761
|
+
|
|
1690
1762
|
/**
|
|
1691
1763
|
* State machine instance for managing task state transitions and derived properties.
|
|
1692
1764
|
* The state machine handles:
|
|
@@ -1875,6 +1947,18 @@ export interface ITask extends IEventEmitter {
|
|
|
1875
1947
|
*/
|
|
1876
1948
|
consultConference(): Promise<TaskResponse>;
|
|
1877
1949
|
|
|
1950
|
+
/**
|
|
1951
|
+
* Removes a supported participant from the active conference.
|
|
1952
|
+
* Resolves after the correlated ParticipantLeftConference routing event.
|
|
1953
|
+
* @param payload - Participant identifier to remove
|
|
1954
|
+
* @returns Promise<TaskResponse>
|
|
1955
|
+
* @example
|
|
1956
|
+
* ```typescript
|
|
1957
|
+
* await task.dropConferenceParticipant({participantId: 'participant-id'});
|
|
1958
|
+
* ```
|
|
1959
|
+
*/
|
|
1960
|
+
dropConferenceParticipant(payload: DropConferenceParticipantPayload): Promise<TaskResponse>;
|
|
1961
|
+
|
|
1878
1962
|
/**
|
|
1879
1963
|
* Exits from an ongoing conference.
|
|
1880
1964
|
* @returns Promise<TaskResponse>
|
|
@@ -1909,14 +1993,29 @@ export interface ITask extends IEventEmitter {
|
|
|
1909
1993
|
switchCall(): Promise<TaskResponse>;
|
|
1910
1994
|
|
|
1911
1995
|
/**
|
|
1912
|
-
* Toggles mute/unmute for the
|
|
1996
|
+
* Toggles mute/unmute for the active call.
|
|
1997
|
+
* WebRTC tasks toggle the local stream; wxApp engaged tasks route to telephony mute REST when
|
|
1998
|
+
* `enableWxBetterTogether` is active.
|
|
1999
|
+
* @param options - Optional target mute state (`muted`) for wxApp; ignored for WebRTC toggle.
|
|
1913
2000
|
* @returns Promise<void>
|
|
1914
2001
|
* @example
|
|
1915
2002
|
* ```typescript
|
|
1916
2003
|
* await task.toggleMute();
|
|
2004
|
+
* await task.toggleMute({ muted: true });
|
|
2005
|
+
* ```
|
|
2006
|
+
*/
|
|
2007
|
+
toggleMute(options?: TaskToggleMuteOptions): Promise<void>;
|
|
2008
|
+
|
|
2009
|
+
/**
|
|
2010
|
+
* Sends in-call DTMF tones for wxApp engaged telephony tasks when `enableWxBetterTogether` is active.
|
|
2011
|
+
* @param options - DTMF digit(s) and optional shared-line owner id.
|
|
2012
|
+
* @returns Promise<void>
|
|
2013
|
+
* @example
|
|
2014
|
+
* ```typescript
|
|
2015
|
+
* await task.transmitDtmf({ dtmf: '5' });
|
|
1917
2016
|
* ```
|
|
1918
2017
|
*/
|
|
1919
|
-
|
|
2018
|
+
transmitDtmf(options: TaskTransmitDtmfOptions): Promise<void>;
|
|
1920
2019
|
}
|
|
1921
2020
|
|
|
1922
2021
|
/**
|
|
@@ -1952,6 +2051,12 @@ export interface IVoice extends ITask {
|
|
|
1952
2051
|
* ```
|
|
1953
2052
|
*/
|
|
1954
2053
|
holdResume(): Promise<TaskResponse>;
|
|
2054
|
+
/** @see wxAppVoiceMethods — WXCC-6026 */
|
|
2055
|
+
isWebexAppCallingOffer(): boolean;
|
|
2056
|
+
/** @see wxAppVoiceMethods — WXCC-6026 */
|
|
2057
|
+
getCallingDeviceDetails(): import('./WebexCallingUtils').WebexCallingDeviceDetails | undefined;
|
|
2058
|
+
/** @see wxAppVoiceMethods — WXCC-6026 */
|
|
2059
|
+
getWebexCallingCallId(): string | null;
|
|
1955
2060
|
}
|
|
1956
2061
|
|
|
1957
2062
|
/**
|
|
@@ -1962,6 +2067,9 @@ export type VoiceUIControlOptions = {
|
|
|
1962
2067
|
isEndConsultEnabled?: boolean;
|
|
1963
2068
|
voiceVariant?: VoiceVariant;
|
|
1964
2069
|
isRecordingEnabled?: boolean;
|
|
2070
|
+
enableWxBetterTogether?: boolean;
|
|
2071
|
+
consultTransferConfig?: ConsultTransferDestinationConfig;
|
|
2072
|
+
answerCallOnWebexService?: import('../AnswerCallOnWebexService').default;
|
|
1965
2073
|
};
|
|
1966
2074
|
|
|
1967
2075
|
/**
|
|
@@ -1987,7 +2095,7 @@ export interface IWebRTC extends IVoice {
|
|
|
1987
2095
|
* task.toggleMute();
|
|
1988
2096
|
* ```
|
|
1989
2097
|
*/
|
|
1990
|
-
toggleMute(): Promise<void>;
|
|
2098
|
+
toggleMute(options?: TaskToggleMuteOptions): Promise<void>;
|
|
1991
2099
|
/**
|
|
1992
2100
|
* Decline the incoming task for Browser Login
|
|
1993
2101
|
*
|
|
@@ -2012,6 +2120,8 @@ export type WebSocketPayload = TaskData & {
|
|
|
2012
2120
|
type: string;
|
|
2013
2121
|
mediaResourceId?: string;
|
|
2014
2122
|
reason?: string;
|
|
2123
|
+
/** ContactEnded: party that ended the contact (e.g. 'Agent', 'Customer') */
|
|
2124
|
+
terminatingParty?: string;
|
|
2015
2125
|
/**
|
|
2016
2126
|
* Optional real-time transcript chunk payload.
|
|
2017
2127
|
* Present on REAL_TIME_TRANSCRIPTION notifications.
|