@webex/contact-center 3.12.0-llmrefactor.1 → 3.12.0-llmrefactor.10
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 +7 -5
- package/ai-docs/ARCHITECTURE.md +1 -1
- package/ai-docs/CONTRACTS.md +8 -3
- 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 +544 -12
- 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/MetricsManager.js +16 -0
- package/dist/metrics/MetricsManager.js.map +1 -1
- package/dist/metrics/behavioral-events.js +104 -0
- package/dist/metrics/behavioral-events.js.map +1 -1
- package/dist/metrics/constants.js +18 -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 +202 -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 +222 -0
- package/dist/services/WebexCrossClientService.js.map +1 -0
- package/dist/services/WxAppTelephonyMercurySync.js +108 -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 +490 -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 +162 -53
- 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 +7 -10
- 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 +456 -15
- 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 +354 -0
- package/dist/services/task/voice/wxAppVoiceMethods.js.map +1 -0
- package/dist/services/wxAppDiagnosticLogging.js +122 -0
- package/dist/services/wxAppDiagnosticLogging.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 +78 -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/MetricsManager.d.ts +6 -0
- package/dist/types/metrics/constants.d.ts +17 -0
- package/dist/types/services/AddressBook.d.ts +2 -1
- package/dist/types/services/AnswerCallOnWebexService.d.ts +38 -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 +32 -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 +304 -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 +52 -9
- package/dist/types/services/task/voice/WebRTC.d.ts +2 -2
- package/dist/types/services/task/voice/wxAppVoiceMethods.d.ts +55 -0
- package/dist/types/services/wxAppDiagnosticLogging.d.ts +51 -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 +8 -8
- package/src/cc.ts +657 -12
- package/src/config.ts +7 -0
- package/src/constants.ts +8 -0
- package/src/index.ts +2 -0
- package/src/metrics/MetricsManager.ts +16 -0
- package/src/metrics/ai-docs/metrics-spec.md +78 -10
- package/src/metrics/behavioral-events.ts +106 -0
- package/src/metrics/constants.ts +20 -0
- package/src/services/AddressBook.ts +17 -6
- package/src/services/AnswerCallOnWebexService.ts +239 -0
- package/src/services/EntryPoint.ts +59 -60
- package/src/services/Queue.ts +29 -12
- package/src/services/WebexCrossClientService.ts +293 -0
- package/src/services/WxAppTelephonyMercurySync.ts +142 -0
- package/src/services/agent/ai-docs/agent-spec.md +1 -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 +716 -17
- 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 +156 -3
- 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 +235 -81
- package/src/services/task/state-machine/actions.ts +5 -2
- package/src/services/task/state-machine/ai-docs/AGENTS.md +6 -4
- package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +35 -16
- package/src/services/task/state-machine/ai-docs/task-state-machine-spec.md +103 -33
- package/src/services/task/state-machine/guards.ts +7 -10
- 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 +595 -14
- package/src/services/task/voice/WebRTC.ts +5 -1
- package/src/services/task/voice/wxAppVoiceMethods.ts +516 -0
- package/src/services/wxAppDiagnosticLogging.ts +174 -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 +1522 -19
- package/test/unit/spec/metrics/MetricsManager.ts +25 -0
- package/test/unit/spec/metrics/behavioral-events.ts +60 -0
- package/test/unit/spec/services/AddressBook.ts +37 -6
- package/test/unit/spec/services/AnswerCallOnWebexService.ts +264 -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 +467 -0
- package/test/unit/spec/services/WxAppTelephonyMercurySync.ts +136 -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 +274 -6
- package/test/unit/spec/services/task/TaskFactory.ts +39 -2
- package/test/unit/spec/services/task/TaskManager.ts +1717 -9
- 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 +1485 -109
- 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 +1412 -0
- package/test/unit/spec/services/task/voice/wxAppVoiceMethods.ts +603 -0
- package/test/unit/spec/services/wxAppDiagnosticLogging.ts +143 -0
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
|
@@ -52,12 +52,81 @@ 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
|
+
],
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
guard: guards.didCurrentAgentLeaveMainInteraction,
|
|
80
|
+
target: TaskState.TERMINATED,
|
|
81
|
+
actions: [
|
|
82
|
+
'updateTaskData',
|
|
83
|
+
'handleParticipantLeft',
|
|
84
|
+
'markEnded',
|
|
85
|
+
'clearConsultState',
|
|
86
|
+
'emitTaskParticipantLeft',
|
|
87
|
+
'emitTaskEnd',
|
|
88
|
+
],
|
|
89
|
+
},
|
|
90
|
+
];
|
|
91
|
+
|
|
92
|
+
const exitConferenceSuccessTransitions = () => [
|
|
93
|
+
{
|
|
94
|
+
guard: guards.shouldWrapUp,
|
|
95
|
+
target: TaskState.WRAPPING_UP,
|
|
96
|
+
actions: ['updateTaskData', 'markEnded', 'clearConsultState'],
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
target: TaskState.TERMINATED,
|
|
100
|
+
actions: ['updateTaskData', 'markEnded', 'clearConsultState', 'emitTaskEnd'],
|
|
101
|
+
},
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
const currentAgentConsultEndTransitions = () => [
|
|
105
|
+
{
|
|
106
|
+
guard: (params) =>
|
|
107
|
+
guards.didCurrentAgentLeaveMainInteraction(params) && guards.shouldWrapUp(params),
|
|
108
|
+
target: TaskState.WRAPPING_UP,
|
|
109
|
+
actions: [
|
|
110
|
+
'updateTaskData',
|
|
111
|
+
'markEnded',
|
|
112
|
+
'clearConsultState',
|
|
113
|
+
'emitTaskConsultEnd',
|
|
114
|
+
'emitTaskWrapup',
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
guard: guards.didCurrentAgentLeaveMainInteraction,
|
|
119
|
+
target: TaskState.TERMINATED,
|
|
120
|
+
actions: [
|
|
121
|
+
'updateTaskData',
|
|
122
|
+
'markEnded',
|
|
123
|
+
'clearConsultState',
|
|
124
|
+
'emitTaskConsultEnd',
|
|
125
|
+
'emitTaskEnd',
|
|
126
|
+
],
|
|
127
|
+
},
|
|
128
|
+
];
|
|
129
|
+
|
|
61
130
|
return {
|
|
62
131
|
id: 'taskStateMachine',
|
|
63
132
|
initial: TaskState.IDLE,
|
|
@@ -70,7 +139,7 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
70
139
|
actions: ['updateTaskData', 'syncTaskDataFromEvent'],
|
|
71
140
|
},
|
|
72
141
|
[TaskEvent.CONTACT_OWNER_CHANGED]: {
|
|
73
|
-
actions: ['updateTaskData', 'syncTaskDataFromEvent'],
|
|
142
|
+
actions: ['updateTaskData', 'syncTaskDataFromEvent', 'emitTaskHydrate'],
|
|
74
143
|
},
|
|
75
144
|
// HYDRATE: Update task data from AgentContact event
|
|
76
145
|
// Note: State restoration with transitions is handled in IDLE state.
|
|
@@ -190,10 +259,17 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
190
259
|
target: TaskState.TERMINATED,
|
|
191
260
|
actions: ['updateTaskData', 'markEnded', 'emitTaskReject'],
|
|
192
261
|
},
|
|
193
|
-
[TaskEvent.TASK_WRAPUP]:
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
262
|
+
[TaskEvent.TASK_WRAPUP]: [
|
|
263
|
+
{
|
|
264
|
+
guard: guards.shouldWrapUp,
|
|
265
|
+
target: TaskState.WRAPPING_UP,
|
|
266
|
+
actions: ['updateTaskData', 'markEnded'],
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
target: TaskState.TERMINATED,
|
|
270
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskEnd'],
|
|
271
|
+
},
|
|
272
|
+
],
|
|
197
273
|
[TaskEvent.CONTACT_ENDED]: {
|
|
198
274
|
target: TaskState.TERMINATED,
|
|
199
275
|
actions: ['updateTaskData', 'markEnded', 'emitTaskEnd'],
|
|
@@ -334,6 +410,7 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
334
410
|
},
|
|
335
411
|
// AgentConsultEnded from Stable Prod while on connected leg (external end consult).
|
|
336
412
|
[TaskEvent.CONSULT_END]: [
|
|
413
|
+
...currentAgentConsultEndTransitions(),
|
|
337
414
|
{
|
|
338
415
|
guard: ({context, event}) => {
|
|
339
416
|
if (context.consultInitiator !== true) return false;
|
|
@@ -378,14 +455,26 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
378
455
|
],
|
|
379
456
|
[TaskEvent.TASK_WRAPUP]: {
|
|
380
457
|
target: TaskState.WRAPPING_UP,
|
|
381
|
-
actions: ['updateTaskData', 'markEnded'
|
|
458
|
+
actions: ['updateTaskData', 'markEnded'],
|
|
382
459
|
},
|
|
460
|
+
[TaskEvent.OUTBOUND_FAILED]: [
|
|
461
|
+
{
|
|
462
|
+
guard: guards.shouldWrapUp,
|
|
463
|
+
target: TaskState.WRAPPING_UP,
|
|
464
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskWrapup'],
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
target: TaskState.TERMINATED,
|
|
468
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskEnd'],
|
|
469
|
+
},
|
|
470
|
+
],
|
|
383
471
|
[TaskEvent.PAUSE_RECORDING]: {
|
|
384
472
|
actions: ['updateTaskData', 'setRecordingState', 'emitTaskRecordingPaused'],
|
|
385
473
|
},
|
|
386
474
|
[TaskEvent.RESUME_RECORDING]: {
|
|
387
475
|
actions: ['updateTaskData', 'setRecordingState', 'emitTaskRecordingResumed'],
|
|
388
476
|
},
|
|
477
|
+
[TaskEvent.EXIT_CONFERENCE_SUCCESS]: exitConferenceSuccessTransitions(),
|
|
389
478
|
},
|
|
390
479
|
},
|
|
391
480
|
|
|
@@ -401,6 +490,21 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
401
490
|
target: TaskState.CONNECTED,
|
|
402
491
|
actions: ['updateTaskData'],
|
|
403
492
|
},
|
|
493
|
+
[TaskEvent.OUTBOUND_FAILED]: [
|
|
494
|
+
{
|
|
495
|
+
guard: guards.shouldWrapUp,
|
|
496
|
+
target: TaskState.WRAPPING_UP,
|
|
497
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskWrapup'],
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
target: TaskState.TERMINATED,
|
|
501
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskEnd'],
|
|
502
|
+
},
|
|
503
|
+
],
|
|
504
|
+
[TaskEvent.TASK_WRAPUP]: {
|
|
505
|
+
target: TaskState.WRAPPING_UP,
|
|
506
|
+
actions: ['updateTaskData', 'markEnded'],
|
|
507
|
+
},
|
|
404
508
|
},
|
|
405
509
|
},
|
|
406
510
|
|
|
@@ -487,14 +591,31 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
487
591
|
},
|
|
488
592
|
],
|
|
489
593
|
// AgentConsultEnded from Stable Prod while main leg is held (external end consult).
|
|
490
|
-
[TaskEvent.CONSULT_END]:
|
|
491
|
-
|
|
492
|
-
|
|
594
|
+
[TaskEvent.CONSULT_END]: [
|
|
595
|
+
...currentAgentConsultEndTransitions(),
|
|
596
|
+
{actions: ['updateTaskData', 'clearConsultState', 'emitTaskConsultEnd']},
|
|
597
|
+
],
|
|
598
|
+
[TaskEvent.PARTICIPANT_LEAVE]: [
|
|
599
|
+
...currentAgentParticipantLeaveTransitions(),
|
|
600
|
+
{actions: ['updateTaskData', 'handleParticipantLeft', 'emitTaskParticipantLeft']},
|
|
601
|
+
],
|
|
493
602
|
// TODO: This may not be a valid transition, this needs to be checked as well
|
|
494
603
|
[TaskEvent.TASK_WRAPUP]: {
|
|
495
604
|
target: TaskState.WRAPPING_UP,
|
|
496
|
-
actions: ['updateTaskData', 'markEnded'
|
|
605
|
+
actions: ['updateTaskData', 'markEnded'],
|
|
497
606
|
},
|
|
607
|
+
[TaskEvent.OUTBOUND_FAILED]: [
|
|
608
|
+
{
|
|
609
|
+
guard: guards.shouldWrapUp,
|
|
610
|
+
target: TaskState.WRAPPING_UP,
|
|
611
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskWrapup'],
|
|
612
|
+
},
|
|
613
|
+
{
|
|
614
|
+
target: TaskState.TERMINATED,
|
|
615
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskEnd'],
|
|
616
|
+
},
|
|
617
|
+
],
|
|
618
|
+
[TaskEvent.EXIT_CONFERENCE_SUCCESS]: exitConferenceSuccessTransitions(),
|
|
498
619
|
},
|
|
499
620
|
},
|
|
500
621
|
|
|
@@ -507,6 +628,25 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
507
628
|
[TaskEvent.UNHOLD_FAILED]: {
|
|
508
629
|
target: TaskState.HELD,
|
|
509
630
|
},
|
|
631
|
+
[TaskEvent.PARTICIPANT_LEAVE]: [
|
|
632
|
+
...currentAgentParticipantLeaveTransitions(),
|
|
633
|
+
{actions: ['updateTaskData', 'handleParticipantLeft', 'emitTaskParticipantLeft']},
|
|
634
|
+
],
|
|
635
|
+
[TaskEvent.OUTBOUND_FAILED]: [
|
|
636
|
+
{
|
|
637
|
+
guard: guards.shouldWrapUp,
|
|
638
|
+
target: TaskState.WRAPPING_UP,
|
|
639
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskWrapup'],
|
|
640
|
+
},
|
|
641
|
+
{
|
|
642
|
+
target: TaskState.TERMINATED,
|
|
643
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskEnd'],
|
|
644
|
+
},
|
|
645
|
+
],
|
|
646
|
+
[TaskEvent.TASK_WRAPUP]: {
|
|
647
|
+
target: TaskState.WRAPPING_UP,
|
|
648
|
+
actions: ['updateTaskData', 'markEnded'],
|
|
649
|
+
},
|
|
510
650
|
},
|
|
511
651
|
},
|
|
512
652
|
|
|
@@ -569,6 +709,7 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
569
709
|
],
|
|
570
710
|
// AgentConsultEnded from Stable Prod during consult initiation (external end consult).
|
|
571
711
|
[TaskEvent.CONSULT_END]: [
|
|
712
|
+
...currentAgentConsultEndTransitions(),
|
|
572
713
|
{
|
|
573
714
|
guard: guards.isPrimaryMediaOnHold,
|
|
574
715
|
target: TaskState.HELD,
|
|
@@ -579,6 +720,25 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
579
720
|
actions: ['updateTaskData', 'clearConsultState', 'emitTaskConsultEnd'],
|
|
580
721
|
},
|
|
581
722
|
],
|
|
723
|
+
[TaskEvent.PARTICIPANT_LEAVE]: [
|
|
724
|
+
...currentAgentParticipantLeaveTransitions(),
|
|
725
|
+
{actions: ['updateTaskData', 'handleParticipantLeft', 'emitTaskParticipantLeft']},
|
|
726
|
+
],
|
|
727
|
+
[TaskEvent.OUTBOUND_FAILED]: [
|
|
728
|
+
{
|
|
729
|
+
guard: guards.shouldWrapUp,
|
|
730
|
+
target: TaskState.WRAPPING_UP,
|
|
731
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskWrapup'],
|
|
732
|
+
},
|
|
733
|
+
{
|
|
734
|
+
target: TaskState.TERMINATED,
|
|
735
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskEnd'],
|
|
736
|
+
},
|
|
737
|
+
],
|
|
738
|
+
[TaskEvent.TASK_WRAPUP]: {
|
|
739
|
+
target: TaskState.WRAPPING_UP,
|
|
740
|
+
actions: ['updateTaskData', 'markEnded'],
|
|
741
|
+
},
|
|
582
742
|
},
|
|
583
743
|
},
|
|
584
744
|
|
|
@@ -619,6 +779,7 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
619
779
|
|
|
620
780
|
// AgentConsultEnded
|
|
621
781
|
[TaskEvent.CONSULT_END]: [
|
|
782
|
+
...currentAgentConsultEndTransitions(),
|
|
622
783
|
{
|
|
623
784
|
// Initiator returning to conference only while conference is still active.
|
|
624
785
|
guard: ({context, event}) =>
|
|
@@ -686,7 +847,13 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
686
847
|
{
|
|
687
848
|
// Consulted agent → TERMINATED
|
|
688
849
|
target: TaskState.TERMINATED,
|
|
689
|
-
actions: [
|
|
850
|
+
actions: [
|
|
851
|
+
'updateTaskData',
|
|
852
|
+
'markEnded',
|
|
853
|
+
'clearConsultState',
|
|
854
|
+
'emitTaskConsultEnd',
|
|
855
|
+
'emitTaskEnd',
|
|
856
|
+
],
|
|
690
857
|
},
|
|
691
858
|
],
|
|
692
859
|
|
|
@@ -705,34 +872,10 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
705
872
|
},
|
|
706
873
|
|
|
707
874
|
[TaskEvent.PARTICIPANT_LEAVE]: [
|
|
875
|
+
...currentAgentParticipantLeaveTransitions(),
|
|
708
876
|
{
|
|
709
877
|
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) &&
|
|
878
|
+
!guards.didCurrentAgentLeaveMainInteraction(params) &&
|
|
736
879
|
guards.shouldDowngradeConferenceToConnected(params),
|
|
737
880
|
target: TaskState.CONNECTED,
|
|
738
881
|
actions: [
|
|
@@ -775,7 +918,6 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
775
918
|
'clearConsultState',
|
|
776
919
|
'handleTransferConferenceSuccess',
|
|
777
920
|
'clearTransferConferenceRequested',
|
|
778
|
-
'emitTaskWrapup',
|
|
779
921
|
],
|
|
780
922
|
},
|
|
781
923
|
{
|
|
@@ -823,8 +965,19 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
823
965
|
},
|
|
824
966
|
[TaskEvent.TASK_WRAPUP]: {
|
|
825
967
|
target: TaskState.WRAPPING_UP,
|
|
826
|
-
actions: ['updateTaskData', 'markEnded', 'clearConsultState'
|
|
968
|
+
actions: ['updateTaskData', 'markEnded', 'clearConsultState'],
|
|
827
969
|
},
|
|
970
|
+
[TaskEvent.OUTBOUND_FAILED]: [
|
|
971
|
+
{
|
|
972
|
+
guard: guards.shouldWrapUp,
|
|
973
|
+
target: TaskState.WRAPPING_UP,
|
|
974
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskWrapup'],
|
|
975
|
+
},
|
|
976
|
+
{
|
|
977
|
+
target: TaskState.TERMINATED,
|
|
978
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskEnd'],
|
|
979
|
+
},
|
|
980
|
+
],
|
|
828
981
|
[TaskEvent.MERGE_TO_CONFERENCE]: {
|
|
829
982
|
target: TaskState.CONF_INITIATING,
|
|
830
983
|
},
|
|
@@ -860,6 +1013,7 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
860
1013
|
},
|
|
861
1014
|
// AgentConsultEnded while conference is initiating (end call before conference completes)
|
|
862
1015
|
[TaskEvent.CONSULT_END]: [
|
|
1016
|
+
...currentAgentConsultEndTransitions(),
|
|
863
1017
|
{
|
|
864
1018
|
guard: ({event}) => {
|
|
865
1019
|
const taskData = getTaskDataFromEvent(event);
|
|
@@ -874,6 +1028,21 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
874
1028
|
actions: ['updateTaskData', 'clearConsultState'],
|
|
875
1029
|
},
|
|
876
1030
|
],
|
|
1031
|
+
[TaskEvent.OUTBOUND_FAILED]: [
|
|
1032
|
+
{
|
|
1033
|
+
guard: guards.shouldWrapUp,
|
|
1034
|
+
target: TaskState.WRAPPING_UP,
|
|
1035
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskWrapup'],
|
|
1036
|
+
},
|
|
1037
|
+
{
|
|
1038
|
+
target: TaskState.TERMINATED,
|
|
1039
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskEnd'],
|
|
1040
|
+
},
|
|
1041
|
+
],
|
|
1042
|
+
[TaskEvent.TASK_WRAPUP]: {
|
|
1043
|
+
target: TaskState.WRAPPING_UP,
|
|
1044
|
+
actions: ['updateTaskData', 'markEnded'],
|
|
1045
|
+
},
|
|
877
1046
|
},
|
|
878
1047
|
},
|
|
879
1048
|
|
|
@@ -887,20 +1056,11 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
887
1056
|
'emitTaskConferenceStarted',
|
|
888
1057
|
],
|
|
889
1058
|
},
|
|
890
|
-
[TaskEvent.EXIT_CONFERENCE_SUCCESS]:
|
|
891
|
-
{
|
|
892
|
-
guard: guards.shouldWrapUp,
|
|
893
|
-
target: TaskState.WRAPPING_UP,
|
|
894
|
-
actions: ['updateTaskData', 'markEnded', 'clearConsultState', 'emitTaskWrapup'],
|
|
895
|
-
},
|
|
896
|
-
{
|
|
897
|
-
target: TaskState.TERMINATED,
|
|
898
|
-
actions: ['updateTaskData', 'markEnded', 'clearConsultState', 'emitTaskEnd'],
|
|
899
|
-
},
|
|
900
|
-
],
|
|
1059
|
+
[TaskEvent.EXIT_CONFERENCE_SUCCESS]: exitConferenceSuccessTransitions(),
|
|
901
1060
|
|
|
902
1061
|
// Needed as all agents in conference get this event, hence we need to clear the consult state
|
|
903
1062
|
[TaskEvent.CONSULT_END]: [
|
|
1063
|
+
...currentAgentConsultEndTransitions(),
|
|
904
1064
|
{
|
|
905
1065
|
guard: ({context, event}) => {
|
|
906
1066
|
const taskData = getTaskDataFromEvent(event);
|
|
@@ -975,37 +1135,11 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
975
1135
|
|
|
976
1136
|
// Participant leaves - handle conference downgrade scenarios
|
|
977
1137
|
[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
|
-
},
|
|
1138
|
+
...currentAgentParticipantLeaveTransitions(),
|
|
1005
1139
|
{
|
|
1006
1140
|
// Conference downgraded, customer present → CONNECTED
|
|
1007
1141
|
guard: (params) =>
|
|
1008
|
-
!guards.
|
|
1142
|
+
!guards.didCurrentAgentLeaveMainInteraction(params) &&
|
|
1009
1143
|
guards.shouldDowngradeConferenceToConnected(params),
|
|
1010
1144
|
target: TaskState.CONNECTED,
|
|
1011
1145
|
actions: [
|
|
@@ -1040,7 +1174,6 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
1040
1174
|
'clearConsultState',
|
|
1041
1175
|
'handleTransferConferenceSuccess',
|
|
1042
1176
|
'clearTransferConferenceRequested',
|
|
1043
|
-
'emitTaskWrapup',
|
|
1044
1177
|
],
|
|
1045
1178
|
},
|
|
1046
1179
|
{
|
|
@@ -1075,7 +1208,7 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
1075
1208
|
// Agent who should wrap up → WRAPPING_UP
|
|
1076
1209
|
guard: guards.shouldWrapUp,
|
|
1077
1210
|
target: TaskState.WRAPPING_UP,
|
|
1078
|
-
actions: ['updateTaskData', 'markEnded', 'clearConsultState'
|
|
1211
|
+
actions: ['updateTaskData', 'markEnded', 'clearConsultState'],
|
|
1079
1212
|
},
|
|
1080
1213
|
{
|
|
1081
1214
|
// Customer still in call → CONNECTED
|
|
@@ -1113,8 +1246,19 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
1113
1246
|
[TaskEvent.TASK_WRAPUP]: {
|
|
1114
1247
|
guard: guards.shouldWrapUp,
|
|
1115
1248
|
target: TaskState.WRAPPING_UP,
|
|
1116
|
-
actions: ['updateTaskData', 'markEnded', 'clearConsultState'
|
|
1249
|
+
actions: ['updateTaskData', 'markEnded', 'clearConsultState'],
|
|
1117
1250
|
},
|
|
1251
|
+
[TaskEvent.OUTBOUND_FAILED]: [
|
|
1252
|
+
{
|
|
1253
|
+
guard: guards.shouldWrapUp,
|
|
1254
|
+
target: TaskState.WRAPPING_UP,
|
|
1255
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskWrapup'],
|
|
1256
|
+
},
|
|
1257
|
+
{
|
|
1258
|
+
target: TaskState.TERMINATED,
|
|
1259
|
+
actions: ['updateTaskData', 'markEnded', 'emitTaskOutdialFailed', 'emitTaskEnd'],
|
|
1260
|
+
},
|
|
1261
|
+
],
|
|
1118
1262
|
},
|
|
1119
1263
|
},
|
|
1120
1264
|
|
|
@@ -1122,6 +1266,16 @@ export function getTaskStateMachineConfig(uiControlConfig: UIControlConfig) {
|
|
|
1122
1266
|
// Only emit wrapup event on entry - task:end should only be emitted when COMPLETED
|
|
1123
1267
|
entry: ['emitTaskWrapup'],
|
|
1124
1268
|
on: {
|
|
1269
|
+
// Late AgentWrapup after conference exit already entered WRAPPING_UP
|
|
1270
|
+
[TaskEvent.TASK_WRAPUP]: [
|
|
1271
|
+
{
|
|
1272
|
+
guard: ({context}) => context.taskData?.wrapUpRequired === true,
|
|
1273
|
+
actions: ['updateTaskData'],
|
|
1274
|
+
},
|
|
1275
|
+
{
|
|
1276
|
+
actions: ['updateTaskData', 'emitTaskWrapup'],
|
|
1277
|
+
},
|
|
1278
|
+
],
|
|
1125
1279
|
// AgentWrappedup Event
|
|
1126
1280
|
[TaskEvent.WRAPUP_COMPLETE]: {
|
|
1127
1281
|
target: TaskState.COMPLETED,
|
|
@@ -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,16 @@ 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
|
+
// Self missing from the updated participants map is terminal (EP-DN removal).
|
|
278
|
+
// Remaining in the map with hasLeft, or disappearing only from mainCall media, is not.
|
|
277
279
|
}
|
|
278
280
|
```
|
|
279
281
|
|