@webex/contact-center 3.11.0 → 3.12.0-auth-prejoin-fetch.1

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 (325) hide show
  1. package/.sdd/manifest.json +883 -0
  2. package/AGENTS.md +94 -0
  3. package/ai-docs/ARCHITECTURE.md +168 -0
  4. package/ai-docs/CONTRACTS.md +50 -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 +359 -0
  17. package/ai-docs/features/consult-transfer-list-policy/spec/feature-spec.md +362 -0
  18. package/ai-docs/features/generated-spec-conformance-fidelity-remediation/spec/feature-spec.md +117 -0
  19. package/ai-docs/features/residual-warning-coverage-completion/spec/feature-spec.md +203 -0
  20. package/ai-docs/features/validator-code-fidelity-drift-fix/spec/feature-spec.md +315 -0
  21. package/ai-docs/patterns/event-driven-patterns.md +485 -0
  22. package/ai-docs/patterns/testing-patterns.md +480 -0
  23. package/ai-docs/patterns/typescript-patterns.md +365 -0
  24. package/ai-docs/templates/README.md +102 -0
  25. package/ai-docs/templates/documentation/create-agents-md.md +240 -0
  26. package/ai-docs/templates/documentation/create-architecture-md.md +295 -0
  27. package/ai-docs/templates/existing-service/bug-fix.md +254 -0
  28. package/ai-docs/templates/existing-service/feature-enhancement.md +450 -0
  29. package/ai-docs/templates/new-method/00-master.md +80 -0
  30. package/ai-docs/templates/new-method/01-requirements.md +232 -0
  31. package/ai-docs/templates/new-method/02-implementation.md +295 -0
  32. package/ai-docs/templates/new-method/03-tests.md +201 -0
  33. package/ai-docs/templates/new-method/04-validation.md +141 -0
  34. package/ai-docs/templates/new-service/00-master.md +109 -0
  35. package/ai-docs/templates/new-service/01-pre-questions.md +159 -0
  36. package/ai-docs/templates/new-service/02-code-generation.md +346 -0
  37. package/ai-docs/templates/new-service/03-integration.md +178 -0
  38. package/ai-docs/templates/new-service/04-test-generation.md +205 -0
  39. package/ai-docs/templates/new-service/05-validation.md +145 -0
  40. package/dist/cc.js +818 -59
  41. package/dist/cc.js.map +1 -1
  42. package/dist/config.js +13 -0
  43. package/dist/config.js.map +1 -1
  44. package/dist/constants.js +31 -3
  45. package/dist/constants.js.map +1 -1
  46. package/dist/index.js +27 -5
  47. package/dist/index.js.map +1 -1
  48. package/dist/metrics/behavioral-events.js +127 -0
  49. package/dist/metrics/behavioral-events.js.map +1 -1
  50. package/dist/metrics/constants.js +34 -3
  51. package/dist/metrics/constants.js.map +1 -1
  52. package/dist/services/AddressBook.js +18 -15
  53. package/dist/services/AddressBook.js.map +1 -1
  54. package/dist/services/AnswerCallOnWebexService.js +174 -0
  55. package/dist/services/AnswerCallOnWebexService.js.map +1 -0
  56. package/dist/services/ApiAiAssistant.js +318 -0
  57. package/dist/services/ApiAiAssistant.js.map +1 -0
  58. package/dist/services/EntryPoint.js +46 -68
  59. package/dist/services/EntryPoint.js.map +1 -1
  60. package/dist/services/Queue.js +27 -22
  61. package/dist/services/Queue.js.map +1 -1
  62. package/dist/services/UserPreference.js +427 -0
  63. package/dist/services/UserPreference.js.map +1 -0
  64. package/dist/services/WebexCrossClientService.js +171 -0
  65. package/dist/services/WebexCrossClientService.js.map +1 -0
  66. package/dist/services/WxAppTelephonyMercurySync.js +93 -0
  67. package/dist/services/WxAppTelephonyMercurySync.js.map +1 -0
  68. package/dist/services/agent/types.js.map +1 -1
  69. package/dist/services/config/Util.js +11 -4
  70. package/dist/services/config/Util.js.map +1 -1
  71. package/dist/services/config/constants.js +45 -8
  72. package/dist/services/config/constants.js.map +1 -1
  73. package/dist/services/config/index.js +41 -2
  74. package/dist/services/config/index.js.map +1 -1
  75. package/dist/services/config/types.js +70 -8
  76. package/dist/services/config/types.js.map +1 -1
  77. package/dist/services/constants.js +27 -1
  78. package/dist/services/constants.js.map +1 -1
  79. package/dist/services/core/Err.js.map +1 -1
  80. package/dist/services/core/Utils.js +122 -25
  81. package/dist/services/core/Utils.js.map +1 -1
  82. package/dist/services/core/WebexRequest.js +6 -2
  83. package/dist/services/core/WebexRequest.js.map +1 -1
  84. package/dist/services/core/aqm-reqs.js +119 -30
  85. package/dist/services/core/aqm-reqs.js.map +1 -1
  86. package/dist/services/core/types.js.map +1 -1
  87. package/dist/services/core/websocket/WebSocketManager.js +22 -6
  88. package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
  89. package/dist/services/core/websocket/connection-service.js +3 -1
  90. package/dist/services/core/websocket/connection-service.js.map +1 -1
  91. package/dist/services/core/websocket/types.js.map +1 -1
  92. package/dist/services/index.js +6 -0
  93. package/dist/services/index.js.map +1 -1
  94. package/dist/services/task/Task.js +754 -0
  95. package/dist/services/task/Task.js.map +1 -0
  96. package/dist/services/task/TaskFactory.js +49 -0
  97. package/dist/services/task/TaskFactory.js.map +1 -0
  98. package/dist/services/task/TaskManager.js +1073 -447
  99. package/dist/services/task/TaskManager.js.map +1 -1
  100. package/dist/services/task/TaskUtils.js +220 -23
  101. package/dist/services/task/TaskUtils.js.map +1 -1
  102. package/dist/services/task/WebexCallingUtils.js +70 -0
  103. package/dist/services/task/WebexCallingUtils.js.map +1 -0
  104. package/dist/services/task/constants.js +26 -2
  105. package/dist/services/task/constants.js.map +1 -1
  106. package/dist/services/task/contact.js +29 -0
  107. package/dist/services/task/contact.js.map +1 -1
  108. package/dist/services/task/dialer.js +129 -0
  109. package/dist/services/task/dialer.js.map +1 -1
  110. package/dist/services/task/digital/Digital.js +78 -0
  111. package/dist/services/task/digital/Digital.js.map +1 -0
  112. package/dist/services/task/state-machine/TaskStateMachine.js +971 -0
  113. package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -0
  114. package/dist/services/task/state-machine/actions.js +572 -0
  115. package/dist/services/task/state-machine/actions.js.map +1 -0
  116. package/dist/services/task/state-machine/constants.js +161 -0
  117. package/dist/services/task/state-machine/constants.js.map +1 -0
  118. package/dist/services/task/state-machine/guards.js +409 -0
  119. package/dist/services/task/state-machine/guards.js.map +1 -0
  120. package/dist/services/task/state-machine/index.js +53 -0
  121. package/dist/services/task/state-machine/index.js.map +1 -0
  122. package/dist/services/task/state-machine/types.js +54 -0
  123. package/dist/services/task/state-machine/types.js.map +1 -0
  124. package/dist/services/task/state-machine/uiControlsComputer.js +703 -0
  125. package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -0
  126. package/dist/services/task/taskDataNormalizer.js +99 -0
  127. package/dist/services/task/taskDataNormalizer.js.map +1 -0
  128. package/dist/services/task/types.js +243 -5
  129. package/dist/services/task/types.js.map +1 -1
  130. package/dist/services/task/voice/Voice.js +1380 -0
  131. package/dist/services/task/voice/Voice.js.map +1 -0
  132. package/dist/services/task/voice/WebRTC.js +152 -0
  133. package/dist/services/task/voice/WebRTC.js.map +1 -0
  134. package/dist/services/task/voice/wxAppVoiceMethods.js +201 -0
  135. package/dist/services/task/voice/wxAppVoiceMethods.js.map +1 -0
  136. package/dist/services/wxAppTelephonyUtils.js +19 -0
  137. package/dist/services/wxAppTelephonyUtils.js.map +1 -0
  138. package/dist/types/cc.d.ts +967 -0
  139. package/dist/types/config.d.ts +79 -0
  140. package/dist/types/constants.d.ts +74 -0
  141. package/dist/types/index.d.ts +201 -0
  142. package/dist/types/logger-proxy.d.ts +71 -0
  143. package/dist/types/metrics/MetricsManager.d.ts +223 -0
  144. package/dist/types/metrics/behavioral-events.d.ts +29 -0
  145. package/dist/types/metrics/constants.d.ts +183 -0
  146. package/dist/types/services/AddressBook.d.ts +75 -0
  147. package/dist/types/services/AnswerCallOnWebexService.d.ts +37 -0
  148. package/dist/types/services/ApiAiAssistant.d.ts +49 -0
  149. package/dist/types/services/EntryPoint.d.ts +69 -0
  150. package/dist/types/services/Queue.d.ts +78 -0
  151. package/dist/types/services/UserPreference.d.ts +118 -0
  152. package/dist/types/services/WebCallingService.d.ts +1 -0
  153. package/dist/types/services/WebexCrossClientService.d.ts +28 -0
  154. package/dist/types/services/WxAppTelephonyMercurySync.d.ts +28 -0
  155. package/dist/types/services/agent/index.d.ts +46 -0
  156. package/dist/types/services/agent/types.d.ts +413 -0
  157. package/dist/types/services/config/Util.d.ts +20 -0
  158. package/dist/types/services/config/constants.d.ts +273 -0
  159. package/dist/types/services/config/index.d.ts +177 -0
  160. package/dist/types/services/config/types.d.ts +1381 -0
  161. package/dist/types/services/constants.d.ts +110 -0
  162. package/dist/types/services/core/Err.d.ts +127 -0
  163. package/dist/types/services/core/GlobalTypes.d.ts +58 -0
  164. package/dist/types/services/core/Utils.d.ts +121 -0
  165. package/dist/types/services/core/WebexRequest.d.ts +23 -0
  166. package/dist/types/services/core/aqm-reqs.d.ts +65 -0
  167. package/dist/types/services/core/constants.d.ts +99 -0
  168. package/dist/types/services/core/types.d.ts +49 -0
  169. package/dist/types/services/core/websocket/WebSocketManager.d.ts +36 -0
  170. package/dist/types/services/core/websocket/connection-service.d.ts +27 -0
  171. package/dist/types/services/core/websocket/keepalive.worker.d.ts +2 -0
  172. package/dist/types/services/core/websocket/types.d.ts +37 -0
  173. package/dist/types/services/index.d.ts +54 -0
  174. package/dist/types/services/task/AutoWrapup.d.ts +40 -0
  175. package/dist/types/services/task/Task.d.ts +175 -0
  176. package/dist/types/services/task/TaskFactory.d.ts +13 -0
  177. package/dist/types/services/task/TaskManager.d.ts +1 -0
  178. package/dist/types/services/task/TaskUtils.d.ts +138 -0
  179. package/dist/types/services/task/WebexCallingUtils.d.ts +11 -0
  180. package/dist/types/services/task/constants.d.ts +94 -0
  181. package/dist/types/services/task/contact.d.ts +73 -0
  182. package/dist/types/services/task/dialer.d.ts +73 -0
  183. package/dist/types/services/task/digital/Digital.d.ts +22 -0
  184. package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +1398 -0
  185. package/dist/types/services/task/state-machine/actions.d.ts +10 -0
  186. package/dist/types/services/task/state-machine/constants.d.ts +107 -0
  187. package/dist/types/services/task/state-machine/guards.d.ts +103 -0
  188. package/dist/types/services/task/state-machine/index.d.ts +13 -0
  189. package/dist/types/services/task/state-machine/types.d.ts +277 -0
  190. package/dist/types/services/task/state-machine/uiControlsComputer.d.ts +9 -0
  191. package/dist/types/services/task/taskDataNormalizer.d.ts +10 -0
  192. package/dist/types/services/task/types.d.ts +1933 -0
  193. package/dist/types/services/task/voice/Voice.d.ts +223 -0
  194. package/dist/types/services/task/voice/WebRTC.d.ts +53 -0
  195. package/dist/types/services/task/voice/wxAppVoiceMethods.d.ts +52 -0
  196. package/dist/types/services/wxAppTelephonyUtils.d.ts +5 -0
  197. package/dist/types/types.d.ts +784 -0
  198. package/dist/types/utils/PageCache.d.ts +190 -0
  199. package/dist/types/webex-config.d.ts +53 -0
  200. package/dist/types/webex.d.ts +8 -0
  201. package/dist/types.js +137 -3
  202. package/dist/types.js.map +1 -1
  203. package/dist/utils/PageCache.js +19 -5
  204. package/dist/utils/PageCache.js.map +1 -1
  205. package/dist/webex.js +14 -2
  206. package/dist/webex.js.map +1 -1
  207. package/package.json +16 -12
  208. package/src/cc.ts +983 -60
  209. package/src/config.ts +13 -0
  210. package/src/constants.ts +29 -1
  211. package/src/index.ts +26 -5
  212. package/src/metrics/ai-docs/AGENTS.md +350 -0
  213. package/src/metrics/ai-docs/ARCHITECTURE.md +338 -0
  214. package/src/metrics/ai-docs/metrics-spec.md +860 -0
  215. package/src/metrics/behavioral-events.ts +134 -0
  216. package/src/metrics/constants.ts +39 -3
  217. package/src/services/AddressBook.ts +17 -6
  218. package/src/services/AnswerCallOnWebexService.ts +206 -0
  219. package/src/services/ApiAiAssistant.ts +412 -0
  220. package/src/services/EntryPoint.ts +59 -60
  221. package/src/services/Queue.ts +29 -12
  222. package/src/services/UserPreference.ts +509 -0
  223. package/src/services/WebexCrossClientService.ts +212 -0
  224. package/src/services/WxAppTelephonyMercurySync.ts +115 -0
  225. package/src/services/agent/ai-docs/AGENTS.md +240 -0
  226. package/src/services/agent/ai-docs/ARCHITECTURE.md +304 -0
  227. package/src/services/agent/ai-docs/agent-spec.md +504 -0
  228. package/src/services/agent/types.ts +1 -1
  229. package/src/services/ai-docs/AGENTS.md +386 -0
  230. package/src/services/ai-docs/services-spec.md +497 -0
  231. package/src/services/config/Util.ts +13 -2
  232. package/src/services/config/ai-docs/AGENTS.md +255 -0
  233. package/src/services/config/ai-docs/ARCHITECTURE.md +426 -0
  234. package/src/services/config/ai-docs/config-spec.md +675 -0
  235. package/src/services/config/constants.ts +47 -7
  236. package/src/services/config/index.ts +45 -1
  237. package/src/services/config/types.ts +253 -11
  238. package/src/services/constants.ts +29 -0
  239. package/src/services/core/Err.ts +4 -0
  240. package/src/services/core/Utils.ts +143 -30
  241. package/src/services/core/WebexRequest.ts +3 -1
  242. package/src/services/core/ai-docs/AGENTS.md +381 -0
  243. package/src/services/core/ai-docs/ARCHITECTURE.md +698 -0
  244. package/src/services/core/ai-docs/core-spec.md +787 -0
  245. package/src/services/core/aqm-reqs.ts +125 -32
  246. package/src/services/core/types.ts +2 -0
  247. package/src/services/core/websocket/WebSocketManager.ts +23 -6
  248. package/src/services/core/websocket/connection-service.ts +5 -1
  249. package/src/services/core/websocket/types.ts +1 -1
  250. package/src/services/index.ts +4 -0
  251. package/src/services/task/Task.ts +908 -0
  252. package/src/services/task/TaskFactory.ts +60 -0
  253. package/src/services/task/TaskManager.ts +1291 -513
  254. package/src/services/task/TaskUtils.ts +314 -24
  255. package/src/services/task/WebexCallingUtils.ts +136 -0
  256. package/src/services/task/ai-docs/AGENTS.md +457 -0
  257. package/src/services/task/ai-docs/ARCHITECTURE.md +595 -0
  258. package/src/services/task/ai-docs/task-spec.md +1469 -0
  259. package/src/services/task/constants.ts +26 -0
  260. package/src/services/task/contact.ts +30 -0
  261. package/src/services/task/dialer.ts +136 -1
  262. package/src/services/task/digital/Digital.ts +97 -0
  263. package/src/services/task/state-machine/TaskStateMachine.ts +1313 -0
  264. package/src/services/task/state-machine/actions.ts +741 -0
  265. package/src/services/task/state-machine/ai-docs/AGENTS.md +462 -0
  266. package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +1146 -0
  267. package/src/services/task/state-machine/ai-docs/task-state-machine-spec.md +2209 -0
  268. package/src/services/task/state-machine/constants.ts +172 -0
  269. package/src/services/task/state-machine/guards.ts +498 -0
  270. package/src/services/task/state-machine/index.ts +28 -0
  271. package/src/services/task/state-machine/types.ts +258 -0
  272. package/src/services/task/state-machine/uiControlsComputer.ts +1135 -0
  273. package/src/services/task/taskDataNormalizer.ts +137 -0
  274. package/src/services/task/types.ts +843 -70
  275. package/src/services/task/voice/Voice.ts +1720 -0
  276. package/src/services/task/voice/WebRTC.ts +191 -0
  277. package/src/services/task/voice/wxAppVoiceMethods.ts +307 -0
  278. package/src/services/wxAppTelephonyUtils.ts +14 -0
  279. package/src/types.ts +238 -11
  280. package/src/utils/AGENTS.md +289 -0
  281. package/src/utils/PageCache.ts +38 -5
  282. package/src/utils/ai-docs/utils-spec.md +391 -0
  283. package/src/webex.js +2 -0
  284. package/test/unit/spec/cc.ts +1856 -122
  285. package/test/unit/spec/logger-proxy.ts +70 -0
  286. package/test/unit/spec/metrics/behavioral-events.ts +18 -0
  287. package/test/unit/spec/services/AddressBook.ts +37 -6
  288. package/test/unit/spec/services/AnswerCallOnWebexService.ts +223 -0
  289. package/test/unit/spec/services/ApiAiAssistant.ts +273 -0
  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 +7 -1
  294. package/test/unit/spec/services/WebexCrossClientService.ts +261 -0
  295. package/test/unit/spec/services/WxAppTelephonyMercurySync.ts +113 -0
  296. package/test/unit/spec/services/config/Util.ts +85 -0
  297. package/test/unit/spec/services/config/index.ts +85 -29
  298. package/test/unit/spec/services/core/Utils.ts +481 -2
  299. package/test/unit/spec/services/core/WebexRequest.ts +3 -1
  300. package/test/unit/spec/services/core/aqm-reqs.ts +113 -1
  301. package/test/unit/spec/services/core/websocket/WebSocketManager.ts +137 -41
  302. package/test/unit/spec/services/core/websocket/connection-service.ts +3 -1
  303. package/test/unit/spec/services/task/AutoWrapup.ts +63 -0
  304. package/test/unit/spec/services/task/Task.ts +677 -0
  305. package/test/unit/spec/services/task/TaskFactory.ts +99 -0
  306. package/test/unit/spec/services/task/TaskManager.ts +2209 -918
  307. package/test/unit/spec/services/task/TaskUtils.ts +235 -0
  308. package/test/unit/spec/services/task/WebexCallingUtils.ts +153 -0
  309. package/test/unit/spec/services/task/contact.ts +33 -0
  310. package/test/unit/spec/services/task/dialer.ts +372 -96
  311. package/test/unit/spec/services/task/digital/Digital.ts +105 -0
  312. package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +3433 -0
  313. package/test/unit/spec/services/task/state-machine/guards.ts +839 -0
  314. package/test/unit/spec/services/task/state-machine/types.ts +18 -0
  315. package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +3101 -0
  316. package/test/unit/spec/services/task/taskTestUtils.ts +87 -0
  317. package/test/unit/spec/services/task/voice/Voice.ts +1523 -0
  318. package/test/unit/spec/services/task/voice/WebRTC.ts +235 -0
  319. package/test/unit/spec/services/task/voice/wxAppVoiceMethods.ts +459 -0
  320. package/umd/contact-center.min.js +2 -2
  321. package/umd/contact-center.min.js.map +1 -1
  322. package/dist/services/task/index.js +0 -1525
  323. package/dist/services/task/index.js.map +0 -1
  324. package/src/services/task/index.ts +0 -1801
  325. package/test/unit/spec/services/task/index.ts +0 -2184
