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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (328) hide show
  1. package/.sdd/manifest.json +887 -0
  2. package/AGENTS.md +94 -0
  3. package/ai-docs/ARCHITECTURE.md +168 -0
  4. package/ai-docs/CONTRACTS.md +62 -0
  5. package/ai-docs/GETTING_STARTED.md +168 -0
  6. package/ai-docs/GLOSSARY.md +43 -0
  7. package/ai-docs/README.md +138 -0
  8. package/ai-docs/REVIEW_CHECKLIST.md +41 -0
  9. package/ai-docs/RULES.md +444 -0
  10. package/ai-docs/SECURITY.md +52 -0
  11. package/ai-docs/SERVICE_STATE.md +52 -0
  12. package/ai-docs/SPEC_INDEX.md +65 -0
  13. package/ai-docs/adr/0001-spec-source-policy.md +55 -0
  14. package/ai-docs/adr/README.md +8 -0
  15. package/ai-docs/adr/_adr-template.md +31 -0
  16. package/ai-docs/contact-center-spec.md +385 -0
  17. package/ai-docs/features/consult-transfer-list-policy/spec/feature-spec.md +362 -0
  18. package/ai-docs/features/contact-owner-change-refactor.md +78 -0
  19. package/ai-docs/features/generated-spec-conformance-fidelity-remediation/spec/feature-spec.md +117 -0
  20. package/ai-docs/features/residual-warning-coverage-completion/spec/feature-spec.md +203 -0
  21. package/ai-docs/features/validator-code-fidelity-drift-fix/spec/feature-spec.md +315 -0
  22. package/ai-docs/patterns/event-driven-patterns.md +485 -0
  23. package/ai-docs/patterns/testing-patterns.md +480 -0
  24. package/ai-docs/patterns/typescript-patterns.md +365 -0
  25. package/ai-docs/templates/README.md +102 -0
  26. package/ai-docs/templates/documentation/create-agents-md.md +240 -0
  27. package/ai-docs/templates/documentation/create-architecture-md.md +295 -0
  28. package/ai-docs/templates/existing-service/bug-fix.md +254 -0
  29. package/ai-docs/templates/existing-service/feature-enhancement.md +450 -0
  30. package/ai-docs/templates/new-method/00-master.md +80 -0
  31. package/ai-docs/templates/new-method/01-requirements.md +232 -0
  32. package/ai-docs/templates/new-method/02-implementation.md +295 -0
  33. package/ai-docs/templates/new-method/03-tests.md +201 -0
  34. package/ai-docs/templates/new-method/04-validation.md +141 -0
  35. package/ai-docs/templates/new-service/00-master.md +109 -0
  36. package/ai-docs/templates/new-service/01-pre-questions.md +159 -0
  37. package/ai-docs/templates/new-service/02-code-generation.md +346 -0
  38. package/ai-docs/templates/new-service/03-integration.md +178 -0
  39. package/ai-docs/templates/new-service/04-test-generation.md +205 -0
  40. package/ai-docs/templates/new-service/05-validation.md +145 -0
  41. package/dist/cc.js +888 -49
  42. package/dist/cc.js.map +1 -1
  43. package/dist/config.js +13 -0
  44. package/dist/config.js.map +1 -1
  45. package/dist/constants.js +38 -3
  46. package/dist/constants.js.map +1 -1
  47. package/dist/index.js +54 -17
  48. package/dist/index.js.map +1 -1
  49. package/dist/metrics/MetricsManager.js +16 -0
  50. package/dist/metrics/MetricsManager.js.map +1 -1
  51. package/dist/metrics/behavioral-events.js +185 -0
  52. package/dist/metrics/behavioral-events.js.map +1 -1
  53. package/dist/metrics/constants.js +54 -4
  54. package/dist/metrics/constants.js.map +1 -1
  55. package/dist/services/AddressBook.js +18 -15
  56. package/dist/services/AddressBook.js.map +1 -1
  57. package/dist/services/AnswerCallOnWebexService.js +202 -0
  58. package/dist/services/AnswerCallOnWebexService.js.map +1 -0
  59. package/dist/services/ApiAiAssistant.js +369 -14
  60. package/dist/services/ApiAiAssistant.js.map +1 -1
  61. package/dist/services/EntryPoint.js +46 -68
  62. package/dist/services/EntryPoint.js.map +1 -1
  63. package/dist/services/Queue.js +27 -22
  64. package/dist/services/Queue.js.map +1 -1
  65. package/dist/services/UserPreference.js +427 -0
  66. package/dist/services/UserPreference.js.map +1 -0
  67. package/dist/services/WebCallingService.js +10 -2
  68. package/dist/services/WebCallingService.js.map +1 -1
  69. package/dist/services/WebexCrossClientService.js +225 -0
  70. package/dist/services/WebexCrossClientService.js.map +1 -0
  71. package/dist/services/WxAppTelephonyMercurySync.js +111 -0
  72. package/dist/services/WxAppTelephonyMercurySync.js.map +1 -0
  73. package/dist/services/config/Util.js +48 -48
  74. package/dist/services/config/Util.js.map +1 -1
  75. package/dist/services/config/constants.js +56 -78
  76. package/dist/services/config/constants.js.map +1 -1
  77. package/dist/services/config/index.js +100 -226
  78. package/dist/services/config/index.js.map +1 -1
  79. package/dist/services/config/types.js +93 -24
  80. package/dist/services/config/types.js.map +1 -1
  81. package/dist/services/constants.js +11 -1
  82. package/dist/services/constants.js.map +1 -1
  83. package/dist/services/core/Err.js.map +1 -1
  84. package/dist/services/core/Utils.js +131 -32
  85. package/dist/services/core/Utils.js.map +1 -1
  86. package/dist/services/core/WebexRequest.js +6 -2
  87. package/dist/services/core/WebexRequest.js.map +1 -1
  88. package/dist/services/core/aqm-reqs.js +17 -11
  89. package/dist/services/core/aqm-reqs.js.map +1 -1
  90. package/dist/services/core/constants.js +9 -1
  91. package/dist/services/core/constants.js.map +1 -1
  92. package/dist/services/core/types.js.map +1 -1
  93. package/dist/services/core/websocket/WebSocketManager.js +19 -2
  94. package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
  95. package/dist/services/core/websocket/types.js.map +1 -1
  96. package/dist/services/index.js +1 -1
  97. package/dist/services/index.js.map +1 -1
  98. package/dist/services/task/Task.js +955 -0
  99. package/dist/services/task/Task.js.map +1 -0
  100. package/dist/services/task/TaskFactory.js +50 -0
  101. package/dist/services/task/TaskFactory.js.map +1 -0
  102. package/dist/services/task/TaskManager.js +1272 -605
  103. package/dist/services/task/TaskManager.js.map +1 -1
  104. package/dist/services/task/TaskUtils.js +221 -27
  105. package/dist/services/task/TaskUtils.js.map +1 -1
  106. package/dist/services/task/WebexCallingUtils.js +70 -0
  107. package/dist/services/task/WebexCallingUtils.js.map +1 -0
  108. package/dist/services/task/constants.js +19 -2
  109. package/dist/services/task/constants.js.map +1 -1
  110. package/dist/services/task/contact.js +29 -0
  111. package/dist/services/task/contact.js.map +1 -1
  112. package/dist/services/task/digital/Digital.js +78 -0
  113. package/dist/services/task/digital/Digital.js.map +1 -0
  114. package/dist/services/task/state-machine/TaskStateMachine.js +982 -0
  115. package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -0
  116. package/dist/services/task/state-machine/actions.js +572 -0
  117. package/dist/services/task/state-machine/actions.js.map +1 -0
  118. package/dist/services/task/state-machine/constants.js +161 -0
  119. package/dist/services/task/state-machine/constants.js.map +1 -0
  120. package/dist/services/task/state-machine/guards.js +379 -0
  121. package/dist/services/task/state-machine/guards.js.map +1 -0
  122. package/dist/services/task/state-machine/index.js +53 -0
  123. package/dist/services/task/state-machine/index.js.map +1 -0
  124. package/dist/services/task/state-machine/types.js +54 -0
  125. package/dist/services/task/state-machine/types.js.map +1 -0
  126. package/dist/services/task/state-machine/uiControlsComputer.js +703 -0
  127. package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -0
  128. package/dist/services/task/taskDataNormalizer.js +99 -0
  129. package/dist/services/task/taskDataNormalizer.js.map +1 -0
  130. package/dist/services/task/types.js +215 -5
  131. package/dist/services/task/types.js.map +1 -1
  132. package/dist/services/task/voice/Voice.js +1504 -0
  133. package/dist/services/task/voice/Voice.js.map +1 -0
  134. package/dist/services/task/voice/WebRTC.js +152 -0
  135. package/dist/services/task/voice/WebRTC.js.map +1 -0
  136. package/dist/services/task/voice/wxAppOfferObservability.js +145 -0
  137. package/dist/services/task/voice/wxAppOfferObservability.js.map +1 -0
  138. package/dist/services/task/voice/wxAppVoiceMethods.js +395 -0
  139. package/dist/services/task/voice/wxAppVoiceMethods.js.map +1 -0
  140. package/dist/services/wxAppDiagnosticLogging.js +159 -0
  141. package/dist/services/wxAppDiagnosticLogging.js.map +1 -0
  142. package/dist/services/wxAppTelephonyUtils.js +19 -0
  143. package/dist/services/wxAppTelephonyUtils.js.map +1 -0
  144. package/dist/types/cc.d.ts +152 -9
  145. package/dist/types/config.d.ts +13 -0
  146. package/dist/types/constants.d.ts +36 -1
  147. package/dist/types/index.d.ts +54 -20
  148. package/dist/types/metrics/MetricsManager.d.ts +6 -0
  149. package/dist/types/metrics/constants.d.ts +48 -1
  150. package/dist/types/services/AddressBook.d.ts +2 -1
  151. package/dist/types/services/AnswerCallOnWebexService.d.ts +38 -0
  152. package/dist/types/services/ApiAiAssistant.d.ts +67 -5
  153. package/dist/types/services/EntryPoint.d.ts +7 -5
  154. package/dist/types/services/Queue.d.ts +5 -3
  155. package/dist/types/services/UserPreference.d.ts +118 -0
  156. package/dist/types/services/WebexCrossClientService.d.ts +32 -0
  157. package/dist/types/services/WxAppTelephonyMercurySync.d.ts +28 -0
  158. package/dist/types/services/config/Util.d.ts +4 -8
  159. package/dist/types/services/config/constants.d.ts +49 -76
  160. package/dist/types/services/config/index.d.ts +16 -64
  161. package/dist/types/services/config/types.d.ts +240 -114
  162. package/dist/types/services/constants.d.ts +9 -0
  163. package/dist/types/services/core/Err.d.ts +2 -0
  164. package/dist/types/services/core/Utils.d.ts +43 -13
  165. package/dist/types/services/core/WebexRequest.d.ts +1 -0
  166. package/dist/types/services/core/constants.d.ts +7 -0
  167. package/dist/types/services/core/types.d.ts +2 -0
  168. package/dist/types/services/core/websocket/WebSocketManager.d.ts +1 -0
  169. package/dist/types/services/core/websocket/types.d.ts +1 -1
  170. package/dist/types/services/index.d.ts +1 -1
  171. package/dist/types/services/task/Task.d.ts +186 -0
  172. package/dist/types/services/task/TaskFactory.d.ts +14 -0
  173. package/dist/types/services/task/TaskUtils.d.ts +54 -2
  174. package/dist/types/services/task/WebexCallingUtils.d.ts +11 -0
  175. package/dist/types/services/task/constants.d.ts +17 -0
  176. package/dist/types/services/task/contact.d.ts +4 -0
  177. package/dist/types/services/task/digital/Digital.d.ts +23 -0
  178. package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +1442 -0
  179. package/dist/types/services/task/state-machine/actions.d.ts +10 -0
  180. package/dist/types/services/task/state-machine/constants.d.ts +107 -0
  181. package/dist/types/services/task/state-machine/guards.d.ts +103 -0
  182. package/dist/types/services/task/state-machine/index.d.ts +13 -0
  183. package/dist/types/services/task/state-machine/types.d.ts +277 -0
  184. package/dist/types/services/task/state-machine/uiControlsComputer.d.ts +9 -0
  185. package/dist/types/services/task/taskDataNormalizer.d.ts +10 -0
  186. package/dist/types/services/task/types.d.ts +738 -66
  187. package/dist/types/services/task/voice/Voice.d.ts +241 -0
  188. package/dist/types/services/task/voice/WebRTC.d.ts +54 -0
  189. package/dist/types/services/task/voice/wxAppOfferObservability.d.ts +39 -0
  190. package/dist/types/services/task/voice/wxAppVoiceMethods.d.ts +68 -0
  191. package/dist/types/services/wxAppDiagnosticLogging.d.ts +63 -0
  192. package/dist/types/services/wxAppTelephonyUtils.d.ts +5 -0
  193. package/dist/types/types.d.ts +213 -11
  194. package/dist/types/utils/PageCache.d.ts +20 -3
  195. package/dist/types/webex.d.ts +1 -0
  196. package/dist/types.js +168 -6
  197. package/dist/types.js.map +1 -1
  198. package/dist/utils/PageCache.js +19 -5
  199. package/dist/utils/PageCache.js.map +1 -1
  200. package/dist/webex.js +22 -2
  201. package/dist/webex.js.map +1 -1
  202. package/package.json +16 -12
  203. package/src/cc.ts +1137 -67
  204. package/src/config.ts +13 -0
  205. package/src/constants.ts +39 -1
  206. package/src/index.ts +62 -15
  207. package/src/metrics/MetricsManager.ts +16 -0
  208. package/src/metrics/ai-docs/AGENTS.md +350 -0
  209. package/src/metrics/ai-docs/ARCHITECTURE.md +338 -0
  210. package/src/metrics/ai-docs/metrics-spec.md +971 -0
  211. package/src/metrics/behavioral-events.ts +190 -0
  212. package/src/metrics/constants.ts +59 -4
  213. package/src/services/AddressBook.ts +17 -6
  214. package/src/services/AnswerCallOnWebexService.ts +239 -0
  215. package/src/services/ApiAiAssistant.ts +494 -15
  216. package/src/services/EntryPoint.ts +59 -60
  217. package/src/services/Queue.ts +29 -12
  218. package/src/services/UserPreference.ts +509 -0
  219. package/src/services/WebCallingService.ts +16 -2
  220. package/src/services/WebexCrossClientService.ts +298 -0
  221. package/src/services/WxAppTelephonyMercurySync.ts +142 -0
  222. package/src/services/agent/ai-docs/AGENTS.md +240 -0
  223. package/src/services/agent/ai-docs/ARCHITECTURE.md +304 -0
  224. package/src/services/agent/ai-docs/agent-spec.md +505 -0
  225. package/src/services/ai-docs/AGENTS.md +386 -0
  226. package/src/services/ai-docs/services-spec.md +512 -0
  227. package/src/services/config/Util.ts +54 -84
  228. package/src/services/config/ai-docs/AGENTS.md +250 -0
  229. package/src/services/config/ai-docs/ARCHITECTURE.md +413 -0
  230. package/src/services/config/ai-docs/config-spec.md +669 -0
  231. package/src/services/config/constants.ts +63 -85
  232. package/src/services/config/index.ts +116 -277
  233. package/src/services/config/types.ts +229 -125
  234. package/src/services/constants.ts +10 -0
  235. package/src/services/core/Err.ts +1 -0
  236. package/src/services/core/Utils.ts +151 -37
  237. package/src/services/core/WebexRequest.ts +3 -1
  238. package/src/services/core/ai-docs/AGENTS.md +381 -0
  239. package/src/services/core/ai-docs/ARCHITECTURE.md +698 -0
  240. package/src/services/core/ai-docs/core-spec.md +797 -0
  241. package/src/services/core/aqm-reqs.ts +18 -12
  242. package/src/services/core/constants.ts +8 -0
  243. package/src/services/core/types.ts +33 -1
  244. package/src/services/core/websocket/WebSocketManager.ts +28 -2
  245. package/src/services/core/websocket/types.ts +1 -1
  246. package/src/services/index.ts +1 -1
  247. package/src/services/task/Task.ts +1211 -0
  248. package/src/services/task/TaskFactory.ts +82 -0
  249. package/src/services/task/TaskManager.ts +1585 -724
  250. package/src/services/task/TaskUtils.ts +316 -25
  251. package/src/services/task/WebexCallingUtils.ts +136 -0
  252. package/src/services/task/ai-docs/AGENTS.md +457 -0
  253. package/src/services/task/ai-docs/ARCHITECTURE.md +595 -0
  254. package/src/services/task/ai-docs/task-spec.md +1501 -0
  255. package/src/services/task/constants.ts +18 -0
  256. package/src/services/task/contact.ts +30 -0
  257. package/src/services/task/digital/Digital.ts +102 -0
  258. package/src/services/task/state-machine/TaskStateMachine.ts +1320 -0
  259. package/src/services/task/state-machine/actions.ts +741 -0
  260. package/src/services/task/state-machine/ai-docs/AGENTS.md +460 -0
  261. package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +1156 -0
  262. package/src/services/task/state-machine/ai-docs/task-state-machine-spec.md +2247 -0
  263. package/src/services/task/state-machine/constants.ts +172 -0
  264. package/src/services/task/state-machine/guards.ts +442 -0
  265. package/src/services/task/state-machine/index.ts +28 -0
  266. package/src/services/task/state-machine/types.ts +258 -0
  267. package/src/services/task/state-machine/uiControlsComputer.ts +1135 -0
  268. package/src/services/task/taskDataNormalizer.ts +137 -0
  269. package/src/services/task/types.ts +918 -70
  270. package/src/services/task/voice/Voice.ts +1878 -0
  271. package/src/services/task/voice/WebRTC.ts +194 -0
  272. package/src/services/task/voice/wxAppOfferObservability.ts +204 -0
  273. package/src/services/task/voice/wxAppVoiceMethods.ts +575 -0
  274. package/src/services/wxAppDiagnosticLogging.ts +286 -0
  275. package/src/services/wxAppTelephonyUtils.ts +14 -0
  276. package/src/types.ts +272 -13
  277. package/src/utils/AGENTS.md +289 -0
  278. package/src/utils/PageCache.ts +38 -5
  279. package/src/utils/ai-docs/utils-spec.md +391 -0
  280. package/src/webex.js +10 -0
  281. package/test/unit/fixtures/aiSummaryTestUtils.ts +40 -0
  282. package/test/unit/spec/cc.ts +3553 -107
  283. package/test/unit/spec/index.ts +885 -0
  284. package/test/unit/spec/logger-proxy.ts +70 -0
  285. package/test/unit/spec/metrics/MetricsManager.ts +25 -0
  286. package/test/unit/spec/metrics/behavioral-events.ts +60 -0
  287. package/test/unit/spec/services/AddressBook.ts +37 -6
  288. package/test/unit/spec/services/AnswerCallOnWebexService.ts +264 -0
  289. package/test/unit/spec/services/ApiAiAssistant.ts +442 -23
  290. package/test/unit/spec/services/EntryPoint.ts +87 -40
  291. package/test/unit/spec/services/Queue.ts +123 -12
  292. package/test/unit/spec/services/UserPreference.ts +401 -0
  293. package/test/unit/spec/services/WebCallingService.ts +45 -1
  294. package/test/unit/spec/services/WebexCrossClientService.ts +509 -0
  295. package/test/unit/spec/services/WxAppTelephonyMercurySync.ts +136 -0
  296. package/test/unit/spec/services/config/Util.ts +501 -0
  297. package/test/unit/spec/services/config/index.ts +317 -547
  298. package/test/unit/spec/services/core/Utils.ts +447 -8
  299. package/test/unit/spec/services/core/WebexRequest.ts +8 -7
  300. package/test/unit/spec/services/core/aqm-reqs.ts +142 -1
  301. package/test/unit/spec/services/core/websocket/WebSocketManager.ts +129 -53
  302. package/test/unit/spec/services/task/AutoWrapup.ts +63 -0
  303. package/test/unit/spec/services/task/Task.ts +2723 -0
  304. package/test/unit/spec/services/task/TaskFactory.ts +116 -0
  305. package/test/unit/spec/services/task/TaskManager.ts +4734 -1769
  306. package/test/unit/spec/services/task/TaskUtils.ts +307 -0
  307. package/test/unit/spec/services/task/WebexCallingUtils.ts +153 -0
  308. package/test/unit/spec/services/task/contact.ts +33 -0
  309. package/test/unit/spec/services/task/digital/Digital.ts +105 -0
  310. package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +4060 -0
  311. package/test/unit/spec/services/task/state-machine/guards.ts +839 -0
  312. package/test/unit/spec/services/task/state-machine/types.ts +18 -0
  313. package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +3101 -0
  314. package/test/unit/spec/services/task/taskTestUtils.ts +87 -0
  315. package/test/unit/spec/services/task/voice/Voice.ts +2355 -0
  316. package/test/unit/spec/services/task/voice/WebRTC.ts +235 -0
  317. package/test/unit/spec/services/task/voice/wxAppOfferObservability.ts +361 -0
  318. package/test/unit/spec/services/task/voice/wxAppVoiceMethods.ts +719 -0
  319. package/test/unit/spec/services/wxAppDiagnosticLogging.ts +179 -0
  320. package/test/unit/spec/wellnessSampleUtils.ts +288 -0
  321. package/typedoc.md +1 -1
  322. package/umd/contact-center.min.js +2 -2
  323. package/umd/contact-center.min.js.map +1 -1
  324. package/dist/services/task/index.js +0 -1530
  325. package/dist/services/task/index.js.map +0 -1
  326. package/dist/types/services/task/index.d.ts +0 -650
  327. package/src/services/task/index.ts +0 -1806
  328. package/test/unit/spec/services/task/index.ts +0 -2205
