@webex/contact-center 3.12.0-next.9 → 3.12.0-task-refactor.2

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.
Files changed (200) hide show
  1. package/AGENTS.md +438 -0
  2. package/ai-docs/README.md +131 -0
  3. package/ai-docs/RULES.md +455 -0
  4. package/ai-docs/patterns/event-driven-patterns.md +485 -0
  5. package/ai-docs/patterns/testing-patterns.md +480 -0
  6. package/ai-docs/patterns/typescript-patterns.md +365 -0
  7. package/ai-docs/templates/README.md +102 -0
  8. package/ai-docs/templates/documentation/create-agents-md.md +240 -0
  9. package/ai-docs/templates/documentation/create-architecture-md.md +295 -0
  10. package/ai-docs/templates/existing-service/bug-fix.md +254 -0
  11. package/ai-docs/templates/existing-service/feature-enhancement.md +450 -0
  12. package/ai-docs/templates/new-method/00-master.md +80 -0
  13. package/ai-docs/templates/new-method/01-requirements.md +232 -0
  14. package/ai-docs/templates/new-method/02-implementation.md +295 -0
  15. package/ai-docs/templates/new-method/03-tests.md +201 -0
  16. package/ai-docs/templates/new-method/04-validation.md +141 -0
  17. package/ai-docs/templates/new-service/00-master.md +109 -0
  18. package/ai-docs/templates/new-service/01-pre-questions.md +159 -0
  19. package/ai-docs/templates/new-service/02-code-generation.md +346 -0
  20. package/ai-docs/templates/new-service/03-integration.md +178 -0
  21. package/ai-docs/templates/new-service/04-test-generation.md +205 -0
  22. package/ai-docs/templates/new-service/05-validation.md +145 -0
  23. package/dist/cc.js +65 -123
  24. package/dist/cc.js.map +1 -1
  25. package/dist/constants.js +13 -2
  26. package/dist/constants.js.map +1 -1
  27. package/dist/index.js +13 -5
  28. package/dist/index.js.map +1 -1
  29. package/dist/metrics/behavioral-events.js +26 -13
  30. package/dist/metrics/behavioral-events.js.map +1 -1
  31. package/dist/metrics/constants.js +7 -6
  32. package/dist/metrics/constants.js.map +1 -1
  33. package/dist/services/ApiAiAssistant.js +0 -3
  34. package/dist/services/ApiAiAssistant.js.map +1 -1
  35. package/dist/services/config/Util.js +2 -3
  36. package/dist/services/config/Util.js.map +1 -1
  37. package/dist/services/config/types.js +16 -14
  38. package/dist/services/config/types.js.map +1 -1
  39. package/dist/services/constants.js +0 -1
  40. package/dist/services/constants.js.map +1 -1
  41. package/dist/services/core/Err.js.map +1 -1
  42. package/dist/services/core/Utils.js +79 -55
  43. package/dist/services/core/Utils.js.map +1 -1
  44. package/dist/services/core/aqm-reqs.js +17 -92
  45. package/dist/services/core/aqm-reqs.js.map +1 -1
  46. package/dist/services/core/websocket/WebSocketManager.js +5 -25
  47. package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
  48. package/dist/services/core/websocket/types.js.map +1 -1
  49. package/dist/services/index.js +1 -2
  50. package/dist/services/index.js.map +1 -1
  51. package/dist/services/task/Task.js +644 -0
  52. package/dist/services/task/Task.js.map +1 -0
  53. package/dist/services/task/TaskFactory.js +45 -0
  54. package/dist/services/task/TaskFactory.js.map +1 -0
  55. package/dist/services/task/TaskManager.js +570 -535
  56. package/dist/services/task/TaskManager.js.map +1 -1
  57. package/dist/services/task/TaskUtils.js +132 -28
  58. package/dist/services/task/TaskUtils.js.map +1 -1
  59. package/dist/services/task/constants.js +7 -6
  60. package/dist/services/task/constants.js.map +1 -1
  61. package/dist/services/task/dialer.js +0 -51
  62. package/dist/services/task/dialer.js.map +1 -1
  63. package/dist/services/task/digital/Digital.js +77 -0
  64. package/dist/services/task/digital/Digital.js.map +1 -0
  65. package/dist/services/task/state-machine/TaskStateMachine.js +634 -0
  66. package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -0
  67. package/dist/services/task/state-machine/actions.js +372 -0
  68. package/dist/services/task/state-machine/actions.js.map +1 -0
  69. package/dist/services/task/state-machine/constants.js +139 -0
  70. package/dist/services/task/state-machine/constants.js.map +1 -0
  71. package/dist/services/task/state-machine/guards.js +263 -0
  72. package/dist/services/task/state-machine/guards.js.map +1 -0
  73. package/dist/services/task/state-machine/index.js +53 -0
  74. package/dist/services/task/state-machine/index.js.map +1 -0
  75. package/dist/services/task/state-machine/types.js +54 -0
  76. package/dist/services/task/state-machine/types.js.map +1 -0
  77. package/dist/services/task/state-machine/uiControlsComputer.js +377 -0
  78. package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -0
  79. package/dist/services/task/taskDataNormalizer.js +99 -0
  80. package/dist/services/task/taskDataNormalizer.js.map +1 -0
  81. package/dist/services/task/types.js +157 -18
  82. package/dist/services/task/types.js.map +1 -1
  83. package/dist/services/task/voice/Voice.js +1031 -0
  84. package/dist/services/task/voice/Voice.js.map +1 -0
  85. package/dist/services/task/voice/WebRTC.js +149 -0
  86. package/dist/services/task/voice/WebRTC.js.map +1 -0
  87. package/dist/types/cc.d.ts +4 -33
  88. package/dist/types/constants.d.ts +13 -2
  89. package/dist/types/index.d.ts +11 -5
  90. package/dist/types/metrics/constants.d.ts +5 -3
  91. package/dist/types/services/ApiAiAssistant.d.ts +1 -1
  92. package/dist/types/services/config/types.d.ts +97 -25
  93. package/dist/types/services/core/Err.d.ts +0 -2
  94. package/dist/types/services/core/Utils.d.ts +25 -23
  95. package/dist/types/services/core/aqm-reqs.d.ts +0 -49
  96. package/dist/types/services/core/websocket/WebSocketManager.d.ts +1 -1
  97. package/dist/types/services/core/websocket/connection-service.d.ts +0 -1
  98. package/dist/types/services/core/websocket/types.d.ts +1 -1
  99. package/dist/types/services/index.d.ts +1 -1
  100. package/dist/types/services/task/Task.d.ts +146 -0
  101. package/dist/types/services/task/TaskFactory.d.ts +12 -0
  102. package/dist/types/services/task/TaskUtils.d.ts +39 -8
  103. package/dist/types/services/task/constants.d.ts +5 -4
  104. package/dist/types/services/task/dialer.d.ts +0 -15
  105. package/dist/types/services/task/digital/Digital.d.ts +22 -0
  106. package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +906 -0
  107. package/dist/types/services/task/state-machine/actions.d.ts +8 -0
  108. package/dist/types/services/task/state-machine/constants.d.ts +91 -0
  109. package/dist/types/services/task/state-machine/guards.d.ts +78 -0
  110. package/dist/types/services/task/state-machine/index.d.ts +13 -0
  111. package/dist/types/services/task/state-machine/types.d.ts +256 -0
  112. package/dist/types/services/task/state-machine/uiControlsComputer.d.ts +9 -0
  113. package/dist/types/services/task/taskDataNormalizer.d.ts +10 -0
  114. package/dist/types/services/task/types.d.ts +539 -88
  115. package/dist/types/services/task/voice/Voice.d.ts +183 -0
  116. package/dist/types/services/task/voice/WebRTC.d.ts +53 -0
  117. package/dist/types/types.d.ts +68 -0
  118. package/dist/types/webex.d.ts +1 -0
  119. package/dist/types.js +70 -0
  120. package/dist/types.js.map +1 -1
  121. package/dist/webex.js +14 -2
  122. package/dist/webex.js.map +1 -1
  123. package/package.json +14 -11
  124. package/src/cc.ts +91 -177
  125. package/src/constants.ts +13 -2
  126. package/src/index.ts +14 -5
  127. package/src/metrics/ai-docs/AGENTS.md +348 -0
  128. package/src/metrics/ai-docs/ARCHITECTURE.md +336 -0
  129. package/src/metrics/behavioral-events.ts +28 -14
  130. package/src/metrics/constants.ts +7 -8
  131. package/src/services/ApiAiAssistant.ts +2 -4
  132. package/src/services/agent/ai-docs/AGENTS.md +238 -0
  133. package/src/services/agent/ai-docs/ARCHITECTURE.md +302 -0
  134. package/src/services/ai-docs/AGENTS.md +384 -0
  135. package/src/services/config/Util.ts +2 -3
  136. package/src/services/config/ai-docs/AGENTS.md +253 -0
  137. package/src/services/config/ai-docs/ARCHITECTURE.md +424 -0
  138. package/src/services/config/types.ts +108 -20
  139. package/src/services/constants.ts +0 -1
  140. package/src/services/core/Err.ts +0 -1
  141. package/src/services/core/Utils.ts +90 -67
  142. package/src/services/core/ai-docs/AGENTS.md +379 -0
  143. package/src/services/core/ai-docs/ARCHITECTURE.md +696 -0
  144. package/src/services/core/aqm-reqs.ts +22 -100
  145. package/src/services/core/websocket/WebSocketManager.ts +4 -23
  146. package/src/services/core/websocket/types.ts +1 -1
  147. package/src/services/index.ts +1 -2
  148. package/src/services/task/Task.ts +785 -0
  149. package/src/services/task/TaskFactory.ts +55 -0
  150. package/src/services/task/TaskManager.ts +579 -633
  151. package/src/services/task/TaskUtils.ts +175 -31
  152. package/src/services/task/ai-docs/AGENTS.md +448 -0
  153. package/src/services/task/ai-docs/ARCHITECTURE.md +573 -0
  154. package/src/services/task/constants.ts +5 -4
  155. package/src/services/task/dialer.ts +1 -56
  156. package/src/services/task/digital/Digital.ts +95 -0
  157. package/src/services/task/state-machine/TaskStateMachine.ts +793 -0
  158. package/src/services/task/state-machine/actions.ts +422 -0
  159. package/src/services/task/state-machine/ai-docs/AGENTS.md +495 -0
  160. package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +1135 -0
  161. package/src/services/task/state-machine/constants.ts +150 -0
  162. package/src/services/task/state-machine/guards.ts +303 -0
  163. package/src/services/task/state-machine/index.ts +28 -0
  164. package/src/services/task/state-machine/types.ts +228 -0
  165. package/src/services/task/state-machine/uiControlsComputer.ts +542 -0
  166. package/src/services/task/taskDataNormalizer.ts +137 -0
  167. package/src/services/task/types.ts +641 -95
  168. package/src/services/task/voice/Voice.ts +1255 -0
  169. package/src/services/task/voice/WebRTC.ts +187 -0
  170. package/src/types.ts +88 -5
  171. package/src/utils/AGENTS.md +276 -0
  172. package/src/webex.js +2 -0
  173. package/test/unit/spec/cc.ts +59 -142
  174. package/test/unit/spec/logger-proxy.ts +70 -0
  175. package/test/unit/spec/services/ApiAiAssistant.ts +17 -0
  176. package/test/unit/spec/services/config/index.ts +26 -55
  177. package/test/unit/spec/services/core/Utils.ts +103 -52
  178. package/test/unit/spec/services/core/websocket/WebSocketManager.ts +48 -112
  179. package/test/unit/spec/services/core/websocket/connection-service.ts +5 -4
  180. package/test/unit/spec/services/task/AutoWrapup.ts +63 -0
  181. package/test/unit/spec/services/task/Task.ts +416 -0
  182. package/test/unit/spec/services/task/TaskFactory.ts +62 -0
  183. package/test/unit/spec/services/task/TaskManager.ts +781 -1735
  184. package/test/unit/spec/services/task/TaskUtils.ts +125 -0
  185. package/test/unit/spec/services/task/dialer.ts +112 -198
  186. package/test/unit/spec/services/task/digital/Digital.ts +105 -0
  187. package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +473 -0
  188. package/test/unit/spec/services/task/state-machine/guards.ts +288 -0
  189. package/test/unit/spec/services/task/state-machine/types.ts +18 -0
  190. package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +147 -0
  191. package/test/unit/spec/services/task/taskTestUtils.ts +87 -0
  192. package/test/unit/spec/services/task/voice/Voice.ts +587 -0
  193. package/test/unit/spec/services/task/voice/WebRTC.ts +242 -0
  194. package/umd/contact-center.min.js +2 -2
  195. package/umd/contact-center.min.js.map +1 -1
  196. package/dist/services/task/index.js +0 -1525
  197. package/dist/services/task/index.js.map +0 -1
  198. package/dist/types/services/task/index.d.ts +0 -650
  199. package/src/services/task/index.ts +0 -1801
  200. package/test/unit/spec/services/task/index.ts +0 -2184
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Task State Machine Actions - Action implementations executed during state transitions
3
+ */
4
+ import { TaskContext, TaskEventPayload, UIControlConfig, TaskActionsMap } from './types';
5
+ import { TaskState } from './constants';
6
+ export declare function createInitialContext(uiControlConfig: UIControlConfig, initialState?: TaskState): TaskContext;
7
+ export declare function updateUIControls(currentState: TaskState): import("xstate").ActionFunction<TaskContext, TaskEventPayload, TaskEventPayload, {}, import("xstate").ProvidedActor, never, never, never, never>;
8
+ export declare const actions: TaskActionsMap;
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Constants for the task state machine.
3
+ * These enums define the allowed states, events, and built-in action identifiers.
4
+ */
5
+ /**
6
+ * Maximum number of participants allowed in a multi-party conference.
7
+ * Max 7 counted agents + 1 customer.
8
+ */
9
+ export declare const MAX_PARTICIPANTS_IN_MULTIPARTY_CONFERENCE = 7;
10
+ /** Participant types for conference filtering */
11
+ export declare const PARTICIPANT_TYPE: {
12
+ readonly CUSTOMER: "Customer";
13
+ readonly SUPERVISOR: "Supervisor";
14
+ readonly VVA: "VVA";
15
+ };
16
+ export type ParticipantType = (typeof PARTICIPANT_TYPE)[keyof typeof PARTICIPANT_TYPE];
17
+ /** Media type for consult calls */
18
+ export declare const MEDIA_TYPE_CONSULT = "consult";
19
+ /** Media type for main calls */
20
+ export declare const MEDIA_TYPE_MAIN_CALL = "mainCall";
21
+ export declare enum TaskState {
22
+ IDLE = "IDLE",
23
+ OFFERED = "OFFERED",
24
+ CONNECTED = "CONNECTED",
25
+ HOLD_INITIATING = "HOLD_INITIATING",
26
+ HELD = "HELD",
27
+ RESUME_INITIATING = "RESUME_INITIATING",
28
+ CONSULT_INITIATING = "CONSULT_INITIATING",
29
+ CONSULTING = "CONSULTING",
30
+ CONF_INITIATING = "CONF_INITIATING",
31
+ CONFERENCING = "CONFERENCING",
32
+ WRAPPING_UP = "WRAPPING_UP",
33
+ COMPLETED = "COMPLETED",
34
+ TERMINATED = "TERMINATED",
35
+ CONSULT_INITIATED = "CONSULT_INITIATED",
36
+ CONSULT_COMPLETED = "CONSULT_COMPLETED",
37
+ POST_CALL = "POST_CALL",
38
+ PARKED = "PARKED",
39
+ MONITORING = "MONITORING"
40
+ }
41
+ export declare enum TaskEvent {
42
+ TASK_INCOMING = "TASK_INCOMING",
43
+ TASK_OFFERED = "TASK_OFFERED",
44
+ OFFER_CONSULT = "OFFER_CONSULT",
45
+ HYDRATE = "HYDRATE",
46
+ CONTACT_UPDATED = "CONTACT_UPDATED",
47
+ CONTACT_OWNER_CHANGED = "CONTACT_OWNER_CHANGED",
48
+ ASSIGN = "ASSIGN",
49
+ HOLD_SUCCESS = "HOLD_SUCCESS",
50
+ HOLD_FAILED = "HOLD_FAILED",
51
+ UNHOLD_SUCCESS = "UNHOLD_SUCCESS",
52
+ UNHOLD_FAILED = "UNHOLD_FAILED",
53
+ HOLD_INITIATED = "HOLD_INITIATED",
54
+ UNHOLD_INITIATED = "UNHOLD_INITIATED",
55
+ CONSULT = "CONSULT",
56
+ CONSULT_SUCCESS = "CONSULT_SUCCESS",
57
+ CONSULT_CREATED = "CONSULT_CREATED",
58
+ CONSULTING_ACTIVE = "CONSULTING_ACTIVE",
59
+ CONSULT_END = "CONSULT_END",
60
+ CONSULT_FAILED = "CONSULT_FAILED",
61
+ MERGE_TO_CONFERENCE = "MERGE_TO_CONFERENCE",
62
+ CONFERENCE_START = "CONFERENCE_START",
63
+ CONFERENCE_FAILED = "CONFERENCE_FAILED",
64
+ CONFERENCE_END = "CONFERENCE_END",
65
+ TRANSFER_CONFERENCE = "TRANSFER_CONFERENCE",
66
+ TRANSFER_CONFERENCE_SUCCESS = "TRANSFER_CONFERENCE_SUCCESS",
67
+ TRANSFER_CONFERENCE_FAILED = "TRANSFER_CONFERENCE_FAILED",
68
+ PARTICIPANT_LEAVE = "PARTICIPANT_LEAVE",
69
+ EXIT_CONFERENCE = "EXIT_CONFERENCE",
70
+ EXIT_CONFERENCE_SUCCESS = "EXIT_CONFERENCE_SUCCESS",
71
+ EXIT_CONFERENCE_FAILED = "EXIT_CONFERENCE_FAILED",
72
+ RECORDING_STARTED = "RECORDING_STARTED",
73
+ PAUSE_RECORDING = "PAUSE_RECORDING",
74
+ RESUME_RECORDING = "RESUME_RECORDING",
75
+ TRANSFER_SUCCESS = "TRANSFER_SUCCESS",
76
+ TRANSFER_FAILED = "TRANSFER_FAILED",
77
+ WRAPUP_COMPLETE = "WRAPUP_COMPLETE",
78
+ TASK_WRAPUP = "TASK_WRAPUP",
79
+ RONA = "RONA",// Ring On No Answer
80
+ CONTACT_ENDED = "CONTACT_ENDED",
81
+ ASSIGN_FAILED = "ASSIGN_FAILED",
82
+ INVITE_FAILED = "INVITE_FAILED",
83
+ OUTBOUND_FAILED = "OUTBOUND_FAILED",
84
+ SWITCH_TO_MAIN_CALL = "SWITCH_TO_MAIN_CALL",
85
+ SWITCH_TO_CONSULT = "SWITCH_TO_CONSULT",
86
+ ACCEPT = "ACCEPT",
87
+ DECLINE = "DECLINE",
88
+ END = "END",
89
+ CTQ_CANCEL = "CTQ_CANCEL",// Cancel To Queue
90
+ CTQ_CANCEL_FAILED = "CTQ_CANCEL_FAILED"
91
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Task State Machine Guards
3
+ *
4
+ * Guard functions that determine if a state transition is allowed.
5
+ * These functions validate the current context before allowing transitions.
6
+ *
7
+ * All guards are consolidated here for:
8
+ * - Single source of truth
9
+ * - Easy testing
10
+ * - Reusability across state machine transitions
11
+ *
12
+ * Guards are organized by category:
13
+ * 1. Helper Functions - Extract data from events/context
14
+ * 2. Hydrate Guards - For state restoration on page refresh
15
+ * 3. Conference Guards - Conference state checks
16
+ * 4. Customer Guards - Customer presence checks
17
+ * 5. Consult Guards - Consult flow checks
18
+ * 6. Wrapup Guards - End-of-call flow checks
19
+ * 7. Server State Guards - Check backend-reported state
20
+ * 8. Recording Guards - Recording state checks
21
+ */
22
+ import { TaskContext, TaskEventPayload } from './types';
23
+ import { TaskData } from '../types';
24
+ export declare const getTaskDataFromEvent: (event?: TaskEventPayload) => TaskData | undefined;
25
+ export declare const getSelfAgentId: (context: TaskContext, taskData?: TaskData) => string | undefined;
26
+ export declare const isSelfConsultingAgent: (context: TaskContext, taskData?: TaskData) => boolean;
27
+ /**
28
+ * Determines if this agent should enter WRAPPING_UP state.
29
+ * Priority: agentsPendingWrapUp > wrapUpRequired / participant.isWrapUp > ownership > !isConsulted
30
+ */
31
+ export declare const shouldWrapUpForThisAgent: (context: TaskContext, taskData: TaskData) => boolean;
32
+ export interface GuardParams {
33
+ context: TaskContext;
34
+ event?: TaskEventPayload;
35
+ }
36
+ export type GuardFunction = (params: GuardParams) => boolean;
37
+ export declare const guards: {
38
+ isInteractionTerminated: ({ context, event }: GuardParams) => boolean;
39
+ isInteractionConsulting: ({ event }: GuardParams) => boolean;
40
+ isInteractionHeld: ({ event }: GuardParams) => boolean;
41
+ isInteractionConnected: ({ event }: GuardParams) => boolean;
42
+ isConferencingByParticipants: ({ event }: GuardParams) => boolean;
43
+ conferenceInProgressFromEvent: ({ event }: GuardParams) => boolean;
44
+ /**
45
+ * Conference downgrade check specifically for transitioning back to CONNECTED.
46
+ *
47
+ * Returns true only when:
48
+ * - conference has downgraded (fewer than 2 active agent participants in main call)
49
+ * - customer is still in the call
50
+ * - current agent is still in the main call
51
+ */
52
+ shouldDowngradeConferenceToConnected: ({ context, event }: GuardParams) => boolean;
53
+ /**
54
+ * Check if this agent initiated the consult (using event data)
55
+ * Handles both consultingAgentId and fallback to context flag
56
+ */
57
+ didInitiateConsult: ({ context, event }: GuardParams) => boolean;
58
+ /**
59
+ * EP-DN / consulted consult legs can arrive as AGENT_CONTACT_ASSIGNED without a preceding
60
+ * AgentConsulting event. When that happens, we should enter CONSULTING (not CONNECTED).
61
+ */
62
+ isConsultingAssignment: ({ event }: GuardParams) => boolean;
63
+ shouldWrapUp: ({ context, event }: GuardParams) => boolean;
64
+ /**
65
+ * Check if wrapUpRequired in payload OR is consult initiator
66
+ */
67
+ shouldWrapUpOrIsInitiator: ({ context, event }: GuardParams) => boolean;
68
+ /**
69
+ * True if PARTICIPANT_LEAVE indicates that *this* agent left the conference.
70
+ *
71
+ * Important: PARTICIPANT_LEAVE is broadcast to all agents in the conference.
72
+ * Only the agent whose id matches the leaving participant should transition to
73
+ * TERMINATED / WRAPPING_UP based on wrapup rules.
74
+ */
75
+ didCurrentAgentLeaveConference: ({ context, event }: GuardParams) => boolean;
76
+ isPrimaryMediaOnHold: ({ event }: GuardParams) => boolean;
77
+ };
78
+ export type GuardName = keyof typeof guards;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Task State Machine
3
+ *
4
+ * Export all state machine components for easy importing
5
+ */
6
+ export { createTaskStateMachine } from './TaskStateMachine';
7
+ export type { TaskStateMachine } from './TaskStateMachine';
8
+ export { TaskState, TaskEvent } from './constants';
9
+ export { isEventOfType } from './types';
10
+ export type { TaskContext, TaskEventPayload, TaskStateMachineConfig, UIControlConfig, TaskActionsMap, TaskActionArgs, } from './types';
11
+ export { guards } from './guards';
12
+ export type { GuardParams, GuardFunction } from './guards';
13
+ export { actions, createInitialContext } from './actions';
@@ -0,0 +1,256 @@
1
+ /**
2
+ * Task State Machine Types
3
+ *
4
+ * Type definitions for the XState-based task state machine.
5
+ * These types define states, events, context, and schemas for task lifecycle management.
6
+ */
7
+ import type { AnyStateNodeConfig, ActionFunctionMap, EventObject, ActionArgs } from 'xstate';
8
+ import { DestinationType, TaskChannelType, TaskData, TaskUIControls, VoiceVariant } from '../types';
9
+ import { TaskEvent, TaskState } from './constants';
10
+ /**
11
+ * Represents a participant in a conference call
12
+ */
13
+ export interface ConferenceParticipant {
14
+ /** Unique identifier for the participant */
15
+ id: string;
16
+ /** Type of participant (agent, customer, or external party) */
17
+ type: 'AGENT' | 'CUSTOMER' | 'EXTERNAL';
18
+ /** Display name of the participant */
19
+ name?: string;
20
+ /** Timestamp when participant joined the conference */
21
+ joinedAt: Date;
22
+ /** Whether this participant initiated the conference */
23
+ isInitiator: boolean;
24
+ /** Whether this participant can be removed from the conference */
25
+ canBeRemoved: boolean;
26
+ }
27
+ /**
28
+ * UI Control configuration for the task
29
+ */
30
+ export interface UIControlConfig {
31
+ /** Whether end call button is enabled (config option) */
32
+ isEndTaskEnabled: boolean;
33
+ /** Whether end consult button is enabled (config option) */
34
+ isEndConsultEnabled: boolean;
35
+ /** Channel type determines which controls are available */
36
+ channelType: TaskChannelType;
37
+ /** Optional voice channel variant to toggle WebRTC-specific controls */
38
+ voiceVariant?: VoiceVariant;
39
+ /** Whether recording controls should be shown for this task */
40
+ isRecordingEnabled: boolean;
41
+ /** Current agent ID for ownership checks (transfer conference) */
42
+ agentId?: string;
43
+ }
44
+ /**
45
+ * Task state machine context.
46
+ * Only stores data that cannot be derived from state machine state.
47
+ */
48
+ export interface TaskContext {
49
+ taskData: TaskData | null;
50
+ consultInitiator: boolean;
51
+ exitingConference: boolean;
52
+ consultFromConference: boolean;
53
+ transferConferenceRequested: boolean;
54
+ consultDestinationType: DestinationType | null;
55
+ consultDestinationAgentId: string | null;
56
+ consultDestinationAgentJoined: boolean;
57
+ consultCallHeld: boolean;
58
+ recordingControlsAvailable: boolean;
59
+ recordingInProgress: boolean;
60
+ uiControlConfig: UIControlConfig;
61
+ uiControls: TaskUIControls;
62
+ }
63
+ export type RecordingStateUpdate = Partial<Pick<TaskContext, 'recordingControlsAvailable' | 'recordingInProgress'>>;
64
+ /**
65
+ * Base event type - all events have a type property
66
+ */
67
+ type BaseEvent<T extends TaskEvent> = {
68
+ type: T;
69
+ };
70
+ /**
71
+ * Event payload mapping - defines the payload for each event type
72
+ */
73
+ interface TaskEventPayloadMap {
74
+ [TaskEvent.TASK_INCOMING]: BaseEvent<TaskEvent.TASK_INCOMING> & {
75
+ taskData: TaskData;
76
+ };
77
+ [TaskEvent.TASK_OFFERED]: BaseEvent<TaskEvent.TASK_OFFERED> & {
78
+ taskData: TaskData;
79
+ };
80
+ [TaskEvent.OFFER_CONSULT]: BaseEvent<TaskEvent.OFFER_CONSULT> & {
81
+ taskData: TaskData;
82
+ };
83
+ [TaskEvent.HYDRATE]: BaseEvent<TaskEvent.HYDRATE> & {
84
+ taskData: TaskData;
85
+ agentId?: string;
86
+ };
87
+ [TaskEvent.CONTACT_UPDATED]: BaseEvent<TaskEvent.CONTACT_UPDATED> & {
88
+ taskData: TaskData;
89
+ };
90
+ [TaskEvent.CONTACT_OWNER_CHANGED]: BaseEvent<TaskEvent.CONTACT_OWNER_CHANGED> & {
91
+ taskData: TaskData;
92
+ };
93
+ [TaskEvent.ASSIGN]: BaseEvent<TaskEvent.ASSIGN> & {
94
+ taskData: TaskData;
95
+ };
96
+ [TaskEvent.HOLD_INITIATED]: BaseEvent<TaskEvent.HOLD_INITIATED> & {
97
+ mediaResourceId: string;
98
+ };
99
+ [TaskEvent.HOLD_SUCCESS]: BaseEvent<TaskEvent.HOLD_SUCCESS> & {
100
+ mediaResourceId: string;
101
+ taskData?: TaskData;
102
+ };
103
+ [TaskEvent.HOLD_FAILED]: BaseEvent<TaskEvent.HOLD_FAILED> & {
104
+ reason?: string;
105
+ mediaResourceId: string;
106
+ };
107
+ [TaskEvent.UNHOLD_INITIATED]: BaseEvent<TaskEvent.UNHOLD_INITIATED> & {
108
+ mediaResourceId: string;
109
+ };
110
+ [TaskEvent.UNHOLD_SUCCESS]: BaseEvent<TaskEvent.UNHOLD_SUCCESS> & {
111
+ mediaResourceId: string;
112
+ taskData?: TaskData;
113
+ };
114
+ [TaskEvent.UNHOLD_FAILED]: BaseEvent<TaskEvent.UNHOLD_FAILED> & {
115
+ reason?: string;
116
+ mediaResourceId: string;
117
+ };
118
+ [TaskEvent.CONSULT]: BaseEvent<TaskEvent.CONSULT> & {
119
+ destination: string;
120
+ destAgentId?: string;
121
+ destinationType: DestinationType;
122
+ };
123
+ [TaskEvent.CONSULT_SUCCESS]: BaseEvent<TaskEvent.CONSULT_SUCCESS> & {
124
+ taskData?: TaskData;
125
+ };
126
+ [TaskEvent.CONSULT_CREATED]: BaseEvent<TaskEvent.CONSULT_CREATED> & {
127
+ taskData: TaskData;
128
+ };
129
+ [TaskEvent.CONSULTING_ACTIVE]: BaseEvent<TaskEvent.CONSULTING_ACTIVE> & {
130
+ consultDestinationAgentJoined: boolean;
131
+ taskData?: TaskData;
132
+ };
133
+ [TaskEvent.CONSULT_END]: BaseEvent<TaskEvent.CONSULT_END> & {
134
+ taskData?: TaskData;
135
+ };
136
+ [TaskEvent.CONSULT_FAILED]: BaseEvent<TaskEvent.CONSULT_FAILED> & {
137
+ reason?: string;
138
+ taskData?: TaskData;
139
+ };
140
+ [TaskEvent.MERGE_TO_CONFERENCE]: BaseEvent<TaskEvent.MERGE_TO_CONFERENCE>;
141
+ [TaskEvent.CONFERENCE_START]: BaseEvent<TaskEvent.CONFERENCE_START> & {
142
+ participants?: ConferenceParticipant[];
143
+ taskData?: TaskData;
144
+ };
145
+ [TaskEvent.CONFERENCE_FAILED]: BaseEvent<TaskEvent.CONFERENCE_FAILED> & {
146
+ reason?: string;
147
+ taskData?: TaskData;
148
+ };
149
+ [TaskEvent.CONFERENCE_END]: BaseEvent<TaskEvent.CONFERENCE_END> & {
150
+ taskData: TaskData;
151
+ };
152
+ [TaskEvent.TRANSFER_CONFERENCE]: BaseEvent<TaskEvent.TRANSFER_CONFERENCE> & {
153
+ agentId?: string;
154
+ };
155
+ [TaskEvent.PARTICIPANT_LEAVE]: BaseEvent<TaskEvent.PARTICIPANT_LEAVE> & {
156
+ participantId?: string;
157
+ taskData: TaskData;
158
+ };
159
+ [TaskEvent.EXIT_CONFERENCE]: BaseEvent<TaskEvent.EXIT_CONFERENCE> & {
160
+ agentId?: string;
161
+ };
162
+ [TaskEvent.EXIT_CONFERENCE_SUCCESS]: BaseEvent<TaskEvent.EXIT_CONFERENCE_SUCCESS> & {
163
+ taskData: TaskData;
164
+ };
165
+ [TaskEvent.EXIT_CONFERENCE_FAILED]: BaseEvent<TaskEvent.EXIT_CONFERENCE_FAILED> & {
166
+ reason?: string;
167
+ };
168
+ [TaskEvent.TRANSFER_CONFERENCE_SUCCESS]: BaseEvent<TaskEvent.TRANSFER_CONFERENCE_SUCCESS> & {
169
+ taskData: TaskData;
170
+ };
171
+ [TaskEvent.TRANSFER_CONFERENCE_FAILED]: BaseEvent<TaskEvent.TRANSFER_CONFERENCE_FAILED> & {
172
+ reason?: string;
173
+ };
174
+ [TaskEvent.RECORDING_STARTED]: BaseEvent<TaskEvent.RECORDING_STARTED> & {
175
+ taskData: TaskData;
176
+ };
177
+ [TaskEvent.PAUSE_RECORDING]: BaseEvent<TaskEvent.PAUSE_RECORDING> & {
178
+ taskData: TaskData;
179
+ };
180
+ [TaskEvent.RESUME_RECORDING]: BaseEvent<TaskEvent.RESUME_RECORDING> & {
181
+ taskData: TaskData;
182
+ };
183
+ [TaskEvent.TRANSFER_SUCCESS]: BaseEvent<TaskEvent.TRANSFER_SUCCESS> & {
184
+ taskData?: TaskData;
185
+ };
186
+ [TaskEvent.TRANSFER_FAILED]: BaseEvent<TaskEvent.TRANSFER_FAILED> & {
187
+ reason?: string;
188
+ taskData?: TaskData;
189
+ };
190
+ [TaskEvent.WRAPUP_COMPLETE]: BaseEvent<TaskEvent.WRAPUP_COMPLETE> & {
191
+ taskData?: TaskData;
192
+ };
193
+ [TaskEvent.TASK_WRAPUP]: BaseEvent<TaskEvent.TASK_WRAPUP> & {
194
+ taskData?: TaskData;
195
+ };
196
+ [TaskEvent.RONA]: BaseEvent<TaskEvent.RONA> & {
197
+ taskData?: TaskData;
198
+ reason?: string;
199
+ };
200
+ [TaskEvent.CONTACT_ENDED]: BaseEvent<TaskEvent.CONTACT_ENDED> & {
201
+ taskData: TaskData;
202
+ };
203
+ [TaskEvent.ASSIGN_FAILED]: BaseEvent<TaskEvent.ASSIGN_FAILED> & {
204
+ reason?: string;
205
+ };
206
+ [TaskEvent.INVITE_FAILED]: BaseEvent<TaskEvent.INVITE_FAILED> & {
207
+ reason?: string;
208
+ };
209
+ [TaskEvent.OUTBOUND_FAILED]: BaseEvent<TaskEvent.OUTBOUND_FAILED> & {
210
+ reason?: string;
211
+ taskData?: TaskData;
212
+ };
213
+ [TaskEvent.SWITCH_TO_MAIN_CALL]: BaseEvent<TaskEvent.SWITCH_TO_MAIN_CALL>;
214
+ [TaskEvent.SWITCH_TO_CONSULT]: BaseEvent<TaskEvent.SWITCH_TO_CONSULT>;
215
+ [TaskEvent.ACCEPT]: BaseEvent<TaskEvent.ACCEPT>;
216
+ [TaskEvent.DECLINE]: BaseEvent<TaskEvent.DECLINE>;
217
+ [TaskEvent.END]: BaseEvent<TaskEvent.END> & {
218
+ taskData?: TaskData;
219
+ };
220
+ [TaskEvent.CTQ_CANCEL]: BaseEvent<TaskEvent.CTQ_CANCEL> & {
221
+ taskData: TaskData;
222
+ };
223
+ [TaskEvent.CTQ_CANCEL_FAILED]: BaseEvent<TaskEvent.CTQ_CANCEL_FAILED> & {
224
+ taskData: TaskData;
225
+ };
226
+ }
227
+ /**
228
+ * Union of all possible event payloads
229
+ */
230
+ export type TaskEventPayload = TaskEventPayloadMap[TaskEvent];
231
+ /**
232
+ * Type guard to check event type
233
+ */
234
+ export declare function isEventOfType<T extends TaskEvent>(event: TaskEventPayload | undefined, type: T): event is TaskEventPayloadMap[T];
235
+ /**
236
+ * Recording control state for UI controls computer
237
+ */
238
+ export interface RecordingControlState {
239
+ available: boolean;
240
+ inProgress: boolean;
241
+ }
242
+ /**
243
+ * State machine configuration type
244
+ */
245
+ export interface TaskStateMachineConfig {
246
+ id: string;
247
+ initial: TaskState;
248
+ context: TaskContext;
249
+ states: Record<string, AnyStateNodeConfig>;
250
+ }
251
+ export type TaskActionsMap = ActionFunctionMap<TaskContext, TaskEventPayload, never, {
252
+ type: string;
253
+ params: undefined;
254
+ }, never, never, EventObject>;
255
+ export type TaskActionArgs = ActionArgs<TaskContext, TaskEventPayload, TaskEventPayload>;
256
+ export {};
@@ -0,0 +1,9 @@
1
+ /**
2
+ * UI Controls Computer - Centralized logic for computing UI control states
3
+ */
4
+ import { TaskData, TaskUIControls } from '../types';
5
+ import { TaskContext } from './types';
6
+ import { TaskState } from './constants';
7
+ export declare function getDefaultUIControls(): TaskUIControls;
8
+ export declare function computeUIControls(currentState: TaskState, context: TaskContext, fallbackTaskData?: TaskData): TaskUIControls;
9
+ export declare function haveUIControlsChanged(previous: TaskUIControls | undefined, next: TaskUIControls): boolean;
@@ -0,0 +1,10 @@
1
+ import { TaskData } from './types';
2
+ /**
3
+ * Normalize backend task payload quirks so downstream code can rely on actual booleans.
4
+ *
5
+ * Applies to every Agent Contact websocket event before it reaches the state machine:
6
+ * - Converts string booleans in callProcessingDetails to actual booleans.
7
+ * - Also normalizes known boolean fields on interaction and participants.
8
+ * - Keeps payload shape intact; only coerces known boolean fields.
9
+ */
10
+ export declare function normalizeTaskData(data: TaskData): TaskData;