@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,212 @@
1
+ import LoggerProxy from '../logger-proxy';
2
+ import {METHODS} from '../constants';
3
+ import {WebexSDK} from '../types';
4
+
5
+ const WEBEX_CROSS_CLIENT_FILE = 'WebexCrossClientService';
6
+ const DEFAULT_CROSS_CLIENT_STATE_TTL = 900;
7
+ const EXPIRATION_OFFSET_MS = 60_000;
8
+ /** Must match Agent Desktop usersub publish — Webex App reads `wxcc` cross-client state. */
9
+ const DEFAULT_APP_NAME = 'wxcc';
10
+ const REFRESH_RETRY_DELAY_MS = 30_000;
11
+ const MAX_REFRESH_RETRIES = 3;
12
+
13
+ type RefreshTimer = ReturnType<typeof setTimeout>;
14
+
15
+ /**
16
+ * Publishes usersub cross-client state so Webex App suppresses native calling toasts (WXCC-6026).
17
+ */
18
+ export default class WebexCrossClientService {
19
+ private webex: WebexSDK;
20
+ private refreshTimer?: RefreshTimer;
21
+ private refreshRetryTimer?: RefreshTimer;
22
+ private answerCallsState = false;
23
+ private appName = DEFAULT_APP_NAME;
24
+ /** Incremented on teardown/disable to ignore stale refresh timer callbacks. */
25
+ private refreshGeneration = 0;
26
+
27
+ constructor(webex: WebexSDK) {
28
+ this.webex = webex;
29
+ }
30
+
31
+ private extractDeviceIdFromUrl(url: string): string {
32
+ const match = url.match(/\/devices\/([^/?]+)/);
33
+
34
+ return match ? match[1] : '';
35
+ }
36
+
37
+ private getDeviceUrl(): string | undefined {
38
+ return this.webex.internal.device?.url;
39
+ }
40
+
41
+ private clearRefreshTimer(): void {
42
+ if (this.refreshTimer) {
43
+ clearTimeout(this.refreshTimer);
44
+ this.refreshTimer = undefined;
45
+ }
46
+
47
+ if (this.refreshRetryTimer) {
48
+ clearTimeout(this.refreshRetryTimer);
49
+ this.refreshRetryTimer = undefined;
50
+ }
51
+ }
52
+
53
+ private scheduleRefreshRetry(
54
+ userId: string,
55
+ ttl: number,
56
+ scheduledGeneration: number,
57
+ retryAttempt: number
58
+ ): void {
59
+ if (
60
+ retryAttempt >= MAX_REFRESH_RETRIES ||
61
+ scheduledGeneration !== this.refreshGeneration ||
62
+ !this.answerCallsState
63
+ ) {
64
+ return;
65
+ }
66
+
67
+ this.refreshRetryTimer = setTimeout(async () => {
68
+ if (scheduledGeneration !== this.refreshGeneration || !this.answerCallsState) {
69
+ return;
70
+ }
71
+
72
+ try {
73
+ await this.setManageWebexCallingInWxcc(true, {userId, ttl, appName: this.appName});
74
+ } catch (error) {
75
+ LoggerProxy.error(`WebexCrossClientService refresh retry failed: ${error}`, {
76
+ module: WEBEX_CROSS_CLIENT_FILE,
77
+ method: METHODS.SET_MANAGE_WEBEX_CALLING_IN_WXCC,
78
+ });
79
+ this.scheduleRefreshRetry(userId, ttl, scheduledGeneration, retryAttempt + 1);
80
+ }
81
+ }, REFRESH_RETRY_DELAY_MS);
82
+ }
83
+
84
+ private startRefreshTimer(userId: string, ttl: number): void {
85
+ this.clearRefreshTimer();
86
+
87
+ if (!this.answerCallsState) {
88
+ return;
89
+ }
90
+
91
+ const refreshTime = ttl * 1000 - EXPIRATION_OFFSET_MS;
92
+ const scheduledGeneration = this.refreshGeneration;
93
+ this.refreshTimer = setTimeout(async () => {
94
+ if (scheduledGeneration !== this.refreshGeneration || !this.answerCallsState) {
95
+ return;
96
+ }
97
+
98
+ try {
99
+ await this.setManageWebexCallingInWxcc(true, {userId, ttl, appName: this.appName});
100
+ } catch (error) {
101
+ LoggerProxy.error(`WebexCrossClientService refresh failed: ${error}`, {
102
+ module: WEBEX_CROSS_CLIENT_FILE,
103
+ method: METHODS.SET_MANAGE_WEBEX_CALLING_IN_WXCC,
104
+ });
105
+ this.scheduleRefreshRetry(userId, ttl, scheduledGeneration, 0);
106
+ }
107
+ }, refreshTime);
108
+ }
109
+
110
+ private publishCrossClientState(
111
+ users: string[],
112
+ ttl: number,
113
+ composition: Record<string, unknown>,
114
+ logContext: string
115
+ ): Promise<unknown> {
116
+ const body = {
117
+ users,
118
+ compositions: [
119
+ {
120
+ type: 'cross-client-state',
121
+ ttl,
122
+ composition,
123
+ },
124
+ ],
125
+ };
126
+
127
+ return this.webex
128
+ .request({
129
+ method: 'POST',
130
+ service: 'usersub',
131
+ resource: 'publish',
132
+ body,
133
+ })
134
+ .then((response: {body?: unknown}) => response?.body)
135
+ .catch((error: unknown) => {
136
+ LoggerProxy.error(`WebexCrossClientService.${logContext} failed: ${error}`, {
137
+ module: WEBEX_CROSS_CLIENT_FILE,
138
+ method: METHODS.SET_MANAGE_WEBEX_CALLING_IN_WXCC,
139
+ });
140
+
141
+ return Promise.reject(error);
142
+ });
143
+ }
144
+
145
+ public async setManageWebexCallingInWxcc(
146
+ enable: boolean,
147
+ options?: {userId?: string; ttl?: number; appName?: string}
148
+ ): Promise<void> {
149
+ const operationGeneration = this.refreshGeneration;
150
+ const userId = options?.userId ?? this.webex.internal.device?.userId;
151
+ const ttl = options?.ttl ?? DEFAULT_CROSS_CLIENT_STATE_TTL;
152
+ const appName = options?.appName ?? DEFAULT_APP_NAME;
153
+ this.appName = appName;
154
+
155
+ if (!userId) {
156
+ throw new Error('User ID is unavailable for cross-client publish');
157
+ }
158
+
159
+ const deviceUrl = this.getDeviceUrl();
160
+ if (!deviceUrl) {
161
+ throw new Error('Device URL is unavailable for cross-client publish');
162
+ }
163
+
164
+ const composition = {
165
+ devices: [
166
+ {
167
+ deviceId: this.extractDeviceIdFromUrl(deviceUrl),
168
+ appName,
169
+ state: {
170
+ 'answer-calls-on-wxcc': enable,
171
+ },
172
+ },
173
+ ],
174
+ };
175
+
176
+ await this.publishCrossClientState([userId], ttl, composition, 'setManageWebexCallingInWxcc');
177
+
178
+ if (operationGeneration !== this.refreshGeneration) {
179
+ return;
180
+ }
181
+
182
+ this.answerCallsState = enable;
183
+
184
+ if (enable) {
185
+ this.startRefreshTimer(userId, ttl);
186
+ } else {
187
+ this.refreshGeneration += 1;
188
+ this.clearRefreshTimer();
189
+ }
190
+
191
+ LoggerProxy.info(`Cross-client answer-calls-on-wxcc set to ${enable}`, {
192
+ module: WEBEX_CROSS_CLIENT_FILE,
193
+ method: METHODS.SET_MANAGE_WEBEX_CALLING_IN_WXCC,
194
+ data: {
195
+ appName,
196
+ deviceId: this.extractDeviceIdFromUrl(deviceUrl),
197
+ ttl,
198
+ },
199
+ });
200
+ }
201
+
202
+ public teardown(): void {
203
+ this.refreshGeneration += 1;
204
+ this.clearRefreshTimer();
205
+ this.answerCallsState = false;
206
+ }
207
+
208
+ /** Whether usersub `answer-calls-on-wxcc: true` was successfully published this session. */
209
+ public isAnswerCallsStateActive(): boolean {
210
+ return this.answerCallsState;
211
+ }
212
+ }
@@ -0,0 +1,115 @@
1
+ import LoggerProxy from '../logger-proxy';
2
+ import {METHODS} from '../constants';
3
+ import {WebexSDK} from '../types';
4
+
5
+ const WXAPP_TELEPHONY_MERCURY_SYNC_FILE = 'WxAppTelephonyMercurySync';
6
+
7
+ export const TELEPHONY_CALL_MUTED = 'event:telephony_calls.muted';
8
+ export const TELEPHONY_CALL_UNMUTED = 'event:telephony_calls.unmuted';
9
+
10
+ export type UpdatedCallMuteStateEvent = {
11
+ data: {
12
+ actorId: string;
13
+ callId: string;
14
+ muted: boolean;
15
+ };
16
+ };
17
+
18
+ type MuteChangeHandler = (callId: string, muted: boolean) => void;
19
+
20
+ /**
21
+ * Subscribes to Mercury telephony mute/unmute events for wxApp thick-client sync (AD parity).
22
+ */
23
+ export default class WxAppTelephonyMercurySync {
24
+ private webex: WebexSDK;
25
+ private subscribedAgentId?: string;
26
+ private muteChangeHandler?: MuteChangeHandler;
27
+ private boundMuteHandler?: (event: UpdatedCallMuteStateEvent) => void;
28
+ private boundUnmuteHandler?: (event: UpdatedCallMuteStateEvent) => void;
29
+
30
+ constructor(webex: WebexSDK) {
31
+ this.webex = webex;
32
+ }
33
+
34
+ private decodeBase64(value: string): string {
35
+ try {
36
+ return atob(value);
37
+ } catch {
38
+ return value;
39
+ }
40
+ }
41
+
42
+ private handleMuteStateEvent = (agentId: string, event: UpdatedCallMuteStateEvent): void => {
43
+ const {actorId, callId, muted} = event?.data ?? {};
44
+ if (!actorId || !callId || muted === undefined) {
45
+ return;
46
+ }
47
+
48
+ const decodedActorId = this.decodeBase64(actorId);
49
+ const decodedCallId = this.decodeBase64(callId);
50
+
51
+ if (!decodedActorId.endsWith(agentId)) {
52
+ return;
53
+ }
54
+
55
+ LoggerProxy.info('WxApp telephony mute state sync received', {
56
+ module: WXAPP_TELEPHONY_MERCURY_SYNC_FILE,
57
+ method: METHODS.SYNC_WXAPP_MUTE_FROM_MERCURY,
58
+ data: {muted},
59
+ });
60
+
61
+ this.muteChangeHandler?.(decodedCallId, muted);
62
+ };
63
+
64
+ public subscribe(agentId: string, onMuteChange: MuteChangeHandler): void {
65
+ this.unsubscribe();
66
+
67
+ const mercury = this.webex.internal.mercury;
68
+ if (!mercury) {
69
+ LoggerProxy.error('Mercury is unavailable for wxApp mute sync', {
70
+ module: WXAPP_TELEPHONY_MERCURY_SYNC_FILE,
71
+ method: METHODS.SYNC_WXAPP_MUTE_FROM_MERCURY,
72
+ });
73
+
74
+ return;
75
+ }
76
+
77
+ this.subscribedAgentId = agentId;
78
+ this.muteChangeHandler = onMuteChange;
79
+
80
+ this.boundMuteHandler = (event: UpdatedCallMuteStateEvent) => {
81
+ this.handleMuteStateEvent(agentId, event);
82
+ };
83
+ this.boundUnmuteHandler = (event: UpdatedCallMuteStateEvent) => {
84
+ this.handleMuteStateEvent(agentId, event);
85
+ };
86
+
87
+ mercury.on(TELEPHONY_CALL_MUTED, this.boundMuteHandler);
88
+ mercury.on(TELEPHONY_CALL_UNMUTED, this.boundUnmuteHandler);
89
+
90
+ LoggerProxy.info('Subscribed to wxApp telephony Mercury mute sync', {
91
+ module: WXAPP_TELEPHONY_MERCURY_SYNC_FILE,
92
+ method: METHODS.SYNC_WXAPP_MUTE_FROM_MERCURY,
93
+ });
94
+ }
95
+
96
+ public unsubscribe(): void {
97
+ const mercury = this.webex.internal.mercury;
98
+
99
+ if (mercury && this.boundMuteHandler) {
100
+ mercury.off(TELEPHONY_CALL_MUTED, this.boundMuteHandler);
101
+ }
102
+ if (mercury && this.boundUnmuteHandler) {
103
+ mercury.off(TELEPHONY_CALL_UNMUTED, this.boundUnmuteHandler);
104
+ }
105
+
106
+ this.subscribedAgentId = undefined;
107
+ this.muteChangeHandler = undefined;
108
+ this.boundMuteHandler = undefined;
109
+ this.boundUnmuteHandler = undefined;
110
+ }
111
+
112
+ public isSubscribed(): boolean {
113
+ return Boolean(this.subscribedAgentId && this.muteChangeHandler);
114
+ }
115
+ }
@@ -0,0 +1,240 @@
1
+ # Agent Service - AI Agent Guide
2
+
3
+ > **Legacy/reference-only.** Canonical SDD: [`agent-spec.md`](agent-spec.md). Use the package [manifest](../../../../.sdd/manifest.json) and [`SPEC_INDEX.md`](../../../../ai-docs/SPEC_INDEX.md) for routing; code and tests remain the behavioral referee.
4
+
5
+ > **Purpose**: Manage agent lifecycle including login, logout, state changes, and buddy agent queries.
6
+
7
+ ---
8
+
9
+ ## Quick Start
10
+
11
+ ```typescript
12
+ const cc = webex.cc;
13
+
14
+ // Register and login
15
+ const profile = await cc.register();
16
+ await cc.stationLogin({
17
+ teamId: profile.teams[0].teamId,
18
+ loginOption: 'BROWSER',
19
+ });
20
+
21
+ // Set state to Available
22
+ await cc.setAgentState({
23
+ state: 'Available',
24
+ auxCodeId: '0',
25
+ });
26
+
27
+ // Get available agents for transfer
28
+ const buddies = await cc.getBuddyAgents({
29
+ state: 'Available',
30
+ mediaType: 'telephony',
31
+ });
32
+ ```
33
+
34
+ ---
35
+
36
+ ## Key Capabilities
37
+
38
+ - **Station Login**: Login with browser (WebRTC), extension, or dial number
39
+ - **Station Logout**: Logout from current station with reason
40
+ - **State Management**: Toggle between Available/Idle states with aux codes
41
+ - **Buddy Agents**: Query available agents for consult/transfer
42
+ - **Silent Relogin**: Automatic re-authentication on reconnection
43
+
44
+ ---
45
+
46
+ ## API Reference
47
+
48
+ ### Login Options
49
+
50
+ | Option | Description | Requires dialNumber |
51
+ |--------|-------------|---------------------|
52
+ | `BROWSER` | WebRTC softphone in browser | No |
53
+ | `EXTENSION` | Desk phone extension | Yes |
54
+ | `AGENT_DN` | Direct dial number | Yes |
55
+
56
+ ### Methods
57
+
58
+ #### `cc.stationLogin(params)`
59
+
60
+ Login agent to a station.
61
+
62
+ **Parameters**:
63
+ - `teamId` (string): Team to login to
64
+ - `loginOption` ('BROWSER' | 'EXTENSION' | 'AGENT_DN'): Device type
65
+ - `dialNumber` (string, optional): Required for EXTENSION/AGENT_DN
66
+
67
+ **Returns**: `Promise<StationLoginResponse>`
68
+
69
+ **Example**:
70
+ ```typescript
71
+ // Browser login
72
+ const response = await cc.stationLogin({
73
+ teamId: 'team-123',
74
+ loginOption: 'BROWSER',
75
+ });
76
+
77
+ // Extension login
78
+ const response = await cc.stationLogin({
79
+ teamId: 'team-123',
80
+ loginOption: 'EXTENSION',
81
+ dialNumber: '1234',
82
+ });
83
+ ```
84
+
85
+ ---
86
+
87
+ #### `cc.stationLogout(params)`
88
+
89
+ Logout agent from station.
90
+
91
+ **Parameters**:
92
+ - `logoutReason` (string, optional): 'User requested logout' | 'Inactivity Logout' | 'User requested agent profile update'
93
+
94
+ **Returns**: `Promise<StationLogoutResponse>`
95
+
96
+ **Example**:
97
+ ```typescript
98
+ await cc.stationLogout({
99
+ logoutReason: 'User requested logout',
100
+ });
101
+ ```
102
+
103
+ ---
104
+
105
+ #### `cc.setAgentState(params)`
106
+
107
+ Change agent state (Available/Idle).
108
+
109
+ **Parameters**:
110
+ - `state` ('Available' | 'Idle'): New state
111
+ - `auxCodeId` (string): Auxiliary code ID
112
+ - `lastStateChangeReason` (string, optional): Reason for change
113
+ - `agentId` (string, optional): Agent ID (defaults to current agent)
114
+
115
+ **Returns**: `Promise<SetStateResponse>`
116
+
117
+ **Example**:
118
+ ```typescript
119
+ // Go Available
120
+ await cc.setAgentState({
121
+ state: 'Available',
122
+ auxCodeId: '0',
123
+ });
124
+
125
+ // Go to Idle with specific code
126
+ await cc.setAgentState({
127
+ state: 'Idle',
128
+ auxCodeId: 'break-code-123',
129
+ lastStateChangeReason: 'Coffee break',
130
+ });
131
+ ```
132
+
133
+ ---
134
+
135
+ #### `cc.getBuddyAgents(params)`
136
+
137
+ Get list of agents for consult/transfer.
138
+
139
+ **Parameters**:
140
+ - `state` (string, optional): Filter by state ('Available', 'Idle')
141
+ - `mediaType` (string): Media type filter ('telephony', 'chat', 'social', 'email')
142
+ **Returns**: `Promise<BuddyAgentsResponse>`
143
+
144
+ **Example**:
145
+ ```typescript
146
+ const response = await cc.getBuddyAgents({
147
+ state: 'Available',
148
+ mediaType: 'telephony',
149
+ });
150
+
151
+ response.data.agentList.forEach(agent => {
152
+ console.log(`${agent.agentName} (${agent.state})`);
153
+ });
154
+ ```
155
+
156
+ ---
157
+
158
+ ## Events
159
+
160
+ | Event | Type | Description |
161
+ |-------|------|-------------|
162
+ | `agent:stationLoginSuccess` | `StationLoginSuccessResponse` | Login succeeded |
163
+ | `agent:stationLoginFailed` | Error | Login failed |
164
+ | `agent:logoutSuccess` | `LogoutSuccess` | Logout succeeded |
165
+ | `agent:logoutFailed` | Error | Logout failed |
166
+ | `agent:stateChange` | `StateChangeSuccess` | State changed (any source) |
167
+ | `agent:stateChangeSuccess` | `StateChangeSuccess` | State change succeeded |
168
+ | `agent:stateChangeFailed` | Error | State change failed |
169
+ | `agent:multiLogin` | Object | Multi-login detected |
170
+ | `agent:reloginSuccess` | `ReloginSuccess` | Silent relogin succeeded |
171
+ | `agent:dnRegistered` | Object | DN registration complete |
172
+
173
+ ### Event Usage
174
+
175
+ ```typescript
176
+ cc.on('agent:stateChange', (event) => {
177
+ console.log(`State: ${event.subStatus}, AuxCode: ${event.auxCodeId}`);
178
+ });
179
+
180
+ cc.on('agent:multiLogin', (event) => {
181
+ console.warn('Another session detected');
182
+ });
183
+ ```
184
+
185
+ ---
186
+
187
+ ## Agent States
188
+
189
+ The `AgentState` type (`'Available' | 'Idle' | 'RONA' | string`) is extensible -- the `string` union member allows backend-defined states beyond the known values listed below.
190
+
191
+ | State | SubStatus | Description |
192
+ |-------|-----------|-------------|
193
+ | LoggedIn | Available | Ready to receive tasks |
194
+ | LoggedIn | Idle | On break or not ready (uses aux code for sub-reason) |
195
+ | RONA | - | Rang but no answer; agent failed to accept offered task |
196
+ | LoggedOut | - | Not logged in |
197
+ | LoggedIn | *(custom)* | Additional org-specific states defined via aux codes |
198
+
199
+ > **Note**: `AgentState` is a union with `string`, so consumers should handle unknown state values gracefully rather than exhaustively matching only the known literals.
200
+
201
+ ---
202
+
203
+ ## Error Handling
204
+
205
+ ```typescript
206
+ try {
207
+ await cc.stationLogin(params);
208
+ } catch (error) {
209
+ console.error('Login failed:', error.message);
210
+ // Access error details
211
+ if (error.data) {
212
+ console.error('Field:', error.data.fieldName);
213
+ console.error('Message:', error.data.message);
214
+ }
215
+ }
216
+ ```
217
+
218
+ ### Common Error Reasons
219
+
220
+ | Reason | Description |
221
+ |--------|-------------|
222
+ | `DUPLICATE_LOCATION` | Extension/DN already in use |
223
+ | `INVALID_DIAL_NUMBER` | Invalid phone number format |
224
+ | `AGENT_NOT_FOUND` | Agent doesn't exist (silent relogin) |
225
+
226
+ ---
227
+
228
+ ## Dependencies
229
+
230
+ - Requires `cc.register()` to be called first
231
+ - Agent profile must be fetched before login
232
+ - WebRTC (BROWSER option) requires mercury connection
233
+
234
+ ---
235
+
236
+ ## Related
237
+
238
+ - [ARCHITECTURE.md](ARCHITECTURE.md) - Technical deep-dive
239
+ - [`cc.ts`](../../../cc.ts) - Main plugin implementation
240
+ - [`types.ts`](../types.ts) - Type definitions