@@ -0,0 +1,787 @@
1
+ # Core — SPEC
2
+
3
+ > Start here → root [`AGENTS.md`](../../../../AGENTS.md) · router [`SPEC_INDEX.md`](../../../../ai-docs/SPEC_INDEX.md) · system [`ARCHITECTURE.md`](../../../../ai-docs/ARCHITECTURE.md). This is the module's canonical specification.
4
+
5
+ ## Metadata
6
+
7
+ | Field | Value |
8
+ |---|---|
9
+ | Module id | `core` |
10
+ | Source path(s) | `src/services/core` |
11
+ | Doc kind | Module spec |
12
+ | Coverage score | Partial (manifest-authoritative); 15/15 required document fields present |
13
+ | Generated from | `module-spec` @ SDLC template library `0.2.1` |
14
+ | generated_by / approved_by / updated_at | Codex generator / developer-approved follow-up review remediation / 2026-07-21 |
15
+ | Validation status | Follow-up validation passed (independent Claude fallback, 2026-07-21); coverage remains Partial |
16
+
17
+ ## Evidence Rules
18
+ Every requirement cites stable source and test file paths. Code/tests are the behavioral referee; routed source text supplies explicit intent and rationale. Missing or contradictory evidence blocks promotion.
19
+
20
+ ## Source Material Register
21
+ | Source material | Scope | Decision | Detail location or disposition |
22
+ |---|---|---|---|
23
+ | Reviewed prior module guides and architecture material | overview / architecture / API / tests | used and code-checked | Content is placed by meaning throughout this specification; exact routing remains in the manifest. |
24
+
25
+ ## Overview
26
+ Core is one of nine confirmed Contact Center SDK modules. Own authenticated HTTP, realtime WebSocket lifecycle, AQM request correlation, reconnect/keepalive behavior, and shared error normalization. Existing reviewed documentation is migrated by meaning and code/tests remain the behavioral referee.
27
+
28
+ The Core service provides the foundational infrastructure layer that all other services depend on:
29
+
30
+ - **WebSocket Communication**: Real-time bidirectional messaging with the contact center backend, including automatic reconnection and keepalive management
31
+
32
+ - **HTTP Request Handling**: Authenticated REST API calls to WCC API Gateway with built-in error handling and log upload support
33
+
34
+ - **AQM Request/Response Pattern**: A structured pattern used by the routing and contact layers to send HTTP requests to the contact center backend and correlate responses/failures via WebSocket notifications
35
+
36
+ - **Error Handling & Logging**: Standardized error extraction, logging via `LoggerProxy`, and log upload utilities that all services use for consistent error reporting
37
+
38
+ | Component | File | Description |
39
+ |---|---|---|
40
+ | `WebSocketManager` | [`WebSocketManager.ts`](../websocket/WebSocketManager.ts) | Manages the WebSocket connection lifecycle including initialization, message dispatch, and graceful shutdown. Emits `message` events for incoming data and `socketClose` when the connection drops while reconnect is allowed. |
41
+ | `ConnectionService` | [`connection-service.ts`](../websocket/connection-service.ts) | Orchestrates reconnection logic and keepalive heartbeats on top of `WebSocketManager`. Detects connection loss/recovery and emits `connectionLost` details; ContactCenter owns any `silentRelogin()` policy. |
42
+ | `WebexRequest` | [`WebexRequest.ts`](../WebexRequest.ts) | Singleton HTTP client that forwards service/resource/method/body options to the authenticated host request API and provides `uploadLogs` diagnostics. |
43
+ | `AqmReqs` | [`aqm-reqs.ts`](../aqm-reqs.ts) | Factory for creating request methods that send HTTP requests and wait for correlated WebSocket notifications (success or failure). Used by routing and task services to implement their API methods. |
44
+ | `Utils` | [`Utils.ts`](../Utils.ts) | Shared utility functions including `getErrorDetails()` for standardized error handling, `generateTaskErrorObject()` for task-specific errors, and `createErrDetailsObject()` for constructing error detail objects. |
45
+ | `Err` | [`Err.ts`](../Err.ts) | Error class definitions. `Err.Details` carries structured error metadata (status, type, trackingId) for consistent error propagation. |
46
+ | `constants` | [`constants.ts`](../constants.ts) | Timeout values, interval durations, participant types, interaction states, and method name constants used throughout the core layer. Any new constants for core should be defined here. |
47
+
48
+ ## Purpose / Responsibility
49
+ Own authenticated HTTP, realtime WebSocket lifecycle, AQM request correlation, reconnect/keepalive behavior, and shared error normalization.
50
+
51
+ ## Stack
52
+ TypeScript/JavaScript, WebSocket, Web Worker keepalive, EventEmitter, Webex request client, Jest 27.
53
+
54
+ ## Folder / Package Structure
55
+ ```text
56
+ src/services/core/
57
+ ├── Err.ts
58
+ ├── GlobalTypes.ts
59
+ ├── Utils.ts
60
+ ├── WebexRequest.ts
61
+ ├── aqm-reqs.ts
62
+ ├── constants.ts
63
+ ├── types.ts
64
+ ├── websocket/
65
+ ```
66
+
67
+ ```text
68
+ services/core/
69
+ ├── aqm-reqs.ts # AQM request handler
70
+ ├── constants.ts # Core constants
71
+ ├── Err.ts # Error classes
72
+ ├── GlobalTypes.ts # Failure, Msg<T>, etc.
73
+ ├── types.ts # Request/response types
74
+ ├── Utils.ts # Utility functions
75
+ ├── WebexRequest.ts # HTTP client
76
+ └── websocket/
77
+ ├── WebSocketManager.ts # Main WS handler
78
+ ├── connection-service.ts # Connection lifecycle
79
+ ├── keepalive.worker.js # Keepalive worker
80
+ └── types.ts # WS types
81
+ ```
82
+
83
+ ## Key Files (source of truth)
84
+ | File | Holds |
85
+ |---|---|
86
+ | `src/services/core/WebexRequest.ts` | Authoritative Core implementation or contract source. |
87
+ | `src/services/core/aqm-reqs.ts` | Authoritative Core implementation or contract source. |
88
+ | `src/services/core/Utils.ts` | Authoritative Core implementation or contract source. |
89
+ | `src/services/core/Err.ts` | Authoritative Core implementation or contract source. |
90
+ | `src/services/core/websocket/WebSocketManager.ts` | Authoritative Core implementation or contract source. |
91
+ | `src/services/core/websocket/connection-service.ts` | Authoritative Core implementation or contract source. |
92
+
93
+ ## Public Surface
94
+ | Contract ID | Type | Surface | Purpose | Compatibility / deprecation | Schema / detail link | Root index |
95
+ |---|---|---|---|---|---|---|
96
+ | `core.surface` | SDK / event / internal API | Internal WebexRequest, WebSocketManager, ConnectionService, AqmReqs, and shared error/request types and helpers. | Stable module consumption boundary. | Additive changes by default; breaking package exports require a major-version transition. | `src/services/core/WebexRequest.ts` | `../../../../ai-docs/CONTRACTS.md` |
97
+
98
+ Compatibility notes:
99
+ - Do not remove or reinterpret exported symbols/events without a documented consumer migration.
100
+
101
+ | Event | Data | Description |
102
+ |---|---|---|
103
+ | `message` | string (JSON) | WebSocket message received |
104
+ | `socketClose` | - | Socket closed while reconnect is allowed |
105
+
106
+ Generic message wrapper used throughout the SDK. All WebSocket messages and AQM responses conform to this shape:
107
+
108
+ ```typescript
109
+ export type Msg<T = any> = {
110
+ type: string; // Message/Event type identifier
111
+ orgId: string; // Organization identifier
112
+ trackingId: string; // Unique tracking identifier
113
+ data: T; // Message/Event payload data
114
+ };
115
+
116
+ // Usage — the payload type goes into `data`
117
+ export type LoginSuccess = Msg<{
118
+ agentId: string;
119
+ status: string;
120
+ // ...
121
+ }>;
122
+ // Resulting shape: { type, orgId, trackingId, data: { agentId, status, ... } }
123
+ ```
124
+
125
+ ### ConnectionService internal surface — not public contracts
126
+
127
+ The only public method in the following list is `setConnectionProp`. The remaining methods are private implementation details documented for ownership and maintenance; they are not public API contracts.
128
+
129
+ 1. `setConnectionProp(prop: ConnectionProp): void` (public)
130
+
131
+ - **Purpose**: Updates connection-level runtime settings used by timers (mainly recovery timeout behavior).
132
+
133
+ - **Params**: `prop` - new connection config object.
134
+
135
+ - **Returns**: `void`.
136
+
137
+ - **Usage**: Called by higher layers when timeout behavior must be tuned after initialization.
138
+
139
+ 2. `setupEventListeners(): void` (private)
140
+
141
+ - **Purpose**: Wires `WebSocketManager` events to internal handlers (`'message' -> onPing`, `'socketClose' -> onSocketClose`).
142
+
143
+ - **Params**: none.
144
+
145
+ - **Returns**: `void`.
146
+
147
+ - **Usage**: Invoked from the constructor once, during `ConnectionService` setup.
148
+
149
+ 3. `onPing(event: any): void` (private)
150
+
151
+ - **Purpose**: Handles every incoming socket message, resets timers, updates keepalive/recovery flags, and emits recovery events when state changes.
152
+
153
+ - **Params**: `event` - raw message payload (JSON string) received from the socket event stream.
154
+
155
+ - **Returns**: `void`.
156
+
157
+ - **Usage**: Triggered automatically by the `'message'` listener.
158
+
159
+ 4. `onSocketClose(): void` (private)
160
+
161
+ - **Purpose**: Starts the reconnect interval when socket close is detected.
162
+
163
+ - **Params**: none.
164
+
165
+ - **Returns**: `void`.
166
+
167
+ - **Usage**: Triggered automatically by the `'socketClose'` listener.
168
+
169
+ 5. `handleSocketClose(): Promise<void>` (private)
170
+
171
+ - **Purpose**: Performs one reconnect attempt; if browser is online, reinitializes WebSocket and marks socket as reconnected.
172
+
173
+ - **Params**: none.
174
+
175
+ - **Returns**: `Promise<void>` (rejects when browser is offline).
176
+
177
+ - **Usage**: Called repeatedly from `onSocketClose` interval loop.
178
+
179
+ 6. `handleConnectionLost(): void` (private)
180
+
181
+ - **Purpose**: Marks the connection as lost and dispatches a connection status event.
182
+
183
+ - **Params**: none.
184
+
185
+ - **Returns**: `void`.
186
+
187
+ - **Usage**: Scheduled by `onPing` via `reconnectingTimer` after inactivity.
188
+
189
+ 7. `handleRestoreFailed(): Promise<void>` (private)
190
+
191
+ - **Purpose**: Marks restore as failed, disables reconnect, emits failure state, and clears reconnect interval.
192
+
193
+ - **Params**: none.
194
+
195
+ - **Returns**: `Promise<void>`.
196
+
197
+ - **Usage**: Scheduled by `onPing` via `restoreTimer`.
198
+
199
+ 8. `clearTimerOnRestoreFailed(): Promise<void>` (private)
200
+
201
+ - **Purpose**: Stops active reconnect interval to avoid duplicate retries.
202
+
203
+ - **Params**: none.
204
+
205
+ - **Returns**: `Promise<void>`.
206
+
207
+ - **Usage**: Called from reconnect/failure paths whenever interval cleanup is needed.
208
+
209
+ 9. `updateConnectionData(): void` (private)
210
+
211
+ - **Purpose**: Resets transient connection flags (`isConnectionLost`, `isRestoreFailed`, `isSocketReconnected`) after recovery.
212
+
213
+ - **Params**: none.
214
+
215
+ - **Returns**: `void`.
216
+
217
+ - **Usage**: Called inside `onPing` before dispatching recovered state.
218
+
219
+ 10. `dispatchConnectionEvent(socketReconnected = false): void` (private)
220
+
221
+ - **Purpose**: Builds `ConnectionLostDetails`, forwards it to `WebSocketManager.handleConnectionLost`, and emits `'connectionLost'`.
222
+
223
+ - **Params**: `socketReconnected` - optional override used when reconnect is explicitly detected.
224
+
225
+ - **Returns**: `void`.
226
+
227
+ - **Usage**: Used by lost/recovered/restore-failed paths to publish uniform connection state.
228
+
229
+ ```typescript
230
+ type ConnectionLostDetails = {
231
+ isConnectionLost: boolean;
232
+ isRestoreFailed: boolean;
233
+ isSocketReconnected: boolean;
234
+ isKeepAlive: boolean;
235
+ };
236
+
237
+ connectionService.on('connectionLost', (details: ConnectionLostDetails) => {
238
+ if (details.isConnectionLost) {
239
+ // Connection lost — waiting for recovery
240
+ } else if (details.isRestoreFailed) {
241
+ // Recovery timeout (50 s) exceeded
242
+ } else if (details.isSocketReconnected) {
243
+ // Socket successfully reconnected
244
+ }
245
+ });
246
+ ```
247
+
248
+ ## Requires (dependencies)
249
+ - Webex SDK service catalog and authenticated request API
250
+ - Browser WebSocket, Worker, URL and network-status APIs
251
+ - LoggerProxy and log upload
252
+
253
+ ## Requirements
254
+ | ID | WHAT | WHY | Source Evidence | Test / Example Evidence | Assumptions / Gaps | Confidence |
255
+ |---|---|---|---|---|---|---|
256
+ | CORE-R-001 | WebexRequest must delegate service/resource/method/body options to the authenticated host request API and return or reject with the host result unchanged. | All Contact Center REST clients share host-owned authentication and service routing without duplicating credential logic. | `src/services/core/WebexRequest.ts` | `test/unit/spec/services/core/WebexRequest.ts` | Authorization-header masking belongs to `AqmReqs` HTTP-failure handling, not `WebexRequest.request`. | PRESENT |
257
+ | CORE-R-002 | `initWebSocket` requires `{body: SubscribeRequest, resource: string}` and resolves only after WebSocket welcome or rejects on register/connect failure. | Subscription resource selection and readiness are required for a valid realtime session. | `src/services/core/websocket/WebSocketManager.ts` | `test/unit/spec/services/core/websocket/WebSocketManager.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
258
+ | CORE-R-003 | AqmReqs must be constructed with the primary WebSocket manager and settle generated request promises from `notifSuccess`/`notifFail` binds or `TIMEOUT_REQ`. | HTTP acknowledgement alone does not represent backend operation completion. | `src/services/core/aqm-reqs.ts` | `test/unit/spec/services/core/aqm-reqs.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
259
+ | CORE-R-004 | ConnectionService must emit transport-state details and retry `initWebSocket({body, resource})`; ContactCenter owns relogin policy. | Separating transport detection from agent recovery prevents Core from mutating package-level session state. | `src/services/core/websocket/connection-service.ts` | `test/unit/spec/services/core/websocket/connection-service.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
260
+ | CORE-R-005 | The keepalive worker must use the configured 4-second interval and 16-second close-socket timeout; AQM defaults to 20 seconds unless disabled/overridden. | Accurate timing is required for predictable recovery and request failure behavior. | `src/services/core/constants.ts` | `test/unit/spec/services/core/websocket/WebSocketManager.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
261
+ | CORE-R-006 | Treat Core timeout, keepalive, and recovery constants as fixed behavior controls, not rollout flags; Core owns no feature-gate evaluation. | Conflating operational constants with rollout policy could disable transport or correlation paths unexpectedly. | `src/services/core/constants.ts`, `src/services/index.ts` | `test/unit/spec/services/core/websocket/WebSocketManager.ts` | None; rollout applicability is explicitly N/A for Core. | PRESENT |
262
+ | CORE-R-007 | When an AQM request sets `redactSensitiveLogs`, routing-failure and timeout logs must omit the request URL, bind key, response, and raw routing payload while preserving settlement and cleanup behavior. | Dynamic request paths and routing messages can contain participant identifiers or phone numbers that must not enter diagnostic logs. | `src/services/core/aqm-reqs.ts`, `src/services/core/types.ts` | `test/unit/spec/services/core/aqm-reqs.ts` | The flag is internal and opt-in; ordinary AQM logging remains backward compatible. | PRESENT |
263
+
264
+ ## Design Overview
265
+ Core separates four responsibilities:
266
+
267
+ 1. `WebexRequest` wraps the authenticated host request API and service-catalog routing.
268
+ 2. `WebSocketManager` registers a subscription using both `body` and `resource`, connects the socket, owns the keepalive worker, and emits raw messages/socket lifecycle events.
269
+ 3. `AqmReqs` registers bind matchers on the primary WebSocket, sends HTTP through WebexRequest, and settles requests only from matching notifications, HTTP failure, or timeout.
270
+ 4. `ConnectionService` observes message/socket liveness, emits connection-state details, and retries socket initialization. ContactCenter listens to those details and owns optional silent relogin.
271
+
272
+ ```typescript
273
+ const aqmReqs = new AqmReqs(webSocketManager);
274
+ const setState = aqmReqs.req((p: {data: Agent.StateChange}) => ({
275
+ host: WCC_API_GATEWAY,
276
+ url: '/v1/agents/session/state',
277
+ data: p.data,
278
+ method: HTTP_METHODS.PUT,
279
+ notifSuccess: {
280
+ bind: {
281
+ type: CC_EVENTS.AGENT_STATE_CHANGE,
282
+ data: {type: CC_EVENTS.AGENT_STATE_CHANGE_SUCCESS},
283
+ },
284
+ msg: {} as Agent.StateChangeSuccess,
285
+ },
286
+ notifFail: {
287
+ bind: {
288
+ type: CC_EVENTS.AGENT_STATE_CHANGE,
289
+ data: {type: CC_EVENTS.AGENT_STATE_CHANGE_FAILED},
290
+ },
291
+ errId: 'Service.aqm.agent.stateChange',
292
+ },
293
+ }));
294
+ await setState({data: stateChangePayload});
295
+ ```
296
+
297
+ `CLOSE_SOCKET_TIMEOUT` is 16000 ms. `CONNECTIVITY_CHECK_INTERVAL` drives reconnect attempts separately. `TIMEOUT_REQ` is the 20000 ms default AQM timeout; `WEBSOCKET_EVENT_TIMEOUT` is not the active AqmReqs default. A request configuration may set internal `redactSensitiveLogs: true`; this changes only routing-failure and timeout diagnostics, not correlation, errors, timing, or cleanup.
298
+
299
+ ## Data Flow
300
+ ```mermaid
301
+ flowchart LR
302
+ Service[Agent/contact/dialer request] --> AQM[AqmReqs generated function]
303
+ AQM --> Bind[Register success/failure bind matchers]
304
+ AQM --> WR[WebexRequest authenticated HTTP]
305
+ WR --> Backend[WCC backend]
306
+ Backend --> Ack[HTTP acknowledgement]
307
+ Backend --> WS[Primary WebSocket notification]
308
+ WS --> Match{Bind matches?}
309
+ Match -->|success| Resolve[Resolve typed response]
310
+ Match -->|failure| Reject[Reject structured error]
311
+ Bind -->|TIMEOUT_REQ| Reject
312
+ ```
313
+
314
+ ```mermaid
315
+ flowchart TD
316
+ Message[WebSocket message] --> WSM[WebSocketManager emits message]
317
+ WSM --> CS[ConnectionService resets liveness timers]
318
+ CS --> Lost{Lost/recovered state changed?}
319
+ Lost -->|yes| Emit[Emit connectionLost details]
320
+ Emit --> CC[ContactCenter recovery policy]
321
+ SocketClose[Socket close] --> Retry[Retry every CONNECTIVITY_CHECK_INTERVAL]
322
+ Retry --> Init[initWebSocket body + SUBSCRIBE_API resource]
323
+ ```
324
+
325
+ ## Sequence Diagram(s)
326
+ Sequence coverage:
327
+
328
+ | Operation group | Diagram | Failure / recovery coverage |
329
+ |---|---|---|
330
+ | Authenticated REST | WebexRequest | Host/service rejection is propagated unchanged; AQM applies its own error mapping separately. |
331
+ | WebSocket subscribe/connect | Subscribe and connect | Register/connect rejection and welcome resolution. |
332
+ | AQM operation | Correlated request | Duplicate pending request, HTTP failure, failure bind, and timeout reject. |
333
+ | Reconnect | Connection recovery | Offline attempts retry on the next interval; restored and restore-failed states are emitted to ContactCenter. |
334
+
335
+ ### WebexRequest
336
+
337
+ ```mermaid
338
+ sequenceDiagram
339
+ participant Caller
340
+ participant WR as WebexRequest
341
+ participant Host as webex.request
342
+ participant API as WCC backend
343
+ Caller->>WR: request(service, resource, method, body)
344
+ WR->>Host: authenticated request(options)
345
+ Host->>API: HTTP request
346
+ alt success
347
+ API-->>Host: response
348
+ Host-->>WR: status/body/headers
349
+ WR-->>Caller: response
350
+ else host/service rejection
351
+ API-->>Host: error
352
+ Host-->>WR: same rejection
353
+ WR-->>Caller: same rejection
354
+ end
355
+ ```
356
+
357
+ ### Subscribe and connect
358
+
359
+ ```mermaid
360
+ sequenceDiagram
361
+ participant Caller
362
+ participant WSM as WebSocketManager
363
+ participant Host as webex.request
364
+ participant WS as Browser WebSocket
365
+ Caller->>WSM: initWebSocket({body, resource})
366
+ WSM->>Host: register(body, resource)
367
+ Host-->>WSM: WebSocket URL/subscription
368
+ WSM->>WS: connect()
369
+ alt welcome
370
+ WS-->>WSM: Welcome event
371
+ WSM-->>Caller: WelcomeResponse
372
+ else register/connect failure
373
+ WSM-->>Caller: throw error
374
+ end
375
+ ```
376
+
377
+ ### Correlated request
378
+
379
+ ```mermaid
380
+ sequenceDiagram
381
+ participant Caller
382
+ participant AQM as AqmReqs
383
+ participant WR as WebexRequest
384
+ participant WS as Primary WebSocket
385
+ Caller->>AQM: generated request(payload)
386
+ AQM->>AQM: install notifSuccess/notifFail matchers
387
+ alt matching pending request already exists and timeout is enabled
388
+ AQM-->>Caller: Service.aqm.reqs.Pending
389
+ else request accepted
390
+ AQM->>WR: request(config)
391
+ WR-->>AQM: HTTP acknowledgement only
392
+ alt success bind
393
+ WS-->>AQM: matching success notification
394
+ AQM-->>Caller: typed result
395
+ else failure bind or HTTP rejection
396
+ AQM-->>Caller: structured error
397
+ else timeout
398
+ AQM-->>Caller: Service.aqm.reqs.Timeout
399
+ end
400
+ end
401
+ ```
402
+
403
+ ### Connection recovery
404
+
405
+ ```mermaid
406
+ sequenceDiagram
407
+ participant WSM as WebSocketManager
408
+ participant CS as ConnectionService
409
+ participant CC as ContactCenter
410
+ WSM-->>CS: socketClose/message events
411
+ CS->>CS: update timers and reconnect state
412
+ alt browser online during retry interval
413
+ CS->>WSM: initWebSocket({body: subscribeRequest, resource: SUBSCRIBE_API})
414
+ WSM-->>CS: welcome/message
415
+ CS-->>CC: connectionLost({isSocketReconnected: true})
416
+ CC->>CC: decide whether to silentRelogin()
417
+ else browser offline or reconnect fails
418
+ CS->>CS: retain interval; retry on next CONNECTIVITY_CHECK_INTERVAL
419
+ opt recovery timeout expires
420
+ CS-->>CC: connectionLost({isRestoreFailed: true})
421
+ end
422
+ end
423
+ ```
424
+
425
+ ## Class / Component Relationships
426
+ ```mermaid
427
+ classDiagram
428
+ class WebexRequest
429
+ class WebSocketManager
430
+ class AqmReqs
431
+ class ConnectionService
432
+ class ContactCenter
433
+ AqmReqs --> WebexRequest : authenticated HTTP
434
+ AqmReqs --> WebSocketManager : bind-matched completion
435
+ ConnectionService --> WebSocketManager : liveness + reconnect
436
+ ConnectionService --> ContactCenter : connectionLost details
437
+ ContactCenter --> WebSocketManager : registration lifecycle
438
+ ```
439
+
440
+ ## Use Cases
441
+ - **UC-1 Authenticated REST:** pass the service key and request options to the host and return its response or rejection unchanged. Evidence: `src/services/core/WebexRequest.ts`, `test/unit/spec/services/core/WebexRequest.ts`.
442
+ - **UC-2 Subscribe/connect:** register with `{body, resource}`, connect, and wait for welcome. Evidence: `src/services/core/websocket/WebSocketManager.ts`, `test/unit/spec/services/core/websocket/WebSocketManager.ts`.
443
+ - **UC-3 AQM correlation:** send HTTP but settle on matching notification/failure/timeout. Evidence: `src/services/core/aqm-reqs.ts`, `test/unit/spec/services/core/aqm-reqs.ts`.
444
+ - **UC-4 Reconnect:** retry socket initialization and emit state for ContactCenter-owned recovery. Evidence: `src/services/core/websocket/connection-service.ts`, `test/unit/spec/services/core/websocket/connection-service.ts`.
445
+
446
+ ## State Model
447
+ WebSocketManager owns socket/welcome/worker state. AqmReqs owns pending success/failure/cancel bind maps until settlement or timeout. ConnectionService owns liveness/reconnect timers and flags, then emits state details. It does not own agent credentials, profile, or silent relogin.
448
+
449
+ ## Business Rules & Invariants
450
+ - Core must preserve its typed public/event contracts and must not invent backend states or responses. Enforced in `src/services/core/WebexRequest.ts`.
451
+ - Rollout applicability is N/A for Core: keepalive, timeout, and reconnect constants control behavior, while Services constructs Core without a feature gate.
452
+
453
+ ## Concurrency & Reactive Flow
454
+ The primary WebSocket fans messages to independent AqmReqs, ContactCenter, TaskManager, and ConnectionService listeners. AqmReqs clears all correlated bind entries on settlement. The keepalive worker posts status every 4000 ms and may request closure after 16000 ms offline; reconnect attempts use their separate interval. Listener registration/removal must preserve identity.
455
+
456
+ ## State Machine
457
+ ```mermaid
458
+ stateDiagram-v2
459
+ [*] --> SocketClosed
460
+ SocketClosed --> Connecting: initWebSocket(body, resource)
461
+ Connecting --> Connected: welcome
462
+ Connecting --> SocketClosed: register/connect error
463
+ Connected --> ConnectionSuspect: liveness timer expires
464
+ ConnectionSuspect --> Reconnecting: socket close / retry
465
+ Reconnecting --> Connected: reconnect + message
466
+ Reconnecting --> Reconnecting: offline or retry failure
467
+ Connected --> SocketClosed: manual close
468
+ ```
469
+
470
+ ## Protocol / Wire Format
471
+ `WebSocketManager.initWebSocket` accepts `{body: SubscribeRequest, resource: string}`. Subscription uses the host Webex request API; AqmReqs operational HTTP uses the WebexRequest wrapper. AQM request configs carry `host`, `url`, optional `method`/`data`, `notifSuccess.bind`, optional `notifFail.bind`, optional cancel bind, and optional timeout. HTTP acknowledgement never substitutes for the matching WebSocket operation result.
472
+
473
+ ## Error Handling & Failure Modes
474
+ | Condition | Signal (error/code/result) | Caller recovery |
475
+ |---|---|---|
476
+ | Dependency rejection | Typed/rethrown error or failure event | Inspect structured details, preserve tracking id, and retry only when the operation is safe. |
477
+ | Timeout or missing async completion | Timeout/recovery state | Follow the module-specific recovery path; never synthesize success. |
478
+
479
+ Standard error handler for SDK operations:
480
+
481
+ ```typescript
482
+ import {getErrorDetails} from './services/core/Utils';
483
+
484
+ try {
485
+ await operation();
486
+ } catch (error) {
487
+ const {error: detailedError, reason} = getErrorDetails(
488
+ error,
489
+ 'methodName', // Method name for logging
490
+ 'ModuleName' // Module name for logging
491
+ );
492
+
493
+ // getErrorDetails automatically:
494
+ // 1. Logs the error
495
+ // 2. Uploads logs (unless AGENT_NOT_FOUND in silentRelogin)
496
+ // 3. Extracts reason from error.details
497
+ // 4. Creates Error with reason as message
498
+
499
+ throw detailedError;
500
+ }
501
+ ```
502
+
503
+ Error handler for task operations:
504
+
505
+ ```typescript
506
+ import {generateTaskErrorObject} from './services/core/Utils';
507
+
508
+ try {
509
+ await taskOperation();
510
+ } catch (error) {
511
+ const taskError = generateTaskErrorObject(
512
+ error,
513
+ 'transfer',
514
+ 'TaskModule'
515
+ );
516
+ throw taskError;
517
+ }
518
+ ```
519
+
520
+ A specific `Msg<T>` for failure responses. Access error details via `failure.data`:
521
+
522
+ ```typescript
523
+ export type Failure = Msg<{
524
+ agentId: string;
525
+ trackingId: string;
526
+ reasonCode: number;
527
+ orgId: string;
528
+ reason: string;
529
+ }>;
530
+
531
+ // Usage in catch
532
+ const failure = error.details as Failure;
533
+ LoggerProxy.error(`Operation failed: ${failure.data?.reason}`, {
534
+ module: 'MyService',
535
+ method: 'myMethod',
536
+ trackingId: failure?.trackingId,
537
+ });
538
+ ```
539
+
540
+ Error interface with a flexible data field for additional context:
541
+
542
+ ```typescript
543
+ export interface AugmentedError extends Error {
544
+ data?: Record<string, any>;
545
+ }
546
+ ```
547
+
548
+ ```typescript
549
+ import * as Err from './Err';
550
+
551
+ const error = new Err.Details('Service.aqm.agent.login', {
552
+ status: 401,
553
+ type: 'UNAUTHORIZED',
554
+ trackingId: 'uuid',
555
+ });
556
+ ```
557
+
558
+ ```typescript
559
+ import {createErrDetailsObject} from './Utils';
560
+
561
+ const errDetails = createErrDetailsObject(webexRequestPayload);
562
+ // Returns Err.Details with trackingId and body
563
+ ```
564
+
565
+ ```typescript
566
+ // Correct
567
+ const {error: detailedError} = getErrorDetails(error, method, module);
568
+ throw detailedError;
569
+
570
+ // Wrong - loses context
571
+ throw error;
572
+ ```
573
+
574
+ This section documents shared error helpers in `Utils.ts` that normalize errors, enrich them with context, and ensure consistent logging/upload behavior across services.
575
+
576
+ ```typescript
577
+ // Msg - Generic message interface (GlobalTypes.ts)
578
+ export type Msg<T = any> = {
579
+ type: string;
580
+ orgId: string;
581
+ trackingId: string;
582
+ data: T;
583
+ };
584
+
585
+ // Failure - Backend error structure (GlobalTypes.ts)
586
+ // Built on Msg<T> with specific error data fields
587
+ export type Failure = Msg<{
588
+ agentId: string;
589
+ trackingId: string;
590
+ reasonCode: number;
591
+ orgId: string;
592
+ reason: string;
593
+ }>;
594
+
595
+ // AugmentedError - Extended Error with flexible data field (GlobalTypes.ts)
596
+ export interface AugmentedError extends Error {
597
+ data?: Record<string, any>;
598
+ }
599
+ ```
600
+
601
+ ```mermaid
602
+ flowchart TD
603
+ A[Error caught] --> B[Cast error.details to Failure]
604
+ B --> C[Extract reason from failure.data.reason]
605
+ C --> D{Is silentRelogin + AGENT_NOT_FOUND?}
606
+ D -->|Yes| E[Skip logging/upload]
607
+ D -->|No| F[Log error with LoggerProxy]
608
+ F --> G[Upload logs via WebexRequest]
609
+ G --> H[Check if stationLogin]
610
+ H -->|Yes| I[Get field-specific error data]
611
+ H -->|No| J[Use generic error]
612
+ I --> K[Create Error with data property]
613
+ J --> K
614
+ K --> L["Return {error, reason}"]
615
+ ```
616
+
617
+ Use this helper for agent/config-style flows where backend failure payloads are transformed into a user-facing `Error` plus `reason`, with optional station-login field metadata.
618
+
619
+ ```typescript
620
+ export const getErrorDetails = (error: any, methodName: string, moduleName: string) => {
621
+ let errData = {message: '', fieldName: ''};
622
+
623
+ const failure = error.details as Failure;
624
+ const reason = failure?.data?.reason ?? `Error while performing ${methodName}`;
625
+
626
+ // Log error (unless AGENT_NOT_FOUND in silentRelogin)
627
+ if (!(reason === 'AGENT_NOT_FOUND' && methodName === 'silentRelogin')) {
628
+ LoggerProxy.error(`${methodName} failed with reason: ${reason}`, {
629
+ module: moduleName,
630
+ method: methodName,
631
+ trackingId: failure?.trackingId,
632
+ });
633
+
634
+ // Upload logs
635
+ WebexRequest.getInstance().uploadLogs({
636
+ correlationId: failure?.trackingId,
637
+ });
638
+ }
639
+
640
+ // For stationLogin, extract field-specific error data (message + fieldName)
641
+ if (methodName === 'stationLogin') {
642
+ errData = getStationLoginErrorData(failure, error.loginOption);
643
+ }
644
+
645
+ const err = new Error(reason);
646
+ // @ts-ignore - custom property for backward compatibility
647
+ err.data = errData;
648
+
649
+ return {error: err, reason};
650
+ };
651
+ ```
652
+
653
+ Use this helper for task/interaction flows where richer task error metadata (`errorType`, `errorData`, `reasonCode`, `trackingId`) is required on the returned `AugmentedError`.
654
+
655
+ ```typescript
656
+ export const generateTaskErrorObject = (
657
+ error: any,
658
+ methodName: string,
659
+ moduleName: string
660
+ ): AugmentedError => {
661
+ const trackingId = error?.details?.trackingId || error?.trackingId || '';
662
+ const errorMsg = error?.details?.msg;
663
+
664
+ const errorMessage = errorMsg?.errorMessage || error.message || 'Error';
665
+ const errorType = errorMsg?.errorType || error.name || 'Unknown Error';
666
+ const errorData = errorMsg?.errorData || '';
667
+ const reasonCode = errorMsg?.reasonCode || 0;
668
+
669
+ LoggerProxy.error(`${methodName} failed: ${errorMessage} (${errorType})`, {
670
+ module: moduleName,
671
+ method: methodName,
672
+ trackingId,
673
+ });
674
+ WebexRequest.getInstance().uploadLogs({correlationId: trackingId});
675
+
676
+ const reason = `${errorType}: ${errorMessage}${errorData ? ` (${errorData})` : ''}`;
677
+ const err: AugmentedError = new Error(reason);
678
+ err.data = {
679
+ message: errorMessage,
680
+ errorType,
681
+ errorData,
682
+ reasonCode,
683
+ trackingId,
684
+ };
685
+
686
+ return err;
687
+ };
688
+ ```
689
+
690
+ ```typescript
691
+ // Use getErrorDetails for:
692
+ // - Agent service operations
693
+ // - Station login/logout flows
694
+ //
695
+ // Use generateTaskErrorObject for:
696
+ // - Task service operations
697
+ // - Interaction-related errors
698
+ ```
699
+
700
+ **Cause**: Subscribe API failed or invalid URL
701
+
702
+ **Solution**: Check subscribe response and WebSocket URL
703
+
704
+ **Cause**: Event listener not registered
705
+
706
+ **Solution**: Ensure `on('message', handler)` called before connect
707
+
708
+ **Cause**: Keepalive not enabled or network issues
709
+
710
+ **Solution**: Verify worker-driven keepalive is running after socket `onopen`, and check network/offline transitions
711
+
712
+ ## Pitfalls
713
+ - `initWebSocket` requires both `body` and `resource`; omitting `resource` registers against no durable subscription endpoint.
714
+ - AqmReqs installs notification binds before HTTP and never resolves from acknowledgement; duplicate binds, timeout, and cleanup ordering are correctness-critical.
715
+ - Sensitive AQM configurations must use the opt-in redaction flag so dynamic URLs and raw routing messages are not included in timeout/failure logs.
716
+ - Keepalive closure (16 seconds), lost-connection detection (8 seconds), reconnect interval (5 seconds), and recovery timeout (50 seconds) are separate controls and must not be conflated.
717
+
718
+ ## Module Do's / Don'ts
719
+ - DO keep authentication and service resolution in the host Webex request layer; `WebexRequest.request` is a thin delegating wrapper.
720
+ - DO mask authorization headers in the `AqmReqs` HTTP-error/timeout paths before those details are logged or surfaced.
721
+ - DO enable `redactSensitiveLogs` for AQM requests whose dynamic URL or event payload can contain identity/PII.
722
+ - DO clear success/failure/cancel bind entries together when an AQM request settles.
723
+ - DON'T move silent-relogin policy into ConnectionService; it emits transport state only.
724
+ - DON'T treat timeout constants as feature flags or reuse one timer for another lifecycle purpose.
725
+
726
+ ```typescript
727
+ const response = await webexReq.request({...});
728
+
729
+ if (response.statusCode !== 200) {
730
+ throw new Error(`API call failed with ${response.statusCode}`);
731
+ }
732
+ ```
733
+
734
+ ```typescript
735
+ const trackingId = response.headers?.trackingid ||
736
+ response.headers?.TrackingID;
737
+ ```
738
+
739
+ ## Key Design Trade-off
740
+ - Request initiation stays HTTP while completion can arrive asynchronously over WebSocket; explicit timers and correlation preserve backend fidelity but increase lifecycle complexity.
741
+
742
+ ## Test-Case Strategy (module)
743
+ Unit tests mirror module paths under `test/unit/spec/services/core`. Preserve positive and negative paths, event ordering, timeout/recovery behavior, and the package's 85% global branch/function/line/statement threshold.
744
+
745
+ | Behavior / Requirement | Existing test evidence | Gap |
746
+ |---|---|---|
747
+ | `CORE-R-001` | `test/unit/spec/services/core/WebexRequest.ts` | None. |
748
+ | `CORE-R-002` | `test/unit/spec/services/core/websocket/WebSocketManager.ts` | None. |
749
+ | `CORE-R-003` | `test/unit/spec/services/core/aqm-reqs.ts` | None. |
750
+ | `CORE-R-004` | `test/unit/spec/services/core/websocket/connection-service.ts` | None. |
751
+ | `CORE-R-005` | `test/unit/spec/services/core/websocket/WebSocketManager.ts` | Keep timer-value assertions synchronized with constants. |
752
+ | `CORE-R-006` | `test/unit/spec/services/core/websocket/WebSocketManager.ts` | Feature-gate absence is verified from construction/source rather than a dedicated negative test. |
753
+ | `CORE-R-007` | `test/unit/spec/services/core/aqm-reqs.ts` | None. |
754
+
755
+ ## Traceability
756
+ - Repo architecture: `../../../../ai-docs/ARCHITECTURE.md` · Registry: `../../../../ai-docs/SPEC_INDEX.md`
757
+ - Coverage state and contracts baseline: `../../../../.sdd/manifest.json`
758
+
759
+ - [Root Orchestrator AGENTS.md](../../../../AGENTS.md) - Task routing, critical rules, cross-service patterns
760
+
761
+ - [WebSocketManager.ts](../websocket/WebSocketManager.ts)
762
+
763
+ - [WebexRequest.ts](../WebexRequest.ts)
764
+
765
+ - [Utils.ts](../Utils.ts)
766
+
767
+ - [GlobalTypes.ts](../GlobalTypes.ts)
768
+
769
+ - [Root Orchestrator AGENTS.md](../../../../AGENTS.md) — Task routing, critical rules, cross-service patterns
770
+
771
+ - [WebSocketManager.ts](../websocket/WebSocketManager.ts) — WebSocket lifecycle, keepalive worker integration
772
+
773
+ - [connection-service.ts](../websocket/connection-service.ts) — Reconnection logic, connection state events
774
+
775
+ - [keepalive.worker.js](../websocket/keepalive.worker.js) — Web Worker for periodic keepalive and offline detection
776
+
777
+ - [WebexRequest.ts](../WebexRequest.ts) — Singleton HTTP request handler
778
+
779
+ - [Utils.ts](../Utils.ts) — `getErrorDetails`, `generateTaskErrorObject`, consult utilities
780
+
781
+ - [Err.ts](../Err.ts) — `Err.Message` and `Err.Details` error classes
782
+
783
+ - [aqm-reqs.ts](../aqm-reqs.ts) — AQM request/response pattern, WebSocket notification binding
784
+
785
+ - [GlobalTypes.ts](../GlobalTypes.ts) — `Msg`, `Failure`, `AugmentedError` type definitions
786
+
787
+ - [types.ts](../types.ts) — `Pending`, `Req`, `Conf`, `Res` types for AqmReqs