@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,113 @@
1
+ import WxAppTelephonyMercurySync, {
2
+ TELEPHONY_CALL_MUTED,
3
+ TELEPHONY_CALL_UNMUTED,
4
+ } from '../../../../src/services/WxAppTelephonyMercurySync';
5
+
6
+ describe('WxAppTelephonyMercurySync', () => {
7
+ const agentId = 'agent-123';
8
+ let mercury: {on: jest.Mock; off: jest.Mock};
9
+ let webex: {internal: {mercury?: typeof mercury}};
10
+ let sync: WxAppTelephonyMercurySync;
11
+ let onMuteChange: jest.Mock;
12
+
13
+ beforeEach(() => {
14
+ mercury = {on: jest.fn(), off: jest.fn()};
15
+ webex = {internal: {mercury}};
16
+ sync = new WxAppTelephonyMercurySync(webex as never);
17
+ onMuteChange = jest.fn();
18
+ });
19
+
20
+ afterEach(() => {
21
+ sync.unsubscribe();
22
+ });
23
+
24
+ it('subscribes to muted and unmuted Mercury events', () => {
25
+ sync.subscribe(agentId, onMuteChange);
26
+
27
+ expect(mercury.on).toHaveBeenCalledWith(TELEPHONY_CALL_MUTED, expect.any(Function));
28
+ expect(mercury.on).toHaveBeenCalledWith(TELEPHONY_CALL_UNMUTED, expect.any(Function));
29
+ expect(sync.isSubscribed()).toBe(true);
30
+ });
31
+
32
+ it('invokes callback with decoded callId and muted when actorId matches agent', () => {
33
+ const callId = 'prefix:call-half-1';
34
+ const encodedCallId = btoa(callId);
35
+ const encodedActorId = btoa(`some-prefix-${agentId}`);
36
+
37
+ sync.subscribe(agentId, onMuteChange);
38
+ const muteHandler = mercury.on.mock.calls.find(([event]) => event === TELEPHONY_CALL_MUTED)![1];
39
+ muteHandler({data: {actorId: encodedActorId, callId: encodedCallId, muted: true}});
40
+
41
+ expect(onMuteChange).toHaveBeenCalledWith(callId, true);
42
+ });
43
+
44
+ it('ignores events when decoded actorId does not end with agentId', () => {
45
+ sync.subscribe(agentId, onMuteChange);
46
+ const muteHandler = mercury.on.mock.calls.find(([event]) => event === TELEPHONY_CALL_MUTED)![1];
47
+ muteHandler({data: {actorId: btoa('other-agent'), callId: btoa('call-1'), muted: true}});
48
+
49
+ expect(onMuteChange).not.toHaveBeenCalled();
50
+ });
51
+
52
+ it('ignores events with missing payload fields', () => {
53
+ sync.subscribe(agentId, onMuteChange);
54
+ const muteHandler = mercury.on.mock.calls.find(([event]) => event === TELEPHONY_CALL_MUTED)![1];
55
+ muteHandler({data: {actorId: btoa(agentId), callId: btoa('call-1')}});
56
+
57
+ expect(onMuteChange).not.toHaveBeenCalled();
58
+ });
59
+
60
+ it('unsubscribes and removes Mercury listeners', () => {
61
+ sync.subscribe(agentId, onMuteChange);
62
+ const muteHandler = mercury.on.mock.calls.find(([event]) => event === TELEPHONY_CALL_MUTED)![1];
63
+ const unmuteHandler = mercury.on.mock.calls.find(
64
+ ([event]) => event === TELEPHONY_CALL_UNMUTED
65
+ )![1];
66
+
67
+ sync.unsubscribe();
68
+
69
+ expect(mercury.off).toHaveBeenCalledWith(TELEPHONY_CALL_MUTED, muteHandler);
70
+ expect(mercury.off).toHaveBeenCalledWith(TELEPHONY_CALL_UNMUTED, unmuteHandler);
71
+ expect(sync.isSubscribed()).toBe(false);
72
+ });
73
+
74
+ it('does not subscribe when mercury is unavailable', () => {
75
+ sync = new WxAppTelephonyMercurySync({internal: {}} as never);
76
+ sync.subscribe(agentId, onMuteChange);
77
+
78
+ expect(sync.isSubscribed()).toBe(false);
79
+ expect(onMuteChange).not.toHaveBeenCalled();
80
+ });
81
+
82
+ it('invokes callback with muted false on unmuted Mercury event', () => {
83
+ const callId = 'prefix:call-half-1';
84
+ const encodedCallId = btoa(callId);
85
+ const encodedActorId = btoa(`some-prefix-${agentId}`);
86
+
87
+ sync.subscribe(agentId, onMuteChange);
88
+ const unmuteHandler = mercury.on.mock.calls.find(
89
+ ([event]) => event === TELEPHONY_CALL_UNMUTED
90
+ )![1];
91
+ unmuteHandler({data: {actorId: encodedActorId, callId: encodedCallId, muted: false}});
92
+
93
+ expect(onMuteChange).toHaveBeenCalledWith(callId, false);
94
+ });
95
+
96
+ it('resubscribe replaces previous Mercury listeners', () => {
97
+ sync.subscribe(agentId, onMuteChange);
98
+ const firstMuteHandler = mercury.on.mock.calls.find(
99
+ ([event]) => event === TELEPHONY_CALL_MUTED
100
+ )![1];
101
+ const firstUnmuteHandler = mercury.on.mock.calls.find(
102
+ ([event]) => event === TELEPHONY_CALL_UNMUTED
103
+ )![1];
104
+ expect(mercury.on).toHaveBeenCalledTimes(2);
105
+
106
+ const secondHandler = jest.fn();
107
+ sync.subscribe(agentId, secondHandler);
108
+
109
+ expect(mercury.off).toHaveBeenCalledWith(TELEPHONY_CALL_MUTED, firstMuteHandler);
110
+ expect(mercury.off).toHaveBeenCalledWith(TELEPHONY_CALL_UNMUTED, firstUnmuteHandler);
111
+ expect(mercury.on).toHaveBeenCalledTimes(4);
112
+ });
113
+ });
@@ -0,0 +1,85 @@
1
+ import {parseAgentConfigs} from '../../../../../src/services/config/Util';
2
+ import {AuxCode, DesktopProfileResponse} from '../../../../../src/services/config/types';
3
+
4
+ const baseAgentProfile: DesktopProfileResponse = {
5
+ timeoutDesktopInactivityCustomEnabled: false,
6
+ timeoutDesktopInactivityMins: 10,
7
+ accessWrapUpCode: 'ALL',
8
+ wrapUpCodes: [],
9
+ accessIdleCode: 'ALL',
10
+ idleCodes: [],
11
+ autoWrapUp: false,
12
+ autoWrapAfterSeconds: 30,
13
+ lastAgentRouting: false,
14
+ allowAutoWrapUpExtension: false,
15
+ outdialEnabled: true,
16
+ dialPlanEnabled: false,
17
+ agentAvailableAfterOutdial: true,
18
+ outdialEntryPointId: 'ep-1',
19
+ consultToQueue: false,
20
+ viewableStatistics: {agentStats: false},
21
+ addressBookId: 'ab-1',
22
+ outdialANIId: 'ani-1',
23
+ loginVoiceOptions: [],
24
+ dialPlans: [],
25
+ agentDNValidation: 'PROVISIONED_VALUE',
26
+ accessQueue: 'SPECIFIC',
27
+ accessEntryPoint: 'NONE',
28
+ accessBuddyTeam: 'ALL',
29
+ } as DesktopProfileResponse;
30
+
31
+ const baseProfileData = {
32
+ userData: {
33
+ ciUserId: 'agent-1',
34
+ firstName: 'Jane',
35
+ lastName: 'Agent',
36
+ email: 'jane@example.com',
37
+ agentProfileId: 'profile-1',
38
+ skillProfileId: 'skill-1',
39
+ siteId: 'site-1',
40
+ dbId: 'db-1',
41
+ deafultDialledNumber: '+15551234567',
42
+ id: 'user-1',
43
+ teamIds: ['team-1'],
44
+ },
45
+ teamData: [{id: 'team-1', name: 'Support'}],
46
+ tenantData: {
47
+ timeoutDesktopInactivityEnabled: false,
48
+ timeoutDesktopInactivityMins: 15,
49
+ forceDefaultDn: false,
50
+ dnDefaultRegex: '',
51
+ dnOtherRegex: '',
52
+ outdialEnabled: true,
53
+ endCallEnabled: true,
54
+ endConsultEnabled: true,
55
+ callVariablesSuppressed: false,
56
+ privacyShieldVisible: false,
57
+ },
58
+ orgInfoData: {
59
+ tenantId: 'tenant-1',
60
+ timezone: 'UTC',
61
+ environment: 'produs1',
62
+ },
63
+ auxCodes: [] as AuxCode[],
64
+ orgSettingsData: {
65
+ campaignManagerEnabled: false,
66
+ webRtcEnabled: true,
67
+ maskSensitiveData: false,
68
+ },
69
+ agentProfileData: baseAgentProfile,
70
+ dialPlanData: [],
71
+ urlMapping: [],
72
+ multimediaProfileId: 'mm-1',
73
+ aiFeatureFlags: {data: []},
74
+ };
75
+
76
+ describe('parseAgentConfigs collaboration access fields', () => {
77
+ it('maps Desktop Profile collaboration access flags onto Profile', () => {
78
+ const profile = parseAgentConfigs(baseProfileData);
79
+
80
+ expect(profile.allowConsultToQueue).toBe(false);
81
+ expect(profile.accessQueue).toBe('SPECIFIC');
82
+ expect(profile.accessEntryPoint).toBe('NONE');
83
+ expect(profile.accessBuddyTeam).toBe('ALL');
84
+ });
85
+ });
@@ -66,7 +66,6 @@ describe('AgentConfigService', () => {
66
66
  method: 'GET',
67
67
  });
