@webex/contact-center 3.12.0-llmrefactor.2 → 3.12.0-llmrefactor.4

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 +6 -2
  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 +353 -21
  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 +9 -9
  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 +522 -16
  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 +152 -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 +56 -24
  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 +1294 -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
@@ -13,41 +13,305 @@ var _MetricsManager = _interopRequireDefault(require("../../../metrics/MetricsMa
13
13
  var _constants2 = require("../../../metrics/constants");
14
14
  var _stateMachine = require("../state-machine");
15
15
  var _TaskUtils = require("../TaskUtils");
16
+ var _wxAppTelephonyUtils = require("../../wxAppTelephonyUtils");
17
+ var _wxAppVoiceMethods = require("./wxAppVoiceMethods");
16
18
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
17
19
  class Voice extends _Task.default {
20
+ static WXAPP_MUTE_SYNC_RETRY_DELAY_MS = 50;
21
+ static WXAPP_MUTE_SYNC_MAX_RETRIES = 3;
22
+ enableWxBetterTogether = false;
23
+ wxAppMuted = false;
24
+ wxAppAnswerPending = false;
25
+ wxAppAcceptInFlight = false;
18
26
  constructor(contact, data, callOptions, wrapupData, agentId) {
19
27
  const resolvedOptions = {
20
28
  isEndTaskEnabled: callOptions?.isEndTaskEnabled ?? true,
21
29
  isEndConsultEnabled: callOptions?.isEndConsultEnabled ?? true,
22
30
  voiceVariant: callOptions?.voiceVariant ?? _types.VOICE_VARIANT.PSTN,
23
- isRecordingEnabled: callOptions?.isRecordingEnabled ?? true
31
+ isRecordingEnabled: callOptions?.isRecordingEnabled ?? true,
32
+ enableWxBetterTogether: callOptions?.enableWxBetterTogether ?? false
24
33
  };
25
34
  super(contact, data, {
26
- ...resolvedOptions
35
+ ...resolvedOptions,
36
+ consultTransferConfig: callOptions?.consultTransferConfig
27
37
  }, wrapupData, agentId);
38
+ this.enableWxBetterTogether = resolvedOptions.enableWxBetterTogether;
39
+ this.answerCallOnWebexService = callOptions?.answerCallOnWebexService;
40
+ }
41
+ getWxAppVoiceDependencies() {
42
+ return {
43
+ enableWxBetterTogether: this.enableWxBetterTogether,
44
+ answerCallOnWebexService: this.answerCallOnWebexService,
45
+ agentId: this.agentId,
46
+ getTaskData: () => this.data,
47
+ getTaskState: () => this.stateMachineService?.getSnapshot?.()?.value,
48
+ getWxAppMuted: () => this.wxAppMuted,
49
+ setWxAppMuted: muted => {
50
+ this.wxAppMuted = muted;
51
+ }
52
+ };
53
+ }
54
+
55
+ /** @deprecated Use {@link Voice.getWxAppVoiceDependencies} */
56
+ getWxAppVoiceDeps() {
57
+ return this.getWxAppVoiceDependencies();
58
+ }
59
+ isWebexAppCallingOffer() {
60
+ return (0, _wxAppVoiceMethods.isWebexAppCallingOffer)(this.getWxAppVoiceDeps());
61
+ }
62
+ isWebexAppInboundCallingOffer() {
63
+ return (0, _wxAppVoiceMethods.isWebexAppInboundCallingOffer)(this.getWxAppVoiceDeps());
64
+ }
65
+ setWxAppAnswerPending(pending) {
66
+ this.wxAppAnswerPending = pending;
67
+ this.uiControlConfig = {
68
+ ...this.uiControlConfig,
69
+ wxAppAnswerPending: pending
70
+ };
71
+ this.updateUiControls(true);
72
+ }
73
+ setWxAppAcceptInFlight(inFlight) {
74
+ this.wxAppAcceptInFlight = inFlight;
75
+ this.uiControlConfig = {
76
+ ...this.uiControlConfig,
77
+ wxAppAcceptInFlight: inFlight
78
+ };
79
+ this.updateUiControls(true);
80
+ }
81
+ setEnableWxBetterTogether(enabled) {
82
+ this.enableWxBetterTogether = enabled;
83
+ this.uiControlConfig = {
84
+ ...this.uiControlConfig,
85
+ enableWxBetterTogether: enabled
86
+ };
87
+ this.updateUiControls(true);
88
+ }
89
+ applyWxAppMuteStateFromSync(incomingCallId, muted) {
90
+ if (!this.enableWxBetterTogether) {
91
+ return;
92
+ }
93
+ const activeCallId = this.getWebexCallingCallId();
94
+ if (!activeCallId || !incomingCallId.endsWith(activeCallId) || this.wxAppMuted === muted) {
95
+ return;
96
+ }
97
+ this.wxAppMuted = muted;
98
+ this.emit(_types.TASK_EVENTS.TASK_WXAPP_MUTE_STATE_UPDATED, {
99
+ muted
100
+ });
101
+ }
102
+ getWxAppMuted() {
103
+ return this.wxAppMuted;
104
+ }
105
+ static delay(ms) {
106
+ return new Promise(resolve => {
107
+ setTimeout(resolve, ms);
108
+ });
109
+ }
110
+ canRetryWxAppMuteSync() {
111
+ if (!this.enableWxBetterTogether) {
112
+ return false;
113
+ }
114
+ return Boolean((0, _wxAppVoiceMethods.getCallingDeviceDetails)(this.getWxAppVoiceDeps())?.deviceCallId) && !this.getWebexCallingCallId();
115
+ }
116
+ shouldSkipWxAppMuteSync() {
117
+ if (this.data?.interaction?.isTerminated) {
118
+ return true;
119
+ }
120
+ return this.isWebexAppCallingOffer() && !this.uiControlConfig?.wxAppAnswerPending;
121
+ }
122
+ applyWxAppMuteFromBackfill(callId, muted) {
123
+ if (!this.enableWxBetterTogether || this.wxAppMuted === muted) {
124
+ return;
125
+ }
126
+ const activeCallId = this.getWebexCallingCallId();
127
+ if (activeCallId && !callId.endsWith(activeCallId) && !activeCallId.endsWith(callId)) {
128
+ return;
129
+ }
130
+ this.wxAppMuted = muted;
131
+ this.emit(_types.TASK_EVENTS.TASK_WXAPP_MUTE_STATE_UPDATED, {
132
+ muted
133
+ });
134
+ }
135
+ async syncWxAppMuteFromCallDetails(retryAttempt = 0) {
136
+ if (!this.enableWxBetterTogether || !this.answerCallOnWebexService) {
137
+ return undefined;
138
+ }
139
+ if (retryAttempt === 0 && this.shouldSkipWxAppMuteSync()) {
140
+ return undefined;
141
+ }
142
+ if (retryAttempt === 0 && this.wxAppMuteSyncInFlight) {
143
+ return this.wxAppMuteSyncInFlight;
144
+ }
145
+ const syncPromise = this.performWxAppMuteSync(retryAttempt);
146
+ if (retryAttempt === 0) {
147
+ this.wxAppMuteSyncInFlight = syncPromise;
148
+ syncPromise.finally(() => {
149
+ if (this.wxAppMuteSyncInFlight === syncPromise) {
150
+ this.wxAppMuteSyncInFlight = undefined;
151
+ }
152
+ }).catch(() => undefined);
153
+ return syncPromise;
154
+ }
155
+ return syncPromise;
156
+ }
157
+ async performWxAppMuteSync(retryAttempt) {
158
+ if (this.shouldSkipWxAppMuteSync()) {
159
+ return undefined;
160
+ }
161
+ let callId = this.getWebexCallingCallId();
162
+ if (!callId) {
163
+ if (retryAttempt < Voice.WXAPP_MUTE_SYNC_MAX_RETRIES && this.canRetryWxAppMuteSync()) {
164
+ await Voice.delay(Voice.WXAPP_MUTE_SYNC_RETRY_DELAY_MS);
165
+ return this.performWxAppMuteSync(retryAttempt + 1);
166
+ }
167
+ callId = (0, _wxAppVoiceMethods.getCallingDeviceDetails)(this.getWxAppVoiceDeps())?.deviceCallId ?? null;
168
+ if (!callId) {
169
+ return undefined;
170
+ }
171
+ }
172
+ try {
173
+ const lineOwnerId = (0, _wxAppVoiceMethods.resolveWxAppLineOwnerId)(this.getWxAppVoiceDeps());
174
+ const details = await this.answerCallOnWebexService.getCallDetails({
175
+ callId,
176
+ lineOwnerId
177
+ });
178
+ if (details.muted !== undefined) {
179
+ this.applyWxAppMuteStateFromSync(callId, details.muted);
180
+ if (this.wxAppMuted !== details.muted) {
181
+ this.applyWxAppMuteFromBackfill(callId, details.muted);
182
+ }
183
+ return details.muted;
184
+ }
185
+ return this.wxAppMuted;
186
+ } catch (error) {
187
+ if (!(0, _wxAppTelephonyUtils.isWxAppCallNotFoundError)(error)) {
188
+ _loggerProxy.default.error(`Failed to sync wxApp mute from call details: ${error}`, {
189
+ module: _constants.CC_FILE,
190
+ method: _constants.METHODS.GET_CALL_DETAILS_ON_WEBEX,
191
+ interactionId: this.data?.interactionId
192
+ });
193
+ }
194
+ return undefined;
195
+ }
196
+ }
197
+ onTaskAssigned() {
198
+ this.setWxAppAnswerPending(false);
199
+ queueMicrotask(() => {
200
+ this.syncWxAppMuteFromCallDetails().catch(() => undefined);
201
+ });
202
+ }
203
+ onTaskHydrated() {
204
+ const state = this.stateMachineService?.getSnapshot?.()?.value;
205
+ const answerStillPending = state === _stateMachine.TaskState.OFFERED && (this.uiControlConfig?.wxAppAcceptInFlight || this.uiControlConfig?.wxAppAnswerPending);
206
+ if (!answerStillPending) {
207
+ this.setWxAppAnswerPending(false);
208
+ }
209
+ this.syncWxAppMuteFromCallDetails().catch(() => undefined);
210
+ }
211
+ getCallingDeviceDetails() {
212
+ return (0, _wxAppVoiceMethods.getCallingDeviceDetails)(this.getWxAppVoiceDeps());
213
+ }
214
+ getWebexCallingCallId() {
215
+ return (0, _wxAppVoiceMethods.getWebexCallingCallId)(this.getWxAppVoiceDeps());
216
+ }
217
+ createWxAppLifecycle() {
218
+ return {
219
+ setWxAppAcceptInFlight: inFlight => this.setWxAppAcceptInFlight(inFlight),
220
+ setWxAppAnswerPending: pending => this.setWxAppAnswerPending(pending),
221
+ resetWxAppMuted: () => {
222
+ this.wxAppMuted = false;
223
+ },
224
+ syncWxAppMuteFromCallDetails: () => this.syncWxAppMuteFromCallDetails(),
225
+ mapWxAppVoiceError: (error, method) => (0, _wxAppVoiceMethods.mapWxAppVoiceError)(error, method, _constants.CC_FILE)
226
+ };
28
227
  }
29
228
  getStateMachineSnapshot() {
30
229
  return this.stateMachineService?.getSnapshot?.();
31
230
  }
32
231
 
33
232
  /**
34
- * This method is used to accept the task.
35
- * It is expected to be overridden by child classes.
36
- * @returns Promise<TaskResponse>
37
- * @throws Error
233
+ * Accepts the task. Routes to wxApp telephony answer when `enableWxBetterTogether` and wxApp offer.
38
234
  */
39
235
  async accept() {
40
- super.unsupportedMethodError(_constants.METHODS.ACCEPT);
236
+ if (this.enableWxBetterTogether && this.isWebexAppCallingOffer()) {
237
+ await (0, _wxAppVoiceMethods.runWxAppAccept)(this.getWxAppVoiceDependencies(), this.createWxAppLifecycle());
238
+ return Promise.resolve();
239
+ }
240
+ return super.unsupportedMethodError(_constants.METHODS.ACCEPT);
41
241
  }
42
242
 
43
243
  /**
44
- * This method is used to decline the task.
45
- * It is expected to be overridden by child classes.
46
- * @returns Promise<TaskResponse>
47
- * @throws Error
244
+ * Declines the task. Routes wxApp inbound to telephony reject; wxApp outdial offer to cancelTask.
48
245
  */
49
246
  async decline() {
50
- super.unsupportedMethodError(_constants.METHODS.REJECT);
247
+ if (this.enableWxBetterTogether && this.isWebexAppInboundCallingOffer()) {
248
+ await (0, _wxAppVoiceMethods.runWxAppReject)(this.getWxAppVoiceDependencies(), this.createWxAppLifecycle());
249
+ return Promise.resolve();
250
+ }
251
+ const isOutdial = this.data?.interaction?.outboundType === 'OUTDIAL';
252
+ if (!this.enableWxBetterTogether || !isOutdial || !this.isWebexAppCallingOffer()) {
253
+ return super.unsupportedMethodError(_constants.METHODS.REJECT);
254
+ }
255
+ const interactionId = this.data.interactionId;
256
+ _loggerProxy.default.log(`Declining wxApp outdial task for taskId:${interactionId}`, {
257
+ module: _constants.CC_FILE,
258
+ method: _constants.METHODS.REJECT,
259
+ interactionId
260
+ });
261
+ try {
262
+ this.metricsManager.timeEvent([_constants2.METRIC_EVENT_NAMES.TASK_DECLINE_SUCCESS, _constants2.METRIC_EVENT_NAMES.TASK_DECLINE_FAILED]);
263
+ this.setWxAppAnswerPending(false);
264
+ const response = await this.contact.cancelTask({
265
+ interactionId
266
+ });
267
+ this.metricsManager.trackEvent(_constants2.METRIC_EVENT_NAMES.TASK_DECLINE_SUCCESS, {
268
+ taskId: interactionId,
269
+ ..._MetricsManager.default.getCommonTrackingFieldForAQMResponse(response)
270
+ }, ['operational', 'behavioral']);
271
+ return response;
272
+ } catch (error) {
273
+ this.metricsManager.trackEvent(_constants2.METRIC_EVENT_NAMES.TASK_DECLINE_FAILED, {
274
+ taskId: interactionId,
275
+ error: error.toString(),
276
+ ..._MetricsManager.default.getCommonTrackingFieldForAQMResponseFailed(error.details || {})
277
+ }, ['operational', 'behavioral']);
278
+ const {
279
+ error: detailedError
280
+ } = (0, _Utils.getErrorDetails)(error, _constants.METHODS.REJECT, _constants.CC_FILE);
281
+ throw detailedError;
282
+ }
283
+ }
284
+
285
+ /**
286
+ * Toggles mute for wxApp engaged telephony when `enableWxBetterTogether` is active.
287
+ */
288
+ async toggleMute(options) {
289
+ if (this.enableWxBetterTogether && this.getWebexCallingCallId()) {
290
+ if (this.wxAppMuteToggleInFlight) {
291
+ await this.wxAppMuteToggleInFlight.catch(() => undefined);
292
+ }
293
+ const togglePromise = (0, _wxAppVoiceMethods.runWxAppToggleMute)(this.getWxAppVoiceDependencies(), this.createWxAppLifecycle(), options);
294
+ this.wxAppMuteToggleInFlight = togglePromise;
295
+ togglePromise.finally(() => {
296
+ if (this.wxAppMuteToggleInFlight === togglePromise) {
297
+ this.wxAppMuteToggleInFlight = undefined;
298
+ }
299
+ }).catch(() => undefined);
300
+ await togglePromise;
301
+ return;
302
+ }
303
+ super.unsupportedMethodError(_constants.METHODS.TOGGLE_MUTE);
304
+ }
305
+
306
+ /**
307
+ * Sends in-call DTMF for wxApp engaged telephony when `enableWxBetterTogether` is active.
308
+ */
309
+ async transmitDtmf(options) {
310
+ if (this.enableWxBetterTogether && this.getWebexCallingCallId()) {
311
+ await (0, _wxAppVoiceMethods.runWxAppTransmitDtmf)(this.getWxAppVoiceDependencies(), this.createWxAppLifecycle(), options);
312
+ return;
313
+ }
314
+ super.unsupportedMethodError(_constants.METHODS.TRANSMIT_DTMF);
51
315
  }
52
316
 
53
317
  /**
@@ -667,6 +931,74 @@ class Voice extends _Task.default {
667
931
  }
668
932
  }
669
933
 
934
+ /**
935
+ * Removes another participant from an active conference.
936
+ * Completion is correlated with ParticipantLeftConference by the AQM request layer.
937
+ * @param payload - Participant identifier to remove
938
+ * @returns Promise<TaskResponse>
939
+ */
940
+ async dropConferenceParticipant(payload) {
941
+ // The TypeScript contract requires payload, but the published SDK is also callable from
942
+ // untyped JavaScript. Keep an explicit runtime boundary check before direct property access.
943
+ if (!payload) {
944
+ throw new Error('participantId must be a non-empty string');
945
+ }
946
+ const {
947
+ participantId
948
+ } = payload;
949
+ if (typeof participantId !== 'string' || participantId.trim().length === 0) {
950
+ throw new Error('participantId must be a non-empty string');
951
+ }
952
+ const requestInteractionId = this.data.interaction?.mainInteractionId || this.data.interactionId;
953
+ // taskId identifies the SDK task instance, which can remain child-interaction keyed after
954
+ // consult/EP-DN flows. requestInteractionId identifies the main interaction sent to AQM.
955
+
956
+ _loggerProxy.default.info('Dropping conference participant', {
957
+ module: _constants.CC_FILE,
958
+ method: _constants.METHODS.DROP_CONFERENCE_PARTICIPANT,
959
+ interactionId: requestInteractionId
960
+ });
961
+ try {
962
+ this.metricsManager.timeEvent([_constants2.METRIC_EVENT_NAMES.TASK_CONFERENCE_PARTICIPANT_DROP_SUCCESS, _constants2.METRIC_EVENT_NAMES.TASK_CONFERENCE_PARTICIPANT_DROP_FAILED]);
963
+ const response = await this.contact.dropConferenceParticipant({
964
+ interactionId: requestInteractionId,
965
+ participantId
966
+ });
967
+ this.metricsManager.trackEvent(_constants2.METRIC_EVENT_NAMES.TASK_CONFERENCE_PARTICIPANT_DROP_SUCCESS, {
968
+ taskId: this.data.interactionId,
969
+ requestInteractionId,
970
+ ..._MetricsManager.default.getCommonTrackingFieldForAQMResponse(response),
971
+ agentId: this.agentId
972
+ }, ['operational', 'behavioral', 'business']);
973
+ _loggerProxy.default.log('Successfully dropped conference participant', {
974
+ module: _constants.CC_FILE,
975
+ method: _constants.METHODS.DROP_CONFERENCE_PARTICIPANT,
976
+ trackingId: response?.trackingId,
977
+ interactionId: requestInteractionId
978
+ });
979
+ return response;
980
+ } catch (error) {
981
+ const failureTrackingFields = _MetricsManager.default.getCommonTrackingFieldForAQMResponseFailed(error?.details || {});
982
+ this.metricsManager.trackEvent(_constants2.METRIC_EVENT_NAMES.TASK_CONFERENCE_PARTICIPANT_DROP_FAILED, {
983
+ taskId: this.data.interactionId,
984
+ requestInteractionId,
985
+ agentId: this.agentId,
986
+ trackingId: failureTrackingFields.trackingId,
987
+ notifTrackingId: failureTrackingFields.notifTrackingId,
988
+ orgId: failureTrackingFields.orgId,
989
+ failureType: failureTrackingFields.failureType,
990
+ reasonCode: failureTrackingFields.reasonCode
991
+ }, ['operational', 'behavioral', 'business']);
992
+ _loggerProxy.default.error('Failed to drop conference participant', {
993
+ module: _constants.CC_FILE,
994
+ method: _constants.METHODS.DROP_CONFERENCE_PARTICIPANT,
995
+ trackingId: failureTrackingFields.trackingId,
996
+ interactionId: requestInteractionId
997
+ });
998
+ throw error;
999
+ }
1000
+ }
1001
+
670
1002
  /**
671
1003
  * Exit from a conference call.
672
1004
  * Per conference-spec.md:
@@ -1031,8 +1363,12 @@ class Voice extends _Task.default {
1031
1363
  emitTaskOutdialFailed: ({
1032
1364
  event
1033
1365
  }) => {
1034
- if (event && 'taskData' in event && event.taskData) {
1035
- this.updateTaskData(event.taskData);
1366
+ const taskData = event?.taskData;
1367
+ if (taskData) {
1368
+ this.updateTaskData(taskData);
1369
+ }
1370
+ if (taskData?.suppressOutdialFailedPopup) {
1371
+ return;
1036
1372
  }
1037
1373
  const reason = event?.reason || 'Outdial failed';
1038
1374
  this.emit(_types.TASK_EVENTS.TASK_OUTDIAL_FAILED, reason);