@webex/contact-center 3.12.0-llmrefactor.2 → 3.12.0-llmrefactor.3
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 +5 -4
- package/ai-docs/ARCHITECTURE.md +1 -1
- package/ai-docs/CONTRACTS.md +5 -1
- package/ai-docs/SECURITY.md +1 -1
- package/ai-docs/contact-center-spec.md +22 -4
- package/ai-docs/features/consult-transfer-list-policy/spec/feature-spec.md +362 -0
- package/dist/cc.js +440 -10
- package/dist/cc.js.map +1 -1
- package/dist/config.js +7 -0
- package/dist/config.js.map +1 -1
- package/dist/constants.js +10 -2
- package/dist/constants.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/metrics/behavioral-events.js +13 -0
- package/dist/metrics/behavioral-events.js.map +1 -1
- package/dist/metrics/constants.js +2 -0
- package/dist/metrics/constants.js.map +1 -1
- package/dist/services/AddressBook.js +18 -15
- package/dist/services/AddressBook.js.map +1 -1
- package/dist/services/AnswerCallOnWebexService.js +174 -0
- package/dist/services/AnswerCallOnWebexService.js.map +1 -0
- package/dist/services/EntryPoint.js +46 -68
- package/dist/services/EntryPoint.js.map +1 -1
- package/dist/services/Queue.js +27 -22
- package/dist/services/Queue.js.map +1 -1
- package/dist/services/WebexCrossClientService.js +171 -0
- package/dist/services/WebexCrossClientService.js.map +1 -0
- package/dist/services/WxAppTelephonyMercurySync.js +93 -0
- package/dist/services/WxAppTelephonyMercurySync.js.map +1 -0
- package/dist/services/config/Util.js +3 -0
- package/dist/services/config/Util.js.map +1 -1
- package/dist/services/config/constants.js +10 -6
- package/dist/services/config/constants.js.map +1 -1
- package/dist/services/config/types.js +4 -0
- package/dist/services/config/types.js.map +1 -1
- package/dist/services/core/Err.js.map +1 -1
- package/dist/services/core/WebexRequest.js +6 -2
- package/dist/services/core/WebexRequest.js.map +1 -1
- package/dist/services/core/aqm-reqs.js +28 -14
- package/dist/services/core/aqm-reqs.js.map +1 -1
- package/dist/services/core/types.js.map +1 -1
- package/dist/services/task/Task.js +73 -7
- package/dist/services/task/Task.js.map +1 -1
- package/dist/services/task/TaskFactory.js +8 -4
- package/dist/services/task/TaskFactory.js.map +1 -1
- package/dist/services/task/TaskManager.js +176 -20
- package/dist/services/task/TaskManager.js.map +1 -1
- package/dist/services/task/WebexCallingUtils.js +70 -0
- package/dist/services/task/WebexCallingUtils.js.map +1 -0
- package/dist/services/task/constants.js +4 -1
- package/dist/services/task/constants.js.map +1 -1
- package/dist/services/task/contact.js +29 -0
- package/dist/services/task/contact.js.map +1 -1
- package/dist/services/task/digital/Digital.js +3 -2
- package/dist/services/task/digital/Digital.js.map +1 -1
- package/dist/services/task/state-machine/TaskStateMachine.js +135 -37
- package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -1
- package/dist/services/task/state-machine/actions.js +6 -1
- package/dist/services/task/state-machine/actions.js.map +1 -1
- package/dist/services/task/state-machine/guards.js +38 -11
- package/dist/services/task/state-machine/guards.js.map +1 -1
- package/dist/services/task/state-machine/types.js.map +1 -1
- package/dist/services/task/state-machine/uiControlsComputer.js +118 -18
- package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -1
- package/dist/services/task/types.js +16 -1
- package/dist/services/task/types.js.map +1 -1
- package/dist/services/task/voice/Voice.js +350 -14
- package/dist/services/task/voice/Voice.js.map +1 -1
- package/dist/services/task/voice/WebRTC.js +4 -1
- package/dist/services/task/voice/WebRTC.js.map +1 -1
- package/dist/services/task/voice/wxAppVoiceMethods.js +201 -0
- package/dist/services/task/voice/wxAppVoiceMethods.js.map +1 -0
- package/dist/services/wxAppTelephonyUtils.js +19 -0
- package/dist/services/wxAppTelephonyUtils.js.map +1 -0
- package/dist/types/cc.d.ts +77 -4
- package/dist/types/config.d.ts +7 -0
- package/dist/types/constants.d.ts +8 -0
- package/dist/types/index.d.ts +3 -1
- package/dist/types/metrics/constants.d.ts +2 -0
- package/dist/types/services/AddressBook.d.ts +2 -1
- package/dist/types/services/AnswerCallOnWebexService.d.ts +37 -0
- package/dist/types/services/EntryPoint.d.ts +7 -5
- package/dist/types/services/Queue.d.ts +5 -3
- package/dist/types/services/WebexCrossClientService.d.ts +28 -0
- package/dist/types/services/WxAppTelephonyMercurySync.d.ts +28 -0
- package/dist/types/services/config/constants.d.ts +8 -5
- package/dist/types/services/config/types.d.ts +17 -4
- package/dist/types/services/core/Err.d.ts +2 -0
- package/dist/types/services/core/WebexRequest.d.ts +1 -0
- package/dist/types/services/core/types.d.ts +2 -0
- package/dist/types/services/task/Task.d.ts +20 -2
- package/dist/types/services/task/TaskFactory.d.ts +2 -1
- package/dist/types/services/task/WebexCallingUtils.d.ts +11 -0
- package/dist/types/services/task/constants.d.ts +3 -0
- package/dist/types/services/task/contact.d.ts +4 -0
- package/dist/types/services/task/digital/Digital.d.ts +2 -2
- package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +260 -56
- package/dist/types/services/task/state-machine/guards.d.ts +6 -5
- package/dist/types/services/task/state-machine/types.d.ts +9 -1
- package/dist/types/services/task/types.d.ts +81 -4
- package/dist/types/services/task/voice/Voice.d.ts +48 -9
- package/dist/types/services/task/voice/WebRTC.d.ts +2 -2
- package/dist/types/services/task/voice/wxAppVoiceMethods.d.ts +52 -0
- package/dist/types/services/wxAppTelephonyUtils.d.ts +5 -0
- package/dist/types/types.d.ts +14 -8
- package/dist/types/utils/PageCache.d.ts +20 -3
- package/dist/types.js +7 -2
- package/dist/types.js.map +1 -1
- package/dist/utils/PageCache.js +19 -5
- package/dist/utils/PageCache.js.map +1 -1
- package/dist/webex.js +1 -1
- package/package.json +1 -1
- package/src/cc.ts +506 -9
- package/src/config.ts +7 -0
- package/src/constants.ts +8 -0
- package/src/index.ts +2 -0
- package/src/metrics/ai-docs/metrics-spec.md +9 -3
- package/src/metrics/behavioral-events.ts +14 -0
- package/src/metrics/constants.ts +2 -0
- package/src/services/AddressBook.ts +17 -6
- package/src/services/AnswerCallOnWebexService.ts +206 -0
- package/src/services/EntryPoint.ts +59 -60
- package/src/services/Queue.ts +29 -12
- package/src/services/WebexCrossClientService.ts +212 -0
- package/src/services/WxAppTelephonyMercurySync.ts +115 -0
- package/src/services/ai-docs/AGENTS.md +10 -10
- package/src/services/ai-docs/services-spec.md +6 -1
- package/src/services/config/Util.ts +3 -0
- package/src/services/config/ai-docs/AGENTS.md +1 -1
- package/src/services/config/ai-docs/ARCHITECTURE.md +2 -2
- package/src/services/config/ai-docs/config-spec.md +6 -0
- package/src/services/config/constants.ts +10 -6
- package/src/services/config/types.ts +16 -4
- package/src/services/core/Err.ts +1 -0
- package/src/services/core/WebexRequest.ts +3 -1
- package/src/services/core/ai-docs/core-spec.md +5 -1
- package/src/services/core/aqm-reqs.ts +30 -15
- package/src/services/core/types.ts +2 -0
- package/src/services/task/Task.ts +79 -8
- package/src/services/task/TaskFactory.ts +8 -3
- package/src/services/task/TaskManager.ts +254 -15
- package/src/services/task/WebexCallingUtils.ts +136 -0
- package/src/services/task/ai-docs/ARCHITECTURE.md +1 -0
- package/src/services/task/ai-docs/task-spec.md +117 -2
- package/src/services/task/constants.ts +3 -0
- package/src/services/task/contact.ts +30 -0
- package/src/services/task/digital/Digital.ts +4 -2
- package/src/services/task/state-machine/TaskStateMachine.ts +210 -63
- package/src/services/task/state-machine/actions.ts +5 -2
- package/src/services/task/state-machine/ai-docs/AGENTS.md +8 -4
- package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +17 -8
- package/src/services/task/state-machine/ai-docs/task-state-machine-spec.md +46 -22
- package/src/services/task/state-machine/guards.ts +64 -11
- package/src/services/task/state-machine/types.ts +16 -1
- package/src/services/task/state-machine/uiControlsComputer.ts +206 -32
- package/src/services/task/types.ts +114 -4
- package/src/services/task/voice/Voice.ts +462 -12
- package/src/services/task/voice/WebRTC.ts +5 -1
- package/src/services/task/voice/wxAppVoiceMethods.ts +307 -0
- package/src/services/wxAppTelephonyUtils.ts +14 -0
- package/src/types.ts +33 -9
- package/src/utils/AGENTS.md +21 -10
- package/src/utils/PageCache.ts +38 -5
- package/src/utils/ai-docs/utils-spec.md +21 -11
- package/test/unit/spec/cc.ts +1274 -0
- package/test/unit/spec/metrics/behavioral-events.ts +18 -0
- package/test/unit/spec/services/AddressBook.ts +37 -6
- package/test/unit/spec/services/AnswerCallOnWebexService.ts +223 -0
- package/test/unit/spec/services/EntryPoint.ts +87 -40
- package/test/unit/spec/services/Queue.ts +123 -12
- package/test/unit/spec/services/WebexCrossClientService.ts +261 -0
- package/test/unit/spec/services/WxAppTelephonyMercurySync.ts +113 -0
- package/test/unit/spec/services/config/Util.ts +85 -0
- package/test/unit/spec/services/core/WebexRequest.ts +3 -1
- package/test/unit/spec/services/core/aqm-reqs.ts +113 -1
- package/test/unit/spec/services/task/Task.ts +200 -0
- package/test/unit/spec/services/task/TaskFactory.ts +39 -2
- package/test/unit/spec/services/task/TaskManager.ts +653 -1
- package/test/unit/spec/services/task/WebexCallingUtils.ts +153 -0
- package/test/unit/spec/services/task/contact.ts +33 -0
- package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +854 -72
- package/test/unit/spec/services/task/state-machine/guards.ts +210 -8
- package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +445 -7
- package/test/unit/spec/services/task/voice/Voice.ts +874 -0
- package/test/unit/spec/services/task/voice/wxAppVoiceMethods.ts +459 -0
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
|
@@ -259,6 +259,7 @@ connectionService.on('connectionLost', (details: ConnectionLostDetails) => {
|
|
|
259
259
|
| CORE-R-004 | ConnectionService must emit transport-state details and retry `initWebSocket({body, resource})`; ContactCenter owns relogin policy. | Separating transport detection from agent recovery prevents Core from mutating package-level session state. | `src/services/core/websocket/connection-service.ts` | `test/unit/spec/services/core/websocket/connection-service.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
|
|
260
260
|
| CORE-R-005 | The keepalive worker must use the configured 4-second interval and 16-second close-socket timeout; AQM defaults to 20 seconds unless disabled/overridden. | Accurate timing is required for predictable recovery and request failure behavior. | `src/services/core/constants.ts` | `test/unit/spec/services/core/websocket/WebSocketManager.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
|
|
261
261
|
| CORE-R-006 | Treat Core timeout, keepalive, and recovery constants as fixed behavior controls, not rollout flags; Core owns no feature-gate evaluation. | Conflating operational constants with rollout policy could disable transport or correlation paths unexpectedly. | `src/services/core/constants.ts`, `src/services/index.ts` | `test/unit/spec/services/core/websocket/WebSocketManager.ts` | None; rollout applicability is explicitly N/A for Core. | PRESENT |
|
|
262
|
+
| CORE-R-007 | When an AQM request sets `redactSensitiveLogs`, routing-failure and timeout logs must omit the request URL, bind key, response, and raw routing payload while preserving settlement and cleanup behavior. | Dynamic request paths and routing messages can contain participant identifiers or phone numbers that must not enter diagnostic logs. | `src/services/core/aqm-reqs.ts`, `src/services/core/types.ts` | `test/unit/spec/services/core/aqm-reqs.ts` | The flag is internal and opt-in; ordinary AQM logging remains backward compatible. | PRESENT |
|
|
262
263
|
|
|
263
264
|
## Design Overview
|
|
264
265
|
Core separates four responsibilities:
|
|
@@ -293,7 +294,7 @@ const setState = aqmReqs.req((p: {data: Agent.StateChange}) => ({
|
|
|
293
294
|
await setState({data: stateChangePayload});
|
|
294
295
|
```
|
|
295
296
|
|
|
296
|
-
`CLOSE_SOCKET_TIMEOUT` is 16000 ms. `CONNECTIVITY_CHECK_INTERVAL` drives reconnect attempts separately. `TIMEOUT_REQ` is the 20000 ms default AQM timeout; `WEBSOCKET_EVENT_TIMEOUT` is not the active AqmReqs default.
|
|
297
|
+
`CLOSE_SOCKET_TIMEOUT` is 16000 ms. `CONNECTIVITY_CHECK_INTERVAL` drives reconnect attempts separately. `TIMEOUT_REQ` is the 20000 ms default AQM timeout; `WEBSOCKET_EVENT_TIMEOUT` is not the active AqmReqs default. A request configuration may set internal `redactSensitiveLogs: true`; this changes only routing-failure and timeout diagnostics, not correlation, errors, timing, or cleanup.
|
|
297
298
|
|
|
298
299
|
## Data Flow
|
|
299
300
|
```mermaid
|
|
@@ -711,11 +712,13 @@ export const generateTaskErrorObject = (
|
|
|
711
712
|
## Pitfalls
|
|
712
713
|
- `initWebSocket` requires both `body` and `resource`; omitting `resource` registers against no durable subscription endpoint.
|
|
713
714
|
- AqmReqs installs notification binds before HTTP and never resolves from acknowledgement; duplicate binds, timeout, and cleanup ordering are correctness-critical.
|
|
715
|
+
- Sensitive AQM configurations must use the opt-in redaction flag so dynamic URLs and raw routing messages are not included in timeout/failure logs.
|
|
714
716
|
- Keepalive closure (16 seconds), lost-connection detection (8 seconds), reconnect interval (5 seconds), and recovery timeout (50 seconds) are separate controls and must not be conflated.
|
|
715
717
|
|
|
716
718
|
## Module Do's / Don'ts
|
|
717
719
|
- DO keep authentication and service resolution in the host Webex request layer; `WebexRequest.request` is a thin delegating wrapper.
|
|
718
720
|
- DO mask authorization headers in the `AqmReqs` HTTP-error/timeout paths before those details are logged or surfaced.
|
|
721
|
+
- DO enable `redactSensitiveLogs` for AQM requests whose dynamic URL or event payload can contain identity/PII.
|
|
719
722
|
- DO clear success/failure/cancel bind entries together when an AQM request settles.
|
|
720
723
|
- DON'T move silent-relogin policy into ConnectionService; it emits transport state only.
|
|
721
724
|
- DON'T treat timeout constants as feature flags or reuse one timer for another lifecycle purpose.
|
|
@@ -747,6 +750,7 @@ Unit tests mirror module paths under `test/unit/spec/services/core`. Preserve po
|
|
|
747
750
|
| `CORE-R-004` | `test/unit/spec/services/core/websocket/connection-service.ts` | None. |
|
|
748
751
|
| `CORE-R-005` | `test/unit/spec/services/core/websocket/WebSocketManager.ts` | Keep timer-value assertions synchronized with constants. |
|
|
749
752
|
| `CORE-R-006` | `test/unit/spec/services/core/websocket/WebSocketManager.ts` | Feature-gate absence is verified from construction/source rather than a dedicated negative test. |
|
|
753
|
+
| `CORE-R-007` | `test/unit/spec/services/core/aqm-reqs.ts` | None. |
|
|
750
754
|
|
|
751
755
|
## Traceability
|
|
752
756
|
- Repo architecture: `../../../../ai-docs/ARCHITECTURE.md` · Registry: `../../../../ai-docs/SPEC_INDEX.md`
|
|
@@ -117,16 +117,24 @@ export default class AqmReqs {
|
|
|
117
117
|
clear();
|
|
118
118
|
const notifFail = c.notifFail!;
|
|
119
119
|
if ('errId' in notifFail) {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
120
|
+
const error = new Err.Details(notifFail.errId, msg as any);
|
|
121
|
+
|
|
122
|
+
if (c.redactSensitiveLogs) {
|
|
123
|
+
LoggerProxy.log('Routing request failed (sensitive details redacted)', {
|
|
124
|
+
module: AQM_REQS_FILE,
|
|
125
|
+
method: METHODS.CREATE_PROMISE,
|
|
126
|
+
});
|
|
127
|
+
} else {
|
|
128
|
+
LoggerProxy.log(`Routing request failed: ${JSON.stringify(msg)}`, {
|
|
129
|
+
module: AQM_REQS_FILE,
|
|
130
|
+
method: METHODS.CREATE_PROMISE,
|
|
131
|
+
});
|
|
132
|
+
LoggerProxy.log(`Routing request failed: ${error}`, {
|
|
133
|
+
module: AQM_REQS_FILE,
|
|
134
|
+
method: METHODS.CREATE_PROMISE,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
reject(error);
|
|
130
138
|
} else {
|
|
131
139
|
reject(notifFail.err(msg as any));
|
|
132
140
|
}
|
|
@@ -176,13 +184,20 @@ export default class AqmReqs {
|
|
|
176
184
|
if (response?.headers) {
|
|
177
185
|
response.headers.Authorization = '*';
|
|
178
186
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
{
|
|
187
|
+
if (c.redactSensitiveLogs) {
|
|
188
|
+
LoggerProxy.error('Routing request timeout (sensitive details redacted)', {
|
|
182
189
|
module: AQM_REQS_FILE,
|
|
183
190
|
method: METHODS.CREATE_PROMISE,
|
|
184
|
-
}
|
|
185
|
-
|
|
191
|
+
});
|
|
192
|
+
} else {
|
|
193
|
+
LoggerProxy.error(
|
|
194
|
+
`Routing request timeout${keySuccess}${JSON.stringify(response)}${c.url}`,
|
|
195
|
+
{
|
|
196
|
+
module: AQM_REQS_FILE,
|
|
197
|
+
method: METHODS.CREATE_PROMISE,
|
|
198
|
+
}
|
|
199
|
+
);
|
|
200
|
+
}
|
|
186
201
|
reject(
|
|
187
202
|
new Err.Details('Service.aqm.reqs.Timeout', {
|
|
188
203
|
key: keySuccess,
|
|
@@ -20,6 +20,8 @@ export type Req<TRes, TErr> = {
|
|
|
20
20
|
url: string;
|
|
21
21
|
host?: string;
|
|
22
22
|
method?: HTTP_METHODS;
|
|
23
|
+
/** Suppress request URLs and routing payloads from AQM logs for sensitive operations. */
|
|
24
|
+
redactSensitiveLogs?: boolean;
|
|
23
25
|
err?:
|
|
24
26
|
| ((errObj: WebexRequestPayload) => Err.Details<'Service.reqs.generic.failure'>)
|
|
25
27
|
| Err.IdsMessage
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
DESTINATION_TYPE,
|
|
12
12
|
TASK_EVENTS,
|
|
13
13
|
TaskUIControls,
|
|
14
|
+
DropConferenceParticipantPayload,
|
|
14
15
|
ConsultEndPayload,
|
|
15
16
|
ConsultPayload,
|
|
16
17
|
ConsultTransferPayLoad,
|
|
@@ -19,8 +20,10 @@ import {
|
|
|
19
20
|
TASK_CHANNEL_TYPE,
|
|
20
21
|
VOICE_VARIANT,
|
|
21
22
|
CallId,
|
|
23
|
+
TaskToggleMuteOptions,
|
|
24
|
+
TaskTransmitDtmfOptions,
|
|
22
25
|
} from './types';
|
|
23
|
-
import {METHODS} from './constants';
|
|
26
|
+
import {ENTRY_POINT_TRANSFER_DESTINATION_TYPE, METHODS} from './constants';
|
|
24
27
|
import {CC_FILE, TASK_FILE} from '../../constants';
|
|
25
28
|
import {getErrorDetails} from '../core/Utils';
|
|
26
29
|
import routingContact from './contact';
|
|
@@ -141,6 +144,14 @@ export default abstract class Task extends EventEmitter implements ITask {
|
|
|
141
144
|
this.unsupportedMethodError('consultConference');
|
|
142
145
|
}
|
|
143
146
|
|
|
147
|
+
public async dropConferenceParticipant(
|
|
148
|
+
// The base task preserves the public signature; Voice provides the implementation.
|
|
149
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
150
|
+
payload: DropConferenceParticipantPayload
|
|
151
|
+
): Promise<TaskResponse> {
|
|
152
|
+
this.unsupportedMethodError(METHODS.DROP_CONFERENCE_PARTICIPANT);
|
|
153
|
+
}
|
|
154
|
+
|
|
144
155
|
public async exitConference(): Promise<TaskResponse> {
|
|
145
156
|
this.unsupportedMethodError('exitConference');
|
|
146
157
|
}
|
|
@@ -153,10 +164,20 @@ export default abstract class Task extends EventEmitter implements ITask {
|
|
|
153
164
|
this.unsupportedMethodError('switchCall');
|
|
154
165
|
}
|
|
155
166
|
|
|
156
|
-
public async toggleMute(): Promise<void> {
|
|
167
|
+
public async toggleMute(options?: TaskToggleMuteOptions): Promise<void> {
|
|
168
|
+
if (options) {
|
|
169
|
+
// parameter intentionally unused
|
|
170
|
+
}
|
|
157
171
|
this.unsupportedMethodError('toggleMute');
|
|
158
172
|
}
|
|
159
173
|
|
|
174
|
+
public async transmitDtmf(options: TaskTransmitDtmfOptions): Promise<void> {
|
|
175
|
+
if (options) {
|
|
176
|
+
// parameter intentionally unused
|
|
177
|
+
}
|
|
178
|
+
this.unsupportedMethodError('transmitDtmf');
|
|
179
|
+
}
|
|
180
|
+
|
|
160
181
|
public unregisterWebCallListeners(): void {
|
|
161
182
|
// Default implementation - child classes can override
|
|
162
183
|
LoggerProxy.log('unregisterWebCallListeners called', {
|
|
@@ -268,6 +289,36 @@ export default abstract class Task extends EventEmitter implements ITask {
|
|
|
268
289
|
*
|
|
269
290
|
* @returns UI control states for all task actions
|
|
270
291
|
*/
|
|
292
|
+
/**
|
|
293
|
+
* Update wxApp thick-client answer flag at runtime (Voice overrides).
|
|
294
|
+
*/
|
|
295
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
296
|
+
public setEnableWxBetterTogether(_enabled: boolean): void {
|
|
297
|
+
// no-op for non-voice tasks
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Apply wxApp mute state from external sync (Voice overrides).
|
|
302
|
+
*/
|
|
303
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
304
|
+
public applyWxAppMuteStateFromSync(_incomingCallId: string, _muted: boolean): void {
|
|
305
|
+
// no-op for non-voice tasks
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Hook for post-assign wxApp sync (Voice overrides).
|
|
310
|
+
*/
|
|
311
|
+
protected onTaskAssigned(): void {
|
|
312
|
+
// no-op by default
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Hook for post-hydrate wxApp sync (Voice overrides).
|
|
317
|
+
*/
|
|
318
|
+
protected onTaskHydrated(): void {
|
|
319
|
+
// no-op by default
|
|
320
|
+
}
|
|
321
|
+
|
|
271
322
|
protected computeUIControls(): TaskUIControls {
|
|
272
323
|
const snapshot = this.stateMachineService?.getSnapshot?.();
|
|
273
324
|
|
|
@@ -277,8 +328,12 @@ export default abstract class Task extends EventEmitter implements ITask {
|
|
|
277
328
|
|
|
278
329
|
const currentState = snapshot.value as TaskState;
|
|
279
330
|
const context = snapshot.context as TaskContext;
|
|
331
|
+
const mergedContext: TaskContext = {
|
|
332
|
+
...context,
|
|
333
|
+
uiControlConfig: {...context.uiControlConfig, ...this.uiControlConfig},
|
|
334
|
+
};
|
|
280
335
|
|
|
281
|
-
const uiControls = computeUIControls(currentState,
|
|
336
|
+
const uiControls = computeUIControls(currentState, mergedContext, this.data);
|
|
282
337
|
|
|
283
338
|
return uiControls;
|
|
284
339
|
}
|
|
@@ -427,9 +482,16 @@ export default abstract class Task extends EventEmitter implements ITask {
|
|
|
427
482
|
emitTaskCampaignPreviewRemoveFailed: this.createEmitSelfAction(
|
|
428
483
|
TASK_EVENTS.TASK_CAMPAIGN_PREVIEW_REMOVE_FAILED
|
|
429
484
|
),
|
|
430
|
-
emitTaskHydrate:
|
|
431
|
-
|
|
432
|
-
|
|
485
|
+
emitTaskHydrate: ({event}: TaskActionArgs) => {
|
|
486
|
+
this.updateTaskFromEvent(event);
|
|
487
|
+
LoggerProxy.info(`Emitting task event ${TASK_EVENTS.TASK_HYDRATE}`, {
|
|
488
|
+
module: TASK_FILE,
|
|
489
|
+
method: 'emitTaskEvent',
|
|
490
|
+
interactionId: this.data?.interactionId,
|
|
491
|
+
});
|
|
492
|
+
this.emit(TASK_EVENTS.TASK_HYDRATE, this);
|
|
493
|
+
this.onTaskHydrated();
|
|
494
|
+
},
|
|
433
495
|
emitTaskOfferContact: this.createEmitSelfAction(TASK_EVENTS.TASK_OFFER_CONTACT, {
|
|
434
496
|
updateTaskData: true,
|
|
435
497
|
}),
|
|
@@ -437,6 +499,7 @@ export default abstract class Task extends EventEmitter implements ITask {
|
|
|
437
499
|
this.updateTaskFromEvent(event);
|
|
438
500
|
this.emit(TASK_EVENTS.TASK_ASSIGNED, this);
|
|
439
501
|
this.emit(TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE, this);
|
|
502
|
+
this.onTaskAssigned();
|
|
440
503
|
},
|
|
441
504
|
emitTaskEnd: this.createEmitSelfAction(TASK_EVENTS.TASK_END, {updateTaskData: true}),
|
|
442
505
|
emitTaskOfferConsult: this.createEmitSelfAction(TASK_EVENTS.TASK_OFFER_CONSULT, {
|
|
@@ -672,10 +735,18 @@ export default abstract class Task extends EventEmitter implements ITask {
|
|
|
672
735
|
METRIC_EVENT_NAMES.TASK_TRANSFER_FAILED,
|
|
673
736
|
]);
|
|
674
737
|
let result: TaskResponse;
|
|
675
|
-
|
|
738
|
+
const isQueueTransfer = transferPayload.destinationType === DESTINATION_TYPE.QUEUE;
|
|
739
|
+
const isEntryPointTransfer = transferPayload.destinationType === DESTINATION_TYPE.ENTRYPOINT;
|
|
740
|
+
|
|
741
|
+
if (isQueueTransfer || isEntryPointTransfer) {
|
|
676
742
|
result = await this.contact.vteamTransfer({
|
|
677
743
|
interactionId: this.data.interactionId,
|
|
678
|
-
data:
|
|
744
|
+
data: {
|
|
745
|
+
...transferPayload,
|
|
746
|
+
destinationType: isEntryPointTransfer
|
|
747
|
+
? ENTRY_POINT_TRANSFER_DESTINATION_TYPE
|
|
748
|
+
: DESTINATION_TYPE.QUEUE,
|
|
749
|
+
},
|
|
679
750
|
});
|
|
680
751
|
} else {
|
|
681
752
|
result = await this.contact.blindTransfer({
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import routingContact from './contact';
|
|
2
2
|
import WebCallingService from '../WebCallingService';
|
|
3
|
+
import AnswerCallOnWebexService from '../AnswerCallOnWebexService';
|
|
3
4
|
import Task from './Task';
|
|
4
5
|
import Voice from './voice/Voice';
|
|
5
6
|
import WebRTC from './voice/WebRTC';
|
|
@@ -18,15 +19,19 @@ export default class TaskFactory {
|
|
|
18
19
|
data: TaskData,
|
|
19
20
|
configFlags: ConfigFlags,
|
|
20
21
|
wrapupData?: WrapupData,
|
|
21
|
-
agentId?: string
|
|
22
|
+
agentId?: string,
|
|
23
|
+
answerCallOnWebexService?: AnswerCallOnWebexService
|
|
22
24
|
): Task {
|
|
23
25
|
const mediaType = data.interaction.mediaType ?? MEDIA_CHANNEL.TELEPHONY;
|
|
24
|
-
const {isEndTaskEnabled, isEndConsultEnabled} = configFlags;
|
|
26
|
+
const {isEndTaskEnabled, isEndConsultEnabled, consultTransfer} = configFlags;
|
|
25
27
|
const recordingEnabled = data?.interaction?.callProcessingDetails?.pauseResumeEnabled ?? true;
|
|
26
28
|
const voiceControlOptions = {
|
|
27
29
|
isEndTaskEnabled,
|
|
28
30
|
isEndConsultEnabled,
|
|
29
31
|
isRecordingEnabled: recordingEnabled,
|
|
32
|
+
enableWxBetterTogether: configFlags.enableWxBetterTogether ?? false,
|
|
33
|
+
answerCallOnWebexService,
|
|
34
|
+
consultTransferConfig: consultTransfer,
|
|
30
35
|
};
|
|
31
36
|
switch (mediaType) {
|
|
32
37
|
case MEDIA_CHANNEL.TELEPHONY:
|
|
@@ -46,7 +51,7 @@ export default class TaskFactory {
|
|
|
46
51
|
case MEDIA_CHANNEL.CHAT:
|
|
47
52
|
case MEDIA_CHANNEL.EMAIL:
|
|
48
53
|
case MEDIA_CHANNEL.SOCIAL:
|
|
49
|
-
return new Digital(contact, data, wrapupData, agentId);
|
|
54
|
+
return new Digital(contact, data, wrapupData, agentId, consultTransfer);
|
|
50
55
|
|
|
51
56
|
default:
|
|
52
57
|
throw new Error(`Unknown media type: ${mediaType}`);
|