@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.
Files changed (188) hide show
  1. package/AGENTS.md +438 -0
  2. package/ai-docs/README.md +131 -0
  3. package/ai-docs/RULES.md +455 -0
  4. package/ai-docs/patterns/event-driven-patterns.md +485 -0
  5. package/ai-docs/patterns/testing-patterns.md +480 -0
  6. package/ai-docs/patterns/typescript-patterns.md +365 -0
  7. package/ai-docs/templates/README.md +102 -0
  8. package/ai-docs/templates/documentation/create-agents-md.md +240 -0
  9. package/ai-docs/templates/documentation/create-architecture-md.md +295 -0
  10. package/ai-docs/templates/existing-service/bug-fix.md +254 -0
  11. package/ai-docs/templates/existing-service/feature-enhancement.md +450 -0
  12. package/ai-docs/templates/new-method/00-master.md +80 -0
  13. package/ai-docs/templates/new-method/01-requirements.md +232 -0
  14. package/ai-docs/templates/new-method/02-implementation.md +295 -0
  15. package/ai-docs/templates/new-method/03-tests.md +201 -0
  16. package/ai-docs/templates/new-method/04-validation.md +141 -0
  17. package/ai-docs/templates/new-service/00-master.md +109 -0
  18. package/ai-docs/templates/new-service/01-pre-questions.md +159 -0
  19. package/ai-docs/templates/new-service/02-code-generation.md +346 -0
  20. package/ai-docs/templates/new-service/03-integration.md +178 -0
  21. package/ai-docs/templates/new-service/04-test-generation.md +205 -0
  22. package/ai-docs/templates/new-service/05-validation.md +145 -0
  23. package/dist/cc.js +53 -38
  24. package/dist/cc.js.map +1 -1
  25. package/dist/config.js +6 -0
  26. package/dist/config.js.map +1 -1
  27. package/dist/constants.js +14 -1
  28. package/dist/constants.js.map +1 -1
  29. package/dist/index.js +13 -5
  30. package/dist/index.js.map +1 -1
  31. package/dist/metrics/behavioral-events.js +26 -0
  32. package/dist/metrics/behavioral-events.js.map +1 -1
  33. package/dist/metrics/constants.js +9 -3
  34. package/dist/metrics/constants.js.map +1 -1
  35. package/dist/services/ApiAiAssistant.js +74 -3
  36. package/dist/services/ApiAiAssistant.js.map +1 -1
  37. package/dist/services/config/Util.js +2 -2
  38. package/dist/services/config/Util.js.map +1 -1
  39. package/dist/services/config/types.js +25 -9
  40. package/dist/services/config/types.js.map +1 -1
  41. package/dist/services/core/Utils.js +74 -27
  42. package/dist/services/core/Utils.js.map +1 -1
  43. package/dist/services/core/websocket/WebSocketManager.js +2 -1
  44. package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
  45. package/dist/services/core/websocket/types.js.map +1 -1
  46. package/dist/services/index.js +1 -1
  47. package/dist/services/index.js.map +1 -1
  48. package/dist/services/task/Task.js +688 -0
  49. package/dist/services/task/Task.js.map +1 -0
  50. package/dist/services/task/TaskFactory.js +45 -0
  51. package/dist/services/task/TaskFactory.js.map +1 -0
  52. package/dist/services/task/TaskManager.js +725 -612
  53. package/dist/services/task/TaskManager.js.map +1 -1
  54. package/dist/services/task/TaskUtils.js +162 -26
  55. package/dist/services/task/TaskUtils.js.map +1 -1
  56. package/dist/services/task/constants.js +6 -1
  57. package/dist/services/task/constants.js.map +1 -1
  58. package/dist/services/task/digital/Digital.js +77 -0
  59. package/dist/services/task/digital/Digital.js.map +1 -0
  60. package/dist/services/task/state-machine/TaskStateMachine.js +837 -0
  61. package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -0
  62. package/dist/services/task/state-machine/actions.js +543 -0
  63. package/dist/services/task/state-machine/actions.js.map +1 -0
  64. package/dist/services/task/state-machine/constants.js +161 -0
  65. package/dist/services/task/state-machine/constants.js.map +1 -0
  66. package/dist/services/task/state-machine/guards.js +340 -0
  67. package/dist/services/task/state-machine/guards.js.map +1 -0
  68. package/dist/services/task/state-machine/index.js +53 -0
  69. package/dist/services/task/state-machine/index.js.map +1 -0
  70. package/dist/services/task/state-machine/types.js +54 -0
  71. package/dist/services/task/state-machine/types.js.map +1 -0
  72. package/dist/services/task/state-machine/uiControlsComputer.js +553 -0
  73. package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -0
  74. package/dist/services/task/taskDataNormalizer.js +99 -0
  75. package/dist/services/task/taskDataNormalizer.js.map +1 -0
  76. package/dist/services/task/types.js +168 -16
  77. package/dist/services/task/types.js.map +1 -1
  78. package/dist/services/task/voice/Voice.js +1042 -0
  79. package/dist/services/task/voice/Voice.js.map +1 -0
  80. package/dist/services/task/voice/WebRTC.js +149 -0
  81. package/dist/services/task/voice/WebRTC.js.map +1 -0
  82. package/dist/types/cc.d.ts +19 -18
  83. package/dist/types/config.d.ts +6 -0
  84. package/dist/types/constants.d.ts +14 -1
  85. package/dist/types/index.d.ts +11 -5
  86. package/dist/types/metrics/constants.d.ts +7 -1
  87. package/dist/types/services/ApiAiAssistant.d.ts +11 -3
  88. package/dist/types/services/config/types.d.ts +113 -9
  89. package/dist/types/services/core/Utils.d.ts +23 -10
  90. package/dist/types/services/core/websocket/WebSocketManager.d.ts +1 -0
  91. package/dist/types/services/core/websocket/types.d.ts +1 -1
  92. package/dist/types/services/index.d.ts +1 -1
  93. package/dist/types/services/task/Task.d.ts +157 -0
  94. package/dist/types/services/task/TaskFactory.d.ts +12 -0
  95. package/dist/types/services/task/TaskUtils.d.ts +46 -2
  96. package/dist/types/services/task/constants.d.ts +5 -0
  97. package/dist/types/services/task/digital/Digital.d.ts +22 -0
  98. package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +1144 -0
  99. package/dist/types/services/task/state-machine/actions.d.ts +10 -0
  100. package/dist/types/services/task/state-machine/constants.d.ts +107 -0
  101. package/dist/types/services/task/state-machine/guards.d.ts +90 -0
  102. package/dist/types/services/task/state-machine/index.d.ts +13 -0
  103. package/dist/types/services/task/state-machine/types.d.ts +267 -0
  104. package/dist/types/services/task/state-machine/uiControlsComputer.d.ts +9 -0
  105. package/dist/types/services/task/taskDataNormalizer.d.ts +10 -0
  106. package/dist/types/services/task/types.d.ts +551 -78
  107. package/dist/types/services/task/voice/Voice.d.ts +184 -0
  108. package/dist/types/services/task/voice/WebRTC.d.ts +53 -0
  109. package/dist/types/types.d.ts +92 -0
  110. package/dist/types/webex.d.ts +1 -0
  111. package/dist/types.js +85 -0
  112. package/dist/types.js.map +1 -1
  113. package/dist/webex.js +14 -2
  114. package/dist/webex.js.map +1 -1
  115. package/package.json +15 -12
  116. package/src/cc.ts +63 -43
  117. package/src/config.ts +6 -0
  118. package/src/constants.ts +14 -1
  119. package/src/index.ts +14 -5
  120. package/src/metrics/ai-docs/AGENTS.md +348 -0
  121. package/src/metrics/ai-docs/ARCHITECTURE.md +336 -0
  122. package/src/metrics/behavioral-events.ts +28 -0
  123. package/src/metrics/constants.ts +9 -4
  124. package/src/services/ApiAiAssistant.ts +104 -3
  125. package/src/services/agent/ai-docs/AGENTS.md +238 -0
  126. package/src/services/agent/ai-docs/ARCHITECTURE.md +302 -0
  127. package/src/services/ai-docs/AGENTS.md +384 -0
  128. package/src/services/config/Util.ts +2 -2
  129. package/src/services/config/ai-docs/AGENTS.md +253 -0
  130. package/src/services/config/ai-docs/ARCHITECTURE.md +424 -0
  131. package/src/services/config/types.ts +116 -10
  132. package/src/services/core/Utils.ts +85 -34
  133. package/src/services/core/ai-docs/AGENTS.md +379 -0
  134. package/src/services/core/ai-docs/ARCHITECTURE.md +696 -0
  135. package/src/services/core/websocket/WebSocketManager.ts +2 -0
  136. package/src/services/core/websocket/types.ts +1 -1
  137. package/src/services/index.ts +1 -1
  138. package/src/services/task/Task.ts +837 -0
  139. package/src/services/task/TaskFactory.ts +55 -0
  140. package/src/services/task/TaskManager.ts +738 -697
  141. package/src/services/task/TaskUtils.ts +205 -25
  142. package/src/services/task/ai-docs/AGENTS.md +455 -0
  143. package/src/services/task/ai-docs/ARCHITECTURE.md +585 -0
  144. package/src/services/task/constants.ts +5 -0
  145. package/src/services/task/digital/Digital.ts +95 -0
  146. package/src/services/task/state-machine/TaskStateMachine.ts +1077 -0
  147. package/src/services/task/state-machine/actions.ts +685 -0
  148. package/src/services/task/state-machine/ai-docs/AGENTS.md +495 -0
  149. package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +1135 -0
  150. package/src/services/task/state-machine/constants.ts +172 -0
  151. package/src/services/task/state-machine/guards.ts +406 -0
  152. package/src/services/task/state-machine/index.ts +28 -0
  153. package/src/services/task/state-machine/types.ts +241 -0
  154. package/src/services/task/state-machine/uiControlsComputer.ts +867 -0
  155. package/src/services/task/taskDataNormalizer.ts +137 -0
  156. package/src/services/task/types.ts +654 -85
  157. package/src/services/task/voice/Voice.ts +1267 -0
  158. package/src/services/task/voice/WebRTC.ts +187 -0
  159. package/src/types.ts +112 -1
  160. package/src/utils/AGENTS.md +276 -0
  161. package/src/webex.js +2 -0
  162. package/test/unit/spec/cc.ts +133 -3
  163. package/test/unit/spec/logger-proxy.ts +70 -0
  164. package/test/unit/spec/services/ApiAiAssistant.ts +122 -17
  165. package/test/unit/spec/services/WebCallingService.ts +7 -1
  166. package/test/unit/spec/services/config/index.ts +27 -27
  167. package/test/unit/spec/services/core/Utils.ts +335 -1
  168. package/test/unit/spec/services/core/websocket/WebSocketManager.ts +66 -40
  169. package/test/unit/spec/services/task/AutoWrapup.ts +63 -0
  170. package/test/unit/spec/services/task/Task.ts +477 -0
  171. package/test/unit/spec/services/task/TaskFactory.ts +62 -0
  172. package/test/unit/spec/services/task/TaskManager.ts +821 -1936
  173. package/test/unit/spec/services/task/TaskUtils.ts +206 -0
  174. package/test/unit/spec/services/task/digital/Digital.ts +105 -0
  175. package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +1825 -0
  176. package/test/unit/spec/services/task/state-machine/guards.ts +479 -0
  177. package/test/unit/spec/services/task/state-machine/types.ts +18 -0
  178. package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +2020 -0
  179. package/test/unit/spec/services/task/taskTestUtils.ts +87 -0
  180. package/test/unit/spec/services/task/voice/Voice.ts +631 -0
  181. package/test/unit/spec/services/task/voice/WebRTC.ts +235 -0
  182. package/umd/contact-center.min.js +2 -2
  183. package/umd/contact-center.min.js.map +1 -1
  184. package/dist/services/task/index.js +0 -1530
  185. package/dist/services/task/index.js.map +0 -1
  186. package/dist/types/services/task/index.d.ts +0 -650
  187. package/src/services/task/index.ts +0 -1806
  188. package/test/unit/spec/services/task/index.ts +0 -2205
