@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.
- package/.sdd/manifest.json +5 -4
- package/ai-docs/ARCHITECTURE.md +1 -1
- package/ai-docs/CONTRACTS.md +6 -2
- package/ai-docs/SECURITY.md +1 -1
- package/ai-docs/contact-center-spec.md +22 -4
- package/ai-docs/features/consult-transfer-list-policy/spec/feature-spec.md +362 -0
- package/dist/cc.js +440 -10
- package/dist/cc.js.map +1 -1
- package/dist/config.js +7 -0
- package/dist/config.js.map +1 -1
- package/dist/constants.js +10 -2
- package/dist/constants.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/metrics/behavioral-events.js +13 -0
- package/dist/metrics/behavioral-events.js.map +1 -1
- package/dist/metrics/constants.js +2 -0
- package/dist/metrics/constants.js.map +1 -1
- package/dist/services/AddressBook.js +18 -15
- package/dist/services/AddressBook.js.map +1 -1
- package/dist/services/AnswerCallOnWebexService.js +174 -0
- package/dist/services/AnswerCallOnWebexService.js.map +1 -0
- package/dist/services/EntryPoint.js +46 -68
- package/dist/services/EntryPoint.js.map +1 -1
- package/dist/services/Queue.js +27 -22
- package/dist/services/Queue.js.map +1 -1
- package/dist/services/WebexCrossClientService.js +171 -0
- package/dist/services/WebexCrossClientService.js.map +1 -0
- package/dist/services/WxAppTelephonyMercurySync.js +93 -0
- package/dist/services/WxAppTelephonyMercurySync.js.map +1 -0
- package/dist/services/config/Util.js +3 -0
- package/dist/services/config/Util.js.map +1 -1
- package/dist/services/config/constants.js +10 -6
- package/dist/services/config/constants.js.map +1 -1
- package/dist/services/config/types.js +4 -0
- package/dist/services/config/types.js.map +1 -1
- package/dist/services/core/Err.js.map +1 -1
- package/dist/services/core/WebexRequest.js +6 -2
- package/dist/services/core/WebexRequest.js.map +1 -1
- package/dist/services/core/aqm-reqs.js +28 -14
- package/dist/services/core/aqm-reqs.js.map +1 -1
- package/dist/services/core/types.js.map +1 -1
- package/dist/services/task/Task.js +73 -7
- package/dist/services/task/Task.js.map +1 -1
- package/dist/services/task/TaskFactory.js +8 -4
- package/dist/services/task/TaskFactory.js.map +1 -1
- package/dist/services/task/TaskManager.js +353 -21
- package/dist/services/task/TaskManager.js.map +1 -1
- package/dist/services/task/WebexCallingUtils.js +70 -0
- package/dist/services/task/WebexCallingUtils.js.map +1 -0
- package/dist/services/task/constants.js +4 -1
- package/dist/services/task/constants.js.map +1 -1
- package/dist/services/task/contact.js +29 -0
- package/dist/services/task/contact.js.map +1 -1
- package/dist/services/task/digital/Digital.js +3 -2
- package/dist/services/task/digital/Digital.js.map +1 -1
- package/dist/services/task/state-machine/TaskStateMachine.js +135 -37
- package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -1
- package/dist/services/task/state-machine/actions.js +6 -1
- package/dist/services/task/state-machine/actions.js.map +1 -1
- package/dist/services/task/state-machine/guards.js +38 -11
- package/dist/services/task/state-machine/guards.js.map +1 -1
- package/dist/services/task/state-machine/types.js.map +1 -1
- package/dist/services/task/state-machine/uiControlsComputer.js +118 -18
- package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -1
- package/dist/services/task/types.js +16 -1
- package/dist/services/task/types.js.map +1 -1
- package/dist/services/task/voice/Voice.js +350 -14
- package/dist/services/task/voice/Voice.js.map +1 -1
- package/dist/services/task/voice/WebRTC.js +4 -1
- package/dist/services/task/voice/WebRTC.js.map +1 -1
- package/dist/services/task/voice/wxAppVoiceMethods.js +201 -0
- package/dist/services/task/voice/wxAppVoiceMethods.js.map +1 -0
- package/dist/services/wxAppTelephonyUtils.js +19 -0
- package/dist/services/wxAppTelephonyUtils.js.map +1 -0
- package/dist/types/cc.d.ts +77 -4
- package/dist/types/config.d.ts +7 -0
- package/dist/types/constants.d.ts +8 -0
- package/dist/types/index.d.ts +3 -1
- package/dist/types/metrics/constants.d.ts +2 -0
- package/dist/types/services/AddressBook.d.ts +2 -1
- package/dist/types/services/AnswerCallOnWebexService.d.ts +37 -0
- package/dist/types/services/EntryPoint.d.ts +7 -5
- package/dist/types/services/Queue.d.ts +5 -3
- package/dist/types/services/WebexCrossClientService.d.ts +28 -0
- package/dist/types/services/WxAppTelephonyMercurySync.d.ts +28 -0
- package/dist/types/services/config/constants.d.ts +8 -5
- package/dist/types/services/config/types.d.ts +17 -4
- package/dist/types/services/core/Err.d.ts +2 -0
- package/dist/types/services/core/WebexRequest.d.ts +1 -0
- package/dist/types/services/core/types.d.ts +2 -0
- package/dist/types/services/task/Task.d.ts +20 -2
- package/dist/types/services/task/TaskFactory.d.ts +2 -1
- package/dist/types/services/task/WebexCallingUtils.d.ts +11 -0
- package/dist/types/services/task/constants.d.ts +3 -0
- package/dist/types/services/task/contact.d.ts +4 -0
- package/dist/types/services/task/digital/Digital.d.ts +2 -2
- package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +260 -56
- package/dist/types/services/task/state-machine/guards.d.ts +6 -5
- package/dist/types/services/task/state-machine/types.d.ts +9 -1
- package/dist/types/services/task/types.d.ts +81 -4
- package/dist/types/services/task/voice/Voice.d.ts +48 -9
- package/dist/types/services/task/voice/WebRTC.d.ts +2 -2
- package/dist/types/services/task/voice/wxAppVoiceMethods.d.ts +52 -0
- package/dist/types/services/wxAppTelephonyUtils.d.ts +5 -0
- package/dist/types/types.d.ts +14 -8
- package/dist/types/utils/PageCache.d.ts +20 -3
- package/dist/types.js +7 -2
- package/dist/types.js.map +1 -1
- package/dist/utils/PageCache.js +19 -5
- package/dist/utils/PageCache.js.map +1 -1
- package/dist/webex.js +1 -1
- package/package.json +9 -9
- package/src/cc.ts +506 -9
- package/src/config.ts +7 -0
- package/src/constants.ts +8 -0
- package/src/index.ts +2 -0
- package/src/metrics/ai-docs/metrics-spec.md +9 -3
- package/src/metrics/behavioral-events.ts +14 -0
- package/src/metrics/constants.ts +2 -0
- package/src/services/AddressBook.ts +17 -6
- package/src/services/AnswerCallOnWebexService.ts +206 -0
- package/src/services/EntryPoint.ts +59 -60
- package/src/services/Queue.ts +29 -12
- package/src/services/WebexCrossClientService.ts +212 -0
- package/src/services/WxAppTelephonyMercurySync.ts +115 -0
- package/src/services/ai-docs/AGENTS.md +10 -10
- package/src/services/ai-docs/services-spec.md +6 -1
- package/src/services/config/Util.ts +3 -0
- package/src/services/config/ai-docs/AGENTS.md +1 -1
- package/src/services/config/ai-docs/ARCHITECTURE.md +2 -2
- package/src/services/config/ai-docs/config-spec.md +6 -0
- package/src/services/config/constants.ts +10 -6
- package/src/services/config/types.ts +16 -4
- package/src/services/core/Err.ts +1 -0
- package/src/services/core/WebexRequest.ts +3 -1
- package/src/services/core/ai-docs/core-spec.md +5 -1
- package/src/services/core/aqm-reqs.ts +30 -15
- package/src/services/core/types.ts +2 -0
- package/src/services/task/Task.ts +79 -8
- package/src/services/task/TaskFactory.ts +8 -3
- package/src/services/task/TaskManager.ts +522 -16
- package/src/services/task/WebexCallingUtils.ts +136 -0
- package/src/services/task/ai-docs/ARCHITECTURE.md +1 -0
- package/src/services/task/ai-docs/task-spec.md +152 -2
- package/src/services/task/constants.ts +3 -0
- package/src/services/task/contact.ts +30 -0
- package/src/services/task/digital/Digital.ts +4 -2
- package/src/services/task/state-machine/TaskStateMachine.ts +210 -63
- package/src/services/task/state-machine/actions.ts +5 -2
- package/src/services/task/state-machine/ai-docs/AGENTS.md +8 -4
- package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +17 -8
- package/src/services/task/state-machine/ai-docs/task-state-machine-spec.md +56 -24
- package/src/services/task/state-machine/guards.ts +64 -11
- package/src/services/task/state-machine/types.ts +16 -1
- package/src/services/task/state-machine/uiControlsComputer.ts +206 -32
- package/src/services/task/types.ts +114 -4
- package/src/services/task/voice/Voice.ts +462 -12
- package/src/services/task/voice/WebRTC.ts +5 -1
- package/src/services/task/voice/wxAppVoiceMethods.ts +307 -0
- package/src/services/wxAppTelephonyUtils.ts +14 -0
- package/src/types.ts +33 -9
- package/src/utils/AGENTS.md +21 -10
- package/src/utils/PageCache.ts +38 -5
- package/src/utils/ai-docs/utils-spec.md +21 -11
- package/test/unit/spec/cc.ts +1274 -0
- package/test/unit/spec/metrics/behavioral-events.ts +18 -0
- package/test/unit/spec/services/AddressBook.ts +37 -6
- package/test/unit/spec/services/AnswerCallOnWebexService.ts +223 -0
- package/test/unit/spec/services/EntryPoint.ts +87 -40
- package/test/unit/spec/services/Queue.ts +123 -12
- package/test/unit/spec/services/WebexCrossClientService.ts +261 -0
- package/test/unit/spec/services/WxAppTelephonyMercurySync.ts +113 -0
- package/test/unit/spec/services/config/Util.ts +85 -0
- package/test/unit/spec/services/core/WebexRequest.ts +3 -1
- package/test/unit/spec/services/core/aqm-reqs.ts +113 -1
- package/test/unit/spec/services/task/Task.ts +200 -0
- package/test/unit/spec/services/task/TaskFactory.ts +39 -2
- package/test/unit/spec/services/task/TaskManager.ts +1294 -1
- package/test/unit/spec/services/task/WebexCallingUtils.ts +153 -0
- package/test/unit/spec/services/task/contact.ts +33 -0
- package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +854 -72
- package/test/unit/spec/services/task/state-machine/guards.ts +210 -8
- package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +445 -7
- package/test/unit/spec/services/task/voice/Voice.ts +874 -0
- package/test/unit/spec/services/task/voice/wxAppVoiceMethods.ts +459 -0
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import {TaskState} from './state-machine/constants';
|
|
2
|
+
|
|
3
|
+
export type WebexCallingDeviceDetails = {
|
|
4
|
+
deviceType: string;
|
|
5
|
+
deviceId: string;
|
|
6
|
+
deviceCallId: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
type WebexCallingParticipant = {
|
|
10
|
+
id?: unknown;
|
|
11
|
+
deviceType?: unknown;
|
|
12
|
+
deviceCallId?: unknown;
|
|
13
|
+
deviceId?: unknown;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const normalizeId = (id: unknown): string | undefined => {
|
|
17
|
+
if (typeof id !== 'string') {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const normalizedId = id.trim();
|
|
22
|
+
|
|
23
|
+
return normalizedId === '' ? undefined : normalizedId;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const isParticipantsById = (participants: unknown): participants is Record<string, unknown> =>
|
|
27
|
+
Boolean(participants) &&
|
|
28
|
+
typeof participants === 'object' &&
|
|
29
|
+
!Array.isArray(participants) &&
|
|
30
|
+
!(participants instanceof Map);
|
|
31
|
+
|
|
32
|
+
const hasWebexCallingDeviceDetails = (
|
|
33
|
+
participant: unknown
|
|
34
|
+
): participant is WebexCallingParticipant &
|
|
35
|
+
Pick<WebexCallingDeviceDetails, 'deviceCallId' | 'deviceId'> => {
|
|
36
|
+
const participantDetails = participant as WebexCallingParticipant | undefined;
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
typeof participantDetails?.deviceCallId === 'string' &&
|
|
40
|
+
participantDetails.deviceCallId.trim() !== '' &&
|
|
41
|
+
typeof participantDetails?.deviceId === 'string' &&
|
|
42
|
+
participantDetails.deviceId.trim() !== ''
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const isWebexCallingParticipantForAgent = (
|
|
47
|
+
participant: unknown,
|
|
48
|
+
agentId: string
|
|
49
|
+
): participant is WebexCallingParticipant &
|
|
50
|
+
Pick<WebexCallingDeviceDetails, 'deviceCallId' | 'deviceId'> => {
|
|
51
|
+
const participantDetails = participant as WebexCallingParticipant | undefined;
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
normalizeId(participantDetails?.id) === agentId && hasWebexCallingDeviceDetails(participant)
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const getWebexCallingDeviceDetails = (
|
|
59
|
+
participant: WebexCallingParticipant &
|
|
60
|
+
Pick<WebexCallingDeviceDetails, 'deviceCallId' | 'deviceId'>
|
|
61
|
+
): WebexCallingDeviceDetails => ({
|
|
62
|
+
deviceType: typeof participant.deviceType === 'string' ? participant.deviceType : '',
|
|
63
|
+
deviceId: participant.deviceId,
|
|
64
|
+
deviceCallId: participant.deviceCallId,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
export function getWebexCallingDeviceDetailsForAgent(
|
|
68
|
+
agentId: string | undefined,
|
|
69
|
+
participants: unknown
|
|
70
|
+
): WebexCallingDeviceDetails | undefined {
|
|
71
|
+
const normalizedAgentId = normalizeId(agentId);
|
|
72
|
+
if (!normalizedAgentId || !isParticipantsById(participants)) {
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const agentParticipant = participants[normalizedAgentId];
|
|
77
|
+
const matchingAgentParticipant = hasWebexCallingDeviceDetails(agentParticipant)
|
|
78
|
+
? agentParticipant
|
|
79
|
+
: Object.values(participants).find((participant) =>
|
|
80
|
+
isWebexCallingParticipantForAgent(participant, normalizedAgentId)
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
if (!matchingAgentParticipant || !hasWebexCallingDeviceDetails(matchingAgentParticipant)) {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return getWebexCallingDeviceDetails(matchingAgentParticipant);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function isWebexCallingCallForAgent(
|
|
91
|
+
agentId: string | undefined,
|
|
92
|
+
participants: unknown
|
|
93
|
+
): boolean {
|
|
94
|
+
return Boolean(getWebexCallingDeviceDetailsForAgent(agentId, participants));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Matches wxAppVoiceMethods.getWebexCallingCallId engaged semantics for uiControls. */
|
|
98
|
+
export function isWxAppEngagedForControls(
|
|
99
|
+
enableWxBetterTogether: boolean,
|
|
100
|
+
agentId: string | undefined,
|
|
101
|
+
participants: unknown,
|
|
102
|
+
state: TaskState
|
|
103
|
+
): boolean {
|
|
104
|
+
if (!enableWxBetterTogether) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (
|
|
109
|
+
!state ||
|
|
110
|
+
state === TaskState.OFFERED ||
|
|
111
|
+
state === TaskState.IDLE ||
|
|
112
|
+
state === TaskState.WRAPPING_UP ||
|
|
113
|
+
state === TaskState.TERMINATED ||
|
|
114
|
+
state === TaskState.COMPLETED
|
|
115
|
+
) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const details = getWebexCallingDeviceDetailsForAgent(agentId, participants);
|
|
120
|
+
|
|
121
|
+
return details?.deviceType === 'wxApp';
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function decodedLineOwnerId(lineOwnerId?: string): string | undefined {
|
|
125
|
+
if (!lineOwnerId) {
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
try {
|
|
130
|
+
const decoded = atob(lineOwnerId);
|
|
131
|
+
|
|
132
|
+
return decoded.split('/').pop();
|
|
133
|
+
} catch {
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
- `state?: SnapshotFrom<TaskStateMachine>`
|
|
36
36
|
- `autoWrapup?: AutoWrapup`
|
|
37
37
|
- `uiControls: TaskUIControls` (getter)
|
|
38
|
+
- includes ordered, action-specific `consultTransferDestinations` computed from Task profile configuration and live interaction data
|
|
38
39
|
|
|
39
40
|
**Methods**
|
|
40
41
|
|
|
@@ -33,7 +33,7 @@ Manage task lifecycle including inbound/outbound calls, hold/resume, consult, tr
|
|
|
33
33
|
|
|
34
34
|
- **Event Emission and Public APIs**: Task objects register listeners, update context, emit SDK events (e.g., `task:*`), and expose public methods that delegate to `contact.ts` for call control and to the state machine for transition validation.
|
|
35
35
|
|
|
36
|
-
- **AQM Contact Operations**: `contact.ts` builds the AQM request surface for call control (accept, hold, consult, transfer, wrapup, end) and is the primary bridge from `Task`/`Voice`/`WebRTC`/`Digital` methods to WCC task APIs.
|
|
36
|
+
- **AQM Contact Operations**: `contact.ts` builds the AQM request surface for call control (accept, hold, consult, transfer, participant Drop, wrapup, end) and is the primary bridge from `Task`/`Voice`/`WebRTC`/`Digital` methods to WCC task APIs.
|
|
37
37
|
|
|
38
38
|
- **Outbound and Preview-Campaign Dialing**: `dialer.ts` exposes `startOutdial` plus `acceptPreviewContact`, `skipPreviewContact`, and `removePreviewContact`; ContactCenter publishes these operations through typed `cc` methods.
|
|
39
39
|
|
|
@@ -141,6 +141,8 @@ services/task/
|
|
|
141
141
|
|---|---|---|---|---|---|---|
|
|
142
142
|
| `task.surface` | SDK / event / internal API | Exported Task/types/events plus application-facing task instances and call-control methods. | Stable module consumption boundary. | Additive changes by default; breaking package exports require a major-version transition. | `src/services/task/Task.ts` | `../../../../ai-docs/CONTRACTS.md` |
|
|
143
143
|
| `task.preview-campaign` | SDK/AQM API | `acceptPreviewContact`, `skipPreviewContact`, `removePreviewContact`, and `PreviewContactPayload`. | Accept, skip, or remove a reserved campaign preview contact; each method returns `Promise<TaskResponse>`. | Additive semver-public methods; removals or signature changes are breaking. | `src/cc.ts`, `src/services/task/dialer.ts`, `src/services/task/types.ts` | `../../../../ai-docs/CONTRACTS.md` |
|
|
144
|
+
| `task.consult-transfer-controls` | SDK task controls | `TaskUIControls.consultTransferDestinations` with ordered `consult` and `transfer` arrays. | Surface default destination availability on every Task without an extra policy method. | Additive semver-public field/types; array order is meaningful and the first item is the default. | `src/services/task/types.ts`, `src/services/task/state-machine/uiControlsComputer.ts` | `../../../../ai-docs/CONTRACTS.md` |
|
|
145
|
+
| `task.conference-participant-drop` | SDK/AQM API | `task.dropConferenceParticipant(payload: DropConferenceParticipantPayload): Promise<TaskResponse>`. | Remove a supported target from a voice conference after correlated routing completion. | Additive semver-public method and payload; removals or signature changes are breaking. | `src/services/task/voice/Voice.ts`, `src/services/task/contact.ts`, `src/services/task/types.ts` | `../../../../ai-docs/CONTRACTS.md` |
|
|
144
146
|
|
|
145
147
|
Compatibility notes:
|
|
146
148
|
- Do not remove or reinterpret exported symbols/events without a documented consumer migration.
|
|
@@ -151,6 +153,8 @@ Compatibility notes:
|
|
|
151
153
|
|
|
152
154
|
- `PreviewContactPayload` (`types.ts`) with `interactionId` and campaign-name `campaignId`
|
|
153
155
|
|
|
156
|
+
- `DropConferenceParticipantPayload` (`types.ts`) with a runtime-validated non-empty `participantId`
|
|
157
|
+
|
|
154
158
|
- `ITask`, `IVoice`, `IWebRTC`, `IDigital` (`types.ts`)
|
|
155
159
|
|
|
156
160
|
- `MEDIA_CHANNEL`, `TASK_CHANNEL_TYPE`, `VOICE_VARIANT` (`types.ts`)
|
|
@@ -346,6 +350,20 @@ End consultation without transfer.
|
|
|
346
350
|
|
|
347
351
|
**Returns**: `Promise<TaskResponse>`
|
|
348
352
|
|
|
353
|
+
Remove another participant from a voice conference.
|
|
354
|
+
|
|
355
|
+
**Parameters**:
|
|
356
|
+
|
|
357
|
+
- `participantId` (string, required): backend participant target identifier; blank and non-string values reject before AQM registration or telemetry.
|
|
358
|
+
|
|
359
|
+
**Returns**: `Promise<TaskResponse>` after `ParticipantLeftConference` is received for the latest `interaction.mainInteractionId || task.data.interactionId`.
|
|
360
|
+
|
|
361
|
+
**Failure**: `ParticipantDropConferenceFailed`, HTTP rejection, or the default 20-second AQM timeout rejects the promise. The operation does not add a task state-machine event or optimistically change the roster.
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
await task.dropConferenceParticipant({participantId});
|
|
365
|
+
```
|
|
366
|
+
|
|
349
367
|
### Complete TASK_EVENTS inventory
|
|
350
368
|
|
|
351
369
|
The public `TASK_EVENTS` enum contains 49 members; every member is listed below from `src/services/task/types.ts`.
|
|
@@ -417,6 +435,9 @@ The public `TASK_EVENTS` enum contains 49 members; every member is listed below
|
|
|
417
435
|
| TASK-R-005 | The contact dependency belongs to Task/TaskFactory-created tasks; dialer is an AqmReqs request factory without that constructor. | Misattributing constructor dependencies causes invalid instantiation examples. | `src/services/task/TaskFactory.ts` | `test/unit/spec/services/task/dialer.ts` | None; source and test evidence rechecked during the 2026-07-09 remediation; independent document revalidation pending. | PRESENT |
|
|
418
436
|
| TASK-R-006 | Keep credentials and authentication outside Task; remote operations delegate through contact/dialer routing, AqmReqs, and Core/WebexRequest. | Task lifecycle objects should never duplicate host token handling or leak authentication state into interaction data. | `src/services/task/Task.ts`, `src/services/task/contact.ts`, `src/services/core/WebexRequest.ts` | `test/unit/spec/services/task/Task.ts`, `test/unit/spec/services/task/contact.ts` | None; authentication ownership is explicit. | PRESENT |
|
|
419
437
|
| TASK-R-007 | Route enabled preview-campaign accept, skip, and remove operations through the dialer AQM factory using `PreviewContactPayload`, returning `Promise<TaskResponse>` from the public ContactCenter methods. Before routing skip/remove, reject the operation when the matching task's disable flag is `'true'`. | Preview reservations require typed payloads and correlated backend completion, while campaign controls must block prohibited skip/remove requests before transport begins. | `src/cc.ts`, `src/services/task/dialer.ts`, `src/services/task/types.ts` | `test/unit/spec/cc.ts`, `test/unit/spec/services/task/dialer.ts` | Public delegation and dialer requests are covered; the `campaignPreviewSkipDisabled` and `campaignPreviewRemoveDisabled` early-exit guards lack direct unit coverage. Independent review identified this gap on 2026-07-15. | PRESENT |
|
|
438
|
+
| TASK-R-008 | Voice `dropConferenceParticipant` must validate the public target, resolve the latest main interaction, POST an empty body to the encoded participant-drop route, and settle only from `ParticipantLeftConference`, `ParticipantDropConferenceFailed`, HTTP failure, or the existing AQM timeout. | Participant removal is backend-authoritative and must preserve event-driven roster/state synchronization without exposing participant identifiers through telemetry or logs. | `src/services/task/voice/Voice.ts`, `src/services/task/contact.ts`, `src/services/task/types.ts` | `test/unit/spec/services/task/voice/Voice.ts`, `test/unit/spec/services/task/contact.ts`, `test/unit/spec/services/core/aqm-reqs.ts` | Backend authorization and media removal are remote-service responsibilities. | PRESENT |
|
|
439
|
+
| TASK-R-009 | ContactCenter must inject Desktop Profile collaboration policy into TaskFactory, and every created voice/digital Task must expose ordered Consult and Transfer destination categories through `TaskUIControls.consultTransferDestinations`. | Task consumers need one already-computed policy surface and must not fetch profile flags or duplicate destination decisions. | `src/cc.ts`, `src/services/task/TaskFactory.ts`, `src/services/task/types.ts` | `test/unit/spec/cc.ts`, `test/unit/spec/services/task/TaskFactory.ts` | Host-specific UI options may only further hide an SDK-allowed category. | PRESENT |
|
|
440
|
+
| TASK-R-010 | TaskManager must propagate backend owner promotion without electing an owner locally. `ContactOwnerChanged` resolves an exact task first, then one unique related task whose existing snapshot proves that the current Agent is active on `mainCall`, or whose incoming snapshot both names that Agent as `interaction.owner` and proves the same active-main-leg membership. Active membership requires a participant entry with `hasLeft !== true`. If no task exists, recovery is limited to that incoming owner=current-Agent proof: create the normal Task under the stable main interaction ID, silently HYDRATE its actor before listener installation, then process the original owner-change event so consumers receive one `task:hydrate` and no `task:incoming`. An owner-changing `ContactUpdated` uses the existing owner-change hydrate path only for an existing task, and a late `ParticipantLeftConference` cannot replace a confirmed active owner with the departed participant. | Every surviving agent must observe the backend-selected primary Agent immediately, including stale child-keyed and narrowly recoverable desynchronization cases, without duplicating tasks or exposing an uninitialized actor. | `src/services/task/TaskManager.ts` | `test/unit/spec/services/task/TaskManager.ts`, `test/unit/spec/services/task/Task.ts` | Backend owner selection and delivery of a complete owner-bearing `ContactOwnerChanged` payload remain remote responsibilities; missing-task `ContactUpdated` remains update-only. | PRESENT |
|
|
420
441
|
|
|
421
442
|
## Design Overview
|
|
422
443
|
Task separates its stable consumption boundary from collaborators so ownership and failure behavior stay explicit. A shared Task base preserves a stable API while media-specific subclasses and a separate state engine enforce capability differences.
|
|
@@ -494,6 +515,8 @@ Returns an object of AQM request methods wired to `TASK_API` and `TASK_MESSAGE_T
|
|
|
494
515
|
|
|
495
516
|
- `consultConference`
|
|
496
517
|
|
|
518
|
+
- `dropConferenceParticipant`
|
|
519
|
+
|
|
497
520
|
- `exitConference`
|
|
498
521
|
|
|
499
522
|
- `conferenceTransfer`
|
|
@@ -532,6 +555,8 @@ Uses `contact` for:
|
|
|
532
555
|
|
|
533
556
|
- `consultConference`, `exitConference`, `conferenceTransfer`
|
|
534
557
|
|
|
558
|
+
- `dropConferenceParticipant` (Voice only; base Task rejects as unsupported)
|
|
559
|
+
|
|
535
560
|
Uses `contact.accept` in `accept()`.
|
|
536
561
|
|
|
537
562
|
TaskManager maintains a map of active tasks:
|
|
@@ -588,6 +613,14 @@ this.webSocketManager.on('message', (event) => {
|
|
|
588
613
|
|
|
589
614
|
This keeps transcript and suggestion delivery aligned on the same per-task event surface.
|
|
590
615
|
|
|
616
|
+
**wxApp outdial `ContactEnded` / `AgentOutboundFailed` mapping:** Applies only when the current agent is a **wxApp-managed** outdial (`enableWxBetterTogether` + agent participant `deviceType: wxApp`). Pre-accept decline maps to `CONTACT_ENDED` when `wxAppAnswerPending` is false and `agentsPendingWrapUp` is empty — even if the backend sends misleading `interaction.state: wrapUp`. Post-accept wxApp agent end remaps to `OUTBOUND_FAILED` / `AGENT_ENDS` when `wxAppAnswerPending`, `agentsPendingWrapUp`, or `interaction.state === 'wrapUp'` indicates wrapup. **Non-wxApp** agent-terminated `AgentOutboundFailed` (`AGENT_ENDS` / `terminatingParty: Agent`) stays on `OUTBOUND_FAILED` so the OFFERED-state `shouldWrapUp` path runs; `suppressOutdialFailedPopup` on `taskData` skips the outdial-failed modal only. Non-wxApp `ContactEnded` keeps the legacy path. Other failure reasons (`CUSTOMER_BUSY`, etc.) still use `OUTBOUND_FAILED` with the popup. See `TaskManager.isWxAppManagedOutdialTask`, `isAgentTerminatedOutdialWrapup`, and `task-state-machine-spec.md`.
|
|
617
|
+
|
|
618
|
+
**wxApp consumer contract (WXCC-6026):** Hosts enable `enableWxBetterTogether` at init (Phase 1 init-only; re-init to change), bind UI to `task.uiControls` (including optional `main.keypad`), and call **`task.accept()`**, **`task.decline()`**, **`task.toggleMute({ muted? })`**, **`task.transmitDtmf({ dtmf })`**. SDK routes wxApp telephony internally on `Voice`. Shared-line `lineOwnerId` defaults from the wxApp agent participant when omitted.
|
|
619
|
+
|
|
620
|
+
**wxApp offer UI (`uiControlsComputer`):** `wxAppAcceptInFlight` disables accept/decline during the accept REST call. `wxAppAnswerPending` additionally disables accept and decline for **inbound** offers until ASSIGN; wxApp **outdial** keeps decline enabled during the post-accept "Calling…" phase so `cancelTask` remains available.
|
|
621
|
+
|
|
622
|
+
**wxApp mute backfill guard (`Voice.syncWxAppMuteFromCallDetails`):** Skips telephony `GET /calls/{callId}` when the interaction is terminated or the task is a pre-accept wxApp OFFERED offer (`wxAppAnswerPending` false). Post-accept OFFERED and engaged CONNECTED sync still run. `isWxAppEngagedForControls` and `getWebexCallingCallId` exclude `TERMINATED` and `COMPLETED`. Expected 400 / "Call not found" / `101002` responses are not logged as errors.
|
|
623
|
+
|
|
591
624
|
For BROWSER login, TaskManager integrates with WebCalling:
|
|
592
625
|
|
|
593
626
|
```mermaid
|
|
@@ -689,6 +722,7 @@ isSecondaryEpDnAgent(interaction);
|
|
|
689
722
|
| `TASK_WRAPUP_SUCCESS` | operational | Wrapup completed |
|
|
690
723
|
| `TASK_TRANSFER_SUCCESS` | behavioral, business | Transfer completed |
|
|
691
724
|
| `TASK_OUTDIAL_SUCCESS` | behavioral, business | Outdial completed |
|
|
725
|
+
| `TASK_CONFERENCE_PARTICIPANT_DROP_SUCCESS` | operational, behavioral, business | Participant Drop completed |
|
|
692
726
|
|
|
693
727
|
## Data Flow
|
|
694
728
|
1. **WebSocket event arrives** → `TaskManager` maps CC event to `TaskEvent`.
|
|
@@ -727,6 +761,7 @@ Sequence coverage:
|
|
|
727
761
|
| Incoming task creation | Incoming task | Unsupported media or incomplete event context prevents publication of a partial task. |
|
|
728
762
|
| Voice hold/resume | Hold or resume | Invalid state rejects before transport; failure notification/HTTP error/timeout sends the matching failure event and throws. |
|
|
729
763
|
| Consult/transfer/conference | Consult and transfer | Backend failure notifications drive explicit failure actions and preserve stable call context. |
|
|
764
|
+
| Participant Drop | Participant Drop | Validation rejects locally; AQM success/failure/HTTP/timeout paths settle and clean up without optimistic state changes. |
|
|
730
765
|
| Wrapup/end | Wrapup or end | Validation and backend failures throw; backend events retain distinct WRAPPING_UP/COMPLETED/TERMINATED outcomes. |
|
|
731
766
|
| WebRTC and digital accept | Channel-specific accept | WebRTC media/calling failure and Digital AQM failure follow different rejection paths. |
|
|
732
767
|
|
|
@@ -820,6 +855,118 @@ sequenceDiagram
|
|
|
820
855
|
end
|
|
821
856
|
```
|
|
822
857
|
|
|
858
|
+
### Participant Drop
|
|
859
|
+
|
|
860
|
+
```mermaid
|
|
861
|
+
sequenceDiagram
|
|
862
|
+
participant App
|
|
863
|
+
participant Voice
|
|
864
|
+
participant Contact as routingContact
|
|
865
|
+
participant AQM as AqmReqs
|
|
866
|
+
participant Backend
|
|
867
|
+
participant WS as Primary WebSocket
|
|
868
|
+
participant TM as TaskManager/state machine
|
|
869
|
+
App->>Voice: dropConferenceParticipant({participantId})
|
|
870
|
+
alt participantId is invalid
|
|
871
|
+
Voice-->>App: reject before metrics, HTTP, or bind registration
|
|
872
|
+
else valid target
|
|
873
|
+
Voice->>Voice: select latest main interaction ID
|
|
874
|
+
Voice->>Contact: participant Drop request
|
|
875
|
+
Contact->>AQM: POST encoded path with empty body and sensitive-log redaction
|
|
876
|
+
AQM->>Backend: authenticated HTTP initiation
|
|
877
|
+
alt ParticipantLeftConference
|
|
878
|
+
Backend-->>WS: ParticipantLeftConference
|
|
879
|
+
WS-->>AQM: correlated success
|
|
880
|
+
AQM-->>Voice: TaskResponse
|
|
881
|
+
WS-->>TM: existing PARTICIPANT_LEAVE mapping updates roster/conference state
|
|
882
|
+
Voice-->>App: resolve
|
|
883
|
+
else ParticipantDropConferenceFailed, HTTP failure, or timeout
|
|
884
|
+
AQM-->>Voice: structured rejection
|
|
885
|
+
Voice-->>App: reject without participant data in logs/metrics
|
|
886
|
+
end
|
|
887
|
+
end
|
|
888
|
+
```
|
|
889
|
+
|
|
890
|
+
`ParticipantLeftConference` is authoritative for both a customer hangup and an
|
|
891
|
+
agent-initiated customer Drop. The task removes only participants absent from
|
|
892
|
+
the latest interaction snapshot. TaskManager first uses the exact interaction
|
|
893
|
+
key, then the existing reservation fallback, and finally one unique task whose
|
|
894
|
+
`interaction.mainInteractionId`, interaction-level `parentInteractionId`, or
|
|
895
|
+
`callProcessingDetails.parentInteractionId` matches an identifier carried by the
|
|
896
|
+
lifecycle event. Object aliases are deduplicated and all aliases are removed
|
|
897
|
+
during terminal cleanup; ambiguous related-interaction matches are ignored
|
|
898
|
+
without logging participant data. Events carrying none of those correlation
|
|
899
|
+
identifiers are not routed. `ContactMerged` removes the EP-DN child task,
|
|
900
|
+
hydrates the main-interaction task, and publishes the existing `task:merged`
|
|
901
|
+
event so consumers can rebind to the surviving task object.
|
|
902
|
+
|
|
903
|
+
Dropping an Agent while that Agent is consulting continues through the existing
|
|
904
|
+
`PARTICIPANT_LEAVE` transition, which clears consult state and emits the normal
|
|
905
|
+
participant-left and task-end lifecycle. This self-departure check applies in
|
|
906
|
+
every active call-control state and uses an explicit self participant ID,
|
|
907
|
+
`hasLeft`, or removal of a previously active Agent from the participant map. A
|
|
908
|
+
participant-left event naming somebody else never infers self-departure from a
|
|
909
|
+
partial media roster. A consulted Agent receiving
|
|
910
|
+
`AgentConsultEnded` continues through `CONSULT_END`; current-agent departure is
|
|
911
|
+
evaluated before consult-initiator recovery. For the from-conference nested-consult
|
|
912
|
+
ordering race only, the guard also compares `mainCall` membership (located by
|
|
913
|
+
`mType`) when the Agent remains active in the participant map and is still present
|
|
914
|
+
on the consult leg. Missing, contradictory, or ordinary CONNECTED/HELD media snapshots
|
|
915
|
+
are non-terminal. Accepted consultees emit
|
|
916
|
+
`task:consultEnd` and `task:end`, while an unaccepted OFFERED consultee retains
|
|
917
|
+
the existing consult-end-only signal. A surviving consult initiator still
|
|
918
|
+
returns to the main-call state selected by the existing guards. Starting a
|
|
919
|
+
consult preserves the prior task snapshot so this membership comparison remains
|
|
920
|
+
available while the consult is initiating.
|
|
921
|
+
|
|
922
|
+
Primary-Agent promotion remains backend-authoritative and follows the two-event
|
|
923
|
+
desktop contract. `ContactOwnerChanged` updates the promoted Agent; TaskManager
|
|
924
|
+
prefers an exact task, then one unique related task resolved through nested
|
|
925
|
+
main/parent identifiers or the `mainCall` media-map identity. A related
|
|
926
|
+
candidate is eligible when its current
|
|
927
|
+
snapshot contains the current Agent's participant entry with `hasLeft !== true`
|
|
928
|
+
and membership on the `mType: mainCall` leg. The incoming snapshot can provide
|
|
929
|
+
that evidence only when it also names the current Agent as `interaction.owner`;
|
|
930
|
+
this permits an authoritative promotion payload to repair a stale child-keyed
|
|
931
|
+
snapshot while still excluding consult-only tasks. The update keeps the
|
|
932
|
+
surviving main interaction identity even when the notification names a
|
|
933
|
+
promoted-Agent child interaction.
|
|
934
|
+
|
|
935
|
+
If no related task exists, TaskManager recovers only the promoted current Agent
|
|
936
|
+
from a non-terminal telephony `ContactOwnerChanged` payload that provides the same
|
|
937
|
+
active-main-leg evidence. It creates the normal Task through TaskFactory under the
|
|
938
|
+
stable main interaction ID, sends an internal HYDRATE before installing external
|
|
939
|
+
listeners, and then processes the original owner-change event. Consumers
|
|
940
|
+
therefore receive one `task:hydrate`, never a synthetic `task:incoming`, and a
|
|
941
|
+
later canonical contact or merge event reuses the same task rather than creating
|
|
942
|
+
an alias. Missing, partial, departed, consult-only, non-promoted, and ambiguous
|
|
943
|
+
payloads are ignored for recovery.
|
|
944
|
+
|
|
945
|
+
For other surviving Agents, a `ContactUpdated` whose non-empty
|
|
946
|
+
`interaction.owner` differs from the current owner is delivered through the
|
|
947
|
+
existing `CONTACT_OWNER_CHANGED`/`task:hydrate` path; same-owner or owner-less
|
|
948
|
+
updates remain data-only, and a missing task is not created from `ContactUpdated`.
|
|
949
|
+
If a later `ParticipantLeftConference` still names the departed participant as
|
|
950
|
+
owner, an already confirmed owner is retained only when the new roster proves
|
|
951
|
+
that confirmed owner remains active on `mainCall` and explicitly names the
|
|
952
|
+
incoming owner as `participantId` or marks it `hasLeft`. Main-call omission alone
|
|
953
|
+
is not departure evidence. The SDK never chooses the successor locally.
|
|
954
|
+
|
|
955
|
+
In the Contact Center sample roster, non-owner and Supervisor targets remain
|
|
956
|
+
visible but non-actionable; the UI does not display a separate read-only label.
|
|
957
|
+
The roster is visible whenever the viewing agent remains active on the main leg
|
|
958
|
+
and at least one supported non-customer participant (Agent, EP-DN, or Supervisor)
|
|
959
|
+
is visible. Consequently, Customer-only calls use the original 1-to-1 UI, while
|
|
960
|
+
a single Agent remains visible after the Customer leaves. Dropping the last
|
|
961
|
+
non-customer participant while the Customer remains restores the 1-to-1 UI.
|
|
962
|
+
Terminated tasks and viewing-agent departure hide the roster immediately.
|
|
963
|
+
|
|
964
|
+
The current consult leg may additionally contribute a pending EP-DN row before
|
|
965
|
+
conference merge. The sample displays its `dn`, then its participant/media key
|
|
966
|
+
as a fallback, and deduplicates the row once it joins the main leg. The owner can
|
|
967
|
+
see a disabled Drop action until merge; other active main-call agents see the
|
|
968
|
+
same row without an action. Consult-only Agent targets remain excluded.
|
|
969
|
+
|
|
823
970
|
### Wrapup or end
|
|
824
971
|
|
|
825
972
|
```mermaid
|
|
@@ -1270,7 +1417,7 @@ await cc.stationLogin({ loginOption: 'BROWSER', ... });
|
|
|
1270
1417
|
- A shared Task base preserves a stable API while media-specific subclasses and a separate state engine enforce capability differences.
|
|
1271
1418
|
|
|
1272
1419
|
## Test-Case Strategy (module)
|
|
1273
|
-
Use `test/unit/spec/services/task/Task.ts`, `TaskFactory.ts`, `TaskManager.ts`, media-specific suites, contact/dialer suites, and state-machine suites. Cover concrete-versus-interface method signatures, every TASK_EVENTS group, unsupported media rejection, primary/RTD event ownership, injected state actions, preview-campaign accept/skip/remove payloads and failure paths, the disabled skip/remove pre-guards, and success/failure/timeout paths.
|
|
1420
|
+
Use `test/unit/spec/services/task/Task.ts`, `TaskFactory.ts`, `TaskManager.ts`, media-specific suites, contact/dialer suites, and state-machine suites. Cover concrete-versus-interface method signatures, every TASK_EVENTS group, unsupported media rejection, primary/RTD event ownership, injected state actions, preview-campaign accept/skip/remove payloads and failure paths, the disabled skip/remove pre-guards, Participant Drop validation/correlation/privacy, primary-owner promotion propagation, and success/failure/timeout paths.
|
|
1274
1421
|
|
|
1275
1422
|
| Behavior / Requirement | Existing test evidence | Gap |
|
|
1276
1423
|
|---|---|---|
|
|
@@ -1281,6 +1428,9 @@ Use `test/unit/spec/services/task/Task.ts`, `TaskFactory.ts`, `TaskManager.ts`,
|
|
|
1281
1428
|
| `TASK-R-005` | `test/unit/spec/services/task/TaskFactory.ts`, `test/unit/spec/services/task/dialer.ts` | None. |
|
|
1282
1429
|
| `TASK-R-006` | `test/unit/spec/services/task/contact.ts`, `test/unit/spec/services/core/WebexRequest.ts` | Authentication ownership is verified across routing/Core boundaries. |
|
|
1283
1430
|
| `TASK-R-007` | `test/unit/spec/cc.ts`, `test/unit/spec/services/task/dialer.ts` | Add direct tests proving disabled skip/remove flags throw before dialer invocation; keep public signatures, metrics/error handling, and AQM request contracts synchronized. |
|
|
1431
|
+
| `TASK-R-008` | `test/unit/spec/services/task/Task.ts`, `test/unit/spec/services/task/voice/Voice.ts`, `test/unit/spec/services/task/contact.ts`, `test/unit/spec/services/core/aqm-reqs.ts`, `test/unit/spec/services/task/TaskManager.ts` | None. |
|
|
1432
|
+
| `TASK-R-009` | `test/unit/spec/cc.ts`, `test/unit/spec/services/task/TaskFactory.ts`, `test/unit/spec/services/task/state-machine/uiControlsComputer.ts` | None. |
|
|
1433
|
+
| `TASK-R-010` | `test/unit/spec/services/task/TaskManager.ts`, `test/unit/spec/services/task/Task.ts` | None. |
|
|
1284
1434
|
|
|
1285
1435
|
## Traceability
|
|
1286
1436
|
- Repo architecture: `../../../../ai-docs/ARCHITECTURE.md` · Registry: `../../../../ai-docs/SPEC_INDEX.md`
|
|
@@ -14,6 +14,8 @@ export const CONSULT = '/consult';
|
|
|
14
14
|
export const CONSULT_ACCEPT = '/consult/accept';
|
|
15
15
|
export const CONSULT_END = '/consult/end';
|
|
16
16
|
export const TRANSFER = '/transfer';
|
|
17
|
+
/** Backend destination value for direct entry-point transfers through the vteam endpoint. */
|
|
18
|
+
export const ENTRY_POINT_TRANSFER_DESTINATION_TYPE = 'entrypointDialNumber';
|
|
17
19
|
export const CONSULT_TRANSFER = '/consult/transfer';
|
|
18
20
|
export const PAUSE = '/record/pause';
|
|
19
21
|
export const RESUME = '/record/resume';
|
|
@@ -73,6 +75,7 @@ export const METHODS = {
|
|
|
73
75
|
TRANSFER: 'transfer',
|
|
74
76
|
CONSULT_TRANSFER: 'consultTransfer',
|
|
75
77
|
CONSULT_CONFERENCE: 'consultConference',
|
|
78
|
+
DROP_CONFERENCE_PARTICIPANT: 'dropConferenceParticipant',
|
|
76
79
|
EXIT_CONFERENCE: 'exitConference',
|
|
77
80
|
TRANSFER_CONFERENCE: 'transferConference',
|
|
78
81
|
UPDATE_TASK_DATA: 'updateTaskData',
|
|
@@ -458,6 +458,36 @@ export default function routingContact(aqm: AqmReqs) {
|
|
|
458
458
|
})
|
|
459
459
|
),
|
|
460
460
|
|
|
461
|
+
/*
|
|
462
|
+
* Drop another participant from an active conference
|
|
463
|
+
*/
|
|
464
|
+
dropConferenceParticipant: aqm.req((p: {interactionId: string; participantId: string}) => ({
|
|
465
|
+
url: `${TASK_API}${p.interactionId}/conference/participants/${encodeURIComponent(
|
|
466
|
+
p.participantId
|
|
467
|
+
)}/drop`,
|
|
468
|
+
data: {},
|
|
469
|
+
host: WCC_API_GATEWAY,
|
|
470
|
+
err,
|
|
471
|
+
redactSensitiveLogs: true,
|
|
472
|
+
notifSuccess: {
|
|
473
|
+
bind: {
|
|
474
|
+
type: TASK_MESSAGE_TYPE,
|
|
475
|
+
data: {
|
|
476
|
+
type: CC_EVENTS.PARTICIPANT_LEFT_CONFERENCE,
|
|
477
|
+
interactionId: p.interactionId,
|
|
478
|
+
},
|
|
479
|
+
},
|
|
480
|
+
msg: {} as Contact.AgentContact,
|
|
481
|
+
},
|
|
482
|
+
notifFail: {
|
|
483
|
+
bind: {
|
|
484
|
+
type: TASK_MESSAGE_TYPE,
|
|
485
|
+
data: {type: CC_EVENTS.PARTICIPANT_DROP_CONFERENCE_FAILED},
|
|
486
|
+
},
|
|
487
|
+
errId: 'Service.aqm.task.dropConferenceParticipant',
|
|
488
|
+
},
|
|
489
|
+
})),
|
|
490
|
+
|
|
461
491
|
/*
|
|
462
492
|
* Exit conference
|
|
463
493
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {CC_FILE, METHODS} from '../../../constants';
|
|
2
2
|
import {getErrorDetails} from '../../core/Utils';
|
|
3
|
-
import {IDigital, TaskResponse, TaskData} from '../types';
|
|
3
|
+
import {ConsultTransferDestinationConfig, IDigital, TaskResponse, TaskData} from '../types';
|
|
4
4
|
import {WrapupData} from '../../config/types';
|
|
5
5
|
import Task from '../Task';
|
|
6
6
|
import routingContact from '../contact';
|
|
@@ -13,7 +13,8 @@ export default class Digital extends Task implements IDigital {
|
|
|
13
13
|
contact: ReturnType<typeof routingContact>,
|
|
14
14
|
data: TaskData,
|
|
15
15
|
wrapupData?: WrapupData,
|
|
16
|
-
agentId?: string
|
|
16
|
+
agentId?: string,
|
|
17
|
+
consultTransferConfig?: ConsultTransferDestinationConfig
|
|
17
18
|
) {
|
|
18
19
|
super(
|
|
19
20
|
contact,
|
|
@@ -22,6 +23,7 @@ export default class Digital extends Task implements IDigital {
|
|
|
22
23
|
isEndTaskEnabled: true,
|
|
23
24
|
isEndConsultEnabled: false,
|
|
24
25
|
isRecordingEnabled: false,
|
|
26
|
+
consultTransferConfig,
|
|
25
27
|
},
|
|
26
28
|
wrapupData,
|
|
27
29
|
agentId
|