@webex/contact-center 3.11.0 → 3.12.0-auth-prejoin-fetch.1
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 +883 -0
- package/AGENTS.md +94 -0
- package/ai-docs/ARCHITECTURE.md +168 -0
- package/ai-docs/CONTRACTS.md +50 -0
- package/ai-docs/GETTING_STARTED.md +168 -0
- package/ai-docs/GLOSSARY.md +43 -0
- package/ai-docs/README.md +138 -0
- package/ai-docs/REVIEW_CHECKLIST.md +41 -0
- package/ai-docs/RULES.md +444 -0
- package/ai-docs/SECURITY.md +52 -0
- package/ai-docs/SERVICE_STATE.md +48 -0
- package/ai-docs/SPEC_INDEX.md +65 -0
- package/ai-docs/adr/0001-spec-source-policy.md +55 -0
- package/ai-docs/adr/README.md +8 -0
- package/ai-docs/adr/_adr-template.md +31 -0
- package/ai-docs/contact-center-spec.md +359 -0
- package/ai-docs/features/consult-transfer-list-policy/spec/feature-spec.md +362 -0
- package/ai-docs/features/generated-spec-conformance-fidelity-remediation/spec/feature-spec.md +117 -0
- package/ai-docs/features/residual-warning-coverage-completion/spec/feature-spec.md +203 -0
- package/ai-docs/features/validator-code-fidelity-drift-fix/spec/feature-spec.md +315 -0
- package/ai-docs/patterns/event-driven-patterns.md +485 -0
- package/ai-docs/patterns/testing-patterns.md +480 -0
- package/ai-docs/patterns/typescript-patterns.md +365 -0
- package/ai-docs/templates/README.md +102 -0
- package/ai-docs/templates/documentation/create-agents-md.md +240 -0
- package/ai-docs/templates/documentation/create-architecture-md.md +295 -0
- package/ai-docs/templates/existing-service/bug-fix.md +254 -0
- package/ai-docs/templates/existing-service/feature-enhancement.md +450 -0
- package/ai-docs/templates/new-method/00-master.md +80 -0
- package/ai-docs/templates/new-method/01-requirements.md +232 -0
- package/ai-docs/templates/new-method/02-implementation.md +295 -0
- package/ai-docs/templates/new-method/03-tests.md +201 -0
- package/ai-docs/templates/new-method/04-validation.md +141 -0
- package/ai-docs/templates/new-service/00-master.md +109 -0
- package/ai-docs/templates/new-service/01-pre-questions.md +159 -0
- package/ai-docs/templates/new-service/02-code-generation.md +346 -0
- package/ai-docs/templates/new-service/03-integration.md +178 -0
- package/ai-docs/templates/new-service/04-test-generation.md +205 -0
- package/ai-docs/templates/new-service/05-validation.md +145 -0
- package/dist/cc.js +818 -59
- package/dist/cc.js.map +1 -1
- package/dist/config.js +13 -0
- package/dist/config.js.map +1 -1
- package/dist/constants.js +31 -3
- package/dist/constants.js.map +1 -1
- package/dist/index.js +27 -5
- package/dist/index.js.map +1 -1
- package/dist/metrics/behavioral-events.js +127 -0
- package/dist/metrics/behavioral-events.js.map +1 -1
- package/dist/metrics/constants.js +34 -3
- 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/ApiAiAssistant.js +318 -0
- package/dist/services/ApiAiAssistant.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/UserPreference.js +427 -0
- package/dist/services/UserPreference.js.map +1 -0
- 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/agent/types.js.map +1 -1
- package/dist/services/config/Util.js +11 -4
- package/dist/services/config/Util.js.map +1 -1
- package/dist/services/config/constants.js +45 -8
- package/dist/services/config/constants.js.map +1 -1
- package/dist/services/config/index.js +41 -2
- package/dist/services/config/index.js.map +1 -1
- package/dist/services/config/types.js +70 -8
- package/dist/services/config/types.js.map +1 -1
- package/dist/services/constants.js +27 -1
- package/dist/services/constants.js.map +1 -1
- package/dist/services/core/Err.js.map +1 -1
- package/dist/services/core/Utils.js +122 -25
- package/dist/services/core/Utils.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 +119 -30
- package/dist/services/core/aqm-reqs.js.map +1 -1
- package/dist/services/core/types.js.map +1 -1
- package/dist/services/core/websocket/WebSocketManager.js +22 -6
- package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
- package/dist/services/core/websocket/connection-service.js +3 -1
- package/dist/services/core/websocket/connection-service.js.map +1 -1
- package/dist/services/core/websocket/types.js.map +1 -1
- package/dist/services/index.js +6 -0
- package/dist/services/index.js.map +1 -1
- package/dist/services/task/Task.js +754 -0
- package/dist/services/task/Task.js.map +1 -0
- package/dist/services/task/TaskFactory.js +49 -0
- package/dist/services/task/TaskFactory.js.map +1 -0
- package/dist/services/task/TaskManager.js +1073 -447
- package/dist/services/task/TaskManager.js.map +1 -1
- package/dist/services/task/TaskUtils.js +220 -23
- package/dist/services/task/TaskUtils.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 +26 -2
- 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/dialer.js +129 -0
- package/dist/services/task/dialer.js.map +1 -1
- package/dist/services/task/digital/Digital.js +78 -0
- package/dist/services/task/digital/Digital.js.map +1 -0
- package/dist/services/task/state-machine/TaskStateMachine.js +971 -0
- package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -0
- package/dist/services/task/state-machine/actions.js +572 -0
- package/dist/services/task/state-machine/actions.js.map +1 -0
- package/dist/services/task/state-machine/constants.js +161 -0
- package/dist/services/task/state-machine/constants.js.map +1 -0
- package/dist/services/task/state-machine/guards.js +409 -0
- package/dist/services/task/state-machine/guards.js.map +1 -0
- package/dist/services/task/state-machine/index.js +53 -0
- package/dist/services/task/state-machine/index.js.map +1 -0
- package/dist/services/task/state-machine/types.js +54 -0
- package/dist/services/task/state-machine/types.js.map +1 -0
- package/dist/services/task/state-machine/uiControlsComputer.js +703 -0
- package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -0
- package/dist/services/task/taskDataNormalizer.js +99 -0
- package/dist/services/task/taskDataNormalizer.js.map +1 -0
- package/dist/services/task/types.js +243 -5
- package/dist/services/task/types.js.map +1 -1
- package/dist/services/task/voice/Voice.js +1380 -0
- package/dist/services/task/voice/Voice.js.map +1 -0
- package/dist/services/task/voice/WebRTC.js +152 -0
- package/dist/services/task/voice/WebRTC.js.map +1 -0
- 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 +967 -0
- package/dist/types/config.d.ts +79 -0
- package/dist/types/constants.d.ts +74 -0
- package/dist/types/index.d.ts +201 -0
- package/dist/types/logger-proxy.d.ts +71 -0
- package/dist/types/metrics/MetricsManager.d.ts +223 -0
- package/dist/types/metrics/behavioral-events.d.ts +29 -0
- package/dist/types/metrics/constants.d.ts +183 -0
- package/dist/types/services/AddressBook.d.ts +75 -0
- package/dist/types/services/AnswerCallOnWebexService.d.ts +37 -0
- package/dist/types/services/ApiAiAssistant.d.ts +49 -0
- package/dist/types/services/EntryPoint.d.ts +69 -0
- package/dist/types/services/Queue.d.ts +78 -0
- package/dist/types/services/UserPreference.d.ts +118 -0
- package/dist/types/services/WebCallingService.d.ts +1 -0
- package/dist/types/services/WebexCrossClientService.d.ts +28 -0
- package/dist/types/services/WxAppTelephonyMercurySync.d.ts +28 -0
- package/dist/types/services/agent/index.d.ts +46 -0
- package/dist/types/services/agent/types.d.ts +413 -0
- package/dist/types/services/config/Util.d.ts +20 -0
- package/dist/types/services/config/constants.d.ts +273 -0
- package/dist/types/services/config/index.d.ts +177 -0
- package/dist/types/services/config/types.d.ts +1381 -0
- package/dist/types/services/constants.d.ts +110 -0
- package/dist/types/services/core/Err.d.ts +127 -0
- package/dist/types/services/core/GlobalTypes.d.ts +58 -0
- package/dist/types/services/core/Utils.d.ts +121 -0
- package/dist/types/services/core/WebexRequest.d.ts +23 -0
- package/dist/types/services/core/aqm-reqs.d.ts +65 -0
- package/dist/types/services/core/constants.d.ts +99 -0
- package/dist/types/services/core/types.d.ts +49 -0
- package/dist/types/services/core/websocket/WebSocketManager.d.ts +36 -0
- package/dist/types/services/core/websocket/connection-service.d.ts +27 -0
- package/dist/types/services/core/websocket/keepalive.worker.d.ts +2 -0
- package/dist/types/services/core/websocket/types.d.ts +37 -0
- package/dist/types/services/index.d.ts +54 -0
- package/dist/types/services/task/AutoWrapup.d.ts +40 -0
- package/dist/types/services/task/Task.d.ts +175 -0
- package/dist/types/services/task/TaskFactory.d.ts +13 -0
- package/dist/types/services/task/TaskManager.d.ts +1 -0
- package/dist/types/services/task/TaskUtils.d.ts +138 -0
- package/dist/types/services/task/WebexCallingUtils.d.ts +11 -0
- package/dist/types/services/task/constants.d.ts +94 -0
- package/dist/types/services/task/contact.d.ts +73 -0
- package/dist/types/services/task/dialer.d.ts +73 -0
- package/dist/types/services/task/digital/Digital.d.ts +22 -0
- package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +1398 -0
- package/dist/types/services/task/state-machine/actions.d.ts +10 -0
- package/dist/types/services/task/state-machine/constants.d.ts +107 -0
- package/dist/types/services/task/state-machine/guards.d.ts +103 -0
- package/dist/types/services/task/state-machine/index.d.ts +13 -0
- package/dist/types/services/task/state-machine/types.d.ts +277 -0
- package/dist/types/services/task/state-machine/uiControlsComputer.d.ts +9 -0
- package/dist/types/services/task/taskDataNormalizer.d.ts +10 -0
- package/dist/types/services/task/types.d.ts +1933 -0
- package/dist/types/services/task/voice/Voice.d.ts +223 -0
- package/dist/types/services/task/voice/WebRTC.d.ts +53 -0
- 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 +784 -0
- package/dist/types/utils/PageCache.d.ts +190 -0
- package/dist/types/webex-config.d.ts +53 -0
- package/dist/types/webex.d.ts +8 -0
- package/dist/types.js +137 -3
- 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 +14 -2
- package/dist/webex.js.map +1 -1
- package/package.json +16 -12
- package/src/cc.ts +983 -60
- package/src/config.ts +13 -0
- package/src/constants.ts +29 -1
- package/src/index.ts +26 -5
- package/src/metrics/ai-docs/AGENTS.md +350 -0
- package/src/metrics/ai-docs/ARCHITECTURE.md +338 -0
- package/src/metrics/ai-docs/metrics-spec.md +860 -0
- package/src/metrics/behavioral-events.ts +134 -0
- package/src/metrics/constants.ts +39 -3
- package/src/services/AddressBook.ts +17 -6
- package/src/services/AnswerCallOnWebexService.ts +206 -0
- package/src/services/ApiAiAssistant.ts +412 -0
- package/src/services/EntryPoint.ts +59 -60
- package/src/services/Queue.ts +29 -12
- package/src/services/UserPreference.ts +509 -0
- package/src/services/WebexCrossClientService.ts +212 -0
- package/src/services/WxAppTelephonyMercurySync.ts +115 -0
- package/src/services/agent/ai-docs/AGENTS.md +240 -0
- package/src/services/agent/ai-docs/ARCHITECTURE.md +304 -0
- package/src/services/agent/ai-docs/agent-spec.md +504 -0
- package/src/services/agent/types.ts +1 -1
- package/src/services/ai-docs/AGENTS.md +386 -0
- package/src/services/ai-docs/services-spec.md +497 -0
- package/src/services/config/Util.ts +13 -2
- package/src/services/config/ai-docs/AGENTS.md +255 -0
- package/src/services/config/ai-docs/ARCHITECTURE.md +426 -0
- package/src/services/config/ai-docs/config-spec.md +675 -0
- package/src/services/config/constants.ts +47 -7
- package/src/services/config/index.ts +45 -1
- package/src/services/config/types.ts +253 -11
- package/src/services/constants.ts +29 -0
- package/src/services/core/Err.ts +4 -0
- package/src/services/core/Utils.ts +143 -30
- package/src/services/core/WebexRequest.ts +3 -1
- package/src/services/core/ai-docs/AGENTS.md +381 -0
- package/src/services/core/ai-docs/ARCHITECTURE.md +698 -0
- package/src/services/core/ai-docs/core-spec.md +787 -0
- package/src/services/core/aqm-reqs.ts +125 -32
- package/src/services/core/types.ts +2 -0
- package/src/services/core/websocket/WebSocketManager.ts +23 -6
- package/src/services/core/websocket/connection-service.ts +5 -1
- package/src/services/core/websocket/types.ts +1 -1
- package/src/services/index.ts +4 -0
- package/src/services/task/Task.ts +908 -0
- package/src/services/task/TaskFactory.ts +60 -0
- package/src/services/task/TaskManager.ts +1291 -513
- package/src/services/task/TaskUtils.ts +314 -24
- package/src/services/task/WebexCallingUtils.ts +136 -0
- package/src/services/task/ai-docs/AGENTS.md +457 -0
- package/src/services/task/ai-docs/ARCHITECTURE.md +595 -0
- package/src/services/task/ai-docs/task-spec.md +1469 -0
- package/src/services/task/constants.ts +26 -0
- package/src/services/task/contact.ts +30 -0
- package/src/services/task/dialer.ts +136 -1
- package/src/services/task/digital/Digital.ts +97 -0
- package/src/services/task/state-machine/TaskStateMachine.ts +1313 -0
- package/src/services/task/state-machine/actions.ts +741 -0
- package/src/services/task/state-machine/ai-docs/AGENTS.md +462 -0
- package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +1146 -0
- package/src/services/task/state-machine/ai-docs/task-state-machine-spec.md +2209 -0
- package/src/services/task/state-machine/constants.ts +172 -0
- package/src/services/task/state-machine/guards.ts +498 -0
- package/src/services/task/state-machine/index.ts +28 -0
- package/src/services/task/state-machine/types.ts +258 -0
- package/src/services/task/state-machine/uiControlsComputer.ts +1135 -0
- package/src/services/task/taskDataNormalizer.ts +137 -0
- package/src/services/task/types.ts +843 -70
- package/src/services/task/voice/Voice.ts +1720 -0
- package/src/services/task/voice/WebRTC.ts +191 -0
- package/src/services/task/voice/wxAppVoiceMethods.ts +307 -0
- package/src/services/wxAppTelephonyUtils.ts +14 -0
- package/src/types.ts +238 -11
- package/src/utils/AGENTS.md +289 -0
- package/src/utils/PageCache.ts +38 -5
- package/src/utils/ai-docs/utils-spec.md +391 -0
- package/src/webex.js +2 -0
- package/test/unit/spec/cc.ts +1856 -122
- package/test/unit/spec/logger-proxy.ts +70 -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/ApiAiAssistant.ts +273 -0
- package/test/unit/spec/services/EntryPoint.ts +87 -40
- package/test/unit/spec/services/Queue.ts +123 -12
- package/test/unit/spec/services/UserPreference.ts +401 -0
- package/test/unit/spec/services/WebCallingService.ts +7 -1
- 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/config/index.ts +85 -29
- package/test/unit/spec/services/core/Utils.ts +481 -2
- 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/core/websocket/WebSocketManager.ts +137 -41
- package/test/unit/spec/services/core/websocket/connection-service.ts +3 -1
- package/test/unit/spec/services/task/AutoWrapup.ts +63 -0
- package/test/unit/spec/services/task/Task.ts +677 -0
- package/test/unit/spec/services/task/TaskFactory.ts +99 -0
- package/test/unit/spec/services/task/TaskManager.ts +2209 -918
- package/test/unit/spec/services/task/TaskUtils.ts +235 -0
- 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/dialer.ts +372 -96
- package/test/unit/spec/services/task/digital/Digital.ts +105 -0
- package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +3433 -0
- package/test/unit/spec/services/task/state-machine/guards.ts +839 -0
- package/test/unit/spec/services/task/state-machine/types.ts +18 -0
- package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +3101 -0
- package/test/unit/spec/services/task/taskTestUtils.ts +87 -0
- package/test/unit/spec/services/task/voice/Voice.ts +1523 -0
- package/test/unit/spec/services/task/voice/WebRTC.ts +235 -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
- package/dist/services/task/index.js +0 -1525
- package/dist/services/task/index.js.map +0 -1
- package/src/services/task/index.ts +0 -1801
- package/test/unit/spec/services/task/index.ts +0 -2184
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import {LocalMicrophoneStream, CALL_EVENT_KEYS} from '@webex/calling';
|
|
2
|
+
import {CC_FILE} from '../../../constants';
|
|
3
|
+
import {getErrorDetails} from '../../core/Utils';
|
|
4
|
+
import routingContact from '../contact';
|
|
5
|
+
import {
|
|
6
|
+
TaskData,
|
|
7
|
+
TaskResponse,
|
|
8
|
+
TASK_EVENTS,
|
|
9
|
+
IWebRTC,
|
|
10
|
+
VoiceUIControlOptions,
|
|
11
|
+
VOICE_VARIANT,
|
|
12
|
+
TaskToggleMuteOptions,
|
|
13
|
+
} from '../types';
|
|
14
|
+
import Voice from './Voice';
|
|
15
|
+
import WebCallingService from '../../WebCallingService';
|
|
16
|
+
import {WrapupData} from '../../config/types';
|
|
17
|
+
import MetricsManager from '../../../metrics/MetricsManager';
|
|
18
|
+
import {METRIC_EVENT_NAMES} from '../../../metrics/constants';
|
|
19
|
+
import LoggerProxy from '../../../logger-proxy';
|
|
20
|
+
|
|
21
|
+
export default class WebRTC extends Voice implements IWebRTC {
|
|
22
|
+
private localAudioStream: LocalMicrophoneStream;
|
|
23
|
+
private webCallingService: WebCallingService;
|
|
24
|
+
|
|
25
|
+
constructor(
|
|
26
|
+
contact: ReturnType<typeof routingContact>,
|
|
27
|
+
webCallingService: WebCallingService,
|
|
28
|
+
data: TaskData,
|
|
29
|
+
callOptions?: VoiceUIControlOptions,
|
|
30
|
+
wrapupData?: WrapupData,
|
|
31
|
+
agentId?: string
|
|
32
|
+
) {
|
|
33
|
+
const mergedCallOptions: VoiceUIControlOptions = {
|
|
34
|
+
...callOptions,
|
|
35
|
+
voiceVariant: VOICE_VARIANT.WEBRTC,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
super(contact, data, mergedCallOptions, wrapupData, agentId);
|
|
39
|
+
this.webCallingService = webCallingService;
|
|
40
|
+
this.registerWebCallListeners();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private registerWebCallListeners() {
|
|
44
|
+
this.webCallingService.on(CALL_EVENT_KEYS.REMOTE_MEDIA, this.handleRemoteMedia);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private handleRemoteMedia = (track: MediaStreamTrack) => {
|
|
48
|
+
this.emit(TASK_EVENTS.TASK_MEDIA, track);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* This method is used to unregister the web call listeners.
|
|
53
|
+
* @returns void
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* task.unregisterWebCallListeners();
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
public unregisterWebCallListeners() {
|
|
60
|
+
this.webCallingService.off(CALL_EVENT_KEYS.REMOTE_MEDIA, this.handleRemoteMedia);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* This is used for incoming task accept by agent.
|
|
65
|
+
*
|
|
66
|
+
* @returns Promise<TaskResponse>
|
|
67
|
+
* @throws Error
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* task.accept().then(()=>{}).catch(()=>{})
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
public async accept(): Promise<TaskResponse> {
|
|
74
|
+
LoggerProxy.log(`Accepting WebRTC task for taskId:${this.data.interactionId}`, {
|
|
75
|
+
module: 'WebRTC',
|
|
76
|
+
method: 'accept',
|
|
77
|
+
});
|
|
78
|
+
try {
|
|
79
|
+
this.metricsManager.timeEvent([
|
|
80
|
+
METRIC_EVENT_NAMES.TASK_ACCEPT_SUCCESS,
|
|
81
|
+
METRIC_EVENT_NAMES.TASK_ACCEPT_FAILED,
|
|
82
|
+
]);
|
|
83
|
+
|
|
84
|
+
const constraints = {audio: true};
|
|
85
|
+
const localStream = await navigator.mediaDevices.getUserMedia(constraints);
|
|
86
|
+
const audioTrack = localStream.getAudioTracks()[0];
|
|
87
|
+
this.localAudioStream = new LocalMicrophoneStream(new MediaStream([audioTrack]));
|
|
88
|
+
this.webCallingService.answerCall(this.localAudioStream, this.data.interactionId);
|
|
89
|
+
|
|
90
|
+
this.metricsManager.trackEvent(
|
|
91
|
+
METRIC_EVENT_NAMES.TASK_ACCEPT_SUCCESS,
|
|
92
|
+
{
|
|
93
|
+
taskId: this.data.interactionId,
|
|
94
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponse(this.data),
|
|
95
|
+
},
|
|
96
|
+
['operational', 'behavioral', 'business']
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
return Promise.resolve();
|
|
100
|
+
} catch (error) {
|
|
101
|
+
this.metricsManager.trackEvent(
|
|
102
|
+
METRIC_EVENT_NAMES.TASK_ACCEPT_FAILED,
|
|
103
|
+
{
|
|
104
|
+
taskId: this.data.interactionId,
|
|
105
|
+
error: error.toString(),
|
|
106
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(
|
|
107
|
+
(error as any).details || {}
|
|
108
|
+
),
|
|
109
|
+
},
|
|
110
|
+
['operational', 'behavioral', 'business']
|
|
111
|
+
);
|
|
112
|
+
const {error: detailedError} = getErrorDetails(error, 'accept', CC_FILE);
|
|
113
|
+
throw detailedError;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* This is used for the incoming task decline by agent.
|
|
119
|
+
*
|
|
120
|
+
* @returns Promise<TaskResponse>
|
|
121
|
+
* @throws Error
|
|
122
|
+
* @example
|
|
123
|
+
* ```typescript
|
|
124
|
+
* task.decline().then(()=>{}).catch(()=>{})
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
public async decline(): Promise<TaskResponse> {
|
|
128
|
+
LoggerProxy.log(`Declining WebRTC task for taskId:${this.data.interactionId}`, {
|
|
129
|
+
module: 'WebRTC',
|
|
130
|
+
method: 'decline',
|
|
131
|
+
});
|
|
132
|
+
try {
|
|
133
|
+
this.metricsManager.timeEvent([
|
|
134
|
+
METRIC_EVENT_NAMES.TASK_DECLINE_SUCCESS,
|
|
135
|
+
METRIC_EVENT_NAMES.TASK_DECLINE_FAILED,
|
|
136
|
+
]);
|
|
137
|
+
|
|
138
|
+
this.webCallingService.declineCall(this.data.interactionId);
|
|
139
|
+
this.unregisterWebCallListeners();
|
|
140
|
+
|
|
141
|
+
this.metricsManager.trackEvent(
|
|
142
|
+
METRIC_EVENT_NAMES.TASK_DECLINE_SUCCESS,
|
|
143
|
+
{taskId: this.data.interactionId},
|
|
144
|
+
['operational', 'behavioral']
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
return Promise.resolve();
|
|
148
|
+
} catch (error) {
|
|
149
|
+
this.metricsManager.trackEvent(
|
|
150
|
+
METRIC_EVENT_NAMES.TASK_DECLINE_FAILED,
|
|
151
|
+
{
|
|
152
|
+
taskId: this.data.interactionId,
|
|
153
|
+
error: error.toString(),
|
|
154
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(
|
|
155
|
+
(error as any).details || {}
|
|
156
|
+
),
|
|
157
|
+
},
|
|
158
|
+
['operational', 'behavioral']
|
|
159
|
+
);
|
|
160
|
+
const {error: detailedError} = getErrorDetails(error, 'decline', CC_FILE);
|
|
161
|
+
throw detailedError;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* This is used for the placing the call in mute or unmute by the agent.
|
|
167
|
+
*
|
|
168
|
+
* @throws Error
|
|
169
|
+
* @example
|
|
170
|
+
* ```typescript
|
|
171
|
+
* task.toggleMute().then(()=>{}).catch(()=>{})
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
174
|
+
public async toggleMute(options?: TaskToggleMuteOptions) {
|
|
175
|
+
if (options) {
|
|
176
|
+
// parameter intentionally unused — WebRTC toggles from local stream state
|
|
177
|
+
}
|
|
178
|
+
LoggerProxy.log(`Toggling mute WebRTC task for taskId:${this.data.interactionId}`, {
|
|
179
|
+
module: 'WebRTC',
|
|
180
|
+
method: 'toggleMute',
|
|
181
|
+
});
|
|
182
|
+
try {
|
|
183
|
+
this.webCallingService.muteUnmuteCall(this.localAudioStream);
|
|
184
|
+
|
|
185
|
+
return Promise.resolve();
|
|
186
|
+
} catch (error) {
|
|
187
|
+
const {error: detailedError} = getErrorDetails(error, 'mute', CC_FILE);
|
|
188
|
+
throw detailedError;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import AnswerCallOnWebexService from '../../AnswerCallOnWebexService';
|
|
2
|
+
import LoggerProxy from '../../../logger-proxy';
|
|
3
|
+
import {METHODS} from '../../../constants';
|
|
4
|
+
import {getErrorDetails} from '../../core/Utils';
|
|
5
|
+
import {TaskData, TaskToggleMuteOptions, TaskTransmitDtmfOptions} from '../types';
|
|
6
|
+
import {TaskState} from '../state-machine';
|
|
7
|
+
import {
|
|
8
|
+
decodedLineOwnerId,
|
|
9
|
+
getWebexCallingDeviceDetailsForAgent,
|
|
10
|
+
WebexCallingDeviceDetails,
|
|
11
|
+
} from '../WebexCallingUtils';
|
|
12
|
+
|
|
13
|
+
type WxAppParticipant = {
|
|
14
|
+
deviceType?: string;
|
|
15
|
+
deviceCallId?: string;
|
|
16
|
+
deviceId?: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type WxAppVoiceDependencies = {
|
|
20
|
+
enableWxBetterTogether: boolean;
|
|
21
|
+
answerCallOnWebexService?: AnswerCallOnWebexService;
|
|
22
|
+
agentId?: string;
|
|
23
|
+
getTaskData: () => TaskData;
|
|
24
|
+
getTaskState: () => TaskState | undefined;
|
|
25
|
+
getWxAppMuted: () => boolean;
|
|
26
|
+
setWxAppMuted: (muted: boolean) => void;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/** @deprecated Use {@link WxAppVoiceDependencies} */
|
|
30
|
+
export type WxAppVoiceDeps = WxAppVoiceDependencies;
|
|
31
|
+
|
|
32
|
+
export type WxAppVoiceLifecycle = {
|
|
33
|
+
setWxAppAcceptInFlight: (inFlight: boolean) => void;
|
|
34
|
+
setWxAppAnswerPending: (pending: boolean) => void;
|
|
35
|
+
resetWxAppMuted: () => void;
|
|
36
|
+
syncWxAppMuteFromCallDetails: () => Promise<boolean | undefined>;
|
|
37
|
+
mapWxAppVoiceError: (error: unknown, method: string) => never;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const isWxAppParticipant = (participant: unknown): participant is WxAppParticipant =>
|
|
41
|
+
(participant as WxAppParticipant)?.deviceType === 'wxApp' &&
|
|
42
|
+
typeof (participant as WxAppParticipant)?.deviceCallId === 'string' &&
|
|
43
|
+
(participant as WxAppParticipant).deviceCallId.trim() !== '' &&
|
|
44
|
+
typeof (participant as WxAppParticipant)?.deviceId === 'string' &&
|
|
45
|
+
(participant as WxAppParticipant).deviceId.trim() !== '';
|
|
46
|
+
|
|
47
|
+
const isOutdialTask = (deps: WxAppVoiceDependencies): boolean =>
|
|
48
|
+
deps.getTaskData()?.interaction?.outboundType === 'OUTDIAL';
|
|
49
|
+
|
|
50
|
+
function getWxAppAgentParticipant(deps: WxAppVoiceDependencies): unknown {
|
|
51
|
+
const taskData = deps.getTaskData();
|
|
52
|
+
const participants = taskData.interaction?.participants;
|
|
53
|
+
const agentId = deps.agentId ?? taskData.agentId;
|
|
54
|
+
|
|
55
|
+
if (!participants || !agentId) {
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (participants[agentId]) {
|
|
60
|
+
return participants[agentId];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return Object.values(participants).find(
|
|
64
|
+
(participant) => (participant as {id?: string})?.id === agentId
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function getCallingDeviceDetails(
|
|
69
|
+
deps: WxAppVoiceDependencies
|
|
70
|
+
): WebexCallingDeviceDetails | undefined {
|
|
71
|
+
const taskData = deps.getTaskData();
|
|
72
|
+
const participant = getWxAppAgentParticipant(deps);
|
|
73
|
+
|
|
74
|
+
if (!isWxAppParticipant(participant)) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return getWebexCallingDeviceDetailsForAgent(
|
|
79
|
+
deps.agentId ?? taskData.agentId,
|
|
80
|
+
taskData.interaction?.participants
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function isWebexAppCallingOffer(deps: WxAppVoiceDependencies): boolean {
|
|
85
|
+
if (!deps.enableWxBetterTogether) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const state = deps.getTaskState();
|
|
90
|
+
if (state !== TaskState.OFFERED) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const details = getCallingDeviceDetails(deps);
|
|
95
|
+
|
|
96
|
+
return Boolean(details);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** Inbound wxApp offer only — outdial decline uses CC routing, not telephony reject. */
|
|
100
|
+
export function isWebexAppInboundCallingOffer(deps: WxAppVoiceDependencies): boolean {
|
|
101
|
+
return isWebexAppCallingOffer(deps) && !isOutdialTask(deps);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function getWebexCallingCallId(deps: WxAppVoiceDependencies): string | null {
|
|
105
|
+
const state = deps.getTaskState();
|
|
106
|
+
if (
|
|
107
|
+
!state ||
|
|
108
|
+
state === TaskState.OFFERED ||
|
|
109
|
+
state === TaskState.IDLE ||
|
|
110
|
+
state === TaskState.WRAPPING_UP ||
|
|
111
|
+
state === TaskState.TERMINATED ||
|
|
112
|
+
state === TaskState.COMPLETED
|
|
113
|
+
) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return getCallingDeviceDetails(deps)?.deviceCallId ?? null;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function getWxAppLineOwnerId(deps: WxAppVoiceDependencies): string | undefined {
|
|
121
|
+
const participant = getWxAppAgentParticipant(deps) as {lineOwnerId?: string} | undefined;
|
|
122
|
+
const lineOwnerId = participant?.lineOwnerId;
|
|
123
|
+
|
|
124
|
+
return typeof lineOwnerId === 'string' && lineOwnerId.trim() !== '' ? lineOwnerId : undefined;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function resolveWxAppLineOwnerId(
|
|
128
|
+
deps: WxAppVoiceDependencies,
|
|
129
|
+
override?: string
|
|
130
|
+
): string | undefined {
|
|
131
|
+
if (typeof override === 'string' && override.trim() !== '') {
|
|
132
|
+
return override;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return decodedLineOwnerId(getWxAppLineOwnerId(deps));
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function assertWxAppEnabled(deps: WxAppVoiceDependencies): void {
|
|
139
|
+
if (!deps.enableWxBetterTogether) {
|
|
140
|
+
throw new Error('enableWxBetterTogether is disabled');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (!deps.answerCallOnWebexService) {
|
|
144
|
+
throw new Error('AnswerCallOnWebexService is unavailable');
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export async function acceptOnWebex(
|
|
149
|
+
deps: WxAppVoiceDependencies,
|
|
150
|
+
options?: {lineOwnerId?: string}
|
|
151
|
+
): Promise<void> {
|
|
152
|
+
assertWxAppEnabled(deps);
|
|
153
|
+
|
|
154
|
+
if (!isWebexAppCallingOffer(deps)) {
|
|
155
|
+
throw new Error('Task is not a wxApp calling offer');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const details = getCallingDeviceDetails(deps);
|
|
159
|
+
if (!details) {
|
|
160
|
+
throw new Error('WxApp calling device details are unavailable');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
await deps.answerCallOnWebexService.answerCall({
|
|
164
|
+
callId: details.deviceCallId,
|
|
165
|
+
endpointId: details.deviceId,
|
|
166
|
+
lineOwnerId: resolveWxAppLineOwnerId(deps, options?.lineOwnerId),
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export async function rejectOnWebex(
|
|
171
|
+
deps: WxAppVoiceDependencies,
|
|
172
|
+
options?: {lineOwnerId?: string}
|
|
173
|
+
): Promise<void> {
|
|
174
|
+
assertWxAppEnabled(deps);
|
|
175
|
+
|
|
176
|
+
if (!isWebexAppInboundCallingOffer(deps)) {
|
|
177
|
+
throw new Error('Task is not a wxApp inbound calling offer');
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const details = getCallingDeviceDetails(deps);
|
|
181
|
+
if (!details) {
|
|
182
|
+
throw new Error('WxApp calling device details are unavailable');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
await deps.answerCallOnWebexService.rejectCall({
|
|
186
|
+
callId: details.deviceCallId,
|
|
187
|
+
lineOwnerId: resolveWxAppLineOwnerId(deps, options?.lineOwnerId),
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export async function toggleMuteOnWebex(
|
|
192
|
+
deps: WxAppVoiceDependencies,
|
|
193
|
+
options?: {lineOwnerId?: string; muted?: boolean}
|
|
194
|
+
): Promise<void> {
|
|
195
|
+
assertWxAppEnabled(deps);
|
|
196
|
+
|
|
197
|
+
const callId = getWebexCallingCallId(deps);
|
|
198
|
+
if (!callId) {
|
|
199
|
+
throw new Error('WxApp call ID is unavailable');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const targetMuted = options?.muted ?? !deps.getWxAppMuted();
|
|
203
|
+
const request = targetMuted
|
|
204
|
+
? deps.answerCallOnWebexService.muteCall.bind(deps.answerCallOnWebexService)
|
|
205
|
+
: deps.answerCallOnWebexService.unmuteCall.bind(deps.answerCallOnWebexService);
|
|
206
|
+
|
|
207
|
+
await request({
|
|
208
|
+
callId,
|
|
209
|
+
lineOwnerId: resolveWxAppLineOwnerId(deps, options?.lineOwnerId),
|
|
210
|
+
});
|
|
211
|
+
deps.setWxAppMuted(targetMuted);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export async function transmitDtmfOnWebex(
|
|
215
|
+
deps: WxAppVoiceDependencies,
|
|
216
|
+
options: {dtmf: string; lineOwnerId?: string}
|
|
217
|
+
): Promise<void> {
|
|
218
|
+
assertWxAppEnabled(deps);
|
|
219
|
+
|
|
220
|
+
const callId = getWebexCallingCallId(deps);
|
|
221
|
+
if (!callId) {
|
|
222
|
+
throw new Error('WxApp call ID is unavailable');
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
LoggerProxy.info('transmitDtmf', {
|
|
226
|
+
module: 'wxAppVoiceMethods',
|
|
227
|
+
method: METHODS.TRANSMIT_DTMF,
|
|
228
|
+
data: {
|
|
229
|
+
callId,
|
|
230
|
+
dtmfLength: options.dtmf.length,
|
|
231
|
+
hasLineOwnerId: Boolean(options.lineOwnerId),
|
|
232
|
+
},
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
await deps.answerCallOnWebexService.transmitDtmf({
|
|
236
|
+
callId,
|
|
237
|
+
dtmf: options.dtmf,
|
|
238
|
+
lineOwnerId: resolveWxAppLineOwnerId(deps, options.lineOwnerId),
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export async function runWxAppAccept(
|
|
243
|
+
deps: WxAppVoiceDependencies,
|
|
244
|
+
lifecycle: WxAppVoiceLifecycle,
|
|
245
|
+
options?: {lineOwnerId?: string}
|
|
246
|
+
): Promise<void> {
|
|
247
|
+
try {
|
|
248
|
+
lifecycle.setWxAppAcceptInFlight(true);
|
|
249
|
+
lifecycle.setWxAppAnswerPending(true);
|
|
250
|
+
await acceptOnWebex(deps, options);
|
|
251
|
+
lifecycle.resetWxAppMuted();
|
|
252
|
+
await lifecycle.syncWxAppMuteFromCallDetails();
|
|
253
|
+
} catch (error) {
|
|
254
|
+
lifecycle.setWxAppAnswerPending(false);
|
|
255
|
+
lifecycle.mapWxAppVoiceError(error, METHODS.ACCEPT);
|
|
256
|
+
} finally {
|
|
257
|
+
lifecycle.setWxAppAcceptInFlight(false);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export async function runWxAppReject(
|
|
262
|
+
deps: WxAppVoiceDependencies,
|
|
263
|
+
lifecycle: WxAppVoiceLifecycle,
|
|
264
|
+
options?: {lineOwnerId?: string}
|
|
265
|
+
): Promise<void> {
|
|
266
|
+
try {
|
|
267
|
+
await rejectOnWebex(deps, options);
|
|
268
|
+
} catch (error) {
|
|
269
|
+
lifecycle.mapWxAppVoiceError(error, METHODS.REJECT);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export async function runWxAppToggleMute(
|
|
274
|
+
deps: WxAppVoiceDependencies,
|
|
275
|
+
lifecycle: WxAppVoiceLifecycle,
|
|
276
|
+
options?: TaskToggleMuteOptions
|
|
277
|
+
): Promise<void> {
|
|
278
|
+
try {
|
|
279
|
+
await toggleMuteOnWebex(deps, options);
|
|
280
|
+
} catch (error) {
|
|
281
|
+
lifecycle.mapWxAppVoiceError(error, METHODS.TOGGLE_MUTE);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export async function runWxAppTransmitDtmf(
|
|
286
|
+
deps: WxAppVoiceDependencies,
|
|
287
|
+
lifecycle: WxAppVoiceLifecycle,
|
|
288
|
+
options: TaskTransmitDtmfOptions
|
|
289
|
+
): Promise<void> {
|
|
290
|
+
try {
|
|
291
|
+
await transmitDtmfOnWebex(deps, options);
|
|
292
|
+
} catch (error) {
|
|
293
|
+
lifecycle.mapWxAppVoiceError(error, METHODS.TRANSMIT_DTMF);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
export function mapWxAppVoiceError(error: unknown, method: string, module: string): never {
|
|
298
|
+
if (
|
|
299
|
+
error instanceof Error &&
|
|
300
|
+
(error as Error & {isWxAppTelephonyError?: boolean}).isWxAppTelephonyError
|
|
301
|
+
) {
|
|
302
|
+
throw error;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const {error: detailedError} = getErrorDetails(error, method, module);
|
|
306
|
+
throw detailedError;
|
|
307
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Expected Hydra responses when mute backfill races call creation (WXCC-6026).
|
|
3
|
+
* These must not be logged as errors — see task-spec wxApp mute backfill guard.
|
|
4
|
+
*/
|
|
5
|
+
export function isWxAppCallNotFoundError(error: unknown): boolean {
|
|
6
|
+
const err = error as {status?: number | string; message?: string};
|
|
7
|
+
if (err?.status === 400 || err?.status === '400') {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const message = String(err?.message ?? error ?? '');
|
|
12
|
+
|
|
13
|
+
return message.includes('Call not found') || message.includes('101002');
|
|
14
|
+
}
|