@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
|
@@ -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
|
|
|
@@ -94,8 +94,11 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
94
94
|
- `CONSULTING_ACTIVE` -> `CONSULTING`
|
|
95
95
|
- Guard: none
|
|
96
96
|
- Actions: `updateTaskData`, `setConsultAgentJoined`, `emitTaskConsultAccepted`, `emitTaskConsulting`
|
|
97
|
-
- `TASK_WRAPUP` -> `
|
|
98
|
-
- Guard:
|
|
97
|
+
- `TASK_WRAPUP` -> `WRAPPING_UP`
|
|
98
|
+
- Guard: `guards.shouldWrapUp`
|
|
99
|
+
- Actions: `updateTaskData`, `markEnded`; `WRAPPING_UP` entry emits `task:wrapup`
|
|
100
|
+
- `TASK_WRAPUP` -> `TERMINATED` (default branch)
|
|
101
|
+
- Guard: default
|
|
99
102
|
- Actions: `updateTaskData`, `markEnded`, `emitTaskEnd`
|
|
100
103
|
- `RONA` / `ASSIGN_FAILED` / `INVITE_FAILED` / `OUTBOUND_FAILED` -> `TERMINATED`
|
|
101
104
|
- Guard: none
|
|
@@ -159,7 +162,7 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
159
162
|
- Actions: `updateTaskData`, `markEnded`, `emitTaskEnd`
|
|
160
163
|
- `TASK_WRAPUP` -> `WRAPPING_UP`
|
|
161
164
|
- Guard: none
|
|
162
|
-
- Actions: `updateTaskData`, `markEnded
|
|
165
|
+
- Actions: `updateTaskData`, `markEnded`; `WRAPPING_UP` entry emits `task:wrapup`
|
|
163
166
|
- `PAUSE_RECORDING` / `RESUME_RECORDING` -> Stay `CONNECTED`
|
|
164
167
|
- Guard: none
|
|
165
168
|
- Actions: `updateTaskData`, `setRecordingState`, `emitTaskRecordingPaused` / `emitTaskRecordingResumed`
|
|
@@ -366,7 +369,7 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
366
369
|
- Actions: `updateTaskData`, `handleTransferConferenceSuccess`, `clearTransferConferenceRequested`
|
|
367
370
|
- `TRANSFER_CONFERENCE_SUCCESS` -> `WRAPPING_UP`
|
|
368
371
|
- Guard: `guards.shouldWrapUp`
|
|
369
|
-
- Actions: `updateTaskData`, `markEnded`, `clearConsultState`, `handleTransferConferenceSuccess`, `clearTransferConferenceRequested
|
|
372
|
+
- Actions: `updateTaskData`, `markEnded`, `clearConsultState`, `handleTransferConferenceSuccess`, `clearTransferConferenceRequested`; `WRAPPING_UP` entry emits `task:wrapup`
|
|
370
373
|
- `TRANSFER_CONFERENCE_SUCCESS` -> `CONFERENCING`
|
|
371
374
|
- Guard: inline `!context.consultInitiator`
|
|
372
375
|
- Actions: `updateTaskData`, `clearConsultState`, `handleTransferConferenceSuccess`, `clearTransferConferenceRequested`
|
|
@@ -384,7 +387,7 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
384
387
|
- Actions: `updateTaskData`, `markEnded`, `clearConsultState`, `emitTaskWrapup`, `requestCleanup`
|
|
385
388
|
- `TASK_WRAPUP` -> `WRAPPING_UP`
|
|
386
389
|
- Guard: none
|
|
387
|
-
- Actions: `updateTaskData`, `markEnded`, `clearConsultState
|
|
390
|
+
- Actions: `updateTaskData`, `markEnded`, `clearConsultState`; `WRAPPING_UP` entry emits `task:wrapup`
|
|
388
391
|
- `MERGE_TO_CONFERENCE` -> `CONF_INITIATING`
|
|
389
392
|
- Guard: none
|
|
390
393
|
- Actions: none
|
|
@@ -464,10 +467,10 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
464
467
|
- Guard: none
|
|
465
468
|
- Actions: `clearTransferConferenceRequested`
|
|
466
469
|
- `PARTICIPANT_LEAVE` -> `WRAPPING_UP`
|
|
467
|
-
- Guard: `guards.
|
|
468
|
-
- Actions: `updateTaskData`, `handleParticipantLeft`, `markEnded`, `clearConsultState`, `emitTaskParticipantLeft
|
|
470
|
+
- Guard: `guards.didCurrentAgentLeaveMainInteraction && guards.shouldWrapUp`
|
|
471
|
+
- Actions: `updateTaskData`, `handleParticipantLeft`, `markEnded`, `clearConsultState`, `emitTaskParticipantLeft` (entry emits `task:wrapup`)
|
|
469
472
|
- `PARTICIPANT_LEAVE` -> `TERMINATED`
|
|
470
|
-
- Guard: `guards.
|
|
473
|
+
- Guard: `guards.didCurrentAgentLeaveMainInteraction`
|
|
471
474
|
- Actions: `updateTaskData`, `handleParticipantLeft`, `markEnded`, `clearConsultState`, `emitTaskParticipantLeft`, `emitTaskEnd`
|
|
472
475
|
- `PARTICIPANT_LEAVE` -> `CONNECTED`
|
|
473
476
|
- Guard: `guards.shouldDowngradeConferenceToConnected`
|
|
@@ -475,15 +478,29 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
475
478
|
- `PARTICIPANT_LEAVE` -> stay `CONFERENCING` (default)
|
|
476
479
|
- Guard: default
|
|
477
480
|
- Actions: `updateTaskData`, `handleParticipantLeft`, `emitTaskParticipantLeft`
|
|
481
|
+
|
|
482
|
+
`didCurrentAgentLeaveMainInteraction` treats an explicit self participant ID
|
|
483
|
+
or absence from the updated participants map as terminal (EP-DN removal).
|
|
484
|
+
Remaining in the map with `hasLeft`, or disappearing only from `mainCall` media,
|
|
485
|
+
is not treated as departure. `PARTICIPANT_LEAVE` is handled in `HELD`,
|
|
486
|
+
`RESUME_INITIATING`, `CONSULTING`, `CONSULT_INITIATING`, and `CONFERENCING`;
|
|
487
|
+
`CONNECTED`, `HOLD_INITIATING`, and `CONF_INITIATING` ignore the event.
|
|
488
|
+
|
|
489
|
+
- `EXIT_CONFERENCE_SUCCESS` -> `WRAPPING_UP` or `TERMINATED`
|
|
490
|
+
- Guard: `guards.shouldWrapUp` or default
|
|
491
|
+
- Actions: `updateTaskData`, `markEnded`, `clearConsultState`, or `emitTaskEnd` on terminate; `WRAPPING_UP` entry emits `task:wrapup` (shared helper on `CONNECTED`, `HELD`, and `CONFERENCING` for Voice HTTP exit)
|
|
478
492
|
- `CONFERENCE_END` -> `WRAPPING_UP`
|
|
479
493
|
- Guard: `guards.shouldWrapUp`
|
|
480
|
-
- Actions: `updateTaskData`, `markEnded`, `clearConsultState
|
|
494
|
+
- Actions: `updateTaskData`, `markEnded`, `clearConsultState`; `WRAPPING_UP` entry emits `task:wrapup`
|
|
481
495
|
- `CONFERENCE_END` -> `CONNECTED`
|
|
482
496
|
- Guard: inline `!context.exitingConference && customerInCall`
|
|
483
497
|
- Actions: `updateTaskData`, `clearConsultState`, `emitTaskConferenceEnded`
|
|
484
498
|
- `CONFERENCE_END` -> `TERMINATED` (default branch)
|
|
485
499
|
- Guard: default
|
|
486
500
|
- Actions: `updateTaskData`, `markEnded`, `clearConsultState`, `emitTaskEnd`
|
|
501
|
+
- `TASK_WRAPUP` -> `WRAPPING_UP`
|
|
502
|
+
- Guard: `guards.shouldWrapUp`
|
|
503
|
+
- Actions: `updateTaskData`, `markEnded`, `clearConsultState`; `WRAPPING_UP` entry emits `task:wrapup`
|
|
487
504
|
- `CONTACT_ENDED` -> stay `CONFERENCING`
|
|
488
505
|
- Guard: none
|
|
489
506
|
- Actions: `updateTaskData`, `requestCleanup`
|
|
@@ -505,6 +522,8 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
505
522
|
|
|
506
523
|
**Valid transitions from `WRAPPING_UP`**:
|
|
507
524
|
|
|
525
|
+
- `TASK_WRAPUP` -> stay `WRAPPING_UP`
|
|
526
|
+
- Guard: if `context.taskData.wrapUpRequired === true`, `updateTaskData` only; else `updateTaskData`, `emitTaskWrapup`
|
|
508
527
|
- `WRAPUP_COMPLETE` -> `COMPLETED`
|
|
509
528
|
- Guard: none
|
|
510
529
|
- Actions: `updateTaskData`
|
|
@@ -749,7 +768,7 @@ Complete mapping from backend CC_EVENTS to internal TaskEvent types.
|
|
|
749
768
|
| `PARTICIPANT_JOINED_CONFERENCE` | `CONFERENCE_START` | `CONSULTING` / `CONF_INITIATING` / `CONFERENCING` | `CONFERENCING` / same | Conference participant joined |
|
|
750
769
|
| `AGENT_CONSULT_CONFERENCE_FAILED` | `CONFERENCE_FAILED` | `CONF_INITIATING` | `CONSULTING` | Merge fail fallback |
|
|
751
770
|
| `AGENT_CONSULT_CONFERENCE_ENDED` | `CONFERENCE_END` | `CONFERENCING` | `WRAPPING_UP` / `CONNECTED` / `TERMINATED` | Guard-driven |
|
|
752
|
-
| `PARTICIPANT_LEFT_CONFERENCE` | `PARTICIPANT_LEAVE` | `CONFERENCING`
|
|
771
|
+
| `PARTICIPANT_LEFT_CONFERENCE` | `PARTICIPANT_LEAVE` | `HELD` / `RESUME_INITIATING` / `CONSULTING` / `CONSULT_INITIATING` / `CONFERENCING` | `WRAPPING_UP` / `TERMINATED` / `CONNECTED` / same | Named self or omitted from participant map; `CONNECTED` / `HOLD_INITIATING` / `CONF_INITIATING` ignore |
|
|
753
772
|
| `AGENT_CONFERENCE_TRANSFERRED` | `TRANSFER_CONFERENCE_SUCCESS` | `CONSULTING` / `CONFERENCING` | `WRAPPING_UP` / `CONFERENCING` / `TERMINATED` / same | Initiator/receiver dependent |
|
|
754
773
|
|
|
755
774
|
### Explicitly not mapped to state machine
|
|
@@ -809,7 +828,7 @@ Complete mapping from backend CC_EVENTS to internal TaskEvent types.
|
|
|
809
828
|
| API `task.consultConference()` | `MERGE_TO_CONFERENCE` | CONSULTING → CONF_INITIATING | Starts merge flow |
|
|
810
829
|
| `AgentConsultConferenced` | `CONFERENCE_START` | CONSULTING/CONF_INITIATING → CONFERENCING | `handleConferenceStarted` path |
|
|
811
830
|
| `ParticipantJoinedConference` | `CONFERENCE_START` | CONFERENCING → CONFERENCING | Refresh + emit conference started |
|
|
812
|
-
| `ParticipantLeftConference` | `PARTICIPANT_LEAVE` | CONFERENCING → WRAPPING_UP / TERMINATED / CONNECTED / stay | Uses `
|
|
831
|
+
| `ParticipantLeftConference` | `PARTICIPANT_LEAVE` | HELD / RESUME_INITIATING / CONSULTING / CONSULT_INITIATING / CONFERENCING → WRAPPING_UP / TERMINATED / CONNECTED / stay; CONNECTED / HOLD_INITIATING / CONF_INITIATING ignore | Uses `didCurrentAgentLeaveMainInteraction` (named self or omitted from participant map), `shouldWrapUp`, `shouldDowngradeConferenceToConnected` |
|
|
813
832
|
| `AgentConsultConferenceEnded` | `CONFERENCE_END` | CONFERENCING → WRAPPING_UP / CONNECTED / TERMINATED | Guard-based branch |
|
|
814
833
|
| `AgentConsultConferenceFailed` | `CONFERENCE_FAILED` | CONF_INITIATING → CONSULTING | Merge failed fallback |
|
|
815
834
|
| `AgentConferenceTransferred` | `TRANSFER_CONFERENCE_SUCCESS` | CONSULTING/CONFERENCING branch logic | Initiator/receiver dependent |
|
|
@@ -921,8 +940,8 @@ stateDiagram-v2
|
|
|
921
940
|
|
|
922
941
|
%% CONFERENCING
|
|
923
942
|
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) [
|
|
943
|
+
CONFERENCING --> WRAPPING_UP: PARTICIPANT_LEAVE (CC Event) -> PARTICIPANT_LEAVE (State Machine Event) [didCurrentAgentLeaveMainInteraction && shouldWrapUp]
|
|
944
|
+
CONFERENCING --> TERMINATED: PARTICIPANT_LEAVE (CC Event) -> PARTICIPANT_LEAVE (State Machine Event) [didCurrentAgentLeaveMainInteraction]
|
|
926
945
|
CONFERENCING --> CONNECTED: PARTICIPANT_LEAVE (CC Event) -> PARTICIPANT_LEAVE (State Machine Event) [shouldDowngradeConferenceToConnected]
|
|
927
946
|
CONFERENCING --> WRAPPING_UP: CONFERENCE_END (CC Event) -> CONFERENCE_END (State Machine Event) [shouldWrapUp]
|
|
928
947
|
CONFERENCING --> CONNECTED: CONFERENCE_END (CC Event) -> CONFERENCE_END (State Machine Event) [customerInCall]
|
|
@@ -1038,8 +1057,8 @@ stateDiagram-v2
|
|
|
1038
1057
|
CONFERENCING --> CONFERENCING: AGENT_CONFERENCE_TRANSFERRED -> TRANSFER_CONFERENCE_SUCCESS
|
|
1039
1058
|
CONFERENCING --> CONFERENCING: AGENT_CONFERENCE_TRANSFER_FAILED-> TRANSFER_CONFERENCE_FAILED
|
|
1040
1059
|
|
|
1041
|
-
CONFERENCING --> WRAPPING_UP: PARTICIPANT_LEFT_CONFERENCE -> PARTICIPANT_LEAVE [
|
|
1042
|
-
CONFERENCING --> TERMINATED: PARTICIPANT_LEFT_CONFERENCE -> PARTICIPANT_LEAVE [
|
|
1060
|
+
CONFERENCING --> WRAPPING_UP: PARTICIPANT_LEFT_CONFERENCE -> PARTICIPANT_LEAVE [didCurrentAgentLeaveMainInteraction && shouldWrapUp]
|
|
1061
|
+
CONFERENCING --> TERMINATED: PARTICIPANT_LEFT_CONFERENCE -> PARTICIPANT_LEAVE [didCurrentAgentLeaveMainInteraction]
|
|
1043
1062
|
CONFERENCING --> CONNECTED: PARTICIPANT_LEFT_CONFERENCE -> PARTICIPANT_LEAVE [shouldDowngradeConferenceToConnected]
|
|
1044
1063
|
CONFERENCING --> WRAPPING_UP: AGENT_CONSULT_CONFERENCE_ENDED -> CONFERENCE_END [shouldWrapUp]
|
|
1045
1064
|
CONFERENCING --> CONNECTED: AGENT_CONSULT_CONFERENCE_ENDED -> CONFERENCE_END [customerInCall]
|
|
@@ -74,10 +74,11 @@ See root `CONTRACTS.md` for the package-level state-control export.
|
|
|
74
74
|
| TASK_STATE_MACHINE-R-001 | Map typed Task events through the XState graph and preserve guards/actions for offer, assignment, consult, conference, transfer, wrapup, termination, and hydration. | A deterministic event vocabulary isolates lifecycle policy from transport payloads. | `src/services/task/state-machine/TaskStateMachine.ts` | `test/unit/spec/services/task/state-machine/TaskStateMachine.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
|
|
75
75
|
| TASK_STATE_MACHINE-R-002 | Keep `handleConferenceFailed`, `handleSwitchToMainCall`, and `handleSwitchToConsult` wired where the graph invokes them; retain `forceConsultInitiator` as defined-but-currently-unwired. | Incorrect absence/wiring claims cause maintainers to duplicate or remove real actions. | `src/services/task/state-machine/actions.ts` | `test/unit/spec/services/task/state-machine/TaskStateMachine.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
|
|
76
76
|
| TASK_STATE_MACHINE-R-003 | Treat `syncTaskDataFromEvent` as a Task-supplied machine implementation, not a default action in `actions.ts`. | The reusable graph declares the action name while Task owns integration-specific data synchronization. | `src/services/task/Task.ts` | `test/unit/spec/services/task/Task.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
|
|
77
|
-
| TASK_STATE_MACHINE-R-004 | Compute
|
|
77
|
+
| TASK_STATE_MACHINE-R-004 | Compute per-leg action controls and ordered `consultTransferDestinations.consult`/`.transfer` arrays through `uiControlsComputer`, preserving the public `getDefaultUIControls` shape with empty destination arrays. Voice queue rules use Consult profile enablement or Transfer direction plus `callProcessingDetails.outdialTransferToQueueEnabled`; digital supports agent/queue only; profile `NONE` removes the matching category. | Applications depend on one deterministic Task control surface, the default order (`agent`, `queue`, `dialNumber`, `entryPoint`), and correct action/media/profile gating. | `src/services/task/state-machine/uiControlsComputer.ts` | `test/unit/spec/services/task/state-machine/uiControlsComputer.ts` | Consumers may further hide allowed categories but must not infer or enable omitted categories. | PRESENT |
|
|
78
78
|
| TASK_STATE_MACHINE-R-005 | Keep authentication and credentials outside the state-machine layer; it receives typed Task data/events and never invokes authenticated transport. | Pure transition logic remains reusable and cannot leak or mutate host authentication state. | `src/services/task/state-machine/TaskStateMachine.ts`, `src/services/task/state-machine/types.ts` | `test/unit/spec/services/task/state-machine/TaskStateMachine.ts` | None; security/auth applicability is explicitly N/A. | PRESENT |
|
|
79
79
|
| TASK_STATE_MACHINE-R-006 | Treat `UIControlConfig` values as Task-supplied capability configuration, not rollout flags evaluated or owned by the state machine. | Rollout and profile policy must be resolved before actor construction so transitions remain deterministic. | `src/services/task/state-machine/types.ts`, `src/services/task/Task.ts` | `test/unit/spec/services/task/Task.ts` | None; rollout ownership is explicit. | PRESENT |
|
|
80
80
|
| TASK_STATE_MACHINE-R-007 | Keep logging and metrics in Task/TaskManager integration; the state-machine implementation has no LoggerProxy or MetricsManager dependency. | Separating observability side effects from guards/actions preserves deterministic transition tests. | `src/services/task/state-machine/TaskStateMachine.ts`, `src/services/task/Task.ts` | `test/unit/spec/services/task/state-machine/TaskStateMachine.ts`, `test/unit/spec/services/task/Task.ts` | None; observability ownership is explicit. | PRESENT |
|
|
81
|
+
| TASK_STATE_MACHINE-R-008 | `CONTACT_OWNER_CHANGED` must synchronize task/context data and emit `task:hydrate` without transitioning state. A TaskManager-recovered promoted-Agent task first receives an internal IDLE `HYDRATE` before listener installation, then the original owner-change event produces exactly one external hydrate and no incoming event. TaskManager maps an owner-changing `ContactUpdated` for an existing task to that owner-change event, while same-owner or owner-less updates remain `CONTACT_UPDATED`; missing-task `ContactUpdated` does not create a task. It also preserves an already confirmed active owner from a late participant-left snapshot that still names the departed owner. Participant Drop must rely on the existing `ParticipantLeftConference` mapping rather than adding an initiating state event. `PARTICIPANT_LEAVE` is handled in `HELD`, `RESUME_INITIATING`, `CONSULTING`, `CONSULT_INITIATING`, and `CONFERENCING`; `CONNECTED`, `HOLD_INITIATING`, and `CONF_INITIATING` ignore the event. The current Agent is treated as departed only when the event names that Agent or the updated participants map omits that Agent (EP-DN removal). Remaining in the map with `hasLeft`, or disappearing only from `mainCall` media, is non-terminal. `CONSULT_END` does not use mainCall membership as self-departure evidence. Removed accepted Agents emit `task:consultEnd` plus `task:end`, surviving initiators recover to their main call, and an unaccepted OFFERED consultee emits only `task:consultEnd`. Starting Consult must preserve the prior task snapshot used by the guard. | Owner-sensitive consumers must rerender promptly while owner selection, participant removal, consult removal, and narrowly scoped desynchronization recovery remain backend-authoritative and compatible with existing incoming-task callback behavior. | `src/services/task/state-machine/TaskStateMachine.ts`, `src/services/task/state-machine/actions.ts`, `src/services/task/state-machine/guards.ts`, `src/services/task/TaskManager.ts` | `test/unit/spec/services/task/Task.ts`, `test/unit/spec/services/task/TaskManager.ts`, `test/unit/spec/services/task/state-machine/TaskStateMachine.ts`, `test/unit/spec/services/task/state-machine/guards.ts` | Backend ownership-successor selection and delivery of complete recovery payloads are outside this module. | PRESENT |
|
|
81
82
|
|
|
82
83
|
## Design Overview
|
|
83
84
|
TaskManager maps Contact Center notifications to `TaskEvent` values. Each Task sends those events to its XState actor built by `createTaskStateMachine()`. The configuration applies guards and named actions, updates `TaskContext`, and computes UI controls. Task supplies the integration-specific `syncTaskDataFromEvent` implementation through machine options; it is not a default action in `actions.ts`.
|
|
@@ -215,6 +216,14 @@ sequenceDiagram
|
|
|
215
216
|
|
|
216
217
|
### Hydrate and recovery
|
|
217
218
|
|
|
219
|
+
When TaskManager narrowly recovers a missing promoted-Agent task from a complete
|
|
220
|
+
`ContactOwnerChanged` payload, it sends `HYDRATE` while the new actor is still
|
|
221
|
+
unobserved so the IDLE guards restore CONNECTED, HELD, CONFERENCING, or another
|
|
222
|
+
backend-represented state. TaskManager then installs listeners and forwards the
|
|
223
|
+
original `CONTACT_OWNER_CHANGED`; only that second event emits the single public
|
|
224
|
+
`task:hydrate`. Recovery never emits `task:incoming`, and missing-task
|
|
225
|
+
`ContactUpdated` does not use this path.
|
|
226
|
+
|
|
218
227
|
```mermaid
|
|
219
228
|
sequenceDiagram
|
|
220
229
|
participant TM as TaskManager
|
|
@@ -507,14 +516,16 @@ shouldWrapUpOrIsInitiator(context, event) {
|
|
|
507
516
|
return Boolean(event.taskData?.wrapUpRequired || context.consultInitiator);
|
|
508
517
|
}
|
|
509
518
|
|
|
510
|
-
// Check whether the
|
|
511
|
-
|
|
519
|
+
// Check whether the current agent left the main interaction
|
|
520
|
+
didCurrentAgentLeaveMainInteraction(context, event) {
|
|
512
521
|
const selfAgentId = getSelfAgentId(context, event.taskData);
|
|
513
522
|
if (!selfAgentId) return false;
|
|
514
523
|
|
|
515
524
|
const participantIdFromEvent = 'participantId' in event ? event.participantId : undefined;
|
|
516
525
|
const participantId = participantIdFromEvent ?? event.taskData?.participantId;
|
|
517
|
-
|
|
526
|
+
if (Boolean(participantId) && participantId === selfAgentId) return true;
|
|
527
|
+
// Self missing from the updated participants map is terminal (EP-DN removal).
|
|
528
|
+
// Remaining in the map with hasLeft, or disappearing only from mainCall media, is not.
|
|
518
529
|
}
|
|
519
530
|
|
|
520
531
|
// True when this agent initiated the conference transfer (widgets or desktop).
|
|
@@ -859,9 +870,15 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
859
870
|
|
|
860
871
|
- Actions: `updateTaskData`, `setConsultAgentJoined`, `emitTaskConsultAccepted`, `emitTaskConsulting`
|
|
861
872
|
|
|
873
|
+
- `TASK_WRAPUP` -> `WRAPPING_UP`
|
|
874
|
+
|
|
875
|
+
- Guard: `guards.shouldWrapUp`
|
|
876
|
+
|
|
877
|
+
- Actions: `updateTaskData`, `markEnded`; `WRAPPING_UP` entry emits `task:wrapup`
|
|
878
|
+
|
|
862
879
|
- `TASK_WRAPUP` -> `TERMINATED`
|
|
863
880
|
|
|
864
|
-
- Guard:
|
|
881
|
+
- Guard: default (when wrap-up is not required)
|
|
865
882
|
|
|
866
883
|
- Actions: `updateTaskData`, `markEnded`, `emitTaskEnd`
|
|
867
884
|
|
|
@@ -971,7 +988,7 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
971
988
|
|
|
972
989
|
- Guard: none
|
|
973
990
|
|
|
974
|
-
- Actions: `updateTaskData`, `markEnded
|
|
991
|
+
- Actions: `updateTaskData`, `markEnded`; `WRAPPING_UP` entry emits `task:wrapup`
|
|
975
992
|
|
|
976
993
|
- `PAUSE_RECORDING` / `RESUME_RECORDING` -> Stay `CONNECTED`
|
|
977
994
|
|
|
@@ -979,6 +996,12 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
979
996
|
|
|
980
997
|
- Actions: `updateTaskData`, `setRecordingState`, `emitTaskRecordingPaused` / `emitTaskRecordingResumed`
|
|
981
998
|
|
|
999
|
+
- `EXIT_CONFERENCE_SUCCESS` -> `WRAPPING_UP` or `TERMINATED`
|
|
1000
|
+
|
|
1001
|
+
- Guard: `guards.shouldWrapUp` (wrap-up branch) or default (terminate)
|
|
1002
|
+
|
|
1003
|
+
- Actions: `updateTaskData`, `markEnded`, `clearConsultState`, or `emitTaskEnd`; `WRAPPING_UP` entry emits `task:wrapup` (same as `CONFERENCING`; Voice `exitConference()` while actor stays `CONNECTED` with conference in task data)
|
|
1004
|
+
|
|
982
1005
|
**Description**: Main call is on hold.
|
|
983
1006
|
|
|
984
1007
|
**How this state is reached (incoming transitions)**:
|
|
@@ -1073,7 +1096,13 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
1073
1096
|
|
|
1074
1097
|
- Guard: none
|
|
1075
1098
|
|
|
1076
|
-
- Actions: `updateTaskData`, `markEnded
|
|
1099
|
+
- Actions: `updateTaskData`, `markEnded`; `WRAPPING_UP` entry emits `task:wrapup`
|
|
1100
|
+
|
|
1101
|
+
- `EXIT_CONFERENCE_SUCCESS` -> `WRAPPING_UP` or `TERMINATED`
|
|
1102
|
+
|
|
1103
|
+
- Guard: `guards.shouldWrapUp` or default
|
|
1104
|
+
|
|
1105
|
+
- Actions: `updateTaskData`, `markEnded`, `clearConsultState`, or `emitTaskEnd`; `WRAPPING_UP` entry emits `task:wrapup` (shared with `CONNECTED` / `CONFERENCING`)
|
|
1077
1106
|
|
|
1078
1107
|
**Description**: Hold request has been sent and is awaiting backend confirmation.
|
|
1079
1108
|
|
|
@@ -1099,6 +1128,12 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
1099
1128
|
|
|
1100
1129
|
- Actions: `updateTaskData`
|
|
1101
1130
|
|
|
1131
|
+
- `TASK_WRAPUP` -> `WRAPPING_UP`
|
|
1132
|
+
|
|
1133
|
+
- Guard: none
|
|
1134
|
+
|
|
1135
|
+
- Actions: `updateTaskData`, `markEnded` (`WRAPPING_UP` entry emits `task:wrapup`)
|
|
1136
|
+
|
|
1102
1137
|
**Description**: Resume/unhold request has been sent and is awaiting backend confirmation.
|
|
1103
1138
|
|
|
1104
1139
|
**How this state is reached (incoming transitions)**:
|
|
@@ -1123,6 +1158,12 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
1123
1158
|
|
|
1124
1159
|
- Actions: none
|
|
1125
1160
|
|
|
1161
|
+
- `TASK_WRAPUP` -> `WRAPPING_UP`
|
|
1162
|
+
|
|
1163
|
+
- Guard: none
|
|
1164
|
+
|
|
1165
|
+
- Actions: `updateTaskData`, `markEnded` (`WRAPPING_UP` entry emits `task:wrapup`)
|
|
1166
|
+
|
|
1126
1167
|
**Description**: Consult request is in-flight.
|
|
1127
1168
|
|
|
1128
1169
|
**How this state is reached (incoming transitions)**:
|
|
@@ -1289,7 +1330,7 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
1289
1330
|
|
|
1290
1331
|
- Guard: `guards.shouldWrapUp`
|
|
1291
1332
|
|
|
1292
|
-
- Actions: `updateTaskData`, `markEnded`, `clearConsultState`, `handleTransferConferenceSuccess`, `clearTransferConferenceRequested
|
|
1333
|
+
- Actions: `updateTaskData`, `markEnded`, `clearConsultState`, `handleTransferConferenceSuccess`, `clearTransferConferenceRequested`; `WRAPPING_UP` entry emits `task:wrapup`
|
|
1293
1334
|
|
|
1294
1335
|
- `TRANSFER_CONFERENCE_SUCCESS` -> `CONFERENCING`
|
|
1295
1336
|
|
|
@@ -1311,19 +1352,19 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
1311
1352
|
|
|
1312
1353
|
- `PARTICIPANT_LEAVE` -> `WRAPPING_UP`
|
|
1313
1354
|
|
|
1314
|
-
- Guard: `guards.
|
|
1355
|
+
- Guard: `guards.didCurrentAgentLeaveMainInteraction && guards.shouldWrapUp`
|
|
1315
1356
|
|
|
1316
|
-
- Actions: `updateTaskData`, `handleParticipantLeft`, `markEnded`, `clearConsultState`, `emitTaskParticipantLeft
|
|
1357
|
+
- Actions: `updateTaskData`, `handleParticipantLeft`, `markEnded`, `clearConsultState`, `emitTaskParticipantLeft` (entry emits `task:wrapup`)
|
|
1317
1358
|
|
|
1318
1359
|
- `PARTICIPANT_LEAVE` -> `TERMINATED`
|
|
1319
1360
|
|
|
1320
|
-
- Guard: `guards.
|
|
1361
|
+
- Guard: `guards.didCurrentAgentLeaveMainInteraction`
|
|
1321
1362
|
|
|
1322
1363
|
- Actions: `updateTaskData`, `handleParticipantLeft`, `markEnded`, `clearConsultState`, `emitTaskParticipantLeft`, `emitTaskEnd`
|
|
1323
1364
|
|
|
1324
1365
|
- `PARTICIPANT_LEAVE` -> `CONNECTED`
|
|
1325
1366
|
|
|
1326
|
-
- Guard:
|
|
1367
|
+
- Guard: `guards.shouldDowngradeConferenceToConnected` (after current-agent departure guards)
|
|
1327
1368
|
|
|
1328
1369
|
- Actions: `updateTaskData`, `handleParticipantLeft`, `clearConsultState`, `emitTaskParticipantLeft`, `emitTaskConferenceEnded`
|
|
1329
1370
|
|
|
@@ -1349,7 +1390,7 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
1349
1390
|
|
|
1350
1391
|
- Guard: none
|
|
1351
1392
|
|
|
1352
|
-
- Actions: `updateTaskData`, `markEnded`, `clearConsultState
|
|
1393
|
+
- Actions: `updateTaskData`, `markEnded`, `clearConsultState`; `WRAPPING_UP` entry emits `task:wrapup`
|
|
1353
1394
|
|
|
1354
1395
|
- `MERGE_TO_CONFERENCE` -> `CONF_INITIATING`
|
|
1355
1396
|
|
|
@@ -1441,6 +1482,12 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
1441
1482
|
|
|
1442
1483
|
- Actions: `updateTaskData`, `clearConsultState`, `emitTaskConferenceStarted`
|
|
1443
1484
|
|
|
1485
|
+
- `EXIT_CONFERENCE_SUCCESS` -> `WRAPPING_UP` or `TERMINATED`
|
|
1486
|
+
|
|
1487
|
+
- Guard: `guards.shouldWrapUp` or default
|
|
1488
|
+
|
|
1489
|
+
- Actions: `updateTaskData`, `markEnded`, `clearConsultState`, or `emitTaskEnd`; `WRAPPING_UP` entry emits `task:wrapup` (shared with `CONNECTED` / `HELD`)
|
|
1490
|
+
|
|
1444
1491
|
- `CONSULT_END` -> stay `CONFERENCING`
|
|
1445
1492
|
|
|
1446
1493
|
- Guard: none
|
|
@@ -1469,7 +1516,7 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
1469
1516
|
|
|
1470
1517
|
- Guard: `guards.shouldWrapUp`
|
|
1471
1518
|
|
|
1472
|
-
- Actions: `updateTaskData`, `markEnded`, `clearConsultState`, `handleTransferConferenceSuccess`, `clearTransferConferenceRequested
|
|
1519
|
+
- Actions: `updateTaskData`, `markEnded`, `clearConsultState`, `handleTransferConferenceSuccess`, `clearTransferConferenceRequested`; `WRAPPING_UP` entry emits `task:wrapup`
|
|
1473
1520
|
|
|
1474
1521
|
- `TRANSFER_CONFERENCE_SUCCESS` -> `CONFERENCING`
|
|
1475
1522
|
|
|
@@ -1491,13 +1538,13 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
1491
1538
|
|
|
1492
1539
|
- `PARTICIPANT_LEAVE` -> `WRAPPING_UP`
|
|
1493
1540
|
|
|
1494
|
-
- Guard: `guards.
|
|
1541
|
+
- Guard: `guards.didCurrentAgentLeaveMainInteraction && guards.shouldWrapUp`
|
|
1495
1542
|
|
|
1496
|
-
- Actions: `updateTaskData`, `handleParticipantLeft`, `markEnded`, `clearConsultState`, `emitTaskParticipantLeft
|
|
1543
|
+
- Actions: `updateTaskData`, `handleParticipantLeft`, `markEnded`, `clearConsultState`, `emitTaskParticipantLeft` (entry emits `task:wrapup`)
|
|
1497
1544
|
|
|
1498
1545
|
- `PARTICIPANT_LEAVE` -> `TERMINATED`
|
|
1499
1546
|
|
|
1500
|
-
- Guard: `guards.
|
|
1547
|
+
- Guard: `guards.didCurrentAgentLeaveMainInteraction`
|
|
1501
1548
|
|
|
1502
1549
|
- Actions: `updateTaskData`, `handleParticipantLeft`, `markEnded`, `clearConsultState`, `emitTaskParticipantLeft`, `emitTaskEnd`
|
|
1503
1550
|
|
|
@@ -1513,11 +1560,19 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
1513
1560
|
|
|
1514
1561
|
- Actions: `updateTaskData`, `handleParticipantLeft`, `emitTaskParticipantLeft`
|
|
1515
1562
|
|
|
1563
|
+
Customer hangup and agent-initiated customer Drop share this backend event.
|
|
1564
|
+
When two or more active conference participants survive on the main leg, the
|
|
1565
|
+
customer is removed from the authoritative snapshot while the task remains
|
|
1566
|
+
`CONFERENCING`; no `task:conferenceEnded` event is emitted. When another
|
|
1567
|
+
agent/endpoint leaves, the same rule preserves the remaining conference, and
|
|
1568
|
+
the guarded `CONNECTED` branch is used only after the conference participant
|
|
1569
|
+
count falls below two while the customer remains.
|
|
1570
|
+
|
|
1516
1571
|
- `CONFERENCE_END` -> `WRAPPING_UP`
|
|
1517
1572
|
|
|
1518
1573
|
- Guard: `guards.shouldWrapUp`
|
|
1519
1574
|
|
|
1520
|
-
- Actions: `updateTaskData`, `markEnded`, `clearConsultState
|
|
1575
|
+
- Actions: `updateTaskData`, `markEnded`, `clearConsultState`; `WRAPPING_UP` entry emits `task:wrapup`
|
|
1521
1576
|
|
|
1522
1577
|
- `CONFERENCE_END` -> `CONNECTED`
|
|
1523
1578
|
|
|
@@ -1537,6 +1592,12 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
1537
1592
|
|
|
1538
1593
|
- Actions: `updateTaskData`, `requestCleanup`
|
|
1539
1594
|
|
|
1595
|
+
- `TASK_WRAPUP` -> `WRAPPING_UP`
|
|
1596
|
+
|
|
1597
|
+
- Guard: `guards.shouldWrapUp`
|
|
1598
|
+
|
|
1599
|
+
- Actions: `updateTaskData`, `markEnded`, `clearConsultState`; `WRAPPING_UP` entry emits `task:wrapup`
|
|
1600
|
+
|
|
1540
1601
|
**Description**: Post-interaction work (ACW) is in progress.
|
|
1541
1602
|
|
|
1542
1603
|
**How this state is reached (incoming transitions)**:
|
|
@@ -1551,6 +1612,10 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
1551
1612
|
|
|
1552
1613
|
**Valid transitions from `WRAPPING_UP`**:
|
|
1553
1614
|
|
|
1615
|
+
- `TASK_WRAPUP` -> stay `WRAPPING_UP`
|
|
1616
|
+
|
|
1617
|
+
- Guard: if `context.taskData.wrapUpRequired === true` before the event, actions are `updateTaskData` only; otherwise `updateTaskData`, `emitTaskWrapup` (late AgentWrapup after wrap-up was already published)
|
|
1618
|
+
|
|
1554
1619
|
- `WRAPUP_COMPLETE` -> `COMPLETED`
|
|
1555
1620
|
|
|
1556
1621
|
- Guard: none
|
|
@@ -1561,7 +1626,7 @@ It is instantiated by `Task` and receives mapped backend/user events through `se
|
|
|
1561
1626
|
|
|
1562
1627
|
**Description**: Final wrapped-up terminal state.
|
|
1563
1628
|
|
|
1564
|
-
**Entry Actions
|
|
1629
|
+
**Entry Actions** (order matters — `emitTaskWrappedup` before `cleanupResources` so subscribers receive intact task data):
|
|
1565
1630
|
|
|
1566
1631
|
- `emitTaskWrappedup`
|
|
1567
1632
|
|
|
@@ -1730,8 +1795,8 @@ Complete mapping from backend CC_EVENTS to internal TaskEvent types.
|
|
|
1730
1795
|
| `AGENT_CONTACT_RESERVED` | `TASK_INCOMING` | `IDLE` | `OFFERED` | Incoming task entry |
|
|
1731
1796
|
| `AGENT_OFFER_CONTACT` | `TASK_OFFERED` | `OFFERED` | `OFFERED` | Offer payload refresh |
|
|
1732
1797
|
| `AGENT_CONTACT` | `HYDRATE` | `IDLE` | `WRAPPING_UP` / `CONSULTING` / `HELD` / `CONNECTED` / `CONFERENCING` / `IDLE` | Guard-based restore |
|
|
1733
|
-
| `CONTACT_UPDATED` | `CONTACT_UPDATED`
|
|
1734
|
-
| `CONTACT_OWNER_CHANGED` | `CONTACT_OWNER_CHANGED` | any | same | Context sync
|
|
1798
|
+
| `CONTACT_UPDATED` | `CONTACT_UPDATED` or `CONTACT_OWNER_CHANGED` | any | same | Owner delta uses existing hydrate path; same/missing owner is context sync only |
|
|
1799
|
+
| `CONTACT_OWNER_CHANGED` | `CONTACT_OWNER_CHANGED` | any | same | Context/data sync + `task:hydrate` |
|
|
1735
1800
|
| `AGENT_OFFER_CONSULT` | `OFFER_CONSULT` | `OFFERED` | `OFFERED` | Receiver-side consult offer |
|
|
1736
1801
|
| `AGENT_CONTACT_ASSIGNED` | `ASSIGN` | `OFFERED` / `CONNECTED` / `CONSULTING` | `CONNECTED` | Assign/reassign |
|
|
1737
1802
|
| `AGENT_CONTACT_HELD` | `HOLD_SUCCESS` | `HOLD_INITIATING` | `HELD` | Includes `mediaResourceId` |
|
|
@@ -1746,16 +1811,16 @@ Complete mapping from backend CC_EVENTS to internal TaskEvent types.
|
|
|
1746
1811
|
| `AGENT_BLIND_TRANSFERRED` | `TRANSFER_SUCCESS` | `CONNECTED` / `HELD` / `CONSULTING` | `WRAPPING_UP` / `CONNECTED` | `shouldWrapUpOrIsInitiator` |
|
|
1747
1812
|
| `AGENT_CONSULT_TRANSFERRED` | `TRANSFER_SUCCESS` | `CONNECTED` / `HELD` / `CONSULTING` | `WRAPPING_UP` / `CONNECTED` | Same path |
|
|
1748
1813
|
| `AGENT_VTEAM_TRANSFERRED` | `TRANSFER_SUCCESS` | `CONNECTED` / `HELD` / `CONSULTING` | `WRAPPING_UP` / `CONNECTED` | Same path |
|
|
1749
|
-
| `AGENT_WRAPUP` | `TASK_WRAPUP` | `OFFERED` / `CONNECTED` / `HELD` / `CONSULTING` | `
|
|
1814
|
+
| `AGENT_WRAPUP` | `TASK_WRAPUP` | `OFFERED` / `CONNECTED` / `HELD` / `CONSULTING` | `WRAPPING_UP` / `TERMINATED` | `shouldWrapUp` selects wrap-up; default terminates (wxApp outdial pre-accept agent end may wrap while still `OFFERED`) |
|
|
1750
1815
|
| `AGENT_BLIND_TRANSFER_FAILED` | `TRANSFER_FAILED` | `CONNECTED` / `HELD` / `CONSULTING` | same | Context update |
|
|
1751
1816
|
| `AGENT_VTEAM_TRANSFER_FAILED` | `TRANSFER_FAILED` | `CONNECTED` / `HELD` / `CONSULTING` | same | Context update |
|
|
1752
1817
|
| `AGENT_CONSULT_TRANSFER_FAILED` | `TRANSFER_FAILED` | `CONNECTED` / `HELD` / `CONSULTING` | same | Context update |
|
|
1753
1818
|
| `AGENT_CONFERENCE_TRANSFER_FAILED` | `TRANSFER_FAILED` | `CONNECTED` / `HELD` / `CONSULTING` | same | Context update |
|
|
1754
|
-
| `CONTACT_ENDED` | `CONTACT_ENDED`
|
|
1819
|
+
| `CONTACT_ENDED` | `CONTACT_ENDED` or `OUTBOUND_FAILED` | `OFFERED` / `CONNECTED` / `HELD` / `CONSULTING` / `CONFERENCING` | `WRAPPING_UP` / `TERMINATED` / etc. | wxApp outdial pre-accept decline → `CONTACT_ENDED` → `TERMINATED` (no wrapup) when `wxAppAnswerPending` is false and `agentsPendingWrapUp` is empty (backend may still send `interaction.state: wrapUp`). Post-accept agent end remaps to `OUTBOUND_FAILED` (`AGENT_ENDS`) when `wxAppAnswerPending` or wrapup pending — including while SM is still `OFFERED` before `ASSIGN`. |
|
|
1755
1820
|
| `AGENT_INVITE_FAILED` | `INVITE_FAILED` | `OFFERED` | `TERMINATED` | Reject path |
|
|
1756
1821
|
| `AGENT_CONTACT_ASSIGN_FAILED` | `ASSIGN_FAILED` | `OFFERED` | `TERMINATED` | Reject path |
|
|
1757
1822
|
| `AGENT_CONTACT_OFFER_RONA` | `RONA` | `OFFERED` | `TERMINATED` | Timeout path |
|
|
1758
|
-
| `AGENT_OUTBOUND_FAILED` | `OUTBOUND_FAILED` | `OFFERED`
|
|
1823
|
+
| `AGENT_OUTBOUND_FAILED` | `OUTBOUND_FAILED` | `IDLE` / `OFFERED` / `CONNECTED` / `HOLD_INITIATING` / `HELD` / `RESUME_INITIATING` / `CONSULT_INITIATING` / `CONSULTING` / `CONF_INITIATING` / `CONFERENCING` | `WRAPPING_UP` or `TERMINATED` | Outbound failure; wrapup when `shouldWrapUp`. Non-wxApp agent-terminated `AGENT_ENDS` sets `suppressOutdialFailedPopup` (wrapup without outdial-failed modal). `IDLE` handles race before `TASK_INCOMING`. |
|
|
1759
1824
|
| `CONTACT_RECORDING_STARTED` | `RECORDING_STARTED` | any | same | Recording state update |
|
|
1760
1825
|
| `CONTACT_RECORDING_PAUSED` | `PAUSE_RECORDING` | `CONNECTED` | same | Recording state update |
|
|
1761
1826
|
| `CONTACT_RECORDING_RESUMED` | `RESUME_RECORDING` | `CONNECTED` | same | Recording state update |
|
|
@@ -1764,7 +1829,7 @@ Complete mapping from backend CC_EVENTS to internal TaskEvent types.
|
|
|
1764
1829
|
| `PARTICIPANT_JOINED_CONFERENCE` | `CONFERENCE_START` | `CONSULTING` / `CONF_INITIATING` / `CONFERENCING` | `CONFERENCING` / same | Conference participant joined |
|
|
1765
1830
|
| `AGENT_CONSULT_CONFERENCE_FAILED` | `CONFERENCE_FAILED` | `CONF_INITIATING` | `CONSULTING` | Merge fail fallback |
|
|
1766
1831
|
| `AGENT_CONSULT_CONFERENCE_ENDED` | `CONFERENCE_END` | `CONFERENCING` | `WRAPPING_UP` / `CONNECTED` / `TERMINATED` | Guard-driven |
|
|
1767
|
-
| `PARTICIPANT_LEFT_CONFERENCE` | `PARTICIPANT_LEAVE` | `CONSULTING` / `CONFERENCING`
|
|
1832
|
+
| `PARTICIPANT_LEFT_CONFERENCE` | `PARTICIPANT_LEAVE` | `HELD` / `RESUME_INITIATING` / `CONSULTING` / `CONSULT_INITIATING` / `CONFERENCING` | `WRAPPING_UP` / `TERMINATED` / `CONNECTED` / same | Named self or omitted from participant map; `CONNECTED` / `HOLD_INITIATING` / `CONF_INITIATING` ignore |
|
|
1768
1833
|
| `AGENT_CONFERENCE_TRANSFERRED` | `TRANSFER_CONFERENCE_SUCCESS` | `CONSULTING` / `CONFERENCING` | `WRAPPING_UP` / `CONFERENCING` / `TERMINATED` / same | Initiator/receiver dependent |
|
|
1769
1834
|
|
|
1770
1835
|
- `AGENT_CONTACT_UNASSIGNED` -> returns `null` in mapper (`TaskManager.mapEventToTaskStateMachineEvent`)
|
|
@@ -1775,8 +1840,8 @@ Complete mapping from backend CC_EVENTS to internal TaskEvent types.
|
|
|
1775
1840
|
| `AgentOfferContact` | `TASK_OFFERED` | Stay in OFFERED | Offer confirmation |
|
|
1776
1841
|
| `AgentContact` | `HYDRATE` | Various | State restoration |
|
|
1777
1842
|
| `AgentContactAssigned` | `ASSIGN` | OFFERED → CONNECTED (also CONNECTED/CONSULTING refresh paths) | Task accepted/reassigned |
|
|
1778
|
-
| `ContactUpdated` | `CONTACT_UPDATED`
|
|
1779
|
-
| `ContactOwnerChanged` | `CONTACT_OWNER_CHANGED` | No change | Owner update
|
|
1843
|
+
| `ContactUpdated` | `CONTACT_UPDATED` or `CONTACT_OWNER_CHANGED` | No change | Changed non-empty owner also emits `task:hydrate`; same/missing owner is data-only |
|
|
1844
|
+
| `ContactOwnerChanged` | `CONTACT_OWNER_CHANGED` | No change | Owner update plus `task:hydrate` emission |
|
|
1780
1845
|
| `ContactEnded` | `CONTACT_ENDED` | Guard-based branch | CONFERENCING / WRAPPING_UP / TERMINATED / stay |
|
|
1781
1846
|
| `AgentContactUnassigned` | None | N/A | Handled by other events |
|
|
1782
1847
|
|
|
@@ -1810,9 +1875,10 @@ Complete mapping from backend CC_EVENTS to internal TaskEvent types.
|
|
|
1810
1875
|
| Backend Event / API | TaskEvent | State Transition | Context Update |
|
|
1811
1876
|
|---|---|---|---|
|
|
1812
1877
|
| API `task.consultConference()` | `MERGE_TO_CONFERENCE` | CONSULTING → CONF_INITIATING | Starts merge flow |
|
|
1878
|
+
| API `task.dropConferenceParticipant()` | None | No direct state transition | AQM waits for backend `ParticipantLeftConference`; that event follows the existing `PARTICIPANT_LEAVE` path |
|
|
1813
1879
|
| `AgentConsultConferenced` | `CONFERENCE_START` | CONSULTING/CONF_INITIATING → CONFERENCING | `handleConferenceStarted` path |
|
|
1814
1880
|
| `ParticipantJoinedConference` | `CONFERENCE_START` | CONFERENCING → CONFERENCING | Refresh + emit conference started |
|
|
1815
|
-
| `ParticipantLeftConference` | `PARTICIPANT_LEAVE` | CONSULTING / CONFERENCING → WRAPPING_UP / TERMINATED / CONNECTED / stay | Uses `
|
|
1881
|
+
| `ParticipantLeftConference` | `PARTICIPANT_LEAVE` | HELD / RESUME_INITIATING / CONSULTING / CONSULT_INITIATING / CONFERENCING → WRAPPING_UP / TERMINATED / CONNECTED / stay; CONNECTED / HOLD_INITIATING / CONF_INITIATING ignore | Uses `didCurrentAgentLeaveMainInteraction` (named self or omitted from participant map), `shouldWrapUp`, `shouldDowngradeConferenceToConnected` |
|
|
1816
1882
|
| `AgentConsultConferenceEnded` | `CONFERENCE_END` | CONFERENCING → WRAPPING_UP / CONNECTED / TERMINATED | Guard-based branch |
|
|
1817
1883
|
| `AgentConsultConferenceFailed` | `CONFERENCE_FAILED` | CONF_INITIATING → CONSULTING | Merge failed fallback |
|
|
1818
1884
|
| `AgentConferenceTransferred` | `TRANSFER_CONFERENCE_SUCCESS` | CONSULTING/CONFERENCING branch logic | Initiator/receiver dependent |
|
|
@@ -1847,6 +1913,7 @@ stateDiagram-v2
|
|
|
1847
1913
|
OFFERED --> TERMINATED: AGENT_CONTACT_ASSIGN_FAILED (CC Event) -> ASSIGN_FAILED (State Machine Event)
|
|
1848
1914
|
OFFERED --> TERMINATED: AGENT_INVITE_FAILED (CC Event) -> INVITE_FAILED (State Machine Event)
|
|
1849
1915
|
OFFERED --> TERMINATED: AGENT_OUTBOUND_FAILED (CC Event) -> OUTBOUND_FAILED (State Machine Event)
|
|
1916
|
+
OFFERED --> WRAPPING_UP: AGENT_WRAPUP (CC Event) -> TASK_WRAPUP (State Machine Event) [shouldWrapUp]
|
|
1850
1917
|
OFFERED --> TERMINATED: AGENT_WRAPUP (CC Event) -> TASK_WRAPUP (State Machine Event)
|
|
1851
1918
|
|
|
1852
1919
|
%% CONNECTED
|
|
@@ -1907,8 +1974,8 @@ stateDiagram-v2
|
|
|
1907
1974
|
|
|
1908
1975
|
%% CONFERENCING
|
|
1909
1976
|
CONFERENCING --> CONSULT_INITIATING: CONSULT (State Machine Event)
|
|
1910
|
-
CONFERENCING --> WRAPPING_UP: PARTICIPANT_LEAVE (CC Event) -> PARTICIPANT_LEAVE (State Machine Event) [
|
|
1911
|
-
CONFERENCING --> TERMINATED: PARTICIPANT_LEAVE (CC Event) -> PARTICIPANT_LEAVE (State Machine Event) [
|
|
1977
|
+
CONFERENCING --> WRAPPING_UP: PARTICIPANT_LEAVE (CC Event) -> PARTICIPANT_LEAVE (State Machine Event) [didCurrentAgentLeaveMainInteraction && shouldWrapUp]
|
|
1978
|
+
CONFERENCING --> TERMINATED: PARTICIPANT_LEAVE (CC Event) -> PARTICIPANT_LEAVE (State Machine Event) [didCurrentAgentLeaveMainInteraction]
|
|
1912
1979
|
CONFERENCING --> CONNECTED: PARTICIPANT_LEAVE (CC Event) -> PARTICIPANT_LEAVE (State Machine Event) [shouldDowngradeConferenceToConnected]
|
|
1913
1980
|
CONFERENCING --> WRAPPING_UP: CONFERENCE_END (CC Event) -> CONFERENCE_END (State Machine Event) [shouldWrapUp]
|
|
1914
1981
|
CONFERENCING --> CONNECTED: CONFERENCE_END (CC Event) -> CONFERENCE_END (State Machine Event) [customerInCall]
|
|
@@ -1930,7 +1997,9 @@ stateDiagram-v2
|
|
|
1930
1997
|
OFFERED --> OFFERED: AGENT_CONTACT_OFFER -> TASK_OFFERED
|
|
1931
1998
|
OFFERED --> OFFERED: AGENT_CONSULT_OFFER -> OFFER_CONSULT
|
|
1932
1999
|
OFFERED --> CONNECTED: AGENT_CONTACT_ASSIGNED -> ASSIGN
|
|
1933
|
-
OFFERED --> TERMINATED: AGENT_CONTACT_OFFER_RONA/AGENT_CONTACT_ASSIGN_FAILED/AGENT_INVITE_FAILED/AGENT_OUTBOUND_FAILED
|
|
2000
|
+
OFFERED --> TERMINATED: AGENT_CONTACT_OFFER_RONA/AGENT_CONTACT_ASSIGN_FAILED/AGENT_INVITE_FAILED/AGENT_OUTBOUND_FAILED -> RONA/ASSIGN_FAILED/INVITE_FAILED/OUTBOUND_FAILED
|
|
2001
|
+
OFFERED --> WRAPPING_UP: AGENT_WRAPUP -> TASK_WRAPUP [shouldWrapUp]
|
|
2002
|
+
OFFERED --> TERMINATED: AGENT_WRAPUP -> TASK_WRAPUP
|
|
1934
2003
|
|
|
1935
2004
|
CONNECTED --> HOLD_INITIATING: task.hold() -> HOLD_INITIATED
|
|
1936
2005
|
CONNECTED --> CONSULT_INITIATING: task.consult() -> CONSULT
|
|
@@ -2012,8 +2081,8 @@ stateDiagram-v2
|
|
|
2012
2081
|
CONFERENCING --> CONFERENCING: AGENT_CONFERENCE_TRANSFERRED -> TRANSFER_CONFERENCE_SUCCESS
|
|
2013
2082
|
CONFERENCING --> CONFERENCING: AGENT_CONFERENCE_TRANSFER_FAILED-> TRANSFER_CONFERENCE_FAILED
|
|
2014
2083
|
|
|
2015
|
-
CONFERENCING --> WRAPPING_UP: PARTICIPANT_LEFT_CONFERENCE -> PARTICIPANT_LEAVE [
|
|
2016
|
-
CONFERENCING --> TERMINATED: PARTICIPANT_LEFT_CONFERENCE -> PARTICIPANT_LEAVE [
|
|
2084
|
+
CONFERENCING --> WRAPPING_UP: PARTICIPANT_LEFT_CONFERENCE -> PARTICIPANT_LEAVE [didCurrentAgentLeaveMainInteraction && shouldWrapUp]
|
|
2085
|
+
CONFERENCING --> TERMINATED: PARTICIPANT_LEFT_CONFERENCE -> PARTICIPANT_LEAVE [didCurrentAgentLeaveMainInteraction]
|
|
2017
2086
|
CONFERENCING --> CONNECTED: PARTICIPANT_LEFT_CONFERENCE -> PARTICIPANT_LEAVE [shouldDowngradeConferenceToConnected]
|
|
2018
2087
|
CONFERENCING --> WRAPPING_UP: AGENT_CONSULT_CONFERENCE_ENDED -> CONFERENCE_END [shouldWrapUp]
|
|
2019
2088
|
CONFERENCING --> CONNECTED: AGENT_CONSULT_CONFERENCE_ENDED -> CONFERENCE_END [customerInCall]
|
|
@@ -2139,6 +2208,7 @@ Use `test/unit/spec/services/task/state-machine/TaskStateMachine.ts`, `guards.ts
|
|
|
2139
2208
|
| `TASK_STATE_MACHINE-R-005` | `test/unit/spec/services/task/state-machine/TaskStateMachine.ts` | Transport/auth absence is also verified from imports. |
|
|
2140
2209
|
| `TASK_STATE_MACHINE-R-006` | `test/unit/spec/services/task/Task.ts` | None. |
|
|
2141
2210
|
| `TASK_STATE_MACHINE-R-007` | `test/unit/spec/services/task/state-machine/TaskStateMachine.ts`, `test/unit/spec/services/task/Task.ts` | Observability absence is also verified from imports. |
|
|
2211
|
+
| `TASK_STATE_MACHINE-R-008` | `test/unit/spec/services/task/Task.ts`, `test/unit/spec/services/task/TaskManager.ts` | None. |
|
|
2142
2212
|
|
|
2143
2213
|
## Traceability
|
|
2144
2214
|
- Repo architecture: `../../../../../ai-docs/ARCHITECTURE.md` · Registry: `../../../../../ai-docs/SPEC_INDEX.md`
|
|
@@ -362,13 +362,14 @@ export const guards = {
|
|
|
362
362
|
},
|
|
363
363
|
|
|
364
364
|
/**
|
|
365
|
-
* True
|
|
365
|
+
* True when an updated lifecycle event shows that this agent left the main interaction.
|
|
366
366
|
*
|
|
367
|
-
*
|
|
368
|
-
*
|
|
369
|
-
*
|
|
367
|
+
* Returns true when the event names this agent, or when this agent is absent from the
|
|
368
|
+
* updated participants map. EP-DN payloads remove the leaving participant instead of
|
|
369
|
+
* setting hasLeft. Remaining in the map with hasLeft, or disappearing only from
|
|
370
|
+
* mainCall media, is not treated as departure.
|
|
370
371
|
*/
|
|
371
|
-
|
|
372
|
+
didCurrentAgentLeaveMainInteraction: ({context, event}: GuardParams): boolean => {
|
|
372
373
|
const taskData = getTaskDataFromEvent(event);
|
|
373
374
|
const selfAgentId = getSelfAgentId(context, taskData);
|
|
374
375
|
if (!selfAgentId) return false;
|
|
@@ -382,11 +383,7 @@ export const guards = {
|
|
|
382
383
|
if (Boolean(participantId) && participantId === selfAgentId) {
|
|
383
384
|
return true;
|
|
384
385
|
}
|
|
385
|
-
|
|
386
|
-
// For EP-DN agents the backend removes the leaving participant entirely
|
|
387
|
-
// from the participants map (rather than setting hasLeft). If this task
|
|
388
|
-
// is in CONFERENCING (implied by the guard being evaluated here) but the
|
|
389
|
-
// agent is absent from the updated participants, they have left.
|
|
386
|
+
// EP-DN payloads remove the leaving participant from the map instead of setting hasLeft.
|
|
390
387
|
const participants = taskData?.interaction?.participants;
|
|
391
388
|
if (participants && !(selfAgentId in participants)) {
|
|
392
389
|
return true;
|
|
@@ -6,7 +6,14 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import type {AnyStateNodeConfig, ActionFunctionMap, EventObject, ActionArgs} from 'xstate';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
ConsultTransferDestinationConfig,
|
|
11
|
+
DestinationType,
|
|
12
|
+
TaskChannelType,
|
|
13
|
+
TaskData,
|
|
14
|
+
TaskUIControls,
|
|
15
|
+
VoiceVariant,
|
|
16
|
+
} from '../types';
|
|
10
17
|
import {TaskEvent, TaskState} from './constants';
|
|
11
18
|
|
|
12
19
|
/**
|
|
@@ -43,6 +50,14 @@ export interface UIControlConfig {
|
|
|
43
50
|
isRecordingEnabled: boolean;
|
|
44
51
|
/** Current agent ID for ownership checks (transfer conference) */
|
|
45
52
|
agentId?: string;
|
|
53
|
+
/** Agent-profile policy for ordered consult/transfer destinations */
|
|
54
|
+
consultTransferConfig?: ConsultTransferDestinationConfig;
|
|
55
|
+
/** Whether wxApp thick-client answer is enabled (WXCC-6026) */
|
|
56
|
+
enableWxBetterTogether?: boolean;
|
|
57
|
+
/** True while wxApp telephony answer is in flight (outdial Calling… label) */
|
|
58
|
+
wxAppAnswerPending?: boolean;
|
|
59
|
+
/** True only during the wxApp accept REST call (decline disabled for inbound + outdial) */
|
|
60
|
+
wxAppAcceptInFlight?: boolean;
|
|
46
61
|
}
|
|
47
62
|
|
|
48
63
|
/**
|