@@ -1,17 +1,24 @@
1
+ import {v4 as uuidv4} from 'uuid';
1
2
  import LoggerProxy from '../logger-proxy';
2
3
  import MetricsManager from '../metrics/MetricsManager';
3
4
  import {METRIC_EVENT_NAMES} from '../metrics/constants';
4
- import {CC_FILE, METHODS} from '../constants';
5
+ import {AI_SUMMARY_ERROR_CODES, CC_FILE, METHODS} from '../constants';
5
6
  import {
6
7
  HTTP_METHODS,
7
8
  WebexSDK,
8
9
  IHttpResponse,
9
- TranscriptAction,
10
10
  AIAssistantEventType,
11
11
  AIAssistantEventName,
12
12
  HistoricTranscriptsResponse,
13
+ RealTimeAssistanceParams,
14
+ RealTimeAssistanceUserActionParams,
15
+ RespondToWellnessBreakParams,
16
+ WellnessBreakUserAction,
17
+ WELLNESS_BREAK_USER_ACTIONS,
18
+ GenericError,
13
19
  } from '../types';
14
20
  import {getErrorDetails} from './core/Utils';
21
+ import type {PendingRtdRequest, RtdRequestOptions} from './core/types';
15
22
  import {
16
23
  AI_ASSISTANT_BASE_URL_TEMPLATE,
17
24
  AI_ASSISTANT_ENV_MAP,
@@ -20,6 +27,12 @@ import {
20
27
  } from './constants';
21
28
  import {AIFeatureFlags} from './config/types';
22
29
 
30
+ type WellnessBreakContextProvider = () => {
31
+ isWellnessBreakEnabled: boolean;
32
+ agentId?: string;
33
+ agentSessionId?: string;
34
+ };
35
+
23
36
  /**
24
37
  * ApiAIAssistant provides AI Assistant APIs for transcript controls.
25
38
  * @public
@@ -27,10 +40,26 @@ import {AIFeatureFlags} from './config/types';
27
40
  export class ApiAIAssistant {
28
41
  private webex: WebexSDK;
29
42
  private metricsManager: MetricsManager;
43
+ /** @internal Current AI flags from the agent configuration. */
30
44
  public aiFeature: AIFeatureFlags;
45
+ private pendingRtdRequests = new Map<string, PendingRtdRequest<unknown>>();
46
+ private readonly wellnessContextProvider?: WellnessBreakContextProvider;
47
+
48
+ private createWellnessError(reason: string): GenericError {
49
+ const error = new Error(reason) as GenericError;
50
+ error.details = {
51
+ type: 'SDK_VALIDATION_ERROR',
52
+ orgId: this.webex.credentials.getOrgId(),
53
+ trackingId: '',
54
+ data: {reason},
55
+ };
56
+
57
+ return error;
58
+ }
31
59
 
32
- constructor(webex: WebexSDK) {
60
+ constructor(webex: WebexSDK, wellnessContextProvider?: WellnessBreakContextProvider) {
33
61
  this.webex = webex;
62
+ this.wellnessContextProvider = wellnessContextProvider;
34
63
  this.metricsManager = MetricsManager.getInstance({webex});
35
64
  }
36
65
 
@@ -38,12 +67,152 @@ export class ApiAIAssistant {
38
67
  this.aiFeature = aiFeature;
39
68
  }
40
69
 
70
+ /**
71
+ * Validates a caller-supplied identifier (agentId/interactionId) before it is used to
72
+ * construct a request. Accepts a non-empty alphanumeric identifier that may contain
73
+ * hyphens or underscores.
74
+ * @param value - the identifier to validate
75
+ * @returns {boolean} true when the identifier is a non-empty, well-formed string
76
+ * @private
77
+ */
78
+ private isValidTranscriptIdentifier(value: unknown): boolean {
79
+ return typeof value === 'string' && /^[A-Za-z0-9_-]{1,128}$/.test(value);
80
+ }
81
+
82
+ private async sendWellnessBreakAction(
83
+ action: WellnessBreakUserAction,
84
+ method: string
85
+ ): Promise<void> {
86
+ this.metricsManager.timeEvent([
87
+ METRIC_EVENT_NAMES.AI_ASSISTANT_WELLNESS_ACTION_ACCEPTED,
88
+ METRIC_EVENT_NAMES.AI_ASSISTANT_WELLNESS_ACTION_FAILED,
89
+ ]);
90
+
91
+ try {
92
+ const context = this.wellnessContextProvider?.();
93
+ const agentId = context?.agentId?.trim();
94
+ const agentSessionId = context?.agentSessionId?.trim();
95
+ const orgId = this.webex.credentials.getOrgId()?.trim();
96
+
97
+ if (context?.isWellnessBreakEnabled !== true) {
98
+ throw this.createWellnessError('WELLNESS_BREAK_NOT_ENABLED');
99
+ }
100
+ if (!orgId) {
101
+ throw this.createWellnessError('WELLNESS_BREAK_ORG_ID_REQUIRED');
102
+ }
103
+ if (!agentId) {
104
+ throw this.createWellnessError('WELLNESS_BREAK_AGENT_ID_REQUIRED');
105
+ }
106
+ if (!agentSessionId) {
107
+ throw this.createWellnessError('WELLNESS_BREAK_AGENT_SESSION_REQUIRED');
108
+ }
109
+
110
+ const baseUrl = this.getBaseUrl();
111
+ const response = (await this.webex.request({
112
+ uri: `${baseUrl}${AI_ASSISTANT_API_URLS.EVENT}`,
113
+ method: HTTP_METHODS.POST,
114
+ addAuthHeader: true,
115
+ body: {
116
+ agentId,
117
+ orgId,
118
+ eventType: AIAssistantEventType.CUSTOM_EVENT,
119
+ eventName: AIAssistantEventName.WELLNESS_BREAK_ACTION,
120
+ eventDetails: {
121
+ data: {
122
+ action,
123
+ agentSessionId,
124
+ actionTimeStamp: Date.now(),
125
+ },
126
+ },
127
+ },
128
+ })) as IHttpResponse;
129
+
130
+ if (response.statusCode !== 202) {
131
+ throw this.createWellnessError(
132
+ `WELLNESS_BREAK_ACTION_UNEXPECTED_STATUS_${response.statusCode}`
133
+ );
134
+ }
135
+
136
+ this.metricsManager.trackEvent(
137
+ METRIC_EVENT_NAMES.AI_ASSISTANT_WELLNESS_ACTION_ACCEPTED,
138
+ {action},
139
+ ['operational']
140
+ );
141
+ LoggerProxy.log('Wellness action accepted by AI Assistant', {
142
+ module: CC_FILE,
143
+ method,
144
+ data: {action},
145
+ });
146
+ } catch (error) {
147
+ this.metricsManager.trackEvent(
148
+ METRIC_EVENT_NAMES.AI_ASSISTANT_WELLNESS_ACTION_FAILED,
149
+ {
150
+ action,
151
+ error: error instanceof Error ? error.message : String(error),
152
+ },
153
+ ['operational']
154
+ );
155
+ const {error: detailedError} = getErrorDetails(error, method, CC_FILE);
156
+ throw detailedError;
157
+ }
158
+ }
159
+
160
+ /**
161
+ * Requests an Agent Wellness Break.
162
+ * The promise resolves when the HTTP request is accepted with status 202; the later
163
+ * approval or denial is delivered independently through a wellness notification.
164
+ * @returns A promise that resolves with no value after HTTP acceptance
165
+ * @throws Structured Contact Center error when disabled, stale, invalid, or delivery fails
166
+ * @example
167
+ * await webex.cc.apiAIAssistant.requestWellnessBreak();
168
+ * @public
169
+ */
170
+ public async requestWellnessBreak(): Promise<void> {
171
+ return this.sendWellnessBreakAction(
172
+ WELLNESS_BREAK_USER_ACTIONS.REQUESTED,
173
+ METHODS.REQUEST_WELLNESS_BREAK
174
+ );
175
+ }
176
+
177
+ /**
178
+ * Responds to a backend-provided Agent Wellness Break offer.
179
+ * The promise resolves when the HTTP request is accepted with status 202 and does not
180
+ * wait for a WebSocket completion event.
181
+ * @param params - ACCEPTED, REJECTED, or NO_RESPONSE
182
+ * @returns A promise that resolves with no value after HTTP acceptance
183
+ * @throws Structured Contact Center error when disabled, stale, invalid, or delivery fails
184
+ * @example
185
+ * await webex.cc.apiAIAssistant.respondToWellnessBreak({
186
+ * action: WELLNESS_BREAK_USER_ACTIONS.ACCEPTED,
187
+ * });
188
+ * @public
189
+ */
190
+ public async respondToWellnessBreak(params: RespondToWellnessBreakParams): Promise<void> {
191
+ const {action} = params;
192
+ if (
193
+ ![
194
+ WELLNESS_BREAK_USER_ACTIONS.ACCEPTED,
195
+ WELLNESS_BREAK_USER_ACTIONS.REJECTED,
196
+ WELLNESS_BREAK_USER_ACTIONS.NO_RESPONSE,
197
+ ].includes(action)
198
+ ) {
199
+ const {error} = getErrorDetails(
200
+ this.createWellnessError('WELLNESS_BREAK_ACTION_INVALID'),
201
+ METHODS.RESPOND_TO_WELLNESS_BREAK,
202
+ CC_FILE
203
+ );
204
+ throw error;
205
+ }
206
+
207
+ return this.sendWellnessBreakAction(action, METHODS.RESPOND_TO_WELLNESS_BREAK);
208
+ }
209
+
41
210
  private getBaseUrl(): string {
42
211
  const wccApiGatewayUrl = this.webex.internal.services.get(WCC_API_GATEWAY) || '';
43
212
 
44
213
  if (!wccApiGatewayUrl) {
45
214
  const {error: detailedError} = getErrorDetails(
46
- new Error('AI_ASSISTANT_BASE_URL_NOT_AVAILABLE'),
215
+ new Error(AI_SUMMARY_ERROR_CODES.AI_ASSISTANT_BASE_URL_NOT_AVAILABLE),
47
216
  METHODS.GET_BASE_URL,
48
217
  CC_FILE
49
218
  );
@@ -58,9 +227,10 @@ export class ApiAIAssistant {
58
227
  }
59
228
 
60
229
  const resolvedEnv = AI_ASSISTANT_ENV_MAP[hostname];
230
+
61
231
  if (!resolvedEnv) {
62
232
  const {error: detailedError} = getErrorDetails(
63
- new Error('AI_ASSISTANT_BASE_URL_NOT_AVAILABLE'),
233
+ new Error(AI_SUMMARY_ERROR_CODES.AI_ASSISTANT_BASE_URL_NOT_AVAILABLE),
64
234
  METHODS.GET_BASE_URL,
65
235
  CC_FILE
66
236
  );
@@ -70,26 +240,131 @@ export class ApiAIAssistant {
70
240
  return AI_ASSISTANT_BASE_URL_TEMPLATE.replace('%s', resolvedEnv);
71
241
  }
72
242
 
243
+ private static getRtdRequestKey(rtdEventType: string, correlationId: string): string {
244
+ return JSON.stringify([rtdEventType, correlationId]);
245
+ }
246
+
247
+ private removeRtdRequest<T>(
248
+ rtdEventType: string,
249
+ correlationId: string,
250
+ settle?: (request: PendingRtdRequest<T>) => void
251
+ ): PendingRtdRequest<T> | undefined {
252
+ const key = ApiAIAssistant.getRtdRequestKey(rtdEventType, correlationId);
253
+ const request = this.pendingRtdRequests.get(key) as PendingRtdRequest<T> | undefined;
254
+
255
+ if (!request) {
256
+ return undefined;
257
+ }
258
+
259
+ if (request.timeoutId) {
260
+ clearTimeout(request.timeoutId);
261
+ }
262
+
263
+ settle?.(request);
264
+ this.pendingRtdRequests.delete(key);
265
+
266
+ return request;
267
+ }
268
+
269
+ /** Sends an AI event and waits for its matching RTD response. @internal */
270
+ public async requestAndWaitForRtd<T>(options: RtdRequestOptions): Promise<T> {
271
+ const key = ApiAIAssistant.getRtdRequestKey(options.rtdEventType, options.correlationId);
272
+ let resolveResult: (payload: T) => void = () => undefined;
273
+ let rejectResult: (error: Error) => void = () => undefined;
274
+ const result = new Promise<T>((resolve, reject) => {
275
+ resolveResult = resolve;
276
+ rejectResult = reject;
277
+ });
278
+ const previousRequest = this.pendingRtdRequests.get(key);
279
+ if (previousRequest?.timeoutId) {
280
+ clearTimeout(previousRequest.timeoutId);
281
+ }
282
+ const request: PendingRtdRequest<T> = {
283
+ correlationId: options.correlationId,
284
+ rtdEventType: options.rtdEventType,
285
+ resolve: resolveResult,
286
+ reject: rejectResult,
287
+ };
288
+
289
+ request.timeoutId = setTimeout(() => {
290
+ this.removeRtdRequest<T>(options.rtdEventType, options.correlationId, (currentRequest) => {
291
+ currentRequest.reject(options.createTimeoutError());
292
+ });
293
+ }, options.timeoutMs);
294
+ this.pendingRtdRequests.set(key, request as PendingRtdRequest<unknown>);
295
+ const publishTimestamp = options.publishTimestamp ?? Date.now();
296
+ const acknowledgement = Promise.resolve()
297
+ .then(() =>
298
+ this.sendEvent(
299
+ options.agentId,
300
+ options.interactionId,
301
+ options.eventType,
302
+ options.eventName,
303
+ options.eventMetaData,
304
+ undefined,
305
+ undefined,
306
+ publishTimestamp,
307
+ options.timeout
308
+ )
309
+ )
310
+ .catch((error) => {
311
+ this.removeRtdRequest(options.rtdEventType, options.correlationId);
312
+ throw error;
313
+ });
314
+
315
+ const [payload] = await Promise.all([result, acknowledgement]);
316
+
317
+ return payload;
318
+ }
319
+
320
+ /** Resolves a pending request from a parsed RTD event. @internal */
321
+ public resolveFromRtdEvent<T>(
322
+ rtdEventType: string,
323
+ correlationId: string,
324
+ payload: T
325
+ ): 'resolved' | 'not-found' {
326
+ const request = this.removeRtdRequest<T>(rtdEventType, correlationId, (currentRequest) => {
327
+ currentRequest.resolve(payload);
328
+ });
329
+
330
+ return request ? 'resolved' : 'not-found';
331
+ }
332
+
333
+ /** Clears pending RTD requests when the RTD lifecycle ends. @internal */
334
+ public clearAllRtdRequests(): void {
335
+ Array.from(this.pendingRtdRequests.values()).forEach((request) => {
336
+ this.removeRtdRequest(request.rtdEventType, request.correlationId, (currentRequest) => {
337
+ currentRequest.reject(new Error('RTD request cleared'));
338
+ });
339
+ });
340
+ }
341
+
73
342
  /**
74
343
  * Sends an event to the AI Assistant service.
75
344
  * @param agentId - agent identifier
76
345
  * @param interactionId - interaction/conversation identifier
77
346
  * @param eventType - the type of event (e.g. 'CUSTOM_EVENT')
78
347
  * @param eventName - the name of the event (e.g. 'GET_TRANSCRIPTS')
79
- * @param action - action within eventDetails (e.g. 'START' or 'STOP')
348
+ * @param eventMetaData - event-specific fields to include in eventDetails.data
349
+ * @param languageCode - language code within eventDetails.data
350
+ * @param trackingId - tracking identifier within eventDetails.data
80
351
  */
81
352
  public async sendEvent(
82
353
  agentId: string,
83
354
  interactionId: string,
84
355
  eventType: AIAssistantEventType,
85
356
  eventName: AIAssistantEventName,
86
- action: TranscriptAction
357
+ eventMetaData?: Record<string, unknown>,
358
+ languageCode?: string,
359
+ trackingId?: string,
360
+ publishTimestamp?: number,
361
+ timeout?: number
87
362
  ): Promise<Record<string, unknown>> {
88
363
  LoggerProxy.info('Sending event', {
89
364
  module: CC_FILE,
90
365
  method: METHODS.SEND_EVENT,
91
366
  interactionId,
92
- data: {eventType, eventName, action},
367
+ data: {eventType, eventName, eventMetaData},
93
368
  });
94
369
  this.metricsManager.timeEvent([
95
370
  METRIC_EVENT_NAMES.AI_ASSISTANT_SEND_EVENT_SUCCESS,
@@ -99,28 +374,33 @@ export class ApiAIAssistant {
99
374
  try {
100
375
  const baseUrl = this.getBaseUrl();
101
376
  const orgId = this.webex.credentials.getOrgId();
377
+ const data = {
378
+ ...eventMetaData,
379
+ interactionId,
380
+ actionTimeStamp: String(Date.now()),
381
+ languageCode,
382
+ trackingId,
383
+ };
102
384
  const response = (await this.webex.request({
103
385
  uri: `${baseUrl}${AI_ASSISTANT_API_URLS.EVENT}`,
104
386
  method: HTTP_METHODS.POST,
105
387
  addAuthHeader: true,
388
+ ...(timeout !== undefined ? {timeout} : {}),
106
389
  body: {
107
390
  agentId,
108
391
  orgId,
109
392
  eventType,
110
393
  eventName,
394
+ ...(publishTimestamp !== undefined ? {publishTimestamp} : {}),
111
395
  eventDetails: {
112
- data: {
113
- interactionId,
114
- action,
115
- actionTimeStamp: String(Date.now()),
116
- },
396
+ data,
117
397
  },
118
398
  },
119
399
  })) as IHttpResponse;
120
400
 
121
401
  this.metricsManager.trackEvent(
122
402
  METRIC_EVENT_NAMES.AI_ASSISTANT_SEND_EVENT_SUCCESS,
123
- {agentId, orgId, interactionId, eventType, eventName, action},
403
+ {agentId, orgId, interactionId, eventType, eventName},
124
404
  ['operational']
125
405
  );
126
406
 
@@ -132,7 +412,6 @@ export class ApiAIAssistant {
132
412
  interactionId,
133
413
  eventType,
134
414
  eventName,
135
- action,
136
415
  error: error instanceof Error ? error.message : String(error),
137
416
  },
138
417
  ['operational']
@@ -143,6 +422,193 @@ export class ApiAIAssistant {
143
422
  }
144
423
  }
145
424
 
425
+ /**
426
+ * Requests real-time assistance for an interaction.
427
+ *
428
+ * @param params - Real-time assistance request parameters
429
+ * @returns HTTP response body from the AI Assistant event API
430
+ * @public
431
+ */
432
+ public async getRealTimeAssistance(params: RealTimeAssistanceParams) {
433
+ const {agentId, interactionId, context} = params;
434
+ const trimmedContext = context?.trim();
435
+ const languageCode = params.languageCode ?? 'en';
436
+ const trackingId = `WX_CC_SDK_${uuidv4()}`;
437
+ const eventName = trimmedContext
438
+ ? AIAssistantEventName.ADD_SUGGESTIONS_EXTRA_CONTEXT
439
+ : AIAssistantEventName.GET_SUGGESTIONS;
440
+
441
+ const loggerContext = {
442
+ module: CC_FILE,
443
+ method: METHODS.GET_REAL_TIME_ASSISTANCE,
444
+ interactionId,
445
+ trackingId,
446
+ data: {eventName},
447
+ };
448
+
449
+ LoggerProxy.info('Requesting real-time assistance', loggerContext);
450
+
451
+ this.metricsManager.timeEvent([
452
+ METRIC_EVENT_NAMES.AI_ASSISTANT_GET_REAL_TIME_ASSISTANCE_SUCCESS,
453
+ METRIC_EVENT_NAMES.AI_ASSISTANT_GET_REAL_TIME_ASSISTANCE_FAILED,
454
+ ]);
455
+
456
+ try {
457
+ if (!this.aiFeature?.suggestedResponses?.enable) {
458
+ const {error: detailedError} = getErrorDetails(
459
+ new Error('SUGGESTED_RESPONSES_NOT_ENABLED'),
460
+ METHODS.GET_REAL_TIME_ASSISTANCE,
461
+ CC_FILE
462
+ );
463
+ throw detailedError;
464
+ }
465
+
466
+ const orgId = this.webex.credentials.getOrgId();
467
+
468
+ const response = await this.sendEvent(
469
+ agentId,
470
+ interactionId,
471
+ AIAssistantEventType.CUSTOM_EVENT,
472
+ eventName,
473
+ trimmedContext !== undefined ? {context: trimmedContext} : undefined,
474
+ languageCode,
475
+ trackingId
476
+ );
477
+
478
+ this.metricsManager.trackEvent(
479
+ METRIC_EVENT_NAMES.AI_ASSISTANT_GET_REAL_TIME_ASSISTANCE_SUCCESS,
480
+ {
481
+ agentId,
482
+ orgId,
483
+ interactionId,
484
+ eventName,
485
+ trackingId,
486
+ context,
487
+ },
488
+ ['operational']
489
+ );
490
+ LoggerProxy.log('Real-time assistance request succeeded', loggerContext);
491
+
492
+ return response;
493
+ } catch (error) {
494
+ LoggerProxy.error('Real-time assistance request failed', {...loggerContext, error});
495
+ this.metricsManager.trackEvent(
496
+ METRIC_EVENT_NAMES.AI_ASSISTANT_GET_REAL_TIME_ASSISTANCE_FAILED,
497
+ {
498
+ agentId,
499
+ interactionId,
500
+ trackingId,
501
+ eventName,
502
+ error: error instanceof Error ? error.message : String(error),
503
+ },
504
+ ['operational']
505
+ );
506
+
507
+ const {error: detailedError} = getErrorDetails(
508
+ error,
509
+ METHODS.GET_REAL_TIME_ASSISTANCE,
510
+ CC_FILE
511
+ );
512
+ throw detailedError;
513
+ }
514
+ }
515
+
516
+ /**
517
+ * Sends user action feedback for a real-time assistance adaptive card.
518
+ *
519
+ * @param params - Real-time assistance user action parameters
520
+ * @returns HTTP response body from the AI Assistant event API
521
+ * @public
522
+ */
523
+ public async sendRealTimeAssistanceUserAction(
524
+ params: RealTimeAssistanceUserActionParams
525
+ ): Promise<Record<string, unknown>> {
526
+ const {agentId, interactionId, adaptiveCardId, actionId} = params;
527
+ const actionType = 'Action.Submit';
528
+ const languageCode = params.languageCode ?? 'en';
529
+ const trackingId = `WX_CC_SDK_${uuidv4()}`;
530
+
531
+ const loggerContext = {
532
+ module: CC_FILE,
533
+ method: METHODS.SEND_REAL_TIME_ASSISTANCE_USER_ACTION,
534
+ interactionId,
535
+ trackingId,
536
+ data: {actionId, adaptiveCardId},
537
+ };
538
+
539
+ LoggerProxy.info('Sending real-time assistance user action', loggerContext);
540
+
541
+ this.metricsManager.timeEvent([
542
+ METRIC_EVENT_NAMES.AI_ASSISTANT_SEND_REAL_TIME_ASSISTANCE_USER_ACTION_SUCCESS,
543
+ METRIC_EVENT_NAMES.AI_ASSISTANT_SEND_REAL_TIME_ASSISTANCE_USER_ACTION_FAILED,
544
+ ]);
545
+
546
+ try {
547
+ if (!this.aiFeature?.suggestedResponses?.enable) {
548
+ const {error: detailedError} = getErrorDetails(
549
+ new Error('SUGGESTED_RESPONSES_NOT_ENABLED'),
550
+ METHODS.SEND_REAL_TIME_ASSISTANCE_USER_ACTION,
551
+ CC_FILE
552
+ );
553
+ throw detailedError;
554
+ }
555
+
556
+ const orgId = this.webex.credentials.getOrgId();
557
+ const response = await this.sendEvent(
558
+ agentId,
559
+ interactionId,
560
+ AIAssistantEventType.CUSTOM_EVENT,
561
+ AIAssistantEventName.SUGGESTED_RESPONSES_USER_ACTION,
562
+ {
563
+ adaptiveCardId,
564
+ userAction: {
565
+ actionType,
566
+ actionId,
567
+ },
568
+ },
569
+ languageCode,
570
+ trackingId
571
+ );
572
+
573
+ this.metricsManager.trackEvent(
574
+ METRIC_EVENT_NAMES.AI_ASSISTANT_SEND_REAL_TIME_ASSISTANCE_USER_ACTION_SUCCESS,
575
+ {
576
+ agentId,
577
+ orgId,
578
+ interactionId,
579
+ adaptiveCardId,
580
+ actionId,
581
+ trackingId,
582
+ },
583
+ ['operational']
584
+ );
585
+ LoggerProxy.log('Real-time assistance user action sent', loggerContext);
586
+
587
+ return response;
588
+ } catch (error) {
589
+ LoggerProxy.error('Real-time assistance user action failed', {...loggerContext, error});
590
+ this.metricsManager.trackEvent(
591
+ METRIC_EVENT_NAMES.AI_ASSISTANT_SEND_REAL_TIME_ASSISTANCE_USER_ACTION_FAILED,
592
+ {
593
+ agentId,
594
+ interactionId,
595
+ adaptiveCardId,
596
+ actionId,
597
+ trackingId,
598
+ error: error instanceof Error ? error.message : String(error),
599
+ },
600
+ ['operational']
601
+ );
602
+
603
+ const {error: detailedError} = getErrorDetails(
604
+ error,
605
+ METHODS.SEND_REAL_TIME_ASSISTANCE_USER_ACTION,
606
+ CC_FILE
607
+ );
608
+ throw detailedError;
609
+ }
610
+ }
611
+
146
612
  /**
147
613
  * Fetches historic transcripts for an interaction.
148
614
  * This API is allowed only when real-time transcription feature is enabled.
@@ -171,6 +637,18 @@ export class ApiAIAssistant {
171
637
  throw detailedError;
172
638
  }
173
639
 
640
+ if (
641
+ !this.isValidTranscriptIdentifier(agentId) ||
642
+ !this.isValidTranscriptIdentifier(interactionId)
643
+ ) {
644
+ const {error: detailedError} = getErrorDetails(
645
+ new Error('INVALID_AGENT_ID_OR_INTERACTION_ID'),
646
+ METHODS.FETCH_HISTORIC_TRANSCRIPTS,
647
+ CC_FILE
648
+ );
649
+ throw detailedError;
650
+ }
651
+
174
652
  try {
175
653
  const baseUrl = this.getBaseUrl();
176
654
  const orgId = this.webex.credentials.getOrgId();
@@ -201,6 +679,7 @@ export class ApiAIAssistant {
201
679
  },
202
680
  ['operational']
203
681
  );
682
+
204
683
  if (error instanceof Error) {
205
684
  throw error;
206
685
  }