@webex/contact-center 3.12.0-next.16 → 3.12.0-next.161

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 (328) hide show
  1. package/.sdd/manifest.json +887 -0
  2. package/AGENTS.md +94 -0
  3. package/ai-docs/ARCHITECTURE.md +168 -0
  4. package/ai-docs/CONTRACTS.md +62 -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 +52 -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 +385 -0
  17. package/ai-docs/features/consult-transfer-list-policy/spec/feature-spec.md +362 -0
  18. package/ai-docs/features/contact-owner-change-refactor.md +78 -0
  19. package/ai-docs/features/generated-spec-conformance-fidelity-remediation/spec/feature-spec.md +117 -0
  20. package/ai-docs/features/residual-warning-coverage-completion/spec/feature-spec.md +203 -0
  21. package/ai-docs/features/validator-code-fidelity-drift-fix/spec/feature-spec.md +315 -0
  22. package/ai-docs/patterns/event-driven-patterns.md +485 -0
  23. package/ai-docs/patterns/testing-patterns.md +480 -0
  24. package/ai-docs/patterns/typescript-patterns.md +365 -0
  25. package/ai-docs/templates/README.md +102 -0
  26. package/ai-docs/templates/documentation/create-agents-md.md +240 -0
  27. package/ai-docs/templates/documentation/create-architecture-md.md +295 -0
  28. package/ai-docs/templates/existing-service/bug-fix.md +254 -0
  29. package/ai-docs/templates/existing-service/feature-enhancement.md +450 -0
  30. package/ai-docs/templates/new-method/00-master.md +80 -0
  31. package/ai-docs/templates/new-method/01-requirements.md +232 -0
  32. package/ai-docs/templates/new-method/02-implementation.md +295 -0
  33. package/ai-docs/templates/new-method/03-tests.md +201 -0
  34. package/ai-docs/templates/new-method/04-validation.md +141 -0
  35. package/ai-docs/templates/new-service/00-master.md +109 -0
  36. package/ai-docs/templates/new-service/01-pre-questions.md +159 -0
  37. package/ai-docs/templates/new-service/02-code-generation.md +346 -0
  38. package/ai-docs/templates/new-service/03-integration.md +178 -0
  39. package/ai-docs/templates/new-service/04-test-generation.md +205 -0
  40. package/ai-docs/templates/new-service/05-validation.md +145 -0
  41. package/dist/cc.js +888 -49
  42. package/dist/cc.js.map +1 -1
  43. package/dist/config.js +13 -0
  44. package/dist/config.js.map +1 -1
  45. package/dist/constants.js +38 -3
  46. package/dist/constants.js.map +1 -1
  47. package/dist/index.js +54 -17
  48. package/dist/index.js.map +1 -1
  49. package/dist/metrics/MetricsManager.js +16 -0
  50. package/dist/metrics/MetricsManager.js.map +1 -1
  51. package/dist/metrics/behavioral-events.js +185 -0
  52. package/dist/metrics/behavioral-events.js.map +1 -1
  53. package/dist/metrics/constants.js +54 -4
  54. package/dist/metrics/constants.js.map +1 -1
  55. package/dist/services/AddressBook.js +18 -15
  56. package/dist/services/AddressBook.js.map +1 -1
  57. package/dist/services/AnswerCallOnWebexService.js +202 -0
  58. package/dist/services/AnswerCallOnWebexService.js.map +1 -0
  59. package/dist/services/ApiAiAssistant.js +369 -14
  60. package/dist/services/ApiAiAssistant.js.map +1 -1
  61. package/dist/services/EntryPoint.js +46 -68
  62. package/dist/services/EntryPoint.js.map +1 -1
  63. package/dist/services/Queue.js +27 -22
  64. package/dist/services/Queue.js.map +1 -1
  65. package/dist/services/UserPreference.js +427 -0
  66. package/dist/services/UserPreference.js.map +1 -0
  67. package/dist/services/WebCallingService.js +10 -2
  68. package/dist/services/WebCallingService.js.map +1 -1
  69. package/dist/services/WebexCrossClientService.js +225 -0
  70. package/dist/services/WebexCrossClientService.js.map +1 -0
  71. package/dist/services/WxAppTelephonyMercurySync.js +111 -0
  72. package/dist/services/WxAppTelephonyMercurySync.js.map +1 -0
  73. package/dist/services/config/Util.js +48 -48
  74. package/dist/services/config/Util.js.map +1 -1
  75. package/dist/services/config/constants.js +56 -78
  76. package/dist/services/config/constants.js.map +1 -1
  77. package/dist/services/config/index.js +100 -226
  78. package/dist/services/config/index.js.map +1 -1
  79. package/dist/services/config/types.js +93 -24
  80. package/dist/services/config/types.js.map +1 -1
  81. package/dist/services/constants.js +11 -1
  82. package/dist/services/constants.js.map +1 -1
  83. package/dist/services/core/Err.js.map +1 -1
  84. package/dist/services/core/Utils.js +131 -32
  85. package/dist/services/core/Utils.js.map +1 -1
  86. package/dist/services/core/WebexRequest.js +6 -2
  87. package/dist/services/core/WebexRequest.js.map +1 -1
  88. package/dist/services/core/aqm-reqs.js +17 -11
  89. package/dist/services/core/aqm-reqs.js.map +1 -1
  90. package/dist/services/core/constants.js +9 -1
  91. package/dist/services/core/constants.js.map +1 -1
  92. package/dist/services/core/types.js.map +1 -1
  93. package/dist/services/core/websocket/WebSocketManager.js +19 -2
  94. package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
  95. package/dist/services/core/websocket/types.js.map +1 -1
  96. package/dist/services/index.js +1 -1
  97. package/dist/services/index.js.map +1 -1
  98. package/dist/services/task/Task.js +955 -0
  99. package/dist/services/task/Task.js.map +1 -0
  100. package/dist/services/task/TaskFactory.js +50 -0
  101. package/dist/services/task/TaskFactory.js.map +1 -0
  102. package/dist/services/task/TaskManager.js +1272 -605
  103. package/dist/services/task/TaskManager.js.map +1 -1
  104. package/dist/services/task/TaskUtils.js +221 -27
  105. package/dist/services/task/TaskUtils.js.map +1 -1
  106. package/dist/services/task/WebexCallingUtils.js +70 -0
  107. package/dist/services/task/WebexCallingUtils.js.map +1 -0
  108. package/dist/services/task/constants.js +19 -2
  109. package/dist/services/task/constants.js.map +1 -1
  110. package/dist/services/task/contact.js +29 -0
  111. package/dist/services/task/contact.js.map +1 -1
  112. package/dist/services/task/digital/Digital.js +78 -0
  113. package/dist/services/task/digital/Digital.js.map +1 -0
  114. package/dist/services/task/state-machine/TaskStateMachine.js +982 -0
  115. package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -0
  116. package/dist/services/task/state-machine/actions.js +572 -0
  117. package/dist/services/task/state-machine/actions.js.map +1 -0
  118. package/dist/services/task/state-machine/constants.js +161 -0
  119. package/dist/services/task/state-machine/constants.js.map +1 -0
  120. package/dist/services/task/state-machine/guards.js +379 -0
  121. package/dist/services/task/state-machine/guards.js.map +1 -0
  122. package/dist/services/task/state-machine/index.js +53 -0
  123. package/dist/services/task/state-machine/index.js.map +1 -0
  124. package/dist/services/task/state-machine/types.js +54 -0
  125. package/dist/services/task/state-machine/types.js.map +1 -0
  126. package/dist/services/task/state-machine/uiControlsComputer.js +703 -0
  127. package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -0
  128. package/dist/services/task/taskDataNormalizer.js +99 -0
  129. package/dist/services/task/taskDataNormalizer.js.map +1 -0
  130. package/dist/services/task/types.js +215 -5
  131. package/dist/services/task/types.js.map +1 -1
  132. package/dist/services/task/voice/Voice.js +1504 -0
  133. package/dist/services/task/voice/Voice.js.map +1 -0
  134. package/dist/services/task/voice/WebRTC.js +152 -0
  135. package/dist/services/task/voice/WebRTC.js.map +1 -0
  136. package/dist/services/task/voice/wxAppOfferObservability.js +145 -0
  137. package/dist/services/task/voice/wxAppOfferObservability.js.map +1 -0
  138. package/dist/services/task/voice/wxAppVoiceMethods.js +395 -0
  139. package/dist/services/task/voice/wxAppVoiceMethods.js.map +1 -0
  140. package/dist/services/wxAppDiagnosticLogging.js +159 -0
  141. package/dist/services/wxAppDiagnosticLogging.js.map +1 -0
  142. package/dist/services/wxAppTelephonyUtils.js +19 -0
  143. package/dist/services/wxAppTelephonyUtils.js.map +1 -0
  144. package/dist/types/cc.d.ts +152 -9
  145. package/dist/types/config.d.ts +13 -0
  146. package/dist/types/constants.d.ts +36 -1
  147. package/dist/types/index.d.ts +54 -20
  148. package/dist/types/metrics/MetricsManager.d.ts +6 -0
  149. package/dist/types/metrics/constants.d.ts +48 -1
  150. package/dist/types/services/AddressBook.d.ts +2 -1
  151. package/dist/types/services/AnswerCallOnWebexService.d.ts +38 -0
  152. package/dist/types/services/ApiAiAssistant.d.ts +67 -5
  153. package/dist/types/services/EntryPoint.d.ts +7 -5
  154. package/dist/types/services/Queue.d.ts +5 -3
  155. package/dist/types/services/UserPreference.d.ts +118 -0
  156. package/dist/types/services/WebexCrossClientService.d.ts +32 -0
  157. package/dist/types/services/WxAppTelephonyMercurySync.d.ts +28 -0
  158. package/dist/types/services/config/Util.d.ts +4 -8
  159. package/dist/types/services/config/constants.d.ts +49 -76
  160. package/dist/types/services/config/index.d.ts +16 -64
  161. package/dist/types/services/config/types.d.ts +240 -114
  162. package/dist/types/services/constants.d.ts +9 -0
  163. package/dist/types/services/core/Err.d.ts +2 -0
  164. package/dist/types/services/core/Utils.d.ts +43 -13
  165. package/dist/types/services/core/WebexRequest.d.ts +1 -0
  166. package/dist/types/services/core/constants.d.ts +7 -0
  167. package/dist/types/services/core/types.d.ts +2 -0
  168. package/dist/types/services/core/websocket/WebSocketManager.d.ts +1 -0
  169. package/dist/types/services/core/websocket/types.d.ts +1 -1
  170. package/dist/types/services/index.d.ts +1 -1
  171. package/dist/types/services/task/Task.d.ts +186 -0
  172. package/dist/types/services/task/TaskFactory.d.ts +14 -0
  173. package/dist/types/services/task/TaskUtils.d.ts +54 -2
  174. package/dist/types/services/task/WebexCallingUtils.d.ts +11 -0
  175. package/dist/types/services/task/constants.d.ts +17 -0
  176. package/dist/types/services/task/contact.d.ts +4 -0
  177. package/dist/types/services/task/digital/Digital.d.ts +23 -0
  178. package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +1442 -0
  179. package/dist/types/services/task/state-machine/actions.d.ts +10 -0
  180. package/dist/types/services/task/state-machine/constants.d.ts +107 -0
  181. package/dist/types/services/task/state-machine/guards.d.ts +103 -0
  182. package/dist/types/services/task/state-machine/index.d.ts +13 -0
  183. package/dist/types/services/task/state-machine/types.d.ts +277 -0
  184. package/dist/types/services/task/state-machine/uiControlsComputer.d.ts +9 -0
  185. package/dist/types/services/task/taskDataNormalizer.d.ts +10 -0
  186. package/dist/types/services/task/types.d.ts +738 -66
  187. package/dist/types/services/task/voice/Voice.d.ts +241 -0
  188. package/dist/types/services/task/voice/WebRTC.d.ts +54 -0
  189. package/dist/types/services/task/voice/wxAppOfferObservability.d.ts +39 -0
  190. package/dist/types/services/task/voice/wxAppVoiceMethods.d.ts +68 -0
  191. package/dist/types/services/wxAppDiagnosticLogging.d.ts +63 -0
  192. package/dist/types/services/wxAppTelephonyUtils.d.ts +5 -0
  193. package/dist/types/types.d.ts +213 -11
  194. package/dist/types/utils/PageCache.d.ts +20 -3
  195. package/dist/types/webex.d.ts +1 -0
  196. package/dist/types.js +168 -6
  197. package/dist/types.js.map +1 -1
  198. package/dist/utils/PageCache.js +19 -5
  199. package/dist/utils/PageCache.js.map +1 -1
  200. package/dist/webex.js +22 -2
  201. package/dist/webex.js.map +1 -1
  202. package/package.json +16 -12
  203. package/src/cc.ts +1137 -67
  204. package/src/config.ts +13 -0
  205. package/src/constants.ts +39 -1
  206. package/src/index.ts +62 -15
  207. package/src/metrics/MetricsManager.ts +16 -0
  208. package/src/metrics/ai-docs/AGENTS.md +350 -0
  209. package/src/metrics/ai-docs/ARCHITECTURE.md +338 -0
  210. package/src/metrics/ai-docs/metrics-spec.md +971 -0
  211. package/src/metrics/behavioral-events.ts +190 -0
  212. package/src/metrics/constants.ts +59 -4
  213. package/src/services/AddressBook.ts +17 -6
  214. package/src/services/AnswerCallOnWebexService.ts +239 -0
  215. package/src/services/ApiAiAssistant.ts +494 -15
  216. package/src/services/EntryPoint.ts +59 -60
  217. package/src/services/Queue.ts +29 -12
  218. package/src/services/UserPreference.ts +509 -0
  219. package/src/services/WebCallingService.ts +16 -2
  220. package/src/services/WebexCrossClientService.ts +298 -0
  221. package/src/services/WxAppTelephonyMercurySync.ts +142 -0
  222. package/src/services/agent/ai-docs/AGENTS.md +240 -0
  223. package/src/services/agent/ai-docs/ARCHITECTURE.md +304 -0
  224. package/src/services/agent/ai-docs/agent-spec.md +505 -0
  225. package/src/services/ai-docs/AGENTS.md +386 -0
  226. package/src/services/ai-docs/services-spec.md +512 -0
  227. package/src/services/config/Util.ts +54 -84
  228. package/src/services/config/ai-docs/AGENTS.md +250 -0
  229. package/src/services/config/ai-docs/ARCHITECTURE.md +413 -0
  230. package/src/services/config/ai-docs/config-spec.md +669 -0
  231. package/src/services/config/constants.ts +63 -85
  232. package/src/services/config/index.ts +116 -277
  233. package/src/services/config/types.ts +229 -125
  234. package/src/services/constants.ts +10 -0
  235. package/src/services/core/Err.ts +1 -0
  236. package/src/services/core/Utils.ts +151 -37
  237. package/src/services/core/WebexRequest.ts +3 -1
  238. package/src/services/core/ai-docs/AGENTS.md +381 -0
  239. package/src/services/core/ai-docs/ARCHITECTURE.md +698 -0
  240. package/src/services/core/ai-docs/core-spec.md +797 -0
  241. package/src/services/core/aqm-reqs.ts +18 -12
  242. package/src/services/core/constants.ts +8 -0
  243. package/src/services/core/types.ts +33 -1
  244. package/src/services/core/websocket/WebSocketManager.ts +28 -2
  245. package/src/services/core/websocket/types.ts +1 -1
  246. package/src/services/index.ts +1 -1
  247. package/src/services/task/Task.ts +1211 -0
  248. package/src/services/task/TaskFactory.ts +82 -0
  249. package/src/services/task/TaskManager.ts +1585 -724
  250. package/src/services/task/TaskUtils.ts +316 -25
  251. package/src/services/task/WebexCallingUtils.ts +136 -0
  252. package/src/services/task/ai-docs/AGENTS.md +457 -0
  253. package/src/services/task/ai-docs/ARCHITECTURE.md +595 -0
  254. package/src/services/task/ai-docs/task-spec.md +1501 -0
  255. package/src/services/task/constants.ts +18 -0
  256. package/src/services/task/contact.ts +30 -0
  257. package/src/services/task/digital/Digital.ts +102 -0
  258. package/src/services/task/state-machine/TaskStateMachine.ts +1320 -0
  259. package/src/services/task/state-machine/actions.ts +741 -0
  260. package/src/services/task/state-machine/ai-docs/AGENTS.md +460 -0
  261. package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +1156 -0
  262. package/src/services/task/state-machine/ai-docs/task-state-machine-spec.md +2247 -0
  263. package/src/services/task/state-machine/constants.ts +172 -0
  264. package/src/services/task/state-machine/guards.ts +442 -0
  265. package/src/services/task/state-machine/index.ts +28 -0
  266. package/src/services/task/state-machine/types.ts +258 -0
  267. package/src/services/task/state-machine/uiControlsComputer.ts +1135 -0
  268. package/src/services/task/taskDataNormalizer.ts +137 -0
  269. package/src/services/task/types.ts +918 -70
  270. package/src/services/task/voice/Voice.ts +1878 -0
  271. package/src/services/task/voice/WebRTC.ts +194 -0
  272. package/src/services/task/voice/wxAppOfferObservability.ts +204 -0
  273. package/src/services/task/voice/wxAppVoiceMethods.ts +575 -0
  274. package/src/services/wxAppDiagnosticLogging.ts +286 -0
  275. package/src/services/wxAppTelephonyUtils.ts +14 -0
  276. package/src/types.ts +272 -13
  277. package/src/utils/AGENTS.md +289 -0
  278. package/src/utils/PageCache.ts +38 -5
  279. package/src/utils/ai-docs/utils-spec.md +391 -0
  280. package/src/webex.js +10 -0
  281. package/test/unit/fixtures/aiSummaryTestUtils.ts +40 -0
  282. package/test/unit/spec/cc.ts +3553 -107
  283. package/test/unit/spec/index.ts +885 -0
  284. package/test/unit/spec/logger-proxy.ts +70 -0
  285. package/test/unit/spec/metrics/MetricsManager.ts +25 -0
  286. package/test/unit/spec/metrics/behavioral-events.ts +60 -0
  287. package/test/unit/spec/services/AddressBook.ts +37 -6
  288. package/test/unit/spec/services/AnswerCallOnWebexService.ts +264 -0
  289. package/test/unit/spec/services/ApiAiAssistant.ts +442 -23
  290. package/test/unit/spec/services/EntryPoint.ts +87 -40
  291. package/test/unit/spec/services/Queue.ts +123 -12
  292. package/test/unit/spec/services/UserPreference.ts +401 -0
  293. package/test/unit/spec/services/WebCallingService.ts +45 -1
  294. package/test/unit/spec/services/WebexCrossClientService.ts +509 -0
  295. package/test/unit/spec/services/WxAppTelephonyMercurySync.ts +136 -0
  296. package/test/unit/spec/services/config/Util.ts +501 -0
  297. package/test/unit/spec/services/config/index.ts +317 -547
  298. package/test/unit/spec/services/core/Utils.ts +447 -8
  299. package/test/unit/spec/services/core/WebexRequest.ts +8 -7
  300. package/test/unit/spec/services/core/aqm-reqs.ts +142 -1
  301. package/test/unit/spec/services/core/websocket/WebSocketManager.ts +129 -53
  302. package/test/unit/spec/services/task/AutoWrapup.ts +63 -0
  303. package/test/unit/spec/services/task/Task.ts +2723 -0
  304. package/test/unit/spec/services/task/TaskFactory.ts +116 -0
  305. package/test/unit/spec/services/task/TaskManager.ts +4734 -1769
  306. package/test/unit/spec/services/task/TaskUtils.ts +307 -0
  307. package/test/unit/spec/services/task/WebexCallingUtils.ts +153 -0
  308. package/test/unit/spec/services/task/contact.ts +33 -0
  309. package/test/unit/spec/services/task/digital/Digital.ts +105 -0
  310. package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +4060 -0
  311. package/test/unit/spec/services/task/state-machine/guards.ts +839 -0
  312. package/test/unit/spec/services/task/state-machine/types.ts +18 -0
  313. package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +3101 -0
  314. package/test/unit/spec/services/task/taskTestUtils.ts +87 -0
  315. package/test/unit/spec/services/task/voice/Voice.ts +2355 -0
  316. package/test/unit/spec/services/task/voice/WebRTC.ts +235 -0
  317. package/test/unit/spec/services/task/voice/wxAppOfferObservability.ts +361 -0
  318. package/test/unit/spec/services/task/voice/wxAppVoiceMethods.ts +719 -0
  319. package/test/unit/spec/services/wxAppDiagnosticLogging.ts +179 -0
  320. package/test/unit/spec/wellnessSampleUtils.ts +288 -0
  321. package/typedoc.md +1 -1
  322. package/umd/contact-center.min.js +2 -2
  323. package/umd/contact-center.min.js.map +1 -1
  324. package/dist/services/task/index.js +0 -1530
  325. package/dist/services/task/index.js.map +0 -1
  326. package/dist/types/services/task/index.d.ts +0 -650
  327. package/src/services/task/index.ts +0 -1806
  328. package/test/unit/spec/services/task/index.ts +0 -2205
