@webex/contact-center 3.12.0-next.9 → 3.12.0-next.91
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 +94 -0
- 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 +138 -0
- package/ai-docs/REVIEW_CHECKLIST.md +41 -0
- package/ai-docs/RULES.md +444 -0
- 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/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 +265 -29
- package/dist/cc.js.map +1 -1
- package/dist/config.js +6 -0
- package/dist/config.js.map +1 -1
- package/dist/constants.js +17 -1
- package/dist/constants.js.map +1 -1
- package/dist/index.js +20 -5
- package/dist/index.js.map +1 -1
- package/dist/metrics/behavioral-events.js +101 -0
- package/dist/metrics/behavioral-events.js.map +1 -1
- package/dist/metrics/constants.js +25 -4
- package/dist/metrics/constants.js.map +1 -1
- package/dist/services/ApiAiAssistant.js +153 -8
- package/dist/services/ApiAiAssistant.js.map +1 -1
- package/dist/services/UserPreference.js +427 -0
- package/dist/services/UserPreference.js.map +1 -0
- package/dist/services/config/Util.js +3 -3
- package/dist/services/config/Util.js.map +1 -1
- package/dist/services/config/constants.js +23 -2
- package/dist/services/config/constants.js.map +1 -1
- package/dist/services/config/types.js +49 -9
- package/dist/services/config/types.js.map +1 -1
- package/dist/services/core/Err.js.map +1 -1
- package/dist/services/core/Utils.js +107 -32
- 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 +728 -527
- 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 +9 -2
- package/dist/services/task/constants.js.map +1 -1
- package/dist/services/task/dialer.js +78 -0
- 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 +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 +212 -4
- 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 +94 -1
- package/dist/types/config.d.ts +6 -0
- package/dist/types/constants.d.ts +17 -1
- package/dist/types/index.d.ts +21 -6
- package/dist/types/metrics/constants.d.ts +21 -1
- package/dist/types/services/ApiAiAssistant.d.ts +22 -4
- package/dist/types/services/UserPreference.d.ts +118 -0
- package/dist/types/services/config/constants.d.ts +21 -0
- package/dist/types/services/config/types.d.ts +171 -10
- package/dist/types/services/core/Err.d.ts +4 -0
- package/dist/types/services/core/Utils.d.ts +33 -13
- 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 +7 -0
- package/dist/types/services/task/dialer.d.ts +30 -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 +603 -66
- 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 +135 -0
- package/dist/types/webex.d.ts +1 -0
- package/dist/types.js +118 -2
- 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 +329 -30
- package/src/config.ts +6 -0
- package/src/constants.ts +17 -1
- package/src/index.ts +23 -5
- package/src/metrics/ai-docs/AGENTS.md +350 -0
- package/src/metrics/ai-docs/ARCHITECTURE.md +338 -0
- package/src/metrics/ai-docs/metrics-spec.md +854 -0
- package/src/metrics/behavioral-events.ts +106 -0
- package/src/metrics/constants.ts +27 -4
- package/src/services/ApiAiAssistant.ts +203 -8
- package/src/services/UserPreference.ts +509 -0
- package/src/services/agent/ai-docs/AGENTS.md +240 -0
- package/src/services/agent/ai-docs/ARCHITECTURE.md +304 -0
- package/src/services/agent/ai-docs/agent-spec.md +504 -0
- package/src/services/ai-docs/AGENTS.md +386 -0
- package/src/services/ai-docs/services-spec.md +492 -0
- package/src/services/config/Util.ts +3 -3
- package/src/services/config/ai-docs/AGENTS.md +255 -0
- package/src/services/config/ai-docs/ARCHITECTURE.md +426 -0
- package/src/services/config/ai-docs/config-spec.md +669 -0
- package/src/services/config/constants.ts +25 -1
- package/src/services/config/types.ts +174 -11
- package/src/services/core/Err.ts +2 -0
- package/src/services/core/Utils.ts +123 -37
- package/src/services/core/ai-docs/AGENTS.md +381 -0
- package/src/services/core/ai-docs/ARCHITECTURE.md +698 -0
- package/src/services/core/ai-docs/core-spec.md +783 -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 +739 -614
- package/src/services/task/TaskUtils.ts +205 -25
- package/src/services/task/ai-docs/AGENTS.md +457 -0
- package/src/services/task/ai-docs/ARCHITECTURE.md +594 -0
- package/src/services/task/ai-docs/task-spec.md +1319 -0
- package/src/services/task/constants.ts +7 -0
- package/src/services/task/dialer.ts +80 -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 +458 -0
- package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +1137 -0
- package/src/services/task/state-machine/ai-docs/task-state-machine-spec.md +2115 -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 +710 -71
- package/src/services/task/voice/Voice.ts +1267 -0
- package/src/services/task/voice/WebRTC.ts +187 -0
- package/src/types.ts +166 -2
- package/src/utils/AGENTS.md +278 -0
- package/src/utils/ai-docs/utils-spec.md +381 -0
- package/src/webex.js +2 -0
- package/test/unit/spec/cc.ts +343 -23
- package/test/unit/spec/logger-proxy.ts +70 -0
- package/test/unit/spec/services/ApiAiAssistant.ts +178 -20
- package/test/unit/spec/services/UserPreference.ts +401 -0
- package/test/unit/spec/services/WebCallingService.ts +7 -1
- package/test/unit/spec/services/config/index.ts +30 -30
- package/test/unit/spec/services/core/Utils.ts +425 -8
- 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 +834 -1704
- package/test/unit/spec/services/task/TaskUtils.ts +206 -0
- package/test/unit/spec/services/task/dialer.ts +190 -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 -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,492 @@
|
|
|
1
|
+
# Services — 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 | `services` |
|
|
10
|
+
| Source path(s) | `src/services` |
|
|
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
|
+
Services is one of nine confirmed Contact Center SDK modules. Own composition and bootstrap order for backend request, realtime, data, and WebRTC service collaborators. Existing reviewed documentation is migrated by meaning and code/tests remain the behavioral referee.
|
|
27
|
+
|
|
28
|
+
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.
|
|
29
|
+
|
|
30
|
+
- Understanding service composition and which service owns which responsibility
|
|
31
|
+
|
|
32
|
+
- Determining the correct instantiation/bootstrap order for services
|
|
33
|
+
|
|
34
|
+
- Tracing request flow from `cc.ts` through services to the backend
|
|
35
|
+
|
|
36
|
+
- Choosing between AqmReqs and direct REST patterns for a new method
|
|
37
|
+
|
|
38
|
+
- Adding a new paginated data service (AddressBook/Queue/EntryPoint pattern) or a direct REST service such as UserPreference
|
|
39
|
+
|
|
40
|
+
- Adding a new AqmReqs method to agent, task, or dialer factories
|
|
41
|
+
|
|
42
|
+
- Routing to the correct service-level docs for task/agent/config/core changes
|
|
43
|
+
|
|
44
|
+
- Clarifying what the Services singleton creates vs what `cc.ts` creates
|
|
45
|
+
|
|
46
|
+
| Capability | Owner | Description |
|
|
47
|
+
|---|---|---|
|
|
48
|
+
| **Service Singleton** | [`index.ts`](../index.ts) | Central `Services` class that instantiates and provides access to all service modules via `Services.getInstance()` |
|
|
49
|
+
| **Agent Operations** | [`agent/`](../agent/index.ts) | Station login/logout, state changes, buddy agents — uses AqmReqs factory pattern |
|
|
50
|
+
| **Task Management** | [`task/`](../task/TaskManager.ts) | Task lifecycle (accept, hold, transfer, conference, wrapup), Task state machine, contact operations, outbound dialing |
|
|
51
|
+
| **Configuration** | [`config/`](../config/index.ts) | Agent profile aggregation from 8+ API endpoints, org settings, teams, aux codes, dial plans |
|
|
52
|
+
| **Core Infrastructure** | [`core/`](../core/WebexRequest.ts) | HTTP requests (`WebexRequest`), WebSocket management (`WebSocketManager`), connection lifecycle (`ConnectionService`), AQM request/response correlation (`AqmReqs`), error handling (`Utils`, `Err`) |
|
|
53
|
+
| **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 |
|
|
54
|
+
| **User Preferences** | [`UserPreference.ts`](../UserPreference.ts) | Direct REST CRUD service exposed as `cc.userPreference`; it resolves the default user from agent configuration and does not use PageCache |
|
|
55
|
+
| **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 |
|
|
56
|
+
| **WebRTC Calling** | [`WebCallingService.ts`](../WebCallingService.ts) | Browser-based voice calling via `@webex/calling`, line registration, call answer/mute/decline |
|
|
57
|
+
|
|
58
|
+
Each service folder contains its own `ai-docs/` with detailed documentation. **Always load the relevant service docs before making changes.**
|
|
59
|
+
|
|
60
|
+
| Service | Scope / Keywords | AGENTS.md | ARCHITECTURE.md |
|
|
61
|
+
|---|---|---|---|
|
|
62
|
+
| **Agent** | login, logout, state change, buddy agents, station, RONA | [`agent/ai-docs/agent-spec.md`](../agent/ai-docs/agent-spec.md) | [`agent/ai-docs/agent-spec.md`](../agent/ai-docs/agent-spec.md) |
|
|
63
|
+
| **Task** | task, hold, transfer, conference, wrapup, outdial, consult, accept, decline, state machine, XState, task states, guards, actions | [`task/ai-docs/task-spec.md`](../task/ai-docs/task-spec.md) | [`task/ai-docs/task-spec.md`](../task/ai-docs/task-spec.md) |
|
|
64
|
+
| **Config** | profile, register, teams, aux codes, desktop profile, org settings, dial plan | [`config/ai-docs/config-spec.md`](../config/ai-docs/config-spec.md) | [`config/ai-docs/config-spec.md`](../config/ai-docs/config-spec.md) |
|
|
65
|
+
| **Core** | websocket, HTTP, connection, reconnect, aqm, utils, errors, keepalive | [`core/ai-docs/core-spec.md`](../core/ai-docs/core-spec.md) | [`core/ai-docs/core-spec.md`](../core/ai-docs/core-spec.md) |
|
|
66
|
+
|
|
67
|
+
> **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/task-state-machine-spec.md`](../task/state-machine/ai-docs/task-state-machine-spec.md) and [`ARCHITECTURE.md`](../task/state-machine/ai-docs/task-state-machine-spec.md). Load these when working on state transitions, guards, or actions.
|
|
68
|
+
|
|
69
|
+
**Paginated 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). `UserPreference` is also a direct REST service, but it has CRUD semantics and does not use their PageCache pattern.
|
|
70
|
+
|
|
71
|
+
**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.
|
|
72
|
+
|
|
73
|
+
The `ContactCenter` plugin class (`cc.ts`) is the **only public entry point**. It delegates all backend work to the services layer:
|
|
74
|
+
|
|
75
|
+
```text
|
|
76
|
+
ContactCenter (cc.ts) — public API surface
|
|
77
|
+
│
|
|
78
|
+
├── WebexRequest.getInstance({webex}) ← initialized FIRST (singleton)
|
|
79
|
+
├── Services.getInstance({webex, connectionConfig}) ← initialized SECOND (singleton)
|
|
80
|
+
│ │
|
|
81
|
+
│ ├── webSocketManager ← primary Contact Center WebSocket transport
|
|
82
|
+
│ ├── rtdWebSocketManager ← separate RTD/transcription WebSocket transport
|
|
83
|
+
│ ├── AqmReqs ← HTTP request + WebSocket notification correlation
|
|
84
|
+
│ ├── ConnectionService ← WebSocket lifecycle, reconnection, keepalive
|
|
85
|
+
│ ├── AgentConfigService (config) ← profile aggregation via REST APIs
|
|
86
|
+
│ ├── routingAgent (agent) ← agent operations via AqmReqs factory
|
|
87
|
+
│ ├── routingContact (contact) ← task/contact operations via AqmReqs factory
|
|
88
|
+
│ └── aqmDialer (dialer) ← outbound dialing via AqmReqs factory
|
|
89
|
+
│
|
|
90
|
+
├── TaskManager ← task lifecycle, created in the Webex READY callback
|
|
91
|
+
├── WebCallingService ← WebRTC calling, created in READY (line registration remains conditional)
|
|
92
|
+
├── ApiAIAssistant ← AI transcript/suggestion API, created in READY
|
|
93
|
+
├── AddressBook ← REST data service, created in READY
|
|
94
|
+
├── EntryPoint ← REST data service, created in READY
|
|
95
|
+
├── Queue ← REST data service, created in READY
|
|
96
|
+
├── UserPreference ← REST user-preference CRUD service, created in READY
|
|
97
|
+
└── MetricsManager.getInstance({webex}) ← telemetry singleton
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Purpose / Responsibility
|
|
101
|
+
Own composition and bootstrap order for backend request, realtime, data, and WebRTC service collaborators.
|
|
102
|
+
|
|
103
|
+
## Stack
|
|
104
|
+
TypeScript 5.4, singleton composition, REST/WebSocket/AQM integrations, @webex/calling, Jest 27.
|
|
105
|
+
|
|
106
|
+
## Folder / Package Structure
|
|
107
|
+
```text
|
|
108
|
+
src/services/
|
|
109
|
+
├── AddressBook.ts
|
|
110
|
+
├── ApiAiAssistant.ts
|
|
111
|
+
├── EntryPoint.ts
|
|
112
|
+
├── Queue.ts
|
|
113
|
+
├── UserPreference.ts
|
|
114
|
+
├── WebCallingService.ts
|
|
115
|
+
├── agent/
|
|
116
|
+
├── config/
|
|
117
|
+
├── constants.ts
|
|
118
|
+
├── core/
|
|
119
|
+
├── index.ts
|
|
120
|
+
├── task/
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
```text
|
|
124
|
+
src/services/
|
|
125
|
+
├── index.ts # Services singleton — composes all services
|
|
126
|
+
├── constants.ts # Shared constants (gateway id, API paths, WebRTC domains/prefixes, timeout, method-name constants)
|
|
127
|
+
├── ai-docs/
|
|
128
|
+
│ └── AGENTS.md # Preserved legacy migration source (non-canonical)
|
|
129
|
+
│
|
|
130
|
+
├── agent/ # Agent operations service
|
|
131
|
+
│ ├── index.ts # routingAgent factory — stationLogin, stateChange, logout, buddyAgents
|
|
132
|
+
│ ├── types.ts # Agent types: StateChange, Logout, AGENT_EVENTS, LoginOption
|
|
133
|
+
│ └── ai-docs/ # Agent-specific documentation
|
|
134
|
+
│ ├── AGENTS.md
|
|
135
|
+
│ └── ARCHITECTURE.md
|
|
136
|
+
│
|
|
137
|
+
├── task/ # Task management service
|
|
138
|
+
│ ├── TaskManager.ts # Task lifecycle manager — creates/destroys Task instances
|
|
139
|
+
│ ├── Task.ts # Individual task — hold, transfer, conference, wrapup
|
|
140
|
+
│ ├── TaskFactory.ts # Creates Task with config flags
|
|
141
|
+
│ ├── contact.ts # routingContact factory — task operations via AqmReqs
|
|
142
|
+
│ ├── dialer.ts # aqmDialer factory — outbound dialing
|
|
143
|
+
│ ├── AutoWrapup.ts # Auto wrapup timer handler
|
|
144
|
+
│ ├── TaskUtils.ts # Task utility functions
|
|
145
|
+
│ ├── taskDataNormalizer.ts # Normalizes task data from events
|
|
146
|
+
│ ├── types.ts # Task types: ITask, TASK_EVENTS, TaskResponse
|
|
147
|
+
│ ├── constants.ts # Task constants
|
|
148
|
+
│ ├── voice/ # Voice-specific task handling
|
|
149
|
+
│ │ ├── Voice.ts # Voice task operations
|
|
150
|
+
│ │ └── WebRTC.ts # WebRTC-specific voice operations
|
|
151
|
+
│ ├── digital/ # Digital channel task handling
|
|
152
|
+
│ │ └── Digital.ts # Digital task operations
|
|
153
|
+
│ ├── state-machine/ # XState-based task state machine
|
|
154
|
+
│ │ ├── TaskStateMachine.ts # State machine definition
|
|
155
|
+
│ │ ├── index.ts # Barrel export for state machine public API
|
|
156
|
+
│ │ ├── constants.ts # TaskState, TaskEvent enums
|
|
157
|
+
│ │ ├── types.ts # TaskContext type
|
|
158
|
+
│ │ ├── guards.ts # State transition guards
|
|
159
|
+
│ │ ├── actions.ts # State transition actions
|
|
160
|
+
│ │ ├── uiControlsComputer.ts # Computes UI controls from state
|
|
161
|
+
│ │ └── ai-docs/ # State machine documentation
|
|
162
|
+
│ │ ├── AGENTS.md
|
|
163
|
+
│ │ └── ARCHITECTURE.md
|
|
164
|
+
│ └── ai-docs/ # Task-specific documentation
|
|
165
|
+
│ ├── AGENTS.md
|
|
166
|
+
│ └── ARCHITECTURE.md
|
|
167
|
+
│
|
|
168
|
+
├── config/ # Configuration service
|
|
169
|
+
│ ├── index.ts # AgentConfigService — getAgentConfig(), profile aggregation
|
|
170
|
+
│ ├── Util.ts # parseAgentConfigs, getFilterAuxCodes, helper functions
|
|
171
|
+
│ ├── types.ts # CC_EVENTS, Profile, CC_AGENT_EVENTS, CC_TASK_EVENTS
|
|
172
|
+
│ ├── constants.ts # endPointMap (API URL builders), pagination defaults
|
|
173
|
+
│ └── ai-docs/ # Config-specific documentation
|
|
174
|
+
│ ├── AGENTS.md
|
|
175
|
+
│ └── ARCHITECTURE.md
|
|
176
|
+
│
|
|
177
|
+
├── core/ # Core infrastructure
|
|
178
|
+
│ ├── WebexRequest.ts # HTTP client singleton — request(), uploadLogs()
|
|
179
|
+
│ ├── aqm-reqs.ts # AqmReqs — HTTP request + WebSocket notification correlation
|
|
180
|
+
│ ├── Utils.ts # getErrorDetails, generateTaskErrorObject, isValidDialNumber
|
|
181
|
+
│ ├── Err.ts # Err.Details error class with structured metadata
|
|
182
|
+
│ ├── GlobalTypes.ts # Msg<T>, Failure, AugmentedError, TaskError
|
|
183
|
+
│ ├── types.ts # Req, Conf, Res types for AqmReqs
|
|
184
|
+
│ ├── constants.ts # Core constants
|
|
185
|
+
│ ├── websocket/
|
|
186
|
+
│ │ ├── WebSocketManager.ts # WebSocket connection handler
|
|
187
|
+
│ │ ├── connection-service.ts # Connection lifecycle, reconnection, keepalive
|
|
188
|
+
│ │ └── types.ts # WebSocket types
|
|
189
|
+
│ └── ai-docs/ # Core-specific documentation
|
|
190
|
+
│ ├── AGENTS.md
|
|
191
|
+
│ └── ARCHITECTURE.md
|
|
192
|
+
│
|
|
193
|
+
├── AddressBook.ts # Address book entries — getEntries() with pagination/cache
|
|
194
|
+
├── EntryPoint.ts # Entry points — getEntryPoints() with pagination/cache
|
|
195
|
+
├── Queue.ts # Queues — getQueues() with pagination/cache
|
|
196
|
+
└── WebCallingService.ts # WebRTC calling — register/deregister line, answer/mute/decline
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
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.
|
|
200
|
+
|
|
201
|
+
Use [`constants.ts`](../constants.ts) as the canonical source for service-level naming and routing constants:
|
|
202
|
+
|
|
203
|
+
- `WCC_API_GATEWAY` — service identifier used by `WebexRequest` calls
|
|
204
|
+
|
|
205
|
+
- `SUBSCRIBE_API`, `LOGIN_API`, `STATE_CHANGE_API` — common API path constants
|
|
206
|
+
|
|
207
|
+
- `WEB_RTC_PREFIX` — path prefix for WebRTC-related endpoints
|
|
208
|
+
|
|
209
|
+
- `WEBSOCKET_EVENT_TIMEOUT` — defined as `20000` ms in `src/services/constants.ts` but not used by AqmReqs; active AQM correlation defaults to Core's `TIMEOUT_REQ = 20000`
|
|
210
|
+
|
|
211
|
+
- `DEFAULT_RTMS_DOMAIN`, `WCC_CALLING_RTMS_DOMAIN` — RTMS/WebRTC domain constants
|
|
212
|
+
|
|
213
|
+
- `METHODS` — method name constants used by `WebCallingService`
|
|
214
|
+
|
|
215
|
+
## Key Files (source of truth)
|
|
216
|
+
| File | Holds |
|
|
217
|
+
|---|---|
|
|
218
|
+
| `src/services/index.ts` | Authoritative Services implementation or contract source. |
|
|
219
|
+
| `src/services/constants.ts` | Authoritative Services implementation or contract source. |
|
|
220
|
+
| `src/services/AddressBook.ts` | Authoritative Services implementation or contract source. |
|
|
221
|
+
| `src/services/EntryPoint.ts` | Authoritative Services implementation or contract source. |
|
|
222
|
+
| `src/services/Queue.ts` | Authoritative Services implementation or contract source. |
|
|
223
|
+
| `src/services/UserPreference.ts` | Direct REST user-preference CRUD exposed through `cc.userPreference`. |
|
|
224
|
+
| `src/services/WebCallingService.ts` | Authoritative Services implementation or contract source. |
|
|
225
|
+
|
|
226
|
+
## Public Surface
|
|
227
|
+
| Contract ID | Type | Surface | Purpose | Compatibility / deprecation | Schema / detail link | Root index |
|
|
228
|
+
|---|---|---|---|---|---|---|
|
|
229
|
+
| `services.surface` | SDK / event / internal API | Internal `Services.getInstance()` composition root plus data-service and calling collaborators consumed by `ContactCenter`. | Stable module consumption boundary. | Additive changes by default; breaking package exports require a major-version transition. | `src/services/index.ts` | `../../../ai-docs/CONTRACTS.md` |
|
|
230
|
+
| `services.user-preference` | SDK data API | `UserPreference` and `cc.userPreference`. | Direct REST CRUD for user preferences; separate from PageCache-based pagination services. | Additive semver-public API; removals or signature changes are breaking. | `src/services/UserPreference.ts`, `src/services/config/types.ts` | `../../../ai-docs/CONTRACTS.md` |
|
|
231
|
+
|
|
232
|
+
Compatibility notes:
|
|
233
|
+
- Do not remove or reinterpret exported symbols/events without a documented consumer migration.
|
|
234
|
+
|
|
235
|
+
## Requires (dependencies)
|
|
236
|
+
- Host Webex SDK READY lifecycle and authenticated request facilities.
|
|
237
|
+
- `WebexRequest` initialized by ContactCenter before `Services.getInstance()`.
|
|
238
|
+
- WCC REST endpoints plus primary Contact Center and RTD WebSocket transports.
|
|
239
|
+
- `ApiAIAssistant`, `WebCallingService`, `MetricsManager`, TaskManager, and PageCache-consuming data services constructed by ContactCenter.
|
|
240
|
+
- `@webex/calling` for browser calling.
|
|
241
|
+
|
|
242
|
+
```text
|
|
243
|
+
ContactCenter READY callback
|
|
244
|
+
├── WebexRequest.getInstance(webex)
|
|
245
|
+
├── Services.getInstance(webex, connectionConfig)
|
|
246
|
+
│ ├── webSocketManager + rtdWebSocketManager
|
|
247
|
+
│ ├── AqmReqs(primary WebSocket)
|
|
248
|
+
│ ├── config + agent + contact + dialer
|
|
249
|
+
│ └── ConnectionService(primary WebSocket)
|
|
250
|
+
├── WebCallingService + ApiAIAssistant + MetricsManager
|
|
251
|
+
├── TaskManager(ApiAIAssistant, contact, calling, primary WS, RTD WS)
|
|
252
|
+
└── AddressBook + EntryPoint + Queue + UserPreference
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Requirements
|
|
256
|
+
| ID | WHAT | WHY | Source Evidence | Test / Example Evidence | Assumptions / Gaps | Confidence |
|
|
257
|
+
|---|---|---|---|---|---|---|
|
|
258
|
+
| SERVICES-R-001 | Build the Services singleton with agent/config/contact/dialer, two WebSocket managers, AqmReqs, and ConnectionService after WebexRequest is initialized. | Every AQM and transport collaborator depends on one shared authenticated host and primary message stream. | `src/services/index.ts` | `test/unit/spec/cc.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
|
|
259
|
+
| SERVICES-R-002 | Keep direct REST services, including UserPreference, separate from AQM request factories. | Direct data/config/user-preference calls complete from HTTP while AQM operations require correlated WebSocket completion. | `src/services/index.ts`, `src/services/UserPreference.ts` | `test/unit/spec/services/AddressBook.ts`, `test/unit/spec/services/UserPreference.ts` | None; UserPreference's direct-REST/no-PageCache behavior was independently validated by claude-code on 2026-07-15. | PRESENT |
|
|
260
|
+
| SERVICES-R-003 | Construct TaskManager, UserPreference, and other non-Services collaborators in ContactCenter's READY callback, not in `register()`. | Registration is a connection boundary; changing construction timing can duplicate listeners or access uninitialized host services. | `src/cc.ts` | `test/unit/spec/cc.ts`, `test/unit/spec/services/UserPreference.ts` | None; READY-time UserPreference ownership was independently validated by claude-code on 2026-07-15. | PRESENT |
|
|
261
|
+
| SERVICES-R-004 | Pass ApiAIAssistant, contact routing, WebCallingService, primary WebSocket, and RTD WebSocket into TaskManager. | Voice, task, transcript, and suggestion behavior depend on the complete collaborator set. | `src/cc.ts` | `test/unit/spec/services/task/TaskManager.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
|
|
262
|
+
| SERVICES-R-005 | Inherit authenticated request identity from the host Webex SDK through Core/WebexRequest; Services must not store, parse, or refresh credentials. | One host-owned authentication boundary avoids duplicate token handling and credential leakage across composed services. | `src/services/index.ts`, `src/services/core/WebexRequest.ts` | `test/unit/spec/services/core/WebexRequest.ts` | None; authentication ownership is explicit. | PRESENT |
|
|
263
|
+
| SERVICES-R-006 | Treat Services composition as unconditionally created by the ContactCenter READY callback; Services owns no rollout or feature-flag decision. | Capability flags belong to the consuming config/task/calling collaborators, so the composition root must not silently gate construction. | `src/services/index.ts`, `src/cc.ts` | `test/unit/spec/cc.ts` | None; rollout applicability is explicitly N/A for Services. | PRESENT |
|
|
264
|
+
|
|
265
|
+
## Design Overview
|
|
266
|
+
`Services` is a singleton composition root for transport-facing capabilities only. It constructs two `WebSocketManager` instances (primary Contact Center and RTD), creates `AqmReqs` on the primary manager, then creates config, agent, contact, dialer, and ConnectionService collaborators.
|
|
267
|
+
|
|
268
|
+
ContactCenter owns the broader READY-time graph: WebCallingService, ApiAIAssistant, MetricsManager, TaskManager, EntryPoint, AddressBook, Queue, and UserPreference. TaskManager receives ApiAIAssistant, contact routing, calling, and both WebSocket managers. None of these collaborators is created by `register()`; registration attaches runtime listeners and connects the primary socket after READY initialization.
|
|
269
|
+
|
|
270
|
+
AQM factories return functions whose HTTP request is initiation and whose promise settles on correlated primary-WebSocket notifications. Direct config/data services return authenticated REST responses.
|
|
271
|
+
|
|
272
|
+
## Data Flow
|
|
273
|
+
```mermaid
|
|
274
|
+
flowchart TD
|
|
275
|
+
Ready[Host READY] --> WR[WebexRequest singleton]
|
|
276
|
+
WR --> S[Services singleton]
|
|
277
|
+
S --> PWS[Primary WebSocketManager]
|
|
278
|
+
S --> RTD[RTD WebSocketManager]
|
|
279
|
+
PWS --> AQM[AqmReqs]
|
|
280
|
+
AQM --> Agent[routingAgent]
|
|
281
|
+
AQM --> Contact[routingContact]
|
|
282
|
+
AQM --> Dialer[aqmDialer]
|
|
283
|
+
S --> Config[AgentConfigService]
|
|
284
|
+
PWS --> CS[ConnectionService]
|
|
285
|
+
Ready --> AI[ApiAIAssistant]
|
|
286
|
+
Ready --> Calling[WebCallingService]
|
|
287
|
+
Ready --> TM[TaskManager]
|
|
288
|
+
Ready --> UP[UserPreference]
|
|
289
|
+
AI --> TM
|
|
290
|
+
Contact --> TM
|
|
291
|
+
Calling --> TM
|
|
292
|
+
PWS --> TM
|
|
293
|
+
RTD --> TM
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Direct REST: caller → AgentConfigService/AddressBook/EntryPoint/Queue/UserPreference → WebexRequest → response.
|
|
297
|
+
|
|
298
|
+
AQM: caller → routing factory → AqmReqs → WebexRequest HTTP acknowledgement → matching primary-WebSocket success/failure → promise settlement.
|
|
299
|
+
|
|
300
|
+
Realtime task/AI: primary or RTD WebSocket → TaskManager → Task/state machine → typed application event.
|
|
301
|
+
|
|
302
|
+
## Sequence Diagram(s)
|
|
303
|
+
Sequence coverage:
|
|
304
|
+
|
|
305
|
+
| Operation group | Diagram | Failure / recovery coverage |
|
|
306
|
+
|---|---|---|
|
|
307
|
+
| READY-time composition | READY composition | Invalid initialization prevents use of the incomplete graph. |
|
|
308
|
+
| Direct REST | Direct REST request | HTTP/service rejection is returned directly to the caller. |
|
|
309
|
+
| AQM | Correlated AQM operation | HTTP rejection, matching failure notification, and timeout reject the operation. |
|
|
310
|
+
|
|
311
|
+
### READY composition
|
|
312
|
+
|
|
313
|
+
```mermaid
|
|
314
|
+
sequenceDiagram
|
|
315
|
+
participant Host
|
|
316
|
+
participant CC as ContactCenter
|
|
317
|
+
participant S as Services
|
|
318
|
+
participant TM as TaskManager
|
|
319
|
+
Host-->>CC: READY
|
|
320
|
+
CC->>CC: initialize WebexRequest
|
|
321
|
+
CC->>S: getInstance(webex, connectionConfig)
|
|
322
|
+
S->>S: primary WS + RTD WS + AqmReqs + config/agent/contact/dialer + ConnectionService
|
|
323
|
+
CC->>CC: create calling + AI assistant + metrics + data services + UserPreference
|
|
324
|
+
CC->>TM: getTaskManager(AI, contact, calling, primary WS, RTD WS)
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Direct REST request
|
|
328
|
+
|
|
329
|
+
```mermaid
|
|
330
|
+
sequenceDiagram
|
|
331
|
+
participant Caller
|
|
332
|
+
participant Service as Config/data service
|
|
333
|
+
participant WR as WebexRequest
|
|
334
|
+
participant Host as Authenticated Webex request
|
|
335
|
+
Caller->>Service: typed REST operation
|
|
336
|
+
Service->>WR: request(service + resource + method)
|
|
337
|
+
WR->>Host: resolve service and send request
|
|
338
|
+
alt HTTP success
|
|
339
|
+
Host-->>WR: response
|
|
340
|
+
WR-->>Service: typed response
|
|
341
|
+
Service-->>Caller: result
|
|
342
|
+
else service/HTTP rejection
|
|
343
|
+
Host-->>WR: error
|
|
344
|
+
WR-->>Service: same rejection
|
|
345
|
+
Service-->>Caller: reject
|
|
346
|
+
end
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### Correlated AQM operation
|
|
350
|
+
|
|
351
|
+
```mermaid
|
|
352
|
+
sequenceDiagram
|
|
353
|
+
participant Caller
|
|
354
|
+
participant Factory as agent/contact/dialer
|
|
355
|
+
participant AQM as AqmReqs
|
|
356
|
+
participant HTTP as WebexRequest
|
|
357
|
+
participant WS as Primary WebSocket
|
|
358
|
+
Caller->>Factory: typed operation
|
|
359
|
+
Factory->>AQM: generated request function(payload)
|
|
360
|
+
AQM->>HTTP: authenticated request(config)
|
|
361
|
+
HTTP-->>AQM: acknowledgement
|
|
362
|
+
alt matching success notification
|
|
363
|
+
WS-->>AQM: notifSuccess.bind match
|
|
364
|
+
AQM-->>Caller: typed response
|
|
365
|
+
else matching failure or timeout
|
|
366
|
+
WS-->>AQM: notifFail.bind match
|
|
367
|
+
AQM-->>Caller: structured rejection
|
|
368
|
+
end
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
## Class / Component Relationships
|
|
372
|
+
```mermaid
|
|
373
|
+
classDiagram
|
|
374
|
+
class ContactCenter
|
|
375
|
+
class Services
|
|
376
|
+
class WebSocketManager
|
|
377
|
+
class AqmReqs
|
|
378
|
+
class ConnectionService
|
|
379
|
+
class AgentConfigService
|
|
380
|
+
class TaskManager
|
|
381
|
+
class ApiAIAssistant
|
|
382
|
+
ContactCenter --> Services
|
|
383
|
+
Services --> WebSocketManager : primary + RTD
|
|
384
|
+
Services --> AqmReqs : primary WS correlation
|
|
385
|
+
Services --> ConnectionService
|
|
386
|
+
Services --> AgentConfigService
|
|
387
|
+
ContactCenter --> ApiAIAssistant
|
|
388
|
+
ContactCenter --> TaskManager
|
|
389
|
+
ContactCenter --> UserPreference
|
|
390
|
+
TaskManager --> ApiAIAssistant
|
|
391
|
+
TaskManager --> WebSocketManager : primary + RTD
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
## Use Cases
|
|
395
|
+
- **UC-1 Compose services:** create the transport/factory singleton once per SDK host. Evidence: `src/services/index.ts`, `test/unit/spec/cc.ts`.
|
|
396
|
+
- **UC-2 Direct REST:** configuration, data, and user-preference services return authenticated HTTP results directly. Evidence: `src/services/config/index.ts`, `src/services/UserPreference.ts`, `test/unit/spec/services/config/index.ts`, `test/unit/spec/services/UserPreference.ts`.
|
|
397
|
+
- **UC-3 AQM operation:** initiate HTTP and settle only on matching WebSocket notification or timeout. Evidence: `src/services/core/aqm-reqs.ts`, `test/unit/spec/services/core/aqm-reqs.ts`.
|
|
398
|
+
- **UC-4 Task/AI realtime:** TaskManager consumes primary and RTD streams with ApiAIAssistant/calling collaborators. Evidence: `src/services/task/TaskManager.ts`, `test/unit/spec/services/task/TaskManager.ts`.
|
|
399
|
+
|
|
400
|
+
## State Model
|
|
401
|
+
`Services` is a process-local singleton. Its first `getInstance({webex, connectionConfig})` call synchronously constructs the two WebSocket managers, AqmReqs-backed factories, config service, and ConnectionService; later calls return that same composed graph. Socket lifecycle and domain records are owned by the corresponding collaborators, not by a Services state machine.
|
|
402
|
+
|
|
403
|
+
## Business Rules & Invariants
|
|
404
|
+
- The first singleton construction fixes the host SDK and connection configuration for that Services instance.
|
|
405
|
+
- The primary WebSocket manager is used for AQM correlation and Contact Center events; the RTD manager remains a distinct TaskManager dependency.
|
|
406
|
+
- ApiAIAssistant, TaskManager, and UserPreference are READY-time ContactCenter collaborators, not fields constructed by Services.
|
|
407
|
+
- Authentication is inherited from the host SDK through Core/WebexRequest; Services owns no credential lifecycle.
|
|
408
|
+
- Rollout applicability is N/A for the Services composition root: it is created at READY and does not evaluate a feature flag.
|
|
409
|
+
|
|
410
|
+
## Concurrency & Reactive Flow
|
|
411
|
+
- `getInstance` composition is synchronous in the JavaScript execution turn. Direct REST promises can proceed independently, while each AQM promise remains pending until its matching primary-WebSocket notification, HTTP failure, or timeout.
|
|
412
|
+
|
|
413
|
+
These three services share an identical pattern. Use any one as a reference when creating similar services:
|
|
414
|
+
|
|
415
|
+
| Aspect | Pattern |
|
|
416
|
+
|---|---|
|
|
417
|
+
| **Class structure** | Standalone class with `WebexRequest`, `WebexSDK`, `MetricsManager`, `PageCache` |
|
|
418
|
+
| **Constructor** | `constructor(webex: WebexSDK)` — gets singletons via `.getInstance()` |
|
|
419
|
+
| **HTTP calls** | `this.webexRequest.request({service: WCC_API_GATEWAY, resource, method: HTTP_METHODS.GET})` |
|
|
420
|
+
| **Endpoints** | Uses `endPointMap` functions from `config/constants.ts` to build URL paths |
|
|
421
|
+
| **Pagination** | Query params with `page`, `pageSize`; uses `PageCache` for caching |
|
|
422
|
+
| **Caching** | `PageCache<T>` — caches pages for simple pagination, bypasses cache for search/filter |
|
|
423
|
+
| **Metrics** | `timeEvent` on API call start, `trackEvent` on success/failure |
|
|
424
|
+
| **Logging** | `LoggerProxy` with `{module: 'ClassName', method: 'methodName'}` context |
|
|
425
|
+
| **Error handling** | try/catch with `LoggerProxy.error` + `metricsManager.trackEvent` for failures, then re-throw so callers receive the error |
|
|
426
|
+
|
|
427
|
+
Reference files:
|
|
428
|
+
|
|
429
|
+
- [`AddressBook.ts`](../AddressBook.ts) — includes `addressBookId` parameter
|
|
430
|
+
|
|
431
|
+
- [`Queue.ts`](../Queue.ts) — includes additional query params (sortBy, sortOrder, etc.)
|
|
432
|
+
|
|
433
|
+
- [`EntryPoint.ts`](../EntryPoint.ts) — simplest example
|
|
434
|
+
|
|
435
|
+
`UserPreference.ts` is a separate direct REST CRUD pattern. It resolves a default user id from `agentConfig`, supports explicit user ids where applicable, and intentionally does not share PageCache behavior with the three paginated services.
|
|
436
|
+
|
|
437
|
+
## State Machine
|
|
438
|
+
```mermaid
|
|
439
|
+
stateDiagram-v2
|
|
440
|
+
[*] --> NotCreated
|
|
441
|
+
NotCreated --> Composed: first getInstance(options)
|
|
442
|
+
Composed --> Composed: later getInstance returns singleton
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
## Protocol / Wire Format
|
|
446
|
+
- Request, response, and event payload ownership is anchored in `src/services/index.ts`. HTTP initiates backend work where applicable; WebSocket messages provide realtime events and, for AQM flows, correlated completion.
|
|
447
|
+
|
|
448
|
+
## Error Handling & Failure Modes
|
|
449
|
+
| Condition | Signal (error/code/result) | Caller recovery |
|
|
450
|
+
|---|---|---|
|
|
451
|
+
| Dependency rejection | Typed/rethrown error or failure event | Inspect structured details, preserve tracking id, and retry only when the operation is safe. |
|
|
452
|
+
| Timeout or missing async completion | Timeout/recovery state | Follow the module-specific recovery path; never synthesize success. |
|
|
453
|
+
|
|
454
|
+
## Pitfalls
|
|
455
|
+
- Direct REST services complete from HTTP, while agent/contact/dialer AQM factories complete from correlated WebSocket notifications; treating them as the same transport model returns too early.
|
|
456
|
+
- The singleton must share one primary WebSocket with AqmReqs and a distinct RTD WebSocket with TaskManager; swapping or omitting either stream loses task or AI events.
|
|
457
|
+
- TaskManager and calling/AI/data/UserPreference collaborators are created by ContactCenter after READY, not by the Services constructor or `register()`.
|
|
458
|
+
|
|
459
|
+
## Module Do's / Don'ts
|
|
460
|
+
- DO initialize `WebexRequest` before obtaining the Services singleton.
|
|
461
|
+
- DO preserve separate primary and RTD WebSocket ownership when changing composition.
|
|
462
|
+
- DON'T wrap direct REST services in AqmReqs or treat HTTP acknowledgement as AQM completion.
|
|
463
|
+
- DON'T add feature-flag decisions to the Services composition root.
|
|
464
|
+
|
|
465
|
+
## Key Design Trade-off
|
|
466
|
+
- Two backend interaction patterns coexist: direct REST for immediate responses and AQM HTTP-plus-WebSocket correlation for asynchronous completion.
|
|
467
|
+
|
|
468
|
+
## Test-Case Strategy (module)
|
|
469
|
+
Unit tests mirror module paths under `test/unit/spec/services`. Preserve positive and negative paths, event ordering, timeout/recovery behavior, and the package's 85% global branch/function/line/statement threshold.
|
|
470
|
+
|
|
471
|
+
| Behavior / Requirement | Existing test evidence | Gap |
|
|
472
|
+
|---|---|---|
|
|
473
|
+
| `SERVICES-R-001` | `test/unit/spec/cc.ts` | Add a focused Services singleton composition test if constructor wiring changes. |
|
|
474
|
+
| `SERVICES-R-002` | `test/unit/spec/services/config/index.ts`, `test/unit/spec/services/UserPreference.ts`, `test/unit/spec/services/core/aqm-reqs.ts` | Coverage is split across direct and AQM owners. |
|
|
475
|
+
| `SERVICES-R-003` | `test/unit/spec/cc.ts`, `test/unit/spec/services/UserPreference.ts` | None. |
|
|
476
|
+
| `SERVICES-R-004` | `test/unit/spec/services/task/TaskManager.ts`, `test/unit/spec/cc.ts` | None. |
|
|
477
|
+
| `SERVICES-R-005` | `test/unit/spec/services/core/WebexRequest.ts` | None. |
|
|
478
|
+
| `SERVICES-R-006` | `test/unit/spec/cc.ts` | None. |
|
|
479
|
+
|
|
480
|
+
## Traceability
|
|
481
|
+
- Repo architecture: `../../../ai-docs/ARCHITECTURE.md` · Registry: `../../../ai-docs/SPEC_INDEX.md`
|
|
482
|
+
- Coverage state and contracts baseline: `../../../.sdd/manifest.json`
|
|
483
|
+
|
|
484
|
+
- [Root orchestrator AGENTS.md](../../../AGENTS.md) — repository rules; use [`SPEC_INDEX.md`](../../../ai-docs/SPEC_INDEX.md) for canonical module routing
|
|
485
|
+
|
|
486
|
+
- [ai-docs/RULES.md](../../../ai-docs/RULES.md) — coding standards
|
|
487
|
+
|
|
488
|
+
- [ai-docs/patterns/](../../../ai-docs/patterns/) — TypeScript, testing, and event patterns
|
|
489
|
+
|
|
490
|
+
- [types.ts](../../types.ts) — public type definitions
|
|
491
|
+
|
|
492
|
+
- [cc.ts](../../cc.ts) — main plugin class (public API surface)
|
|
@@ -185,11 +185,11 @@ function parseAgentConfigs(profileData: {
|
|
|
185
185
|
|
|
186
186
|
const defaultWrapUpData = getDefaultWrapUpCode(wrapupCodes);
|
|
187
187
|
const aiFeature: AIFeatureFlags | undefined =
|
|
188
|
-
aiFeatureFlags?.data
|
|
188
|
+
aiFeatureFlags?.data?.length > 0 ? aiFeatureFlags.data[0] : undefined;
|
|
189
189
|
|
|
190
190
|
const finalData = {
|
|
191
191
|
teams: teamData,
|
|
192
|
-
defaultDn: userData.
|
|
192
|
+
defaultDn: userData.deafultDialledNumber,
|
|
193
193
|
forceDefaultDn: tenantData.forceDefaultDn,
|
|
194
194
|
forceDefaultDnForAgent: getDefaultAgentDN(agentProfileData.agentDNValidation),
|
|
195
195
|
regexUS: tenantData.dnDefaultRegex,
|
|
@@ -233,7 +233,7 @@ function parseAgentConfigs(profileData: {
|
|
|
233
233
|
isAgentAvailableAfterOutdial: agentProfileData.agentAvailableAfterOutdial,
|
|
234
234
|
outDialEp: agentProfileData.outdialEntryPointId,
|
|
235
235
|
isCampaignManagementEnabled: orgSettingsData.campaignManagerEnabled,
|
|
236
|
-
|
|
236
|
+
isEndTaskEnabled: tenantData.endCallEnabled,
|
|
237
237
|
isEndConsultEnabled: tenantData.endConsultEnabled,
|
|
238
238
|
callVariablesSuppressed: tenantData.callVariablesSuppressed,
|
|
239
239
|
agentDbId: userData.dbId,
|