@@ -185,7 +185,7 @@ function parseAgentConfigs(profileData: {
185
185
 
186
186
  const defaultWrapUpData = getDefaultWrapUpCode(wrapupCodes);
187
187
  const aiFeature: AIFeatureFlags | undefined =
188
- aiFeatureFlags?.data && aiFeatureFlags.data.length > 0 ? aiFeatureFlags.data[0] : undefined;
188
+ aiFeatureFlags?.data?.length > 0 ? aiFeatureFlags.data[0] : undefined;
189
189
 
190
190
  const finalData = {
191
191
  teams: teamData,
@@ -233,7 +233,7 @@ function parseAgentConfigs(profileData: {
233
233
  isAgentAvailableAfterOutdial: agentProfileData.agentAvailableAfterOutdial,
234
234
  outDialEp: agentProfileData.outdialEntryPointId,
235
235
  isCampaignManagementEnabled: orgSettingsData.campaignManagerEnabled,
236
- isEndCallEnabled: tenantData.endCallEnabled,
236
+ isEndTaskEnabled: tenantData.endCallEnabled,
237
237
  isEndConsultEnabled: tenantData.endConsultEnabled,
238
238
  callVariablesSuppressed: tenantData.callVariablesSuppressed,
239
239
  agentDbId: userData.dbId,
@@ -0,0 +1,253 @@
1
+ # Config Service - AI Agent Guide
2
+
3
+ > **Purpose**: Fetch and aggregate agent configuration data from multiple API endpoints to build the AgentProfile.
4
+ >
5
+ > **Scope Authority**: This is the authoritative documentation for the **Config** service scope. See [Root AGENTS.md](../../../../AGENTS.md) for the orchestrator and cross-scope rules.
6
+
7
+ ---
8
+
9
+ ## Overview
10
+
11
+ The Config Service is an **internal service** that builds the comprehensive AgentProfile (`Profile` type) by:
12
+ 1. Fetching user data
13
+ 2. Fetching desktop profile
14
+ 3. Fetching teams
15
+ 4. Fetching aux codes (idle/wrapup codes)
16
+ 5. Fetching organization settings
17
+ 6. Aggregating all data into a single AgentProfile
18
+
19
+ The AgentProfile is the central configuration object required for an agent to operate within the contact center. It is built during the registration flow (`cc.register()`) and contains all the data an agent needs: identity, team assignments, dial plans, aux codes, login options, and feature flags. Once constructed, the AgentProfile is stored on the `ContactCenter` plugin instance as `this.agentConfig` and is used by other services (Agent, Task) throughout the session.
20
+
21
+
22
+ ---
23
+
24
+ ## File Structure
25
+
26
+ ```
27
+ services/config/
28
+ ├── index.ts # AgentConfigService class
29
+ ├── types.ts # Profile, CC_EVENTS, types
30
+ ├── constants.ts # API endpoints, defaults
31
+ ├── Util.ts # parseAgentConfigs helper
32
+ └── ai-docs/
33
+ ├── AGENTS.md # Usage documentation
34
+ └── ARCHITECTURE.md # This file
35
+ ```
36
+
37
+ ---
38
+
39
+ ## Quick Usage
40
+
41
+ ```typescript
42
+ // Config service is used internally during the registration flow.
43
+ // Inside cc.ts → connectWebsocket(), after WebSocket connection is established:
44
+ const agentId = data.agentId;
45
+ const orgId = this.$webex.credentials.getOrgId();
46
+ this.agentConfig = await this.services.config.getAgentConfig(orgId, agentId);
47
+
48
+ // The returned AgentProfile contains all agent configuration:
49
+ LoggerProxy.info(`Agent ID: ${this.agentConfig.agentId}`, {
50
+ module: 'cc',
51
+ method: 'connectWebsocket',
52
+ });
53
+ LoggerProxy.info(`Teams: ${this.agentConfig.teams}`, {
54
+ module: 'cc',
55
+ method: 'connectWebsocket',
56
+ });
57
+ ```
58
+
59
+ ---
60
+
61
+ ## Key Capabilities
62
+
63
+ - **AgentProfile Aggregation**: Combines data from 8+ API endpoints
64
+ - **Aux Codes Fetching**: Gets all idle and wrapup codes with pagination
65
+ - **Team Data**: Retrieves agent's team assignments
66
+ - **Dial Plan**: Fetches number transformation rules
67
+ - **Outdial ANI**: Retrieves outbound caller ID options (standalone, publicly exposed via `cc.ts`)
68
+ - **Multimedia Profile**: Fetches channel capacity and blending config (standalone, not yet publicly exposed)
69
+ - **Paginated Data Access**: `getListOfTeams` and `getListOfAuxCodes` support custom pagination independent of profile building
70
+
71
+ ---
72
+
73
+ ## AgentProfile Object (Key Fields)
74
+
75
+ The AgentProfile is defined as the [`Profile`](../types.ts) type. This is not an exhaustive list — see [`types.ts`](../types.ts) for the full 50+ field definition. Key fields:
76
+
77
+ | Field | Type | Description |
78
+ |-------|------|-------------|
79
+ | `agentId` | string | Unique agent identifier |
80
+ | `agentName` | string | Display name |
81
+ | `agentMailId` | string | Email address |
82
+ | `teams` | [`TeamList[]`](../types.ts) | Assigned teams (runtime data from `getAllTeams()` — `Profile` type declares `Team[]` but actual objects are `TeamList` with `id`, `name`, `teamType`, `siteId`, etc.) |
83
+ | `defaultDn` | string | Default dial number |
84
+ | `idleCodes` | [`Entity[]`](../types.ts) | Available idle codes |
85
+ | `wrapupCodes` | [`Entity[]`](../types.ts) | Available wrapup codes |
86
+ | `webRtcEnabled` | boolean | WebRTC calling enabled |
87
+ | `loginVoiceOptions` | [`LoginOption[]`](../types.ts) | Available login types |
88
+ | `dialPlan` | [`DialPlan`](../types.ts) | Number transformation rules |
89
+ | `isOutboundEnabledForAgent` | boolean | Outbound calling allowed |
90
+ | `outDialEp` | string | Outbound entry point ID |
91
+
92
+ ---
93
+
94
+ ## Data Aggregation Flow
95
+
96
+ The following diagram shows how `getAgentConfig` orchestrates multiple API calls and combines their results into the AgentProfile via `parseAgentConfigs()`:
97
+
98
+ ```
99
+ getUserUsingCI ────────────┐
100
+
101
+ getOrgInfo ────────────────┤
102
+
103
+ getOrganizationSetting ────┤
104
+
105
+ getTenantData ─────────────┤
106
+
107
+ getURLMapping ─────────────┼──► parseAgentConfigs() ──► AgentProfile
108
+
109
+ getAllAuxCodes ─────────────┤
110
+
111
+ getDesktopProfileById ─────┤
112
+
113
+ getSiteInfo ───────────────┤ (computes multimediaProfileId)
114
+
115
+ getAllTeams ────────────────┤
116
+
117
+ getDialPlanData ───────────┘
118
+ ```
119
+
120
+ ---
121
+
122
+ ## API Methods (Internal)
123
+
124
+ ### `getAgentConfig(orgId, agentId)`
125
+
126
+ Main method that aggregates all configuration data into the AgentProfile.
127
+
128
+ **Returns**: `Promise<Profile>`
129
+
130
+ **Flow**:
131
+ 1. Fetch user data (`getUserUsingCI`)
132
+ 2. Fetch org info (`getOrgInfo`), settings (`getOrganizationSetting`), tenant data (`getTenantData`) in parallel
133
+ 3. Fetch aux codes with pagination (`getAllAuxCodes`)
134
+ 4. Fetch desktop profile (`getDesktopProfileById`), site info (`getSiteInfo`)
135
+ 5. Fetch dial plan if enabled (`getDialPlanData`)
136
+ 6. Fetch teams (`getAllTeams`)
137
+ 7. Parse and combine all data (`parseAgentConfigs`)
138
+
139
+ ---
140
+
141
+ ## Standalone APIs (Not Part of AgentProfile Building)
142
+
143
+ These methods exist in `AgentConfigService` but are **not** part of the `getAgentConfig()` aggregation flow. They can be used independently by applications.
144
+
145
+ | Method | Status | Returns | Description |
146
+ |--------|--------|---------|-------------|
147
+ | `getOutdialAniEntries(orgId, params)` | **Publicly exposed** via `cc.getOutdialAniEntries()` | `OutdialAniEntriesResponse` | Fetch outbound ANI entries for caller ID selection. Supports pagination and search via [`OutdialAniParams`](../types.ts). |
148
+ | `getMultimediaProfileById(orgId, multimediaProfileId)` | **Not exposed, never called** | `MultimediaProfileResponse` | Fetch channel capacities (chat, email, telephony, social) and blending config. Available but unused anywhere. |
149
+ | `getListOfTeams(orgId, page, pageSize, filter)` | Used internally by `getAllTeams()` | `ListTeamsResponse` | Single-page team fetch with pagination metadata. Useful for custom pagination. |
150
+ | `getListOfAuxCodes(orgId, page, pageSize, filter, attributes)` | Used internally by `getAllAuxCodes()` | `ListAuxCodesResponse` | Single-page aux code fetch with pagination metadata. Useful for custom pagination. |
151
+
152
+ Additionally, the following endpoints are defined in `constants.ts` `endPointMap` but are consumed by separate service classes, not by `AgentConfigService`:
153
+
154
+ | Endpoint | Used By | Description |
155
+ |----------|---------|-------------|
156
+ | `queueList` | [`Queue.ts`](../../Queue.ts) | Fetch contact service queues |
157
+ | `entryPointList` | [`EntryPoint.ts`](../../EntryPoint.ts) | Fetch entry points |
158
+ | `addressBookEntries` | [`AddressBook.ts`](../../AddressBook.ts) | Fetch address book entries |
159
+
160
+ ---
161
+
162
+ ## Key Types
163
+
164
+ Types used by the config service, all defined in [`types.ts`](../types.ts):
165
+
166
+ | Type | Description |
167
+ |------|-------------|
168
+ | `Profile` | Final aggregated agent config returned by `getAgentConfig()` |
169
+ | `AgentResponse` | Raw response from `getUserUsingCI()` — agent metadata, teamIds, siteId, agentProfileId |
170
+ | `DesktopProfileResponse` | Desktop profile settings — layout, dial plan, login options |
171
+ | `TeamList` | Team record from API — `id`, `name`, `teamType`, `siteId`, `multiMediaProfileId` |
172
+ | `ListTeamsResponse` | Paginated wrapper around `TeamList[]` with `meta` for pagination |
173
+ | `OrgInfo` | Organization info — `tenantId`, timezone |
174
+ | `OrgSettings` | Org feature flags — `webRtcEnabled`, `sensitiveDataMaskingEnabled` |
175
+ | `TenantData` | Tenant-level config — inactivity timeout, `forceDefaultDn`, `outdialEnabled` |
176
+ | `SiteInfo` | Site config — `id`, `name`, `multimediaProfileId` |
177
+ | `URLMapping` | External URL mapping — `id`, `name`, `url` |
178
+ | `MultimediaProfileResponse` | Multimedia profile — channel capacities and settings |
179
+ | `AuxCode` | Auxiliary code record — `id`, `name`, `description`, `workTypeCode` |
180
+ | `ListAuxCodesResponse` | Paginated wrapper around `AuxCode[]` with `meta` |
181
+ | `DialPlanEntity` | Dial plan rule — regex pattern, prefix, strip digits |
182
+ | `Entity` | Basic entity info — `isSystem`, `name`, `id`, `description` |
183
+ | `WrapupData` | Wrap-up config — auto-wrapup settings, available wrapup codes |
184
+ | `OutdialAniParams` | Parameters for `getOutdialAniEntries()` — ANI ID, pagination, filtering |
185
+ | `Team` | Simplified team shape in `Profile` — `teamId`, `teamName`, `desktopLayoutId` |
186
+
187
+ ## Events (CC_EVENTS)
188
+
189
+ The config service defines event constants used throughout the SDK:
190
+
191
+ | Event Category | Examples |
192
+ |----------------|----------|
193
+ | Agent Events | WELCOME, AGENT_LOGOUT, AGENT_STATE_CHANGE |
194
+ | Task Events | AGENT_CONTACT, AGENT_OFFER_CONTACT, CONTACT_ENDED |
195
+ | Login Events | AGENT_STATION_LOGIN_SUCCESS, AGENT_STATION_LOGIN_FAILED |
196
+
197
+ See [`types.ts`](../types.ts) for complete list.
198
+
199
+ ---
200
+
201
+ ## Types Defined
202
+
203
+ Key types in `services/config/types.ts`:
204
+
205
+ | Type | Description |
206
+ |------|-------------|
207
+ | `Profile` | Complete AgentProfile |
208
+ | `CC_EVENTS` | All event constants |
209
+ | `CC_AGENT_EVENTS` | Agent-specific events |
210
+ | `CC_TASK_EVENTS` | Task-specific events |
211
+ | `AuxCode` | Idle/wrapup code definition |
212
+ | `Team` | Team configuration |
213
+ | `DesktopProfileResponse` | Desktop profile settings |
214
+ | `LoginOption` | Login types (BROWSER, EXTENSION, AGENT_DN) |
215
+
216
+ ---
217
+
218
+ ## Error Handling
219
+
220
+ All API methods within the config service throw errors on failure. Since `getAgentConfig` calls multiple sub-APIs (`getUserUsingCI`, `getOrgInfo`, `getOrganizationSetting`, `getTenantData`, `getAllAuxCodes`, `getDesktopProfileById`, `getAllTeams`, `getDialPlanData`, etc.) and awaits them via `Promise.all`, **a failure in any single sub-API will cause the entire AgentProfile fetch to fail**. There is no partial profile — either all data is successfully fetched and aggregated, or the operation throws.
221
+
222
+ ```typescript
223
+ try {
224
+ const profile = await this.services.config.getAgentConfig(orgId, agentId);
225
+ } catch (error) {
226
+ LoggerProxy.error(`Config fetch failed: ${error}`, {
227
+ module: 'ConfigService',
228
+ method: 'getAgentConfig',
229
+ });
230
+ throw error;
231
+ }
232
+ ```
233
+
234
+ ---
235
+
236
+ ## Usage in cc.ts
237
+
238
+ ```typescript
239
+ // In register() -> connectWebsocket()
240
+ const agentId = data.agentId;
241
+ const orgId = this.$webex.credentials.getOrgId();
242
+ this.agentConfig = await this.services.config.getAgentConfig(orgId, agentId);
243
+ ```
244
+
245
+ ---
246
+
247
+ ## Related
248
+
249
+ - [Root AGENTS.md](../../../../AGENTS.md) - Orchestrator and cross-scope rules
250
+ - [ARCHITECTURE.md](ARCHITECTURE.md) - Technical deep-dive
251
+ - [types.ts](../types.ts) - Type definitions
252
+ - [Util.ts](../Util.ts) - AgentProfile parsing utilities
253
+ - [constants.ts](../constants.ts) - API endpoints
@@ -0,0 +1,424 @@
1
+ # Config Service - Architecture
2
+
3
+ > **Purpose**: Technical documentation for agent configuration aggregation.
4
+
5
+ ---
6
+
7
+ ## Component Overview
8
+
9
+ | Component | File | Responsibility |
10
+ |-----------|------|----------------|
11
+ | `AgentConfigService` | `config/index.ts` | Main config service class |
12
+ | `parseAgentConfigs` | `config/Util.ts` | Profile parsing/aggregation |
13
+ | `endPointMap` | `config/constants.ts` | API endpoint definitions |
14
+ | `types` | `config/types.ts` | Types, events, interfaces |
15
+
16
+ ---
17
+
18
+ ## Data Flow
19
+
20
+ ```mermaid
21
+ sequenceDiagram
22
+ participant CC as ContactCenter
23
+ participant Cfg as AgentConfigService
24
+ participant WR as WebexRequest
25
+ participant API as Backend APIs
26
+
27
+ CC->>Cfg: getAgentConfig(orgId, agentId)
28
+
29
+ par Wave 1 — fire immediately
30
+ Cfg->>WR: getUserUsingCI
31
+ Cfg->>WR: getOrgInfo
32
+ Cfg->>WR: getOrganizationSetting
33
+ Cfg->>WR: getTenantData
34
+ Cfg->>WR: getURLMapping
35
+ Cfg->>WR: getAllAuxCodes
36
+ end
37
+
38
+ WR->>API: 6 parallel API calls
39
+ API-->>WR: Responses
40
+ Note over Cfg: await userConfigData (needed for wave 2)
41
+
42
+ par Wave 2 — depends on userConfigData
43
+ Cfg->>WR: getDesktopProfileById(agentProfileId)
44
+ Cfg->>WR: getSiteInfo(siteId)
45
+ Cfg->>WR: getAllTeams(teamIds)
46
+ end
47
+
48
+ Note over Cfg: getDialPlanData chained off agentProfile<br/>(fires only if dialPlanEnabled)
49
+
50
+ Note over Cfg: Single Promise.all() awaits all 9 promises<br/>(wave 1 + wave 2 + conditional dialPlan)
51
+
52
+ WR->>API: Remaining API calls
53
+ API-->>WR: Responses
54
+
55
+ Cfg->>Cfg: parseAgentConfigs(allData)
56
+ Cfg-->>CC: Profile
57
+ ```
58
+
59
+ ---
60
+
61
+ ## API Endpoints
62
+
63
+ The config service uses multiple API endpoints to fetch agent configuration data. These endpoints are defined in `constants.ts` and include:
64
+
65
+ - **Core user data**: User profile, agent settings, site information
66
+ - **Team & organization**: Team memberships, organization settings, tenant configuration
67
+ - **Auxiliary codes**: Idle codes and wrap-up codes with pagination
68
+ - **Communication settings**: Dial plans, URL mappings, multimedia profiles
69
+ - **Outbound features**: Queue lists, entry points, address books, outdial ANI entries
70
+
71
+ ### Endpoint Definitions
72
+
73
+ All endpoints are relative to the WCC API Gateway base URL. Query parameters like `agentView=true` filter responses to agent-relevant data.
74
+
75
+ **Example Usage:**
76
+ ```typescript
77
+ // Fetch user data
78
+ const resource = endPointMap.userByCI('org-123', 'agent-456');
79
+ // Result: "organization/org-123/user/by-ci-user-id/agent-456"
80
+
81
+ // Fetch teams with pagination and filtering
82
+ const resource = endPointMap.listTeams('org-123', 0, 100, ['team-1', 'team-2']);
83
+ // Result: "organization/org-123/v2/team?page=0&pageSize=100&filter=id=in=(team-1,team-2)"
84
+
85
+ // Fetch organization settings
86
+ const resource = endPointMap.orgSettings('org-123');
87
+ // Result: "organization/org-123/v2/organization-setting?agentView=true"
88
+ ```
89
+
90
+ **Full Endpoint Map:**
91
+ ```typescript
92
+ export const endPointMap = {
93
+ userByCI: (orgId: string, agentId: string) =>
94
+ `organization/${orgId}/user/by-ci-user-id/${agentId}`,
95
+
96
+ desktopProfile: (orgId: string, desktopProfileId: string) =>
97
+ `organization/${orgId}/agent-profile/${desktopProfileId}`,
98
+
99
+ multimediaProfile: (orgId: string, multimediaProfileId: string) =>
100
+ `organization/${orgId}/multimedia-profile/${multimediaProfileId}`,
101
+
102
+ listTeams: (orgId: string, page: number, pageSize: number, filter: string[]) =>
103
+ `organization/${orgId}/v2/team?page=${page}&pageSize=${pageSize}${
104
+ filter && filter.length > 0 ? `&filter=id=in=(${filter})` : ''
105
+ }`,
106
+
107
+ listAuxCodes: (orgId: string, page: number, pageSize: number, filter: string[], attributes: string[]) =>
108
+ `organization/${orgId}/v2/auxiliary-code?page=${page}&pageSize=${pageSize}${
109
+ filter && filter.length > 0 ? `&filter=id=in=(${filter})` : ''
110
+ }&attributes=${attributes}`,
111
+
112
+ orgInfo: (orgId: string) =>
113
+ `organization/${orgId}`,
114
+
115
+ orgSettings: (orgId: string) =>
116
+ `organization/${orgId}/v2/organization-setting?agentView=true`,
117
+
118
+ siteInfo: (orgId: string, siteId: string) =>
119
+ `organization/${orgId}/site/${siteId}`,
120
+
121
+ tenantData: (orgId: string) =>
122
+ `organization/${orgId}/v2/tenant-configuration?agentView=true`,
123
+
124
+ urlMapping: (orgId: string) =>
125
+ `organization/${orgId}/v2/org-url-mapping?sort=name,ASC`,
126
+
127
+ dialPlan: (orgId: string) =>
128
+ `organization/${orgId}/dial-plan?agentView=true`,
129
+
130
+ queueList: (orgId: string, queryParams: string) =>
131
+ `/organization/${orgId}/v2/contact-service-queue?${queryParams}`,
132
+
133
+ entryPointList: (orgId: string, queryParams: string) =>
134
+ `/organization/${orgId}/v2/entry-point?${queryParams}`,
135
+
136
+ addressBookEntries: (orgId: string, addressBookId: string, queryParams: string) =>
137
+ `/organization/${orgId}/v2/address-book/${addressBookId}/entry?${queryParams}`,
138
+
139
+ outdialAniEntries: (orgId: string, outdialANI: string, queryParams: string) =>
140
+ `organization/${orgId}/v2/outdial-ani/${outdialANI}/entry${
141
+ queryParams ? `?${queryParams}` : ''
142
+ }`,
143
+ };
144
+ ```
145
+
146
+ ---
147
+
148
+ ## Pagination Pattern
149
+
150
+ For endpoints with pagination (teams, aux codes):
151
+
152
+ ```typescript
153
+ import {DEFAULT_PAGE} from './constants'; // DEFAULT_PAGE = 0
154
+
155
+ public async getAllTeams(orgId, pageSize, filter): Promise<TeamList[]> {
156
+ let allTeams: TeamList[] = [];
157
+ let page = DEFAULT_PAGE;
158
+
159
+ // First request to get totalPages
160
+ const firstResponse = await this.getListOfTeams(orgId, page, pageSize, filter);
161
+ allTeams = allTeams.concat(firstResponse.data);
162
+ const totalPages = firstResponse.meta.totalPages;
163
+
164
+ // Parallel requests for remaining pages
165
+ const requests = [];
166
+ for (page = DEFAULT_PAGE + 1; page < totalPages; page += 1) {
167
+ requests.push(this.getListOfTeams(orgId, page, pageSize, filter));
168
+ }
169
+
170
+ const responses = await Promise.all(requests);
171
+ for (const response of responses) {
172
+ allTeams = allTeams.concat(response.data);
173
+ }
174
+
175
+ return allTeams;
176
+ }
177
+ ```
178
+
179
+ ---
180
+
181
+ ## Profile Parsing
182
+
183
+ `parseAgentConfigs` in Util.ts combines all data into a unified `Profile` object. See [types.ts](../types.ts) for full type definitions.
184
+
185
+ ### API Response Structures
186
+
187
+ The service fetches data from multiple APIs with these response structures:
188
+
189
+ | API Method | Response Type | Key Fields | Usage |
190
+ |------------|---------------|------------|-------|
191
+ | `getUserUsingCI` | `AgentResponse` | `ciUserId`, `id`, `firstName`, `lastName`, `email`, `teamIds`, `agentProfileId`, `siteId` | Primary agent identity and profile references |
192
+ | `getDesktopProfileById` | `DesktopProfileResponse` | `dialPlanEnabled`, `autoAnswer`, `accessWrapUpCode`, `wrapUpCodes`, `accessIdleCode`, `idleCodes`, `loginVoiceOptions` | Agent desktop settings and feature enablement |
193
+ | `getAllTeams` | `TeamList[]` | `id`, `name`, `type`, `channelMap` (+ 10 more fields) | Full team details with channel configurations |
194
+ | `getTenantData` | `TenantData` | `outdialEnabled`, `forceDefaultDn`, `privacyShieldVisible`, `timeoutDesktopInactivityEnabled` | Tenant-level feature flags |
195
+ | `getOrgInfo` | `OrgInfo` | `tenantId`, `timezone` | Organization metadata |
196
+ | `getAllAuxCodes` | `AuxCode[]` | `id`, `name`, `workTypeCode`, `active`, `isSystemCode`, `defaultCode` | Auxiliary codes for idle/wrap-up states |
197
+ | `getOrganizationSetting` | `OrgSettings` | `webRtcEnabled`, `maskSensitiveData`, `campaignManagerEnabled` | Organization-level feature flags |
198
+ | `getDialPlanData` | `DialPlanEntity[]` | `id`, `name`, `regularExpression`, `prefix`, `strippedChars` | Dial plan rules for outbound calling |
199
+ | `getURLMapping` | `URLMapping[]` | `name`, `url` | External service URL mappings |
200
+ | `getSiteInfo` | `SiteInfo` | Site-specific configuration | Site details |
201
+
202
+ These responses are parsed and aggregated into a single `Profile` object by the `parseAgentConfigs` function.
203
+
204
+ ### Profile Aggregation Function
205
+
206
+ ```typescript
207
+ // See full implementation in Util.ts
208
+ function parseAgentConfigs(profileData: {
209
+ userData: AgentResponse; // See types.ts:AgentResponse
210
+ teamData: Team[]; // NOTE: Declared as Team[] (teamId, teamName) but receives TeamList[] (id, name, + 12 more fields) at runtime
211
+ tenantData: TenantData; // See types.ts:TenantData
212
+ orgInfoData: OrgInfo; // See types.ts:OrgInfo
213
+ auxCodes: AuxCode[]; // See types.ts:AuxCode
214
+ orgSettingsData: OrgSettings; // See types.ts:OrgSettings
215
+ agentProfileData: DesktopProfileResponse; // See types.ts:DesktopProfileResponse
216
+ dialPlanData: DialPlanEntity[]; // See types.ts:DialPlanEntity
217
+ urlMapping: URLMapping[]; // See types.ts:URLMapping
218
+ multimediaProfileId: string;
219
+ }): Profile { // See types.ts:Profile
220
+ const { userData, teamData, tenantData, orgInfoData, auxCodes,
221
+ orgSettingsData, agentProfileData, dialPlanData, urlMapping } = profileData;
222
+
223
+ // Aux code filtering via getFilterAuxCodes():
224
+ // - checks auxCode.active
225
+ // - checks specificCodes access level (ALL → no filter, SPECIFIC → include list)
226
+ // - maps to Entity {id, name, isSystem, isDefault}
227
+ const wrapupCodes = getFilterAuxCodes(auxCodes, WRAP_UP_CODE,
228
+ agentProfileData.accessWrapUpCode === 'ALL' ? [] : agentProfileData.wrapUpCodes);
229
+ const idleCodes = getFilterAuxCodes(auxCodes, IDLE_CODE,
230
+ agentProfileData.accessIdleCode === 'ALL' ? [] : agentProfileData.idleCodes);
231
+
232
+ // Hardcoded "Available" state always appended to idle codes
233
+ idleCodes.push({ id: '0', name: 'Available', isSystem: false, isDefault: false });
234
+
235
+ return {
236
+ agentId: userData.ciUserId, // NOTE: uses ciUserId for agent identification
237
+ analyserUserId: userData.id, // NOTE: userData.id is used for analytics/reporting
238
+ agentName: `${userData.firstName} ${userData.lastName}`,
239
+ teams: teamData, // NOTE: Raw TeamList[] passed directly without mapping
240
+ idleCodes, // NOTE: Filtered via getFilterAuxCodes() + hardcoded "Available" state
241
+ wrapupCodes, // NOTE: Filtered via getFilterAuxCodes()
242
+ webRtcEnabled: orgSettingsData.webRtcEnabled,
243
+ loginVoiceOptions: agentProfileData.loginVoiceOptions ?? [],
244
+ enterpriseId: orgInfoData.tenantId,
245
+ tenantTimezone: orgInfoData.timezone,
246
+ multimediaProfileId: profileData.multimediaProfileId,
247
+ // ... 30+ more fields — see Util.ts:184-258 for full implementation
248
+ };
249
+ }
250
+ ```
251
+
252
+ ---
253
+
254
+ ## Error Handling
255
+
256
+ Each method follows consistent error handling:
257
+
258
+ ```typescript
259
+ public async getUserUsingCI(orgId: string, agentId: string): Promise<AgentResponse> {
260
+ LoggerProxy.info('Fetching user data using CI', {
261
+ module: CONFIG_FILE_NAME,
262
+ method: METHODS.GET_USER_USING_CI,
263
+ });
264
+
265
+ try {
266
+ const resource = endPointMap.userByCI(orgId, agentId);
267
+ const response = await this.webexReq.request({
268
+ service: WCC_API_GATEWAY,
269
+ resource,
270
+ method: HTTP_METHODS.GET,
271
+ });
272
+
273
+ if (response.statusCode !== 200) {
274
+ throw new Error(`API call failed with ${response.statusCode}`);
275
+ }
276
+
277
+ LoggerProxy.log('getUserUsingCI api success.', {
278
+ module: CONFIG_FILE_NAME,
279
+ method: METHODS.GET_USER_USING_CI,
280
+ });
281
+
282
+ return Promise.resolve(response.body);
283
+ } catch (error) {
284
+ LoggerProxy.error(`getUserUsingCI API call failed with ${error}`, {
285
+ module: CONFIG_FILE_NAME,
286
+ method: METHODS.GET_USER_USING_CI,
287
+ });
288
+ throw error;
289
+ }
290
+ }
291
+ ```
292
+
293
+ ---
294
+
295
+ ## Troubleshooting
296
+
297
+ ### Common Issues and Log Patterns
298
+
299
+ #### Issue: Profile incomplete or getAgentConfig fails
300
+
301
+ **Cause**: One of the parallel API calls failed (network error, 401/403/404/500 response)
302
+
303
+ **Log patterns to search for:**
304
+ ```typescript
305
+ // General config failure
306
+ "getAgentConfig call failed"
307
+ "module": "config/index.ts", "method": "getAgentConfig"
308
+
309
+ // Specific API method failures
310
+ "getUserUsingCI API call failed"
311
+ "getDesktopProfileById API call failed"
312
+ "getAllTeams API call failed"
313
+ "getAllAuxCodes API call failed"
314
+
315
+ // Look for HTTP error codes
316
+ "API call failed with 401" // Authentication
317
+ "API call failed with 403" // Authorization
318
+ "API call failed with 404" // Not found
319
+ "API call failed with 500" // Server error
320
+ ```
321
+
322
+ **Solution**:
323
+ 1. Check logs for specific API that failed
324
+ 2. Verify orgId and agentId are correct
325
+ 3. Ensure authentication tokens are valid
326
+ 4. Check network connectivity to WCC API Gateway
327
+
328
+ #### Issue: Empty teams or aux codes
329
+
330
+ **Cause**: Pagination not completing or filter parameters incorrect
331
+
332
+ **Log patterns:**
333
+ ```typescript
334
+ "getAllTeams API call failed"
335
+ "getAllAuxCodes API call failed"
336
+ "method": "getListOfTeams"
337
+ "method": "getListOfAuxCodes"
338
+ ```
339
+
340
+ **Solution**:
341
+ 1. Check `totalPages` in first response
342
+ 2. Verify filter array contains valid team/aux code IDs
343
+ 3. Check if pageSize is appropriate (default: 100)
344
+ 4. Ensure all pages are fetched in Promise.all()
345
+
346
+ #### Issue: WebRTC or other features not enabled
347
+
348
+ **Cause**: Organization or tenant settings have feature disabled
349
+
350
+ **Log patterns:**
351
+ ```typescript
352
+ "getOrganizationSetting api success"
353
+ "getTenantData api success"
354
+ ```
355
+
356
+ **Solution**:
357
+ 1. Check `orgSettingsData.webRtcEnabled` in response
358
+ 2. Check `tenantData.outdialEnabled` for outbound features
359
+ 3. Verify feature is enabled in admin portal settings
360
+ 4. Confirm agentProfileData has correct feature flags
361
+
362
+ #### Issue: Missing dial plan data
363
+
364
+ **Cause**: `dialPlanEnabled` is false in desktop profile
365
+
366
+ **Solution**:
367
+ 1. Check `agentProfileData.dialPlanEnabled` value
368
+ 2. Verify dial plans are assigned in agent profile configuration
369
+ 3. Note: dial plan fetch only happens if `dialPlanEnabled === true`
370
+
371
+ #### Issue: Incorrect auxiliary code filtering
372
+
373
+ **Cause**: Access level set to 'SPECIFIC' but missing code IDs
374
+
375
+ **Log patterns:**
376
+ ```typescript
377
+ "method": "getFilterAuxCodes"
378
+ ```
379
+
380
+ **Solution**:
381
+ 1. Check `agentProfileData.accessWrapUpCode` (should be 'ALL' or 'SPECIFIC')
382
+ 2. Check `agentProfileData.accessIdleCode`
383
+ 3. If 'SPECIFIC', verify `wrapUpCodes` and `idleCodes` arrays contain valid IDs
384
+ 4. Ensure aux codes have `active: true` status
385
+ 5. Note: "Available" state is always appended to idle codes
386
+
387
+ ---
388
+
389
+ ## Types and Events
390
+
391
+ The config service defines comprehensive TypeScript types for all data structures. See [types.ts](../types.ts) for complete definitions.
392
+
393
+ ### Core Types
394
+
395
+ **Configuration Types:**
396
+ - `Profile` - Unified agent profile after aggregation
397
+ - `AgentResponse` - User data from userByCI endpoint
398
+ - `DesktopProfileResponse` - Agent desktop settings
399
+ - `TeamList` - Team data with full details (id, name, type, channelMap, etc.)
400
+ - `Team` - Simplified team reference (teamId, teamName, desktopLayoutId)
401
+ - `AuxCode` - Auxiliary code definition
402
+ - `Entity` - Filtered code entity (used for idle/wrapup codes in Profile)
403
+
404
+ **Organization Types:**
405
+ - `OrgInfo` - Organization metadata
406
+ - `OrgSettings` - Organization-level feature flags
407
+ - `TenantData` - Tenant configuration and feature enablement
408
+ - `SiteInfo` - Site-specific configuration
409
+
410
+ **Communication Types:**
411
+ - `DialPlanEntity` - Dial plan rule definition
412
+ - `URLMapping` - External service URL mapping
413
+ - `MultimediaProfile` - Multimedia profile configuration
414
+
415
+ **Note:** The config service itself does not emit events. For agent and task events, see the Agent and Task services. Event constants are defined in [types.ts](../types.ts) under `CC_AGENT_EVENTS` and `CC_TASK_EVENTS`.
416
+
417
+ ---
418
+
419
+ ## Related Files
420
+
421
+ - [index.ts](../index.ts) - Service implementation with all API methods
422
+ - [types.ts](../types.ts) - Complete type definitions and event constants
423
+ - [Util.ts](../Util.ts) - Profile parsing utilities (parseAgentConfigs, getFilterAuxCodes, etc.)
424
+ - [constants.ts](../constants.ts) - API endpoints, default values, and method names