@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,232 @@
1
+ # New Method - Requirements
2
+
3
+ > **Purpose**: Gather requirements from the developer before implementing the new method.
4
+
5
+ ---
6
+
7
+ ## STOP — Ask These Questions First
8
+
9
+ **You MUST present the following questions to the developer and wait for their answers before proceeding.** Do not infer answers from the developer's initial request. Do not fill in fields yourself. Do not start reading implementation code yet.
10
+
11
+ Present questions grouped by section. If the developer cannot answer a MANDATORY question, ask follow-up questions to help them clarify. Only proceed to implementation when all MANDATORY fields have explicit developer-provided answers.
12
+
13
+ ---
14
+
15
+ ## 1. Method Identity (MANDATORY)
16
+
17
+ Ask the developer:
18
+
19
+ 1. **"Which file should this method be added to?"**
20
+ - e.g., `cc.ts`, `services/agent/index.ts`, `services/task/contact.ts`
21
+
22
+ 2. **"What should the method be named?"**
23
+ - Must be camelCase (e.g., `getTeamStats`, `getBuddyAgents`)
24
+
25
+ 3. **"What does this method do? Describe the expected behavior in one or two sentences."**
26
+
27
+ ---
28
+
29
+ ## 2. Method Signature (MANDATORY)
30
+
31
+ Ask the developer:
32
+
33
+ 4. **"What parameters does this method accept? For each parameter, provide:"**
34
+ - Parameter name
35
+ - Type (string, number, object — if object, what fields?)
36
+ - Required or optional?
37
+
38
+ 5. **"What does this method return?"**
39
+ - Return type structure (e.g., `{ data: { agentList: Agent[] }, trackingId: string }`)
40
+ - What fields will consumers use?
41
+
42
+ ---
43
+
44
+ ## 3. API Integration (MANDATORY if the method calls a backend API, otherwise skip)
45
+
46
+ Ask the developer:
47
+
48
+ 6. **"Does this method call a backend API?"**
49
+ - If YES, for each API call ask:
50
+
51
+ | Field | What to Ask |
52
+ |---|---|
53
+ | HTTP Method | "Is this a GET, POST, PUT, or DELETE?" |
54
+ | Endpoint | "What is the full endpoint path?" |
55
+ | Request Payload | "What fields does the request body contain? Which are required vs optional?" |
56
+ | Response Channel | "Is the response received in the HTTP response itself, or via a WebSocket message?" |
57
+ | Response Structure | "What does the response look like?" |
58
+ | Error Shape | "What error reason codes can this return?" |
59
+
60
+ > **Note**: Some methods receive their response directly in the HTTP response (e.g., `getBuddyAgents` returns data in the API response). Others initiate an operation via HTTP and receive the result asynchronously through a WebSocket message (e.g., `stationLogin` sends HTTP request, then receives `AGENT_STATION_LOGIN_SUCCESS` or `AGENT_STATION_LOGIN_FAILED` via WebSocket). Clarify which pattern applies.
61
+
62
+ **If any API field is unknown, STOP and ask the developer. Do not guess.**
63
+
64
+ - If NO (e.g., local computation, state change only): note "No API call" and skip to section 4.
65
+
66
+ ---
67
+
68
+ ## 4. Event Contract (MANDATORY if the method emits or listens to events, otherwise skip)
69
+
70
+ Ask the developer:
71
+
72
+ 7. **"Does this method emit any events or listen to events?"**
73
+ - If YES, for each event ask:
74
+
75
+ | Field | What to Ask |
76
+ |---|---|
77
+ | Event Name | "What is the event name?" (e.g., `agent:buddyListSuccess`) |
78
+ | Direction | "Is this incoming (WebSocket) or outgoing (emitted by SDK)?" |
79
+ | Listen/Emit Object | "Where do consumers subscribe?" (`cc`, `task`, `taskManager`, service) |
80
+ | Payload Type/Shape | "What data does the event carry?" |
81
+ | Emitted From | "Which class/file emits this?" |
82
+ | Emission Trigger | "What causes this event to fire?" (e.g., API success, WebSocket message) |
83
+
84
+ **If the developer needs new event constants, note the constant names and values.**
85
+
86
+ - If NO: note "No events" and skip to section 5.
87
+
88
+ ---
89
+
90
+ ## 5. Metrics (MANDATORY)
91
+
92
+ Ask the developer:
93
+
94
+ 8. **"What should the success and failure metric event names be?"**
95
+ - e.g., `FETCH_BUDDY_AGENTS_SUCCESS` / `FETCH_BUDDY_AGENTS_FAILED`
96
+ - If the developer is unsure, suggest names following the convention: `[ACTION]_[OPERATION]_SUCCESS` / `[ACTION]_[OPERATION]_FAILED`
97
+
98
+ 9. **"Do new metric constants need to be added to `src/metrics/constants.ts`?"**
99
+
100
+ ---
101
+
102
+ ## 6. Behavior Details (MANDATORY)
103
+
104
+ Ask the developer:
105
+
106
+ 10. **"What should happen on success? (e.g., return data, emit event, update state)"**
107
+
108
+ 11. **"What should happen on failure? (e.g., throw error, emit failure event, retry)"**
109
+
110
+ 12. **"Are there any edge cases or special scenarios to handle?"**
111
+ - e.g., empty results, missing permissions, specific error codes
112
+
113
+ ---
114
+
115
+ ## Completion Gate
116
+
117
+ **Before proceeding, verify:**
118
+
119
+ - [ ] Target file identified by developer
120
+ - [ ] Method name provided by developer
121
+ - [ ] Purpose/behavior described by developer
122
+ - [ ] Parameters fully specified (names, types, required/optional)
123
+ - [ ] Return type fully specified
124
+ - [ ] API contract captured (or developer confirmed no API call)
125
+ - [ ] Event contract captured (or developer confirmed no events)
126
+ - [ ] Metric event names defined
127
+ - [ ] Success and failure behavior described
128
+
129
+ **If any MANDATORY field above is missing an explicit developer answer, ask a targeted follow-up question. Do not proceed.**
130
+
131
+ ---
132
+
133
+ ## Spec Summary
134
+
135
+ Once all questions are answered, present this summary to the developer for approval before proceeding to implementation:
136
+
137
+ ```
138
+ ## Spec Summary — New Method
139
+
140
+ **Method**: `[methodName]([params]): Promise<[ReturnType]>`
141
+ **Target file**: [file path]
142
+ **Purpose**: [from Q3]
143
+
144
+ ### Parameters:
145
+ | Name | Type | Required | Description |
146
+ |---|---|---|---|
147
+ | [param] | [type] | [Yes/No] | [description] |
148
+
149
+ ### API Contract:
150
+ - HTTP: [METHOD] [endpoint]
151
+ - Request: [payload structure]
152
+ - Response: [response structure]
153
+ - Errors: [reason codes]
154
+ (or "No API call")
155
+
156
+ ### Events:
157
+ | Event | Direction | Object | Payload | Trigger |
158
+ |---|---|---|---|---|
159
+ | [event] | [in/out] | [object] | [payload] | [trigger] |
160
+ (or "No events")
161
+
162
+ ### Metrics:
163
+ - Success: [METRIC_NAME_SUCCESS]
164
+ - Failure: [METRIC_NAME_FAILED]
165
+ - New constants needed: [Yes/No]
166
+
167
+ ### Behavior:
168
+ - On success: [description]
169
+ - On failure: [description]
170
+ - Edge cases: [list or "None"]
171
+
172
+ ---
173
+ Does this match your intent? (Yes / No / Adjust)
174
+ ```
175
+
176
+ **Wait for developer approval. Do not proceed to [`02-implementation.md`](02-implementation.md) until confirmed.**
177
+
178
+ ---
179
+
180
+ ## Example: Adding getBuddyAgents
181
+
182
+ ```
183
+ ## Spec Summary — New Method
184
+
185
+ **Method**: `getBuddyAgents(data: BuddyAgents): Promise<BuddyAgentsResponse>`
186
+ **Target file**: cc.ts
187
+ **Purpose**: Get list of available agents for consult/transfer
188
+ **Types to create**: Define `BuddyAgents` (request params) and `BuddyAgentsResponse` (response) in the appropriate types file (`src/types.ts` for public types, or `src/services/[service]/types.ts` for internal types). Export public types from `src/types.ts`.
189
+
190
+ ### Parameters:
191
+ | Name | Type | Required | Description |
192
+ |---|---|---|---|
193
+ | mediaType | 'telephony' \| 'chat' \| 'social' \| 'email' | Yes | Media type channel filter |
194
+ | state | 'Available' \| 'Idle' | No | Optional agent state filter |
195
+
196
+ ### API Contract:
197
+ - HTTP: POST /v1/agents/buddyList
198
+ - Request: { agentProfileId: string, mediaType: string, state?: string }
199
+ - Response channel: HTTP response (synchronous)
200
+ - Response: { data: { agentList: BuddyDetails[] }, trackingId: string }
201
+ - Errors: INVALID_STATE, UNAUTHORIZED
202
+
203
+ ### Events: No events (promise-based only)
204
+
205
+ ### Metrics:
206
+ - Success: FETCH_BUDDY_AGENTS_SUCCESS
207
+ - Failure: FETCH_BUDDY_AGENTS_FAILED
208
+ - New constants needed: Yes
209
+
210
+ ### Behavior:
211
+ - On success: return response data
212
+ - On failure: throw augmented error via getErrorDetails
213
+ - Edge cases: empty agentList returns { data: { agentList: [] } }
214
+
215
+ ### Type Definitions:
216
+ - **Input type `BuddyAgents`**: Defined in `src/types.ts` (public, consumer-facing)
217
+ and `src/services/agent/types.ts` (internal, includes `agentProfileId` added by cc.ts)
218
+ - **Response type `BuddyAgentsResponse`**: Defined in `src/types.ts` as
219
+ `Agent.BuddyAgentsSuccess | Error`
220
+ - **Internal types `BuddyAgentsSuccess`, `BuddyDetails`**: Defined in
221
+ `src/services/agent/types.ts`
222
+ - **Pattern**: Public types (what consumers see) go in `src/types.ts`.
223
+ Internal/service types (with extra fields like `agentProfileId`) go in
224
+ `src/services/[service]/types.ts`.
225
+ ```
226
+
227
+ ---
228
+
229
+ ## Next Step
230
+
231
+ Once the developer approves the spec summary, proceed to:
232
+ [`02-implementation.md`](02-implementation.md)
@@ -0,0 +1,295 @@
1
+ # New Method - Implementation
2
+
3
+ > **Purpose**: Implement the new method following SDK patterns.
4
+
5
+ ---
6
+
7
+ ## Method Invocation Patterns
8
+
9
+ There are two common patterns for where methods are implemented. The public method lives on whichever object owns the feature's scope (currently `cc` for SDK-level operations, `task` for per-interaction operations, or a public service accessor for domain-specific queries). New public objects may be introduced in the future.
10
+
11
+ 1. **Public wrapper + internal service call**: The public method is defined on the owning object, but the actual implementation lives in a service module. The public method delegates internally.
12
+ ```typescript
13
+ // Example A: cc.ts — SDK-level method delegates to agent service
14
+ public async getBuddyAgents(data: BuddyAgents): Promise<BuddyAgentsResponse> {
15
+ const resp = await this.services.agent.buddyAgents({
16
+ data: {agentProfileId: this.agentConfig.agentProfileID, ...data},
17
+ });
18
+ return resp;
19
+ }
20
+
21
+ // Example B: Task.ts — per-interaction method delegates to contact service
22
+ public async hold(): Promise<TaskResponse> {
23
+ return this.contact.hold({...});
24
+ }
25
+ ```
26
+
27
+ 2. **Direct service access**: Sometimes consumers call a service method directly via a public service accessor on `cc`.
28
+ ```typescript
29
+ // Consumer code calling service directly via public accessor
30
+ const queues = await cc.queue.getQueues();
31
+ const entries = await cc.addressBook.getEntries();
32
+ ```
33
+ > **Note:** Use `cc.<serviceName>` (e.g., `cc.queue`, `cc.addressBook`), NOT `cc.services.<serviceName>`. The `services` object is internal.
34
+
35
+ Determine which pattern applies based on the requirements gathered in Step 1.
36
+
37
+ ---
38
+
39
+ ## Method Template
40
+
41
+ ```typescript
42
+ /**
43
+ * Brief description of what this method does.
44
+ *
45
+ * @description
46
+ * Detailed description including:
47
+ * - What the method accomplishes
48
+ * - When to use it
49
+ * - Prerequisites (e.g., must be logged in)
50
+ *
51
+ * @param {ParamType} data - Description of parameters
52
+ * @param {string} data.requiredField - Description
53
+ * @param {number} [data.optionalField] - Optional field description
54
+ *
55
+ * @returns {Promise<ReturnType>} Description including:
56
+ * - field1: What this field contains
57
+ * - field2: What this field contains
58
+ *
59
+ * @throws {Error} When operation fails with reason in error.message
60
+ *
61
+ * @public
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * const cc = webex.cc;
66
+ * await cc.register();
67
+ * await cc.stationLogin({ teamId: 'team123', loginOption: 'BROWSER' });
68
+ *
69
+ * // Basic usage
70
+ * const result = await cc.methodName({
71
+ * requiredField: 'value',
72
+ * });
73
+ *
74
+ * // With optional params
75
+ * const result = await cc.methodName({
76
+ * requiredField: 'value',
77
+ * optionalField: 42,
78
+ * });
79
+ * ```
80
+ */
81
+ public async methodName(data: ParamType): Promise<ReturnType> {
82
+ // 1. Log start of operation
83
+ LoggerProxy.info('Starting operation', {
84
+ module: CC_FILE,
85
+ method: METHODS.METHOD_NAME,
86
+ });
87
+
88
+ try {
89
+ // 2. Start timing for metrics
90
+ this.metricsManager.timeEvent([
91
+ METRIC_EVENT_NAMES.OPERATION_SUCCESS,
92
+ METRIC_EVENT_NAMES.OPERATION_FAILED,
93
+ ]);
94
+
95
+ // 3. Validate input if needed
96
+ if (!data.requiredField) {
97
+ throw new Error('requiredField is required');
98
+ }
99
+
100
+ // 4. Call service method
101
+ const result = await this.services.someService.method({
102
+ data: {
103
+ ...data,
104
+ // Add any additional fields from agentConfig if needed
105
+ agentId: this.agentConfig.agentId,
106
+ },
107
+ });
108
+
109
+ // 5. Track success metrics
110
+ this.metricsManager.trackEvent(
111
+ METRIC_EVENT_NAMES.OPERATION_SUCCESS,
112
+ {
113
+ ...MetricsManager.getCommonTrackingFieldForAQMResponse(result),
114
+ // Add operation-specific fields
115
+ customField: data.requiredField,
116
+ },
117
+ ['behavioral', 'operational'] // Adjust metric types as needed
118
+ );
119
+
120
+ // 6. Log success
121
+ LoggerProxy.log('Operation completed successfully', {
122
+ module: CC_FILE,
123
+ method: METHODS.METHOD_NAME,
124
+ trackingId: result.trackingId,
125
+ });
126
+
127
+ // 7. Return result (transform if needed)
128
+ return result;
129
+
130
+ } catch (error) {
131
+ // 8. Cast error details
132
+ const failure = error.details as Failure;
133
+
134
+ // 9. Track failure metrics
135
+ this.metricsManager.trackEvent(
136
+ METRIC_EVENT_NAMES.OPERATION_FAILED,
137
+ {
138
+ ...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(failure),
139
+ customField: data.requiredField,
140
+ },
141
+ ['behavioral', 'operational']
142
+ );
143
+
144
+ // 10. Get detailed error (this logs and uploads logs automatically)
145
+ const {error: detailedError} = getErrorDetails(
146
+ error,
147
+ METHODS.METHOD_NAME,
148
+ CC_FILE
149
+ );
150
+
151
+ // 11. Throw augmented error
152
+ throw detailedError;
153
+ }
154
+ }
155
+ ```
156
+
157
+ ---
158
+
159
+ ## Event Emission (if applicable)
160
+
161
+ If the method needs to emit events, understand the two-step flow used in the SDK:
162
+
163
+ ### How it works: WebSocket trigger → EventEmitter emit
164
+
165
+ For methods that go through `aqm-reqs` (used by all AQM-integrated services — agent, task, etc., except config service GET methods), the flow is:
166
+
167
+ 1. **cc.ts** public method calls a service method (e.g., `this.services.agent.stationLogin()`)
168
+ 2. **aqm-reqs.ts** sends an HTTP request AND registers pending handlers for the expected WebSocket success/fail messages (via `notifSuccess`/`notifFail` bindings)
169
+ 3. **Backend** processes the request and sends the result back via **WebSocket**
170
+ 4. **aqm-reqs.onMessage()** receives the WS message, matches it to the pending request, and resolves/rejects the Promise
171
+ 5. **cc.ts `handleWebsocketMessage()`** also receives the same WS message and uses `trigger` to fire events for consumers
172
+
173
+ ```
174
+ HTTP request → Backend → WS message
175
+ ├─→ aqm-reqs.onMessage() → resolves/rejects Promise
176
+ └─→ cc.ts handleWebsocketMessage() → this.trigger(EVENT)
177
+ ```
178
+
179
+ ### Real example: `setAgentState` in cc.ts
180
+
181
+ **Step 1 — Service defines WS bindings** (in `services/agent/index.ts`):
182
+ ```typescript
183
+ stateChange: routing.req((p: {data: Agent.StateChange}) => ({
184
+ url: '/v1/agents/state',
185
+ host: WCC_API_GATEWAY,
186
+ data: p.data,
187
+ err,
188
+ notifSuccess: {
189
+ bind: { type: CC_EVENTS.AGENT_STATE_CHANGE_SUCCESS },
190
+ msg: {} as Agent.StateChangeSuccess,
191
+ },
192
+ notifFail: {
193
+ bind: { type: CC_EVENTS.AGENT_STATE_CHANGE_FAILED },
194
+ errId: 'Service.aqm.agent.stateChange',
195
+ },
196
+ })),
197
+ ```
198
+
199
+ **Step 2 — WS message triggers event** (in `cc.ts handleWebsocketMessage()`):
200
+ ```typescript
201
+ case CC_EVENTS.AGENT_STATE_CHANGE_SUCCESS:
202
+ // cc.ts extends WebexPlugin — use trigger, not emit
203
+ // @ts-ignore
204
+ this.trigger(AGENT_EVENTS.AGENT_STATE_CHANGE_SUCCESS, eventData.data);
205
+ break;
206
+ case CC_EVENTS.AGENT_STATE_CHANGE_FAILED:
207
+ // @ts-ignore
208
+ this.trigger(AGENT_EVENTS.AGENT_STATE_CHANGE_FAILED, eventData.data);
209
+ break;
210
+ ```
211
+
212
+ **Step 3 — Consumer listens** using `.on()`:
213
+ ```typescript
214
+ const handleStateChangeSuccess = (data) => {
215
+ // Handle state change success
216
+ };
217
+ cc.on(AGENT_EVENTS.AGENT_STATE_CHANGE_SUCCESS, handleStateChangeSuccess);
218
+ ```
219
+
220
+ ### Task-level events (method-level emit)
221
+
222
+ For Task methods (which extend `EventEmitter`), events are emitted directly using `emit`:
223
+ ```typescript
224
+ // Task.ts extends EventEmitter — emit works natively
225
+ // On success, emit directly:
226
+ this.emit(TASK_EVENTS.TASK_AUTO_ANSWERED, this);
227
+ ```
228
+
229
+ > **When to emit events**: Emit events when consumers need to react asynchronously to state changes (WS-driven methods like `stationLogin`, `setAgentState`). For simple request-response methods (like `getBuddyAgents`), the returned Promise is sufficient — no events needed.
230
+
231
+ ---
232
+
233
+ ## Adding Method Constants
234
+
235
+ In `src/constants.ts`, add method name:
236
+
237
+ ```typescript
238
+ export const METHODS = {
239
+ // ... existing
240
+ METHOD_NAME: 'methodName',
241
+ } as const;
242
+ ```
243
+
244
+ ---
245
+
246
+ ## Adding Metric Constants
247
+
248
+ In `src/metrics/constants.ts`:
249
+
250
+ ```typescript
251
+ export const METRIC_EVENT_NAMES = {
252
+ // ... existing
253
+ OPERATION_SUCCESS: 'operation success',
254
+ OPERATION_FAILED: 'operation failed',
255
+ } as const;
256
+ ```
257
+
258
+ ---
259
+
260
+ ## Adding Types
261
+
262
+ In `src/types.ts` or appropriate service types file:
263
+
264
+ ```typescript
265
+ /**
266
+ * Parameters for methodName operation
267
+ * @public
268
+ */
269
+ export type ParamType = {
270
+ /** Description of required field */
271
+ requiredField: string;
272
+ /** Description of optional field */
273
+ optionalField?: number;
274
+ };
275
+
276
+ /**
277
+ * Response from methodName operation
278
+ * @public
279
+ */
280
+ export type ReturnType = {
281
+ /** Description of data */
282
+ data: {
283
+ /** Field description */
284
+ field: string;
285
+ };
286
+ /** Request tracking ID */
287
+ trackingId: string;
288
+ };
289
+ ```
290
+
291
+ ---
292
+
293
+ ## Next Step
294
+
295
+ Proceed to: [`03-tests.md`](03-tests.md)