@webex/contact-center 3.12.0-next.9 → 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.
- package/AGENTS.md +438 -0
- package/ai-docs/README.md +131 -0
- package/ai-docs/RULES.md +455 -0
- package/ai-docs/patterns/event-driven-patterns.md +485 -0
- package/ai-docs/patterns/testing-patterns.md +480 -0
- package/ai-docs/patterns/typescript-patterns.md +365 -0
- package/ai-docs/templates/README.md +102 -0
- package/ai-docs/templates/documentation/create-agents-md.md +240 -0
- package/ai-docs/templates/documentation/create-architecture-md.md +295 -0
- package/ai-docs/templates/existing-service/bug-fix.md +254 -0
- package/ai-docs/templates/existing-service/feature-enhancement.md +450 -0
- package/ai-docs/templates/new-method/00-master.md +80 -0
- package/ai-docs/templates/new-method/01-requirements.md +232 -0
- package/ai-docs/templates/new-method/02-implementation.md +295 -0
- package/ai-docs/templates/new-method/03-tests.md +201 -0
- package/ai-docs/templates/new-method/04-validation.md +141 -0
- package/ai-docs/templates/new-service/00-master.md +109 -0
- package/ai-docs/templates/new-service/01-pre-questions.md +159 -0
- package/ai-docs/templates/new-service/02-code-generation.md +346 -0
- package/ai-docs/templates/new-service/03-integration.md +178 -0
- package/ai-docs/templates/new-service/04-test-generation.md +205 -0
- package/ai-docs/templates/new-service/05-validation.md +145 -0
- package/dist/cc.js +65 -123
- package/dist/cc.js.map +1 -1
- package/dist/constants.js +13 -2
- package/dist/constants.js.map +1 -1
- package/dist/index.js +13 -5
- package/dist/index.js.map +1 -1
- package/dist/metrics/behavioral-events.js +26 -13
- package/dist/metrics/behavioral-events.js.map +1 -1
- package/dist/metrics/constants.js +7 -6
- package/dist/metrics/constants.js.map +1 -1
- package/dist/services/ApiAiAssistant.js +0 -3
- package/dist/services/ApiAiAssistant.js.map +1 -1
- package/dist/services/config/Util.js +2 -3
- package/dist/services/config/Util.js.map +1 -1
- package/dist/services/config/types.js +16 -14
- package/dist/services/config/types.js.map +1 -1
- package/dist/services/constants.js +0 -1
- package/dist/services/constants.js.map +1 -1
- package/dist/services/core/Err.js.map +1 -1
- package/dist/services/core/Utils.js +79 -55
- package/dist/services/core/Utils.js.map +1 -1
- package/dist/services/core/aqm-reqs.js +17 -92
- package/dist/services/core/aqm-reqs.js.map +1 -1
- package/dist/services/core/websocket/WebSocketManager.js +5 -25
- package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
- package/dist/services/core/websocket/types.js.map +1 -1
- package/dist/services/index.js +1 -2
- package/dist/services/index.js.map +1 -1
- package/dist/services/task/Task.js +644 -0
- package/dist/services/task/Task.js.map +1 -0
- package/dist/services/task/TaskFactory.js +45 -0
- package/dist/services/task/TaskFactory.js.map +1 -0
- package/dist/services/task/TaskManager.js +556 -532
- package/dist/services/task/TaskManager.js.map +1 -1
- package/dist/services/task/TaskUtils.js +132 -28
- package/dist/services/task/TaskUtils.js.map +1 -1
- package/dist/services/task/constants.js +7 -6
- package/dist/services/task/constants.js.map +1 -1
- package/dist/services/task/dialer.js +0 -51
- package/dist/services/task/dialer.js.map +1 -1
- package/dist/services/task/digital/Digital.js +77 -0
- package/dist/services/task/digital/Digital.js.map +1 -0
- package/dist/services/task/state-machine/TaskStateMachine.js +634 -0
- package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -0
- package/dist/services/task/state-machine/actions.js +366 -0
- package/dist/services/task/state-machine/actions.js.map +1 -0
- package/dist/services/task/state-machine/constants.js +139 -0
- package/dist/services/task/state-machine/constants.js.map +1 -0
- package/dist/services/task/state-machine/guards.js +256 -0
- package/dist/services/task/state-machine/guards.js.map +1 -0
- package/dist/services/task/state-machine/index.js +53 -0
- package/dist/services/task/state-machine/index.js.map +1 -0
- package/dist/services/task/state-machine/types.js +54 -0
- package/dist/services/task/state-machine/types.js.map +1 -0
- package/dist/services/task/state-machine/uiControlsComputer.js +369 -0
- package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -0
- package/dist/services/task/taskDataNormalizer.js +99 -0
- package/dist/services/task/taskDataNormalizer.js.map +1 -0
- package/dist/services/task/types.js +157 -18
- package/dist/services/task/types.js.map +1 -1
- package/dist/services/task/voice/Voice.js +1031 -0
- package/dist/services/task/voice/Voice.js.map +1 -0
- package/dist/services/task/voice/WebRTC.js +149 -0
- package/dist/services/task/voice/WebRTC.js.map +1 -0
- package/dist/types/cc.d.ts +4 -33
- package/dist/types/constants.d.ts +13 -2
- package/dist/types/index.d.ts +11 -5
- package/dist/types/metrics/constants.d.ts +5 -3
- package/dist/types/services/ApiAiAssistant.d.ts +1 -1
- package/dist/types/services/config/types.d.ts +97 -25
- package/dist/types/services/core/Err.d.ts +0 -2
- package/dist/types/services/core/Utils.d.ts +25 -23
- package/dist/types/services/core/aqm-reqs.d.ts +0 -49
- package/dist/types/services/core/websocket/WebSocketManager.d.ts +1 -1
- package/dist/types/services/core/websocket/connection-service.d.ts +0 -1
- package/dist/types/services/core/websocket/types.d.ts +1 -1
- package/dist/types/services/index.d.ts +1 -1
- package/dist/types/services/task/Task.d.ts +146 -0
- package/dist/types/services/task/TaskFactory.d.ts +12 -0
- package/dist/types/services/task/TaskUtils.d.ts +39 -8
- package/dist/types/services/task/constants.d.ts +5 -4
- package/dist/types/services/task/dialer.d.ts +0 -15
- package/dist/types/services/task/digital/Digital.d.ts +22 -0
- package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +906 -0
- package/dist/types/services/task/state-machine/actions.d.ts +8 -0
- package/dist/types/services/task/state-machine/constants.d.ts +91 -0
- package/dist/types/services/task/state-machine/guards.d.ts +78 -0
- package/dist/types/services/task/state-machine/index.d.ts +13 -0
- package/dist/types/services/task/state-machine/types.d.ts +256 -0
- package/dist/types/services/task/state-machine/uiControlsComputer.d.ts +9 -0
- package/dist/types/services/task/taskDataNormalizer.d.ts +10 -0
- package/dist/types/services/task/types.d.ts +539 -88
- package/dist/types/services/task/voice/Voice.d.ts +183 -0
- package/dist/types/services/task/voice/WebRTC.d.ts +53 -0
- package/dist/types/types.d.ts +68 -0
- package/dist/types/webex.d.ts +1 -0
- package/dist/types.js +70 -0
- package/dist/types.js.map +1 -1
- package/dist/webex.js +14 -2
- package/dist/webex.js.map +1 -1
- package/package.json +14 -11
- package/src/cc.ts +91 -177
- package/src/constants.ts +13 -2
- package/src/index.ts +14 -5
- package/src/metrics/ai-docs/AGENTS.md +348 -0
- package/src/metrics/ai-docs/ARCHITECTURE.md +336 -0
- package/src/metrics/behavioral-events.ts +28 -14
- package/src/metrics/constants.ts +7 -8
- package/src/services/ApiAiAssistant.ts +2 -4
- package/src/services/agent/ai-docs/AGENTS.md +238 -0
- package/src/services/agent/ai-docs/ARCHITECTURE.md +302 -0
- package/src/services/ai-docs/AGENTS.md +384 -0
- package/src/services/config/Util.ts +2 -3
- package/src/services/config/ai-docs/AGENTS.md +253 -0
- package/src/services/config/ai-docs/ARCHITECTURE.md +424 -0
- package/src/services/config/types.ts +108 -20
- package/src/services/constants.ts +0 -1
- package/src/services/core/Err.ts +0 -1
- package/src/services/core/Utils.ts +90 -67
- package/src/services/core/ai-docs/AGENTS.md +379 -0
- package/src/services/core/ai-docs/ARCHITECTURE.md +696 -0
- package/src/services/core/aqm-reqs.ts +22 -100
- package/src/services/core/websocket/WebSocketManager.ts +4 -23
- package/src/services/core/websocket/types.ts +1 -1
- package/src/services/index.ts +1 -2
- package/src/services/task/Task.ts +785 -0
- package/src/services/task/TaskFactory.ts +55 -0
- package/src/services/task/TaskManager.ts +567 -633
- package/src/services/task/TaskUtils.ts +175 -31
- package/src/services/task/ai-docs/AGENTS.md +448 -0
- package/src/services/task/ai-docs/ARCHITECTURE.md +573 -0
- package/src/services/task/constants.ts +5 -4
- package/src/services/task/dialer.ts +1 -56
- package/src/services/task/digital/Digital.ts +95 -0
- package/src/services/task/state-machine/TaskStateMachine.ts +793 -0
- package/src/services/task/state-machine/actions.ts +409 -0
- package/src/services/task/state-machine/ai-docs/AGENTS.md +495 -0
- package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +1135 -0
- package/src/services/task/state-machine/constants.ts +150 -0
- package/src/services/task/state-machine/guards.ts +295 -0
- package/src/services/task/state-machine/index.ts +28 -0
- package/src/services/task/state-machine/types.ts +228 -0
- package/src/services/task/state-machine/uiControlsComputer.ts +529 -0
- package/src/services/task/taskDataNormalizer.ts +137 -0
- package/src/services/task/types.ts +641 -95
- package/src/services/task/voice/Voice.ts +1255 -0
- package/src/services/task/voice/WebRTC.ts +187 -0
- package/src/types.ts +88 -5
- package/src/utils/AGENTS.md +276 -0
- package/src/webex.js +2 -0
- package/test/unit/spec/cc.ts +59 -142
- package/test/unit/spec/logger-proxy.ts +70 -0
- package/test/unit/spec/services/ApiAiAssistant.ts +17 -0
- package/test/unit/spec/services/config/index.ts +26 -55
- package/test/unit/spec/services/core/Utils.ts +103 -52
- package/test/unit/spec/services/core/websocket/WebSocketManager.ts +48 -112
- package/test/unit/spec/services/core/websocket/connection-service.ts +5 -4
- package/test/unit/spec/services/task/AutoWrapup.ts +63 -0
- package/test/unit/spec/services/task/Task.ts +416 -0
- package/test/unit/spec/services/task/TaskFactory.ts +62 -0
- package/test/unit/spec/services/task/TaskManager.ts +781 -1735
- package/test/unit/spec/services/task/TaskUtils.ts +125 -0
- package/test/unit/spec/services/task/dialer.ts +112 -198
- package/test/unit/spec/services/task/digital/Digital.ts +105 -0
- package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +473 -0
- package/test/unit/spec/services/task/state-machine/guards.ts +288 -0
- package/test/unit/spec/services/task/state-machine/types.ts +18 -0
- package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +147 -0
- package/test/unit/spec/services/task/taskTestUtils.ts +87 -0
- package/test/unit/spec/services/task/voice/Voice.ts +587 -0
- package/test/unit/spec/services/task/voice/WebRTC.ts +242 -0
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
- package/dist/services/task/index.js +0 -1525
- package/dist/services/task/index.js.map +0 -1
- package/dist/types/services/task/index.d.ts +0 -650
- package/src/services/task/index.ts +0 -1801
- 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)
|