@webex/contact-center 3.12.0-next.84 → 3.12.0-next.85
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/.sdd/manifest.json +876 -0
- package/AGENTS.md +65 -409
- package/ai-docs/ARCHITECTURE.md +168 -0
- package/ai-docs/CONTRACTS.md +46 -0
- package/ai-docs/GETTING_STARTED.md +168 -0
- package/ai-docs/GLOSSARY.md +43 -0
- package/ai-docs/README.md +25 -18
- package/ai-docs/REVIEW_CHECKLIST.md +41 -0
- package/ai-docs/RULES.md +187 -198
- package/ai-docs/SECURITY.md +52 -0
- package/ai-docs/SERVICE_STATE.md +48 -0
- package/ai-docs/SPEC_INDEX.md +65 -0
- package/ai-docs/adr/0001-spec-source-policy.md +55 -0
- package/ai-docs/adr/README.md +8 -0
- package/ai-docs/adr/_adr-template.md +31 -0
- package/ai-docs/contact-center-spec.md +341 -0
- package/ai-docs/features/generated-spec-conformance-fidelity-remediation/spec/feature-spec.md +117 -0
- package/ai-docs/features/residual-warning-coverage-completion/spec/feature-spec.md +203 -0
- package/ai-docs/features/validator-code-fidelity-drift-fix/spec/feature-spec.md +315 -0
- package/ai-docs/templates/README.md +1 -1
- package/ai-docs/templates/new-method/04-validation.md +1 -1
- package/ai-docs/templates/new-service/05-validation.md +1 -1
- package/dist/webex.js +1 -1
- package/package.json +1 -1
- package/src/metrics/ai-docs/AGENTS.md +2 -0
- package/src/metrics/ai-docs/ARCHITECTURE.md +2 -0
- package/src/metrics/ai-docs/metrics-spec.md +854 -0
- package/src/services/agent/ai-docs/AGENTS.md +3 -1
- package/src/services/agent/ai-docs/ARCHITECTURE.md +2 -0
- package/src/services/agent/ai-docs/agent-spec.md +504 -0
- package/src/services/ai-docs/AGENTS.md +4 -2
- package/src/services/ai-docs/services-spec.md +492 -0
- package/src/services/config/ai-docs/AGENTS.md +3 -1
- package/src/services/config/ai-docs/ARCHITECTURE.md +2 -0
- package/src/services/config/ai-docs/config-spec.md +669 -0
- package/src/services/core/ai-docs/AGENTS.md +4 -2
- package/src/services/core/ai-docs/ARCHITECTURE.md +2 -0
- package/src/services/core/ai-docs/core-spec.md +783 -0
- package/src/services/task/ai-docs/AGENTS.md +2 -0
- package/src/services/task/ai-docs/ARCHITECTURE.md +11 -2
- package/src/services/task/ai-docs/task-spec.md +1319 -0
- package/src/services/task/state-machine/ai-docs/AGENTS.md +38 -75
- package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +6 -4
- package/src/services/task/state-machine/ai-docs/task-state-machine-spec.md +2115 -0
- package/src/utils/AGENTS.md +3 -1
- package/src/utils/ai-docs/utils-spec.md +381 -0
- package/umd/contact-center.min.js +2 -2
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Agent Service - AI Agent Guide
|
|
2
2
|
|
|
3
|
+
> **Legacy/reference-only.** Canonical SDD: [`agent-spec.md`](agent-spec.md). Use the package [manifest](../../../../.sdd/manifest.json) and [`SPEC_INDEX.md`](../../../../ai-docs/SPEC_INDEX.md) for routing; code and tests remain the behavioral referee.
|
|
4
|
+
|
|
3
5
|
> **Purpose**: Manage agent lifecycle including login, logout, state changes, and buddy agent queries.
|
|
4
6
|
|
|
5
7
|
---
|
|
@@ -235,4 +237,4 @@ try {
|
|
|
235
237
|
|
|
236
238
|
- [ARCHITECTURE.md](ARCHITECTURE.md) - Technical deep-dive
|
|
237
239
|
- [`cc.ts`](../../../cc.ts) - Main plugin implementation
|
|
238
|
-
- [`types.ts`](../types.ts) - Type definitions
|
|
240
|
+
- [`types.ts`](../types.ts) - Type definitions
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Agent Service - Architecture
|
|
2
2
|
|
|
3
|
+
> **Legacy/reference-only.** Canonical SDD: [`agent-spec.md`](agent-spec.md). Use the package [manifest](../../../../.sdd/manifest.json) and [`SPEC_INDEX.md`](../../../../ai-docs/SPEC_INDEX.md) for routing; code and tests remain the behavioral referee.
|
|
4
|
+
|
|
3
5
|
> **Purpose**: Technical documentation for agent lifecycle operations.
|
|
4
6
|
|
|
5
7
|
---
|
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
# Agent — SPEC
|
|
2
|
+
|
|
3
|
+
> Start here → root [`AGENTS.md`](../../../../AGENTS.md) · router [`SPEC_INDEX.md`](../../../../ai-docs/SPEC_INDEX.md) · system [`ARCHITECTURE.md`](../../../../ai-docs/ARCHITECTURE.md). This is the module's canonical specification.
|
|
4
|
+
|
|
5
|
+
## Metadata
|
|
6
|
+
|
|
7
|
+
| Field | Value |
|
|
8
|
+
|---|---|
|
|
9
|
+
| Module id | `agent` |
|
|
10
|
+
| Source path(s) | `src/services/agent` |
|
|
11
|
+
| Doc kind | Module spec |
|
|
12
|
+
| Coverage score | Partial (manifest-authoritative); 15/15 required document fields present |
|
|
13
|
+
| Generated from | `module-spec` @ SDLC template library `0.2.1` |
|
|
14
|
+
| generated_by / approved_by / updated_at | Codex generator / developer-approved follow-up review remediation / 2026-07-21 |
|
|
15
|
+
| Validation status | Follow-up validation passed (independent Claude fallback, 2026-07-21); coverage remains Partial |
|
|
16
|
+
|
|
17
|
+
## Evidence Rules
|
|
18
|
+
Every requirement cites stable source and test file paths. Code/tests are the behavioral referee; routed source text supplies explicit intent and rationale. Missing or contradictory evidence blocks promotion.
|
|
19
|
+
|
|
20
|
+
## Source Material Register
|
|
21
|
+
| Source material | Scope | Decision | Detail location or disposition |
|
|
22
|
+
|---|---|---|---|
|
|
23
|
+
| Reviewed prior module guides and architecture material | overview / architecture / API / tests | used and code-checked | Content is placed by meaning throughout this specification; exact routing remains in the manifest. |
|
|
24
|
+
|
|
25
|
+
## Overview
|
|
26
|
+
Agent owns the `routingAgent(AqmReqs)` request factory for station login, station logout, agent-state change, buddy-agent lookup, and agent-session reload. ContactCenter exposes the application-facing methods/events and owns profile/device updates plus recovery policy.
|
|
27
|
+
|
|
28
|
+
The factory initiates authenticated HTTP requests and supplies `CC_EVENTS` success/failure binds to AqmReqs. Public response aliases such as `StationLoginResponse`, `StationLogoutResponse`, `BuddyAgentsResponse`, and `SetStateResponse` are package-level contracts in `src/types.ts`; routing payload/notification types remain in `src/services/agent/types.ts`.
|
|
29
|
+
|
|
30
|
+
## Purpose / Responsibility
|
|
31
|
+
Own AQM request definitions for station login/logout, state change, buddy-agent queries, and reload. Device/profile update and automated relogin orchestration belong to ContactCenter.
|
|
32
|
+
|
|
33
|
+
## Stack
|
|
34
|
+
TypeScript 5.4 AQM request factory, REST initiation, WebSocket completion events, Jest 27.
|
|
35
|
+
|
|
36
|
+
## Folder / Package Structure
|
|
37
|
+
```text
|
|
38
|
+
src/services/agent/
|
|
39
|
+
├── index.ts
|
|
40
|
+
├── types.ts
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```text
|
|
44
|
+
services/agent/
|
|
45
|
+
├── index.ts # Agent service factory
|
|
46
|
+
├── types.ts # Agent types and events
|
|
47
|
+
└── ai-docs/
|
|
48
|
+
├── AGENTS.md # Usage documentation
|
|
49
|
+
└── ARCHITECTURE.md # Preserved legacy migration source (non-canonical)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Key Files (source of truth)
|
|
53
|
+
| File | Holds |
|
|
54
|
+
|---|---|
|
|
55
|
+
| `src/services/agent/index.ts` | Authoritative Agent implementation or contract source. |
|
|
56
|
+
| `src/services/agent/types.ts` | Authoritative Agent implementation or contract source. |
|
|
57
|
+
| `src/cc.ts` | Authoritative Agent implementation or contract source. |
|
|
58
|
+
|
|
59
|
+
## Public Surface
|
|
60
|
+
| Contract | Owner | Real surface | Source |
|
|
61
|
+
|---|---|---|---|
|
|
62
|
+
| `routingAgent` | Agent | exported factory `(routing: AqmReqs) => {reload, logout, stationLogin, stateChange, buddyAgents}` | `src/services/agent/index.ts`, `src/index.ts` |
|
|
63
|
+
| ContactCenter agent methods | Contact Center | `stationLogin`, `stationLogout`, `setAgentState`, `getBuddyAgents` | `src/cc.ts`, `src/types.ts` |
|
|
64
|
+
| Profile/device update | Contact Center | `updateAgentProfile(AgentProfileUpdate)`; not a routingAgent method | `src/cc.ts`, `src/types.ts` |
|
|
65
|
+
| Automated relogin | Contact Center | private `silentRelogin()` invokes `services.agent.reload()` | `src/cc.ts` |
|
|
66
|
+
| Routing notification types | Agent | `Logout`, `StateChange`, `StationLoginSuccess`, `BuddyAgentsSuccess`, `ReloginSuccess`, and related contracts | `src/services/agent/types.ts` |
|
|
67
|
+
| Public response aliases | Package | `StationLoginResponse`, `StationLogoutResponse`, `BuddyAgentsResponse`, `SetStateResponse`, `UpdateDeviceTypeResponse` | `src/types.ts`, `src/index.ts` |
|
|
68
|
+
|
|
69
|
+
Key nested WebSocket binds use the actual outer/data constants, for example `CC_EVENTS.AGENT_STATION_LOGIN` with `data.type = CC_EVENTS.AGENT_STATION_LOGIN_SUCCESS` or `CC_EVENTS.AGENT_STATION_LOGIN_FAILED`. See root `CONTRACTS.md` for the package export index.
|
|
70
|
+
|
|
71
|
+
## Requires (dependencies)
|
|
72
|
+
- AqmReqs and WCC API gateway
|
|
73
|
+
- Correlated WebSocket success/failure notifications
|
|
74
|
+
- Registered ContactCenter profile and connection state
|
|
75
|
+
|
|
76
|
+
- Requires `cc.register()` to be called first
|
|
77
|
+
|
|
78
|
+
- Agent profile must be fetched before login
|
|
79
|
+
|
|
80
|
+
- WebRTC (BROWSER option) requires mercury connection
|
|
81
|
+
|
|
82
|
+
## Requirements
|
|
83
|
+
| ID | WHAT | WHY | Source Evidence | Test / Example Evidence | Assumptions / Gaps | Confidence |
|
|
84
|
+
|---|---|---|---|---|---|---|
|
|
85
|
+
| AGENT-R-001 | routingAgent station login/logout must use the documented WCC endpoints and settle on their nested `CC_EVENTS` success/failure notifications. | The backend operation is asynchronous and HTTP acknowledgement is not final agent state. | `src/services/agent/index.ts` | `test/unit/spec/services/agent/index.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
|
|
86
|
+
| AGENT-R-002 | State change must use PUT `/v1/agents/session/state` and preserve typed success/failure binds. | Agent availability drives routing eligibility and must not be inferred from request acknowledgement. | `src/services/agent/index.ts` | `test/unit/spec/services/agent/index.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
|
|
87
|
+
| AGENT-R-003 | Buddy-agent lookup must preserve its typed request and correlated response contract. | Consult/transfer selection depends on backend-filtered availability. | `src/services/agent/index.ts` | `test/unit/spec/services/agent/index.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
|
|
88
|
+
| AGENT-R-004 | The agent factory exposes `reload`, while ContactCenter alone decides when automated relogin is permitted. | Transport recovery lacks the profile/policy context required to mutate an agent session safely. | `src/cc.ts` | `test/unit/spec/cc.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
|
|
89
|
+
| AGENT-R-005 | Device/profile update must be documented as `ContactCenter.updateAgentProfile`, not as an agent-factory method. | Calling a non-existent `routingAgent.deviceUpdate` would fail at runtime. | `src/cc.ts` | `test/unit/spec/cc.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
|
|
90
|
+
|
|
91
|
+
## Design Overview
|
|
92
|
+
`routingAgent` is a pure AQM factory. It receives an initialized AqmReqs instance and returns five request functions: `reload`, `logout`, `stationLogin`, `stateChange`, and `buddyAgents`. Each request config declares the endpoint/payload plus exact `CC_EVENTS` notification binds.
|
|
93
|
+
|
|
94
|
+
ContactCenter validates and enriches public inputs, starts metrics, delegates to the factory, performs browser-calling work when required, and maps backend notifications to application-facing events. `updateAgentProfile()` and private `silentRelogin()` are ContactCenter methods; the latter calls `services.agent.reload()` only after package-level recovery policy permits it.
|
|
95
|
+
|
|
96
|
+
## Data Flow
|
|
97
|
+
```mermaid
|
|
98
|
+
flowchart LR
|
|
99
|
+
App[Application] --> CC[ContactCenter public method]
|
|
100
|
+
CC --> Validate[Validate/enrich profile input]
|
|
101
|
+
Validate --> Factory[routingAgent request function]
|
|
102
|
+
Factory --> AQM[AqmReqs]
|
|
103
|
+
AQM --> HTTP[Authenticated WCC HTTP]
|
|
104
|
+
HTTP --> Ack[Acknowledgement]
|
|
105
|
+
AQM --> WS[Await matching CC_EVENTS notification]
|
|
106
|
+
WS -->|success| Result[Typed result to ContactCenter]
|
|
107
|
+
WS -->|failure/timeout| Error[Structured rejection]
|
|
108
|
+
Result --> AppEvent[Return result / emit application event]
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Recovery is separate: ConnectionService emits state → ContactCenter evaluates `allowAutomatedRelogin` → ContactCenter calls private `silentRelogin()` → `services.agent.reload()` uses the agent factory.
|
|
112
|
+
|
|
113
|
+
### Station-login orchestration detail
|
|
114
|
+
|
|
115
|
+
```mermaid
|
|
116
|
+
flowchart TD
|
|
117
|
+
A[cc.stationLogin] --> B[Validate dial number for AGENT_DN]
|
|
118
|
+
B --> C[services.agent.stationLogin]
|
|
119
|
+
C --> D[AqmReqs.req]
|
|
120
|
+
D --> E[HTTP REST request to backend]
|
|
121
|
+
E --> F[Backend processes]
|
|
122
|
+
F --> G{Success?}
|
|
123
|
+
G -->|Yes| H[StationLoginSuccess event]
|
|
124
|
+
G -->|No| I[StationLoginFailed event]
|
|
125
|
+
H --> J[Register WebCalling if BROWSER]
|
|
126
|
+
J --> K[Track metrics]
|
|
127
|
+
K --> L[Return response]
|
|
128
|
+
I --> M[getErrorDetails]
|
|
129
|
+
M --> N[Throw error]
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### WebSocket-to-application event mapping
|
|
133
|
+
|
|
134
|
+
```mermaid
|
|
135
|
+
flowchart LR
|
|
136
|
+
A[WebSocket Message] --> B[WebSocketManager]
|
|
137
|
+
B --> C[cc.handleWebsocketMessage]
|
|
138
|
+
C --> D{Event Type?}
|
|
139
|
+
D -->|AGENT_STATE_CHANGE| E[emit agent:stateChange]
|
|
140
|
+
D -->|data.type check| F{Nested Type?}
|
|
141
|
+
F -->|STATION_LOGIN_SUCCESS| G[Transform channelsMap]
|
|
142
|
+
G --> H[emit agent:stationLoginSuccess]
|
|
143
|
+
F -->|LOGOUT_SUCCESS| I[emit agent:logoutSuccess]
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Silent-relogin decision flow
|
|
147
|
+
|
|
148
|
+
```mermaid
|
|
149
|
+
flowchart TD
|
|
150
|
+
A[WebSocket Reconnected] --> B[handleConnectionLost]
|
|
151
|
+
B --> C{allowAutomatedRelogin?}
|
|
152
|
+
C -->|Yes| D[silentRelogin]
|
|
153
|
+
C -->|No| M[Retain reported connection state]
|
|
154
|
+
D --> E[services.agent.reload]
|
|
155
|
+
E --> F{Success?}
|
|
156
|
+
F -->|Yes| G[Update agentConfig and device state]
|
|
157
|
+
G --> H{lastStateChangeReason?}
|
|
158
|
+
H -->|agent-wss-disconnect| I[setAgentState Available]
|
|
159
|
+
H -->|Other| J[Keep backend state]
|
|
160
|
+
F -->|No, AGENT_NOT_FOUND| K[Handle silently]
|
|
161
|
+
F -->|No, Other| L[Throw detailed error]
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Sequence Diagram(s)
|
|
165
|
+
Sequence coverage:
|
|
166
|
+
|
|
167
|
+
| Operation group | Diagram | Failure / recovery coverage |
|
|
168
|
+
|---|---|---|
|
|
169
|
+
| Station login | Station login | Validation, nested failure notification, HTTP rejection, and timeout throw. |
|
|
170
|
+
| Station logout | Station logout | Nested failure/timeout rejects and calling deregistration occurs only after success. |
|
|
171
|
+
| State change | State change | PUT failure notification/timeout returns a structured rejection. |
|
|
172
|
+
| Buddy agents | Buddy-agent lookup | Correlated retrieval failure/timeout rejects. |
|
|
173
|
+
| Reload | Recovery reload | ContactCenter gates reload; relogin failure or disabled policy preserves failure state. |
|
|
174
|
+
|
|
175
|
+
### Station login
|
|
176
|
+
|
|
177
|
+
```mermaid
|
|
178
|
+
sequenceDiagram
|
|
179
|
+
participant App
|
|
180
|
+
participant CC as ContactCenter
|
|
181
|
+
participant Svc as Services.agent
|
|
182
|
+
participant AQM as AqmReqs
|
|
183
|
+
participant WS as WebSocket
|
|
184
|
+
participant BE as Backend
|
|
185
|
+
App->>CC: stationLogin(params)
|
|
186
|
+
CC->>CC: Validate dial number
|
|
187
|
+
CC->>CC: timeEvent(LOGIN_SUCCESS, LOGIN_FAILED)
|
|
188
|
+
CC->>Svc: stationLogin({data})
|
|
189
|
+
Svc->>AQM: req(config)
|
|
190
|
+
AQM->>BE: HTTP POST /v1/agents/login
|
|
191
|
+
alt nested success
|
|
192
|
+
BE-->>WS: AgentStationLoginSuccess
|
|
193
|
+
WS-->>AQM: matching success notification
|
|
194
|
+
AQM-->>Svc: StationLoginSuccess
|
|
195
|
+
Svc-->>CC: login response
|
|
196
|
+
CC->>CC: Register WebCalling if BROWSER and enabled
|
|
197
|
+
CC->>CC: trackEvent(LOGIN_SUCCESS)
|
|
198
|
+
CC-->>App: StationLoginResponse
|
|
199
|
+
else nested failure, HTTP rejection, or timeout
|
|
200
|
+
WS-->>AQM: failure notification or no completion
|
|
201
|
+
AQM-->>CC: structured rejection
|
|
202
|
+
CC->>CC: trackEvent(LOGIN_FAILED)
|
|
203
|
+
CC-->>App: throw detailed error
|
|
204
|
+
end
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Station logout
|
|
208
|
+
|
|
209
|
+
```mermaid
|
|
210
|
+
sequenceDiagram
|
|
211
|
+
participant App
|
|
212
|
+
participant CC as ContactCenter
|
|
213
|
+
participant Agent as routingAgent
|
|
214
|
+
participant AQM as AqmReqs
|
|
215
|
+
participant WS as Primary WebSocket
|
|
216
|
+
App->>CC: stationLogout({logoutReason})
|
|
217
|
+
CC->>Agent: logout({data})
|
|
218
|
+
Agent->>AQM: POST /v1/agents/logout + nested binds
|
|
219
|
+
alt AGENT_LOGOUT_SUCCESS
|
|
220
|
+
WS-->>AQM: matching nested success
|
|
221
|
+
AQM-->>CC: LogoutSuccess
|
|
222
|
+
CC->>CC: track success; deregister WebCalling line
|
|
223
|
+
CC-->>App: StationLogoutResponse
|
|
224
|
+
else failure, HTTP rejection, or timeout
|
|
225
|
+
WS-->>AQM: matching failure or no completion
|
|
226
|
+
CC->>CC: track failure
|
|
227
|
+
CC-->>App: throw detailed error
|
|
228
|
+
end
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### State change
|
|
232
|
+
|
|
233
|
+
```mermaid
|
|
234
|
+
sequenceDiagram
|
|
235
|
+
participant App
|
|
236
|
+
participant CC as ContactCenter
|
|
237
|
+
participant Agent as routingAgent
|
|
238
|
+
participant AQM as AqmReqs
|
|
239
|
+
participant WS as Primary WebSocket
|
|
240
|
+
App->>CC: setAgentState(data)
|
|
241
|
+
CC->>Agent: stateChange({data + agentId})
|
|
242
|
+
Agent->>AQM: PUT /v1/agents/session/state + binds
|
|
243
|
+
alt AGENT_STATE_CHANGE_SUCCESS
|
|
244
|
+
WS-->>AQM: matching nested success
|
|
245
|
+
AQM-->>CC: StateChangeSuccess
|
|
246
|
+
CC-->>App: SetStateResponse
|
|
247
|
+
else failure, HTTP rejection, or timeout
|
|
248
|
+
WS-->>AQM: matching failure or no completion
|
|
249
|
+
AQM-->>CC: structured rejection
|
|
250
|
+
CC-->>App: throw detailed error
|
|
251
|
+
end
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Buddy-agent lookup
|
|
255
|
+
|
|
256
|
+
```mermaid
|
|
257
|
+
sequenceDiagram
|
|
258
|
+
participant App
|
|
259
|
+
participant CC as ContactCenter
|
|
260
|
+
participant Agent as routingAgent
|
|
261
|
+
participant AQM as AqmReqs
|
|
262
|
+
participant WS as Primary WebSocket
|
|
263
|
+
App->>CC: getBuddyAgents(query)
|
|
264
|
+
CC->>Agent: buddyAgents({data})
|
|
265
|
+
Agent->>AQM: POST /v1/agents/buddyList + binds
|
|
266
|
+
alt AGENT_BUDDY_AGENTS_SUCCESS
|
|
267
|
+
WS-->>AQM: matching nested success
|
|
268
|
+
AQM-->>App: BuddyAgentsResponse
|
|
269
|
+
else retrieve failure or timeout
|
|
270
|
+
WS-->>AQM: matching failure or no completion
|
|
271
|
+
AQM-->>App: structured rejection
|
|
272
|
+
end
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Recovery reload
|
|
276
|
+
|
|
277
|
+
```mermaid
|
|
278
|
+
sequenceDiagram
|
|
279
|
+
participant CS as ConnectionService
|
|
280
|
+
participant CC as ContactCenter
|
|
281
|
+
participant Agent as routingAgent
|
|
282
|
+
CS-->>CC: connectionLost(details)
|
|
283
|
+
alt automated relogin allowed
|
|
284
|
+
CC->>CC: silentRelogin()
|
|
285
|
+
CC->>Agent: reload()
|
|
286
|
+
Agent-->>CC: relogin result/failure
|
|
287
|
+
else not allowed
|
|
288
|
+
CC->>CC: retain reported state
|
|
289
|
+
end
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## Class / Component Relationships
|
|
293
|
+
```mermaid
|
|
294
|
+
classDiagram
|
|
295
|
+
class ContactCenter
|
|
296
|
+
class routingAgent
|
|
297
|
+
class AqmReqs
|
|
298
|
+
class WebSocketManager
|
|
299
|
+
ContactCenter --> routingAgent : public agent operations / reload
|
|
300
|
+
routingAgent --> AqmReqs : request factories
|
|
301
|
+
AqmReqs --> WebSocketManager : correlated notifications
|
|
302
|
+
ContactCenter --> ContactCenter : updateAgentProfile + silentRelogin ownership
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
## Use Cases
|
|
306
|
+
- **UC-1 Station login/logout:** validate public input in ContactCenter, initiate through routingAgent, settle from nested WebSocket notification. Evidence: `src/cc.ts`, `src/services/agent/index.ts`, `test/unit/spec/services/agent/index.ts`.
|
|
307
|
+
- **UC-2 State change:** PUT the state payload and return the correlated typed response. Evidence: `src/services/agent/index.ts`, `test/unit/spec/services/agent/index.ts`.
|
|
308
|
+
- **UC-3 Buddy-agent query:** retrieve backend-filtered candidates for consult/transfer. Evidence: `src/services/agent/index.ts`, `test/unit/spec/services/agent/index.ts`.
|
|
309
|
+
- **UC-4 Recovery reload:** ContactCenter decides whether to invoke private relogin and the factory's `reload`. Evidence: `src/cc.ts`, `test/unit/spec/cc.ts`.
|
|
310
|
+
- **UC-5 Device/profile update:** ContactCenter owns `updateAgentProfile`; the agent factory has no device-update method. Evidence: `src/cc.ts`, `test/unit/spec/cc.ts`.
|
|
311
|
+
|
|
312
|
+
## Business Rules & Invariants
|
|
313
|
+
- Agent must preserve its typed public/event contracts and must not invent backend states or responses. Enforced in `src/services/agent/index.ts`.
|
|
314
|
+
|
|
315
|
+
Change agent state (Available/Idle).
|
|
316
|
+
|
|
317
|
+
**Parameters**:
|
|
318
|
+
|
|
319
|
+
- `state` ('Available' | 'Idle'): New state
|
|
320
|
+
|
|
321
|
+
- `auxCodeId` (string): Auxiliary code ID
|
|
322
|
+
|
|
323
|
+
- `lastStateChangeReason` (string, optional): Reason for change
|
|
324
|
+
|
|
325
|
+
- `agentId` (string, optional): Agent ID (defaults to current agent)
|
|
326
|
+
|
|
327
|
+
**Returns**: `Promise<SetStateResponse>`
|
|
328
|
+
|
|
329
|
+
**Example**:
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
// Go Available
|
|
333
|
+
await cc.setAgentState({
|
|
334
|
+
state: 'Available',
|
|
335
|
+
auxCodeId: '0',
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
// Go to Idle with specific code
|
|
339
|
+
await cc.setAgentState({
|
|
340
|
+
state: 'Idle',
|
|
341
|
+
auxCodeId: 'break-code-123',
|
|
342
|
+
lastStateChangeReason: 'Coffee break',
|
|
343
|
+
});
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
The `AgentState` type (`'Available' | 'Idle' | 'RONA' | string`) is extensible -- the `string` union member allows backend-defined states beyond the known values listed below.
|
|
347
|
+
|
|
348
|
+
| State | SubStatus | Description |
|
|
349
|
+
|---|---|---|
|
|
350
|
+
| LoggedIn | Available | Ready to receive tasks |
|
|
351
|
+
| LoggedIn | Idle | On break or not ready (uses aux code for sub-reason) |
|
|
352
|
+
| RONA | - | Rang but no answer; agent failed to accept offered task |
|
|
353
|
+
| LoggedOut | - | Not logged in |
|
|
354
|
+
| LoggedIn | *(custom)* | Additional org-specific states defined via aux codes |
|
|
355
|
+
|
|
356
|
+
> **Note**: `AgentState` is a union with `string`, so consumers should handle unknown state values gracefully rather than exhaustively matching only the known literals.
|
|
357
|
+
|
|
358
|
+
## Concurrency & Reactive Flow
|
|
359
|
+
- Async operations must remain non-blocking; listener/queue/actor ordering and cleanup rules in the preserved source content are contractual.
|
|
360
|
+
|
|
361
|
+
## Protocol / Wire Format
|
|
362
|
+
- Request, response, and event payload ownership is anchored in `src/services/agent/index.ts`. HTTP initiates backend work where applicable; WebSocket messages provide realtime events and, for AQM flows, correlated completion.
|
|
363
|
+
|
|
364
|
+
For example, station login defines the real outer and nested event binds:
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
{
|
|
368
|
+
url: '/v1/agents/login',
|
|
369
|
+
host: WCC_API_GATEWAY,
|
|
370
|
+
data: p.data,
|
|
371
|
+
err: (e) => new Err.Details('Service.aqm.agent.stationLogin', {/* response fields */}),
|
|
372
|
+
notifSuccess: {
|
|
373
|
+
bind: {
|
|
374
|
+
type: CC_EVENTS.AGENT_STATION_LOGIN,
|
|
375
|
+
data: {type: CC_EVENTS.AGENT_STATION_LOGIN_SUCCESS},
|
|
376
|
+
},
|
|
377
|
+
msg: {} as Agent.StationLoginSuccess,
|
|
378
|
+
},
|
|
379
|
+
notifFail: {
|
|
380
|
+
bind: {
|
|
381
|
+
type: CC_EVENTS.AGENT_STATION_LOGIN,
|
|
382
|
+
data: {type: CC_EVENTS.AGENT_STATION_LOGIN_FAILED},
|
|
383
|
+
},
|
|
384
|
+
errId: 'Service.aqm.agent.stationLoginFailed',
|
|
385
|
+
},
|
|
386
|
+
}
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
## Error Handling & Failure Modes
|
|
390
|
+
| Condition | Signal (error/code/result) | Caller recovery |
|
|
391
|
+
|---|---|---|
|
|
392
|
+
| Dependency rejection | Typed/rethrown error or failure event | Inspect structured details, preserve tracking id, and retry only when the operation is safe. |
|
|
393
|
+
| Timeout or missing async completion | Timeout/recovery state | Follow the module-specific recovery path; never synthesize success. |
|
|
394
|
+
|
|
395
|
+
> **Host-application example:** `showStationLoginError` represents consumer-owned UI handling. SDK package implementation must use `LoggerProxy` and must not log raw runtime values.
|
|
396
|
+
|
|
397
|
+
```typescript
|
|
398
|
+
try {
|
|
399
|
+
await cc.stationLogin(params);
|
|
400
|
+
} catch (error) {
|
|
401
|
+
showStationLoginError({
|
|
402
|
+
message: error.message,
|
|
403
|
+
fieldName: error.data?.fieldName,
|
|
404
|
+
fieldMessage: error.data?.message,
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
| Reason | Description |
|
|
410
|
+
|---|---|
|
|
411
|
+
| `DUPLICATE_LOCATION` | Extension/DN already in use |
|
|
412
|
+
| `INVALID_DIAL_NUMBER` | Invalid phone number format |
|
|
413
|
+
| `AGENT_NOT_FOUND` | Agent doesn't exist (silent relogin) |
|
|
414
|
+
|
|
415
|
+
For `stationLogin`, special error handling extracts field-specific messages:
|
|
416
|
+
|
|
417
|
+
```typescript
|
|
418
|
+
// src/services/core/Utils.ts - getStationLoginErrorData
|
|
419
|
+
const errorCodeMessageMap = {
|
|
420
|
+
DUPLICATE_LOCATION: {
|
|
421
|
+
message: 'This extension is already in use',
|
|
422
|
+
fieldName: loginOption,
|
|
423
|
+
},
|
|
424
|
+
INVALID_DIAL_NUMBER: {
|
|
425
|
+
message: 'Enter a valid US dial number...',
|
|
426
|
+
fieldName: loginOption,
|
|
427
|
+
},
|
|
428
|
+
};
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
**Cause**: Extension/DN already in use by another session
|
|
432
|
+
|
|
433
|
+
**Solution**:
|
|
434
|
+
|
|
435
|
+
1. Logout from other session
|
|
436
|
+
|
|
437
|
+
2. Use different extension
|
|
438
|
+
|
|
439
|
+
3. Contact admin if stuck
|
|
440
|
+
|
|
441
|
+
**Cause**: Agent may be in a call or transitioning state
|
|
442
|
+
|
|
443
|
+
**Solution**:
|
|
444
|
+
|
|
445
|
+
1. Complete current interaction
|
|
446
|
+
|
|
447
|
+
2. Wait for state to stabilize
|
|
448
|
+
|
|
449
|
+
3. Retry state change
|
|
450
|
+
|
|
451
|
+
**Cause**: `allowAutomatedRelogin` config not set
|
|
452
|
+
|
|
453
|
+
**Solution**:
|
|
454
|
+
|
|
455
|
+
```typescript
|
|
456
|
+
const webex = Webex.init({
|
|
457
|
+
config: {
|
|
458
|
+
cc: {
|
|
459
|
+
allowAutomatedRelogin: true,
|
|
460
|
+
},
|
|
461
|
+
},
|
|
462
|
+
});
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
## Pitfalls
|
|
466
|
+
- Station login/logout and state-change binds match both the outer event type and nested `data.type`; flattening either bind can settle the wrong request.
|
|
467
|
+
- `routingAgent` has exactly five request functions and no `deviceUpdate`; profile/device changes belong to ContactCenter.
|
|
468
|
+
- ConnectionService reports transport state, but ContactCenter alone decides whether `silentRelogin()` is allowed and whether `AGENT_NOT_FOUND` is handled silently.
|
|
469
|
+
|
|
470
|
+
## Module Do's / Don'ts
|
|
471
|
+
- DO keep HTTP endpoint/method and WebSocket success/failure binds in the same routing factory definition.
|
|
472
|
+
- DO keep browser-calling registration/deregistration in ContactCenter around successful station operations.
|
|
473
|
+
- DON'T resolve an agent operation from HTTP acknowledgement.
|
|
474
|
+
- DON'T move automated relogin policy into the agent factory or ConnectionService.
|
|
475
|
+
|
|
476
|
+
## Key Design Trade-off
|
|
477
|
+
- HTTP initiates each operation while the correlated WebSocket notification is the completion signal, matching backend semantics at the cost of timeout/correlation complexity.
|
|
478
|
+
|
|
479
|
+
## Test-Case Strategy (module)
|
|
480
|
+
Use `test/unit/spec/services/agent/index.ts` for factory endpoint/bind/payload contracts and `test/unit/spec/cc.ts` for public validation, metrics, calling, updateAgentProfile, and recovery ownership. Cover success, nested failure, HTTP rejection, and timeout without inventing a `deviceUpdate` factory method.
|
|
481
|
+
|
|
482
|
+
| Behavior / Requirement | Existing test evidence | Gap |
|
|
483
|
+
|---|---|---|
|
|
484
|
+
| `AGENT-R-001` | `test/unit/spec/services/agent/index.ts`, `test/unit/spec/cc.ts` | None. |
|
|
485
|
+
| `AGENT-R-002` | `test/unit/spec/services/agent/index.ts`, `test/unit/spec/cc.ts` | None. |
|
|
486
|
+
| `AGENT-R-003` | `test/unit/spec/services/agent/index.ts` | None. |
|
|
487
|
+
| `AGENT-R-004` | `test/unit/spec/cc.ts` | None. |
|
|
488
|
+
| `AGENT-R-005` | `test/unit/spec/cc.ts` | Keep a negative assertion that `routingAgent.deviceUpdate` is absent. |
|
|
489
|
+
|
|
490
|
+
## Traceability
|
|
491
|
+
- Repo architecture: `../../../../ai-docs/ARCHITECTURE.md` · Registry: `../../../../ai-docs/SPEC_INDEX.md`
|
|
492
|
+
- Coverage state and contracts baseline: `../../../../.sdd/manifest.json`
|
|
493
|
+
|
|
494
|
+
- [`cc.ts`](../../../cc.ts) - Main plugin implementation
|
|
495
|
+
|
|
496
|
+
- [`types.ts`](../types.ts) - Type definitions
|
|
497
|
+
|
|
498
|
+
- [cc.ts](../../../cc.ts) - Main plugin
|
|
499
|
+
|
|
500
|
+
- [agent/index.ts](../index.ts) - Service implementation
|
|
501
|
+
|
|
502
|
+
- [agent/types.ts](../types.ts) - Type definitions
|
|
503
|
+
|
|
504
|
+
- [cc.ts test](../../../../test/unit/spec/cc.ts) - Test file
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Services Layer - AI Agent Guide
|
|
2
2
|
|
|
3
|
-
> **
|
|
3
|
+
> **Legacy/reference-only.** Canonical SDD: [`services-spec.md`](services-spec.md). Use the package [manifest](../../../.sdd/manifest.json) and [`SPEC_INDEX.md`](../../../ai-docs/SPEC_INDEX.md) for routing; code and tests remain the behavioral referee.
|
|
4
|
+
>
|
|
5
|
+
> **Legacy scope:** This guide describes how service modules were documented before canonical SDD routing. For repository rules, see the [root orchestrator AGENTS.md](../../../AGENTS.md).
|
|
4
6
|
|
|
5
7
|
---
|
|
6
8
|
|
|
@@ -377,7 +379,7 @@ CC Backend
|
|
|
377
379
|
|
|
378
380
|
## Related
|
|
379
381
|
|
|
380
|
-
- [Root orchestrator AGENTS.md](../../../AGENTS.md) —
|
|
382
|
+
- [Root orchestrator AGENTS.md](../../../AGENTS.md) — repository rules; use [`SPEC_INDEX.md`](../../../ai-docs/SPEC_INDEX.md) for canonical module routing
|
|
381
383
|
- [ai-docs/RULES.md](../../../ai-docs/RULES.md) — coding standards
|
|
382
384
|
- [ai-docs/patterns/](../../../ai-docs/patterns/) — TypeScript, testing, and event patterns
|
|
383
385
|
- [types.ts](../../types.ts) — public type definitions
|