@webex/contact-center 3.12.0-next.9 → 3.12.0-next.91

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 (229) hide show
  1. package/.sdd/manifest.json +876 -0
  2. package/AGENTS.md +94 -0
  3. package/ai-docs/ARCHITECTURE.md +168 -0
  4. package/ai-docs/CONTRACTS.md +46 -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 +341 -0
  17. package/ai-docs/features/generated-spec-conformance-fidelity-remediation/spec/feature-spec.md +117 -0
  18. package/ai-docs/features/residual-warning-coverage-completion/spec/feature-spec.md +203 -0
  19. package/ai-docs/features/validator-code-fidelity-drift-fix/spec/feature-spec.md +315 -0
  20. package/ai-docs/patterns/event-driven-patterns.md +485 -0
  21. package/ai-docs/patterns/testing-patterns.md +480 -0
  22. package/ai-docs/patterns/typescript-patterns.md +365 -0
  23. package/ai-docs/templates/README.md +102 -0
  24. package/ai-docs/templates/documentation/create-agents-md.md +240 -0
  25. package/ai-docs/templates/documentation/create-architecture-md.md +295 -0
  26. package/ai-docs/templates/existing-service/bug-fix.md +254 -0
  27. package/ai-docs/templates/existing-service/feature-enhancement.md +450 -0
  28. package/ai-docs/templates/new-method/00-master.md +80 -0
  29. package/ai-docs/templates/new-method/01-requirements.md +232 -0
  30. package/ai-docs/templates/new-method/02-implementation.md +295 -0
  31. package/ai-docs/templates/new-method/03-tests.md +201 -0
  32. package/ai-docs/templates/new-method/04-validation.md +141 -0
  33. package/ai-docs/templates/new-service/00-master.md +109 -0
  34. package/ai-docs/templates/new-service/01-pre-questions.md +159 -0
  35. package/ai-docs/templates/new-service/02-code-generation.md +346 -0
  36. package/ai-docs/templates/new-service/03-integration.md +178 -0
  37. package/ai-docs/templates/new-service/04-test-generation.md +205 -0
  38. package/ai-docs/templates/new-service/05-validation.md +145 -0
  39. package/dist/cc.js +265 -29
  40. package/dist/cc.js.map +1 -1
  41. package/dist/config.js +6 -0
  42. package/dist/config.js.map +1 -1
  43. package/dist/constants.js +17 -1
  44. package/dist/constants.js.map +1 -1
  45. package/dist/index.js +20 -5
  46. package/dist/index.js.map +1 -1
  47. package/dist/metrics/behavioral-events.js +101 -0
  48. package/dist/metrics/behavioral-events.js.map +1 -1
  49. package/dist/metrics/constants.js +25 -4
  50. package/dist/metrics/constants.js.map +1 -1
  51. package/dist/services/ApiAiAssistant.js +153 -8
  52. package/dist/services/ApiAiAssistant.js.map +1 -1
  53. package/dist/services/UserPreference.js +427 -0
  54. package/dist/services/UserPreference.js.map +1 -0
  55. package/dist/services/config/Util.js +3 -3
  56. package/dist/services/config/Util.js.map +1 -1
  57. package/dist/services/config/constants.js +23 -2
  58. package/dist/services/config/constants.js.map +1 -1
  59. package/dist/services/config/types.js +49 -9
  60. package/dist/services/config/types.js.map +1 -1
  61. package/dist/services/core/Err.js.map +1 -1
  62. package/dist/services/core/Utils.js +107 -32
  63. package/dist/services/core/Utils.js.map +1 -1
  64. package/dist/services/core/websocket/WebSocketManager.js +2 -1
  65. package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
  66. package/dist/services/core/websocket/types.js.map +1 -1
  67. package/dist/services/index.js +1 -1
  68. package/dist/services/index.js.map +1 -1
  69. package/dist/services/task/Task.js +688 -0
  70. package/dist/services/task/Task.js.map +1 -0
  71. package/dist/services/task/TaskFactory.js +45 -0
  72. package/dist/services/task/TaskFactory.js.map +1 -0
  73. package/dist/services/task/TaskManager.js +728 -527
  74. package/dist/services/task/TaskManager.js.map +1 -1
  75. package/dist/services/task/TaskUtils.js +162 -26
  76. package/dist/services/task/TaskUtils.js.map +1 -1
  77. package/dist/services/task/constants.js +9 -2
  78. package/dist/services/task/constants.js.map +1 -1
  79. package/dist/services/task/dialer.js +78 -0
  80. package/dist/services/task/dialer.js.map +1 -1
  81. package/dist/services/task/digital/Digital.js +77 -0
  82. package/dist/services/task/digital/Digital.js.map +1 -0
  83. package/dist/services/task/state-machine/TaskStateMachine.js +837 -0
  84. package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -0
  85. package/dist/services/task/state-machine/actions.js +543 -0
  86. package/dist/services/task/state-machine/actions.js.map +1 -0
  87. package/dist/services/task/state-machine/constants.js +161 -0
  88. package/dist/services/task/state-machine/constants.js.map +1 -0
  89. package/dist/services/task/state-machine/guards.js +340 -0
  90. package/dist/services/task/state-machine/guards.js.map +1 -0
  91. package/dist/services/task/state-machine/index.js +53 -0
  92. package/dist/services/task/state-machine/index.js.map +1 -0
  93. package/dist/services/task/state-machine/types.js +54 -0
  94. package/dist/services/task/state-machine/types.js.map +1 -0
  95. package/dist/services/task/state-machine/uiControlsComputer.js +553 -0
  96. package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -0
  97. package/dist/services/task/taskDataNormalizer.js +99 -0
  98. package/dist/services/task/taskDataNormalizer.js.map +1 -0
  99. package/dist/services/task/types.js +212 -4
  100. package/dist/services/task/types.js.map +1 -1
  101. package/dist/services/task/voice/Voice.js +1042 -0
  102. package/dist/services/task/voice/Voice.js.map +1 -0
  103. package/dist/services/task/voice/WebRTC.js +149 -0
  104. package/dist/services/task/voice/WebRTC.js.map +1 -0
  105. package/dist/types/cc.d.ts +94 -1
  106. package/dist/types/config.d.ts +6 -0
  107. package/dist/types/constants.d.ts +17 -1
  108. package/dist/types/index.d.ts +21 -6
  109. package/dist/types/metrics/constants.d.ts +21 -1
  110. package/dist/types/services/ApiAiAssistant.d.ts +22 -4
  111. package/dist/types/services/UserPreference.d.ts +118 -0
  112. package/dist/types/services/config/constants.d.ts +21 -0
  113. package/dist/types/services/config/types.d.ts +171 -10
  114. package/dist/types/services/core/Err.d.ts +4 -0
  115. package/dist/types/services/core/Utils.d.ts +33 -13
  116. package/dist/types/services/core/websocket/WebSocketManager.d.ts +1 -0
  117. package/dist/types/services/core/websocket/types.d.ts +1 -1
  118. package/dist/types/services/index.d.ts +1 -1
  119. package/dist/types/services/task/Task.d.ts +157 -0
  120. package/dist/types/services/task/TaskFactory.d.ts +12 -0
  121. package/dist/types/services/task/TaskUtils.d.ts +46 -2
  122. package/dist/types/services/task/constants.d.ts +7 -0
  123. package/dist/types/services/task/dialer.d.ts +30 -0
  124. package/dist/types/services/task/digital/Digital.d.ts +22 -0
  125. package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +1144 -0
  126. package/dist/types/services/task/state-machine/actions.d.ts +10 -0
  127. package/dist/types/services/task/state-machine/constants.d.ts +107 -0
  128. package/dist/types/services/task/state-machine/guards.d.ts +90 -0
  129. package/dist/types/services/task/state-machine/index.d.ts +13 -0
  130. package/dist/types/services/task/state-machine/types.d.ts +267 -0
  131. package/dist/types/services/task/state-machine/uiControlsComputer.d.ts +9 -0
  132. package/dist/types/services/task/taskDataNormalizer.d.ts +10 -0
  133. package/dist/types/services/task/types.d.ts +603 -66
  134. package/dist/types/services/task/voice/Voice.d.ts +184 -0
  135. package/dist/types/services/task/voice/WebRTC.d.ts +53 -0
  136. package/dist/types/types.d.ts +135 -0
  137. package/dist/types/webex.d.ts +1 -0
  138. package/dist/types.js +118 -2
  139. package/dist/types.js.map +1 -1
  140. package/dist/webex.js +14 -2
  141. package/dist/webex.js.map +1 -1
  142. package/package.json +15 -12
  143. package/src/cc.ts +329 -30
  144. package/src/config.ts +6 -0
  145. package/src/constants.ts +17 -1
  146. package/src/index.ts +23 -5
  147. package/src/metrics/ai-docs/AGENTS.md +350 -0
  148. package/src/metrics/ai-docs/ARCHITECTURE.md +338 -0
  149. package/src/metrics/ai-docs/metrics-spec.md +854 -0
  150. package/src/metrics/behavioral-events.ts +106 -0
  151. package/src/metrics/constants.ts +27 -4
  152. package/src/services/ApiAiAssistant.ts +203 -8
  153. package/src/services/UserPreference.ts +509 -0
  154. package/src/services/agent/ai-docs/AGENTS.md +240 -0
  155. package/src/services/agent/ai-docs/ARCHITECTURE.md +304 -0
  156. package/src/services/agent/ai-docs/agent-spec.md +504 -0
  157. package/src/services/ai-docs/AGENTS.md +386 -0
  158. package/src/services/ai-docs/services-spec.md +492 -0
  159. package/src/services/config/Util.ts +3 -3
  160. package/src/services/config/ai-docs/AGENTS.md +255 -0
  161. package/src/services/config/ai-docs/ARCHITECTURE.md +426 -0
  162. package/src/services/config/ai-docs/config-spec.md +669 -0
  163. package/src/services/config/constants.ts +25 -1
  164. package/src/services/config/types.ts +174 -11
  165. package/src/services/core/Err.ts +2 -0
  166. package/src/services/core/Utils.ts +123 -37
  167. package/src/services/core/ai-docs/AGENTS.md +381 -0
  168. package/src/services/core/ai-docs/ARCHITECTURE.md +698 -0
  169. package/src/services/core/ai-docs/core-spec.md +783 -0
  170. package/src/services/core/websocket/WebSocketManager.ts +2 -0
  171. package/src/services/core/websocket/types.ts +1 -1
  172. package/src/services/index.ts +1 -1
  173. package/src/services/task/Task.ts +837 -0
  174. package/src/services/task/TaskFactory.ts +55 -0
  175. package/src/services/task/TaskManager.ts +739 -614
  176. package/src/services/task/TaskUtils.ts +205 -25
  177. package/src/services/task/ai-docs/AGENTS.md +457 -0
  178. package/src/services/task/ai-docs/ARCHITECTURE.md +594 -0
  179. package/src/services/task/ai-docs/task-spec.md +1319 -0
  180. package/src/services/task/constants.ts +7 -0
  181. package/src/services/task/dialer.ts +80 -0
  182. package/src/services/task/digital/Digital.ts +95 -0
  183. package/src/services/task/state-machine/TaskStateMachine.ts +1077 -0
  184. package/src/services/task/state-machine/actions.ts +685 -0
  185. package/src/services/task/state-machine/ai-docs/AGENTS.md +458 -0
  186. package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +1137 -0
  187. package/src/services/task/state-machine/ai-docs/task-state-machine-spec.md +2115 -0
  188. package/src/services/task/state-machine/constants.ts +172 -0
  189. package/src/services/task/state-machine/guards.ts +406 -0
  190. package/src/services/task/state-machine/index.ts +28 -0
  191. package/src/services/task/state-machine/types.ts +241 -0
  192. package/src/services/task/state-machine/uiControlsComputer.ts +867 -0
  193. package/src/services/task/taskDataNormalizer.ts +137 -0
  194. package/src/services/task/types.ts +710 -71
  195. package/src/services/task/voice/Voice.ts +1267 -0
  196. package/src/services/task/voice/WebRTC.ts +187 -0
  197. package/src/types.ts +166 -2
  198. package/src/utils/AGENTS.md +278 -0
  199. package/src/utils/ai-docs/utils-spec.md +381 -0
  200. package/src/webex.js +2 -0
  201. package/test/unit/spec/cc.ts +343 -23
  202. package/test/unit/spec/logger-proxy.ts +70 -0
  203. package/test/unit/spec/services/ApiAiAssistant.ts +178 -20
  204. package/test/unit/spec/services/UserPreference.ts +401 -0
  205. package/test/unit/spec/services/WebCallingService.ts +7 -1
  206. package/test/unit/spec/services/config/index.ts +30 -30
  207. package/test/unit/spec/services/core/Utils.ts +425 -8
  208. package/test/unit/spec/services/core/websocket/WebSocketManager.ts +66 -40
  209. package/test/unit/spec/services/task/AutoWrapup.ts +63 -0
  210. package/test/unit/spec/services/task/Task.ts +477 -0
  211. package/test/unit/spec/services/task/TaskFactory.ts +62 -0
  212. package/test/unit/spec/services/task/TaskManager.ts +834 -1704
  213. package/test/unit/spec/services/task/TaskUtils.ts +206 -0
  214. package/test/unit/spec/services/task/dialer.ts +190 -0
  215. package/test/unit/spec/services/task/digital/Digital.ts +105 -0
  216. package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +1825 -0
  217. package/test/unit/spec/services/task/state-machine/guards.ts +479 -0
  218. package/test/unit/spec/services/task/state-machine/types.ts +18 -0
  219. package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +2020 -0
  220. package/test/unit/spec/services/task/taskTestUtils.ts +87 -0
  221. package/test/unit/spec/services/task/voice/Voice.ts +631 -0
  222. package/test/unit/spec/services/task/voice/WebRTC.ts +235 -0
  223. package/umd/contact-center.min.js +2 -2
  224. package/umd/contact-center.min.js.map +1 -1
  225. package/dist/services/task/index.js +0 -1525
  226. package/dist/services/task/index.js.map +0 -1
  227. package/dist/types/services/task/index.d.ts +0 -650
  228. package/src/services/task/index.ts +0 -1801
  229. package/test/unit/spec/services/task/index.ts +0 -2184
