@webex/contact-center 3.11.0 → 3.12.0-llmrefactor.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 (267) hide show
  1. package/.sdd/manifest.json +882 -0
  2. package/AGENTS.md +94 -0
  3. package/ai-docs/ARCHITECTURE.md +168 -0
  4. package/ai-docs/CONTRACTS.md +46 -0
  5. package/ai-docs/GETTING_STARTED.md +168 -0
  6. package/ai-docs/GLOSSARY.md +43 -0
  7. package/ai-docs/README.md +138 -0
  8. package/ai-docs/REVIEW_CHECKLIST.md +41 -0
  9. package/ai-docs/RULES.md +444 -0
  10. package/ai-docs/SECURITY.md +52 -0
  11. package/ai-docs/SERVICE_STATE.md +48 -0
  12. package/ai-docs/SPEC_INDEX.md +65 -0
  13. package/ai-docs/adr/0001-spec-source-policy.md +55 -0
  14. package/ai-docs/adr/README.md +8 -0
  15. package/ai-docs/adr/_adr-template.md +31 -0
  16. package/ai-docs/contact-center-spec.md +341 -0
  17. package/ai-docs/features/generated-spec-conformance-fidelity-remediation/spec/feature-spec.md +117 -0
  18. package/ai-docs/features/residual-warning-coverage-completion/spec/feature-spec.md +203 -0
  19. package/ai-docs/features/validator-code-fidelity-drift-fix/spec/feature-spec.md +315 -0
  20. package/ai-docs/patterns/event-driven-patterns.md +485 -0
  21. package/ai-docs/patterns/testing-patterns.md +480 -0
  22. package/ai-docs/patterns/typescript-patterns.md +365 -0
  23. package/ai-docs/templates/README.md +102 -0
  24. package/ai-docs/templates/documentation/create-agents-md.md +240 -0
  25. package/ai-docs/templates/documentation/create-architecture-md.md +295 -0
  26. package/ai-docs/templates/existing-service/bug-fix.md +254 -0
  27. package/ai-docs/templates/existing-service/feature-enhancement.md +450 -0
  28. package/ai-docs/templates/new-method/00-master.md +80 -0
  29. package/ai-docs/templates/new-method/01-requirements.md +232 -0
  30. package/ai-docs/templates/new-method/02-implementation.md +295 -0
  31. package/ai-docs/templates/new-method/03-tests.md +201 -0
  32. package/ai-docs/templates/new-method/04-validation.md +141 -0
  33. package/ai-docs/templates/new-service/00-master.md +109 -0
  34. package/ai-docs/templates/new-service/01-pre-questions.md +159 -0
  35. package/ai-docs/templates/new-service/02-code-generation.md +346 -0
  36. package/ai-docs/templates/new-service/03-integration.md +178 -0
  37. package/ai-docs/templates/new-service/04-test-generation.md +205 -0
  38. package/ai-docs/templates/new-service/05-validation.md +145 -0
  39. package/dist/cc.js +379 -50
  40. package/dist/cc.js.map +1 -1
  41. package/dist/config.js +6 -0
  42. package/dist/config.js.map +1 -1
  43. package/dist/constants.js +22 -2
  44. package/dist/constants.js.map +1 -1
  45. package/dist/index.js +27 -5
  46. package/dist/index.js.map +1 -1
  47. package/dist/metrics/behavioral-events.js +114 -0
  48. package/dist/metrics/behavioral-events.js.map +1 -1
  49. package/dist/metrics/constants.js +32 -3
  50. package/dist/metrics/constants.js.map +1 -1
  51. package/dist/services/ApiAiAssistant.js +318 -0
  52. package/dist/services/ApiAiAssistant.js.map +1 -0
  53. package/dist/services/UserPreference.js +427 -0
  54. package/dist/services/UserPreference.js.map +1 -0
  55. package/dist/services/agent/types.js.map +1 -1
  56. package/dist/services/config/Util.js +8 -4
  57. package/dist/services/config/Util.js.map +1 -1
  58. package/dist/services/config/constants.js +35 -2
  59. package/dist/services/config/constants.js.map +1 -1
  60. package/dist/services/config/index.js +41 -2
  61. package/dist/services/config/index.js.map +1 -1
  62. package/dist/services/config/types.js +66 -8
  63. package/dist/services/config/types.js.map +1 -1
  64. package/dist/services/constants.js +27 -1
  65. package/dist/services/constants.js.map +1 -1
  66. package/dist/services/core/Err.js.map +1 -1
  67. package/dist/services/core/Utils.js +122 -25
  68. package/dist/services/core/Utils.js.map +1 -1
  69. package/dist/services/core/aqm-reqs.js +92 -17
  70. package/dist/services/core/aqm-reqs.js.map +1 -1
  71. package/dist/services/core/websocket/WebSocketManager.js +22 -6
  72. package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
  73. package/dist/services/core/websocket/connection-service.js +3 -1
  74. package/dist/services/core/websocket/connection-service.js.map +1 -1
  75. package/dist/services/core/websocket/types.js.map +1 -1
  76. package/dist/services/index.js +6 -0
  77. package/dist/services/index.js.map +1 -1
  78. package/dist/services/task/Task.js +688 -0
  79. package/dist/services/task/Task.js.map +1 -0
  80. package/dist/services/task/TaskFactory.js +45 -0
  81. package/dist/services/task/TaskFactory.js.map +1 -0
  82. package/dist/services/task/TaskManager.js +751 -457
  83. package/dist/services/task/TaskManager.js.map +1 -1
  84. package/dist/services/task/TaskUtils.js +220 -23
  85. package/dist/services/task/TaskUtils.js.map +1 -1
  86. package/dist/services/task/constants.js +23 -2
  87. package/dist/services/task/constants.js.map +1 -1
  88. package/dist/services/task/dialer.js +129 -0
  89. package/dist/services/task/dialer.js.map +1 -1
  90. package/dist/services/task/digital/Digital.js +77 -0
  91. package/dist/services/task/digital/Digital.js.map +1 -0
  92. package/dist/services/task/state-machine/TaskStateMachine.js +873 -0
  93. package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -0
  94. package/dist/services/task/state-machine/actions.js +567 -0
  95. package/dist/services/task/state-machine/actions.js.map +1 -0
  96. package/dist/services/task/state-machine/constants.js +161 -0
  97. package/dist/services/task/state-machine/constants.js.map +1 -0
  98. package/dist/services/task/state-machine/guards.js +382 -0
  99. package/dist/services/task/state-machine/guards.js.map +1 -0
  100. package/dist/services/task/state-machine/index.js +53 -0
  101. package/dist/services/task/state-machine/index.js.map +1 -0
  102. package/dist/services/task/state-machine/types.js +54 -0
  103. package/dist/services/task/state-machine/types.js.map +1 -0
  104. package/dist/services/task/state-machine/uiControlsComputer.js +603 -0
  105. package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -0
  106. package/dist/services/task/taskDataNormalizer.js +99 -0
  107. package/dist/services/task/taskDataNormalizer.js.map +1 -0
  108. package/dist/services/task/types.js +227 -4
  109. package/dist/services/task/types.js.map +1 -1
  110. package/dist/services/task/voice/Voice.js +1044 -0
  111. package/dist/services/task/voice/Voice.js.map +1 -0
  112. package/dist/services/task/voice/WebRTC.js +149 -0
  113. package/dist/services/task/voice/WebRTC.js.map +1 -0
  114. package/dist/types/cc.d.ts +894 -0
  115. package/dist/types/config.d.ts +72 -0
  116. package/dist/types/constants.d.ts +66 -0
  117. package/dist/types/index.d.ts +199 -0
  118. package/dist/types/logger-proxy.d.ts +71 -0
  119. package/dist/types/metrics/MetricsManager.d.ts +223 -0
  120. package/dist/types/metrics/behavioral-events.d.ts +29 -0
  121. package/dist/types/metrics/constants.d.ts +181 -0
  122. package/dist/types/services/AddressBook.d.ts +74 -0
  123. package/dist/types/services/ApiAiAssistant.d.ts +49 -0
  124. package/dist/types/services/EntryPoint.d.ts +67 -0
  125. package/dist/types/services/Queue.d.ts +76 -0
  126. package/dist/types/services/UserPreference.d.ts +118 -0
  127. package/dist/types/services/WebCallingService.d.ts +1 -0
  128. package/dist/types/services/agent/index.d.ts +46 -0
  129. package/dist/types/services/agent/types.d.ts +413 -0
  130. package/dist/types/services/config/Util.d.ts +20 -0
  131. package/dist/types/services/config/constants.d.ts +270 -0
  132. package/dist/types/services/config/index.d.ts +177 -0
  133. package/dist/types/services/config/types.d.ts +1368 -0
  134. package/dist/types/services/constants.d.ts +110 -0
  135. package/dist/types/services/core/Err.d.ts +125 -0
  136. package/dist/types/services/core/GlobalTypes.d.ts +58 -0
  137. package/dist/types/services/core/Utils.d.ts +121 -0
  138. package/dist/types/services/core/WebexRequest.d.ts +22 -0
  139. package/dist/types/services/core/aqm-reqs.d.ts +65 -0
  140. package/dist/types/services/core/constants.d.ts +99 -0
  141. package/dist/types/services/core/types.d.ts +47 -0
  142. package/dist/types/services/core/websocket/WebSocketManager.d.ts +36 -0
  143. package/dist/types/services/core/websocket/connection-service.d.ts +27 -0
  144. package/dist/types/services/core/websocket/keepalive.worker.d.ts +2 -0
  145. package/dist/types/services/core/websocket/types.d.ts +37 -0
  146. package/dist/types/services/index.d.ts +54 -0
  147. package/dist/types/services/task/AutoWrapup.d.ts +40 -0
  148. package/dist/types/services/task/Task.d.ts +157 -0
  149. package/dist/types/services/task/TaskFactory.d.ts +12 -0
  150. package/dist/types/services/task/TaskManager.d.ts +1 -0
  151. package/dist/types/services/task/TaskUtils.d.ts +138 -0
  152. package/dist/types/services/task/constants.d.ts +91 -0
  153. package/dist/types/services/task/contact.d.ts +69 -0
  154. package/dist/types/services/task/dialer.d.ts +73 -0
  155. package/dist/types/services/task/digital/Digital.d.ts +22 -0
  156. package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +1194 -0
  157. package/dist/types/services/task/state-machine/actions.d.ts +10 -0
  158. package/dist/types/services/task/state-machine/constants.d.ts +107 -0
  159. package/dist/types/services/task/state-machine/guards.d.ts +102 -0
  160. package/dist/types/services/task/state-machine/index.d.ts +13 -0
  161. package/dist/types/services/task/state-machine/types.d.ts +269 -0
  162. package/dist/types/services/task/state-machine/uiControlsComputer.d.ts +9 -0
  163. package/dist/types/services/task/taskDataNormalizer.d.ts +10 -0
  164. package/dist/types/services/task/types.d.ts +1856 -0
  165. package/dist/types/services/task/voice/Voice.d.ts +184 -0
  166. package/dist/types/services/task/voice/WebRTC.d.ts +53 -0
  167. package/dist/types/types.d.ts +778 -0
  168. package/dist/types/utils/PageCache.d.ts +173 -0
  169. package/dist/types/webex-config.d.ts +53 -0
  170. package/dist/types/webex.d.ts +8 -0
  171. package/dist/types.js +130 -1
  172. package/dist/types.js.map +1 -1
  173. package/dist/webex.js +14 -2
  174. package/dist/webex.js.map +1 -1
  175. package/package.json +16 -12
  176. package/src/cc.ts +477 -51
  177. package/src/config.ts +6 -0
  178. package/src/constants.ts +21 -1
  179. package/src/index.ts +24 -5
  180. package/src/metrics/ai-docs/AGENTS.md +350 -0
  181. package/src/metrics/ai-docs/ARCHITECTURE.md +338 -0
  182. package/src/metrics/ai-docs/metrics-spec.md +854 -0
  183. package/src/metrics/behavioral-events.ts +120 -0
  184. package/src/metrics/constants.ts +37 -3
  185. package/src/services/ApiAiAssistant.ts +412 -0
  186. package/src/services/UserPreference.ts +509 -0
  187. package/src/services/agent/ai-docs/AGENTS.md +240 -0
  188. package/src/services/agent/ai-docs/ARCHITECTURE.md +304 -0
  189. package/src/services/agent/ai-docs/agent-spec.md +504 -0
  190. package/src/services/agent/types.ts +1 -1
  191. package/src/services/ai-docs/AGENTS.md +386 -0
  192. package/src/services/ai-docs/services-spec.md +492 -0
  193. package/src/services/config/Util.ts +10 -2
  194. package/src/services/config/ai-docs/AGENTS.md +255 -0
  195. package/src/services/config/ai-docs/ARCHITECTURE.md +426 -0
  196. package/src/services/config/ai-docs/config-spec.md +669 -0
  197. package/src/services/config/constants.ts +37 -1
  198. package/src/services/config/index.ts +45 -1
  199. package/src/services/config/types.ts +241 -11
  200. package/src/services/constants.ts +29 -0
  201. package/src/services/core/Err.ts +3 -0
  202. package/src/services/core/Utils.ts +143 -30
  203. package/src/services/core/ai-docs/AGENTS.md +381 -0
  204. package/src/services/core/ai-docs/ARCHITECTURE.md +698 -0
  205. package/src/services/core/ai-docs/core-spec.md +783 -0
  206. package/src/services/core/aqm-reqs.ts +100 -22
  207. package/src/services/core/websocket/WebSocketManager.ts +23 -6
  208. package/src/services/core/websocket/connection-service.ts +5 -1
  209. package/src/services/core/websocket/types.ts +1 -1
  210. package/src/services/index.ts +4 -0
  211. package/src/services/task/Task.ts +837 -0
  212. package/src/services/task/TaskFactory.ts +55 -0
  213. package/src/services/task/TaskManager.ts +793 -521
  214. package/src/services/task/TaskUtils.ts +314 -24
  215. package/src/services/task/ai-docs/AGENTS.md +457 -0
  216. package/src/services/task/ai-docs/ARCHITECTURE.md +594 -0
  217. package/src/services/task/ai-docs/task-spec.md +1319 -0
  218. package/src/services/task/constants.ts +23 -0
  219. package/src/services/task/dialer.ts +136 -1
  220. package/src/services/task/digital/Digital.ts +95 -0
  221. package/src/services/task/state-machine/TaskStateMachine.ts +1166 -0
  222. package/src/services/task/state-machine/actions.ts +738 -0
  223. package/src/services/task/state-machine/ai-docs/AGENTS.md +458 -0
  224. package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +1137 -0
  225. package/src/services/task/state-machine/ai-docs/task-state-machine-spec.md +2177 -0
  226. package/src/services/task/state-machine/constants.ts +172 -0
  227. package/src/services/task/state-machine/guards.ts +445 -0
  228. package/src/services/task/state-machine/index.ts +28 -0
  229. package/src/services/task/state-machine/types.ts +243 -0
  230. package/src/services/task/state-machine/uiControlsComputer.ts +961 -0
  231. package/src/services/task/taskDataNormalizer.ts +137 -0
  232. package/src/services/task/types.ts +734 -71
  233. package/src/services/task/voice/Voice.ts +1270 -0
  234. package/src/services/task/voice/WebRTC.ts +187 -0
  235. package/src/types.ts +205 -2
  236. package/src/utils/AGENTS.md +278 -0
  237. package/src/utils/ai-docs/utils-spec.md +381 -0
  238. package/src/webex.js +2 -0
  239. package/test/unit/spec/cc.ts +503 -43
  240. package/test/unit/spec/logger-proxy.ts +70 -0
  241. package/test/unit/spec/services/ApiAiAssistant.ts +273 -0
  242. package/test/unit/spec/services/UserPreference.ts +401 -0
  243. package/test/unit/spec/services/WebCallingService.ts +7 -1
  244. package/test/unit/spec/services/config/index.ts +85 -29
  245. package/test/unit/spec/services/core/Utils.ts +481 -2
  246. package/test/unit/spec/services/core/websocket/WebSocketManager.ts +137 -41
  247. package/test/unit/spec/services/core/websocket/connection-service.ts +3 -1
  248. package/test/unit/spec/services/task/AutoWrapup.ts +63 -0
  249. package/test/unit/spec/services/task/Task.ts +477 -0
  250. package/test/unit/spec/services/task/TaskFactory.ts +62 -0
  251. package/test/unit/spec/services/task/TaskManager.ts +1001 -1003
  252. package/test/unit/spec/services/task/TaskUtils.ts +235 -0
  253. package/test/unit/spec/services/task/dialer.ts +372 -96
  254. package/test/unit/spec/services/task/digital/Digital.ts +105 -0
  255. package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +2651 -0
  256. package/test/unit/spec/services/task/state-machine/guards.ts +637 -0
  257. package/test/unit/spec/services/task/state-machine/types.ts +18 -0
  258. package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +2663 -0
  259. package/test/unit/spec/services/task/taskTestUtils.ts +87 -0
  260. package/test/unit/spec/services/task/voice/Voice.ts +649 -0
  261. package/test/unit/spec/services/task/voice/WebRTC.ts +235 -0
  262. package/umd/contact-center.min.js +2 -2
  263. package/umd/contact-center.min.js.map +1 -1
  264. package/dist/services/task/index.js +0 -1525
  265. package/dist/services/task/index.js.map +0 -1
  266. package/src/services/task/index.ts +0 -1801
  267. package/test/unit/spec/services/task/index.ts +0 -2184
