@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,191 @@
1
+ import {LocalMicrophoneStream, CALL_EVENT_KEYS} from '@webex/calling';
2
+ import {CC_FILE} from '../../../constants';
3
+ import {getErrorDetails} from '../../core/Utils';
4
+ import routingContact from '../contact';
5
+ import {
6
+ TaskData,
7
+ TaskResponse,
8
+ TASK_EVENTS,
9
+ IWebRTC,
10
+ VoiceUIControlOptions,
11
+ VOICE_VARIANT,
12
+ TaskToggleMuteOptions,
13
+ } from '../types';
14
+ import Voice from './Voice';
15
+ import WebCallingService from '../../WebCallingService';
16
+ import {WrapupData} from '../../config/types';
17
+ import MetricsManager from '../../../metrics/MetricsManager';
18
+ import {METRIC_EVENT_NAMES} from '../../../metrics/constants';
19
+ import LoggerProxy from '../../../logger-proxy';
20
+
21
+ export default class WebRTC extends Voice implements IWebRTC {
22
+ private localAudioStream: LocalMicrophoneStream;
23
+ private webCallingService: WebCallingService;
24
+
25
+ constructor(
26
+ contact: ReturnType<typeof routingContact>,
27
+ webCallingService: WebCallingService,
28
+ data: TaskData,
29
+ callOptions?: VoiceUIControlOptions,
30
+ wrapupData?: WrapupData,
31
+ agentId?: string
32
+ ) {
33
+ const mergedCallOptions: VoiceUIControlOptions = {
34
+ ...callOptions,
35
+ voiceVariant: VOICE_VARIANT.WEBRTC,
36
+ };
37
+
38
+ super(contact, data, mergedCallOptions, wrapupData, agentId);
39
+ this.webCallingService = webCallingService;
40
+ this.registerWebCallListeners();
41
+ }
42
+
43
+ private registerWebCallListeners() {
44
+ this.webCallingService.on(CALL_EVENT_KEYS.REMOTE_MEDIA, this.handleRemoteMedia);
45
+ }
46
+
47
+ private handleRemoteMedia = (track: MediaStreamTrack) => {
48
+ this.emit(TASK_EVENTS.TASK_MEDIA, track);
49
+ };
50
+
51
+ /**
52
+ * This method is used to unregister the web call listeners.
53
+ * @returns void
54
+ * @example
55
+ * ```typescript
56
+ * task.unregisterWebCallListeners();
57
+ * ```
58
+ */
59
+ public unregisterWebCallListeners() {
60
+ this.webCallingService.off(CALL_EVENT_KEYS.REMOTE_MEDIA, this.handleRemoteMedia);
61
+ }
62
+
63
+ /**
64
+ * This is used for incoming task accept by agent.
65
+ *
66
+ * @returns Promise<TaskResponse>
67
+ * @throws Error
68
+ * @example
69
+ * ```typescript
70
+ * task.accept().then(()=>{}).catch(()=>{})
71
+ * ```
72
+ */
73
+ public async accept(): Promise<TaskResponse> {
74
+ LoggerProxy.log(`Accepting WebRTC task for taskId:${this.data.interactionId}`, {
75
+ module: 'WebRTC',
76
+ method: 'accept',
77
+ });
78
+ try {
79
+ this.metricsManager.timeEvent([
80
+ METRIC_EVENT_NAMES.TASK_ACCEPT_SUCCESS,
81
+ METRIC_EVENT_NAMES.TASK_ACCEPT_FAILED,
82
+ ]);
83
+
84
+ const constraints = {audio: true};
85
+ const localStream = await navigator.mediaDevices.getUserMedia(constraints);
86
+ const audioTrack = localStream.getAudioTracks()[0];
87
+ this.localAudioStream = new LocalMicrophoneStream(new MediaStream([audioTrack]));
88
+ this.webCallingService.answerCall(this.localAudioStream, this.data.interactionId);
89
+
90
+ this.metricsManager.trackEvent(
91
+ METRIC_EVENT_NAMES.TASK_ACCEPT_SUCCESS,
92
+ {
93
+ taskId: this.data.interactionId,
94
+ ...MetricsManager.getCommonTrackingFieldForAQMResponse(this.data),
95
+ },
96
+ ['operational', 'behavioral', 'business']
97
+ );
98
+
99
+ return Promise.resolve();
100
+ } catch (error) {
101
+ this.metricsManager.trackEvent(
102
+ METRIC_EVENT_NAMES.TASK_ACCEPT_FAILED,
103
+ {
104
+ taskId: this.data.interactionId,
105
+ error: error.toString(),
106
+ ...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(
107
+ (error as any).details || {}
108
+ ),
109
+ },
110
+ ['operational', 'behavioral', 'business']
111
+ );
112
+ const {error: detailedError} = getErrorDetails(error, 'accept', CC_FILE);
113
+ throw detailedError;
114
+ }
115
+ }
116
+
117
+ /**
118
+ * This is used for the incoming task decline by agent.
119
+ *
120
+ * @returns Promise<TaskResponse>
121
+ * @throws Error
122
+ * @example
123
+ * ```typescript
124
+ * task.decline().then(()=>{}).catch(()=>{})
125
+ * ```
126
+ */
127
+ public async decline(): Promise<TaskResponse> {
128
+ LoggerProxy.log(`Declining WebRTC task for taskId:${this.data.interactionId}`, {
129
+ module: 'WebRTC',
130
+ method: 'decline',
131
+ });
132
+ try {
133
+ this.metricsManager.timeEvent([
134
+ METRIC_EVENT_NAMES.TASK_DECLINE_SUCCESS,
135
+ METRIC_EVENT_NAMES.TASK_DECLINE_FAILED,
136
+ ]);
137
+
138
+ this.webCallingService.declineCall(this.data.interactionId);
139
+ this.unregisterWebCallListeners();
140
+
141
+ this.metricsManager.trackEvent(
142
+ METRIC_EVENT_NAMES.TASK_DECLINE_SUCCESS,
143
+ {taskId: this.data.interactionId},
144
+ ['operational', 'behavioral']
145
+ );
146
+
147
+ return Promise.resolve();
148
+ } catch (error) {
149
+ this.metricsManager.trackEvent(
150
+ METRIC_EVENT_NAMES.TASK_DECLINE_FAILED,
151
+ {
152
+ taskId: this.data.interactionId,
153
+ error: error.toString(),
154
+ ...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(
155
+ (error as any).details || {}
156
+ ),
157
+ },
158
+ ['operational', 'behavioral']
159
+ );
160
+ const {error: detailedError} = getErrorDetails(error, 'decline', CC_FILE);
161
+ throw detailedError;
162
+ }
163
+ }
164
+
165
+ /**
166
+ * This is used for the placing the call in mute or unmute by the agent.
167
+ *
168
+ * @throws Error
169
+ * @example
170
+ * ```typescript
171
+ * task.toggleMute().then(()=>{}).catch(()=>{})
172
+ * ```
173
+ */
174
+ public async toggleMute(options?: TaskToggleMuteOptions) {
175
+ if (options) {
176
+ // parameter intentionally unused — WebRTC toggles from local stream state
177
+ }
178
+ LoggerProxy.log(`Toggling mute WebRTC task for taskId:${this.data.interactionId}`, {
179
+ module: 'WebRTC',
180
+ method: 'toggleMute',
181
+ });
182
+ try {
183
+ this.webCallingService.muteUnmuteCall(this.localAudioStream);
184
+
185
+ return Promise.resolve();
186
+ } catch (error) {
187
+ const {error: detailedError} = getErrorDetails(error, 'mute', CC_FILE);
188
+ throw detailedError;
189
+ }
190
+ }
191
+ }
@@ -0,0 +1,307 @@
1
+ import AnswerCallOnWebexService from '../../AnswerCallOnWebexService';
2
+ import LoggerProxy from '../../../logger-proxy';
3
+ import {METHODS} from '../../../constants';
4
+ import {getErrorDetails} from '../../core/Utils';
5
+ import {TaskData, TaskToggleMuteOptions, TaskTransmitDtmfOptions} from '../types';
6
+ import {TaskState} from '../state-machine';
7
+ import {
8
+ decodedLineOwnerId,
9
+ getWebexCallingDeviceDetailsForAgent,
10
+ WebexCallingDeviceDetails,
11
+ } from '../WebexCallingUtils';
12
+
13
+ type WxAppParticipant = {
14
+ deviceType?: string;
15
+ deviceCallId?: string;
16
+ deviceId?: string;
17
+ };
18
+
19
+ export type WxAppVoiceDependencies = {
20
+ enableWxBetterTogether: boolean;
21
+ answerCallOnWebexService?: AnswerCallOnWebexService;
22
+ agentId?: string;
23
+ getTaskData: () => TaskData;
24
+ getTaskState: () => TaskState | undefined;
25
+ getWxAppMuted: () => boolean;
26
+ setWxAppMuted: (muted: boolean) => void;
27
+ };
28
+
29
+ /** @deprecated Use {@link WxAppVoiceDependencies} */
30
+ export type WxAppVoiceDeps = WxAppVoiceDependencies;
31
+
32
+ export type WxAppVoiceLifecycle = {
33
+ setWxAppAcceptInFlight: (inFlight: boolean) => void;
34
+ setWxAppAnswerPending: (pending: boolean) => void;
35
+ resetWxAppMuted: () => void;
36
+ syncWxAppMuteFromCallDetails: () => Promise<boolean | undefined>;
37
+ mapWxAppVoiceError: (error: unknown, method: string) => never;
38
+ };
39
+
40
+ const isWxAppParticipant = (participant: unknown): participant is WxAppParticipant =>
41
+ (participant as WxAppParticipant)?.deviceType === 'wxApp' &&
42
+ typeof (participant as WxAppParticipant)?.deviceCallId === 'string' &&
43
+ (participant as WxAppParticipant).deviceCallId.trim() !== '' &&
44
+ typeof (participant as WxAppParticipant)?.deviceId === 'string' &&
45
+ (participant as WxAppParticipant).deviceId.trim() !== '';
46
+
47
+ const isOutdialTask = (deps: WxAppVoiceDependencies): boolean =>
48
+ deps.getTaskData()?.interaction?.outboundType === 'OUTDIAL';
49
+
50
+ function getWxAppAgentParticipant(deps: WxAppVoiceDependencies): unknown {
51
+ const taskData = deps.getTaskData();
52
+ const participants = taskData.interaction?.participants;
53
+ const agentId = deps.agentId ?? taskData.agentId;
54
+
55
+ if (!participants || !agentId) {
56
+ return undefined;
57
+ }
58
+
59
+ if (participants[agentId]) {
60
+ return participants[agentId];
61
+ }
62
+
63
+ return Object.values(participants).find(
64
+ (participant) => (participant as {id?: string})?.id === agentId
65
+ );
66
+ }
67
+
68
+ export function getCallingDeviceDetails(
69
+ deps: WxAppVoiceDependencies
70
+ ): WebexCallingDeviceDetails | undefined {
71
+ const taskData = deps.getTaskData();
72
+ const participant = getWxAppAgentParticipant(deps);
73
+
74
+ if (!isWxAppParticipant(participant)) {
75
+ return undefined;
76
+ }
77
+
78
+ return getWebexCallingDeviceDetailsForAgent(
79
+ deps.agentId ?? taskData.agentId,
80
+ taskData.interaction?.participants
81
+ );
82
+ }
83
+
84
+ export function isWebexAppCallingOffer(deps: WxAppVoiceDependencies): boolean {
85
+ if (!deps.enableWxBetterTogether) {
86
+ return false;
87
+ }
88
+
89
+ const state = deps.getTaskState();
90
+ if (state !== TaskState.OFFERED) {
91
+ return false;
92
+ }
93
+
94
+ const details = getCallingDeviceDetails(deps);
95
+
96
+ return Boolean(details);
97
+ }
98
+
99
+ /** Inbound wxApp offer only — outdial decline uses CC routing, not telephony reject. */
100
+ export function isWebexAppInboundCallingOffer(deps: WxAppVoiceDependencies): boolean {
101
+ return isWebexAppCallingOffer(deps) && !isOutdialTask(deps);
102
+ }
103
+
104
+ export function getWebexCallingCallId(deps: WxAppVoiceDependencies): string | null {
105
+ const state = deps.getTaskState();
106
+ if (
107
+ !state ||
108
+ state === TaskState.OFFERED ||
109
+ state === TaskState.IDLE ||
110
+ state === TaskState.WRAPPING_UP ||
111
+ state === TaskState.TERMINATED ||
112
+ state === TaskState.COMPLETED
113
+ ) {
114
+ return null;
115
+ }
116
+
117
+ return getCallingDeviceDetails(deps)?.deviceCallId ?? null;
118
+ }
119
+
120
+ export function getWxAppLineOwnerId(deps: WxAppVoiceDependencies): string | undefined {
121
+ const participant = getWxAppAgentParticipant(deps) as {lineOwnerId?: string} | undefined;
122
+ const lineOwnerId = participant?.lineOwnerId;
123
+
124
+ return typeof lineOwnerId === 'string' && lineOwnerId.trim() !== '' ? lineOwnerId : undefined;
125
+ }
126
+
127
+ export function resolveWxAppLineOwnerId(
128
+ deps: WxAppVoiceDependencies,
129
+ override?: string
130
+ ): string | undefined {
131
+ if (typeof override === 'string' && override.trim() !== '') {
132
+ return override;
133
+ }
134
+
135
+ return decodedLineOwnerId(getWxAppLineOwnerId(deps));
136
+ }
137
+
138
+ function assertWxAppEnabled(deps: WxAppVoiceDependencies): void {
139
+ if (!deps.enableWxBetterTogether) {
140
+ throw new Error('enableWxBetterTogether is disabled');
141
+ }
142
+
143
+ if (!deps.answerCallOnWebexService) {
144
+ throw new Error('AnswerCallOnWebexService is unavailable');
145
+ }
146
+ }
147
+
148
+ export async function acceptOnWebex(
149
+ deps: WxAppVoiceDependencies,
150
+ options?: {lineOwnerId?: string}
151
+ ): Promise<void> {
152
+ assertWxAppEnabled(deps);
153
+
154
+ if (!isWebexAppCallingOffer(deps)) {
155
+ throw new Error('Task is not a wxApp calling offer');
156
+ }
157
+
158
+ const details = getCallingDeviceDetails(deps);
159
+ if (!details) {
160
+ throw new Error('WxApp calling device details are unavailable');
161
+ }
162
+
163
+ await deps.answerCallOnWebexService.answerCall({
164
+ callId: details.deviceCallId,
165
+ endpointId: details.deviceId,
166
+ lineOwnerId: resolveWxAppLineOwnerId(deps, options?.lineOwnerId),
167
+ });
168
+ }
169
+
170
+ export async function rejectOnWebex(
171
+ deps: WxAppVoiceDependencies,
172
+ options?: {lineOwnerId?: string}
173
+ ): Promise<void> {
174
+ assertWxAppEnabled(deps);
175
+
176
+ if (!isWebexAppInboundCallingOffer(deps)) {
177
+ throw new Error('Task is not a wxApp inbound calling offer');
178
+ }
179
+
180
+ const details = getCallingDeviceDetails(deps);
181
+ if (!details) {
182
+ throw new Error('WxApp calling device details are unavailable');
183
+ }
184
+
185
+ await deps.answerCallOnWebexService.rejectCall({
186
+ callId: details.deviceCallId,
187
+ lineOwnerId: resolveWxAppLineOwnerId(deps, options?.lineOwnerId),
188
+ });
189
+ }
190
+
191
+ export async function toggleMuteOnWebex(
192
+ deps: WxAppVoiceDependencies,
193
+ options?: {lineOwnerId?: string; muted?: boolean}
194
+ ): Promise<void> {
195
+ assertWxAppEnabled(deps);
196
+
197
+ const callId = getWebexCallingCallId(deps);
198
+ if (!callId) {
199
+ throw new Error('WxApp call ID is unavailable');
200
+ }
201
+
202
+ const targetMuted = options?.muted ?? !deps.getWxAppMuted();
203
+ const request = targetMuted
204
+ ? deps.answerCallOnWebexService.muteCall.bind(deps.answerCallOnWebexService)
205
+ : deps.answerCallOnWebexService.unmuteCall.bind(deps.answerCallOnWebexService);
206
+
207
+ await request({
208
+ callId,
209
+ lineOwnerId: resolveWxAppLineOwnerId(deps, options?.lineOwnerId),
210
+ });
211
+ deps.setWxAppMuted(targetMuted);
212
+ }
213
+
214
+ export async function transmitDtmfOnWebex(
215
+ deps: WxAppVoiceDependencies,
216
+ options: {dtmf: string; lineOwnerId?: string}
217
+ ): Promise<void> {
218
+ assertWxAppEnabled(deps);
219
+
220
+ const callId = getWebexCallingCallId(deps);
221
+ if (!callId) {
222
+ throw new Error('WxApp call ID is unavailable');
223
+ }
224
+
225
+ LoggerProxy.info('transmitDtmf', {
226
+ module: 'wxAppVoiceMethods',
227
+ method: METHODS.TRANSMIT_DTMF,
228
+ data: {
229
+ callId,
230
+ dtmfLength: options.dtmf.length,
231
+ hasLineOwnerId: Boolean(options.lineOwnerId),
232
+ },
233
+ });
234
+
235
+ await deps.answerCallOnWebexService.transmitDtmf({
236
+ callId,
237
+ dtmf: options.dtmf,
238
+ lineOwnerId: resolveWxAppLineOwnerId(deps, options.lineOwnerId),
239
+ });
240
+ }
241
+
242
+ export async function runWxAppAccept(
243
+ deps: WxAppVoiceDependencies,
244
+ lifecycle: WxAppVoiceLifecycle,
245
+ options?: {lineOwnerId?: string}
246
+ ): Promise<void> {
247
+ try {
248
+ lifecycle.setWxAppAcceptInFlight(true);
249
+ lifecycle.setWxAppAnswerPending(true);
250
+ await acceptOnWebex(deps, options);
251
+ lifecycle.resetWxAppMuted();
252
+ await lifecycle.syncWxAppMuteFromCallDetails();
253
+ } catch (error) {
254
+ lifecycle.setWxAppAnswerPending(false);
255
+ lifecycle.mapWxAppVoiceError(error, METHODS.ACCEPT);
256
+ } finally {
257
+ lifecycle.setWxAppAcceptInFlight(false);
258
+ }
259
+ }
260
+
261
+ export async function runWxAppReject(
262
+ deps: WxAppVoiceDependencies,
263
+ lifecycle: WxAppVoiceLifecycle,
264
+ options?: {lineOwnerId?: string}
265
+ ): Promise<void> {
266
+ try {
267
+ await rejectOnWebex(deps, options);
268
+ } catch (error) {
269
+ lifecycle.mapWxAppVoiceError(error, METHODS.REJECT);
270
+ }
271
+ }
272
+
273
+ export async function runWxAppToggleMute(
274
+ deps: WxAppVoiceDependencies,
275
+ lifecycle: WxAppVoiceLifecycle,
276
+ options?: TaskToggleMuteOptions
277
+ ): Promise<void> {
278
+ try {
279
+ await toggleMuteOnWebex(deps, options);
280
+ } catch (error) {
281
+ lifecycle.mapWxAppVoiceError(error, METHODS.TOGGLE_MUTE);
282
+ }
283
+ }
284
+
285
+ export async function runWxAppTransmitDtmf(
286
+ deps: WxAppVoiceDependencies,
287
+ lifecycle: WxAppVoiceLifecycle,
288
+ options: TaskTransmitDtmfOptions
289
+ ): Promise<void> {
290
+ try {
291
+ await transmitDtmfOnWebex(deps, options);
292
+ } catch (error) {
293
+ lifecycle.mapWxAppVoiceError(error, METHODS.TRANSMIT_DTMF);
294
+ }
295
+ }
296
+
297
+ export function mapWxAppVoiceError(error: unknown, method: string, module: string): never {
298
+ if (
299
+ error instanceof Error &&
300
+ (error as Error & {isWxAppTelephonyError?: boolean}).isWxAppTelephonyError
301
+ ) {
302
+ throw error;
303
+ }
304
+
305
+ const {error: detailedError} = getErrorDetails(error, method, module);
306
+ throw detailedError;
307
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Expected Hydra responses when mute backfill races call creation (WXCC-6026).
3
+ * These must not be logged as errors — see task-spec wxApp mute backfill guard.
4
+ */
5
+ export function isWxAppCallNotFoundError(error: unknown): boolean {
6
+ const err = error as {status?: number | string; message?: string};
7
+ if (err?.status === 400 || err?.status === '400') {
8
+ return true;
9
+ }
10
+
11
+ const message = String(err?.message ?? error ?? '');
12
+
13
+ return message.includes('Call not found') || message.includes('101002');
14
+ }