@@ -0,0 +1,955 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _events = require("events");
8
+ var _xstate = require("xstate");
9
+ var _types = require("./types");
10
+ var _constants = require("./constants");
11
+ var _constants2 = require("../../constants");
12
+ var _Utils = require("../core/Utils");
13
+ var _MetricsManager = _interopRequireDefault(require("../../metrics/MetricsManager"));
14
+ var _constants3 = require("../../metrics/constants");
15
+ var _loggerProxy = _interopRequireDefault(require("../../logger-proxy"));
16
+ var _stateMachine = require("./state-machine");
17
+ var _uiControlsComputer = require("./state-machine/uiControlsComputer");
18
+ var _AutoWrapup = _interopRequireDefault(require("./AutoWrapup"));
19
+ var _types2 = require("../../types");
20
+ var _TaskUtils = require("./TaskUtils");
21
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
22
+ class Task extends _events.EventEmitter {
23
+ aiSummaryCapabilities = {
24
+ midCallEnabled: false,
25
+ postCallEnabled: false
26
+ };
27
+ constructor(contact, data, uiControlConfig, wrapupData, agentId, agentName, apiAIAssistant) {
28
+ super();
29
+ this.contact = contact;
30
+ this.data = data;
31
+ const channelType = uiControlConfig.channelType ?? Task.resolveChannelType(data);
32
+ // Include agentId in the config for ownership checks (transfer conference)
33
+ this.uiControlConfig = {
34
+ ...uiControlConfig,
35
+ channelType,
36
+ agentId
37
+ };
38
+ this.wrapupData = wrapupData;
39
+ this.agentId = agentId;
40
+ this.agentName = agentName;
41
+ this.apiAIAssistant = apiAIAssistant;
42
+ this.metricsManager = _MetricsManager.default.getInstance();
43
+ this.webCallMap = {};
44
+ this.currentUiControls = (0, _uiControlsComputer.getDefaultUIControls)();
45
+ this.initializeStateMachine();
46
+ this.setupAutoWrapupTimer();
47
+ }
48
+ static resolveChannelType(data) {
49
+ const mediaType = data?.interaction?.mediaType ?? _types.MEDIA_CHANNEL.TELEPHONY;
50
+ return mediaType === _types.MEDIA_CHANNEL.TELEPHONY ? _types.TASK_CHANNEL_TYPE.VOICE : _types.TASK_CHANNEL_TYPE.DIGITAL;
51
+ }
52
+
53
+ // Abstract methods that all child classes must implement
54
+
55
+ // Voice-specific methods with default implementations that throw errors
56
+ // Voice class will override these with actual implementations
57
+ async decline() {
58
+ this.unsupportedMethodError('decline');
59
+ }
60
+ async pauseRecording() {
61
+ this.unsupportedMethodError('pauseRecording');
62
+ }
63
+ async resumeRecording(resumeRecordingPayload) {
64
+ if (resumeRecordingPayload) {
65
+ // parameter intentionally unused
66
+ }
67
+ this.unsupportedMethodError('resumeRecording');
68
+ }
69
+ async consult(consultPayload) {
70
+ if (consultPayload) {
71
+ // parameter intentionally unused
72
+ }
73
+ this.unsupportedMethodError('consult');
74
+ }
75
+ async endConsult(consultEndPayload) {
76
+ if (consultEndPayload) {
77
+ // parameter intentionally unused
78
+ }
79
+ this.unsupportedMethodError('endConsult');
80
+ }
81
+ async consultTransfer(consultTransferPayload) {
82
+ if (consultTransferPayload) {
83
+ // parameter intentionally unused
84
+ }
85
+ this.unsupportedMethodError('consultTransfer');
86
+ }
87
+ async consultConference() {
88
+ this.unsupportedMethodError('consultConference');
89
+ }
90
+ async dropConferenceParticipant(
91
+ // The base task preserves the public signature; Voice provides the implementation.
92
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
93
+ payload) {
94
+ this.unsupportedMethodError(_constants.METHODS.DROP_CONFERENCE_PARTICIPANT);
95
+ }
96
+ async exitConference() {
97
+ this.unsupportedMethodError('exitConference');
98
+ }
99
+ async transferConference() {
100
+ this.unsupportedMethodError('transferConference');
101
+ }
102
+ async switchCall() {
103
+ this.unsupportedMethodError('switchCall');
104
+ }
105
+ async toggleMute(options) {
106
+ if (options) {
107
+ // parameter intentionally unused
108
+ }
109
+ this.unsupportedMethodError('toggleMute');
110
+ }
111
+ async transmitDtmf(options) {
112
+ if (options) {
113
+ // parameter intentionally unused
114
+ }
115
+ this.unsupportedMethodError('transmitDtmf');
116
+ }
117
+ unregisterWebCallListeners() {
118
+ // Default implementation - child classes can override
119
+ _loggerProxy.default.log('unregisterWebCallListeners called', {
120
+ module: _constants2.CC_FILE,
121
+ method: 'unregisterWebCallListeners',
122
+ interactionId: this.data?.interactionId
123
+ });
124
+ }
125
+
126
+ /**
127
+ * Cancel any in-progress auto wrap-up timer.
128
+ * Base implementation just clears the timer reference so subclasses inherit the behavior.
129
+ */
130
+ cancelAutoWrapupTimer() {
131
+ if (this.autoWrapup) {
132
+ this.autoWrapup.clear();
133
+ this.autoWrapup = undefined;
134
+ _loggerProxy.default.log('Auto wrap-up timer cancelled', {
135
+ module: _constants2.CC_FILE,
136
+ method: 'cancelAutoWrapupTimer',
137
+ interactionId: this.data?.interactionId
138
+ });
139
+ }
140
+ }
141
+
142
+ // Voice tasks use holdResume(), but provide separate methods for interface compliance
143
+ async hold() {
144
+ this.unsupportedMethodError('hold');
145
+ }
146
+ async resume() {
147
+ this.unsupportedMethodError('resume');
148
+ }
149
+ async holdResume() {
150
+ this.unsupportedMethodError('holdResume');
151
+ }
152
+ setFeatureEnablement(enablement) {
153
+ if (enablement.interactionId !== this.data.interactionId) {
154
+ return;
155
+ }
156
+ this.aiSummaryCapabilities = {
157
+ midCallEnabled: enablement.midCallEnabled === true,
158
+ postCallEnabled: enablement.postCallEnabled === true
159
+ };
160
+ }
161
+ clearFeatureEnablement() {
162
+ this.aiSummaryCapabilities = {
163
+ midCallEnabled: false,
164
+ postCallEnabled: false
165
+ };
166
+ }
167
+ async requestPostCallSummary() {
168
+ const metricFields = {
169
+ operation: _constants.METHODS.REQUEST_POST_CALL_SUMMARY
170
+ };
171
+ try {
172
+ this.metricsManager.timeEvent([_constants3.METRIC_EVENT_NAMES.AI_SUMMARY_GET_POST_CALL_SUCCESS, _constants3.METRIC_EVENT_NAMES.AI_SUMMARY_GET_POST_CALL_FAILED]);
173
+ const interactionId = this.data.interactionId;
174
+ const conversationId = this.data.interaction?.mainInteractionId || interactionId;
175
+ Object.assign(metricFields, {
176
+ conversationId,
177
+ interactionId
178
+ });
179
+ if (!this.apiAIAssistant || this.apiAIAssistant.aiFeature?.generatedSummaries?.wrapUpSummariesEnabled !== true || !this.aiSummaryCapabilities.postCallEnabled) {
180
+ throw (0, _TaskUtils.createSummaryError)(_constants2.AI_SUMMARY_ERROR_CODES.POST_CALL_SUMMARY_DISABLED);
181
+ }
182
+ const result = await this.apiAIAssistant.requestAndWaitForRtd({
183
+ correlationId: conversationId,
184
+ rtdEventType: 'POST_CALL_SUMMARY',
185
+ timeoutMs: _constants.AI_SUMMARY_DURATION_MS,
186
+ createTimeoutError: () => (0, _TaskUtils.createSummaryError)(_constants2.AI_SUMMARY_ERROR_CODES.POST_CALL_SUMMARY_TIMEOUT),
187
+ agentId: this.agentId,
188
+ interactionId,
189
+ eventType: _types2.AIAssistantEventType.CTI_EVENT,
190
+ eventName: _types2.AIAssistantEventName.GET_POST_CALL_SUMMARY,
191
+ eventMetaData: {
192
+ conversationId,
193
+ clientType: _constants2.AI_ASSISTANT_CLIENT_TYPE
194
+ },
195
+ timeout: _constants.AI_SUMMARY_DURATION_MS
196
+ });
197
+ this.metricsManager.trackEvent(_constants3.METRIC_EVENT_NAMES.AI_SUMMARY_GET_POST_CALL_SUCCESS, {
198
+ taskId: this.data?.interactionId,
199
+ ...metricFields
200
+ }, ['operational']);
201
+ return result;
202
+ } catch (error) {
203
+ this.metricsManager.trackEvent(_constants3.METRIC_EVENT_NAMES.AI_SUMMARY_GET_POST_CALL_FAILED, {
204
+ taskId: this.data?.interactionId,
205
+ ...metricFields,
206
+ failureCode: Task.getAISummaryFailureCode(error)
207
+ }, ['operational']);
208
+ throw error;
209
+ }
210
+ }
211
+ async sendPostCallSummaryResponse(response) {
212
+ const metricFields = {
213
+ operation: _constants.METHODS.SEND_POST_CALL_SUMMARY_RESPONSE
214
+ };
215
+ try {
216
+ this.metricsManager.timeEvent([_constants3.METRIC_EVENT_NAMES.AI_SUMMARY_POST_CALL_RESPONSE_SUCCESS, _constants3.METRIC_EVENT_NAMES.AI_SUMMARY_POST_CALL_RESPONSE_FAILED]);
217
+ const interactionId = this.data.interactionId;
218
+ const conversationId = this.data.interaction?.mainInteractionId || interactionId;
219
+ Object.assign(metricFields, {
220
+ conversationId,
221
+ interactionId
222
+ });
223
+ const publishTimestamp = Date.now();
224
+ const eventName = _types2.AIAssistantEventName.POST_CALL_SUMMARY_RESPONSE;
225
+ const eventPayload = {
226
+ conversationId,
227
+ clientType: _constants2.AI_ASSISTANT_CLIENT_TYPE,
228
+ action: eventName,
229
+ summary: response.summary,
230
+ numberOfTimesViewed: response.numberOfTimesViewed,
231
+ numberOfTimesEdited: response.numberOfTimesEdited,
232
+ numberOfTimesCopied: response.numberOfTimesCopied,
233
+ feedback: response.feedback,
234
+ state: response.state,
235
+ wrapUpCode: response.wrapUpCode
236
+ };
237
+ await this.apiAIAssistant.sendEvent(this.agentId, interactionId, _types2.AIAssistantEventType.CTI_EVENT, eventName, eventPayload, undefined, undefined, publishTimestamp, _constants.AI_SUMMARY_DURATION_MS);
238
+ this.metricsManager.trackEvent(_constants3.METRIC_EVENT_NAMES.AI_SUMMARY_POST_CALL_RESPONSE_SUCCESS, {
239
+ taskId: this.data?.interactionId,
240
+ ...metricFields
241
+ }, ['operational']);
242
+ } catch (error) {
243
+ this.metricsManager.trackEvent(_constants3.METRIC_EVENT_NAMES.AI_SUMMARY_POST_CALL_RESPONSE_FAILED, {
244
+ taskId: this.data?.interactionId,
245
+ ...metricFields,
246
+ failureCode: Task.getAISummaryFailureCode(error)
247
+ }, ['operational']);
248
+ throw error;
249
+ }
250
+ }
251
+ async requestMidCallSummary(action) {
252
+ const metricFields = {
253
+ operation: _constants.METHODS.REQUEST_MID_CALL_SUMMARY,
254
+ actionType: action
255
+ };
256
+ try {
257
+ this.metricsManager.timeEvent([_constants3.METRIC_EVENT_NAMES.AI_SUMMARY_GET_MID_CALL_SUCCESS, _constants3.METRIC_EVENT_NAMES.AI_SUMMARY_GET_MID_CALL_FAILED]);
258
+ const interactionId = this.data.interactionId;
259
+ const conversationId = this.data.interaction?.mainInteractionId || interactionId;
260
+ Object.assign(metricFields, {
261
+ conversationId,
262
+ interactionId
263
+ });
264
+ if (!this.apiAIAssistant || this.apiAIAssistant.aiFeature?.generatedSummaries?.consultTransferSummariesEnabled !== true || !this.aiSummaryCapabilities.midCallEnabled) {
265
+ throw (0, _TaskUtils.createSummaryError)(_constants2.AI_SUMMARY_ERROR_CODES.MID_CALL_SUMMARY_DISABLED);
266
+ }
267
+ const eventName = action === 'CONSULT' ? _types2.AIAssistantEventName.GET_MID_CALL_CONSULT_SUMMARY : _types2.AIAssistantEventName.GET_MID_CALL_TRANSFER_SUMMARY;
268
+ const result = await this.apiAIAssistant.requestAndWaitForRtd({
269
+ correlationId: conversationId,
270
+ rtdEventType: 'MID_CALL_SUMMARY',
271
+ timeoutMs: _constants.AI_SUMMARY_DURATION_MS,
272
+ createTimeoutError: () => (0, _TaskUtils.createSummaryError)(_constants2.AI_SUMMARY_ERROR_CODES.MID_CALL_SUMMARY_TIMEOUT),
273
+ agentId: this.agentId,
274
+ interactionId,
275
+ eventType: _types2.AIAssistantEventType.CTI_EVENT,
276
+ eventName,
277
+ eventMetaData: {
278
+ conversationId,
279
+ clientType: _constants2.AI_ASSISTANT_CLIENT_TYPE
280
+ },
281
+ timeout: _constants.AI_SUMMARY_DURATION_MS
282
+ });
283
+ this.metricsManager.trackEvent(_constants3.METRIC_EVENT_NAMES.AI_SUMMARY_GET_MID_CALL_SUCCESS, {
284
+ taskId: this.data?.interactionId,
285
+ ...metricFields
286
+ }, ['operational']);
287
+ return result;
288
+ } catch (error) {
289
+ this.metricsManager.trackEvent(_constants3.METRIC_EVENT_NAMES.AI_SUMMARY_GET_MID_CALL_FAILED, {
290
+ taskId: this.data?.interactionId,
291
+ ...metricFields,
292
+ failureCode: Task.getAISummaryFailureCode(error)
293
+ }, ['operational']);
294
+ throw error;
295
+ }
296
+ }
297
+ async sendMidCallSummaryResponse(response, action) {
298
+ const metricFields = {
299
+ operation: _constants.METHODS.SEND_MID_CALL_SUMMARY_RESPONSE,
300
+ actionType: action
301
+ };
302
+ try {
303
+ this.metricsManager.timeEvent([_constants3.METRIC_EVENT_NAMES.AI_SUMMARY_MID_CALL_RESPONSE_SUCCESS, _constants3.METRIC_EVENT_NAMES.AI_SUMMARY_MID_CALL_RESPONSE_FAILED]);
304
+ const interactionId = this.data.interactionId;
305
+ const conversationId = this.data.interaction?.mainInteractionId || interactionId;
306
+ Object.assign(metricFields, {
307
+ conversationId,
308
+ interactionId
309
+ });
310
+ const publishTimestamp = Date.now();
311
+ const eventName = action === 'CONSULT' ? _types2.AIAssistantEventName.MID_CALL_CONSULT_SUMMARY_RESPONSE : _types2.AIAssistantEventName.MID_CALL_TRANSFER_SUMMARY_RESPONSE;
312
+ const eventPayload = {
313
+ conversationId,
314
+ clientType: _constants2.AI_ASSISTANT_CLIENT_TYPE,
315
+ action: eventName,
316
+ summary: response.summary,
317
+ numberOfTimesViewed: response.numberOfTimesViewed,
318
+ numberOfTimesEdited: response.numberOfTimesEdited,
319
+ numberOfTimesCopied: response.numberOfTimesCopied,
320
+ feedback: response.feedback,
321
+ state: response.state,
322
+ agentName: this.agentName ?? ''
323
+ };
324
+ await this.apiAIAssistant.sendEvent(this.agentId, interactionId, _types2.AIAssistantEventType.CTI_EVENT, eventName, eventPayload, undefined, undefined, publishTimestamp, _constants.AI_SUMMARY_DURATION_MS);
325
+ this.metricsManager.trackEvent(_constants3.METRIC_EVENT_NAMES.AI_SUMMARY_MID_CALL_RESPONSE_SUCCESS, {
326
+ taskId: this.data?.interactionId,
327
+ ...metricFields
328
+ }, ['operational']);
329
+ } catch (error) {
330
+ this.metricsManager.trackEvent(_constants3.METRIC_EVENT_NAMES.AI_SUMMARY_MID_CALL_RESPONSE_FAILED, {
331
+ taskId: this.data?.interactionId,
332
+ ...metricFields,
333
+ failureCode: Task.getAISummaryFailureCode(error)
334
+ }, ['operational']);
335
+ throw error;
336
+ }
337
+ }
338
+ static getAISummaryFailureCode(error) {
339
+ const errorCode = error?.data?.errorCode;
340
+ if (typeof errorCode === 'string') {
341
+ return errorCode;
342
+ }
343
+ return _constants2.AI_SUMMARY_INVALID_RESPONSE_PAYLOAD;
344
+ }
345
+
346
+ /**
347
+ * Latest UI controls derived from state machine state and context.
348
+ */
349
+ get uiControls() {
350
+ return this.currentUiControls;
351
+ }
352
+ updateUiControls(forceEmit = false) {
353
+ const nextControls = this.computeUIControls();
354
+ const shouldEmit = forceEmit || (0, _uiControlsComputer.haveUIControlsChanged)(this.currentUiControls, nextControls);
355
+ this.currentUiControls = nextControls;
356
+ if (shouldEmit) {
357
+ this.emit(_types.TASK_EVENTS.TASK_UI_CONTROLS_UPDATED, this.currentUiControls);
358
+ }
359
+ }
360
+
361
+ /**
362
+ * Initialize the state machine
363
+ */
364
+ initializeStateMachine() {
365
+ const machine = (0, _stateMachine.createTaskStateMachine)(this.uiControlConfig, {
366
+ actions: this.getStateMachineActionOverrides()
367
+ });
368
+ this.stateMachineService = (0, _xstate.createActor)(machine);
369
+ this.stateMachineService.subscribe(snapshot => {
370
+ const previousState = this.lastState;
371
+ const currentState = snapshot.value;
372
+ _loggerProxy.default.log(`State machine transition: ${previousState || 'N/A'} -> ${currentState}`, {
373
+ module: _constants2.CC_FILE,
374
+ method: 'onTransition',
375
+ // @ts-ignore - snapshot may include event detail depending on XState version
376
+ eventType: snapshot?.event?.type
377
+ });
378
+ this.lastState = currentState;
379
+ this.state = snapshot;
380
+ this.updateUiControls(previousState !== currentState);
381
+ });
382
+ this.stateMachineService.start();
383
+ this.updateUiControls(true);
384
+ }
385
+
386
+ /**
387
+ * Send an event to the state machine
388
+ */
389
+ sendStateMachineEvent(event) {
390
+ if (this.stateMachineService) {
391
+ _loggerProxy.default.log(`Sending state machine event: ${event?.type}`, {
392
+ module: _constants2.CC_FILE,
393
+ method: 'sendStateMachineEvent',
394
+ interactionId: this.data?.interactionId
395
+ });
396
+ this.stateMachineService.send(event);
397
+ }
398
+ }
399
+
400
+ /**
401
+ * Get the current state machine state
402
+ */
403
+ getCurrentState() {
404
+ return this.stateMachineService?.getSnapshot()?.value;
405
+ }
406
+
407
+ /**
408
+ * Compute UI controls based on current state machine state.
409
+ *
410
+ * @returns UI control states for all task actions
411
+ */
412
+ /**
413
+ * Update wxApp thick-client answer flag at runtime (Voice overrides).
414
+ */
415
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
416
+ setEnableWxBetterTogether(_enabled) {
417
+ // no-op for non-voice tasks
418
+ }
419
+
420
+ /**
421
+ * Apply wxApp mute state from external sync (Voice overrides).
422
+ */
423
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
424
+ applyWxAppMuteStateFromSync(_incomingCallId, _muted) {
425
+ // no-op for non-voice tasks
426
+ }
427
+
428
+ /**
429
+ * Hook for post-assign wxApp sync (Voice overrides).
430
+ */
431
+ onTaskAssigned() {
432
+ // no-op by default
433
+ }
434
+
435
+ /**
436
+ * Hook for post-hydrate wxApp sync (Voice overrides).
437
+ */
438
+ onTaskHydrated() {
439
+ // no-op by default
440
+ }
441
+ computeUIControls() {
442
+ const snapshot = this.stateMachineService?.getSnapshot?.();
443
+ if (!snapshot) {
444
+ return (0, _uiControlsComputer.getDefaultUIControls)();
445
+ }
446
+ const currentState = snapshot.value;
447
+ const context = snapshot.context;
448
+ const mergedContext = {
449
+ ...context,
450
+ uiControlConfig: {
451
+ ...context.uiControlConfig,
452
+ ...this.uiControlConfig
453
+ }
454
+ };
455
+ const uiControls = (0, _uiControlsComputer.computeUIControls)(currentState, mergedContext, this.data);
456
+ return uiControls;
457
+ }
458
+
459
+ /**
460
+ * Stop the state machine service
461
+ */
462
+ stopStateMachine() {
463
+ if (this.stateMachineService) {
464
+ this.stateMachineService.stop();
465
+ this.stateMachineService = undefined;
466
+ }
467
+ }
468
+ static extractTaskDataFromEvent(event) {
469
+ if (!event || typeof event !== 'object') {
470
+ return undefined;
471
+ }
472
+ if ('taskData' in event) {
473
+ return event.taskData;
474
+ }
475
+ return undefined;
476
+ }
477
+ async autoAnswerIfNeeded() {
478
+ if (!this.data) {
479
+ return;
480
+ }
481
+ const autoAnswerSupported = this.uiControlConfig.channelType === _types.TASK_CHANNEL_TYPE.DIGITAL || this.uiControlConfig.voiceVariant === _types.VOICE_VARIANT.WEBRTC;
482
+ if (!autoAnswerSupported) {
483
+ return;
484
+ }
485
+ const shouldAutoAnswer = this.data.isAutoAnswering === true;
486
+ if (!shouldAutoAnswer) {
487
+ return;
488
+ }
489
+ _loggerProxy.default.info(`Auto-answering task`, {
490
+ module: _constants2.TASK_FILE,
491
+ method: 'autoAnswerIfNeeded',
492
+ interactionId: this.data.interactionId
493
+ });
494
+ try {
495
+ await this.accept();
496
+ _loggerProxy.default.info(`Task auto-answered successfully`, {
497
+ module: _constants2.TASK_FILE,
498
+ method: 'autoAnswerIfNeeded',
499
+ interactionId: this.data.interactionId
500
+ });
501
+ this.metricsManager.trackEvent(_constants3.METRIC_EVENT_NAMES.TASK_AUTO_ANSWER_SUCCESS, {
502
+ taskId: this.data.interactionId,
503
+ mediaType: this.data.interaction.mediaType,
504
+ isAutoAnswered: true
505
+ }, ['behavioral', 'operational']);
506
+ this.emit(_types.TASK_EVENTS.TASK_AUTO_ANSWERED, this);
507
+ } catch (error) {
508
+ this.updateTaskData({
509
+ ...this.data,
510
+ isAutoAnswering: false
511
+ });
512
+ _loggerProxy.default.error(`Failed to auto-answer task`, {
513
+ module: _constants2.TASK_FILE,
514
+ method: 'autoAnswerIfNeeded',
515
+ interactionId: this.data.interactionId,
516
+ error
517
+ });
518
+ this.metricsManager.trackEvent(_constants3.METRIC_EVENT_NAMES.TASK_AUTO_ANSWER_FAILED, {
519
+ taskId: this.data.interactionId,
520
+ mediaType: this.data.interaction.mediaType,
521
+ error: error?.message || 'Unknown error',
522
+ isAutoAnswered: false
523
+ }, ['behavioral', 'operational']);
524
+ }
525
+ }
526
+ updateTaskFromEvent(event) {
527
+ const taskData = Task.extractTaskDataFromEvent(event);
528
+ if (taskData) {
529
+ this.updateTaskData(taskData);
530
+ }
531
+ }
532
+ getStateMachineActionOverrides() {
533
+ return {
534
+ ...this.getCommonActionOverrides(),
535
+ ...this.getChannelSpecificActionOverrides()
536
+ };
537
+ }
538
+ getChannelSpecificActionOverrides() {
539
+ return {};
540
+ }
541
+ createEmitSelfAction(taskEvent, {
542
+ updateTaskData = false
543
+ } = {}) {
544
+ return ({
545
+ event
546
+ }) => {
547
+ if (updateTaskData) {
548
+ this.updateTaskFromEvent(event);
549
+ }
550
+ _loggerProxy.default.info(`Emitting task event ${taskEvent}`, {
551
+ module: _constants2.TASK_FILE,
552
+ method: 'emitTaskEvent',
553
+ interactionId: this.data?.interactionId
554
+ });
555
+ this.emit(taskEvent, this);
556
+ };
557
+ }
558
+ getCommonActionOverrides() {
559
+ return {
560
+ syncTaskDataFromEvent: ({
561
+ event
562
+ }) => {
563
+ this.updateTaskFromEvent(event);
564
+ },
565
+ emitTaskIncoming: this.createEmitSelfAction(_types.TASK_EVENTS.TASK_INCOMING, {
566
+ updateTaskData: true
567
+ }),
568
+ emitTaskCampaignPreviewReservation: this.createEmitSelfAction(_types.TASK_EVENTS.TASK_CAMPAIGN_PREVIEW_RESERVATION, {
569
+ updateTaskData: true
570
+ }),
571
+ emitTaskCampaignPreviewAcceptFailed: this.createEmitSelfAction(_types.TASK_EVENTS.TASK_CAMPAIGN_PREVIEW_ACCEPT_FAILED),
572
+ emitTaskCampaignPreviewSkipFailed: this.createEmitSelfAction(_types.TASK_EVENTS.TASK_CAMPAIGN_PREVIEW_SKIP_FAILED),
573
+ emitTaskCampaignPreviewRemoveFailed: this.createEmitSelfAction(_types.TASK_EVENTS.TASK_CAMPAIGN_PREVIEW_REMOVE_FAILED),
574
+ emitTaskHydrate: ({
575
+ event
576
+ }) => {
577
+ this.updateTaskFromEvent(event);
578
+ _loggerProxy.default.info(`Emitting task event ${_types.TASK_EVENTS.TASK_HYDRATE}`, {
579
+ module: _constants2.TASK_FILE,
580
+ method: 'emitTaskEvent',
581
+ interactionId: this.data?.interactionId
582
+ });
583
+ this.emit(_types.TASK_EVENTS.TASK_HYDRATE, this);
584
+ this.onTaskHydrated();
585
+ },
586
+ emitTaskOfferContact: this.createEmitSelfAction(_types.TASK_EVENTS.TASK_OFFER_CONTACT, {
587
+ updateTaskData: true
588
+ }),
589
+ emitTaskAssigned: ({
590
+ event
591
+ }) => {
592
+ this.updateTaskFromEvent(event);
593
+ this.emit(_types.TASK_EVENTS.TASK_ASSIGNED, this);
594
+ this.emit(_types.TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE, this);
595
+ this.onTaskAssigned();
596
+ },
597
+ emitTaskEnd: this.createEmitSelfAction(_types.TASK_EVENTS.TASK_END, {
598
+ updateTaskData: true
599
+ }),
600
+ emitTaskOfferConsult: this.createEmitSelfAction(_types.TASK_EVENTS.TASK_OFFER_CONSULT, {
601
+ updateTaskData: true
602
+ }),
603
+ emitTaskConsultCreated: this.createEmitSelfAction(_types.TASK_EVENTS.TASK_CONSULT_CREATED, {
604
+ updateTaskData: true
605
+ }),
606
+ emitTaskConsulting: ({
607
+ event
608
+ }) => {
609
+ this.updateTaskFromEvent(event);
610
+ if (this.data.isConsulted) {
611
+ this.emit(_types.TASK_EVENTS.TASK_CONSULT_ACCEPTED, this);
612
+ } else {
613
+ this.emit(_types.TASK_EVENTS.TASK_CONSULTING, this);
614
+ }
615
+ this.emit(_types.TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE, this);
616
+ },
617
+ emitTaskConsultAccepted: this.createEmitSelfAction(_types.TASK_EVENTS.TASK_CONSULT_ACCEPTED),
618
+ emitTaskConsultEnd: this.createEmitSelfAction(_types.TASK_EVENTS.TASK_CONSULT_END, {
619
+ updateTaskData: true
620
+ }),
621
+ emitTaskConsultQueueCancelled: this.createEmitSelfAction(_types.TASK_EVENTS.TASK_CONSULT_QUEUE_CANCELLED, {
622
+ updateTaskData: true
623
+ }),
624
+ emitTaskConsultQueueFailed: this.createEmitSelfAction(_types.TASK_EVENTS.TASK_CONSULT_QUEUE_FAILED, {
625
+ updateTaskData: true
626
+ }),
627
+ emitTaskReject: ({
628
+ event
629
+ }) => {
630
+ this.updateTaskFromEvent(event);
631
+ const reason = event && typeof event === 'object' && 'reason' in event ? event.reason : undefined;
632
+ this.emit(_types.TASK_EVENTS.TASK_REJECT, reason);
633
+ },
634
+ emitTaskWrapup: ({
635
+ event
636
+ }) => {
637
+ this.updateTaskFromEvent(event);
638
+ const shouldEmitWrapup = Boolean(this.data.wrapUpRequired);
639
+ if (!shouldEmitWrapup) {
640
+ _loggerProxy.default.info(`Skipping task:wrapup event - wrapUpRequired is false`, {
641
+ module: _constants2.TASK_FILE,
642
+ method: 'emitTaskEvent',
643
+ interactionId: this.data?.interactionId
644
+ });
645
+ return;
646
+ }
647
+ _loggerProxy.default.info(`Emitting task event ${_types.TASK_EVENTS.TASK_WRAPUP}`, {
648
+ module: _constants2.TASK_FILE,
649
+ method: 'emitTaskEvent',
650
+ interactionId: this.data?.interactionId
651
+ });
652
+ this.emit(_types.TASK_EVENTS.TASK_WRAPUP, this);
653
+ },
654
+ emitTaskWrappedup: this.createEmitSelfAction(_types.TASK_EVENTS.TASK_WRAPPEDUP, {
655
+ updateTaskData: true
656
+ }),
657
+ requestAutoAnswer: ({
658
+ event
659
+ }) => {
660
+ if (event) {
661
+ // parameter intentionally unused
662
+ }
663
+ this.autoAnswerIfNeeded();
664
+ },
665
+ requestCleanup: () => {
666
+ this.emit(_types.TASK_EVENTS.TASK_CLEANUP, this, {
667
+ removeFromCollection: false
668
+ });
669
+ },
670
+ cleanupResources: () => {
671
+ this.emit(_types.TASK_EVENTS.TASK_CLEANUP, this, {
672
+ removeFromCollection: true
673
+ });
674
+ }
675
+ };
676
+ }
677
+
678
+ /**
679
+ * Sets up the automatic wrap-up timer if wrap-up is required
680
+ */
681
+ setupAutoWrapupTimer() {
682
+ if (this.data.wrapUpRequired && !this.autoWrapup && this.wrapupData && this.wrapupData.wrapUpProps) {
683
+ const wrapUpProps = this.wrapupData.wrapUpProps;
684
+ if (!wrapUpProps || wrapUpProps.autoWrapup === false) {
685
+ _loggerProxy.default.info(`Auto wrap-up is not required for this task`, {
686
+ module: _constants2.TASK_FILE,
687
+ method: _constants.METHODS.SETUP_AUTO_WRAPUP_TIMER,
688
+ interactionId: this.data.interactionId
689
+ });
690
+ return;
691
+ }
692
+ const defaultWrapupReason = wrapUpProps.wrapUpReasonList?.find(r => r.isDefault) ?? wrapUpProps.wrapUpReasonList?.[0];
693
+ if (!defaultWrapupReason) {
694
+ _loggerProxy.default.error('No wrap-up reason configured', {
695
+ module: _constants2.TASK_FILE,
696
+ method: _constants.METHODS.SETUP_AUTO_WRAPUP_TIMER
697
+ });
698
+ return;
699
+ }
700
+ const intervalMs = wrapUpProps.autoWrapupInterval;
701
+ if (!intervalMs || intervalMs <= 0) {
702
+ _loggerProxy.default.error(`Invalid auto wrap-up interval: ${intervalMs}`, {
703
+ module: _constants2.TASK_FILE,
704
+ method: _constants.METHODS.SETUP_AUTO_WRAPUP_TIMER
705
+ });
706
+ return;
707
+ }
708
+ this.autoWrapup = new _AutoWrapup.default(intervalMs, wrapUpProps.allowCancelAutoWrapup);
709
+ this.autoWrapup.start(async () => {
710
+ _loggerProxy.default.info(`Auto wrap-up timer triggered`, {
711
+ module: _constants2.TASK_FILE,
712
+ method: _constants.METHODS.SETUP_AUTO_WRAPUP_TIMER,
713
+ interactionId: this.data.interactionId
714
+ });
715
+ await this.wrapup({
716
+ wrapUpReason: defaultWrapupReason.name,
717
+ auxCodeId: defaultWrapupReason.id
718
+ });
719
+ });
720
+ }
721
+ }
722
+
723
+ /**
724
+ * Cancels the automatic wrap-up timer if it's running
725
+ */
726
+ reconcileData(oldData, newData) {
727
+ Object.keys(newData).forEach(key => {
728
+ if (newData[key] && typeof newData[key] === 'object' && !Array.isArray(newData[key])) {
729
+ oldData[key] = this.reconcileData({
730
+ ...oldData[key]
731
+ }, newData[key]);
732
+ } else {
733
+ oldData[key] = newData[key];
734
+ }
735
+ });
736
+ return oldData;
737
+ }
738
+
739
+ /**
740
+ *
741
+ * @param methodName - The name of the method that is unsupported
742
+ * @throws Error
743
+ */
744
+ unsupportedMethodError(methodName) {
745
+ _loggerProxy.default.error(`Unsupported operation`, {
746
+ module: 'TASK',
747
+ method: methodName,
748
+ interactionId: this.data?.interactionId
749
+ });
750
+ throw new Error(`Unsupported operation: ${methodName}`);
751
+ }
752
+
753
+ /**
754
+ * This method is used to update the task data.
755
+ * @param updatedData - TaskData
756
+ * @param shouldOverwrite - boolean
757
+ * @example
758
+ * ```typescript
759
+ * task.updateTaskData(updatedData, true);
760
+ * ```
761
+ */
762
+ updateTaskData(updatedData, shouldOverwrite = false) {
763
+ this.data = shouldOverwrite ? updatedData : this.reconcileData(this.data, updatedData);
764
+ if (!shouldOverwrite) {
765
+ this.pruneStaleInteractionMaps(updatedData);
766
+ }
767
+ this.updateUiControls();
768
+ this.setupAutoWrapupTimer();
769
+ return this;
770
+ }
771
+
772
+ /**
773
+ * The backend sends `interaction.media` and `interaction.participants` as complete snapshots
774
+ * of the current call state. `reconcileData` deep-merges and never removes keys, so entries the
775
+ * backend dropped (e.g. a consult leg's media and consultee participant after the consult ends)
776
+ * linger in `this.data`. That stale data drives incorrect UI controls (e.g. the consult button
777
+ * staying disabled after the consult leg is gone, until a page refresh re-hydrates cleanly).
778
+ * Make only these two snapshot maps authoritative to the incoming payload, leaving every other
779
+ * field on the generic deep-merge path (CAD and other partial updates still merge as before).
780
+ */
781
+ pruneStaleInteractionMaps(incoming) {
782
+ const incomingInteraction = incoming?.interaction;
783
+ const currentInteraction = this.data?.interaction;
784
+ if (!incomingInteraction || !currentInteraction) {
785
+ return;
786
+ }
787
+ ['media', 'participants'].forEach(mapKey => {
788
+ const incomingMap = incomingInteraction[mapKey];
789
+ const currentMap = currentInteraction[mapKey];
790
+ if (!incomingMap || !currentMap || typeof incomingMap !== 'object') {
791
+ return;
792
+ }
793
+ Object.keys(currentMap).forEach(id => {
794
+ if (!(id in incomingMap)) {
795
+ delete currentMap[id];
796
+ }
797
+ });
798
+ });
799
+ }
800
+
801
+ /**
802
+ * This is used to blind transfer or vTeam transfer the task
803
+ * @param transferPayload
804
+ * @returns Promise<TaskResponse>
805
+ * @throws Error
806
+ * @example
807
+ * ```typescript
808
+ * const transferPayload = {
809
+ * to: 'myQueueId',
810
+ * destinationType: 'queue',
811
+ * }
812
+ * task.transfer(transferPayload).then(()=>{}).catch(()=>{});
813
+ * ```
814
+ */
815
+ async transfer(transferPayload) {
816
+ _loggerProxy.default.log(`Starting task transfer for taskId:${this.data.interactionId}`, {
817
+ module: 'Task',
818
+ method: 'transfer'
819
+ });
820
+ try {
821
+ this.metricsManager.timeEvent([_constants3.METRIC_EVENT_NAMES.TASK_TRANSFER_SUCCESS, _constants3.METRIC_EVENT_NAMES.TASK_TRANSFER_FAILED]);
822
+ let result;
823
+ const isQueueTransfer = transferPayload.destinationType === _types.DESTINATION_TYPE.QUEUE;
824
+ const isEntryPointTransfer = transferPayload.destinationType === _types.DESTINATION_TYPE.ENTRYPOINT;
825
+ if (isQueueTransfer || isEntryPointTransfer) {
826
+ result = await this.contact.vteamTransfer({
827
+ interactionId: this.data.interactionId,
828
+ data: {
829
+ ...transferPayload,
830
+ destinationType: isEntryPointTransfer ? _constants.ENTRY_POINT_TRANSFER_DESTINATION_TYPE : _types.DESTINATION_TYPE.QUEUE
831
+ }
832
+ });
833
+ } else {
834
+ result = await this.contact.blindTransfer({
835
+ interactionId: this.data.interactionId,
836
+ data: transferPayload
837
+ });
838
+ }
839
+ this.metricsManager.trackEvent(_constants3.METRIC_EVENT_NAMES.TASK_TRANSFER_SUCCESS, {
840
+ taskId: this.data.interactionId,
841
+ destination: transferPayload.to,
842
+ destinationType: transferPayload.destinationType,
843
+ isConsultTransfer: false,
844
+ ..._MetricsManager.default.getCommonTrackingFieldForAQMResponse(result)
845
+ }, ['operational', 'behavioral', 'business']);
846
+ return result;
847
+ } catch (error) {
848
+ const {
849
+ error: detailedError
850
+ } = (0, _Utils.getErrorDetails)(error, 'transfer', _constants2.CC_FILE);
851
+ this.metricsManager.trackEvent(_constants3.METRIC_EVENT_NAMES.TASK_TRANSFER_FAILED, {
852
+ taskId: this.data.interactionId,
853
+ destination: transferPayload.to,
854
+ destinationType: transferPayload.destinationType,
855
+ isConsultTransfer: false,
856
+ error: error.toString(),
857
+ ..._MetricsManager.default.getCommonTrackingFieldForAQMResponseFailed(error.details || {})
858
+ }, ['operational', 'behavioral', 'business']);
859
+ throw detailedError;
860
+ }
861
+ }
862
+
863
+ /**
864
+ * This is used to end the task.
865
+ * @returns Promise<TaskResponse>
866
+ * @throws Error
867
+ * @example
868
+ * ```typescript
869
+ * task.end().then(()=>{}).catch(()=>{})
870
+ * ```
871
+ */
872
+ async end() {
873
+ _loggerProxy.default.log(`Ending task for taskId:${this.data.interactionId}`, {
874
+ module: 'Task',
875
+ method: 'end'
876
+ });
877
+ const requestInteractionId = this.data.interaction?.mainInteractionId || this.data.interactionId;
878
+ try {
879
+ this.metricsManager.timeEvent([_constants3.METRIC_EVENT_NAMES.TASK_END_SUCCESS, _constants3.METRIC_EVENT_NAMES.TASK_END_FAILED]);
880
+ const response = await this.contact.end({
881
+ interactionId: requestInteractionId
882
+ });
883
+ this.metricsManager.trackEvent(_constants3.METRIC_EVENT_NAMES.TASK_END_SUCCESS, {
884
+ taskId: this.data.interactionId,
885
+ requestInteractionId,
886
+ ..._MetricsManager.default.getCommonTrackingFieldForAQMResponse(response)
887
+ }, ['operational', 'behavioral', 'business']);
888
+ return response;
889
+ } catch (error) {
890
+ const {
891
+ error: detailedError
892
+ } = (0, _Utils.getErrorDetails)(error, 'end', _constants2.CC_FILE);
893
+ this.metricsManager.trackEvent(_constants3.METRIC_EVENT_NAMES.TASK_END_FAILED, {
894
+ taskId: this.data.interactionId,
895
+ requestInteractionId,
896
+ ..._MetricsManager.default.getCommonTrackingFieldForAQMResponseFailed(error.details || {})
897
+ }, ['operational', 'behavioral', 'business']);
898
+ throw detailedError;
899
+ }
900
+ }
901
+
902
+ /**
903
+ * This is used to wrap up the task.
904
+ * @param wrapupPayload - WrapupPayLoad
905
+ * @returns Promise<TaskResponse>
906
+ * @throws Error
907
+ * @example
908
+ * ```typescript
909
+ * task.wrapup(wrapupPayload).then(()=>{}).catch(()=>{})
910
+ * ```
911
+ */
912
+ async wrapup(wrapupPayload) {
913
+ this.cancelAutoWrapupTimer();
914
+ _loggerProxy.default.log(`Starting task wrapup for taskId:${this.data.interactionId}`, {
915
+ module: 'Task',
916
+ method: 'wrapup'
917
+ });
918
+ try {
919
+ this.metricsManager.timeEvent([_constants3.METRIC_EVENT_NAMES.TASK_WRAPUP_SUCCESS, _constants3.METRIC_EVENT_NAMES.TASK_WRAPUP_FAILED]);
920
+ if (!this.data) {
921
+ throw new Error('No task data available');
922
+ }
923
+ if (!wrapupPayload.auxCodeId || wrapupPayload.auxCodeId.length === 0) {
924
+ throw new Error('AuxCodeId is required');
925
+ }
926
+ if (!wrapupPayload.wrapUpReason || wrapupPayload.wrapUpReason.length === 0) {
927
+ throw new Error('WrapUpReason is required');
928
+ }
929
+ const response = await this.contact.wrapup({
930
+ interactionId: this.data.interactionId,
931
+ data: wrapupPayload
932
+ });
933
+ this.metricsManager.trackEvent(_constants3.METRIC_EVENT_NAMES.TASK_WRAPUP_SUCCESS, {
934
+ taskId: this.data.interactionId,
935
+ wrapUpCode: wrapupPayload.auxCodeId,
936
+ wrapUpReason: wrapupPayload.wrapUpReason,
937
+ ..._MetricsManager.default.getCommonTrackingFieldForAQMResponse(response)
938
+ }, ['operational', 'behavioral', 'business']);
939
+ return response;
940
+ } catch (error) {
941
+ const {
942
+ error: detailedError
943
+ } = (0, _Utils.getErrorDetails)(error, 'wrapup', _constants2.CC_FILE);
944
+ this.metricsManager.trackEvent(_constants3.METRIC_EVENT_NAMES.TASK_WRAPUP_FAILED, {
945
+ taskId: this.data.interactionId,
946
+ wrapUpCode: wrapupPayload.auxCodeId,
947
+ wrapUpReason: wrapupPayload.wrapUpReason,
948
+ ..._MetricsManager.default.getCommonTrackingFieldForAQMResponseFailed(error.details || {})
949
+ }, ['operational', 'behavioral', 'business']);
950
+ throw detailedError;
951
+ }
952
+ }
953
+ }
954
+ exports.default = Task;
955
+ //# sourceMappingURL=Task.js.map