@webex/contact-center 3.12.0-next.8 → 3.12.0-task-refactor.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 (200) hide show
  1. package/AGENTS.md +438 -0
  2. package/ai-docs/README.md +131 -0
  3. package/ai-docs/RULES.md +455 -0
  4. package/ai-docs/patterns/event-driven-patterns.md +485 -0
  5. package/ai-docs/patterns/testing-patterns.md +480 -0
  6. package/ai-docs/patterns/typescript-patterns.md +365 -0
  7. package/ai-docs/templates/README.md +102 -0
  8. package/ai-docs/templates/documentation/create-agents-md.md +240 -0
  9. package/ai-docs/templates/documentation/create-architecture-md.md +295 -0
  10. package/ai-docs/templates/existing-service/bug-fix.md +254 -0
  11. package/ai-docs/templates/existing-service/feature-enhancement.md +450 -0
  12. package/ai-docs/templates/new-method/00-master.md +80 -0
  13. package/ai-docs/templates/new-method/01-requirements.md +232 -0
  14. package/ai-docs/templates/new-method/02-implementation.md +295 -0
  15. package/ai-docs/templates/new-method/03-tests.md +201 -0
  16. package/ai-docs/templates/new-method/04-validation.md +141 -0
  17. package/ai-docs/templates/new-service/00-master.md +109 -0
  18. package/ai-docs/templates/new-service/01-pre-questions.md +159 -0
  19. package/ai-docs/templates/new-service/02-code-generation.md +346 -0
  20. package/ai-docs/templates/new-service/03-integration.md +178 -0
  21. package/ai-docs/templates/new-service/04-test-generation.md +205 -0
  22. package/ai-docs/templates/new-service/05-validation.md +145 -0
  23. package/dist/cc.js +65 -123
  24. package/dist/cc.js.map +1 -1
  25. package/dist/constants.js +13 -2
  26. package/dist/constants.js.map +1 -1
  27. package/dist/index.js +13 -5
  28. package/dist/index.js.map +1 -1
  29. package/dist/metrics/behavioral-events.js +26 -13
  30. package/dist/metrics/behavioral-events.js.map +1 -1
  31. package/dist/metrics/constants.js +7 -6
  32. package/dist/metrics/constants.js.map +1 -1
  33. package/dist/services/ApiAiAssistant.js +0 -3
  34. package/dist/services/ApiAiAssistant.js.map +1 -1
  35. package/dist/services/config/Util.js +2 -3
  36. package/dist/services/config/Util.js.map +1 -1
  37. package/dist/services/config/types.js +16 -14
  38. package/dist/services/config/types.js.map +1 -1
  39. package/dist/services/constants.js +0 -1
  40. package/dist/services/constants.js.map +1 -1
  41. package/dist/services/core/Err.js.map +1 -1
  42. package/dist/services/core/Utils.js +79 -55
  43. package/dist/services/core/Utils.js.map +1 -1
  44. package/dist/services/core/aqm-reqs.js +17 -92
  45. package/dist/services/core/aqm-reqs.js.map +1 -1
  46. package/dist/services/core/websocket/WebSocketManager.js +5 -25
  47. package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
  48. package/dist/services/core/websocket/types.js.map +1 -1
  49. package/dist/services/index.js +1 -2
  50. package/dist/services/index.js.map +1 -1
  51. package/dist/services/task/Task.js +644 -0
  52. package/dist/services/task/Task.js.map +1 -0
  53. package/dist/services/task/TaskFactory.js +45 -0
  54. package/dist/services/task/TaskFactory.js.map +1 -0
  55. package/dist/services/task/TaskManager.js +556 -532
  56. package/dist/services/task/TaskManager.js.map +1 -1
  57. package/dist/services/task/TaskUtils.js +132 -28
  58. package/dist/services/task/TaskUtils.js.map +1 -1
  59. package/dist/services/task/constants.js +7 -6
  60. package/dist/services/task/constants.js.map +1 -1
  61. package/dist/services/task/dialer.js +0 -51
  62. package/dist/services/task/dialer.js.map +1 -1
  63. package/dist/services/task/digital/Digital.js +77 -0
  64. package/dist/services/task/digital/Digital.js.map +1 -0
  65. package/dist/services/task/state-machine/TaskStateMachine.js +634 -0
  66. package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -0
  67. package/dist/services/task/state-machine/actions.js +366 -0
  68. package/dist/services/task/state-machine/actions.js.map +1 -0
  69. package/dist/services/task/state-machine/constants.js +139 -0
  70. package/dist/services/task/state-machine/constants.js.map +1 -0
  71. package/dist/services/task/state-machine/guards.js +256 -0
  72. package/dist/services/task/state-machine/guards.js.map +1 -0
  73. package/dist/services/task/state-machine/index.js +53 -0
  74. package/dist/services/task/state-machine/index.js.map +1 -0
  75. package/dist/services/task/state-machine/types.js +54 -0
  76. package/dist/services/task/state-machine/types.js.map +1 -0
  77. package/dist/services/task/state-machine/uiControlsComputer.js +369 -0
  78. package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -0
  79. package/dist/services/task/taskDataNormalizer.js +99 -0
  80. package/dist/services/task/taskDataNormalizer.js.map +1 -0
  81. package/dist/services/task/types.js +157 -18
  82. package/dist/services/task/types.js.map +1 -1
  83. package/dist/services/task/voice/Voice.js +1031 -0
  84. package/dist/services/task/voice/Voice.js.map +1 -0
  85. package/dist/services/task/voice/WebRTC.js +149 -0
  86. package/dist/services/task/voice/WebRTC.js.map +1 -0
  87. package/dist/types/cc.d.ts +4 -33
  88. package/dist/types/constants.d.ts +13 -2
  89. package/dist/types/index.d.ts +11 -5
  90. package/dist/types/metrics/constants.d.ts +5 -3
  91. package/dist/types/services/ApiAiAssistant.d.ts +1 -1
  92. package/dist/types/services/config/types.d.ts +97 -25
  93. package/dist/types/services/core/Err.d.ts +0 -2
  94. package/dist/types/services/core/Utils.d.ts +25 -23
  95. package/dist/types/services/core/aqm-reqs.d.ts +0 -49
  96. package/dist/types/services/core/websocket/WebSocketManager.d.ts +1 -1
  97. package/dist/types/services/core/websocket/connection-service.d.ts +0 -1
  98. package/dist/types/services/core/websocket/types.d.ts +1 -1
  99. package/dist/types/services/index.d.ts +1 -1
  100. package/dist/types/services/task/Task.d.ts +146 -0
  101. package/dist/types/services/task/TaskFactory.d.ts +12 -0
  102. package/dist/types/services/task/TaskUtils.d.ts +39 -8
  103. package/dist/types/services/task/constants.d.ts +5 -4
  104. package/dist/types/services/task/dialer.d.ts +0 -15
  105. package/dist/types/services/task/digital/Digital.d.ts +22 -0
  106. package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +906 -0
  107. package/dist/types/services/task/state-machine/actions.d.ts +8 -0
  108. package/dist/types/services/task/state-machine/constants.d.ts +91 -0
  109. package/dist/types/services/task/state-machine/guards.d.ts +78 -0
  110. package/dist/types/services/task/state-machine/index.d.ts +13 -0
  111. package/dist/types/services/task/state-machine/types.d.ts +256 -0
  112. package/dist/types/services/task/state-machine/uiControlsComputer.d.ts +9 -0
  113. package/dist/types/services/task/taskDataNormalizer.d.ts +10 -0
  114. package/dist/types/services/task/types.d.ts +539 -88
  115. package/dist/types/services/task/voice/Voice.d.ts +183 -0
  116. package/dist/types/services/task/voice/WebRTC.d.ts +53 -0
  117. package/dist/types/types.d.ts +68 -0
  118. package/dist/types/webex.d.ts +1 -0
  119. package/dist/types.js +70 -0
  120. package/dist/types.js.map +1 -1
  121. package/dist/webex.js +14 -2
  122. package/dist/webex.js.map +1 -1
  123. package/package.json +14 -11
  124. package/src/cc.ts +91 -177
  125. package/src/constants.ts +13 -2
  126. package/src/index.ts +14 -5
  127. package/src/metrics/ai-docs/AGENTS.md +348 -0
  128. package/src/metrics/ai-docs/ARCHITECTURE.md +336 -0
  129. package/src/metrics/behavioral-events.ts +28 -14
  130. package/src/metrics/constants.ts +7 -8
  131. package/src/services/ApiAiAssistant.ts +2 -4
  132. package/src/services/agent/ai-docs/AGENTS.md +238 -0
  133. package/src/services/agent/ai-docs/ARCHITECTURE.md +302 -0
  134. package/src/services/ai-docs/AGENTS.md +384 -0
  135. package/src/services/config/Util.ts +2 -3
  136. package/src/services/config/ai-docs/AGENTS.md +253 -0
  137. package/src/services/config/ai-docs/ARCHITECTURE.md +424 -0
  138. package/src/services/config/types.ts +108 -20
  139. package/src/services/constants.ts +0 -1
  140. package/src/services/core/Err.ts +0 -1
  141. package/src/services/core/Utils.ts +90 -67
  142. package/src/services/core/ai-docs/AGENTS.md +379 -0
  143. package/src/services/core/ai-docs/ARCHITECTURE.md +696 -0
  144. package/src/services/core/aqm-reqs.ts +22 -100
  145. package/src/services/core/websocket/WebSocketManager.ts +4 -23
  146. package/src/services/core/websocket/types.ts +1 -1
  147. package/src/services/index.ts +1 -2
  148. package/src/services/task/Task.ts +785 -0
  149. package/src/services/task/TaskFactory.ts +55 -0
  150. package/src/services/task/TaskManager.ts +567 -633
  151. package/src/services/task/TaskUtils.ts +175 -31
  152. package/src/services/task/ai-docs/AGENTS.md +448 -0
  153. package/src/services/task/ai-docs/ARCHITECTURE.md +573 -0
  154. package/src/services/task/constants.ts +5 -4
  155. package/src/services/task/dialer.ts +1 -56
  156. package/src/services/task/digital/Digital.ts +95 -0
  157. package/src/services/task/state-machine/TaskStateMachine.ts +793 -0
  158. package/src/services/task/state-machine/actions.ts +409 -0
  159. package/src/services/task/state-machine/ai-docs/AGENTS.md +495 -0
  160. package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +1135 -0
  161. package/src/services/task/state-machine/constants.ts +150 -0
  162. package/src/services/task/state-machine/guards.ts +295 -0
  163. package/src/services/task/state-machine/index.ts +28 -0
  164. package/src/services/task/state-machine/types.ts +228 -0
  165. package/src/services/task/state-machine/uiControlsComputer.ts +529 -0
  166. package/src/services/task/taskDataNormalizer.ts +137 -0
  167. package/src/services/task/types.ts +641 -95
  168. package/src/services/task/voice/Voice.ts +1255 -0
  169. package/src/services/task/voice/WebRTC.ts +187 -0
  170. package/src/types.ts +88 -5
  171. package/src/utils/AGENTS.md +276 -0
  172. package/src/webex.js +2 -0
  173. package/test/unit/spec/cc.ts +59 -142
  174. package/test/unit/spec/logger-proxy.ts +70 -0
  175. package/test/unit/spec/services/ApiAiAssistant.ts +17 -0
  176. package/test/unit/spec/services/config/index.ts +26 -55
  177. package/test/unit/spec/services/core/Utils.ts +103 -52
  178. package/test/unit/spec/services/core/websocket/WebSocketManager.ts +48 -112
  179. package/test/unit/spec/services/core/websocket/connection-service.ts +5 -4
  180. package/test/unit/spec/services/task/AutoWrapup.ts +63 -0
  181. package/test/unit/spec/services/task/Task.ts +416 -0
  182. package/test/unit/spec/services/task/TaskFactory.ts +62 -0
  183. package/test/unit/spec/services/task/TaskManager.ts +781 -1735
  184. package/test/unit/spec/services/task/TaskUtils.ts +125 -0
  185. package/test/unit/spec/services/task/dialer.ts +112 -198
  186. package/test/unit/spec/services/task/digital/Digital.ts +105 -0
  187. package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +473 -0
  188. package/test/unit/spec/services/task/state-machine/guards.ts +288 -0
  189. package/test/unit/spec/services/task/state-machine/types.ts +18 -0
  190. package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +147 -0
  191. package/test/unit/spec/services/task/taskTestUtils.ts +87 -0
  192. package/test/unit/spec/services/task/voice/Voice.ts +587 -0
  193. package/test/unit/spec/services/task/voice/WebRTC.ts +242 -0
  194. package/umd/contact-center.min.js +2 -2
  195. package/umd/contact-center.min.js.map +1 -1
  196. package/dist/services/task/index.js +0 -1525
  197. package/dist/services/task/index.js.map +0 -1
  198. package/dist/types/services/task/index.d.ts +0 -650
  199. package/src/services/task/index.ts +0 -1801
  200. package/test/unit/spec/services/task/index.ts +0 -2184