68
68
  expect(result).toEqual(mockResponse.body);
69
-
70
69
  expect(LoggerProxy.info).toHaveBeenCalledWith('Fetching user data using CI', {
71
70
  module: CONFIG_FILE_NAME,
72
71
  method: 'getUserUsingCI',
@@ -124,7 +123,6 @@ describe('AgentConfigService', () => {
124
123
  method: 'GET',
125
124
  });
126
125
  expect(result).toEqual(mockResponse.body);
127
-
128
126
  expect(LoggerProxy.info).toHaveBeenCalledWith('Fetching desktop profile', {
129
127
  module: CONFIG_FILE_NAME,
130
128
  method: 'getDesktopProfileById',
@@ -183,7 +181,6 @@ describe('AgentConfigService', () => {
183
181
  method: 'GET',
184
182
  });
185
183
  expect(result).toEqual(mockResponse.body);
186
-
187
184
  expect(LoggerProxy.info).toHaveBeenCalledWith('Fetching list of teams', {
188
185
  module: CONFIG_FILE_NAME,
189
186
  method: 'getListOfTeams',
@@ -263,11 +260,10 @@ describe('AgentConfigService', () => {
263
260
 
264
261
  expect(mockWebexRequest.request).toHaveBeenCalledWith({
265
262
  service: mockWccAPIURL,
266
- resource: `organization/${mockOrgId}/v2/auxiliary-code?page=${page}&pageSize=${pageSize}&filter=id=in=(${filter})&attributes=${attributes}`,
263
+ resource: `organization/${mockOrgId}/v2/auxiliary-code?page=${page}&pageSize=${pageSize}&filter=id=in=(${filter})&attributes=${attributes}&desktopProfileFilter=true`,
267
264
  method: 'GET',
268
265
  });
269
266
  expect(result).toEqual(mockResponse.body);
270
-
271
267
  expect(LoggerProxy.info).toHaveBeenCalledWith('Fetching list of aux codes', {
272
268
  module: CONFIG_FILE_NAME,
273
269
  method: 'getListOfAuxCodes',
@@ -490,6 +486,49 @@ describe('AgentConfigService', () => {
490
486
  });
491
487
  });
492
488
 
489
+ describe('getAIFeatureFlags', () => {
490
+ it('should return AI feature flags successfully', async () => {
491
+ const mockResponse = {
492
+ statusCode: 200,
493
+ body: {
494
+ data: [{realtimeTranscripts: {enable: true}}],
495
+ },
496
+ };
497
+ mockWebexRequest.request.mockResolvedValue(mockResponse);
498
+
499
+ const result = await agentConfigService.getAIFeatureFlags(mockOrgId);
500
+ expect(result).toEqual(mockResponse.body);
501
+ expect(LoggerProxy.log).toHaveBeenCalledWith('getAIFeatureFlags api success.', {
502
+ module: CONFIG_FILE_NAME,
503
+ method: 'getAIFeatureFlags',
504
+ });
505
+ });
506
+
507
+ it('should throw an error if API call returns non-200 status code', async () => {
508
+ const mockError = {statusCode: 500};
509
+ mockWebexRequest.request.mockResolvedValue(mockError);
510
+
511
+ await expect(agentConfigService.getAIFeatureFlags(mockOrgId)).rejects.toThrow(
512
+ 'API call failed with 500'
513
+ );
514
+ expect(LoggerProxy.error).toHaveBeenCalledWith(
515
+ 'getAIFeatureFlags API call failed with Error: API call failed with 500',
516
+ {module: CONFIG_FILE_NAME, method: 'getAIFeatureFlags'}
517
+ );
518
+ });
519
+
520
+ it('should handle network errors gracefully', async () => {
521
+ const networkError = new Error('Network Error');
522
+ mockWebexRequest.request.mockRejectedValue(networkError);
523
+
524
+ await expect(agentConfigService.getAIFeatureFlags(mockOrgId)).rejects.toThrow('Network Error');
525
+ expect(LoggerProxy.error).toHaveBeenCalledWith(
526
+ 'getAIFeatureFlags API call failed with Error: Network Error',
527
+ {module: CONFIG_FILE_NAME, method: 'getAIFeatureFlags'}
528
+ );
529
+ });
530
+ });
531
+
493
532
  describe(`getDialPlanData`, () => {
494
533
  it('should return dial plan data successfully', async () => {
495
534
  const mockResponse = {statusCode: 200, body: {data: {}}}; // Adjust data accordingly
@@ -667,6 +706,32 @@ describe('AgentConfigService', () => {
667
706
  });
668
707
 
669
708
  describe('getAgentConfig', () => {
709
+ const mockTeamData = [
710
+ {id: 'team1', name: 'Support Team'},
711
+ {id: 'team2', name: 'Sales Team'},
712
+ ];
713
+
714
+ const mockOrgInfo = {
715
+ tenantId: 'tenant123',
716
+ timezone: 'GMT',
717
+ environment: 'produs1',
718
+ };
719
+
720
+ const mockSiteInfo = {
721
+ id: 'c6a5451f-5ba7-49a1-aee8-fbef70c19ece',
722
+ name: 'Site-1',
723
+ multimediaProfileId: 'c5888e6f-5661-4871-9936-cbcec7658d41',
724
+ };
725
+
726
+ const mockURLMapping = [
727
+ {key: 'ACQUEON_API_URL', url: 'https://api.example.com'},
728
+ {key: 'ACQUEON_CONSOLE_URL', url: 'https://console.example.com'},
729
+ ];
730
+
731
+ const mockAIFeatureFlags = {
732
+ data: [{realtimeTranscripts: {enable: true}}],
733
+ };
734
+
670
735
  beforeEach(() => {
671
736
  jest.clearAllMocks();
672
737
  });
@@ -681,7 +746,7 @@ describe('AgentConfigService', () => {
681
746
  agentProfileId: 'profile123',
682
747
  siteId: 'site789',
683
748
  dbId: 'db123',
684
- defaultDialledNumber: '1234567890',
749
+ deafultDialledNumber: '1234567890',
685
750
  id: 'user001',
686
751
  teamIds: ['team1', 'team2'],
687
752
  };
@@ -718,6 +783,7 @@ describe('AgentConfigService', () => {
718
783
  const mockOrgInfo = {
719
784
  tenantId: 'tenant123',
720
785
  timezone: 'GMT',
786
+ environment: 'produs1',
721
787
  };
722
788
 
723
789
  const mockOrgSettings = {
@@ -726,12 +792,6 @@ describe('AgentConfigService', () => {
726
792
  maskSensitiveData: false,
727
793
  };
728
794
 
729
- const mockSiteInfo = {
730
- id: 'c6a5451f-5ba7-49a1-aee8-fbef70c19ece',
731
- name: 'Site-1',
732
- multimediaProfileId: 'c5888e6f-5661-4871-9936-cbcec7658d41',
733
- };
734
-
735
795
  const mockTenantData = {
736
796
  timeoutDesktopInactivityEnabled: false,
737
797
  timeoutDesktopInactivityMins: 15,
@@ -745,15 +805,13 @@ describe('AgentConfigService', () => {
745
805
  callVariablesSuppressed: false,
746
806
  };
747
807
 
748
- const mockURLMapping = [
749
- {key: 'ACQUEON_API_URL', url: 'https://api.example.com'},
750
- {key: 'ACQUEON_CONSOLE_URL', url: 'https://console.example.com'},
751
- ];
752
-
753
808
  const mockAuxCodes = [
754
809
  {id: 'aux1', type: 'WRAP_UP_CODE', name: 'Wrap Up Code 1', isDefault: true},
755
810
  {id: 'aux2', type: 'IDLE_CODE', name: 'Idle Code 1', isDefault: true},
756
811
  ];
812
+ const mockAIFeatureFlags = {
813
+ data: [{realtimeTranscripts: {enable: true}}],
814
+ };
757
815
 
758
816
  const parseAgentConfigsSpy = jest.spyOn(util, 'parseAgentConfigs');
759
817
  agentConfigService.getUserUsingCI = jest.fn().mockResolvedValue(mockUserConfig);
@@ -762,6 +820,7 @@ describe('AgentConfigService', () => {
762
820
  agentConfigService.getSiteInfo = jest.fn().mockResolvedValue(mockSiteInfo);
763
821
  agentConfigService.getTenantData = jest.fn().mockResolvedValue(mockTenantData);
764
822
  agentConfigService.getURLMapping = jest.fn().mockResolvedValue(mockURLMapping);
823
+ agentConfigService.getAIFeatureFlags = jest.fn().mockResolvedValue(mockAIFeatureFlags);
765
824
  agentConfigService.getAllAuxCodes = jest.fn().mockResolvedValue(mockAuxCodes);
766
825
  agentConfigService.getDesktopProfileById = jest.fn().mockResolvedValue(mockAgentProfile);
767
826
  agentConfigService.getDialPlanData = jest.fn().mockResolvedValue(mockDialPlanData);
@@ -801,6 +860,7 @@ describe('AgentConfigService', () => {
801
860
  dialPlanData: mockDialPlanData,
802
861
  urlMapping: mockURLMapping,
803
862
  multimediaProfileId: mockSiteInfo.multimediaProfileId,
863
+ aiFeatureFlags: mockAIFeatureFlags,
804
864
  });
805
865
  });
806
866
 
@@ -815,7 +875,7 @@ describe('AgentConfigService', () => {
815
875
  skillProfileId: 'skillProfile456',
816
876
  siteId: 'site789',
817
877
  dbId: 'db123',
818
- defaultDialledNumber: '1234567890',
878
+ deafultDialledNumber: '1234567890',
819
879
  id: 'user001',
820
880
  teamIds: ['team1', 'team2'],
821
881
  };
@@ -857,6 +917,7 @@ describe('AgentConfigService', () => {
857
917
  const mockOrgInfo = {
858
918
  tenantId: 'tenant123',
859
919
  timezone: 'GMT',
920
+ environment: 'produs1',
860
921
  };
861
922
 
862
923
  const mockOrgSettings = {
@@ -865,12 +926,6 @@ describe('AgentConfigService', () => {
865
926
  maskSensitiveData: true,
866
927
  };
867
928
 
868
- const mockSiteInfo = {
869
- id: 'c6a5451f-5ba7-49a1-aee8-fbef70c19ece',
870
- name: 'Site-1',
871
- multimediaProfileId: 'c5888e6f-5661-4871-9936-cbcec7658d41',
872
- };
873
-
874
929
  const mockTenantData = {
875
930
  timeoutDesktopInactivityEnabled: true,
876
931
  timeoutDesktopInactivityMins: 15,
@@ -885,15 +940,13 @@ describe('AgentConfigService', () => {
885
940
  lostConnectionRecoveryTimeout: 30,
886
941
  };
887
942
 
888
- const mockURLMapping = [
889
- {key: 'ACQUEON_API_URL', url: 'https://api.example.com'},
890
- {key: 'ACQUEON_CONSOLE_URL', url: 'https://console.example.com'},
891
- ];
892
-
893
943
  const mockAuxCodes = [
894
944
  {id: 'aux1', type: 'WRAP_UP_CODE', name: 'Wrap Up Code 1'},
895
945
  {id: 'aux2', type: 'IDLE_CODE', name: 'Idle Code 1'},
896
946
  ];
947
+ const mockAIFeatureFlags = {
948
+ data: [{realtimeTranscripts: {enable: true}}],
949
+ };
897
950
 
898
951
  const parseAgentConfigsSpy = jest.spyOn(util, 'parseAgentConfigs');
899
952
  agentConfigService.getUserUsingCI = jest.fn().mockResolvedValue(mockUserConfig);
@@ -902,6 +955,7 @@ describe('AgentConfigService', () => {
902
955
  agentConfigService.getSiteInfo = jest.fn().mockResolvedValue(mockSiteInfo);
903
956
  agentConfigService.getTenantData = jest.fn().mockResolvedValue(mockTenantData);
904
957
  agentConfigService.getURLMapping = jest.fn().mockResolvedValue(mockURLMapping);
958
+ agentConfigService.getAIFeatureFlags = jest.fn().mockResolvedValue(mockAIFeatureFlags);
905
959
  agentConfigService.getAllAuxCodes = jest.fn().mockResolvedValue(mockAuxCodes);
906
960
  agentConfigService.getDesktopProfileById = jest.fn().mockResolvedValue(mockAgentProfile);
907
961
  agentConfigService.getDialPlanData = jest.fn().mockResolvedValue(mockDialPlanData);
@@ -941,6 +995,7 @@ describe('AgentConfigService', () => {
941
995
  dialPlanData: mockDialPlanData,
942
996
  urlMapping: mockURLMapping,
943
997
  multimediaProfileId: mockSiteInfo.multimediaProfileId,
998
+ aiFeatureFlags: mockAIFeatureFlags,
944
999
  });
945
1000
  });
946
1001
 
@@ -952,6 +1007,7 @@ describe('AgentConfigService', () => {
952
1007
  agentConfigService.getOrganizationSetting = jest.fn().mockResolvedValue({});
953
1008
  agentConfigService.getTenantData = jest.fn().mockResolvedValue({});
954
1009
  agentConfigService.getURLMapping = jest.fn().mockResolvedValue({});
1010
+ agentConfigService.getAIFeatureFlags = jest.fn().mockResolvedValue({data: []});
955
1011
  agentConfigService.getAllAuxCodes = jest.fn().mockResolvedValue({});
956
1012
  agentConfigService.getDesktopProfileById = jest.fn().mockResolvedValue({});
957
1013
  agentConfigService.getDialPlanData = jest.fn().mockResolvedValue({});