@@ -0,0 +1,567 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.actions = void 0;
7
+ exports.createInitialContext = createInitialContext;
8
+ exports.getTaskStateForUiControls = void 0;
9
+ exports.updateUIControls = updateUIControls;
10
+ var _xstate = require("xstate");
11
+ var _constants = require("./constants");
12
+ var _types = require("../../config/types");
13
+ var _uiControlsComputer = require("./uiControlsComputer");
14
+ var _TaskUtils = require("../TaskUtils");
15
+ var _guards = require("./guards");
16
+ /**
17
+ * Task State Machine Actions - Action implementations executed during state transitions
18
+ */
19
+
20
+ /** Terminal consult events that clear consult context in deriveTaskDataUpdates. */
21
+ const CONSULT_CONTEXT_CLEAR_EVENTS = new Set([_types.CC_EVENTS.AGENT_CONSULT_ENDED, _types.CC_EVENTS.AGENT_CONSULT_FAILED]);
22
+ const determineConsultInitiator = (taskData, selfAgentId) => {
23
+ if (!selfAgentId) return undefined;
24
+ if (taskData?.consultingAgentId) {
25
+ return taskData.consultingAgentId === selfAgentId;
26
+ }
27
+ if (taskData?.isConsulted === true) return false;
28
+ return undefined;
29
+ };
30
+ const deriveRecordingState = taskData => {
31
+ const callProcessingDetails = taskData?.interaction?.callProcessingDetails;
32
+ if (!callProcessingDetails) {
33
+ return {};
34
+ }
35
+ const update = {};
36
+ const {
37
+ recordingStarted,
38
+ recordInProgress,
39
+ isPaused
40
+ } = callProcessingDetails;
41
+ if (recordingStarted !== undefined) {
42
+ update.recordingControlsAvailable = recordingStarted;
43
+ if (!recordingStarted) {
44
+ update.recordingInProgress = false;
45
+ }
46
+ }
47
+ if (recordInProgress !== undefined) {
48
+ update.recordingControlsAvailable = recordInProgress || recordingStarted || false;
49
+ update.recordingInProgress = recordInProgress;
50
+ }
51
+ if (update.recordingControlsAvailable === undefined && update.recordingInProgress === undefined && recordingStarted) {
52
+ update.recordingControlsAvailable = true;
53
+ update.recordingInProgress = true;
54
+ }
55
+ if (isPaused !== undefined) {
56
+ update.recordingControlsAvailable = true;
57
+ update.recordingInProgress = !isPaused;
58
+ }
59
+ return update;
60
+ };
61
+ const isActiveConsultState = (taskData, selfAgentId) => {
62
+ if (taskData?.interaction?.state === _constants.INTERACTION_STATE.CONSULTING) return true;
63
+ if (selfAgentId) {
64
+ const selfParticipant = taskData?.interaction?.participants?.[selfAgentId];
65
+ const hasConsultMedia = Object.values(taskData?.interaction?.media ?? {}).some(media => media?.mType === _constants.MEDIA_TYPE_CONSULT);
66
+ // Pending consult before destination joins stays HELD, not CONSULTING.
67
+ if (selfParticipant?.consultState === 'consultInitiated' && !hasJoinedConsultDestination(taskData, selfAgentId) && hasConsultMedia && taskData?.isConsulted === false) {
68
+ return false;
69
+ }
70
+ if ((selfParticipant?.consultState === _constants.CONSULT_STATE.CONSULTING || selfParticipant?.consultState === _constants.CONSULT_STATE.CONFERENCING) && hasConsultMedia && taskData?.isConsulted === false) {
71
+ return true;
72
+ }
73
+ }
74
+ if (taskData?.interaction?.state === _constants.INTERACTION_STATE.POST_CALL && selfAgentId) {
75
+ const selfParticipant = taskData.interaction?.participants?.[selfAgentId];
76
+ const hasConsultMedia = Object.values(taskData.interaction?.media ?? {}).some(media => media?.mType === _constants.MEDIA_TYPE_CONSULT);
77
+ if (selfParticipant?.consultState === _constants.CONSULT_STATE.CONSULTING && hasConsultMedia) return true;
78
+ }
79
+ return false;
80
+ };
81
+ const isSelfConsultingOrPending = (taskData, selfAgentId) => {
82
+ if (!taskData || !selfAgentId) return false;
83
+ const selfParticipant = taskData?.interaction?.participants?.[selfAgentId];
84
+ return selfParticipant?.consultState === _constants.CONSULT_STATE.CONSULTING || selfParticipant?.consultState === _constants.CONSULT_STATE.CONFERENCING || selfParticipant?.consultState === 'consultInitiated';
85
+ };
86
+ const isDnOnConsultMedia = (taskData, selfAgentId) => {
87
+ if (!taskData?.interaction?.participants) return false;
88
+ const consultMedia = taskData.consultMediaResourceId ? taskData.interaction.media?.[taskData.consultMediaResourceId] : Object.values(taskData.interaction.media ?? {}).find(m => m?.mType === _constants.MEDIA_TYPE_CONSULT);
89
+ const consultParticipantIds = new Set(consultMedia?.participants ?? []);
90
+ if (consultParticipantIds.size === 0) return false;
91
+ return Object.values(taskData.interaction.participants).some(p => {
92
+ if (!p || p.hasLeft || p.id === selfAgentId) return false;
93
+ if (!consultParticipantIds.has(p.id)) return false;
94
+ const pType = String(p.pType ?? '').toUpperCase();
95
+ return pType === 'DN' || pType === 'EP-DN' || pType === 'EP_DN';
96
+ });
97
+ };
98
+ const mapConsultDestinationType = destinationType => {
99
+ if (!destinationType) return undefined;
100
+ const normalized = String(destinationType).toUpperCase();
101
+ if (normalized === 'DN' || normalized === 'EP-DN' || normalized === 'EP_DN') {
102
+ return 'entryPoint';
103
+ }
104
+ return destinationType;
105
+ };
106
+ const hasJoinedConsultDestination = (taskData, selfAgentId) => {
107
+ if (!taskData?.interaction) return false;
108
+ const participants = taskData.interaction.participants;
109
+ const cpd = taskData.interaction.callProcessingDetails;
110
+ const backendSaysJoined = cpd?.consultDestinationAgentJoined === 'true';
111
+ if (backendSaysJoined) return true;
112
+ if (!participants) return false;
113
+ const effectiveSelfAgentId = selfAgentId ?? taskData.agentId;
114
+ const selfParticipant = effectiveSelfAgentId ? participants[effectiveSelfAgentId] : undefined;
115
+ if (taskData.type === 'AgentConsulting' && selfParticipant?.consultState === _constants.CONSULT_STATE.CONSULTING && taskData.isConsulted === false && isDnOnConsultMedia(taskData, effectiveSelfAgentId)) {
116
+ return true;
117
+ }
118
+ return Object.values(participants).some(p => {
119
+ if (!p || p.isConsulted !== true || p.hasLeft) return false;
120
+ return p.hasJoined === true || p.consultState === _constants.CONSULT_STATE.CONSULTING;
121
+ });
122
+ };
123
+ const deriveConsultCallHeldFromTaskData = taskData => {
124
+ if (!taskData?.interaction) return undefined;
125
+ const eventType = taskData.type;
126
+ if (eventType === 'AgentContactHeld') return true;
127
+ if (eventType === 'AgentContactUnheld') return false;
128
+ const consultMediaId = taskData.consultMediaResourceId;
129
+ const consultMedia = consultMediaId ? taskData.interaction.media?.[consultMediaId] : Object.values(taskData.interaction.media ?? {}).find(m => m?.mType === _constants.MEDIA_TYPE_CONSULT);
130
+ if (!consultMedia) return undefined;
131
+ return Boolean(consultMedia.isHold);
132
+ };
133
+ const getTaskStateForUiControls = (taskData, selfAgentId) => {
134
+ if (!taskData?.interaction) {
135
+ return _constants.TaskState.IDLE;
136
+ }
137
+ if (taskData.interaction.isTerminated === true) {
138
+ return _constants.TaskState.WRAPPING_UP;
139
+ }
140
+
141
+ // EP-DN consult merged to conference before Agent 2 joins main — UI is conferencing (CAI-8329).
142
+ if ((0, _TaskUtils.isEpDnConsultPendingConferenceMerge)(taskData, selfAgentId)) {
143
+ return _constants.TaskState.CONFERENCING;
144
+ }
145
+ if (isActiveConsultState(taskData, selfAgentId)) {
146
+ return _constants.TaskState.CONSULTING;
147
+ }
148
+ if (taskData.interaction.state === _constants.INTERACTION_STATE.CONFERENCE || (0, _TaskUtils.getIsConferenceInProgress)(taskData)) {
149
+ return _constants.TaskState.CONFERENCING;
150
+ }
151
+ const mainMediaId = taskData.interaction.mainInteractionId || taskData.interactionId;
152
+ const isMainHeld = Boolean(mainMediaId && taskData.interaction.media?.[mainMediaId]?.isHold === true);
153
+ if (taskData.interaction.state === 'hold' || isMainHeld) {
154
+ return _constants.TaskState.HELD;
155
+ }
156
+ return _constants.TaskState.CONNECTED;
157
+ };
158
+ exports.getTaskStateForUiControls = getTaskStateForUiControls;
159
+ const deriveTaskDataUpdates = (context, taskData) => taskData ? (() => {
160
+ const enrichedTaskData = taskData.type === 'AgentConsultCreated' && taskData.agentId ? {
161
+ ...taskData,
162
+ consultingAgentId: taskData.agentId
163
+ } : taskData;
164
+ const updates = {
165
+ taskData: enrichedTaskData,
166
+ ...deriveRecordingState(enrichedTaskData)
167
+ };
168
+ const selfAgentId = context.uiControlConfig.agentId ?? enrichedTaskData?.agentId;
169
+ const consultingActive = isActiveConsultState(enrichedTaskData, selfAgentId) || (0, _guards.hasActiveConsultInPostCall)(enrichedTaskData, selfAgentId);
170
+ const conferenceFromPayload = enrichedTaskData?.interaction?.state === _constants.INTERACTION_STATE.CONFERENCE || (0, _TaskUtils.getIsConferenceInProgress)(enrichedTaskData);
171
+ const selfConsultingOrPending = isSelfConsultingOrPending(enrichedTaskData, selfAgentId);
172
+ const inferredConsultingInitiator = selfConsultingOrPending && enrichedTaskData?.isConsulted === false;
173
+ if (enrichedTaskData.destAgentId) {
174
+ const isEpDnWithStoredId = context.consultDestinationType === 'entryPoint' && context.consultDestinationAgentId;
175
+ if (!isEpDnWithStoredId) {
176
+ updates.consultDestinationAgentId = enrichedTaskData.destAgentId;
177
+ }
178
+ }
179
+ const isConsultTerminalEvent = enrichedTaskData.type != null && CONSULT_CONTEXT_CLEAR_EVENTS.has(enrichedTaskData.type);
180
+ const epDnPendingMergeActive = (0, _TaskUtils.isEpDnConsultPendingConferenceMerge)(enrichedTaskData, selfAgentId);
181
+ if (isConsultTerminalEvent && !epDnPendingMergeActive) {
182
+ updates.consultInitiator = false;
183
+ updates.consultFromConference = false;
184
+ updates.consultDestinationAgentJoined = false;
185
+ updates.consultCallHeld = false;
186
+ updates.consultDestinationType = null;
187
+ updates.consultDestinationAgentId = null;
188
+ updates.transferConferenceRequested = false;
189
+ updates.hideBlindTransferForEpDnPendingMerge = false;
190
+ }
191
+ updates.hideBlindTransferForEpDnPendingMerge = (0, _TaskUtils.isEpDnConsultPendingConferenceMerge)(enrichedTaskData, selfAgentId);
192
+ if (consultingActive && enrichedTaskData.destinationType) {
193
+ updates.consultDestinationType = mapConsultDestinationType(enrichedTaskData.destinationType);
194
+ }
195
+ if (!isConsultTerminalEvent) {
196
+ const consultInitiator = determineConsultInitiator(enrichedTaskData, selfAgentId);
197
+ if (consultInitiator !== undefined) {
198
+ updates.consultInitiator = consultInitiator;
199
+ } else if (enrichedTaskData.type === 'AgentConsultCreated' && enrichedTaskData.agentId && enrichedTaskData.agentId !== selfAgentId && conferenceFromPayload) {
200
+ updates.consultInitiator = false;
201
+ } else if (!context.consultInitiator) {
202
+ if (inferredConsultingInitiator || consultingActive && enrichedTaskData.isConsulted === false) {
203
+ updates.consultInitiator = true;
204
+ }
205
+ }
206
+ }
207
+ const effectiveConsultInitiator = updates.consultInitiator ?? context.consultInitiator;
208
+ if (!isConsultTerminalEvent && effectiveConsultInitiator && conferenceFromPayload && (consultingActive || selfConsultingOrPending || Boolean(enrichedTaskData?.consultMediaResourceId))) {
209
+ updates.consultFromConference = true;
210
+ }
211
+ if (!isConsultTerminalEvent && (consultingActive || selfConsultingOrPending) && enrichedTaskData.interaction) {
212
+ const joinedConsultee = hasJoinedConsultDestination(enrichedTaskData, selfAgentId);
213
+ const selfParticipant = selfAgentId ? enrichedTaskData.interaction.participants?.[selfAgentId] : undefined;
214
+ const agentConsultingSelfJoined = enrichedTaskData.type === 'AgentConsulting' && effectiveConsultInitiator && selfParticipant?.consultState === _constants.CONSULT_STATE.CONSULTING;
215
+ if (joinedConsultee || agentConsultingSelfJoined) {
216
+ updates.consultDestinationAgentJoined = true;
217
+ } else if (selfParticipant?.consultState === 'consultInitiated') {
218
+ updates.consultDestinationAgentJoined = false;
219
+ }
220
+ if (!context.consultDestinationType && !updates.consultDestinationType) {
221
+ const hasEpDnParticipant = Boolean(enrichedTaskData.interaction.participants && Object.values(enrichedTaskData.interaction.participants).some(p => {
222
+ if (p?.hasLeft) return false;
223
+ const pType = String(p?.pType ?? '').toUpperCase();
224
+ return pType === 'EP-DN' || pType === 'EP_DN' || pType === 'DN';
225
+ }));
226
+ if (hasEpDnParticipant) updates.consultDestinationType = 'entryPoint';
227
+ }
228
+ if (effectiveConsultInitiator) {
229
+ const consultCallHeld = deriveConsultCallHeldFromTaskData(enrichedTaskData);
230
+ if (consultCallHeld !== undefined) {
231
+ updates.consultCallHeld = consultCallHeld;
232
+ }
233
+ }
234
+ }
235
+ const nextContext = {
236
+ ...context,
237
+ ...updates
238
+ };
239
+ const inferredState = getTaskStateForUiControls(enrichedTaskData, selfAgentId);
240
+ updates.uiControls = (0, _uiControlsComputer.computeUIControls)(inferredState, nextContext, enrichedTaskData);
241
+ return updates;
242
+ })() : {};
243
+ const getTaskDataFromEvent = event => event && typeof event === 'object' ? event.taskData : undefined;
244
+ function createInitialContext(uiControlConfig, initialState = _constants.TaskState.IDLE) {
245
+ const baseContext = {
246
+ taskData: null,
247
+ consultInitiator: false,
248
+ exitingConference: false,
249
+ consultFromConference: false,
250
+ transferConferenceRequested: false,
251
+ consultDestinationType: null,
252
+ consultDestinationAgentId: null,
253
+ consultDestinationAgentJoined: false,
254
+ consultCallHeld: false,
255
+ hideBlindTransferForEpDnPendingMerge: false,
256
+ recordingControlsAvailable: false,
257
+ recordingInProgress: false,
258
+ uiControlConfig,
259
+ uiControls: (0, _uiControlsComputer.getDefaultUIControls)()
260
+ };
261
+ baseContext.uiControls = (0, _uiControlsComputer.computeUIControls)(initialState, baseContext);
262
+ return baseContext;
263
+ }
264
+ function updateUIControls(currentState) {
265
+ return (0, _xstate.assign)(({
266
+ context
267
+ }) => ({
268
+ uiControls: (0, _uiControlsComputer.computeUIControls)(currentState, context, context.taskData ?? undefined)
269
+ }));
270
+ }
271
+ const actions = exports.actions = {
272
+ initializeTask: (0, _xstate.assign)(({
273
+ context,
274
+ event
275
+ }) => {
276
+ return {
277
+ consultInitiator: false,
278
+ exitingConference: false,
279
+ consultDestinationType: null,
280
+ consultDestinationAgentJoined: false,
281
+ ...deriveTaskDataUpdates(context, getTaskDataFromEvent(event))
282
+ };
283
+ }),
284
+ /**
285
+ * Update task data from ASSIGN event
286
+ */
287
+ updateTaskData: (0, _xstate.assign)(({
288
+ context,
289
+ event
290
+ }) => {
291
+ return deriveTaskDataUpdates(context, getTaskDataFromEvent(event));
292
+ }),
293
+ /**
294
+ * Set consult initiator flag
295
+ *
296
+ * IMPORTANT: This action is called for CONSULT (user action) and CONSULT_CREATED (backend event).
297
+ * For CONSULT (user action): The user explicitly clicked Consult, so they ARE the initiator.
298
+ * For CONSULT_CREATED (backend event): Check taskData.isConsulted to determine if this agent
299
+ * is the initiator. If isConsulted === true, this is Agent B (the consulted party), NOT the initiator.
300
+ *
301
+ * This prevents all agents in a conference from becoming consultInitiator when one agent
302
+ * starts a new consult.
303
+ */
304
+ setConsultInitiator: (0, _xstate.assign)(({
305
+ event
306
+ }) => {
307
+ const taskData = getTaskDataFromEvent(event);
308
+ if (event.type === _constants.TaskEvent.CONSULT) return {
309
+ consultInitiator: true
310
+ };
311
+ const selfAgentId = taskData?.agentId;
312
+ const consultInitiator = determineConsultInitiator(taskData, selfAgentId);
313
+ if (consultInitiator === true) return {
314
+ consultInitiator: true
315
+ };
316
+ if (consultInitiator === false) return {
317
+ consultInitiator: false
318
+ };
319
+ return {};
320
+ }),
321
+ handleConsultFailed: (0, _xstate.assign)(({
322
+ context,
323
+ event
324
+ }) => {
325
+ const taskData = getTaskDataFromEvent(event) ?? context.taskData;
326
+ const selfAgentId = context.uiControlConfig.agentId ?? taskData?.agentId;
327
+ const hideBlindTransferForEpDnPendingMerge = (0, _TaskUtils.isEpDnConsultPendingConferenceMerge)(taskData, selfAgentId);
328
+ const cleared = {
329
+ consultDestinationType: null,
330
+ consultDestinationAgentId: null,
331
+ consultDestinationAgentJoined: false,
332
+ consultInitiator: false,
333
+ exitingConference: false,
334
+ consultCallHeld: false,
335
+ consultFromConference: false,
336
+ transferConferenceRequested: false,
337
+ hideBlindTransferForEpDnPendingMerge
338
+ };
339
+ const nextContext = {
340
+ ...context,
341
+ ...cleared,
342
+ taskData
343
+ };
344
+ const inferredState = getTaskStateForUiControls(taskData, selfAgentId);
345
+ return {
346
+ ...cleared,
347
+ uiControls: (0, _uiControlsComputer.computeUIControls)(inferredState, nextContext, taskData)
348
+ };
349
+ }),
350
+ handleConferenceStarted: (0, _xstate.assign)({
351
+ consultInitiator: false
352
+ }),
353
+ setConsultDestination: (0, _xstate.assign)(({
354
+ event
355
+ }) => {
356
+ if (!event || event.type !== _constants.TaskEvent.CONSULT) {
357
+ return {};
358
+ }
359
+ const taskData = getTaskDataFromEvent(event);
360
+ const consultDestinationType = 'destinationType' in event ? event.destinationType ?? null : null;
361
+ const consultDestinationAgentId = ('destAgentId' in event ? event.destAgentId : null) ?? ('destination' in event ? event.destination : null) ?? null;
362
+ return {
363
+ consultDestinationType,
364
+ consultDestinationAgentId,
365
+ consultDestinationAgentJoined: false,
366
+ consultFromConference: false,
367
+ taskData: {
368
+ ...taskData,
369
+ destAgentId: consultDestinationAgentId
370
+ }
371
+ };
372
+ }),
373
+ setConsultFromConference: (0, _xstate.assign)({
374
+ consultFromConference: true
375
+ }),
376
+ forceConsultInitiator: (0, _xstate.assign)({
377
+ consultInitiator: true
378
+ }),
379
+ setConsultAgentJoined: (0, _xstate.assign)(({
380
+ context,
381
+ event
382
+ }) => {
383
+ if (context.consultDestinationAgentJoined) {
384
+ return {};
385
+ }
386
+ if (!event || event.type !== _constants.TaskEvent.CONSULTING_ACTIVE || !('consultDestinationAgentJoined' in event)) {
387
+ return {};
388
+ }
389
+ const eventValue = event.consultDestinationAgentJoined;
390
+ return eventValue ? {
391
+ consultDestinationAgentJoined: true
392
+ } : {};
393
+ }),
394
+ setRecordingState: (0, _xstate.assign)(({
395
+ event
396
+ }) => {
397
+ if (!event || !('type' in event)) {
398
+ return {};
399
+ }
400
+ if (event.type === _constants.TaskEvent.PAUSE_RECORDING) {
401
+ return {
402
+ recordingControlsAvailable: true,
403
+ recordingInProgress: false
404
+ };
405
+ }
406
+ if (event.type === _constants.TaskEvent.RESUME_RECORDING) {
407
+ return {
408
+ recordingControlsAvailable: true,
409
+ recordingInProgress: true
410
+ };
411
+ }
412
+ return {};
413
+ }),
414
+ clearConsultState: (0, _xstate.assign)(({
415
+ context,
416
+ event
417
+ }) => {
418
+ const taskData = context.taskData ?? getTaskDataFromEvent(event);
419
+ const selfAgentId = context.uiControlConfig.agentId ?? taskData?.agentId;
420
+ const hideBlindTransferForEpDnPendingMerge = (0, _TaskUtils.isEpDnConsultPendingConferenceMerge)(taskData, selfAgentId);
421
+ const cleared = {
422
+ consultDestinationType: null,
423
+ consultDestinationAgentId: null,
424
+ consultDestinationAgentJoined: false,
425
+ consultInitiator: false,
426
+ exitingConference: false,
427
+ consultCallHeld: false,
428
+ consultFromConference: false,
429
+ transferConferenceRequested: false,
430
+ hideBlindTransferForEpDnPendingMerge
431
+ };
432
+ const nextContext = {
433
+ ...context,
434
+ ...cleared,
435
+ taskData
436
+ };
437
+ const inferredState = getTaskStateForUiControls(taskData, selfAgentId);
438
+ return {
439
+ ...cleared,
440
+ uiControls: (0, _uiControlsComputer.computeUIControls)(inferredState, nextContext, taskData)
441
+ };
442
+ }),
443
+ setTransferConferenceRequested: (0, _xstate.assign)({
444
+ transferConferenceRequested: true
445
+ }),
446
+ clearTransferConferenceRequested: (0, _xstate.assign)({
447
+ transferConferenceRequested: false
448
+ }),
449
+ setConsultCallHeld: (0, _xstate.assign)({
450
+ consultCallHeld: true
451
+ }),
452
+ clearConsultCallHeld: (0, _xstate.assign)({
453
+ consultCallHeld: false
454
+ }),
455
+ handleSwitchToMainCall: (0, _xstate.assign)({
456
+ consultCallHeld: true
457
+ }),
458
+ handleSwitchToConsult: (0, _xstate.assign)({
459
+ consultCallHeld: false
460
+ }),
461
+ handleConferenceFailed: (0, _xstate.assign)(({
462
+ event
463
+ }) => {
464
+ const taskData = getTaskDataFromEvent(event);
465
+ return taskData ? {
466
+ taskData
467
+ } : {};
468
+ }),
469
+ handleParticipantLeft: (0, _xstate.assign)(({
470
+ event
471
+ }) => {
472
+ const taskData = getTaskDataFromEvent(event);
473
+ return taskData ? {
474
+ taskData
475
+ } : {};
476
+ }),
477
+ setExitingConference: (0, _xstate.assign)({
478
+ exitingConference: true
479
+ }),
480
+ handleTransferConferenceSuccess: (0, _xstate.assign)(({
481
+ event
482
+ }) => {
483
+ const taskData = getTaskDataFromEvent(event);
484
+ return taskData ? {
485
+ taskData
486
+ } : {};
487
+ }),
488
+ setHoldState: (0, _xstate.assign)(({
489
+ context,
490
+ event
491
+ }) => {
492
+ if (!event || event.type !== _constants.TaskEvent.HOLD_SUCCESS && event.type !== _constants.TaskEvent.UNHOLD_SUCCESS) {
493
+ return {};
494
+ }
495
+ const mediaResourceId = 'mediaResourceId' in event ? event.mediaResourceId : undefined;
496
+ if (!mediaResourceId) {
497
+ return {};
498
+ }
499
+ const interaction = context.taskData?.interaction;
500
+ const mediaEntry = interaction?.media?.[mediaResourceId];
501
+ if (!interaction || !mediaEntry) {
502
+ return {};
503
+ }
504
+ const updatedMedia = {
505
+ ...interaction.media,
506
+ [mediaResourceId]: {
507
+ ...mediaEntry,
508
+ isHold: event.type === _constants.TaskEvent.HOLD_SUCCESS
509
+ }
510
+ };
511
+ const updates = {
512
+ taskData: {
513
+ ...context.taskData,
514
+ interaction: {
515
+ ...interaction,
516
+ media: updatedMedia
517
+ }
518
+ }
519
+ };
520
+ const consultMediaId = context.taskData?.consultMediaResourceId;
521
+ const isConsultMedia = consultMediaId ? mediaResourceId === consultMediaId : mediaEntry?.mType === 'consult';
522
+ if (isConsultMedia && context.consultInitiator) {
523
+ updates.consultCallHeld = event.type === _constants.TaskEvent.HOLD_SUCCESS;
524
+ }
525
+ return updates;
526
+ }),
527
+ markEnded: (0, _xstate.assign)(() => ({
528
+ recordingControlsAvailable: false,
529
+ recordingInProgress: false
530
+ })),
531
+ requestAutoAnswer: () => undefined,
532
+ requestCleanup: () => undefined,
533
+ cleanupResources: () => undefined,
534
+ // Event emitters - placeholders overridden by consumers
535
+ emitTaskCampaignPreviewReservation: () => undefined,
536
+ emitTaskCampaignPreviewAcceptFailed: () => undefined,
537
+ emitTaskCampaignPreviewSkipFailed: () => undefined,
538
+ emitTaskCampaignPreviewRemoveFailed: () => undefined,
539
+ emitTaskIncoming: () => undefined,
540
+ emitTaskHydrate: () => undefined,
541
+ emitTaskOfferContact: () => undefined,
542
+ emitTaskAssigned: () => undefined,
543
+ emitTaskHold: () => undefined,
544
+ emitTaskResume: () => undefined,
545
+ emitTaskEnd: () => undefined,
546
+ emitTaskOfferConsult: () => undefined,
547
+ emitTaskConsultCreated: () => undefined,
548
+ emitTaskConsulting: () => undefined,
549
+ emitTaskConsultAccepted: () => undefined,
550
+ emitTaskConsultEnd: () => undefined,
551
+ emitTaskReject: () => undefined,
552
+ emitTaskWrapup: () => undefined,
553
+ emitTaskRecordingStarted: () => undefined,
554
+ emitTaskRecordingPaused: () => undefined,
555
+ emitTaskRecordingResumed: () => undefined,
556
+ emitTaskWrappedup: () => undefined,
557
+ emitTaskParticipantLeft: () => undefined,
558
+ emitTaskConferenceStarted: () => undefined,
559
+ emitTaskConferenceEnded: () => undefined,
560
+ emitTaskExitConference: () => undefined,
561
+ emitTaskTransferConference: () => undefined,
562
+ emitTaskSwitchCall: () => undefined,
563
+ emitTaskConferenceFailed: () => undefined,
564
+ emitTaskTransferConferenceFailed: () => undefined,
565
+ emitTaskOutdialFailed: () => undefined
566
+ };
567
+ //# sourceMappingURL=actions.js.map