@webex/contact-center 3.12.0-next.149 → 3.12.0-next.150
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 +1 -1
- package/ai-docs/CONTRACTS.md +1 -0
- package/dist/cc.js +4 -4
- package/dist/cc.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/services/config/Util.js +38 -45
- package/dist/services/config/Util.js.map +1 -1
- package/dist/services/config/constants.js +15 -71
- package/dist/services/config/constants.js.map +1 -1
- package/dist/services/config/index.js +49 -226
- package/dist/services/config/index.js.map +1 -1
- package/dist/services/config/types.js +33 -11
- package/dist/services/config/types.js.map +1 -1
- package/dist/types/cc.d.ts +3 -3
- package/dist/types/index.d.ts +16 -8
- package/dist/types/services/config/Util.d.ts +4 -8
- package/dist/types/services/config/constants.d.ts +15 -71
- package/dist/types/services/config/index.d.ts +16 -64
- package/dist/types/services/config/types.d.ts +97 -160
- package/dist/webex.js +1 -1
- package/package.json +1 -1
- package/src/cc.ts +4 -4
- package/src/index.ts +16 -8
- package/src/services/agent/ai-docs/AGENTS.md +1 -1
- package/src/services/config/Util.ts +43 -82
- package/src/services/config/ai-docs/AGENTS.md +34 -39
- package/src/services/config/ai-docs/ARCHITECTURE.md +88 -101
- package/src/services/config/ai-docs/config-spec.md +115 -132
- package/src/services/config/constants.ts +18 -80
- package/src/services/config/index.ts +52 -278
- package/src/services/config/types.ts +101 -185
- package/test/unit/spec/index.ts +6 -2
- package/test/unit/spec/services/config/Util.ts +442 -70
- package/test/unit/spec/services/config/index.ts +246 -544
- package/typedoc.md +1 -1
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
| Doc kind | Module spec |
|
|
12
12
|
| Coverage score | Partial (manifest-authoritative); 15/15 required document fields present |
|
|
13
13
|
| Generated from | `module-spec` @ SDLC template library `0.2.1` |
|
|
14
|
-
| generated_by / approved_by / updated_at | Codex generator / developer-approved
|
|
14
|
+
| generated_by / approved_by / updated_at | Codex generator / developer-approved desktop-login aggregate migration delta / 2026-10-05 |
|
|
15
15
|
| Validation status | Agent Wellness Break v0.4 delta independently validated by claude-code on 2026-09-07; coverage remains Partial until the remaining baseline promotion criteria are satisfied |
|
|
16
16
|
|
|
17
17
|
## Evidence Rules
|
|
@@ -27,21 +27,21 @@ Config is one of nine confirmed Contact Center SDK modules. Own retrieval and ag
|
|
|
27
27
|
|
|
28
28
|
The Config Service is an **internal service** that builds the comprehensive AgentProfile (`Profile` type) by:
|
|
29
29
|
|
|
30
|
-
1. Fetching user
|
|
30
|
+
1. Fetching the user desktop-login aggregate (agent identity plus `agentProfile`)
|
|
31
31
|
|
|
32
|
-
2. Fetching desktop
|
|
32
|
+
2. Fetching the organization desktop-login aggregate (org info, org settings, tenant configuration, URL mappings, AI feature, Microsoft/Webex config)
|
|
33
33
|
|
|
34
34
|
3. Fetching teams
|
|
35
35
|
|
|
36
36
|
4. Fetching aux codes (idle/wrapup codes)
|
|
37
37
|
|
|
38
|
-
5. Fetching
|
|
38
|
+
5. Fetching site and, when the agent profile enables it, dial-plan data
|
|
39
39
|
|
|
40
40
|
6. Aggregating all data into a single AgentProfile
|
|
41
41
|
|
|
42
42
|
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.
|
|
43
43
|
|
|
44
|
-
- **AgentProfile Aggregation**: Combines data from
|
|
44
|
+
- **AgentProfile Aggregation**: Combines data from 6 API endpoints (5 when the agent profile disables dial plans)
|
|
45
45
|
|
|
46
46
|
- **Aux Codes Fetching**: Gets all idle and wrapup codes with pagination
|
|
47
47
|
|
|
@@ -53,7 +53,7 @@ The AgentProfile is the central configuration object required for an agent to op
|
|
|
53
53
|
|
|
54
54
|
- **Multimedia Profile**: Fetches channel capacity and blending config (standalone, not yet publicly exposed)
|
|
55
55
|
|
|
56
|
-
- **Paginated Data Access**: `getListOfTeams` and `getListOfAuxCodes` support custom pagination independent of profile building
|
|
56
|
+
- **Paginated Data Access**: `getListOfTeams` and `getListOfAuxCodes` support custom pagination independent of profile building. `getListOfTeams` takes a `userDbId` — the `user.dbId` carried by the user desktop-login aggregate, not the CI user id — rather than a list of team ids
|
|
57
57
|
|
|
58
58
|
## Purpose / Responsibility
|
|
59
59
|
Own retrieval and aggregation of remote organization, agent, team, profile, auxiliary-code, dial-plan, and feature configuration.
|
|
@@ -94,8 +94,9 @@ services/config/
|
|
|
94
94
|
|---|---|---|
|
|
95
95
|
| `getAgentConfig(orgId, agentId)` | staged, all-or-nothing `Promise<Profile>` aggregation | `src/services/config/index.ts` |
|
|
96
96
|
| User/profile/site/team/aux-code fetches | typed REST methods including pagination helpers | `src/services/config/index.ts`, `src/services/config/types.ts` |
|
|
97
|
-
| `
|
|
98
|
-
| `
|
|
97
|
+
| `getOrgDesktopLoginConfig(orgId)` | `OrgDesktopLoginResponse` from `organization/{orgId}/desktop-login` | `src/services/config/index.ts`, `src/services/config/constants.ts` |
|
|
98
|
+
| `getUserDesktopLoginConfig(orgId, ciUserId)` | `UserDesktopLoginResponse` from `organization/{orgId}/v2/user/by-ci-user-id/{ciUserId}/desktop-login` | `src/services/config/index.ts`, `src/services/config/constants.ts` |
|
|
99
|
+
| `Profile.aiFeature` | optional `aiFeature` section of the organization aggregate, mapped by `parseAgentConfigs` | `src/services/config/Util.ts`, `src/services/config/types.ts` |
|
|
99
100
|
| Multimedia profile | `MultimediaProfileResponse` | `src/services/config/types.ts` |
|
|
100
101
|
| Organization masking | `OrgSettings.maskSensitiveData` | `src/services/config/types.ts`, `src/services/config/Util.ts` |
|
|
101
102
|
| Auxiliary-code list URL | includes `desktopProfileFilter=true` | `src/services/config/constants.ts` |
|
|
@@ -113,8 +114,8 @@ The service has no `TeamList.channelMap` contract. Exact package exports are ind
|
|
|
113
114
|
## Requirements
|
|
114
115
|
| ID | WHAT | WHY | Source Evidence | Test / Example Evidence | Assumptions / Gaps | Confidence |
|
|
115
116
|
|---|---|---|---|---|---|---|
|
|
116
|
-
| CONFIG-R-001 | Fetch user
|
|
117
|
-
| CONFIG-R-002 | Include `
|
|
117
|
+
| CONFIG-R-001 | Fetch the user desktop-login aggregate first, then aggregate five dependent promises: the organization desktop-login aggregate, auxiliary codes, teams, site, and the conditional dial plan. | Dependent IDs and all-or-nothing consistency require staged orchestration. | `src/services/config/index.ts` | `test/unit/spec/services/config/index.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
|
|
118
|
+
| CONFIG-R-002 | Include the organization aggregate's `aiFeature` section in `parseAgentConfigs` so `Profile.aiFeature` reflects the organization feature contract. | ApiAIAssistant behavior is gated by the remote organization feature contract. | `src/services/config/index.ts` | `test/unit/spec/services/config/index.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
|
|
118
119
|
| CONFIG-R-003 | Paginate teams and auxiliary codes until completion and include `desktopProfileFilter=true` for auxiliary-code requests. | A partial or unfiltered set yields invalid profile/team/auxiliary choices. | `src/services/config/constants.ts` | `test/unit/spec/services/config/index.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
|
|
119
120
|
| CONFIG-R-004 | Expose current response/field names: `MultimediaProfileResponse`, `OrgSettings.maskSensitiveData`, and real TeamList fields only. | Type-name drift causes invalid consumer code and incorrect privacy behavior. | `src/services/config/types.ts` | `test/unit/spec/services/config/index.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
|
|
120
121
|
| CONFIG-R-005 | Reject the entire profile aggregation when any required dependent request fails. | Consumers must never receive an internally inconsistent partial Profile. | `src/services/config/index.ts` | `test/unit/spec/services/config/index.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
|
|
@@ -168,32 +169,22 @@ The AgentProfile is defined as the [`Profile`](../types.ts) type. This is not an
|
|
|
168
169
|
| `accessBuddyTeam` | `'ALL' \| 'SPECIFIC' \| 'NONE'` | Collaboration tab buddy-team access scope from Desktop Profile |
|
|
169
170
|
| `isWellnessBreakEnabled` | boolean | Effective wellness gate derived from backend enablement/reminder configuration and positive AI Assistant license quantity |
|
|
170
171
|
|
|
171
|
-
`parseAgentConfigs()` maps the three `access*` fields from `
|
|
172
|
+
`parseAgentConfigs()` maps the three `access*` fields from the user aggregate's `AgentProfile` section onto the public `Profile` returned by `cc.register()`.
|
|
172
173
|
|
|
173
|
-
The following diagram shows how `getAgentConfig` orchestrates
|
|
174
|
+
The following diagram shows how `getAgentConfig` orchestrates six API calls and combines their results into the AgentProfile via `parseAgentConfigs()`:
|
|
174
175
|
|
|
175
176
|
```text
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
│
|
|
188
|
-
getAllAuxCodes ─────────────┤
|
|
189
|
-
│
|
|
190
|
-
getDesktopProfileById ─────┤
|
|
191
|
-
│
|
|
192
|
-
getSiteInfo ───────────────┤ (computes multimediaProfileId)
|
|
193
|
-
│
|
|
194
|
-
getAllTeams ────────────────┤
|
|
195
|
-
│
|
|
196
|
-
getDialPlanData ───────────┘
|
|
177
|
+
getUserDesktopLoginConfig ──┐ (awaited first; supplies dbId, siteId, dialPlanEnabled)
|
|
178
|
+
│
|
|
179
|
+
getOrgDesktopLoginConfig ───┤ (org info, org settings, tenant config, urlMappings,
|
|
180
|
+
│ aiFeature, microsoftConfig, webexConfig)
|
|
181
|
+
getAllAuxCodes ─────────────┼──► parseAgentConfigs() ──► AgentProfile
|
|
182
|
+
│
|
|
183
|
+
getAllTeams ────────────────┤ (filtered by userId == user.dbId)
|
|
184
|
+
│
|
|
185
|
+
getSiteInfo ────────────────┤ (team → site fallback for multimediaProfileId)
|
|
186
|
+
│
|
|
187
|
+
getDialPlanData ────────────┘ (only when agentProfile.dialPlanEnabled)
|
|
197
188
|
```
|
|
198
189
|
|
|
199
190
|
Types used by the config service, all defined in [`types.ts`](../types.ts):
|
|
@@ -201,23 +192,26 @@ Types used by the config service, all defined in [`types.ts`](../types.ts):
|
|
|
201
192
|
| Type | Description |
|
|
202
193
|
|---|---|
|
|
203
194
|
| `Profile` | Final aggregated agent config returned by `getAgentConfig()` |
|
|
204
|
-
| `
|
|
205
|
-
| `
|
|
195
|
+
| `OrgDesktopLoginResponse` | Response from `getOrgDesktopLoginConfig()` — `organization`, `organizationSetting`, `tenantConfiguration`, `urlMappings`, `aiFeature`, `microsoftConfig`, `webexConfig` |
|
|
196
|
+
| `UserDesktopLoginResponse` | Response from `getUserDesktopLoginConfig()` — `user` and `agentProfile` sections |
|
|
197
|
+
| `AgentResponse` | `user` section of the user aggregate — agent metadata, `dbId`, `siteId`, `agentProfileId` |
|
|
198
|
+
| `AgentProfile` | `agentProfile` section of the user aggregate — layout, dial-plan enablement, login options |
|
|
206
199
|
| `TeamList` | Team record from API — `id`, `name`, `teamType`, `siteId`, `multiMediaProfileId` |
|
|
207
200
|
| `ListTeamsResponse` | Paginated wrapper around `TeamList[]` with `meta` for pagination |
|
|
208
201
|
| `OrgInfo` | Organization info — `tenantId`, timezone |
|
|
209
202
|
| `OrgSettings` | Org feature flags — `webRtcEnabled`, `maskSensitiveData` |
|
|
210
203
|
| `TenantData` | Tenant-level config — inactivity timeout, `forceDefaultDn`, `outdialEnabled` |
|
|
211
204
|
| `SiteInfo` | Site config — `id`, `name`, `multimediaProfileId` |
|
|
212
|
-
| `
|
|
205
|
+
| `OrgUrlMappings` | Keyed external URL mappings — `ACQUEON_API_URL`, `ACQUEON_CONSOLE_URL` |
|
|
206
|
+
| `MicrosoftConfig` | Org-level Microsoft presence config — `showUserDetails`, `stateSynchronization` |
|
|
207
|
+
| `WebexConfig` | Org-level Webex presence config — `showUserDetails`, `stateSynchronization` |
|
|
213
208
|
| `MultimediaProfileResponse` | Multimedia profile — channel capacities and settings |
|
|
214
209
|
| `AuxCode` | Auxiliary code record — `id`, `name`, `description`, `workTypeCode` |
|
|
215
210
|
| `ListAuxCodesResponse` | Paginated wrapper around `AuxCode[]` with `meta` |
|
|
216
|
-
| `DialPlanEntity` | Dial plan rule — regex pattern, prefix, strip digits |
|
|
211
|
+
| `DialPlanEntity` | Dial plan rule — regex pattern, prefix, strip digits, `active` |
|
|
217
212
|
| `Entity` | Basic entity info — `isSystem`, `name`, `id`, `description` |
|
|
218
213
|
| `WrapupData` | Wrap-up config — auto-wrapup settings, available wrapup codes |
|
|
219
214
|
| `OutdialAniParams` | Parameters for `getOutdialAniEntries()` — ANI ID, pagination, filtering |
|
|
220
|
-
| `Team` | Simplified team shape in `Profile` — `teamId`, `teamName`, `desktopLayoutId` |
|
|
221
215
|
|
|
222
216
|
```typescript
|
|
223
217
|
// In register() -> connectWebsocket()
|
|
@@ -233,19 +227,19 @@ For endpoints with pagination (teams, aux codes):
|
|
|
233
227
|
```typescript
|
|
234
228
|
import {DEFAULT_PAGE} from './constants'; // DEFAULT_PAGE = 0
|
|
235
229
|
|
|
236
|
-
public async getAllTeams(orgId, pageSize,
|
|
230
|
+
public async getAllTeams(orgId, pageSize, userDbId): Promise<TeamList[]> {
|
|
237
231
|
let allTeams: TeamList[] = [];
|
|
238
232
|
let page = DEFAULT_PAGE;
|
|
239
233
|
|
|
240
234
|
// First request to get totalPages
|
|
241
|
-
const firstResponse = await this.getListOfTeams(orgId, page, pageSize,
|
|
235
|
+
const firstResponse = await this.getListOfTeams(orgId, page, pageSize, userDbId);
|
|
242
236
|
allTeams = allTeams.concat(firstResponse.data);
|
|
243
237
|
const totalPages = firstResponse.meta.totalPages;
|
|
244
238
|
|
|
245
239
|
// Parallel requests for remaining pages
|
|
246
240
|
const requests = [];
|
|
247
241
|
for (page = DEFAULT_PAGE + 1; page < totalPages; page += 1) {
|
|
248
|
-
requests.push(this.getListOfTeams(orgId, page, pageSize,
|
|
242
|
+
requests.push(this.getListOfTeams(orgId, page, pageSize, userDbId));
|
|
249
243
|
}
|
|
250
244
|
|
|
251
245
|
const responses = await Promise.all(requests);
|
|
@@ -263,50 +257,44 @@ The service fetches data from multiple APIs with these response structures:
|
|
|
263
257
|
|
|
264
258
|
| API Method | Response Type | Key Fields | Usage |
|
|
265
259
|
|---|---|---|---|
|
|
266
|
-
| `
|
|
267
|
-
| `
|
|
260
|
+
| `getUserDesktopLoginConfig` | `UserDesktopLoginResponse` | `user`: `ciUserId`, `id`, `dbId`, `firstName`, `lastName`, `email`, `agentProfileId`, `siteId`. `agentProfile`: `dialPlanEnabled`, `accessWrapUpCode`, `accessIdleCode`, `loginVoiceOptions`, `viewableStatistics` | Agent identity, team-filter id, site reference, and desktop settings in one call |
|
|
261
|
+
| `getOrgDesktopLoginConfig` | `OrgDesktopLoginResponse` | `organization`: `tenantId`, `timezone`. `organizationSetting`: `webRtcEnabled`, `maskSensitiveData`, `campaignManagerEnabled`, `aiAssistantQuantity`. `tenantConfiguration`: `outdialEnabled`, `forceDefaultDn`, `privacyShieldVisible`, `timeoutDesktopInactivityEnabled`. Optional `urlMappings`, `aiFeature`, `microsoftConfig`, `webexConfig` | All organization-, tenant- and feature-scoped configuration in one call |
|
|
268
262
|
| `getAllTeams` | `TeamList[]` | real `TeamList` fields from `src/services/config/types.ts` | Team identity, name, type, and site assignment; channel capacities belong to `MultimediaProfileResponse` |
|
|
269
|
-
| `getTenantData` | `TenantData` | `outdialEnabled`, `forceDefaultDn`, `privacyShieldVisible`, `timeoutDesktopInactivityEnabled` | Tenant-level feature flags |
|
|
270
|
-
| `getOrgInfo` | `OrgInfo` | `tenantId`, `timezone` | Organization metadata |
|
|
271
263
|
| `getAllAuxCodes` | `AuxCode[]` | `id`, `name`, `workTypeCode`, `active`, `isSystemCode`, `defaultCode` | Auxiliary codes for idle/wrap-up states |
|
|
272
|
-
| `
|
|
273
|
-
| `
|
|
274
|
-
| `getURLMapping` | `URLMapping[]` | `name`, `url` | External service URL mappings |
|
|
275
|
-
| `getSiteInfo` | `SiteInfo` | Site-specific configuration | Site details |
|
|
264
|
+
| `getDialPlanData` | `DialPlanEntity[]` | `id`, `name`, `regularExpression`, `prefix`, `strippedChars`, `active` | Dial plan rules for outbound calling |
|
|
265
|
+
| `getSiteInfo` | `SiteInfo` | Site-specific configuration | Site details, including the `multimediaProfileId` fallback |
|
|
276
266
|
|
|
277
267
|
These responses are parsed and aggregated into a single `Profile` object by the `parseAgentConfigs` function.
|
|
278
268
|
|
|
279
269
|
```typescript
|
|
280
270
|
// See full implementation in Util.ts
|
|
281
271
|
function parseAgentConfigs(profileData: {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
auxCodes: AuxCode[];
|
|
287
|
-
|
|
288
|
-
agentProfileData: DesktopProfileResponse; // See types.ts:DesktopProfileResponse
|
|
289
|
-
dialPlanData: DialPlanEntity[]; // See types.ts:DialPlanEntity
|
|
290
|
-
urlMapping: URLMapping[]; // See types.ts:URLMapping
|
|
272
|
+
orgConfig: OrgDesktopLoginResponse; // See types.ts:OrgDesktopLoginResponse
|
|
273
|
+
userData: AgentResponse; // `user` section; see types.ts:AgentResponse
|
|
274
|
+
agentProfileData: AgentProfile; // `agentProfile` section; see types.ts:AgentProfile
|
|
275
|
+
teamData: TeamList[]; // See types.ts:TeamList
|
|
276
|
+
auxCodes: AuxCode[]; // See types.ts:AuxCode
|
|
277
|
+
dialPlanData: DialPlanEntity[]; // See types.ts:DialPlanEntity
|
|
291
278
|
multimediaProfileId: string;
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
279
|
+
}): Profile { // See types.ts:Profile
|
|
280
|
+
const { orgConfig, userData, agentProfileData, teamData, auxCodes,
|
|
281
|
+
dialPlanData } = profileData;
|
|
282
|
+
const {
|
|
283
|
+
organization: orgInfoData,
|
|
284
|
+
organizationSetting: orgSettingsData,
|
|
285
|
+
tenantConfiguration: tenantData,
|
|
286
|
+
urlMappings,
|
|
287
|
+
aiFeature,
|
|
288
|
+
microsoftConfig,
|
|
289
|
+
webexConfig,
|
|
290
|
+
} = orgConfig;
|
|
301
291
|
|
|
302
292
|
// Aux code filtering via getFilterAuxCodes():
|
|
303
|
-
// - checks auxCode.active
|
|
304
|
-
// -
|
|
293
|
+
// - checks auxCode.workTypeCode and auxCode.active
|
|
294
|
+
// - the aggregate returns the full org pool, so no per-agent restriction is applied
|
|
305
295
|
// - maps to Entity {id, name, isSystem, isDefault}
|
|
306
|
-
const wrapupCodes = getFilterAuxCodes(auxCodes, WRAP_UP_CODE
|
|
307
|
-
|
|
308
|
-
const idleCodes = getFilterAuxCodes(auxCodes, IDLE_CODE,
|
|
309
|
-
agentProfileData.accessIdleCode === 'ALL' ? [] : agentProfileData.idleCodes);
|
|
296
|
+
const wrapupCodes = getFilterAuxCodes(auxCodes, WRAP_UP_CODE);
|
|
297
|
+
const idleCodes = getFilterAuxCodes(auxCodes, IDLE_CODE);
|
|
310
298
|
|
|
311
299
|
// Hardcoded "Available" state always appended to idle codes
|
|
312
300
|
idleCodes.push({ id: '0', name: 'Available', isSystem: false, isDefault: false });
|
|
@@ -315,7 +303,7 @@ function parseAgentConfigs(profileData: {
|
|
|
315
303
|
agentId: userData.ciUserId, // NOTE: uses ciUserId for agent identification
|
|
316
304
|
analyserUserId: userData.id, // NOTE: userData.id is used for analytics/reporting
|
|
317
305
|
agentName: `${userData.firstName} ${userData.lastName}`,
|
|
318
|
-
teams: teamData, //
|
|
306
|
+
teams: teamData, // TeamList[] straight from the team API; Profile.teams is TeamList[]
|
|
319
307
|
idleCodes, // NOTE: Filtered via getFilterAuxCodes() + hardcoded "Available" state
|
|
320
308
|
wrapupCodes, // NOTE: Filtered via getFilterAuxCodes()
|
|
321
309
|
webRtcEnabled: orgSettingsData.webRtcEnabled,
|
|
@@ -332,31 +320,22 @@ function parseAgentConfigs(profileData: {
|
|
|
332
320
|
## Data Flow
|
|
333
321
|
```mermaid
|
|
334
322
|
flowchart TD
|
|
335
|
-
Start[getAgentConfig orgId + agentId] --> User[
|
|
336
|
-
Start --> Org[
|
|
337
|
-
Start --> OrgSettings[getOrganizationSetting]
|
|
338
|
-
Start --> Tenant[getTenantData]
|
|
339
|
-
Start --> URL[getURLMapping]
|
|
340
|
-
Start --> AI[getAIFeatureFlags]
|
|
323
|
+
Start[getAgentConfig orgId + agentId] --> User[getUserDesktopLoginConfig awaited first]
|
|
324
|
+
Start --> Org[getOrgDesktopLoginConfig]
|
|
341
325
|
Start --> Aux[getAllAuxCodes]
|
|
342
|
-
User -->
|
|
343
|
-
User -->
|
|
344
|
-
User -->
|
|
345
|
-
Profile --> Dial{dialPlanEnabled?}
|
|
326
|
+
User --> Site[getSiteInfo siteId]
|
|
327
|
+
User --> Teams[getAllTeams filtered by dbId]
|
|
328
|
+
User --> Dial{agentProfile.dialPlanEnabled?}
|
|
346
329
|
Dial -->|yes| DialPlan[getDialPlanData]
|
|
347
330
|
Dial -->|no| Empty[empty dial plan]
|
|
348
|
-
|
|
349
|
-
Site --> All
|
|
331
|
+
Site --> All[Promise.all of five result promises]
|
|
350
332
|
Teams --> All
|
|
351
333
|
DialPlan --> All
|
|
352
334
|
Empty --> All
|
|
353
335
|
Org --> All
|
|
354
|
-
OrgSettings --> All
|
|
355
|
-
Tenant --> All
|
|
356
|
-
URL --> All
|
|
357
|
-
AI --> All
|
|
358
336
|
Aux --> All
|
|
359
|
-
All -->
|
|
337
|
+
All --> Mm[multimediaProfileId: team value else site value]
|
|
338
|
+
Mm --> Parse[parseAgentConfigs with orgConfig + userData + agentProfileData]
|
|
360
339
|
Parse --> Result[Profile with aiFeature + maskSensitiveData]
|
|
361
340
|
```
|
|
362
341
|
|
|
@@ -380,19 +359,19 @@ sequenceDiagram
|
|
|
380
359
|
participant Util as parseAgentConfigs
|
|
381
360
|
CC->>Cfg: getAgentConfig(orgId, agentId)
|
|
382
361
|
par requests started before user data resolves
|
|
383
|
-
Cfg->>API:
|
|
384
|
-
Cfg->>API:
|
|
385
|
-
Cfg->>API:
|
|
362
|
+
Cfg->>API: getUserDesktopLoginConfig
|
|
363
|
+
Cfg->>API: getOrgDesktopLoginConfig
|
|
364
|
+
Cfg->>API: getAllAuxCodes
|
|
386
365
|
end
|
|
387
|
-
API-->>Cfg: user
|
|
366
|
+
API-->>Cfg: user.dbId / user.siteId / agentProfile.dialPlanEnabled
|
|
388
367
|
par user-dependent requests
|
|
389
|
-
Cfg->>API:
|
|
390
|
-
Cfg->>API: conditional dial plan
|
|
368
|
+
Cfg->>API: getSiteInfo + getAllTeams(filter userId==dbId)
|
|
369
|
+
Cfg->>API: conditional dial plan gated on agentProfile.dialPlanEnabled
|
|
391
370
|
end
|
|
392
|
-
Note over Cfg,API: Promise.all awaits
|
|
371
|
+
Note over Cfg,API: Promise.all awaits 5 result promises after the user aggregate
|
|
393
372
|
alt all succeed
|
|
394
|
-
API-->>Cfg:
|
|
395
|
-
Cfg->>Util: parseAgentConfigs(
|
|
373
|
+
API-->>Cfg: five results
|
|
374
|
+
Cfg->>Util: parseAgentConfigs(orgConfig, userData, agentProfileData, ...)
|
|
396
375
|
Util-->>CC: Profile including aiFeature
|
|
397
376
|
else any fails
|
|
398
377
|
Cfg-->>CC: throw; no partial Profile
|
|
@@ -407,7 +386,7 @@ sequenceDiagram
|
|
|
407
386
|
participant Cfg as AgentConfigService
|
|
408
387
|
participant WR as WebexRequest
|
|
409
388
|
participant API as WCC API
|
|
410
|
-
Caller->>Cfg: getAllTeams/getAllAuxCodes(orgId, pageSize, filters)
|
|
389
|
+
Caller->>Cfg: getAllTeams(orgId, pageSize, userDbId) / getAllAuxCodes(orgId, pageSize, filters)
|
|
411
390
|
Cfg->>WR: request page 0
|
|
412
391
|
WR->>API: authenticated GET
|
|
413
392
|
alt first page succeeds
|
|
@@ -437,7 +416,7 @@ classDiagram
|
|
|
437
416
|
class parseAgentConfigs
|
|
438
417
|
class Profile
|
|
439
418
|
ContactCenter --> AgentConfigService : getAgentConfig
|
|
440
|
-
AgentConfigService --> WebexRequest :
|
|
419
|
+
AgentConfigService --> WebexRequest : six dependent requests
|
|
441
420
|
AgentConfigService --> parseAgentConfigs : aggregate results
|
|
442
421
|
parseAgentConfigs --> Profile : aiFeature + maskSensitiveData
|
|
443
422
|
```
|
|
@@ -450,9 +429,9 @@ classDiagram
|
|
|
450
429
|
| `types` | `config/types.ts` | Types, events, interfaces |
|
|
451
430
|
|
|
452
431
|
## Use Cases
|
|
453
|
-
- **UC-1 Two-wave profile aggregation:** retrieve the user first, run
|
|
432
|
+
- **UC-1 Two-wave profile aggregation:** retrieve the user desktop-login aggregate first, run five dependent promises including the organization aggregate, then parse one complete Profile or reject the whole operation. Evidence: `src/services/config/index.ts`, `src/services/config/Util.ts`, `test/unit/spec/services/config/index.ts`.
|
|
454
433
|
- **UC-2 Paginated teams/aux codes:** follow backend page metadata to completion; auxiliary-code requests include `desktopProfileFilter=true`. Evidence: `src/services/config/index.ts`, `test/unit/spec/services/config/index.ts`.
|
|
455
|
-
- **UC-3 Dial plan and URL
|
|
434
|
+
- **UC-3 Dial plan and URL mappings:** request dial-plan data only when the agent profile enables it, keep only `active` plans, and map the organization aggregate's `urlMappings` into the profile. Evidence: `src/services/config/index.ts`, `src/services/config/Util.ts`, `test/unit/spec/services/config/index.ts`.
|
|
456
435
|
- **UC-4 Outdial ANI retrieval:** return the organization-scoped ANI list through authenticated WebexRequest and propagate failures without a partial substitute. Evidence: `src/services/config/index.ts`, `test/unit/spec/services/config/index.ts`.
|
|
457
436
|
- **UC-5 Wellness configuration:** produce one fail-closed effective profile flag and retrieve the exact system wellness idle code across pages. Evidence: `src/services/config/Util.ts`, `src/services/config/index.ts`, `test/unit/spec/services/config/Util.ts`, `test/unit/spec/services/config/index.ts`.
|
|
458
437
|
|
|
@@ -464,18 +443,20 @@ classDiagram
|
|
|
464
443
|
- The system wellness code lookup is separate from profile auxiliary-code aggregation and uses `desktopProfileFilter=false`.
|
|
465
444
|
|
|
466
445
|
## Concurrency & Reactive Flow
|
|
467
|
-
- The initial user lookup supplies identifiers for a
|
|
446
|
+
- The initial user desktop-login lookup supplies identifiers for a five-promise `Promise.all`; pagination loops await pages in order and stop from returned metadata.
|
|
468
447
|
|
|
469
448
|
## Protocol / Wire Format
|
|
470
449
|
All Config operations are authenticated REST calls through WebexRequest. Important current routes include:
|
|
471
450
|
|
|
472
451
|
| Operation | Resource shape |
|
|
473
452
|
|---|---|
|
|
474
|
-
|
|
|
453
|
+
| Organization desktop-login aggregate | `organization/{orgId}/desktop-login` |
|
|
454
|
+
| User desktop-login aggregate | `organization/{orgId}/v2/user/by-ci-user-id/{ciUserId}/desktop-login` |
|
|
455
|
+
| Teams | `organization/{orgId}/v2/team?page={page}&pageSize={pageSize}&agentView=true&filter=userId=={userDbId}` — the wire field is `userId` but the value is the user's database id; filter value unquoted, no `attributes=` projection |
|
|
475
456
|
| Auxiliary codes | pagination/filter/attributes plus `desktopProfileFilter=true` |
|
|
476
457
|
| Wellness system idle code | `organization/{orgId}/v2/auxiliary-code?page={page}&pageSize={pageSize}&workType=IDLE_CODE&customFilter=isSystemCode==true&desktopProfileFilter=false` |
|
|
477
458
|
| Multimedia profile | organization-scoped multimedia-profile resource |
|
|
478
|
-
| Dial plan | organization-scoped dial-plan resource when
|
|
459
|
+
| Dial plan | organization-scoped dial-plan resource when the agent profile enables it |
|
|
479
460
|
|
|
480
461
|
Exact resources live in `src/services/config/constants.ts`; response/profile fields live in `src/services/config/types.ts`.
|
|
481
462
|
|
|
@@ -485,7 +466,7 @@ Exact resources live in `src/services/config/constants.ts`; response/profile fie
|
|
|
485
466
|
| Dependency rejection | Typed/rethrown error or failure event | Inspect structured details, preserve tracking id, and retry only when the operation is safe. |
|
|
486
467
|
| Timeout or missing async completion | Timeout/recovery state | Follow the module-specific recovery path; never synthesize success. |
|
|
487
468
|
|
|
488
|
-
All API methods within the config service throw errors on failure. After `
|
|
469
|
+
All API methods within the config service throw errors on failure. After `getUserDesktopLoginConfig`, `getAgentConfig` awaits five dependent requests via `Promise.all`: site, conditional dial plan, teams, the organization desktop-login aggregate, and all auxiliary codes. A failure in any required request, including `getOrgDesktopLoginConfig`, causes the entire AgentProfile fetch to fail. There is no partial profile — either all data is successfully fetched and aggregated, or the operation throws.
|
|
489
470
|
|
|
490
471
|
```typescript
|
|
491
472
|
try {
|
|
@@ -502,14 +483,17 @@ try {
|
|
|
502
483
|
Each method follows consistent error handling:
|
|
503
484
|
|
|
504
485
|
```typescript
|
|
505
|
-
public async
|
|
506
|
-
|
|
486
|
+
public async getUserDesktopLoginConfig(
|
|
487
|
+
orgId: string,
|
|
488
|
+
ciUserId: string
|
|
489
|
+
): Promise<UserDesktopLoginResponse> {
|
|
490
|
+
LoggerProxy.info('Fetching user desktop-login configuration', {
|
|
507
491
|
module: CONFIG_FILE_NAME,
|
|
508
|
-
method: METHODS.
|
|
492
|
+
method: METHODS.GET_USER_DESKTOP_LOGIN_CONFIG,
|
|
509
493
|
});
|
|
510
494
|
|
|
511
495
|
try {
|
|
512
|
-
const resource = endPointMap.
|
|
496
|
+
const resource = endPointMap.userDesktopLogin(orgId, ciUserId);
|
|
513
497
|
const response = await this.webexReq.request({
|
|
514
498
|
service: WCC_API_GATEWAY,
|
|
515
499
|
resource,
|
|
@@ -520,16 +504,16 @@ public async getUserUsingCI(orgId: string, agentId: string): Promise<AgentRespon
|
|
|
520
504
|
throw new Error(`API call failed with ${response.statusCode}`);
|
|
521
505
|
}
|
|
522
506
|
|
|
523
|
-
LoggerProxy.log('
|
|
507
|
+
LoggerProxy.log('getUserDesktopLoginConfig api success.', {
|
|
524
508
|
module: CONFIG_FILE_NAME,
|
|
525
|
-
method: METHODS.
|
|
509
|
+
method: METHODS.GET_USER_DESKTOP_LOGIN_CONFIG,
|
|
526
510
|
});
|
|
527
511
|
|
|
528
512
|
return Promise.resolve(response.body);
|
|
529
513
|
} catch (error) {
|
|
530
|
-
LoggerProxy.error(`
|
|
514
|
+
LoggerProxy.error(`getUserDesktopLoginConfig API call failed with ${error}`, {
|
|
531
515
|
module: CONFIG_FILE_NAME,
|
|
532
|
-
method: METHODS.
|
|
516
|
+
method: METHODS.GET_USER_DESKTOP_LOGIN_CONFIG,
|
|
533
517
|
});
|
|
534
518
|
throw error;
|
|
535
519
|
}
|
|
@@ -546,8 +530,8 @@ public async getUserUsingCI(orgId: string, agentId: string): Promise<AgentRespon
|
|
|
546
530
|
"module": "config/index.ts", "method": "getAgentConfig"
|
|
547
531
|
|
|
548
532
|
// Specific API method failures
|
|
549
|
-
"
|
|
550
|
-
"
|
|
533
|
+
"getUserDesktopLoginConfig API call failed"
|
|
534
|
+
"getOrgDesktopLoginConfig API call failed"
|
|
551
535
|
"getAllTeams API call failed"
|
|
552
536
|
"getAllAuxCodes API call failed"
|
|
553
537
|
|
|
@@ -583,7 +567,7 @@ public async getUserUsingCI(orgId: string, agentId: string): Promise<AgentRespon
|
|
|
583
567
|
|
|
584
568
|
1. Check `totalPages` in first response
|
|
585
569
|
|
|
586
|
-
2. Verify filter
|
|
570
|
+
2. Verify the team filter carries a valid `userDbId` (`user.dbId`, not the CI user id) and that aux-code filters contain valid IDs
|
|
587
571
|
|
|
588
572
|
3. Check if pageSize is appropriate (default: 100)
|
|
589
573
|
|
|
@@ -594,8 +578,8 @@ public async getUserUsingCI(orgId: string, agentId: string): Promise<AgentRespon
|
|
|
594
578
|
**Log patterns:**
|
|
595
579
|
|
|
596
580
|
```typescript
|
|
597
|
-
"
|
|
598
|
-
"
|
|
581
|
+
"getOrgDesktopLoginConfig api success."
|
|
582
|
+
"getUserDesktopLoginConfig api success."
|
|
599
583
|
```
|
|
600
584
|
|
|
601
585
|
**Solution**:
|
|
@@ -618,7 +602,7 @@ public async getUserUsingCI(orgId: string, agentId: string): Promise<AgentRespon
|
|
|
618
602
|
|
|
619
603
|
3. Note: dial plan fetch only happens if `dialPlanEnabled === true`
|
|
620
604
|
|
|
621
|
-
**Cause**:
|
|
605
|
+
**Cause**: Expected auxiliary codes missing from the returned pool
|
|
622
606
|
|
|
623
607
|
**Log patterns:**
|
|
624
608
|
|
|
@@ -628,23 +612,22 @@ public async getUserUsingCI(orgId: string, agentId: string): Promise<AgentRespon
|
|
|
628
612
|
|
|
629
613
|
**Solution**:
|
|
630
614
|
|
|
631
|
-
1.
|
|
632
|
-
|
|
633
|
-
2. Check `agentProfileData.accessIdleCode`
|
|
615
|
+
1. `getFilterAuxCodes` no longer applies a per-agent restriction list — the full organization pool is returned for every agent
|
|
634
616
|
|
|
635
|
-
|
|
617
|
+
2. `Profile.idleCodesAccess` / `wrapupCodesAccess` still report `ALL` or `SPECIFIC` from `agentProfileData`
|
|
636
618
|
|
|
637
|
-
|
|
619
|
+
3. Ensure aux codes have `active: true` status and the expected `workTypeCode`
|
|
638
620
|
|
|
639
|
-
|
|
621
|
+
4. Note: "Available" state is always appended to idle codes
|
|
640
622
|
|
|
641
623
|
## Pitfalls
|
|
642
|
-
- `
|
|
643
|
-
-
|
|
624
|
+
- `getUserDesktopLoginConfig` must complete before site/team/dial-plan requests are constructed, while the five dependent promises remain all-or-nothing.
|
|
625
|
+
- The `aiFeature` section is part of the organization aggregate and must be passed into `parseAgentConfigs`; omitting it silently removes `Profile.aiFeature`.
|
|
626
|
+
- The team filter value must stay unquoted (`filter=userId=={dbId}`) — the quoted form returns HTTP 400 — and must not carry an `attributes=` projection, which would strip `multiMediaProfileId`, `teamType` and `siteName`.
|
|
644
627
|
- Team responses do not own channel configuration, and auxiliary-code requests require `desktopProfileFilter=true` during profile construction.
|
|
645
628
|
|
|
646
629
|
## Module Do's / Don'ts
|
|
647
|
-
- DO preserve the user-first dependency boundary and the exact
|
|
630
|
+
- DO preserve the user-first dependency boundary and the exact five-promise result order.
|
|
648
631
|
- DO paginate team and auxiliary-code endpoints until their metadata indicates completion.
|
|
649
632
|
- DON'T return a partially assembled Profile after any required dependency fails.
|
|
650
633
|
- DON'T invent TeamList fields such as `channelMap` or omit `maskSensitiveData`/`aiFeature` mappings.
|
|
@@ -653,7 +636,7 @@ public async getUserUsingCI(orgId: string, agentId: string): Promise<AgentRespon
|
|
|
653
636
|
- Profile creation is all-or-nothing across dependent API calls so consumers never receive internally inconsistent partial configuration.
|
|
654
637
|
|
|
655
638
|
## Test-Case Strategy (module)
|
|
656
|
-
`test/unit/spec/services/config/index.ts` must cover staged user-first orchestration,
|
|
639
|
+
`test/unit/spec/services/config/index.ts` must cover staged user-first orchestration, five-promise aggregation, AI-feature mapping, conditional dial plan, the `userDbId` team filter, pagination, auxiliary-code URL filtering, real response field names, and whole-profile rejection on any required failure.
|
|
657
640
|
|
|
658
641
|
| Behavior / Requirement | Existing test evidence | Gap |
|
|
659
642
|
|---|---|---|
|