@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.
Files changed (187) hide show
  1. package/.sdd/manifest.json +5 -4
  2. package/ai-docs/ARCHITECTURE.md +1 -1
  3. package/ai-docs/CONTRACTS.md +5 -1
  4. package/ai-docs/SECURITY.md +1 -1
  5. package/ai-docs/contact-center-spec.md +22 -4
  6. package/ai-docs/features/consult-transfer-list-policy/spec/feature-spec.md +362 -0
  7. package/dist/cc.js +440 -10
  8. package/dist/cc.js.map +1 -1
  9. package/dist/config.js +7 -0
  10. package/dist/config.js.map +1 -1
  11. package/dist/constants.js +10 -2
  12. package/dist/constants.js.map +1 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/metrics/behavioral-events.js +13 -0
  15. package/dist/metrics/behavioral-events.js.map +1 -1
  16. package/dist/metrics/constants.js +2 -0
  17. package/dist/metrics/constants.js.map +1 -1
  18. package/dist/services/AddressBook.js +18 -15
  19. package/dist/services/AddressBook.js.map +1 -1
  20. package/dist/services/AnswerCallOnWebexService.js +174 -0
  21. package/dist/services/AnswerCallOnWebexService.js.map +1 -0
  22. package/dist/services/EntryPoint.js +46 -68
  23. package/dist/services/EntryPoint.js.map +1 -1
  24. package/dist/services/Queue.js +27 -22
  25. package/dist/services/Queue.js.map +1 -1
  26. package/dist/services/WebexCrossClientService.js +171 -0
  27. package/dist/services/WebexCrossClientService.js.map +1 -0
  28. package/dist/services/WxAppTelephonyMercurySync.js +93 -0
  29. package/dist/services/WxAppTelephonyMercurySync.js.map +1 -0
  30. package/dist/services/config/Util.js +3 -0
  31. package/dist/services/config/Util.js.map +1 -1
  32. package/dist/services/config/constants.js +10 -6
  33. package/dist/services/config/constants.js.map +1 -1
  34. package/dist/services/config/types.js +4 -0
  35. package/dist/services/config/types.js.map +1 -1
  36. package/dist/services/core/Err.js.map +1 -1
  37. package/dist/services/core/WebexRequest.js +6 -2
  38. package/dist/services/core/WebexRequest.js.map +1 -1
  39. package/dist/services/core/aqm-reqs.js +28 -14
  40. package/dist/services/core/aqm-reqs.js.map +1 -1
  41. package/dist/services/core/types.js.map +1 -1
  42. package/dist/services/task/Task.js +73 -7
  43. package/dist/services/task/Task.js.map +1 -1
  44. package/dist/services/task/TaskFactory.js +8 -4
  45. package/dist/services/task/TaskFactory.js.map +1 -1
  46. package/dist/services/task/TaskManager.js +176 -20
  47. package/dist/services/task/TaskManager.js.map +1 -1
  48. package/dist/services/task/WebexCallingUtils.js +70 -0
  49. package/dist/services/task/WebexCallingUtils.js.map +1 -0
  50. package/dist/services/task/constants.js +4 -1
  51. package/dist/services/task/constants.js.map +1 -1
  52. package/dist/services/task/contact.js +29 -0
  53. package/dist/services/task/contact.js.map +1 -1
  54. package/dist/services/task/digital/Digital.js +3 -2
  55. package/dist/services/task/digital/Digital.js.map +1 -1
  56. package/dist/services/task/state-machine/TaskStateMachine.js +135 -37
  57. package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -1
  58. package/dist/services/task/state-machine/actions.js +6 -1
  59. package/dist/services/task/state-machine/actions.js.map +1 -1
  60. package/dist/services/task/state-machine/guards.js +38 -11
  61. package/dist/services/task/state-machine/guards.js.map +1 -1
  62. package/dist/services/task/state-machine/types.js.map +1 -1
  63. package/dist/services/task/state-machine/uiControlsComputer.js +118 -18
  64. package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -1
  65. package/dist/services/task/types.js +16 -1
  66. package/dist/services/task/types.js.map +1 -1
  67. package/dist/services/task/voice/Voice.js +350 -14
  68. package/dist/services/task/voice/Voice.js.map +1 -1
  69. package/dist/services/task/voice/WebRTC.js +4 -1
  70. package/dist/services/task/voice/WebRTC.js.map +1 -1
  71. package/dist/services/task/voice/wxAppVoiceMethods.js +201 -0
  72. package/dist/services/task/voice/wxAppVoiceMethods.js.map +1 -0
  73. package/dist/services/wxAppTelephonyUtils.js +19 -0
  74. package/dist/services/wxAppTelephonyUtils.js.map +1 -0
  75. package/dist/types/cc.d.ts +77 -4
  76. package/dist/types/config.d.ts +7 -0
  77. package/dist/types/constants.d.ts +8 -0
  78. package/dist/types/index.d.ts +3 -1
  79. package/dist/types/metrics/constants.d.ts +2 -0
  80. package/dist/types/services/AddressBook.d.ts +2 -1
  81. package/dist/types/services/AnswerCallOnWebexService.d.ts +37 -0
  82. package/dist/types/services/EntryPoint.d.ts +7 -5
  83. package/dist/types/services/Queue.d.ts +5 -3
  84. package/dist/types/services/WebexCrossClientService.d.ts +28 -0
  85. package/dist/types/services/WxAppTelephonyMercurySync.d.ts +28 -0
  86. package/dist/types/services/config/constants.d.ts +8 -5
  87. package/dist/types/services/config/types.d.ts +17 -4
  88. package/dist/types/services/core/Err.d.ts +2 -0
  89. package/dist/types/services/core/WebexRequest.d.ts +1 -0
  90. package/dist/types/services/core/types.d.ts +2 -0
  91. package/dist/types/services/task/Task.d.ts +20 -2
  92. package/dist/types/services/task/TaskFactory.d.ts +2 -1
  93. package/dist/types/services/task/WebexCallingUtils.d.ts +11 -0
  94. package/dist/types/services/task/constants.d.ts +3 -0
  95. package/dist/types/services/task/contact.d.ts +4 -0
  96. package/dist/types/services/task/digital/Digital.d.ts +2 -2
  97. package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +260 -56
  98. package/dist/types/services/task/state-machine/guards.d.ts +6 -5
  99. package/dist/types/services/task/state-machine/types.d.ts +9 -1
  100. package/dist/types/services/task/types.d.ts +81 -4
  101. package/dist/types/services/task/voice/Voice.d.ts +48 -9
  102. package/dist/types/services/task/voice/WebRTC.d.ts +2 -2
  103. package/dist/types/services/task/voice/wxAppVoiceMethods.d.ts +52 -0
  104. package/dist/types/services/wxAppTelephonyUtils.d.ts +5 -0
  105. package/dist/types/types.d.ts +14 -8
  106. package/dist/types/utils/PageCache.d.ts +20 -3
  107. package/dist/types.js +7 -2
  108. package/dist/types.js.map +1 -1
  109. package/dist/utils/PageCache.js +19 -5
  110. package/dist/utils/PageCache.js.map +1 -1
  111. package/dist/webex.js +1 -1
  112. package/package.json +1 -1
  113. package/src/cc.ts +506 -9
  114. package/src/config.ts +7 -0
  115. package/src/constants.ts +8 -0
  116. package/src/index.ts +2 -0
  117. package/src/metrics/ai-docs/metrics-spec.md +9 -3
  118. package/src/metrics/behavioral-events.ts +14 -0
  119. package/src/metrics/constants.ts +2 -0
  120. package/src/services/AddressBook.ts +17 -6
  121. package/src/services/AnswerCallOnWebexService.ts +206 -0
  122. package/src/services/EntryPoint.ts +59 -60
  123. package/src/services/Queue.ts +29 -12
  124. package/src/services/WebexCrossClientService.ts +212 -0
  125. package/src/services/WxAppTelephonyMercurySync.ts +115 -0
  126. package/src/services/ai-docs/AGENTS.md +10 -10
  127. package/src/services/ai-docs/services-spec.md +6 -1
  128. package/src/services/config/Util.ts +3 -0
  129. package/src/services/config/ai-docs/AGENTS.md +1 -1
  130. package/src/services/config/ai-docs/ARCHITECTURE.md +2 -2
  131. package/src/services/config/ai-docs/config-spec.md +6 -0
  132. package/src/services/config/constants.ts +10 -6
  133. package/src/services/config/types.ts +16 -4
  134. package/src/services/core/Err.ts +1 -0
  135. package/src/services/core/WebexRequest.ts +3 -1
  136. package/src/services/core/ai-docs/core-spec.md +5 -1
  137. package/src/services/core/aqm-reqs.ts +30 -15
  138. package/src/services/core/types.ts +2 -0
  139. package/src/services/task/Task.ts +79 -8
  140. package/src/services/task/TaskFactory.ts +8 -3
  141. package/src/services/task/TaskManager.ts +254 -15
  142. package/src/services/task/WebexCallingUtils.ts +136 -0
  143. package/src/services/task/ai-docs/ARCHITECTURE.md +1 -0
  144. package/src/services/task/ai-docs/task-spec.md +117 -2
  145. package/src/services/task/constants.ts +3 -0
  146. package/src/services/task/contact.ts +30 -0
  147. package/src/services/task/digital/Digital.ts +4 -2
  148. package/src/services/task/state-machine/TaskStateMachine.ts +210 -63
  149. package/src/services/task/state-machine/actions.ts +5 -2
  150. package/src/services/task/state-machine/ai-docs/AGENTS.md +8 -4
  151. package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +17 -8
  152. package/src/services/task/state-machine/ai-docs/task-state-machine-spec.md +46 -22
  153. package/src/services/task/state-machine/guards.ts +64 -11
  154. package/src/services/task/state-machine/types.ts +16 -1
  155. package/src/services/task/state-machine/uiControlsComputer.ts +206 -32
  156. package/src/services/task/types.ts +114 -4
  157. package/src/services/task/voice/Voice.ts +462 -12
  158. package/src/services/task/voice/WebRTC.ts +5 -1
  159. package/src/services/task/voice/wxAppVoiceMethods.ts +307 -0
  160. package/src/services/wxAppTelephonyUtils.ts +14 -0
  161. package/src/types.ts +33 -9
  162. package/src/utils/AGENTS.md +21 -10
  163. package/src/utils/PageCache.ts +38 -5
  164. package/src/utils/ai-docs/utils-spec.md +21 -11
  165. package/test/unit/spec/cc.ts +1274 -0
  166. package/test/unit/spec/metrics/behavioral-events.ts +18 -0
  167. package/test/unit/spec/services/AddressBook.ts +37 -6
  168. package/test/unit/spec/services/AnswerCallOnWebexService.ts +223 -0
  169. package/test/unit/spec/services/EntryPoint.ts +87 -40
  170. package/test/unit/spec/services/Queue.ts +123 -12
  171. package/test/unit/spec/services/WebexCrossClientService.ts +261 -0
  172. package/test/unit/spec/services/WxAppTelephonyMercurySync.ts +113 -0
  173. package/test/unit/spec/services/config/Util.ts +85 -0
  174. package/test/unit/spec/services/core/WebexRequest.ts +3 -1
  175. package/test/unit/spec/services/core/aqm-reqs.ts +113 -1
  176. package/test/unit/spec/services/task/Task.ts +200 -0
  177. package/test/unit/spec/services/task/TaskFactory.ts +39 -2
  178. package/test/unit/spec/services/task/TaskManager.ts +653 -1
  179. package/test/unit/spec/services/task/WebexCallingUtils.ts +153 -0
  180. package/test/unit/spec/services/task/contact.ts +33 -0
  181. package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +854 -72
  182. package/test/unit/spec/services/task/state-machine/guards.ts +210 -8
  183. package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +445 -7
  184. package/test/unit/spec/services/task/voice/Voice.ts +874 -0
  185. package/test/unit/spec/services/task/voice/wxAppVoiceMethods.ts +459 -0
  186. package/umd/contact-center.min.js +2 -2
  187. 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
- LoggerProxy.log(`Routing request failed: ${JSON.stringify(msg)}`, {
121
- module: AQM_REQS_FILE,
122
- method: METHODS.CREATE_PROMISE,
123
- });
124
- const eerr = new Err.Details(notifFail.errId, msg as any);
125
- LoggerProxy.log(`Routing request failed: ${eerr}`, {
126
- module: AQM_REQS_FILE,
127
- method: METHODS.CREATE_PROMISE,
128
- });
129
- reject(eerr);
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
- LoggerProxy.error(
180
- `Routing request timeout${keySuccess}${JSON.stringify(response)}${c.url}`,
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, context, this.data);
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: this.createEmitSelfAction(TASK_EVENTS.TASK_HYDRATE, {
431
- updateTaskData: true,
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
- if (transferPayload.destinationType === DESTINATION_TYPE.QUEUE) {
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: transferPayload,
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}`);