@@ -0,0 +1,594 @@
1
+ # Task Service - Architecture
2
+
3
+ > **Legacy/reference-only.** Canonical SDD: [`task-spec.md`](task-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**: Technical documentation for task lifecycle management.
6
+
7
+ ---
8
+
9
+ ## Component Overview
10
+
11
+ | Component | File | Responsibility |
12
+ | -------------------- | ---------------------------- | ---------------------------------------------------------- |
13
+ | `TaskManager` | `task/TaskManager.ts` | Task lifecycle coordination |
14
+ | `Task` | `task/Task.ts` | Individual task operations |
15
+ | `contact` | `task/contact.ts` | AQM request definitions |
16
+ | `dialer` | `task/dialer.ts` | Outbound call initiation |
17
+ | `AutoWrapup` | `task/AutoWrapup.ts` | Auto wrapup timer |
18
+ | `taskDataNormalizer` | `task/taskDataNormalizer.ts` | Normalizes backend task payloads |
19
+ | `TaskUtils` | `task/TaskUtils.ts` | Utility functions |
20
+ | `state-machine` | `task/state-machine/*` | Task state transitions, guards, and UI control computation |
21
+
22
+ ---
23
+
24
+ ## Task Module Design Overview
25
+
26
+ ### `Task` (abstract)
27
+
28
+ **File:** `Task.ts`
29
+
30
+ **Properties**
31
+
32
+ - `data: TaskData`
33
+ - `webCallMap: Record<TaskId, CallId>`
34
+ - `stateMachineService?: ActorRefFrom<TaskStateMachine>`
35
+ - `state?: SnapshotFrom<TaskStateMachine>`
36
+ - `autoWrapup?: AutoWrapup`
37
+ - `uiControls: TaskUIControls` (getter)
38
+
39
+ **Methods**
40
+
41
+ - `accept(): Promise<TaskResponse>` (abstract)
42
+ - `decline(): Promise<TaskResponse>` (default: unsupportedMethodError)
43
+ - `pauseRecording(): Promise<TaskResponse>` (default: unsupportedMethodError)
44
+ - `resumeRecording(resumeRecordingPayload: ResumeRecordingPayload): Promise<TaskResponse>` (default: unsupportedMethodError)
45
+ - `consult(consultPayload: ConsultPayload): Promise<TaskResponse>` (default: unsupportedMethodError)
46
+ - `endConsult(consultEndPayload?: ConsultEndPayload): Promise<TaskResponse>` (default: unsupportedMethodError)
47
+ - `consultTransfer(consultTransferPayload?: ConsultTransferPayLoad): Promise<TaskResponse>` (default: unsupportedMethodError)
48
+ - `consultConference(): Promise<TaskResponse>` (default: unsupportedMethodError)
49
+ - `exitConference(): Promise<TaskResponse>` (default: unsupportedMethodError)
50
+ - `transferConference(): Promise<TaskResponse>` (default: unsupportedMethodError)
51
+ - `switchCall(): Promise<TaskResponse>` (default: unsupportedMethodError)
52
+ - `toggleMute(): Promise<void>` (default: unsupportedMethodError)
53
+ - `unregisterWebCallListeners(): void` (default: no-op + log)
54
+ - `cancelAutoWrapupTimer(): void`
55
+ - `hold(mediaResourceId?: string): Promise<TaskResponse>` (default: unsupportedMethodError)
56
+ - `resume(mediaResourceId?: string): Promise<TaskResponse>` (default: unsupportedMethodError)
57
+ - `holdResume(): Promise<TaskResponse>` (default: unsupportedMethodError)
58
+ - `sendStateMachineEvent(event: TaskEventPayload): void`
59
+ - `updateTaskData(updatedData: TaskData, shouldOverwrite = false): ITask`
60
+ - `transfer(transferPayload: TransferPayLoad): Promise<TaskResponse>`
61
+ - `end(): Promise<TaskResponse>`
62
+ - `wrapup(wrapupPayload: WrapupPayLoad): Promise<TaskResponse>`
63
+
64
+ ### `Voice`
65
+
66
+ **File:** `voice/Voice.ts`
67
+
68
+ **Notes**
69
+
70
+ - Extends `Task`.
71
+ - Provides `hold()` and `resume()` that delegate to `holdResume()`.
72
+ - Explicitly overrides `accept()` and `decline()` to throw `unsupportedMethodError`.
73
+ - `WebRTC` then overrides these methods with concrete implementations.
74
+
75
+ ### `WebRTC`
76
+
77
+ **File:** `voice/WebRTC.ts`
78
+
79
+ **Notes**
80
+
81
+ - Extends `Voice`.
82
+ - Overrides `accept()` and `decline()` for WebRTC calls.
83
+ - Emits `TASK_EVENTS.TASK_MEDIA` on remote media (`CALL_EVENT_KEYS.REMOTE_MEDIA`).
84
+ - Overrides `unregisterWebCallListeners()`.
85
+
86
+ ### `Digital`
87
+
88
+ **File:** `digital/Digital.ts`
89
+
90
+ **Notes**
91
+
92
+ - Extends `Task`.
93
+ - Implements `accept()`.
94
+ - Overrides `updateTaskData()` to refresh digital task data and UI controls.
95
+
96
+ ### `TaskFactory`
97
+
98
+ **File:** `TaskFactory.ts`
99
+
100
+ **API**
101
+
102
+ - `createTask(contact, webCallingService, data, configFlags, wrapupData?, agentId?): Task`
103
+
104
+ **Behavior**
105
+
106
+ - Chooses `WebRTC` vs `Voice` for `MEDIA_CHANNEL.TELEPHONY` based on `webCallingService.loginOption`.
107
+ - Chooses `Digital` for `MEDIA_CHANNEL.CHAT`, `MEDIA_CHANNEL.EMAIL`, `MEDIA_CHANNEL.SOCIAL`.
108
+ - Throws `Error` for unknown media types.
109
+
110
+ ### Task Class Hierarchy Diagram
111
+
112
+ ```mermaid
113
+ classDiagram
114
+ class Task {
115
+ <<abstract>>
116
+ # contact
117
+ # metricsManager
118
+ + data: TaskData
119
+ + webCallMap: Record~TaskId, CallId~
120
+ + stateMachineService
121
+ + state
122
+ # currentUiControls: TaskUIControls
123
+ # uiControlConfig: UIControlConfig
124
+ + autoWrapup: AutoWrapup
125
+ + accept() TaskResponse
126
+ + transfer(payload) TaskResponse
127
+ + end() TaskResponse
128
+ + wrapup(payload) TaskResponse
129
+ + updateTaskData(updatedData, shouldOverwrite) ITask
130
+ + sendStateMachineEvent(event) void
131
+ + hold() TaskResponse
132
+ + resume() TaskResponse
133
+ + holdResume() TaskResponse
134
+ + consult(payload) TaskResponse
135
+ + endConsult(payload) TaskResponse
136
+ + consultTransfer(payload) TaskResponse
137
+ + consultConference() TaskResponse
138
+ + exitConference() TaskResponse
139
+ + transferConference() TaskResponse
140
+ + pauseRecording() TaskResponse
141
+ + resumeRecording(payload) TaskResponse
142
+ + toggleMute() void
143
+ + unregisterWebCallListeners() void
144
+ + cancelAutoWrapupTimer() void
145
+ }
146
+
147
+ class Voice {
148
+ + accept() TaskResponse
149
+ + decline() TaskResponse
150
+ + hold() TaskResponse
151
+ + resume() TaskResponse
152
+ + holdResume() TaskResponse
153
+ + pauseRecording() TaskResponse
154
+ + resumeRecording(payload) TaskResponse
155
+ + consult(payload) TaskResponse
156
+ + endConsult(payload) TaskResponse
157
+ + transfer(payload) TaskResponse
158
+ + consultConference() TaskResponse
159
+ + exitConference() TaskResponse
160
+ + transferConference() TaskResponse
161
+ }
162
+
163
+ class WebRTC {
164
+ - localAudioStream: LocalMicrophoneStream
165
+ - webCallingService: WebCallingService
166
+ + accept() TaskResponse
167
+ + decline() TaskResponse
168
+ + toggleMute() void
169
+ + unregisterWebCallListeners() void
170
+ }
171
+
172
+ class Digital {
173
+ + accept() TaskResponse
174
+ + updateTaskData(newData, shouldOverwrite) IDigital
175
+ }
176
+
177
+ class TaskFactory {
178
+ + createTask(contact, webCallingService, data, configFlags, wrapupData, agentId) Task
179
+ }
180
+
181
+ Task <|-- Voice
182
+ Voice <|-- WebRTC
183
+ Task <|-- Digital
184
+
185
+ TaskFactory ..> Task : creates
186
+ TaskFactory ..> Voice : creates
187
+ TaskFactory ..> WebRTC : creates
188
+ TaskFactory ..> Digital : creates
189
+ ```
190
+
191
+ ---
192
+
193
+ ## TaskManager Pattern
194
+
195
+ TaskManager is a singleton that:
196
+
197
+ 1. Listens for WebSocket task events
198
+ 2. Creates/manages Task objects
199
+ 3. Routes events to appropriate tasks
200
+ 4. Handles WebRTC call mapping
201
+
202
+ ```typescript
203
+ // Singleton access
204
+ const taskManager = TaskManager.getTaskManager(contact, webCallingService, webSocketManager);
205
+ ```
206
+
207
+ ---
208
+
209
+ ## AQM Request Modules
210
+
211
+ ### `routingContact(aqm: AqmReqs)` (`contact.ts`)
212
+
213
+ Returns an object of AQM request methods wired to `TASK_API` and `TASK_MESSAGE_TYPE`.
214
+
215
+ **Methods**
216
+
217
+ - `accept`
218
+ - `hold`
219
+ - `unHold`
220
+ - `pauseRecording`
221
+ - `resumeRecording`
222
+ - `consult`
223
+ - `consultEnd`
224
+ - `consultAccept`
225
+ - `blindTransfer`
226
+ - `vteamTransfer`
227
+ - `consultTransfer`
228
+ - `end`
229
+ - `wrapup`
230
+ - `cancelTask`
231
+ - `cancelCtq`
232
+ - `consultConference`
233
+ - `exitConference`
234
+ - `conferenceTransfer`
235
+
236
+ **Notes**
237
+
238
+ - Uses `WCC_API_GATEWAY`.
239
+ - Consult with `DESTINATION_TYPE.QUEUE` uses `TIMEOUT_REQ` = `'disabled'` for the request timeout.
240
+
241
+ ### `aqmDialer(aqm: AqmReqs)` (`dialer.ts`)
242
+
243
+ Returns an object of AQM request methods for outbound dialing.
244
+
245
+ **Methods**
246
+
247
+ - `startOutdial` (success: `CC_EVENTS.AGENT_OFFER_CONTACT`, failure: `CC_EVENTS.AGENT_OUTBOUND_FAILED`)
248
+
249
+ ---
250
+
251
+ ## Usage in Task Classes
252
+
253
+ ### `Task` (`Task.ts`)
254
+
255
+ - Constructor accepts `contact: ReturnType<typeof routingContact>`.
256
+ - Uses:
257
+ - `contact.vteamTransfer` / `contact.blindTransfer` in `transfer(...)`.
258
+ - While in consulting state, `transfer(...)` internally routes through consult-transfer behavior.
259
+ - `contact.end` in `end()`.
260
+ - `contact.wrapup` in `wrapup(...)`.
261
+
262
+ ### `Voice` (`voice/Voice.ts`)
263
+
264
+ Uses `contact` for:
265
+
266
+ - `hold`, `unHold`
267
+ - `pauseRecording`, `resumeRecording`
268
+ - `consult`, `consultEnd`, `consultTransfer`
269
+ - `consultConference`, `exitConference`, `conferenceTransfer`
270
+
271
+ ### `Digital` (`digital/Digital.ts`)
272
+
273
+ Uses `contact.accept` in `accept()`.
274
+
275
+ ---
276
+
277
+ ## State Machine Layer
278
+
279
+ `Task` delegates lifecycle transitions and control-state derivation to the state machine:
280
+
281
+ - Transition graph: `state-machine/TaskStateMachine.ts`
282
+ - Transition conditions: `state-machine/guards.ts`
283
+ - Context mutation and integration hooks: `state-machine/actions.ts`
284
+ - UI control derivation: `state-machine/uiControlsComputer.ts`
285
+
286
+ For state-machine-specific implementation guidance, use:
287
+
288
+ - `../state-machine/ai-docs/AGENTS.md`
289
+ - `../state-machine/ai-docs/ARCHITECTURE.md`
290
+
291
+ ### State Inventory (from `state-machine/constants.ts`)
292
+
293
+ - **Active lifecycle + intermediate states**:
294
+ - `IDLE`, `OFFERED`, `CONNECTED`
295
+ - `HOLD_INITIATING`, `HELD`, `RESUME_INITIATING`
296
+ - `CONSULT_INITIATING`, `CONSULTING`, `CONF_INITIATING`
297
+ - `CONFERENCING`, `WRAPPING_UP`, `COMPLETED`, `TERMINATED`
298
+ - **Future placeholders (defined, not currently implemented in transitions)**:
299
+ - `CONSULT_INITIATED`, `CONSULT_COMPLETED`, `POST_CALL`, `PARKED`, `MONITORING`
300
+
301
+ ---
302
+
303
+ ## Event Flow
304
+
305
+ ### Incoming Task Flow
306
+
307
+ ```mermaid
308
+ sequenceDiagram
309
+ participant BE as Backend
310
+ participant WS as WebSocket
311
+ participant TM as TaskManager
312
+ participant TF as TaskFactory
313
+ participant T as Task
314
+ participant CC as ContactCenter
315
+ participant App as Application
316
+
317
+ BE->>WS: AgentOfferContact event
318
+ WS->>TM: message event
319
+ TM->>TM: Check if telephony
320
+ alt BROWSER login
321
+ TM->>TM: Wait for INCOMING_CALL
322
+ WS->>TM: LINE_EVENTS.INCOMING_CALL
323
+ TM->>TM: Map call to task
324
+ end
325
+ TM->>TF: TaskFactory.createTask(...)
326
+ TF-->>TM: Voice/WebRTC/Digital Task instance
327
+ TM->>TM: Store in taskCollection
328
+ TM->>CC: emit task:incoming
329
+ CC->>App: trigger task:incoming
330
+ App->>T: task.accept()
331
+ ```
332
+
333
+ ### Task Operation Flow
334
+
335
+ ```mermaid
336
+ sequenceDiagram
337
+ participant App
338
+ participant T as Task
339
+ participant C as contact service
340
+ participant AQM as AqmReqs
341
+ participant WS as WebSocket
342
+ participant BE as Backend
343
+
344
+ App->>T: task.hold()
345
+ T->>T: Update local state
346
+ T->>C: contact.hold({data})
347
+ C->>AQM: req(config)
348
+ AQM->>BE: POST /v1/tasks/{interactionId}/hold (HTTP via WebexRequest)
349
+ BE-->>AQM: HTTP response (TaskResponse payload)
350
+ AQM-->>C: resolve Promise<TaskResponse>
351
+ C-->>T: return TaskResponse
352
+ T-->>App: Promise resolves
353
+ Note over WS,TM: WebSocket is notification channel, not request transport
354
+ BE-->>WS: AgentContactHeld
355
+ WS-->>TM: message event
356
+ TM-->>T: emit task:hold
357
+ ```
358
+
359
+ ---
360
+
361
+ ## Task Collection
362
+
363
+ TaskManager maintains a map of active tasks:
364
+
365
+ ```typescript
366
+ private taskCollection: Record<TaskId, ITask> = {};
367
+
368
+ // Tasks indexed by interactionId
369
+ this.taskCollection[interactionId] = task;
370
+
371
+ // Retrieve task
372
+ const task = this.taskCollection[interactionId];
373
+ ```
374
+
375
+ ---
376
+
377
+ ## WebSocket Event Handling
378
+
379
+ TaskManager uses a staged pipeline in `registerTaskListeners()`:
380
+
381
+ ```typescript
382
+ this.webSocketManager.on('message', (event) => {
383
+ // 1) Parse and validate message
384
+ const message = TaskManager.parseWebSocketMessage(event);
385
+ if (!message) return;
386
+
387
+ // 2) Build event context (task, payload, mapped state-machine event)
388
+ const eventContext = this.prepareEventContext(message);
389
+ if (!eventContext) return;
390
+
391
+ // 3) Handle lifecycle changes (create/update/remove task)
392
+ const actions = this.handleTaskLifecycleEvent(eventContext);
393
+ const {task} = actions;
394
+ if (!task) return;
395
+
396
+ // 4) Keep task.data synchronized
397
+ const {payload, stateMachineEvent} = eventContext;
398
+ if (payload) this.updateTaskData(task, payload);
399
+
400
+ // 5) Drive state machine (which emits TASK_EVENTS)
401
+ if (stateMachineEvent) {
402
+ task.sendStateMachineEvent(stateMachineEvent);
403
+ }
404
+ });
405
+ ```
406
+
407
+ ### RTD / AI Assistant event routing
408
+
409
+ `TaskManager.handleRealtimeWebsocketEvent()` handles payloads arriving on the realtime subscription socket used for AI features. It:
410
+
411
+ 1. Normalizes the websocket envelope (`payload.data` vs direct payload form)
412
+ 2. Resolves the owning task via `conversationId`
413
+ 3. Emits `REAL_TIME_TRANSCRIPTION` on the task for transcript payloads
414
+ 4. Emits `SUGGESTED_RESPONSE` on the task only when the backend payload is a final suggestion (`data.type === 'SUGGESTION'`)
415
+ 5. Ignores `SUGGESTED_RESPONSE_ACKNOWLEDGE` for public SDK emission
416
+
417
+ This keeps transcript and suggestion delivery aligned on the same per-task event surface.
418
+
419
+ ---
420
+
421
+ ## WebRTC Integration
422
+
423
+ For BROWSER login, TaskManager integrates with WebCalling:
424
+
425
+ ```mermaid
426
+ flowchart TD
427
+ A[AgentOfferContact event] --> B[Determine media + loginOption]
428
+ B --> C[TaskFactory chooses Voice/WebRTC class]
429
+ C --> D[Create Task object]
430
+ D --> E[Store in taskCollection]
431
+ E --> F{BROWSER login?}
432
+ F -->|Yes| G[Wait for INCOMING_CALL]
433
+ G --> H[Map call to task]
434
+ H --> I[Emit task:incoming]
435
+ F -->|No| I
436
+ ```
437
+
438
+ ### Call Mapping
439
+
440
+ ```typescript
441
+ // WebCallingService maps call IDs to interaction IDs
442
+ this.webCallingService.mapCallToTask(callId, interactionId);
443
+
444
+ // Task uses call for media operations
445
+ this.webCallingService.answerCall(localAudioStream: LocalMicrophoneStream, taskId: string);
446
+ ```
447
+
448
+ ---
449
+
450
+ ## Auto Wrapup
451
+
452
+ AutoWrapup handles automatic task completion:
453
+
454
+ ```typescript
455
+ // AutoWrapup.ts
456
+ export default class AutoWrapup {
457
+ private timer: ReturnType<typeof setTimeout> | null = null;
458
+ private readonly interval: number;
459
+
460
+ start(onComplete: () => void) {
461
+ this.timer = setTimeout(onComplete, this.interval);
462
+ }
463
+
464
+ clear() {
465
+ if (this.timer) {
466
+ clearTimeout(this.timer);
467
+ this.timer = null;
468
+ }
469
+ }
470
+
471
+ getTimeLeft() {}
472
+ isRunning() {}
473
+ getTimeLeftSeconds() {}
474
+ }
475
+ ```
476
+
477
+ ---
478
+
479
+ ## Contact Service Operations
480
+
481
+ Each task operation maps to an AQM request:
482
+
483
+ ```typescript
484
+ // contact.ts
485
+ export default function routingContact(routing: AqmReqs) {
486
+ return {
487
+ accept: routing.req((p) => ({
488
+ url: '/v1/tasks/.../accept',
489
+ notifSuccess: { bind: { type: CC_EVENTS.AGENT_CONTACT_ASSIGNED }},
490
+ notifFail: { bind: { type: CC_EVENTS.AGENT_CONTACT_ASSIGN_FAILED }},
491
+ })),
492
+
493
+ hold: routing.req((p) => ({...})),
494
+ unHold: routing.req((p) => ({...})),
495
+ consultAccept: routing.req((p) => ({...})),
496
+ cancelTask: routing.req((p) => ({...})),
497
+ cancelCtq: routing.req((p) => ({...})),
498
+ end: routing.req((p) => ({...})),
499
+ wrapup: routing.req((p) => ({...})),
500
+ blindTransfer: routing.req((p) => ({...})),
501
+ consult: routing.req((p) => ({...})),
502
+ consultTransfer: routing.req((p) => ({...})),
503
+ // ... more operations
504
+ };
505
+ }
506
+ ```
507
+
508
+ ---
509
+
510
+ ## Task Utils
511
+
512
+ Helper functions for task state analysis:
513
+
514
+ ```typescript
515
+ // TaskUtils.ts
516
+
517
+ // Check if participant is in main interaction
518
+ isParticipantInMainInteraction(task, agentId);
519
+
520
+ // Check if conference is in progress
521
+ getIsConferenceInProgress(taskData);
522
+
523
+ // Check if agent is primary
524
+ isPrimary(task, agentId);
525
+
526
+ // Check if secondary EPDN agent
527
+ isSecondaryEpDnAgent(interaction);
528
+ ```
529
+
530
+ ---
531
+
532
+ ## Metrics Tracking
533
+
534
+ | Metric | Type | When Tracked |
535
+ | ----------------------- | -------------------- | ------------------ |
536
+ | `TASK_ACCEPT_SUCCESS` | behavioral, business | Task accepted |
537
+ | `TASK_HOLD_SUCCESS` | operational | Hold succeeded |
538
+ | `TASK_END_SUCCESS` | behavioral, business | Task ended |
539
+ | `TASK_WRAPUP_SUCCESS` | operational | Wrapup completed |
540
+ | `TASK_TRANSFER_SUCCESS` | behavioral, business | Transfer completed |
541
+ | `TASK_OUTDIAL_SUCCESS` | behavioral, business | Outdial completed |
542
+
543
+ ---
544
+
545
+ ## Troubleshooting
546
+
547
+ ### Issue: task:incoming not received
548
+
549
+ **Cause**: Agent not available or TaskManager not initialized
550
+
551
+ **Solution**:
552
+
553
+ 1. Ensure `cc.register()` completed
554
+ 2. Ensure `cc.stationLogin()` completed
555
+ 3. Ensure agent state is Available
556
+
557
+ ### Issue: Task operations fail
558
+
559
+ **Cause**: Task state doesn't allow operation
560
+
561
+ **Solution**: Check task state before operation:
562
+
563
+ ```typescript
564
+ if (task.uiControls.main.hold.isEnabled) {
565
+ await task.hold();
566
+ }
567
+
568
+ // Consult-leg controls are exposed separately.
569
+ if (task.uiControls.consult.hold.isEnabled) {
570
+ // Render or enable the consult-leg hold action.
571
+ }
572
+ ```
573
+
574
+ ### Issue: WebRTC call not connecting
575
+
576
+ **Cause**: Call not mapped to task
577
+
578
+ **Solution**: Ensure BROWSER login and mercury connected:
579
+
580
+ ```typescript
581
+ await webex.internal.mercury.connect();
582
+ await cc.stationLogin({ loginOption: 'BROWSER', ... });
583
+ ```
584
+
585
+ ---
586
+
587
+ ## Related Files
588
+
589
+ - [cc.ts](../../../cc.ts) - Main plugin
590
+ - [TaskManager.ts](../TaskManager.ts) - Manager
591
+ - [contact.ts](../contact.ts) - Contact operations
592
+ - [types.ts](../types.ts) - Type definitions
593
+ - [../state-machine/ai-docs/AGENTS.md](../state-machine/ai-docs/AGENTS.md) - State machine guide
594
+ - [../state-machine/ai-docs/ARCHITECTURE.md](../state-machine/ai-docs/ARCHITECTURE.md) - State machine architecture