@webex/contact-center 3.12.0-next.131 → 3.12.0-next.133
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 -1
- package/ai-docs/contact-center-spec.md +7 -7
- package/dist/cc.js +19 -2
- package/dist/cc.js.map +1 -1
- package/dist/services/config/types.js.map +1 -1
- package/dist/types/services/config/types.d.ts +2 -0
- package/dist/webex.js +1 -1
- package/package.json +2 -2
- package/src/cc.ts +20 -2
- package/src/services/config/types.ts +2 -0
- package/test/unit/spec/cc.ts +74 -3
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
package/.sdd/manifest.json
CHANGED
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"canonical_spec": "ai-docs/contact-center-spec.md",
|
|
52
52
|
"contracts": {
|
|
53
53
|
"provides": [
|
|
54
|
-
"Published @webex/contact-center package; ContactCenter WebexPlugin; public SDK methods, events, types, Task with ordered action-specific consult/transfer destination controls, AddressBook, ApiAIAssistant, UserPreference, cc.userPreference, existing getQueues/getEntryPoints methods with consult/transfer defaults, full Queue records, mapped EntryPoint records with optional numbers, exported user-preference request/response types, preview-campaign methods acceptPreviewContact/skipPreviewContact/removePreviewContact, and Agent Wellness Break effective-profile, exported action constants/types, internally sourced action context, system-code, and primary notification event APIs",
|
|
54
|
+
"Published @webex/contact-center package; ContactCenter WebexPlugin; public SDK methods, events, types, Task with ordered action-specific consult/transfer destination controls, AddressBook, ApiAIAssistant, UserPreference, cc.userPreference, existing getQueues/getEntryPoints methods with consult/transfer defaults, full Queue records, mapped EntryPoint records with optional numbers, exported user-preference request/response types, preview-campaign methods acceptPreviewContact/skipPreviewContact/removePreviewContact, and Agent Wellness Break effective-profile, registered-session Profile projection, exported action constants/types, internally sourced action context, system-code, and primary/RTD notification event APIs",
|
|
55
55
|
"WXCC-6026 wxApp Better Together: enableWxBetterTogether init config, isWxBetterTogetherEnabled read API, unified task telephony (task.accept/decline/toggleMute/transmitDtmf), TASK_WXAPP_MUTE_STATE_UPDATED event, optional main.keypad uiControl, multi-login supported; runtime toggle deferred to Phase 2 (private)",
|
|
56
56
|
"BROWSER stationLogin payload: dialNumber and deviceId are webrtc-{agentId} (contact-center.station-login-browser-dn / AGENT-R-006); public stationLogin({loginOption: 'BROWSER'}) input unchanged"
|
|
57
57
|
],
|
package/ai-docs/CONTRACTS.md
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
| `contact-center.state-controls` | Task state machine | `getDefaultUIControls`, `TaskUIControls` with ordered `consultTransferDestinations` arrays | Task controls include per-leg action state plus ordered `consult`/`transfer` destination categories derived from profile and interaction policy | additive semver public field; destination arrays are SDK-owned and first item is the consumer default | `src/services/task/state-machine/ai-docs/task-state-machine-spec.md` | `src/index.ts`, `src/services/task/types.ts`, `src/services/task/state-machine/uiControlsComputer.ts` |
|
|
18
18
|
| `contact-center.conference-participant-drop` | Task | `DropConferenceParticipantPayload`, `ITask.dropConferenceParticipant` | `(payload: {participantId: string}) => Promise<TaskResponse>`; Voice resolves from correlated `ParticipantLeftConference`, while non-voice base Task rejects as unsupported. Existing participant/consult lifecycle events may resolve one unique child-keyed task by `mainInteractionId`; no new public event is introduced. | semver public | `src/services/task/ai-docs/task-spec.md`, `src/services/task/state-machine/ai-docs/task-state-machine-spec.md` | `src/index.ts`, `src/services/task/types.ts`, `src/services/task/voice/Voice.ts`, `src/services/task/contact.ts`, `src/services/task/TaskManager.ts` |
|
|
19
19
|
| `contact-center.wxapp-answer` | Contact Center / Task | `enableWxBetterTogether`, `isWxBetterTogetherEnabled()`, `getWxAppMuted`, `syncWxAppMuteFromCallDetails`, unified task telephony (`ITask.accept`, `decline`, `toggleMute({ muted?, lineOwnerId? })`, `transmitDtmf({ dtmf, lineOwnerId? })`) | init flag ON → usersub `true` + Mercury on supported station login **and silent relogin**; init flag OFF → force usersub `false` on supported station login **and silent relogin** (clears stale suppression after refresh); **Phase 1 init-only** — change flag via re-init; multi-login supported; mute backfill via GET call details + `getWxAppMuted()` on hydrate/refresh; shared-line `lineOwnerId` defaults from participant; SDK `Voice` routes wxApp telephony when flag active | semver public | `src/services/task/ai-docs/task-spec.md`, `ai-docs/contact-center-spec.md`, `src/services/ai-docs/services-spec.md` | `src/cc.ts`, `src/services/task/voice/Voice.ts`, `src/services/task/voice/wxAppVoiceMethods.ts` |
|
|
20
|
-
| `contact-center.agent-wellness-break` | Contact Center / Services / Config | `Profile.isWellnessBreakEnabled`, `requestWellnessBreak`, `respondToWellnessBreak`, `getWellbeingBreakIdleCode`, `WELLNESS_BREAK_NOTIFICATION_ACTIONS`, `WELLNESS_BREAK_USER_ACTIONS`, `WellnessBreakEvent` | Effective gate = backend-delivered `agentWellbeing.enable` + reminders `ENABLED` + `aiAssistantQuantity > 0`;
|
|
20
|
+
| `contact-center.agent-wellness-break` | Contact Center / Services / Config | `Profile.isWellnessBreakEnabled`, optional `Profile.agentSessionId` after logged-in registration, `requestWellnessBreak`, `respondToWellnessBreak`, `getWellbeingBreakIdleCode`, `WELLNESS_BREAK_NOTIFICATION_ACTIONS`, `WELLNESS_BREAK_USER_ACTIONS`, `WellnessBreakEvent` | Effective gate = backend-delivered `agentWellbeing.enable` + reminders `ENABLED` + `aiAssistantQuantity > 0`; registration projects the SDK-owned active station session after silent relogin so hosts can validate refresh recovery. Action calls accept no identity or context-mutating fields, read the current organization/agent/session from a read-only provider supplied to ApiAIAssistant at construction, and POST a direct `WellnessBreakAction` custom event; current-session logout, multi-login close, relogin, and deregistration entry update or invalidate the provider's source state; system idle code lookup is exact, registration-generation cached, and rejects stale results; valid wellness notifications from either primary or RTD sockets emit the same public event. | additive semver public; no client-side Split dependency or invented rollout field—the delivered AI feature configuration is the server rollout boundary | `ai-docs/contact-center-spec.md`, `src/services/ai-docs/services-spec.md`, `src/services/config/ai-docs/config-spec.md` | `src/index.ts`, `src/types.ts`, `src/cc.ts`, `src/services/config/types.ts`, `src/services/ApiAiAssistant.ts` |
|
|
21
21
|
|
|
22
22
|
### Events
|
|
23
23
|
|
|
@@ -100,8 +100,8 @@ Compatibility notes:
|
|
|
100
100
|
| CONTACT_CENTER-R-004 | `deregister()` must remove registered listeners, stop applicable host/calling resources, close primary and RTD WebSockets, clear agent configuration, and surface cleanup failures. | Listener or connection leaks create duplicate events and stale authenticated sessions in long-lived hosts. | `src/cc.ts` | `test/unit/spec/cc.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
|
|
101
101
|
| CONTACT_CENTER-R-005 | On `connectionLost`, ContactCenter must own recovery policy and invoke private `silentRelogin()` only when automated relogin is allowed. | ConnectionService reports transport state; only ContactCenter has agent profile and policy context for authentication recovery. | `src/cc.ts` | `test/unit/spec/cc.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
|
|
102
102
|
| CONTACT_CENTER-R-006 | Expose Agent Wellness Break methods, action-value objects, and types only through the package façade. Derive the public action unions from those `as const` value objects. Action calls accept no identity or context-mutating API; ApiAIAssistant reads effective enablement and organization/agent/session identity from a read-only provider supplied by ContactCenter at construction and rejects when that context is incomplete. Logout, deregistration entry, a current-session multi-login close, and relogin update the provider's source state. The exact system idle-code cache and its in-flight lookup are owned by one registration generation; a newer registration or deregistration rejects a late result instead of caching it. | Wellness actions and cached configuration are registration-scoped and must not leak across agents, relogins, multi-login closures, organizations, or registrations; one public value/type source prevents wire-value drift. | `src/cc.ts`, `src/types.ts`, `src/services/ApiAiAssistant.ts`, `src/index.ts` | `test/unit/spec/cc.ts`, `test/unit/spec/services/ApiAiAssistant.ts`, `docs/samples/contact-center/` | The backend-delivered `agentWellbeing.enable` value is treated as the server rollout decision because no distinct rollout field exists in the supported SDK response contracts. | PRESENT |
|
|
103
|
-
| CONTACT_CENTER-R-007 | When wellness is effectively enabled,
|
|
104
|
-
| CONTACT_CENTER-R-008 | The standalone SDK sample must keep `WellbeingBreak` out of the ordinary idle-code selector, wait for legacy state confirmation and all tasks to become safe, restore
|
|
103
|
+
| CONTACT_CENTER-R-007 | When wellness is effectively enabled, connect the RTD WebSocket even if transcripts and suggested responses are disabled. Route valid `Wellness_Break_Handler` messages from the primary or RTD data-notification socket to `CC_AGENT_EVENTS.WELLNESS_BREAK`. Notification eligibility is scoped to the current agent and organization and deliberately does not compare the notification-provided `agentSessionId` with the active session; outbound wellness APIs remain active-session validated. Ignore malformed or foreign-identity messages without logging the full payload. | A long-lived host needs parity with Desktop notification routing without dropping legitimate nudges whose backend session metadata differs, while actions must still be sent only for the active local session. | `src/cc.ts`, `src/constants.ts`, `src/services/config/types.ts`, `src/services/ApiAiAssistant.ts` | `test/unit/spec/cc.ts`, `test/unit/spec/services/ApiAiAssistant.ts`, `docs/samples/contact-center/` | Notification delivery remains best-effort; the backend owns offer generation and ordering. | PRESENT |
|
|
104
|
+
| CONTACT_CENTER-R-008 | The standalone SDK sample must keep `WellbeingBreak` out of the ordinary idle-code selector, wait for legacy state confirmation and all tasks to become safe, restore `Available` after a completed break with bounded recovery, synchronize authoritative external state changes, use a session-scoped refresh marker without replaying an offer, action, or break, and revoke manual-request eligibility on `WELLNESS_BREAK_NOT_ALLOWED`. A rejected `REJECTED` or `NO_RESPONSE` delivery must retain and re-arm the offer for retry. Logout cleanup must ignore a different agent session, and deregistration cleanup must run when the SDK has completed its local teardown even if a deferred cleanup error is reported. Pure transition helpers own these decisions and are covered behaviorally; browser/source checks are limited to bundle and copy surfaces. | The sample is the executable public-contract reference and must track backend eligibility, avoid duplicated wire literals, and avoid state stranding or cross-session cleanup. | `docs/samples/contact-center/app.js`, `docs/samples/contact-center/wellness-utils.js`, `docs/samples/contact-center/index.html`, `src/webex.js` | `test/unit/spec/wellnessSampleUtils.ts`, sample build | Live QA still supplies authoritative backend/session integration evidence. | PRESENT |
|
|
105
105
|
|
|
106
106
|
## Design Overview
|
|
107
107
|
`ContactCenter` is the package façade and lifecycle owner. Its constructor waits for the host Webex SDK `READY` event, validates plugin configuration, initializes `WebexRequest`, obtains the singleton `Services` graph, and constructs calling, AI-assistant, metrics, task-management, `UserPreference`, and data-service collaborators. `register()` is deliberately narrower: it attaches runtime listeners and establishes the primary Contact Center WebSocket subscription.
|
|
@@ -114,11 +114,11 @@ Durable agent, task, and configuration records remain remote-system owned. The p
|
|
|
114
114
|
|
|
115
115
|
The public enablement signal is `Profile.isWellnessBreakEnabled`. It is true only when the backend-delivered AI feature row has `agentWellbeing.enable === true`, `wellnessBreakReminders === 'ENABLED'`, and the organization reports `aiAssistantQuantity > 0`. The SDK does not create a Desktop Split client or invent a rollout response field: the backend controls rollout by deciding whether the delivered AI feature configuration enables wellness for the organization.
|
|
116
116
|
|
|
117
|
-
After station login or relogin, ContactCenter retains the current agent-session id. ApiAIAssistant reads the current effective gate and organization/agent/session identity through a read-only provider supplied by ContactCenter at construction; it exposes no context-mutating method or separate factory. Logout, deregistration entry, and a current-session multi-login close invalidate the provider's source state. `requestWellnessBreak()` and `respondToWellnessBreak()` do not accept identity fields; they POST a direct custom event with a fresh numeric timestamp and reject disabled or incomplete context before transport. Public action types are derived from exported `as const` action-value objects so applications and samples can use the same wire values without an enum. `getWellbeingBreakIdleCode()` resolves the exact active system code named `WellbeingBreak` and caches it for the registration lifetime. The lookup captures its registration generation and organization before transport; if either ownership value changes before the response arrives, the stale result is rejected and never repopulates the cache.
|
|
117
|
+
After station login or relogin, ContactCenter retains the current agent-session id. When registration silently restores an already logged-in station, the returned `Profile.agentSessionId` projects that active session. It is absent when registration has no active session. This lets hosts recover session-scoped state after refresh without reading SDK internals or trusting a notification's session id. ApiAIAssistant reads the current effective gate and organization/agent/session identity through a read-only provider supplied by ContactCenter at construction; it exposes no context-mutating method or separate factory. Logout, deregistration entry, and a current-session multi-login close invalidate the provider's source state. `requestWellnessBreak()` and `respondToWellnessBreak()` do not accept identity fields; they POST a direct custom event with a fresh numeric timestamp and reject disabled or incomplete context before transport. Public action types are derived from exported `as const` action-value objects so applications and samples can use the same wire values without an enum. `getWellbeingBreakIdleCode()` resolves the exact active system code named `WellbeingBreak` and caches it for the registration lifetime. The lookup captures its registration generation and organization before transport; if either ownership value changes before the response arrives, the stale result is rejected and never repopulates the cache.
|
|
118
118
|
|
|
119
|
-
Wellness payloads are handled by ContactCenter on the primary data-notification socket before ordinary routing. Only known actions with matching agent and organization are emitted; the notification session is retained as diagnostic metadata and is not treated as action authority. The canonical optional `actionText` field is normalized to public `actionText`. Deregistration clears the wellness session and system-code cache.
|
|
119
|
+
Wellness payloads are handled by ContactCenter on the primary or RTD data-notification socket before ordinary routing. Only known actions with matching agent and organization are emitted; the notification session is retained as diagnostic metadata and is not treated as action authority. The canonical optional `actionText` field is normalized to public `actionText`. Deregistration clears the wellness session and system-code cache.
|
|
120
120
|
|
|
121
|
-
The standalone SDK browser sample keeps `WellbeingBreak` out of the ordinary status selector. It reads the exported wellness wire constants from the standalone `Webex` constructor, creates a session-scoped recovery marker before changing legacy state, confirms the transition, sends `ACCEPTED` only after state success, and waits for every task to leave incoming, active, consult, conference, campaign, and wrap-up work before starting its 60-second demonstration timer. Restoration targets `Available / 0`, retries bounded failures, and retains reconnect recovery ownership after exhaustion. Authoritative external Available changes end the local lifecycle, while refresh recovery restores a matching current session without replaying the offer, response action, or break. Pure helpers own notification, response, logout, and deregistration transition decisions; a failed rejection/no-response delivery retains and re-arms its offer. If SDK deregistration completes its local teardown but reports a deferred error, the sample still detaches listeners and resets its local controls.
|
|
121
|
+
The standalone SDK browser sample keeps `WellbeingBreak` out of the ordinary status selector. It reads the exported wellness wire constants from the standalone `Webex` constructor, seeds its current session and legacy state from a logged-in registration profile after silent relogin, and shows only the action name in its latest-event display. It creates a session-scoped recovery marker before changing legacy state, clears manual-request eligibility when a break starts so the request control remains disabled after restoration until another `SUGGEST_WELLNESS_BREAK`, confirms the transition, sends `ACCEPTED` only after state success, and waits for every task to leave incoming, active, consult, conference, campaign, and wrap-up work before starting its 60-second demonstration timer. Restoration targets `Available / 0`, retries bounded failures, and retains reconnect recovery ownership after exhaustion. Authoritative external Available changes end the local lifecycle, while refresh recovery restores a matching current session without replaying the offer, response action, or break. Pure helpers own notification, response, logout, and deregistration transition decisions; a failed rejection/no-response delivery retains and re-arms its offer. If SDK deregistration completes its local teardown but reports a deferred error, the sample still detaches listeners and resets its local controls.
|
|
122
122
|
|
|
123
123
|
### wxApp Better Together (WXCC-6026)
|
|
124
124
|
|
|
@@ -335,7 +335,7 @@ stateDiagram-v2
|
|
|
335
335
|
```
|
|
336
336
|
|
|
337
337
|
## Protocol / Wire Format
|
|
338
|
-
Authenticated REST initiates direct data/config operations and AQM agent/task operations. For AQM, the HTTP response is acknowledgement only; `notifSuccess.bind`/`notifFail.bind` match WebSocket payloads that settle the promise. Wellness actions are the exception: ApiAIAssistant posts a direct `CUSTOM_EVENT` to `/event` and requires HTTP 202. The primary
|
|
338
|
+
Authenticated REST initiates direct data/config operations and AQM agent/task operations. For AQM, the HTTP response is acknowledgement only; `notifSuccess.bind`/`notifFail.bind` match WebSocket payloads that settle the promise. Wellness actions are the exception: ApiAIAssistant posts a direct `CUSTOM_EVENT` to `/event` and requires HTTP 202. The primary and RTD WebSockets can carry `Wellness_Break_Handler`; ContactCenter routes it before task-specific traffic. Payload and event names are owned by `src/types.ts`, `src/services/config/types.ts`, `src/services/agent/types.ts`, and `src/services/task/types.ts`.
|
|
339
339
|
|
|
340
340
|
## Error Handling & Failure Modes
|
|
341
341
|
| Condition | Signal (error/code/result) | Caller recovery |
|
|
@@ -374,7 +374,7 @@ The module registers as `cc` through the Webex SDK plugin system and depends on
|
|
|
374
374
|
| CONTACT_CENTER-R-004 | `test/unit/spec/cc.ts` | listener/resource cleanup and error propagation |
|
|
375
375
|
| CONTACT_CENTER-R-005 | `test/unit/spec/cc.ts` | relogin policy ownership |
|
|
376
376
|
| CONTACT_CENTER-R-006 | `test/unit/spec/cc.ts`, `test/unit/spec/services/ApiAiAssistant.ts` | Effective-gate and internal organization/agent/session validation, current-session multi-login invalidation, registration-generation idle-code cache ownership, identity-free public input, exact request body, action validation, and direct-HTTP failure paths. |
|
|
377
|
-
| CONTACT_CENTER-R-007 | `test/unit/spec/cc.ts`, `test/unit/spec/services/ApiAiAssistant.ts` | Wellness normalization on
|
|
377
|
+
| CONTACT_CENTER-R-007 | `test/unit/spec/cc.ts`, `test/unit/spec/services/ApiAiAssistant.ts` | Wellness normalization on primary and RTD notification sockets, notification-session mismatch acceptance, invalid agent/org filtering, and active-session outbound validation. |
|
|
378
378
|
| CONTACT_CENTER-R-008 | `test/unit/spec/wellnessSampleUtils.ts`, sample build | Safe-work classification, legacy external/RONA decisions, minimal refresh marker, recovery decisions, retryable offer-response transitions, session-scoped logout cleanup, deferred-error deregistration cleanup, and standalone browser constant exposure. |
|
|
379
379
|
|
|
380
380
|
## Traceability
|
package/dist/cc.js
CHANGED
|
@@ -523,6 +523,15 @@ class ContactCenter extends _webexCore.WebexPlugin {
|
|
|
523
523
|
return true;
|
|
524
524
|
}
|
|
525
525
|
handleRTDWebsocketMessage = event => {
|
|
526
|
+
let payload;
|
|
527
|
+
try {
|
|
528
|
+
payload = JSON.parse(event);
|
|
529
|
+
} catch {
|
|
530
|
+
// TaskManager retains its existing malformed RTD message handling.
|
|
531
|
+
}
|
|
532
|
+
if ((0, _Utils.isRecord)(payload) && this.handleWellnessBreakWebsocketPayload(payload)) {
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
526
535
|
this.taskManager.handleRealtimeWebsocketEvent(event);
|
|
527
536
|
};
|
|
528
537
|
|
|
@@ -597,7 +606,14 @@ class ContactCenter extends _webexCore.WebexPlugin {
|
|
|
597
606
|
module: _constants.CC_FILE,
|
|
598
607
|
method: _constants.METHODS.REGISTER
|
|
599
608
|
});
|
|
600
|
-
|
|
609
|
+
|
|
610
|
+
// Registration can silently restore a station session without emitting a
|
|
611
|
+
// relogin event. Project the active session for consumers that must
|
|
612
|
+
// recover session-scoped state after a page refresh.
|
|
613
|
+
return resp.isAgentLoggedIn && this.currentAgentSessionId ? {
|
|
614
|
+
...resp,
|
|
615
|
+
agentSessionId: this.currentAgentSessionId
|
|
616
|
+
} : resp;
|
|
601
617
|
} catch (error) {
|
|
602
618
|
this.metricsManager.trackEvent(_constants4.METRIC_EVENT_NAMES.WEBSOCKET_REGISTER_FAILED, {
|
|
603
619
|
orgId: error.orgId
|
|
@@ -842,8 +858,9 @@ class ContactCenter extends _webexCore.WebexPlugin {
|
|
|
842
858
|
/**
|
|
843
859
|
* RTD websocket currently supports realtime transcripts and suggested responses.
|
|
844
860
|
* Extend this condition when additional AI RTD features are introduced.
|
|
861
|
+
* Wellness break notifications also arrive on this websocket.
|
|
845
862
|
*/
|
|
846
|
-
if (this.agentConfig.aiFeature?.realtimeTranscripts?.enable || this.agentConfig.aiFeature?.suggestedResponses?.enable) {
|
|
863
|
+
if (this.agentConfig.aiFeature?.realtimeTranscripts?.enable || this.agentConfig.aiFeature?.suggestedResponses?.enable || this.agentConfig.isWellnessBreakEnabled) {
|
|
847
864
|
_loggerProxy.default.info('Connecting to RTD websocket', {
|
|
848
865
|
module: _constants.CC_FILE,
|
|
849
866
|
method: _constants.METHODS.CONNECT_WEBSOCKET
|