@webex/contact-center 3.12.0-llmrefactor.2 → 3.12.0-llmrefactor.4
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 +6 -2
- 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 +353 -21
- 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 +9 -9
- 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 +522 -16
- 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 +152 -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 +56 -24
- 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 +1294 -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
|
@@ -52,12 +52,70 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
52
52
|
* AgentContactHeld -> TaskEvent.HOLD_SUCCESS
|
|
53
53
|
* AgentContactUnheld -> TaskEvent.UNHOLD_SUCCESS
|
|
54
54
|
* AgentConsultEnded -> TaskEvent.CONSULT_END
|
|
55
|
+
* ParticipantLeftConference -> TaskEvent.PARTICIPANT_LEAVE
|
|
55
56
|
* AgentContactEnded -> TaskEvent.CONTACT_ENDED
|
|
56
57
|
* AgentWrapup -> TaskEvent.TASK_WRAPUP (wrapUpRequired)
|
|
57
58
|
* AgentWrappedup -> TaskEvent.WRAPUP_COMPLETE
|
|
58
59
|
*
|
|
59
60
|
* (See TaskManager.mapEventToTaskStateMachineEvent for the full mapping table.)
|
|
60
61
|
*/
|
|
62
|
+
// XState evaluates these guarded transition arrays in order. Each returned entry is a
|
|
63
|
+
// complete transition with its own target and actions; sharing them keeps lifecycle-event
|
|
64
|
+
// handling consistent across active states where ParticipantLeftConference can arrive.
|
|
65
|
+
const currentAgentParticipantLeaveTransitions = () => [
|
|
66
|
+
{
|
|
67
|
+
guard: (params) =>
|
|
68
|
+
guards.didCurrentAgentLeaveMainInteraction(params) && guards.shouldWrapUp(params),
|
|
69
|
+
target: TaskState.WRAPPING_UP,
|
|
70
|
+
actions: [
|
|
71
|
+
'updateTaskData',
|
|
72
|
+
'handleParticipantLeft',
|
|
73
|
+
'markEnded',
|
|
74
|
+
'clearConsultState',
|
|
75
|
+
'emitTaskParticipantLeft',
|
|
76
|
+
'emitTaskWrapup',
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
guard: guards.didCurrentAgentLeaveMainInteraction,
|
|
81
|
+
target: TaskState.TERMINATED,
|
|
82
|
+
actions: [
|
|
83
|
+
'updateTaskData',
|
|
84
|
+
'handleParticipantLeft',
|
|
85
|
+
'markEnded',
|
|
86
|
+
'clearConsultState',
|
|
87
|
+
'emitTaskParticipantLeft',
|
|
88
|
+
'emitTaskEnd',
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
const currentAgentConsultEndTransitions = () => [
|
|
94
|
+
{
|
|
95
|
+
guard: (params) =>
|
|
96
|
+
guards.didCurrentAgentLeaveMainInteraction(params) && guards.shouldWrapUp(params),
|
|
97
|
+
target: TaskState.WRAPPING_UP,
|
|
98
|
+
actions: [
|
|
99
|
+
'updateTaskData',
|
|
100
|
+
'markEnded',
|
|
101
|
+
'clearConsultState',
|
|
102
|
+
'emitTaskConsultEnd',
|
|
103
|
+
'emitTaskWrapup',
|
|
104
|
+
],
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
guard: guards.didCurrentAgentLeaveMainInteraction,
|
|
108
|
+
target: TaskState.TERMINATED,
|
|
109
|
+
actions: [
|
|
110
|
+
'updateTaskData',
|
|
111
|
+
'markEnded',
|
|
112
|
+
'clearConsultState',
|
|
113
|
+
'emitTaskConsultEnd',
|
|
114
|
+
'emitTaskEnd',
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
];
|
|
118
|
+
|
|
61
119
|
return {
|
|
62
120
|
id: 'taskStateMachine',
|
|
63
121
|
initial: TaskState.IDLE,
|
|
@@ -70,7 +128,7 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
70
128
|
actions: ['updateTaskData', 'syncTaskDataFromEvent'],
|
|
71
129
|
},
|
|
72
130
|
[TaskEvent.CONTACT_OWNER_CHANGED]: {
|
|
73
|
-
actions: ['updateTaskData', 'syncTaskDataFromEvent'],
|
|
131
|
+
actions: ['updateTaskData', 'syncTaskDataFromEvent', 'emitTaskHydrate'],
|
|
74
132
|
},
|
|
75
133
|
// HYDRATE: Update task data from AgentContact event
|
|
76
134
|
// Note: State restoration with transitions is handled in IDLE state.
|
|
@@ -190,10 +248,17 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
190
248
|
target: TaskState.TERMINATED,
|
|
191
249
|
actions: ['updateTaskData', 'markEnded', 'emitTaskReject'],
|
|
192
250
|
},
|
|
193
|
-
[TaskEvent.TASK_WRAPUP]:
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
251
|
+
[TaskEvent.TASK_WRAPUP]: [
|
|
252
|
+
{
|
|
253
|
+
guard: guards.shouldWrapUp,
|
|
254
|
+
target: TaskState.WRAPPING_UP,
|
|
255
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskWrapup'],
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
target: TaskState.TERMINATED,
|
|
259
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskEnd'],
|
|
260
|
+
},
|
|
261
|
+
],
|
|
197
262
|
[TaskEvent.CONTACT_ENDED]: {
|
|
198
263
|
target: TaskState.TERMINATED,
|
|
199
264
|
actions: ['updateTaskData', 'markEnded', 'emitTaskEnd'],
|
|
@@ -334,6 +399,7 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
334
399
|
},
|
|
335
400
|
// AgentConsultEnded from Stable Prod while on connected leg (external end consult).
|
|
336
401
|
[TaskEvent.CONSULT_END]: [
|
|
402
|
+
...currentAgentConsultEndTransitions(),
|
|
337
403
|
{
|
|
338
404
|
guard: ({context, event}) => {
|
|
339
405
|
if (context.consultInitiator !== true) return false;
|
|
@@ -350,6 +416,14 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
350
416
|
actions: ['updateTaskData', 'clearConsultState', 'emitTaskConsultEnd'],
|
|
351
417
|
},
|
|
352
418
|
],
|
|
419
|
+
// Routing lifecycle events can arrive out of order in child-task/EP-DN flows. The
|
|
420
|
+
// local actor may still be CONNECTED when ParticipantLeftConference reports that this
|
|
421
|
+
// agent left the main interaction. Handle that self-departure race; for another
|
|
422
|
+
// participant, the action-only fallback updates data while preserving CONNECTED.
|
|
423
|
+
[TaskEvent.PARTICIPANT_LEAVE]: [
|
|
424
|
+
...currentAgentParticipantLeaveTransitions(),
|
|
425
|
+
{actions: ['updateTaskData', 'handleParticipantLeft', 'emitTaskParticipantLeft']},
|
|
426
|
+
],
|
|
353
427
|
// AgentContactEnded Event
|
|
354
428
|
[TaskEvent.CONTACT_ENDED]: [
|
|
355
429
|
{
|
|
@@ -380,6 +454,17 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
380
454
|
target: TaskState.WRAPPING_UP,
|
|
381
455
|
actions: ['updateTaskData', 'markEnded', 'emitTaskWrapup'],
|
|
382
456
|
},
|
|
457
|
+
[TaskEvent.OUTBOUND_FAILED]: [
|
|
458
|
+
{
|
|
459
|
+
guard: guards.shouldWrapUp,
|
|
460
|
+
target: TaskState.WRAPPING_UP,
|
|
461
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskWrapup'],
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
target: TaskState.TERMINATED,
|
|
465
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskEnd'],
|
|
466
|
+
},
|
|
467
|
+
],
|
|
383
468
|
[TaskEvent.PAUSE_RECORDING]: {
|
|
384
469
|
actions: ['updateTaskData', 'setRecordingState', 'emitTaskRecordingPaused'],
|
|
385
470
|
},
|
|
@@ -401,6 +486,24 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
401
486
|
target: TaskState.CONNECTED,
|
|
402
487
|
actions: ['updateTaskData'],
|
|
403
488
|
},
|
|
489
|
+
// Another agent can remove this agent while the local hold request is awaiting its
|
|
490
|
+
// routing acknowledgement. Process that backend lifecycle event independently of
|
|
491
|
+
// whether Drop was initiated from this task; another-participant event preserves state.
|
|
492
|
+
[TaskEvent.PARTICIPANT_LEAVE]: [
|
|
493
|
+
...currentAgentParticipantLeaveTransitions(),
|
|
494
|
+
{actions: ['updateTaskData', 'handleParticipantLeft', 'emitTaskParticipantLeft']},
|
|
495
|
+
],
|
|
496
|
+
[TaskEvent.OUTBOUND_FAILED]: [
|
|
497
|
+
{
|
|
498
|
+
guard: guards.shouldWrapUp,
|
|
499
|
+
target: TaskState.WRAPPING_UP,
|
|
500
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskWrapup'],
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
target: TaskState.TERMINATED,
|
|
504
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskEnd'],
|
|
505
|
+
},
|
|
506
|
+
],
|
|
404
507
|
},
|
|
405
508
|
},
|
|
406
509
|
|
|
@@ -487,14 +590,30 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
487
590
|
},
|
|
488
591
|
],
|
|
489
592
|
// AgentConsultEnded from Stable Prod while main leg is held (external end consult).
|
|
490
|
-
[TaskEvent.CONSULT_END]:
|
|
491
|
-
|
|
492
|
-
|
|
593
|
+
[TaskEvent.CONSULT_END]: [
|
|
594
|
+
...currentAgentConsultEndTransitions(),
|
|
595
|
+
{actions: ['updateTaskData', 'clearConsultState', 'emitTaskConsultEnd']},
|
|
596
|
+
],
|
|
597
|
+
[TaskEvent.PARTICIPANT_LEAVE]: [
|
|
598
|
+
...currentAgentParticipantLeaveTransitions(),
|
|
599
|
+
{actions: ['updateTaskData', 'handleParticipantLeft', 'emitTaskParticipantLeft']},
|
|
600
|
+
],
|
|
493
601
|
// TODO: This may not be a valid transition, this needs to be checked as well
|
|
494
602
|
[TaskEvent.TASK_WRAPUP]: {
|
|
495
603
|
target: TaskState.WRAPPING_UP,
|
|
496
604
|
actions: ['updateTaskData', 'markEnded', 'emitTaskWrapup'],
|
|
497
605
|
},
|
|
606
|
+
[TaskEvent.OUTBOUND_FAILED]: [
|
|
607
|
+
{
|
|
608
|
+
guard: guards.shouldWrapUp,
|
|
609
|
+
target: TaskState.WRAPPING_UP,
|
|
610
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskWrapup'],
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
target: TaskState.TERMINATED,
|
|
614
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskEnd'],
|
|
615
|
+
},
|
|
616
|
+
],
|
|
498
617
|
},
|
|
499
618
|
},
|
|
500
619
|
|
|
@@ -507,6 +626,22 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
507
626
|
[TaskEvent.UNHOLD_FAILED]: {
|
|
508
627
|
target: TaskState.HELD,
|
|
509
628
|
},
|
|
629
|
+
// The same remote-removal race can occur while an unhold request is in flight.
|
|
630
|
+
[TaskEvent.PARTICIPANT_LEAVE]: [
|
|
631
|
+
...currentAgentParticipantLeaveTransitions(),
|
|
632
|
+
{actions: ['updateTaskData', 'handleParticipantLeft', 'emitTaskParticipantLeft']},
|
|
633
|
+
],
|
|
634
|
+
[TaskEvent.OUTBOUND_FAILED]: [
|
|
635
|
+
{
|
|
636
|
+
guard: guards.shouldWrapUp,
|
|
637
|
+
target: TaskState.WRAPPING_UP,
|
|
638
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskWrapup'],
|
|
639
|
+
},
|
|
640
|
+
{
|
|
641
|
+
target: TaskState.TERMINATED,
|
|
642
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskEnd'],
|
|
643
|
+
},
|
|
644
|
+
],
|
|
510
645
|
},
|
|
511
646
|
},
|
|
512
647
|
|
|
@@ -569,6 +704,7 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
569
704
|
],
|
|
570
705
|
// AgentConsultEnded from Stable Prod during consult initiation (external end consult).
|
|
571
706
|
[TaskEvent.CONSULT_END]: [
|
|
707
|
+
...currentAgentConsultEndTransitions(),
|
|
572
708
|
{
|
|
573
709
|
guard: guards.isPrimaryMediaOnHold,
|
|
574
710
|
target: TaskState.HELD,
|
|
@@ -579,6 +715,21 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
579
715
|
actions: ['updateTaskData', 'clearConsultState', 'emitTaskConsultEnd'],
|
|
580
716
|
},
|
|
581
717
|
],
|
|
718
|
+
[TaskEvent.PARTICIPANT_LEAVE]: [
|
|
719
|
+
...currentAgentParticipantLeaveTransitions(),
|
|
720
|
+
{actions: ['updateTaskData', 'handleParticipantLeft', 'emitTaskParticipantLeft']},
|
|
721
|
+
],
|
|
722
|
+
[TaskEvent.OUTBOUND_FAILED]: [
|
|
723
|
+
{
|
|
724
|
+
guard: guards.shouldWrapUp,
|
|
725
|
+
target: TaskState.WRAPPING_UP,
|
|
726
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskWrapup'],
|
|
727
|
+
},
|
|
728
|
+
{
|
|
729
|
+
target: TaskState.TERMINATED,
|
|
730
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskEnd'],
|
|
731
|
+
},
|
|
732
|
+
],
|
|
582
733
|
},
|
|
583
734
|
},
|
|
584
735
|
|
|
@@ -619,6 +770,7 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
619
770
|
|
|
620
771
|
// AgentConsultEnded
|
|
621
772
|
[TaskEvent.CONSULT_END]: [
|
|
773
|
+
...currentAgentConsultEndTransitions(),
|
|
622
774
|
{
|
|
623
775
|
// Initiator returning to conference only while conference is still active.
|
|
624
776
|
guard: ({context, event}) =>
|
|
@@ -686,7 +838,13 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
686
838
|
{
|
|
687
839
|
// Consulted agent → TERMINATED
|
|
688
840
|
target: TaskState.TERMINATED,
|
|
689
|
-
actions: [
|
|
841
|
+
actions: [
|
|
842
|
+
'updateTaskData',
|
|
843
|
+
'markEnded',
|
|
844
|
+
'clearConsultState',
|
|
845
|
+
'emitTaskConsultEnd',
|
|
846
|
+
'emitTaskEnd',
|
|
847
|
+
],
|
|
690
848
|
},
|
|
691
849
|
],
|
|
692
850
|
|
|
@@ -705,34 +863,10 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
705
863
|
},
|
|
706
864
|
|
|
707
865
|
[TaskEvent.PARTICIPANT_LEAVE]: [
|
|
866
|
+
...currentAgentParticipantLeaveTransitions(),
|
|
708
867
|
{
|
|
709
868
|
guard: (params) =>
|
|
710
|
-
guards.
|
|
711
|
-
target: TaskState.WRAPPING_UP,
|
|
712
|
-
actions: [
|
|
713
|
-
'updateTaskData',
|
|
714
|
-
'handleParticipantLeft',
|
|
715
|
-
'markEnded',
|
|
716
|
-
'clearConsultState',
|
|
717
|
-
'emitTaskParticipantLeft',
|
|
718
|
-
'emitTaskWrapup',
|
|
719
|
-
],
|
|
720
|
-
},
|
|
721
|
-
{
|
|
722
|
-
guard: guards.didCurrentAgentLeaveConference,
|
|
723
|
-
target: TaskState.TERMINATED,
|
|
724
|
-
actions: [
|
|
725
|
-
'updateTaskData',
|
|
726
|
-
'handleParticipantLeft',
|
|
727
|
-
'markEnded',
|
|
728
|
-
'clearConsultState',
|
|
729
|
-
'emitTaskParticipantLeft',
|
|
730
|
-
'emitTaskEnd',
|
|
731
|
-
],
|
|
732
|
-
},
|
|
733
|
-
{
|
|
734
|
-
guard: (params) =>
|
|
735
|
-
!guards.didCurrentAgentLeaveConference(params) &&
|
|
869
|
+
!guards.didCurrentAgentLeaveMainInteraction(params) &&
|
|
736
870
|
guards.shouldDowngradeConferenceToConnected(params),
|
|
737
871
|
target: TaskState.CONNECTED,
|
|
738
872
|
actions: [
|
|
@@ -825,6 +959,17 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
825
959
|
target: TaskState.WRAPPING_UP,
|
|
826
960
|
actions: ['updateTaskData', 'markEnded', 'clearConsultState', 'emitTaskWrapup'],
|
|
827
961
|
},
|
|
962
|
+
[TaskEvent.OUTBOUND_FAILED]: [
|
|
963
|
+
{
|
|
964
|
+
guard: guards.shouldWrapUp,
|
|
965
|
+
target: TaskState.WRAPPING_UP,
|
|
966
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskWrapup'],
|
|
967
|
+
},
|
|
968
|
+
{
|
|
969
|
+
target: TaskState.TERMINATED,
|
|
970
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskEnd'],
|
|
971
|
+
},
|
|
972
|
+
],
|
|
828
973
|
[TaskEvent.MERGE_TO_CONFERENCE]: {
|
|
829
974
|
target: TaskState.CONF_INITIATING,
|
|
830
975
|
},
|
|
@@ -860,6 +1005,7 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
860
1005
|
},
|
|
861
1006
|
// AgentConsultEnded while conference is initiating (end call before conference completes)
|
|
862
1007
|
[TaskEvent.CONSULT_END]: [
|
|
1008
|
+
...currentAgentConsultEndTransitions(),
|
|
863
1009
|
{
|
|
864
1010
|
guard: ({event}) => {
|
|
865
1011
|
const taskData = getTaskDataFromEvent(event);
|
|
@@ -874,6 +1020,21 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
874
1020
|
actions: ['updateTaskData', 'clearConsultState'],
|
|
875
1021
|
},
|
|
876
1022
|
],
|
|
1023
|
+
[TaskEvent.PARTICIPANT_LEAVE]: [
|
|
1024
|
+
...currentAgentParticipantLeaveTransitions(),
|
|
1025
|
+
{actions: ['updateTaskData', 'handleParticipantLeft', 'emitTaskParticipantLeft']},
|
|
1026
|
+
],
|
|
1027
|
+
[TaskEvent.OUTBOUND_FAILED]: [
|
|
1028
|
+
{
|
|
1029
|
+
guard: guards.shouldWrapUp,
|
|
1030
|
+
target: TaskState.WRAPPING_UP,
|
|
1031
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskWrapup'],
|
|
1032
|
+
},
|
|
1033
|
+
{
|
|
1034
|
+
target: TaskState.TERMINATED,
|
|
1035
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskEnd'],
|
|
1036
|
+
},
|
|
1037
|
+
],
|
|
877
1038
|
},
|
|
878
1039
|
},
|
|
879
1040
|
|
|
@@ -901,6 +1062,7 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
901
1062
|
|
|
902
1063
|
// Needed as all agents in conference get this event, hence we need to clear the consult state
|
|
903
1064
|
[TaskEvent.CONSULT_END]: [
|
|
1065
|
+
...currentAgentConsultEndTransitions(),
|
|
904
1066
|
{
|
|
905
1067
|
guard: ({context, event}) => {
|
|
906
1068
|
const taskData = getTaskDataFromEvent(event);
|
|
@@ -975,37 +1137,11 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
975
1137
|
|
|
976
1138
|
// Participant leaves - handle conference downgrade scenarios
|
|
977
1139
|
[TaskEvent.PARTICIPANT_LEAVE]: [
|
|
978
|
-
|
|
979
|
-
// Only the leaving agent should wrap up → WRAPPING_UP
|
|
980
|
-
guard: (params) =>
|
|
981
|
-
guards.didCurrentAgentLeaveConference(params) && guards.shouldWrapUp(params),
|
|
982
|
-
target: TaskState.WRAPPING_UP,
|
|
983
|
-
actions: [
|
|
984
|
-
'updateTaskData',
|
|
985
|
-
'handleParticipantLeft',
|
|
986
|
-
'markEnded',
|
|
987
|
-
'clearConsultState',
|
|
988
|
-
'emitTaskParticipantLeft',
|
|
989
|
-
'emitTaskWrapup',
|
|
990
|
-
],
|
|
991
|
-
},
|
|
992
|
-
{
|
|
993
|
-
// Only the leaving agent (no wrapup) → TERMINATED
|
|
994
|
-
guard: guards.didCurrentAgentLeaveConference,
|
|
995
|
-
target: TaskState.TERMINATED,
|
|
996
|
-
actions: [
|
|
997
|
-
'updateTaskData',
|
|
998
|
-
'handleParticipantLeft',
|
|
999
|
-
'markEnded',
|
|
1000
|
-
'clearConsultState',
|
|
1001
|
-
'emitTaskParticipantLeft',
|
|
1002
|
-
'emitTaskEnd',
|
|
1003
|
-
],
|
|
1004
|
-
},
|
|
1140
|
+
...currentAgentParticipantLeaveTransitions(),
|
|
1005
1141
|
{
|
|
1006
1142
|
// Conference downgraded, customer present → CONNECTED
|
|
1007
1143
|
guard: (params) =>
|
|
1008
|
-
!guards.
|
|
1144
|
+
!guards.didCurrentAgentLeaveMainInteraction(params) &&
|
|
1009
1145
|
guards.shouldDowngradeConferenceToConnected(params),
|
|
1010
1146
|
target: TaskState.CONNECTED,
|
|
1011
1147
|
actions: [
|
|
@@ -1115,6 +1251,17 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
1115
1251
|
target: TaskState.WRAPPING_UP,
|
|
1116
1252
|
actions: ['updateTaskData', 'markEnded', 'clearConsultState', 'emitTaskWrapup'],
|
|
1117
1253
|
},
|
|
1254
|
+
[TaskEvent.OUTBOUND_FAILED]: [
|
|
1255
|
+
{
|
|
1256
|
+
guard: guards.shouldWrapUp,
|
|
1257
|
+
target: TaskState.WRAPPING_UP,
|
|
1258
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskWrapup'],
|
|
1259
|
+
},
|
|
1260
|
+
{
|
|
1261
|
+
target: TaskState.TERMINATED,
|
|
1262
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskEnd'],
|
|
1263
|
+
},
|
|
1264
|
+
],
|
|
1118
1265
|
},
|
|
1119
1266
|
},
|
|
1120
1267
|
|
|
@@ -515,12 +515,15 @@ export const actions: TaskActionsMap = {
|
|
|
515
515
|
}),
|
|
516
516
|
handleConferenceStarted: assign({consultInitiator: false}),
|
|
517
517
|
|
|
518
|
-
setConsultDestination: assign(({event}: TaskActionArgs) => {
|
|
518
|
+
setConsultDestination: assign(({context, event}: TaskActionArgs) => {
|
|
519
519
|
if (!event || event.type !== TaskEvent.CONSULT) {
|
|
520
520
|
return {};
|
|
521
521
|
}
|
|
522
522
|
|
|
523
|
-
|
|
523
|
+
// CONSULT is a user action and does not carry taskData. Preserve the current interaction
|
|
524
|
+
// snapshot while recording the destination; replacing it with only destAgentId would remove
|
|
525
|
+
// the main-leg membership needed to correlate an immediately following lifecycle event.
|
|
526
|
+
const taskData = context.taskData;
|
|
524
527
|
const consultDestinationType =
|
|
525
528
|
'destinationType' in event ? event.destinationType ?? null : null;
|
|
526
529
|
const consultDestinationAgentId =
|
|
@@ -66,7 +66,7 @@ state-machine/
|
|
|
66
66
|
- **State Graph and Transition Rules**: `TaskStateMachine.ts` defines all states, transition tables, and event handlers that drive the task lifecycle.
|
|
67
67
|
- **Deterministic Context Updates**: `actions.ts` implements XState actions for task context mutation and provides emitter placeholders that `Task` overrides to surface SDK events.
|
|
68
68
|
- **Transition Eligibility**: `guards.ts` contains pure predicates that gate transitions based on current context, task data, and backend state.
|
|
69
|
-
- **UI Controls Computation**: `uiControlsComputer.ts` derives
|
|
69
|
+
- **UI Controls Computation**: `uiControlsComputer.ts` derives per-leg action controls and ordered Consult/Transfer destination categories from state, Task data, and injected profile policy for voice/digital channels. Consumers read `task.uiControls`; do not add a parallel policy method or UI-side decision tree.
|
|
70
70
|
- **Typed Event Contracts**: `constants.ts` and `types.ts` define `TaskState`, `TaskEvent`, and the `TaskEventPayloadMap` so transitions and payloads stay type-safe.
|
|
71
71
|
- **Public Exports**: `index.ts` exposes the state machine factory, event enums, and types for consumption by the task layer.
|
|
72
72
|
|
|
@@ -266,14 +266,18 @@ shouldWrapUpOrIsInitiator(context, event) {
|
|
|
266
266
|
return Boolean(event.taskData?.wrapUpRequired || context.consultInitiator);
|
|
267
267
|
}
|
|
268
268
|
|
|
269
|
-
// Check whether the
|
|
270
|
-
|
|
269
|
+
// Check whether the current agent left the main interaction
|
|
270
|
+
didCurrentAgentLeaveMainInteraction(context, event) {
|
|
271
271
|
const selfAgentId = getSelfAgentId(context, event.taskData);
|
|
272
272
|
if (!selfAgentId) return false;
|
|
273
273
|
|
|
274
274
|
const participantIdFromEvent = 'participantId' in event ? event.participantId : undefined;
|
|
275
275
|
const participantId = participantIdFromEvent ?? event.taskData?.participantId;
|
|
276
|
-
|
|
276
|
+
if (Boolean(participantId) && participantId === selfAgentId) return true;
|
|
277
|
+
// Explicit hasLeft or removal of a previously active self from the participant map is terminal.
|
|
278
|
+
// PARTICIPANT_LEAVE naming another participant does not infer self departure from media.
|
|
279
|
+
// Only a from-conference CONSULT_END may compare mainCall membership, and only when self
|
|
280
|
+
// remains active in the participant map and on the consult leg. Partial ordinary calls are false.
|
|
277
281
|
}
|
|
278
282
|
```
|
|
279
283
|
|
|
@@ -30,7 +30,7 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
30
30
|
2. `createActor(machine).start()`
|
|
31
31
|
3. `TaskManager` and task APIs map external signals to `TaskEvent`
|
|
32
32
|
4. Actor transitions update context and execute action overrides
|
|
33
|
-
5. `Task` recomputes
|
|
33
|
+
5. `Task` recomputes per-leg controls plus ordered Consult/Transfer destination availability and emits task-level events when either changes
|
|
34
34
|
|
|
35
35
|
---
|
|
36
36
|
|
|
@@ -464,10 +464,10 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
464
464
|
- Guard: none
|
|
465
465
|
- Actions: `clearTransferConferenceRequested`
|
|
466
466
|
- `PARTICIPANT_LEAVE` -> `WRAPPING_UP`
|
|
467
|
-
- Guard: `guards.
|
|
467
|
+
- Guard: `guards.didCurrentAgentLeaveMainInteraction && guards.shouldWrapUp`
|
|
468
468
|
- Actions: `updateTaskData`, `handleParticipantLeft`, `markEnded`, `clearConsultState`, `emitTaskParticipantLeft`, `emitTaskWrapup`
|
|
469
469
|
- `PARTICIPANT_LEAVE` -> `TERMINATED`
|
|
470
|
-
- Guard: `guards.
|
|
470
|
+
- Guard: `guards.didCurrentAgentLeaveMainInteraction`
|
|
471
471
|
- Actions: `updateTaskData`, `handleParticipantLeft`, `markEnded`, `clearConsultState`, `emitTaskParticipantLeft`, `emitTaskEnd`
|
|
472
472
|
- `PARTICIPANT_LEAVE` -> `CONNECTED`
|
|
473
473
|
- Guard: `guards.shouldDowngradeConferenceToConnected`
|
|
@@ -475,6 +475,15 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
475
475
|
- `PARTICIPANT_LEAVE` -> stay `CONFERENCING` (default)
|
|
476
476
|
- Guard: default
|
|
477
477
|
- Actions: `updateTaskData`, `handleParticipantLeft`, `emitTaskParticipantLeft`
|
|
478
|
+
|
|
479
|
+
`didCurrentAgentLeaveMainInteraction` treats an explicit self participant ID,
|
|
480
|
+
self `hasLeft`, or removal from a previously active participant map as terminal.
|
|
481
|
+
A `PARTICIPANT_LEAVE` event naming another participant does not infer departure
|
|
482
|
+
from media membership. The previous-versus-updated `mainCall` comparison is
|
|
483
|
+
restricted to from-conference `CONSULT_END` nested-consult cleanup when self
|
|
484
|
+
remains active in the participant map and on the consult leg; partial ordinary CONNECTED/HELD
|
|
485
|
+
snapshots remain non-terminal.
|
|
486
|
+
|
|
478
487
|
- `CONFERENCE_END` -> `WRAPPING_UP`
|
|
479
488
|
- Guard: `guards.shouldWrapUp`
|
|
480
489
|
- Actions: `updateTaskData`, `markEnded`, `clearConsultState`, `emitTaskWrapup`
|
|
@@ -809,7 +818,7 @@ Complete mapping from backend CC_EVENTS to internal TaskEvent types.
|
|
|
809
818
|
| API `task.consultConference()` | `MERGE_TO_CONFERENCE` | CONSULTING → CONF_INITIATING | Starts merge flow |
|
|
810
819
|
| `AgentConsultConferenced` | `CONFERENCE_START` | CONSULTING/CONF_INITIATING → CONFERENCING | `handleConferenceStarted` path |
|
|
811
820
|
| `ParticipantJoinedConference` | `CONFERENCE_START` | CONFERENCING → CONFERENCING | Refresh + emit conference started |
|
|
812
|
-
| `ParticipantLeftConference` | `PARTICIPANT_LEAVE` |
|
|
821
|
+
| `ParticipantLeftConference` | `PARTICIPANT_LEAVE` | Any active call-control state → WRAPPING_UP / TERMINATED / CONNECTED / stay | Uses `didCurrentAgentLeaveMainInteraction`, `shouldWrapUp`, `shouldDowngradeConferenceToConnected` |
|
|
813
822
|
| `AgentConsultConferenceEnded` | `CONFERENCE_END` | CONFERENCING → WRAPPING_UP / CONNECTED / TERMINATED | Guard-based branch |
|
|
814
823
|
| `AgentConsultConferenceFailed` | `CONFERENCE_FAILED` | CONF_INITIATING → CONSULTING | Merge failed fallback |
|
|
815
824
|
| `AgentConferenceTransferred` | `TRANSFER_CONFERENCE_SUCCESS` | CONSULTING/CONFERENCING branch logic | Initiator/receiver dependent |
|
|
@@ -921,8 +930,8 @@ stateDiagram-v2
|
|
|
921
930
|
|
|
922
931
|
%% CONFERENCING
|
|
923
932
|
CONFERENCING --> CONSULT_INITIATING: CONSULT (State Machine Event)
|
|
924
|
-
CONFERENCING --> WRAPPING_UP: PARTICIPANT_LEAVE (CC Event) -> PARTICIPANT_LEAVE (State Machine Event) [
|
|
925
|
-
CONFERENCING --> TERMINATED: PARTICIPANT_LEAVE (CC Event) -> PARTICIPANT_LEAVE (State Machine Event) [
|
|
933
|
+
CONFERENCING --> WRAPPING_UP: PARTICIPANT_LEAVE (CC Event) -> PARTICIPANT_LEAVE (State Machine Event) [didCurrentAgentLeaveMainInteraction && shouldWrapUp]
|
|
934
|
+
CONFERENCING --> TERMINATED: PARTICIPANT_LEAVE (CC Event) -> PARTICIPANT_LEAVE (State Machine Event) [didCurrentAgentLeaveMainInteraction]
|
|
926
935
|
CONFERENCING --> CONNECTED: PARTICIPANT_LEAVE (CC Event) -> PARTICIPANT_LEAVE (State Machine Event) [shouldDowngradeConferenceToConnected]
|
|
927
936
|
CONFERENCING --> WRAPPING_UP: CONFERENCE_END (CC Event) -> CONFERENCE_END (State Machine Event) [shouldWrapUp]
|
|
928
937
|
CONFERENCING --> CONNECTED: CONFERENCE_END (CC Event) -> CONFERENCE_END (State Machine Event) [customerInCall]
|
|
@@ -1038,8 +1047,8 @@ stateDiagram-v2
|
|
|
1038
1047
|
CONFERENCING --> CONFERENCING: AGENT_CONFERENCE_TRANSFERRED -> TRANSFER_CONFERENCE_SUCCESS
|
|
1039
1048
|
CONFERENCING --> CONFERENCING: AGENT_CONFERENCE_TRANSFER_FAILED-> TRANSFER_CONFERENCE_FAILED
|
|
1040
1049
|
|
|
1041
|
-
CONFERENCING --> WRAPPING_UP: PARTICIPANT_LEFT_CONFERENCE -> PARTICIPANT_LEAVE [
|
|
1042
|
-
CONFERENCING --> TERMINATED: PARTICIPANT_LEFT_CONFERENCE -> PARTICIPANT_LEAVE [
|
|
1050
|
+
CONFERENCING --> WRAPPING_UP: PARTICIPANT_LEFT_CONFERENCE -> PARTICIPANT_LEAVE [didCurrentAgentLeaveMainInteraction && shouldWrapUp]
|
|
1051
|
+
CONFERENCING --> TERMINATED: PARTICIPANT_LEFT_CONFERENCE -> PARTICIPANT_LEAVE [didCurrentAgentLeaveMainInteraction]
|
|
1043
1052
|
CONFERENCING --> CONNECTED: PARTICIPANT_LEFT_CONFERENCE -> PARTICIPANT_LEAVE [shouldDowngradeConferenceToConnected]
|
|
1044
1053
|
CONFERENCING --> WRAPPING_UP: AGENT_CONSULT_CONFERENCE_ENDED -> CONFERENCE_END [shouldWrapUp]
|
|
1045
1054
|
CONFERENCING --> CONNECTED: AGENT_CONSULT_CONFERENCE_ENDED -> CONFERENCE_END [customerInCall]
|