@@ -0,0 +1,485 @@
1
+ # Event-Driven Patterns - Contact Center SDK
2
+
3
+ > **Purpose**: Event handling patterns for the Contact Center SDK, including WebSocket events and EventEmitter usage.
4
+
5
+ ---
6
+
7
+ ## Event Constants
8
+
9
+ ### Definition Pattern
10
+
11
+ Events are defined as const objects for type safety:
12
+
13
+ ```typescript
14
+ // services/config/types.ts
15
+
16
+ // Agent-related events
17
+ export const CC_AGENT_EVENTS = {
18
+ WELCOME: 'Welcome',
19
+ AGENT_RELOGIN_SUCCESS: 'AgentReloginSuccess',
20
+ AGENT_RELOGIN_FAILED: 'AgentReloginFailed',
21
+ AGENT_DN_REGISTERED: 'AgentDNRegistered',
22
+ AGENT_LOGOUT: 'Logout',
23
+ AGENT_LOGOUT_SUCCESS: 'AgentLogoutSuccess',
24
+ AGENT_LOGOUT_FAILED: 'AgentLogoutFailed',
25
+ AGENT_STATION_LOGIN: 'StationLogin',
26
+ AGENT_STATION_LOGIN_SUCCESS: 'AgentStationLoginSuccess',
27
+ AGENT_STATION_LOGIN_FAILED: 'AgentStationLoginFailed',
28
+ AGENT_STATE_CHANGE: 'AgentStateChange',
29
+ AGENT_MULTI_LOGIN: 'AGENT_MULTI_LOGIN',
30
+ AGENT_STATE_CHANGE_SUCCESS: 'AgentStateChangeSuccess',
31
+ AGENT_STATE_CHANGE_FAILED: 'AgentStateChangeFailed',
32
+ AGENT_BUDDY_AGENTS: 'BuddyAgents',
33
+ AGENT_BUDDY_AGENTS_SUCCESS: 'BuddyAgents',
34
+ AGENT_BUDDY_AGENTS_RETRIEVE_FAILED: 'BuddyAgentsRetrieveFailed',
35
+ AGENT_CONTACT_RESERVED: 'AgentContactReserved',
36
+ } as const;
37
+
38
+ // Task-related events
39
+ export const CC_TASK_EVENTS = {
40
+ AGENT_CONTACT_HELD: 'AgentContactHeld',
41
+ AGENT_CONTACT_UNHELD: 'AgentContactUnheld',
42
+ AGENT_CONSULT_CREATED: 'AgentConsultCreated',
43
+ AGENT_BLIND_TRANSFERRED: 'AgentBlindTransferred',
44
+ CONTACT_ENDED: 'ContactEnded',
45
+ AGENT_WRAPUP: 'AgentWrapup',
46
+ AGENT_WRAPPEDUP: 'AgentWrappedUp',
47
+ // ... more events
48
+ } as const;
49
+
50
+ // Combined events
51
+ export const CC_EVENTS = {
52
+ ...CC_AGENT_EVENTS,
53
+ ...CC_TASK_EVENTS,
54
+ } as const;
55
+
56
+ // Type extraction
57
+ type Enum<T extends Record<string, unknown>> = T[keyof T];
58
+ export type CC_EVENTS = Enum<typeof CC_EVENTS>;
59
+ ```
60
+
61
+ ### Agent Events (AGENT_EVENTS)
62
+
63
+ ```typescript
64
+ // services/agent/types.ts
65
+ export enum AGENT_EVENTS {
66
+ AGENT_STATE_CHANGE = 'agent:stateChange',
67
+ AGENT_MULTI_LOGIN = 'agent:multiLogin',
68
+ AGENT_STATION_LOGIN_SUCCESS = 'agent:stationLoginSuccess',
69
+ AGENT_STATION_LOGIN_FAILED = 'agent:stationLoginFailed',
70
+ AGENT_LOGOUT_SUCCESS = 'agent:logoutSuccess',
71
+ AGENT_LOGOUT_FAILED = 'agent:logoutFailed',
72
+ AGENT_DN_REGISTERED = 'agent:dnRegistered',
73
+ AGENT_RELOGIN_SUCCESS = 'agent:reloginSuccess',
74
+ AGENT_STATE_CHANGE_SUCCESS = 'agent:stateChangeSuccess',
75
+ AGENT_STATE_CHANGE_FAILED = 'agent:stateChangeFailed',
76
+ }
77
+ ```
78
+
79
+ ### Task Events (TASK_EVENTS)
80
+
81
+ ```typescript
82
+ // services/task/types.ts
83
+ export enum TASK_EVENTS {
84
+ TASK_INCOMING = 'task:incoming',
85
+ TASK_ASSIGNED = 'task:assigned',
86
+ TASK_MEDIA = 'task:media',
87
+ TASK_UNASSIGNED = 'task:unassigned',
88
+ TASK_HOLD = 'task:hold',
89
+ TASK_RESUME = 'task:resume',
90
+ TASK_HYDRATE = 'task:hydrate',
91
+ TASK_MERGED = 'task:merged',
92
+ TASK_END = 'task:end',
93
+ TASK_WRAPUP = 'task:wrapup',
94
+ TASK_CLEANUP = 'task:cleanup',
95
+ // ... more events (consult, recording, etc.)
96
+ }
97
+ ```
98
+
99
+ ---
100
+
101
+ ## Event Flow
102
+
103
+ ### Generic Event Reception
104
+
105
+ Events flow through a standard pipeline: receive from transport, parse, log, route, and emit to listeners.
106
+
107
+ ```
108
+ Transport (WebSocket/EventEmitter)
109
+
110
+
111
+ Handler receives raw event
112
+
113
+ ├── Parse / validate
114
+ ├── Log reception
115
+ ├── Route by event type
116
+ └── Emit to subscribers
117
+ ```
118
+
119
+ Handlers use one of two patterns to preserve `this` binding: **arrow function properties** (e.g., `handleWebsocketMessage`) or **regular methods with `.bind(this)`** (e.g., `handleConnectionLost`):
120
+
121
+ ```typescript
122
+ // Pattern 1: Arrow function property (used by handleWebsocketMessage)
123
+ private handleEvent = (event: string) => {
124
+ const eventData = JSON.parse(event);
125
+
126
+ // Skip non-actionable events (e.g., keepalives)
127
+ if (eventData.keepalive) {
128
+ return;
129
+ }
130
+
131
+ // Log reception
132
+ LoggerProxy.log(`Received event: ${eventData?.data?.type ?? eventData.type}`, {
133
+ module: CC_FILE,
134
+ method: 'handleEvent',
135
+ });
136
+
137
+ // Route by type and emit to subscribers
138
+ switch (eventData.type) {
139
+ case CC_EVENTS.AGENT_STATE_CHANGE:
140
+ // @ts-ignore
141
+ this.trigger(AGENT_EVENTS.AGENT_STATE_CHANGE, eventData.data);
142
+ break;
143
+ // ... more cases
144
+ }
145
+ };
146
+ ```
147
+
148
+ ---
149
+
150
+ ## Event Emission
151
+
152
+ There are **two methods** for emitting events: `trigger` and `emit`. They are **not interchangeable** — which one to use depends on what the class extends.
153
+
154
+ ### `trigger` — for classes extending `WebexPlugin` (e.g., cc.ts)
155
+
156
+ `cc.ts` (`ContactCenter`) extends `WebexPlugin`, **not** `EventEmitter`. The `emit` method does not exist on `WebexPlugin`. The correct method for emitting events from `cc` is `trigger`, which comes from the Ampersand event system that `WebexPlugin` is built on.
157
+
158
+ ```typescript
159
+ // cc.ts — ContactCenter extends WebexPlugin
160
+ // @ts-ignore
161
+ this.trigger(TASK_EVENTS.TASK_INCOMING, task);
162
+
163
+ // @ts-ignore
164
+ this.trigger(TASK_EVENTS.TASK_HYDRATE, task);
165
+ ```
166
+
167
+ > **Note**: `trigger` requires `// @ts-ignore` because WebexPlugin's TypeScript type definitions don't expose it.
168
+
169
+ ### `emit` — for classes extending `EventEmitter` (e.g., Task, TaskManager, WebCallingService)
170
+
171
+ `emit` is the standard Node.js `EventEmitter` method. It works natively on classes that extend `EventEmitter` — no `@ts-ignore` needed.
172
+
173
+ ```typescript
174
+ // Task extends EventEmitter — emit works natively
175
+ export default abstract class Task extends EventEmitter implements ITask {
176
+ private autoAnswerIfNeeded() {
177
+ // ...
178
+ this.emit(TASK_EVENTS.TASK_AUTO_ANSWERED, this);
179
+ }
180
+ }
181
+
182
+ // TaskManager extends EventEmitter — emit works natively
183
+ export default class TaskManager extends EventEmitter {
184
+ private handleIncomingTask(taskData: TaskData) {
185
+ const task = this.createTask(taskData);
186
+ this.emit(TASK_EVENTS.TASK_INCOMING, task);
187
+ }
188
+ }
189
+ ```
190
+
191
+ > **Note on existing code**: The `cc` object currently uses `this.emit()` in `handleWebsocketMessage` for agent events with `// @ts-ignore`. This works at runtime but is not type-safe. For new code on the `cc` object, always use `trigger`.
192
+
193
+ ### When to Use Which
194
+
195
+ | Class extends | Method | `@ts-ignore` needed? | Example classes |
196
+ |---------------|--------|----------------------|-----------------|
197
+ | `WebexPlugin` | `trigger` | Yes | `cc.ts` (ContactCenter) |
198
+ | `EventEmitter` | `emit` | No | Task, TaskManager, WebCallingService, WebSocketManager |
199
+
200
+ ---
201
+
202
+ ## Event Subscription
203
+
204
+ ### How to Add / Remove a Listener
205
+
206
+ ```typescript
207
+ // Add a listener
208
+ source.on(EVENT_CONSTANT, handler);
209
+
210
+ // Remove a listener (must pass the same function reference)
211
+ source.off(EVENT_CONSTANT, handler);
212
+ ```
213
+
214
+ > **Important**: Always store the callback as a named function reference. Using inline anonymous functions makes it impossible to call `.off()` because you can't pass the same reference back.
215
+
216
+ #### Example
217
+
218
+ Store handler references so you can remove them later. Use **arrow function properties** or **`.bind(this)`** depending on the pattern:
219
+
220
+ ```typescript
221
+ // Pattern 1: Arrow function property (preserves `this` automatically)
222
+ private handleIncomingTask = (task: ITask) => {
223
+ // @ts-ignore
224
+ this.trigger(TASK_EVENTS.TASK_INCOMING, task);
225
+ };
226
+
227
+ // Register
228
+ this.taskManager.on(TASK_EVENTS.TASK_INCOMING, this.handleIncomingTask);
229
+
230
+ // Cleanup
231
+ this.taskManager.off(TASK_EVENTS.TASK_INCOMING, this.handleIncomingTask);
232
+
233
+ // Pattern 2: Regular method with .bind(this) (used by handleConnectionLost in cc.ts)
234
+ private async handleConnectionLost(msg: ConnectionLostDetails): Promise<void> {
235
+ // handle connection lost
236
+ }
237
+
238
+ // Register with .bind(this)
239
+ this.services.connectionService.on('connectionLost', this.handleConnectionLost.bind(this));
240
+ ```
241
+
242
+ ### Internal Event Listening (between services)
243
+
244
+ Internal services listen to each other during initialization, and clean up during deregistration:
245
+
246
+ ```typescript
247
+ // Register listeners after SDK is ready
248
+ this.$webex.once(READY, () => {
249
+ this.services.webSocketManager.on('message', this.handleWebsocketMessage);
250
+ this.services.connectionService.on('connectionLost', this.handleConnectionLost);
251
+ this.taskManager.on(TASK_EVENTS.TASK_INCOMING, this.handleIncomingTask);
252
+ this.taskManager.on(TASK_EVENTS.TASK_HYDRATE, this.handleTaskHydrate);
253
+ });
254
+
255
+ // Remove all listeners on deregister
256
+ public async deregister() {
257
+ this.taskManager.off(TASK_EVENTS.TASK_INCOMING, this.handleIncomingTask);
258
+ this.taskManager.off(TASK_EVENTS.TASK_HYDRATE, this.handleTaskHydrate);
259
+ this.services.webSocketManager.off('message', this.handleWebsocketMessage);
260
+ this.services.connectionService.off('connectionLost', this.handleConnectionLost);
261
+ }
262
+ ```
263
+
264
+ ### Events Sent to Application (from cc, task)
265
+
266
+ Application consumers subscribe to events on the `cc` object or on task instances. Always use named callbacks so `.off()` can reference the same function:
267
+
268
+ ```typescript
269
+ const cc = webex.cc;
270
+
271
+ // Define named callbacks (required for .off() to work)
272
+ const handleStateChange = (event) => {
273
+ // handle agent state change
274
+ };
275
+
276
+ const handleLoginSuccess = (event) => {
277
+ // handle login success
278
+ };
279
+
280
+ const handleIncomingTask = (task) => {
281
+ // handle incoming task
282
+ };
283
+
284
+ // Subscribe — agent events (from cc)
285
+ cc.on(AGENT_EVENTS.AGENT_STATE_CHANGE, handleStateChange);
286
+ cc.on(AGENT_EVENTS.AGENT_STATION_LOGIN_SUCCESS, handleLoginSuccess);
287
+
288
+ // Subscribe — task events (from cc)
289
+ cc.on(TASK_EVENTS.TASK_INCOMING, handleIncomingTask);
290
+
291
+ // Unsubscribe — pass the same function reference
292
+ cc.off(AGENT_EVENTS.AGENT_STATE_CHANGE, handleStateChange);
293
+ cc.off(AGENT_EVENTS.AGENT_STATION_LOGIN_SUCCESS, handleLoginSuccess);
294
+ cc.off(TASK_EVENTS.TASK_INCOMING, handleIncomingTask);
295
+ ```
296
+
297
+ ---
298
+
299
+ ## Event Data Transformation
300
+
301
+ ### Login Success Transformation
302
+
303
+ ```typescript
304
+ case CC_EVENTS.AGENT_STATION_LOGIN_SUCCESS: {
305
+ // Transform channelsMap to mmProfile
306
+ const {channelsMap, ...loginData} = eventData.data;
307
+ const stationLoginData = {
308
+ ...loginData,
309
+ mmProfile: {
310
+ chat: channelsMap.chat?.length,
311
+ email: channelsMap.email?.length,
312
+ social: channelsMap.social?.length,
313
+ telephony: channelsMap.telephony?.length,
314
+ },
315
+ notifsTrackingId: eventData.trackingId,
316
+ };
317
+
318
+ // @ts-ignore
319
+ this.trigger(AGENT_EVENTS.AGENT_STATION_LOGIN_SUCCESS, stationLoginData);
320
+ break;
321
+ }
322
+ ```
323
+
324
+ ---
325
+
326
+ ## Adding New Events
327
+
328
+ ### Step 1: Define Event Constant
329
+
330
+ ```typescript
331
+ // In appropriate types file
332
+ export const CC_MY_EVENTS = {
333
+ MY_NEW_EVENT: 'MyNewEvent',
334
+ MY_NEW_EVENT_SUCCESS: 'MyNewEventSuccess',
335
+ MY_NEW_EVENT_FAILED: 'MyNewEventFailed',
336
+ } as const;
337
+
338
+ // Add to CC_EVENTS if needed
339
+ export const CC_EVENTS = {
340
+ ...CC_AGENT_EVENTS,
341
+ ...CC_TASK_EVENTS,
342
+ ...CC_MY_EVENTS,
343
+ } as const;
344
+ ```
345
+
346
+ ### Step 2: Define External Event Name
347
+
348
+ ```typescript
349
+ export enum AGENT_EVENTS {
350
+ // ... existing
351
+ MY_NEW_EVENT = 'agent:myNewEvent',
352
+ MY_NEW_EVENT_SUCCESS = 'agent:myNewEventSuccess',
353
+ MY_NEW_EVENT_FAILED = 'agent:myNewEventFailed',
354
+ }
355
+ ```
356
+
357
+ ### Step 3: Handle in WebSocket Handler
358
+
359
+ ```typescript
360
+ case CC_EVENTS.MY_NEW_EVENT_SUCCESS:
361
+ // @ts-ignore
362
+ this.trigger(AGENT_EVENTS.MY_NEW_EVENT_SUCCESS, eventData.data);
363
+ break;
364
+ case CC_EVENTS.MY_NEW_EVENT_FAILED:
365
+ // @ts-ignore
366
+ this.trigger(AGENT_EVENTS.MY_NEW_EVENT_FAILED, eventData.data);
367
+ break;
368
+ ```
369
+
370
+ ### Step 4: Document the Event
371
+
372
+ ```typescript
373
+ /**
374
+ * @fires agent:myNewEvent When event occurs
375
+ * @fires agent:myNewEventSuccess When event succeeds
376
+ * @fires agent:myNewEventFailed When event fails
377
+ */
378
+ ```
379
+
380
+ ---
381
+
382
+ ## Event Type Safety
383
+
384
+ ### Typed Event Handlers
385
+
386
+ ```typescript
387
+ // Define event data types
388
+ type AgentStateChangeEvent = {
389
+ agentId: string;
390
+ state: string;
391
+ auxCodeId: string;
392
+ timestamp: number;
393
+ };
394
+
395
+ type TaskIncomingEvent = {
396
+ interactionId: string;
397
+ taskId: string;
398
+ channelType: string;
399
+ };
400
+
401
+ // Type-safe event handler
402
+ function onAgentStateChange(handler: (event: AgentStateChangeEvent) => void) {
403
+ cc.on(AGENT_EVENTS.AGENT_STATE_CHANGE, handler);
404
+ }
405
+ ```
406
+
407
+ ---
408
+
409
+ ## WebSocket Lifecycle
410
+
411
+ ### Registration (subscribing to messages)
412
+
413
+ ```typescript
414
+ // Subscribe to WebSocket messages during initialization
415
+ this.services.webSocketManager.on('message', this.handleWebsocketMessage);
416
+
417
+ // Subscribe to connection state changes
418
+ this.services.connectionService.on('connectionLost', this.handleConnectionLost);
419
+ ```
420
+
421
+ ### Connection
422
+
423
+ ```typescript
424
+ // Establish WebSocket connection via initWebSocket
425
+ const welcomeData = await this.services.webSocketManager.initWebSocket({
426
+ body: this.getConnectionConfig(),
427
+ });
428
+ // welcomeData contains the Welcome event with agentId
429
+ ```
430
+
431
+ ### Reconnection
432
+
433
+ ```typescript
434
+ // ConnectionService emits 'connectionLost' with connection state details
435
+ // The handler checks whether the socket was lost or reconnected
436
+ this.services.connectionService.on('connectionLost', this.handleConnectionLost);
437
+
438
+ // On reconnection, perform a silent relogin to restore agent state
439
+ private async silentRelogin(): Promise<void> {
440
+ await this.services.agent.reload();
441
+ }
442
+ ```
443
+
444
+ ### Disconnection
445
+
446
+ ```typescript
447
+ // 1. Remove all listeners first
448
+ this.services.webSocketManager.off('message', this.handleWebsocketMessage);
449
+ this.services.connectionService.off('connectionLost', this.handleConnectionLost);
450
+
451
+ // 2. Check socket state before closing
452
+ if (!this.services.webSocketManager.isSocketClosed) {
453
+ this.services.webSocketManager.close(false, 'Unregistering the SDK');
454
+ }
455
+ ```
456
+
457
+ ---
458
+
459
+ ## Best Practices
460
+
461
+ ### Always Use Constants
462
+
463
+ ```typescript
464
+ // CORRECT — use event constants, not raw strings
465
+ this.trigger(AGENT_EVENTS.AGENT_STATE_CHANGE, data); // WebexPlugin (cc.ts)
466
+ this.emit(TASK_EVENTS.TASK_INCOMING, task); // EventEmitter (Task, TaskManager)
467
+ cc.on(TASK_EVENTS.TASK_INCOMING, handler);
468
+
469
+ // WRONG — never use raw string event names
470
+ this.trigger('stateChange', data);
471
+ cc.on('task:incoming', handler);
472
+ ```
473
+
474
+ ### Always Clean Up Listeners
475
+
476
+ Every `on()` must have a corresponding `off()` in the deregister/cleanup path. See the [Event Subscription](#event-subscription) section for the full pattern.
477
+
478
+ ### Log Event Reception
479
+
480
+ ```typescript
481
+ LoggerProxy.log(`Received event: ${eventType}`, {
482
+ module: CC_FILE,
483
+ method: 'handleEvent',
484
+ });
485
+ ```