@webex/contact-center 3.12.0-next.73 → 3.12.0-next.74
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 +53 -38
- package/dist/cc.js.map +1 -1
- package/dist/config.js +6 -0
- package/dist/config.js.map +1 -1
- package/dist/constants.js +14 -1
- 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 -0
- package/dist/metrics/behavioral-events.js.map +1 -1
- package/dist/metrics/constants.js +9 -3
- package/dist/metrics/constants.js.map +1 -1
- package/dist/services/ApiAiAssistant.js +74 -3
- package/dist/services/ApiAiAssistant.js.map +1 -1
- package/dist/services/config/Util.js +2 -2
- package/dist/services/config/Util.js.map +1 -1
- package/dist/services/config/types.js +25 -9
- package/dist/services/config/types.js.map +1 -1
- package/dist/services/core/Utils.js +74 -27
- package/dist/services/core/Utils.js.map +1 -1
- package/dist/services/core/websocket/WebSocketManager.js +2 -1
- 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 -1
- package/dist/services/index.js.map +1 -1
- package/dist/services/task/Task.js +688 -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 +725 -612
- package/dist/services/task/TaskManager.js.map +1 -1
- package/dist/services/task/TaskUtils.js +162 -26
- package/dist/services/task/TaskUtils.js.map +1 -1
- package/dist/services/task/constants.js +6 -1
- package/dist/services/task/constants.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 +837 -0
- package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -0
- package/dist/services/task/state-machine/actions.js +543 -0
- package/dist/services/task/state-machine/actions.js.map +1 -0
- package/dist/services/task/state-machine/constants.js +161 -0
- package/dist/services/task/state-machine/constants.js.map +1 -0
- package/dist/services/task/state-machine/guards.js +340 -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 +553 -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 +168 -16
- package/dist/services/task/types.js.map +1 -1
- package/dist/services/task/voice/Voice.js +1042 -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 +19 -18
- package/dist/types/config.d.ts +6 -0
- package/dist/types/constants.d.ts +14 -1
- package/dist/types/index.d.ts +11 -5
- package/dist/types/metrics/constants.d.ts +7 -1
- package/dist/types/services/ApiAiAssistant.d.ts +11 -3
- package/dist/types/services/config/types.d.ts +113 -9
- package/dist/types/services/core/Utils.d.ts +23 -10
- package/dist/types/services/core/websocket/WebSocketManager.d.ts +1 -0
- 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 +157 -0
- package/dist/types/services/task/TaskFactory.d.ts +12 -0
- package/dist/types/services/task/TaskUtils.d.ts +46 -2
- package/dist/types/services/task/constants.d.ts +5 -0
- package/dist/types/services/task/digital/Digital.d.ts +22 -0
- package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +1144 -0
- package/dist/types/services/task/state-machine/actions.d.ts +10 -0
- package/dist/types/services/task/state-machine/constants.d.ts +107 -0
- package/dist/types/services/task/state-machine/guards.d.ts +90 -0
- package/dist/types/services/task/state-machine/index.d.ts +13 -0
- package/dist/types/services/task/state-machine/types.d.ts +267 -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 +551 -78
- package/dist/types/services/task/voice/Voice.d.ts +184 -0
- package/dist/types/services/task/voice/WebRTC.d.ts +53 -0
- package/dist/types/types.d.ts +92 -0
- package/dist/types/webex.d.ts +1 -0
- package/dist/types.js +85 -0
- package/dist/types.js.map +1 -1
- package/dist/webex.js +14 -2
- package/dist/webex.js.map +1 -1
- package/package.json +15 -12
- package/src/cc.ts +63 -43
- package/src/config.ts +6 -0
- package/src/constants.ts +14 -1
- 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 -0
- package/src/metrics/constants.ts +9 -4
- package/src/services/ApiAiAssistant.ts +104 -3
- 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 -2
- 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 +116 -10
- package/src/services/core/Utils.ts +85 -34
- package/src/services/core/ai-docs/AGENTS.md +379 -0
- package/src/services/core/ai-docs/ARCHITECTURE.md +696 -0
- package/src/services/core/websocket/WebSocketManager.ts +2 -0
- package/src/services/core/websocket/types.ts +1 -1
- package/src/services/index.ts +1 -1
- package/src/services/task/Task.ts +837 -0
- package/src/services/task/TaskFactory.ts +55 -0
- package/src/services/task/TaskManager.ts +738 -697
- package/src/services/task/TaskUtils.ts +205 -25
- package/src/services/task/ai-docs/AGENTS.md +455 -0
- package/src/services/task/ai-docs/ARCHITECTURE.md +585 -0
- package/src/services/task/constants.ts +5 -0
- package/src/services/task/digital/Digital.ts +95 -0
- package/src/services/task/state-machine/TaskStateMachine.ts +1077 -0
- package/src/services/task/state-machine/actions.ts +685 -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 +172 -0
- package/src/services/task/state-machine/guards.ts +406 -0
- package/src/services/task/state-machine/index.ts +28 -0
- package/src/services/task/state-machine/types.ts +241 -0
- package/src/services/task/state-machine/uiControlsComputer.ts +867 -0
- package/src/services/task/taskDataNormalizer.ts +137 -0
- package/src/services/task/types.ts +654 -85
- package/src/services/task/voice/Voice.ts +1267 -0
- package/src/services/task/voice/WebRTC.ts +187 -0
- package/src/types.ts +112 -1
- package/src/utils/AGENTS.md +276 -0
- package/src/webex.js +2 -0
- package/test/unit/spec/cc.ts +133 -3
- package/test/unit/spec/logger-proxy.ts +70 -0
- package/test/unit/spec/services/ApiAiAssistant.ts +122 -17
- package/test/unit/spec/services/WebCallingService.ts +7 -1
- package/test/unit/spec/services/config/index.ts +27 -27
- package/test/unit/spec/services/core/Utils.ts +335 -1
- package/test/unit/spec/services/core/websocket/WebSocketManager.ts +66 -40
- package/test/unit/spec/services/task/AutoWrapup.ts +63 -0
- package/test/unit/spec/services/task/Task.ts +477 -0
- package/test/unit/spec/services/task/TaskFactory.ts +62 -0
- package/test/unit/spec/services/task/TaskManager.ts +821 -1936
- package/test/unit/spec/services/task/TaskUtils.ts +206 -0
- package/test/unit/spec/services/task/digital/Digital.ts +105 -0
- package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +1825 -0
- package/test/unit/spec/services/task/state-machine/guards.ts +479 -0
- package/test/unit/spec/services/task/state-machine/types.ts +18 -0
- package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +2020 -0
- package/test/unit/spec/services/task/taskTestUtils.ts +87 -0
- package/test/unit/spec/services/task/voice/Voice.ts +631 -0
- package/test/unit/spec/services/task/voice/WebRTC.ts +235 -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 -1530
- 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 -1806
- package/test/unit/spec/services/task/index.ts +0 -2205
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
# Agent Service - Architecture
|
|
2
|
+
|
|
3
|
+
> **Purpose**: Technical documentation for agent lifecycle operations.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Component Overview
|
|
8
|
+
|
|
9
|
+
| Component | File | Responsibility |
|
|
10
|
+
| --------------- | --------------------------- | --------------------------------------------------------------- |
|
|
11
|
+
| `ContactCenter` | `src/cc.ts` | Plugin class exposing agent methods |
|
|
12
|
+
| `routingAgent` | `services/agent/index.ts` | AQM request definitions |
|
|
13
|
+
| `Services` | `services/index.ts` | Service singleton with agent service |
|
|
14
|
+
| `AqmReqs` | `services/core/aqm-reqs.ts` | HTTP requests to backend; responses via WebSocket notifications |
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## File Structure
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
services/agent/
|
|
22
|
+
├── index.ts # Agent service factory
|
|
23
|
+
├── types.ts # Agent types and events
|
|
24
|
+
└── ai-docs/
|
|
25
|
+
├── AGENTS.md # Usage documentation
|
|
26
|
+
└── ARCHITECTURE.md # This file
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Service Factory Pattern
|
|
32
|
+
|
|
33
|
+
The agent service uses a factory pattern:
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
// services/agent/index.ts
|
|
37
|
+
export default function routingAgent(routing: AqmReqs) {
|
|
38
|
+
return {
|
|
39
|
+
stationLogin: routing.req((p: {data: UserStationLogin}) => ({
|
|
40
|
+
url: '/v1/agents/login',
|
|
41
|
+
host: WCC_API_GATEWAY,
|
|
42
|
+
data: p.data,
|
|
43
|
+
notifSuccess: {
|
|
44
|
+
bind: {type: CC_EVENTS.AGENT_STATION_LOGIN, ...},
|
|
45
|
+
msg: {} as StationLoginSuccess,
|
|
46
|
+
},
|
|
47
|
+
notifFail: {...},
|
|
48
|
+
})),
|
|
49
|
+
logout: routing.req((p: {data: Logout}) => ({...})),
|
|
50
|
+
stateChange: routing.req((p: {data: StateChange}) => ({...})),
|
|
51
|
+
buddyAgents: routing.req((p: {data: BuddyAgents}) => ({...})),
|
|
52
|
+
reload: routing.reqEmpty(() => ({...})),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Data Flow
|
|
60
|
+
|
|
61
|
+
### Station Login Flow
|
|
62
|
+
|
|
63
|
+
```mermaid
|
|
64
|
+
flowchart TD
|
|
65
|
+
A[cc.stationLogin] --> B[Validate input]
|
|
66
|
+
B --> C[services.agent.stationLogin]
|
|
67
|
+
C --> D[AqmReqs.req]
|
|
68
|
+
D --> E[HTTP REST request to backend]
|
|
69
|
+
E --> F[Backend processes]
|
|
70
|
+
F --> G{Success?}
|
|
71
|
+
G -->|Yes| H[StationLoginSuccess event]
|
|
72
|
+
G -->|No| I[StationLoginFailed event]
|
|
73
|
+
H --> J[Register WebCalling if BROWSER]
|
|
74
|
+
J --> K[Track metrics]
|
|
75
|
+
K --> L[Return response]
|
|
76
|
+
I --> M[getErrorDetails]
|
|
77
|
+
M --> N[Throw error]
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Sequence Diagrams
|
|
83
|
+
|
|
84
|
+
### Station Login
|
|
85
|
+
|
|
86
|
+
```mermaid
|
|
87
|
+
sequenceDiagram
|
|
88
|
+
participant App
|
|
89
|
+
participant CC as ContactCenter
|
|
90
|
+
participant Svc as Services.agent
|
|
91
|
+
participant AQM as AqmReqs
|
|
92
|
+
participant WS as WebSocket
|
|
93
|
+
participant BE as Backend
|
|
94
|
+
App->>CC: stationLogin(params)
|
|
95
|
+
CC->>CC: Validate dial number
|
|
96
|
+
CC->>CC: timeEvent(LOGIN_SUCCESS, LOGIN_FAILED)
|
|
97
|
+
CC->>Svc: stationLogin({data})
|
|
98
|
+
Svc->>AQM: req(config)
|
|
99
|
+
AQM->>BE: HTTP POST /v1/agents/login
|
|
100
|
+
BE-->>WS: AgentStationLoginSuccess
|
|
101
|
+
WS-->>AQM: Resolve with response
|
|
102
|
+
AQM-->>Svc: Return response
|
|
103
|
+
Svc-->>CC: Login response
|
|
104
|
+
CC->>CC: Register WebCalling (if BROWSER)
|
|
105
|
+
CC->>CC: trackEvent(LOGIN_SUCCESS)
|
|
106
|
+
CC-->>App: StationLoginResponse
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### State Change
|
|
110
|
+
|
|
111
|
+
```mermaid
|
|
112
|
+
sequenceDiagram
|
|
113
|
+
participant App
|
|
114
|
+
participant CC as ContactCenter
|
|
115
|
+
participant Svc as Services.agent
|
|
116
|
+
participant WS as WebSocket
|
|
117
|
+
participant BE as Backend
|
|
118
|
+
|
|
119
|
+
App->>CC: setAgentState(params)
|
|
120
|
+
CC->>CC: timeEvent(STATE_SUCCESS, STATE_FAILED)
|
|
121
|
+
CC->>Svc: stateChange({data})
|
|
122
|
+
Svc->>BE: HTTP PUT /v1/agents/session/state
|
|
123
|
+
BE-->>WS: AgentStateChangeSuccess
|
|
124
|
+
WS-->>CC: Emit via handleWebsocketMessage
|
|
125
|
+
CC->>CC: emit(agent:stateChange)
|
|
126
|
+
CC->>CC: trackEvent(STATE_SUCCESS)
|
|
127
|
+
CC-->>App: SetStateResponse
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Request Configuration
|
|
133
|
+
|
|
134
|
+
Each agent method defines:
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
{
|
|
138
|
+
url: '/v1/agents/...', // API endpoint
|
|
139
|
+
host: WCC_API_GATEWAY, // Base URL
|
|
140
|
+
data: p.data, // Request payload
|
|
141
|
+
method: HTTP_METHODS.POST, // HTTP method (POST if data present, GET otherwise)
|
|
142
|
+
err: errorHandler, // Error transformer
|
|
143
|
+
notifSuccess: {
|
|
144
|
+
bind: {
|
|
145
|
+
type: CC_EVENTS.SUCCESS_TYPE,
|
|
146
|
+
data: {type: CC_EVENTS.SUCCESS_TYPE},
|
|
147
|
+
},
|
|
148
|
+
msg: {} as SuccessType, // Response type hint
|
|
149
|
+
},
|
|
150
|
+
notifFail: {
|
|
151
|
+
bind: {
|
|
152
|
+
type: CC_EVENTS.FAIL_TYPE,
|
|
153
|
+
data: {type: CC_EVENTS.FAIL_TYPE},
|
|
154
|
+
},
|
|
155
|
+
errId: 'Service.aqm.agent.method',
|
|
156
|
+
},
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Event Flow
|
|
163
|
+
|
|
164
|
+
### WebSocket to Application
|
|
165
|
+
|
|
166
|
+
```mermaid
|
|
167
|
+
flowchart LR
|
|
168
|
+
A[WebSocket Message] --> B[WebSocketManager]
|
|
169
|
+
B --> C[cc.handleWebsocketMessage]
|
|
170
|
+
C --> D{Event Type?}
|
|
171
|
+
D -->|AGENT_STATE_CHANGE| E[emit agent:stateChange]
|
|
172
|
+
D -->|data.type check| F{Nested Type?}
|
|
173
|
+
F -->|STATION_LOGIN_SUCCESS| G[Transform channelsMap]
|
|
174
|
+
G --> H[emit agent:stationLoginSuccess]
|
|
175
|
+
F -->|LOGOUT_SUCCESS| I[emit agent:logoutSuccess]
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### ChannelsMap Transformation
|
|
179
|
+
|
|
180
|
+
The login success event transforms `channelsMap` to `mmProfile`:
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
// Incoming
|
|
184
|
+
channelsMap: {
|
|
185
|
+
chat: ['channel-1', 'channel-2'],
|
|
186
|
+
email: ['channel-3'],
|
|
187
|
+
telephony: ['channel-4'],
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Transformed
|
|
191
|
+
mmProfile: {
|
|
192
|
+
chat: 2, // Length of arrays
|
|
193
|
+
email: 1,
|
|
194
|
+
social: 0,
|
|
195
|
+
telephony: 1,
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Silent Relogin
|
|
202
|
+
|
|
203
|
+
Automatic relogin on WebSocket reconnection:
|
|
204
|
+
|
|
205
|
+
```mermaid
|
|
206
|
+
flowchart TD
|
|
207
|
+
A[WebSocket Reconnected] --> B[handleConnectionLost]
|
|
208
|
+
B --> C{allowAutomatedRelogin?}
|
|
209
|
+
C -->|Yes| D[silentRelogin]
|
|
210
|
+
D --> E[services.agent.reload]
|
|
211
|
+
E --> F{Success?}
|
|
212
|
+
F -->|Yes| G[Update agentConfig]
|
|
213
|
+
G --> H{lastStateChangeReason?}
|
|
214
|
+
H -->|agent-wss-disconnect| I[setAgentState Available]
|
|
215
|
+
H -->|Other| J[Keep current state]
|
|
216
|
+
F -->|No, AGENT_NOT_FOUND| K[Handle silently]
|
|
217
|
+
F -->|No, Other| L[Throw error]
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Error Handling
|
|
223
|
+
|
|
224
|
+
### Login Error Details
|
|
225
|
+
|
|
226
|
+
For `stationLogin`, special error handling extracts field-specific messages:
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
// Utils.ts - getStationLoginErrorData
|
|
230
|
+
const errorCodeMessageMap = {
|
|
231
|
+
DUPLICATE_LOCATION: {
|
|
232
|
+
message: 'This extension is already in use',
|
|
233
|
+
fieldName: loginOption,
|
|
234
|
+
},
|
|
235
|
+
INVALID_DIAL_NUMBER: {
|
|
236
|
+
message: 'Enter a valid US dial number...',
|
|
237
|
+
fieldName: loginOption,
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Metrics Tracking
|
|
245
|
+
|
|
246
|
+
| Metric | Type | When Tracked |
|
|
247
|
+
| ---------------------------- | --------------------------------- | ------------------------ |
|
|
248
|
+
| `STATION_LOGIN_SUCCESS` | behavioral, business, operational | Login succeeds |
|
|
249
|
+
| `STATION_LOGIN_FAILED` | behavioral, business, operational | Login fails |
|
|
250
|
+
| `STATION_LOGOUT_SUCCESS` | behavioral, business, operational | Logout succeeds |
|
|
251
|
+
| `STATION_LOGOUT_FAILED` | behavioral, business, operational | Logout fails |
|
|
252
|
+
| `AGENT_STATE_CHANGE_SUCCESS` | behavioral, business, operational | State change succeeds |
|
|
253
|
+
| `AGENT_STATE_CHANGE_FAILED` | behavioral, business, operational | State change fails |
|
|
254
|
+
| `FETCH_BUDDY_AGENTS_SUCCESS` | operational | Buddy agents fetched |
|
|
255
|
+
| `FETCH_BUDDY_AGENTS_FAILED` | operational | Buddy agents fetch fails |
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Troubleshooting
|
|
260
|
+
|
|
261
|
+
### Issue: Login fails with DUPLICATE_LOCATION
|
|
262
|
+
|
|
263
|
+
**Cause**: Extension/DN already in use by another session
|
|
264
|
+
|
|
265
|
+
**Solution**:
|
|
266
|
+
|
|
267
|
+
1. Logout from other session
|
|
268
|
+
2. Use different extension
|
|
269
|
+
3. Contact admin if stuck
|
|
270
|
+
|
|
271
|
+
### Issue: State change fails
|
|
272
|
+
|
|
273
|
+
**Cause**: Agent may be in a call or transitioning state
|
|
274
|
+
|
|
275
|
+
**Solution**:
|
|
276
|
+
1. Complete current interaction
|
|
277
|
+
2. Wait for state to stabilize
|
|
278
|
+
3. Retry state change
|
|
279
|
+
|
|
280
|
+
### Issue: Silent relogin not working
|
|
281
|
+
|
|
282
|
+
**Cause**: `allowAutomatedRelogin` config not set
|
|
283
|
+
|
|
284
|
+
**Solution**:
|
|
285
|
+
```typescript
|
|
286
|
+
const webex = Webex.init({
|
|
287
|
+
config: {
|
|
288
|
+
cc: {
|
|
289
|
+
allowAutomatedRelogin: true,
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
});
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Related Files
|
|
298
|
+
|
|
299
|
+
- [cc.ts](../../../cc.ts) - Main plugin
|
|
300
|
+
- [agent/index.ts](../index.ts) - Service implementation
|
|
301
|
+
- [agent/types.ts](../types.ts) - Type definitions
|
|
302
|
+
- [cc.ts test](../../../../test/unit/spec/cc.ts) - Test file
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
# Services Layer - AI Agent Guide
|
|
2
|
+
|
|
3
|
+
> **Scope Authority**: This is the authoritative documentation for the **Services** orchestration layer. It describes how all service modules are composed, instantiated, and how they interact. For task routing, critical rules, and code generation workflows, see the [root orchestrator AGENTS.md](../../../AGENTS.md).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Purpose
|
|
8
|
+
|
|
9
|
+
The `src/services/` directory is the service layer of the `@webex/contact-center` SDK. It sits between the public plugin class (`cc.ts`) and the backend APIs/WebSocket. Every backend interaction — HTTP requests, WebSocket messages, agent operations, task lifecycle, configuration fetching — flows through this layer.
|
|
10
|
+
|
|
11
|
+
### Scenarios this document resolves
|
|
12
|
+
|
|
13
|
+
- Understanding service composition and which service owns which responsibility
|
|
14
|
+
- Determining the correct instantiation/bootstrap order for services
|
|
15
|
+
- Tracing request flow from `cc.ts` through services to the backend
|
|
16
|
+
- Choosing between AqmReqs and direct REST patterns for a new method
|
|
17
|
+
- Adding a new data service (AddressBook/Queue/EntryPoint pattern)
|
|
18
|
+
- Adding a new AqmReqs method to agent, task, or dialer factories
|
|
19
|
+
- Routing to the correct service-level docs for task/agent/config/core changes
|
|
20
|
+
- Clarifying what the Services singleton creates vs what `cc.ts` creates
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## When to Load This Document
|
|
25
|
+
|
|
26
|
+
Load this services-layer guide when:
|
|
27
|
+
- Understanding **how services are composed** or **instantiation order**
|
|
28
|
+
- Adding a **new data service** (follow AddressBook/Queue/EntryPoint pattern)
|
|
29
|
+
- Adding a **new AqmReqs method** (follow agent/contact factory pattern)
|
|
30
|
+
- Debugging **cross-service interactions** or **bootstrap failures**
|
|
31
|
+
- Understanding the **request/response flow** (AqmReqs vs direct REST)
|
|
32
|
+
|
|
33
|
+
For implementation details within a specific service, follow the links in the [Service Routing table](#service-routing-scope-level-ai-docs).
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## File Structure
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
src/services/
|
|
41
|
+
├── index.ts # Services singleton — composes all services
|
|
42
|
+
├── constants.ts # Shared constants (gateway id, API paths, WebRTC domains/prefixes, timeout, method-name constants)
|
|
43
|
+
├── ai-docs/
|
|
44
|
+
│ └── AGENTS.md # THIS FILE — services layer orchestrator
|
|
45
|
+
│
|
|
46
|
+
├── agent/ # Agent operations service
|
|
47
|
+
│ ├── index.ts # routingAgent factory — stationLogin, stateChange, logout, buddyAgents
|
|
48
|
+
│ ├── types.ts # Agent types: StateChange, Logout, AGENT_EVENTS, LoginOption
|
|
49
|
+
│ └── ai-docs/ # Agent-specific documentation
|
|
50
|
+
│ ├── AGENTS.md
|
|
51
|
+
│ └── ARCHITECTURE.md
|
|
52
|
+
│
|
|
53
|
+
├── task/ # Task management service
|
|
54
|
+
│ ├── TaskManager.ts # Task lifecycle manager — creates/destroys Task instances
|
|
55
|
+
│ ├── Task.ts # Individual task — hold, transfer, conference, wrapup
|
|
56
|
+
│ ├── TaskFactory.ts # Creates Task with config flags
|
|
57
|
+
│ ├── contact.ts # routingContact factory — task operations via AqmReqs
|
|
58
|
+
│ ├── dialer.ts # aqmDialer factory — outbound dialing
|
|
59
|
+
│ ├── AutoWrapup.ts # Auto wrapup timer handler
|
|
60
|
+
│ ├── TaskUtils.ts # Task utility functions
|
|
61
|
+
│ ├── taskDataNormalizer.ts # Normalizes task data from events
|
|
62
|
+
│ ├── types.ts # Task types: ITask, TASK_EVENTS, TaskResponse
|
|
63
|
+
│ ├── constants.ts # Task constants
|
|
64
|
+
│ ├── voice/ # Voice-specific task handling
|
|
65
|
+
│ │ ├── Voice.ts # Voice task operations
|
|
66
|
+
│ │ └── WebRTC.ts # WebRTC-specific voice operations
|
|
67
|
+
│ ├── digital/ # Digital channel task handling
|
|
68
|
+
│ │ └── Digital.ts # Digital task operations
|
|
69
|
+
│ ├── state-machine/ # XState-based task state machine
|
|
70
|
+
│ │ ├── TaskStateMachine.ts # State machine definition
|
|
71
|
+
│ │ ├── index.ts # Barrel export for state machine public API
|
|
72
|
+
│ │ ├── constants.ts # TaskState, TaskEvent enums
|
|
73
|
+
│ │ ├── types.ts # TaskContext type
|
|
74
|
+
│ │ ├── guards.ts # State transition guards
|
|
75
|
+
│ │ ├── actions.ts # State transition actions
|
|
76
|
+
│ │ ├── uiControlsComputer.ts # Computes UI controls from state
|
|
77
|
+
│ │ └── ai-docs/ # State machine documentation
|
|
78
|
+
│ │ ├── AGENTS.md
|
|
79
|
+
│ │ └── ARCHITECTURE.md
|
|
80
|
+
│ └── ai-docs/ # Task-specific documentation
|
|
81
|
+
│ ├── AGENTS.md
|
|
82
|
+
│ └── ARCHITECTURE.md
|
|
83
|
+
│
|
|
84
|
+
├── config/ # Configuration service
|
|
85
|
+
│ ├── index.ts # AgentConfigService — getAgentConfig(), profile aggregation
|
|
86
|
+
│ ├── Util.ts # parseAgentConfigs, getFilterAuxCodes, helper functions
|
|
87
|
+
│ ├── types.ts # CC_EVENTS, Profile, CC_AGENT_EVENTS, CC_TASK_EVENTS
|
|
88
|
+
│ ├── constants.ts # endPointMap (API URL builders), pagination defaults
|
|
89
|
+
│ └── ai-docs/ # Config-specific documentation
|
|
90
|
+
│ ├── AGENTS.md
|
|
91
|
+
│ └── ARCHITECTURE.md
|
|
92
|
+
│
|
|
93
|
+
├── core/ # Core infrastructure
|
|
94
|
+
│ ├── WebexRequest.ts # HTTP client singleton — request(), uploadLogs()
|
|
95
|
+
│ ├── aqm-reqs.ts # AqmReqs — HTTP request + WebSocket notification correlation
|
|
96
|
+
│ ├── Utils.ts # getErrorDetails, generateTaskErrorObject, isValidDialNumber
|
|
97
|
+
│ ├── Err.ts # Err.Details error class with structured metadata
|
|
98
|
+
│ ├── GlobalTypes.ts # Msg<T>, Failure, AugmentedError, TaskError
|
|
99
|
+
│ ├── types.ts # Req, Conf, Res types for AqmReqs
|
|
100
|
+
│ ├── constants.ts # Core constants
|
|
101
|
+
│ ├── websocket/
|
|
102
|
+
│ │ ├── WebSocketManager.ts # WebSocket connection handler
|
|
103
|
+
│ │ ├── connection-service.ts # Connection lifecycle, reconnection, keepalive
|
|
104
|
+
│ │ └── types.ts # WebSocket types
|
|
105
|
+
│ └── ai-docs/ # Core-specific documentation
|
|
106
|
+
│ ├── AGENTS.md
|
|
107
|
+
│ └── ARCHITECTURE.md
|
|
108
|
+
│
|
|
109
|
+
├── AddressBook.ts # Address book entries — getEntries() with pagination/cache
|
|
110
|
+
├── EntryPoint.ts # Entry points — getEntryPoints() with pagination/cache
|
|
111
|
+
├── Queue.ts # Queues — getQueues() with pagination/cache
|
|
112
|
+
└── WebCallingService.ts # WebRTC calling — register/deregister line, answer/mute/decline
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Note: The `src/utils/` folder (sibling to `src/services/`) contains shared utilities like [`PageCache.ts`](../../utils/PageCache.ts) which provides generic pagination caching with `BaseSearchParams`, `PaginatedResponse`, and `PaginationMeta` types used by all data services.
|
|
116
|
+
|
|
117
|
+
### Shared Constants (`src/services/constants.ts`)
|
|
118
|
+
|
|
119
|
+
Use [`constants.ts`](../constants.ts) as the canonical source for service-level naming and routing constants:
|
|
120
|
+
- `WCC_API_GATEWAY` — service identifier used by `WebexRequest` calls
|
|
121
|
+
- `SUBSCRIBE_API`, `LOGIN_API`, `STATE_CHANGE_API` — common API path constants
|
|
122
|
+
- `WEB_RTC_PREFIX` — path prefix for WebRTC-related endpoints
|
|
123
|
+
- `WEBSOCKET_EVENT_TIMEOUT` — default notification correlation timeout (`20000` ms)
|
|
124
|
+
- `DEFAULT_RTMS_DOMAIN`, `WCC_CALLING_RTMS_DOMAIN` — RTMS/WebRTC domain constants
|
|
125
|
+
- `METHODS` — method name constants used by `WebCallingService`
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Key Capabilities
|
|
130
|
+
|
|
131
|
+
| Capability | Owner | Description |
|
|
132
|
+
|---|---|---|
|
|
133
|
+
| **Service Singleton** | [`index.ts`](../index.ts) | Central `Services` class that instantiates and provides access to all service modules via `Services.getInstance()` |
|
|
134
|
+
| **Agent Operations** | [`agent/`](../agent/index.ts) | Station login/logout, state changes, buddy agents — uses AqmReqs factory pattern |
|
|
135
|
+
| **Task Management** | [`task/`](../task/TaskManager.ts) | Task lifecycle (accept, hold, transfer, conference, wrapup), Task state machine, contact operations, outbound dialing |
|
|
136
|
+
| **Configuration** | [`config/`](../config/index.ts) | Agent profile aggregation from 8+ API endpoints, org settings, teams, aux codes, dial plans |
|
|
137
|
+
| **Core Infrastructure** | [`core/`](../core/WebexRequest.ts) | HTTP requests (`WebexRequest`), WebSocket management (`WebSocketManager`), connection lifecycle (`ConnectionService`), AQM request/response correlation (`AqmReqs`), error handling (`Utils`, `Err`) |
|
|
138
|
+
| **Data Services** | [`AddressBook.ts`](../AddressBook.ts), [`Queue.ts`](../Queue.ts), [`EntryPoint.ts`](../EntryPoint.ts) | Standalone REST-based data services with pagination and caching for address books, queues, and entry points |
|
|
139
|
+
| **Utilities** | [`src/utils/PageCache.ts`](../../utils/PageCache.ts) | Shared `PageCache<T>` generic class for pagination caching, plus `BaseSearchParams`, `PaginatedResponse`, and `PaginationMeta` types used by all data services |
|
|
140
|
+
| **WebRTC Calling** | [`WebCallingService.ts`](../WebCallingService.ts) | Browser-based voice calling via `@webex/calling`, line registration, call answer/mute/decline |
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Service Routing (Scope-Level ai-docs)
|
|
145
|
+
|
|
146
|
+
Each service folder contains its own `ai-docs/` with detailed documentation. **Always load the relevant service docs before making changes.**
|
|
147
|
+
|
|
148
|
+
| Service | Scope / Keywords | AGENTS.md | ARCHITECTURE.md |
|
|
149
|
+
|---------|-----------------|-----------|-----------------|
|
|
150
|
+
| **Agent** | login, logout, state change, buddy agents, station, RONA | [`agent/ai-docs/AGENTS.md`](../agent/ai-docs/AGENTS.md) | [`agent/ai-docs/ARCHITECTURE.md`](../agent/ai-docs/ARCHITECTURE.md) |
|
|
151
|
+
| **Task** | task, hold, transfer, conference, wrapup, outdial, consult, accept, decline, state machine, XState, task states, guards, actions | [`task/ai-docs/AGENTS.md`](../task/ai-docs/AGENTS.md) | [`task/ai-docs/ARCHITECTURE.md`](../task/ai-docs/ARCHITECTURE.md) |
|
|
152
|
+
| **Config** | profile, register, teams, aux codes, desktop profile, org settings, dial plan | [`config/ai-docs/AGENTS.md`](../config/ai-docs/AGENTS.md) | [`config/ai-docs/ARCHITECTURE.md`](../config/ai-docs/ARCHITECTURE.md) |
|
|
153
|
+
| **Core** | websocket, HTTP, connection, reconnect, aqm, utils, errors, keepalive | [`core/ai-docs/AGENTS.md`](../core/ai-docs/AGENTS.md) | [`core/ai-docs/ARCHITECTURE.md`](../core/ai-docs/ARCHITECTURE.md) |
|
|
154
|
+
|
|
155
|
+
> **Note**: The task state machine (`task/state-machine/`) is part of the Task service, not a separate service. Its dedicated docs live at [`task/state-machine/ai-docs/AGENTS.md`](../task/state-machine/ai-docs/AGENTS.md) and [`ARCHITECTURE.md`](../task/state-machine/ai-docs/ARCHITECTURE.md). Load these when working on state transitions, guards, or actions.
|
|
156
|
+
|
|
157
|
+
**Data services** (AddressBook, Queue, EntryPoint) do not have dedicated ai-docs. Read their source files directly — they follow shared REST/pagination/caching patterns documented in [`ai-docs/patterns/typescript-patterns.md`](../../../ai-docs/patterns/typescript-patterns.md).
|
|
158
|
+
|
|
159
|
+
**WebCallingService** also has no dedicated ai-docs, but it follows a different pattern: EventEmitter-based call lifecycle orchestration around `@webex/calling` (`createClient`, line registration/deregistration, `ICall` events), `callTaskMap` tracking, and async registration flows with timeout handling. Read [`WebCallingService.ts`](../WebCallingService.ts) directly when changing browser calling behavior.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Architecture Overview
|
|
164
|
+
|
|
165
|
+
### How cc.ts Uses the Services Layer
|
|
166
|
+
|
|
167
|
+
The `ContactCenter` plugin class (`cc.ts`) is the **only public entry point**. It delegates all backend work to the services layer:
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
ContactCenter (cc.ts) — public API surface
|
|
171
|
+
│
|
|
172
|
+
├── WebexRequest.getInstance({webex}) ← initialized FIRST (singleton)
|
|
173
|
+
├── Services.getInstance({webex, connectionConfig}) ← initialized SECOND (singleton)
|
|
174
|
+
│ │
|
|
175
|
+
│ ├── WebSocketManager ← real-time message transport
|
|
176
|
+
│ ├── AqmReqs ← HTTP request + WebSocket notification correlation
|
|
177
|
+
│ ├── ConnectionService ← WebSocket lifecycle, reconnection, keepalive
|
|
178
|
+
│ ├── AgentConfigService (config) ← profile aggregation via REST APIs
|
|
179
|
+
│ ├── routingAgent (agent) ← agent operations via AqmReqs factory
|
|
180
|
+
│ ├── routingContact (contact) ← task/contact operations via AqmReqs factory
|
|
181
|
+
│ └── aqmDialer (dialer) ← outbound dialing via AqmReqs factory
|
|
182
|
+
│
|
|
183
|
+
├── TaskManager ← task lifecycle, created during register()
|
|
184
|
+
├── WebCallingService ← WebRTC calling, created during register() (line registration is conditional)
|
|
185
|
+
├── AddressBook ← REST data service, created during register()
|
|
186
|
+
├── EntryPoint ← REST data service, created during register()
|
|
187
|
+
├── Queue ← REST data service, created during register()
|
|
188
|
+
└── MetricsManager.getInstance({webex}) ← telemetry singleton
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Bootstrap Order (Critical)
|
|
192
|
+
|
|
193
|
+
Understanding the instantiation order is essential — getting it wrong causes runtime errors:
|
|
194
|
+
|
|
195
|
+
1. **`WebexRequest.getInstance({webex})`** — Must be called first. The singleton HTTP client that all services depend on.
|
|
196
|
+
2. **`Services.getInstance({webex, connectionConfig})`** — Creates `WebSocketManager`, `AqmReqs`, `ConnectionService`, `AgentConfigService`, `routingAgent`, `routingContact`, `aqmDialer`.
|
|
197
|
+
3. **`WebCallingService`** — Created during `register()` for calling lifecycle management. `registerWebCallingLine()` is later invoked conditionally for `loginOption === 'BROWSER'`.
|
|
198
|
+
4. **`MetricsManager.getInstance({webex})`** — Telemetry singleton.
|
|
199
|
+
5. **`TaskManager`** — Created during `register()` and wired to services/WebSocket.
|
|
200
|
+
6. **Data services** (`AddressBook`, `EntryPoint`, `Queue`) — Created during `register()`.
|
|
201
|
+
|
|
202
|
+
### Request/Response Flow Pattern
|
|
203
|
+
|
|
204
|
+
There are two distinct patterns used across services:
|
|
205
|
+
|
|
206
|
+
#### Pattern 1: AqmReqs (Agent + Task operations)
|
|
207
|
+
|
|
208
|
+
Used by `routingAgent`, `routingContact`, and `aqmDialer`. This pattern sends an HTTP REST request to the backend and waits for a correlated WebSocket notification:
|
|
209
|
+
|
|
210
|
+
```
|
|
211
|
+
cc.ts method call
|
|
212
|
+
→ services.agent.methodName({data}) (or services.contact / services.dialer)
|
|
213
|
+
→ AqmReqs.req() sends HTTP request (via WebexRequest.request())
|
|
214
|
+
→ Backend REST API processes
|
|
215
|
+
→ Backend sends WebSocket notification (success or failure)
|
|
216
|
+
→ AqmReqs correlates notification to pending request
|
|
217
|
+
→ Promise resolves/rejects
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Key detail: **The HTTP request goes directly to the backend. The WebSocket only carries the notification back.** This is NOT request-over-WebSocket.
|
|
221
|
+
|
|
222
|
+
#### Pattern 2: Direct REST (Config + Data services)
|
|
223
|
+
|
|
224
|
+
Used by `AgentConfigService`, `AddressBook`, `Queue`, `EntryPoint`. These make direct HTTP calls and return the response:
|
|
225
|
+
|
|
226
|
+
```
|
|
227
|
+
cc.ts method call
|
|
228
|
+
→ service.method()
|
|
229
|
+
→ WebexRequest.request({service, resource, method})
|
|
230
|
+
→ Backend REST API
|
|
231
|
+
→ Response returned directly
|
|
232
|
+
→ Promise resolves/rejects
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Services Singleton (index.ts)
|
|
238
|
+
|
|
239
|
+
The `Services` class is the central composition root. It uses a singleton pattern:
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
const services = Services.getInstance({
|
|
243
|
+
webex: this.$webex,
|
|
244
|
+
connectionConfig: subscribeRequest,
|
|
245
|
+
});
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### What Services creates in its constructor
|
|
249
|
+
|
|
250
|
+
| Component | How Created | Purpose |
|
|
251
|
+
|---|---|---|
|
|
252
|
+
| `webSocketManager` | `new WebSocketManager({webex})` | WebSocket transport for real-time messages |
|
|
253
|
+
| `aqmReq` (internal) | `new AqmReqs(webSocketManager)` | Correlates HTTP requests with WebSocket notifications |
|
|
254
|
+
| `config` | `new AgentConfigService()` | REST-based profile aggregation |
|
|
255
|
+
| `agent` | `routingAgent(aqmReq)` | Agent operations factory |
|
|
256
|
+
| `contact` | `routingContact(aqmReq)` | Task/contact operations factory |
|
|
257
|
+
| `dialer` | `aqmDialer(aqmReq)` | Outbound dialing factory |
|
|
258
|
+
| `connectionService` | `new ConnectionService({webSocketManager, subscribeRequest})` | WebSocket lifecycle management |
|
|
259
|
+
|
|
260
|
+
### What Services does NOT create
|
|
261
|
+
|
|
262
|
+
- `WebexRequest` — initialized by `cc.ts` before `Services.getInstance()`
|
|
263
|
+
- `TaskManager` — created by `cc.ts` during `register()`
|
|
264
|
+
- `WebCallingService` — created by `cc.ts` during `register()` (line registration is conditional on `loginOption === 'BROWSER'`)
|
|
265
|
+
- `AddressBook`, `EntryPoint`, `Queue` — created by `cc.ts` during `register()`
|
|
266
|
+
- `MetricsManager` — independent singleton initialized by `cc.ts`
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## Data Services Pattern (AddressBook, Queue, EntryPoint)
|
|
271
|
+
|
|
272
|
+
These three services share an identical pattern. Use any one as a reference when creating similar services:
|
|
273
|
+
|
|
274
|
+
| Aspect | Pattern |
|
|
275
|
+
|---|---|
|
|
276
|
+
| **Class structure** | Standalone class with `WebexRequest`, `WebexSDK`, `MetricsManager`, `PageCache` |
|
|
277
|
+
| **Constructor** | `constructor(webex: WebexSDK)` — gets singletons via `.getInstance()` |
|
|
278
|
+
| **HTTP calls** | `this.webexRequest.request({service: WCC_API_GATEWAY, resource, method: HTTP_METHODS.GET})` |
|
|
279
|
+
| **Endpoints** | Uses `endPointMap` functions from `config/constants.ts` to build URL paths |
|
|
280
|
+
| **Pagination** | Query params with `page`, `pageSize`; uses `PageCache` for caching |
|
|
281
|
+
| **Caching** | `PageCache<T>` — caches pages for simple pagination, bypasses cache for search/filter |
|
|
282
|
+
| **Metrics** | `timeEvent` on API call start, `trackEvent` on success/failure |
|
|
283
|
+
| **Logging** | `LoggerProxy` with `{module: 'ClassName', method: 'methodName'}` context |
|
|
284
|
+
| **Error handling** | try/catch with `LoggerProxy.error` + `metricsManager.trackEvent` for failures, then re-throw so callers receive the error |
|
|
285
|
+
|
|
286
|
+
Reference files:
|
|
287
|
+
- [`AddressBook.ts`](../AddressBook.ts) — includes `addressBookId` parameter
|
|
288
|
+
- [`Queue.ts`](../Queue.ts) — includes additional query params (sortBy, sortOrder, etc.)
|
|
289
|
+
- [`EntryPoint.ts`](../EntryPoint.ts) — simplest example
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
## AqmReqs Factory Pattern (Agent + Task operations)
|
|
294
|
+
|
|
295
|
+
Agent and task operations use a factory pattern where each method is defined as a `routing.req()` call:
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
export default function routingAgent(routing: AqmReqs) {
|
|
299
|
+
return {
|
|
300
|
+
stationLogin: routing.req((p: {data: LoginPayload}) => ({
|
|
301
|
+
url: '/v1/agents/login',
|
|
302
|
+
host: WCC_API_GATEWAY,
|
|
303
|
+
data: p.data,
|
|
304
|
+
err: createErrDetailsObject,
|
|
305
|
+
notifSuccess: { bind: {...}, msg: {} as SuccessType },
|
|
306
|
+
notifFail: { bind: {...}, errId: 'Service.aqm.agent.stationLogin' },
|
|
307
|
+
})),
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Key points:
|
|
313
|
+
- `url` + `host` define the HTTP endpoint
|
|
314
|
+
- `data` is the request body (POST by default, GET if no data)
|
|
315
|
+
- `notifSuccess.bind` specifies which WebSocket event type indicates success
|
|
316
|
+
- `notifFail.bind` specifies which WebSocket event type indicates failure
|
|
317
|
+
- `errId` maps to an `Err.Details` error identifier
|
|
318
|
+
- The returned function is a `Promise` that resolves when the correlated WebSocket notification arrives
|
|
319
|
+
|
|
320
|
+
Reference files:
|
|
321
|
+
- [`agent/index.ts`](../agent/index.ts) — agent operations
|
|
322
|
+
- [`task/contact.ts`](../task/contact.ts) — task operations
|
|
323
|
+
- [`task/dialer.ts`](../task/dialer.ts) — outbound dialing
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Cross-Service Dependencies
|
|
328
|
+
|
|
329
|
+
```
|
|
330
|
+
cc.ts
|
|
331
|
+
├─ uses → Services.agent (stationLogin, stateChange, logout, buddyAgents)
|
|
332
|
+
├─ uses → Services.config (getAgentConfig)
|
|
333
|
+
├─ uses → Services.contact (task operations, forwarded through TaskManager/Task)
|
|
334
|
+
├─ uses → Services.dialer (startOutdial)
|
|
335
|
+
├─ uses → Services.webSocketManager (message listener for event routing)
|
|
336
|
+
├─ uses → Services.connectionService (connection lifecycle events)
|
|
337
|
+
├─ uses → WebexRequest (uploadLogs)
|
|
338
|
+
├─ uses → TaskManager (task lifecycle, created during register())
|
|
339
|
+
├─ uses → WebCallingService (WebRTC, created during register(); line registration is conditional on BROWSER login)
|
|
340
|
+
├─ uses → AddressBook (address book queries)
|
|
341
|
+
├─ uses → EntryPoint (entry point queries)
|
|
342
|
+
└─ uses → Queue (queue queries)
|
|
343
|
+
|
|
344
|
+
TaskManager
|
|
345
|
+
├─ uses → Services.contact (task operations via AqmReqs)
|
|
346
|
+
├─ uses → Services.dialer (outbound dialing)
|
|
347
|
+
├─ uses → Services.config (config flags)
|
|
348
|
+
└─ creates → Task instances (each with its own state machine)
|
|
349
|
+
|
|
350
|
+
AgentConfigService (config)
|
|
351
|
+
└─ uses → WebexRequest (direct REST calls for profile data)
|
|
352
|
+
|
|
353
|
+
AqmReqs
|
|
354
|
+
├─ uses → WebexRequest (sends HTTP requests)
|
|
355
|
+
└─ uses → WebSocketManager (listens for correlated notifications)
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## Event Flow Through Services
|
|
361
|
+
|
|
362
|
+
WebSocket messages are fanned out to multiple independent listeners on `WebSocketManager`:
|
|
363
|
+
|
|
364
|
+
```
|
|
365
|
+
CC Backend
|
|
366
|
+
→ WebSocket message arrives at WebSocketManager
|
|
367
|
+
→ WebSocketManager emits 'message'
|
|
368
|
+
→ AqmReqs listener (`aqm-reqs.ts`) — correlates pending request notifications
|
|
369
|
+
→ cc.ts listener (`cc.ts`) — handles plugin-level events:
|
|
370
|
+
→ Agent events use `this.emit(...)` (EventEmitter API)
|
|
371
|
+
→ Task notifications use `this.trigger(...)` (WebexPlugin API)
|
|
372
|
+
→ TaskManager listener (`TaskManager.ts`) — processes task events for task lifecycle/state
|
|
373
|
+
→ ConnectionService listener (`connection-service.ts`) — processes connection/keepalive events
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
378
|
+
## Related
|
|
379
|
+
|
|
380
|
+
- [Root orchestrator AGENTS.md](../../../AGENTS.md) — task classification, critical rules, templates
|
|
381
|
+
- [ai-docs/RULES.md](../../../ai-docs/RULES.md) — coding standards
|
|
382
|
+
- [ai-docs/patterns/](../../../ai-docs/patterns/) — TypeScript, testing, and event patterns
|
|
383
|
+
- [types.ts](../../types.ts) — public type definitions
|
|
384
|
+
- [cc.ts](../../cc.ts) — main plugin class (public API surface)
|