@webex/contact-center 3.12.0-next.9 → 3.12.0-task-refactor.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/AGENTS.md +438 -0
- package/ai-docs/README.md +131 -0
- package/ai-docs/RULES.md +455 -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 +65 -123
- package/dist/cc.js.map +1 -1
- package/dist/constants.js +13 -2
- package/dist/constants.js.map +1 -1
- package/dist/index.js +13 -5
- package/dist/index.js.map +1 -1
- package/dist/metrics/behavioral-events.js +26 -13
- package/dist/metrics/behavioral-events.js.map +1 -1
- package/dist/metrics/constants.js +7 -6
- package/dist/metrics/constants.js.map +1 -1
- package/dist/services/ApiAiAssistant.js +0 -3
- package/dist/services/ApiAiAssistant.js.map +1 -1
- package/dist/services/config/Util.js +2 -3
- package/dist/services/config/Util.js.map +1 -1
- package/dist/services/config/types.js +16 -14
- package/dist/services/config/types.js.map +1 -1
- package/dist/services/constants.js +0 -1
- package/dist/services/constants.js.map +1 -1
- package/dist/services/core/Err.js.map +1 -1
- package/dist/services/core/Utils.js +79 -55
- package/dist/services/core/Utils.js.map +1 -1
- package/dist/services/core/aqm-reqs.js +17 -92
- package/dist/services/core/aqm-reqs.js.map +1 -1
- package/dist/services/core/websocket/WebSocketManager.js +5 -25
- package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
- package/dist/services/core/websocket/types.js.map +1 -1
- package/dist/services/index.js +1 -2
- package/dist/services/index.js.map +1 -1
- package/dist/services/task/Task.js +644 -0
- package/dist/services/task/Task.js.map +1 -0
- package/dist/services/task/TaskFactory.js +45 -0
- package/dist/services/task/TaskFactory.js.map +1 -0
- package/dist/services/task/TaskManager.js +556 -532
- package/dist/services/task/TaskManager.js.map +1 -1
- package/dist/services/task/TaskUtils.js +132 -28
- package/dist/services/task/TaskUtils.js.map +1 -1
- package/dist/services/task/constants.js +7 -6
- package/dist/services/task/constants.js.map +1 -1
- package/dist/services/task/dialer.js +0 -51
- package/dist/services/task/dialer.js.map +1 -1
- package/dist/services/task/digital/Digital.js +77 -0
- package/dist/services/task/digital/Digital.js.map +1 -0
- package/dist/services/task/state-machine/TaskStateMachine.js +634 -0
- package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -0
- package/dist/services/task/state-machine/actions.js +366 -0
- package/dist/services/task/state-machine/actions.js.map +1 -0
- package/dist/services/task/state-machine/constants.js +139 -0
- package/dist/services/task/state-machine/constants.js.map +1 -0
- package/dist/services/task/state-machine/guards.js +256 -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 +369 -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 +157 -18
- package/dist/services/task/types.js.map +1 -1
- package/dist/services/task/voice/Voice.js +1031 -0
- package/dist/services/task/voice/Voice.js.map +1 -0
- package/dist/services/task/voice/WebRTC.js +149 -0
- package/dist/services/task/voice/WebRTC.js.map +1 -0
- package/dist/types/cc.d.ts +4 -33
- package/dist/types/constants.d.ts +13 -2
- package/dist/types/index.d.ts +11 -5
- package/dist/types/metrics/constants.d.ts +5 -3
- package/dist/types/services/ApiAiAssistant.d.ts +1 -1
- package/dist/types/services/config/types.d.ts +97 -25
- package/dist/types/services/core/Err.d.ts +0 -2
- package/dist/types/services/core/Utils.d.ts +25 -23
- package/dist/types/services/core/aqm-reqs.d.ts +0 -49
- package/dist/types/services/core/websocket/WebSocketManager.d.ts +1 -1
- package/dist/types/services/core/websocket/connection-service.d.ts +0 -1
- package/dist/types/services/core/websocket/types.d.ts +1 -1
- package/dist/types/services/index.d.ts +1 -1
- package/dist/types/services/task/Task.d.ts +146 -0
- package/dist/types/services/task/TaskFactory.d.ts +12 -0
- package/dist/types/services/task/TaskUtils.d.ts +39 -8
- package/dist/types/services/task/constants.d.ts +5 -4
- package/dist/types/services/task/dialer.d.ts +0 -15
- package/dist/types/services/task/digital/Digital.d.ts +22 -0
- package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +906 -0
- package/dist/types/services/task/state-machine/actions.d.ts +8 -0
- package/dist/types/services/task/state-machine/constants.d.ts +91 -0
- package/dist/types/services/task/state-machine/guards.d.ts +78 -0
- package/dist/types/services/task/state-machine/index.d.ts +13 -0
- package/dist/types/services/task/state-machine/types.d.ts +256 -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 +539 -88
- package/dist/types/services/task/voice/Voice.d.ts +183 -0
- package/dist/types/services/task/voice/WebRTC.d.ts +53 -0
- package/dist/types/types.d.ts +68 -0
- package/dist/types/webex.d.ts +1 -0
- package/dist/types.js +70 -0
- package/dist/types.js.map +1 -1
- package/dist/webex.js +14 -2
- package/dist/webex.js.map +1 -1
- package/package.json +14 -11
- package/src/cc.ts +91 -177
- package/src/constants.ts +13 -2
- package/src/index.ts +14 -5
- package/src/metrics/ai-docs/AGENTS.md +348 -0
- package/src/metrics/ai-docs/ARCHITECTURE.md +336 -0
- package/src/metrics/behavioral-events.ts +28 -14
- package/src/metrics/constants.ts +7 -8
- package/src/services/ApiAiAssistant.ts +2 -4
- package/src/services/agent/ai-docs/AGENTS.md +238 -0
- package/src/services/agent/ai-docs/ARCHITECTURE.md +302 -0
- package/src/services/ai-docs/AGENTS.md +384 -0
- package/src/services/config/Util.ts +2 -3
- package/src/services/config/ai-docs/AGENTS.md +253 -0
- package/src/services/config/ai-docs/ARCHITECTURE.md +424 -0
- package/src/services/config/types.ts +108 -20
- package/src/services/constants.ts +0 -1
- package/src/services/core/Err.ts +0 -1
- package/src/services/core/Utils.ts +90 -67
- package/src/services/core/ai-docs/AGENTS.md +379 -0
- package/src/services/core/ai-docs/ARCHITECTURE.md +696 -0
- package/src/services/core/aqm-reqs.ts +22 -100
- package/src/services/core/websocket/WebSocketManager.ts +4 -23
- package/src/services/core/websocket/types.ts +1 -1
- package/src/services/index.ts +1 -2
- package/src/services/task/Task.ts +785 -0
- package/src/services/task/TaskFactory.ts +55 -0
- package/src/services/task/TaskManager.ts +567 -633
- package/src/services/task/TaskUtils.ts +175 -31
- package/src/services/task/ai-docs/AGENTS.md +448 -0
- package/src/services/task/ai-docs/ARCHITECTURE.md +573 -0
- package/src/services/task/constants.ts +5 -4
- package/src/services/task/dialer.ts +1 -56
- package/src/services/task/digital/Digital.ts +95 -0
- package/src/services/task/state-machine/TaskStateMachine.ts +793 -0
- package/src/services/task/state-machine/actions.ts +409 -0
- package/src/services/task/state-machine/ai-docs/AGENTS.md +495 -0
- package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +1135 -0
- package/src/services/task/state-machine/constants.ts +150 -0
- package/src/services/task/state-machine/guards.ts +295 -0
- package/src/services/task/state-machine/index.ts +28 -0
- package/src/services/task/state-machine/types.ts +228 -0
- package/src/services/task/state-machine/uiControlsComputer.ts +529 -0
- package/src/services/task/taskDataNormalizer.ts +137 -0
- package/src/services/task/types.ts +641 -95
- package/src/services/task/voice/Voice.ts +1255 -0
- package/src/services/task/voice/WebRTC.ts +187 -0
- package/src/types.ts +88 -5
- package/src/utils/AGENTS.md +276 -0
- package/src/webex.js +2 -0
- package/test/unit/spec/cc.ts +59 -142
- package/test/unit/spec/logger-proxy.ts +70 -0
- package/test/unit/spec/services/ApiAiAssistant.ts +17 -0
- package/test/unit/spec/services/config/index.ts +26 -55
- package/test/unit/spec/services/core/Utils.ts +103 -52
- package/test/unit/spec/services/core/websocket/WebSocketManager.ts +48 -112
- package/test/unit/spec/services/core/websocket/connection-service.ts +5 -4
- package/test/unit/spec/services/task/AutoWrapup.ts +63 -0
- package/test/unit/spec/services/task/Task.ts +416 -0
- package/test/unit/spec/services/task/TaskFactory.ts +62 -0
- package/test/unit/spec/services/task/TaskManager.ts +781 -1735
- package/test/unit/spec/services/task/TaskUtils.ts +125 -0
- package/test/unit/spec/services/task/dialer.ts +112 -198
- package/test/unit/spec/services/task/digital/Digital.ts +105 -0
- package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +473 -0
- package/test/unit/spec/services/task/state-machine/guards.ts +288 -0
- package/test/unit/spec/services/task/state-machine/types.ts +18 -0
- package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +147 -0
- package/test/unit/spec/services/task/taskTestUtils.ts +87 -0
- package/test/unit/spec/services/task/voice/Voice.ts +587 -0
- package/test/unit/spec/services/task/voice/WebRTC.ts +242 -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/dist/types/services/task/index.d.ts +0 -650
- package/src/services/task/index.ts +0 -1801
- package/test/unit/spec/services/task/index.ts +0 -2184
|
@@ -0,0 +1,573 @@
|
|
|
1
|
+
# Task Service - Architecture
|
|
2
|
+
|
|
3
|
+
> **Purpose**: Technical documentation for task lifecycle management.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Component Overview
|
|
8
|
+
|
|
9
|
+
| Component | File | Responsibility |
|
|
10
|
+
| -------------------- | ---------------------------- | ---------------------------------------------------------- |
|
|
11
|
+
| `TaskManager` | `task/TaskManager.ts` | Task lifecycle coordination |
|
|
12
|
+
| `Task` | `task/Task.ts` | Individual task operations |
|
|
13
|
+
| `contact` | `task/contact.ts` | AQM request definitions |
|
|
14
|
+
| `dialer` | `task/dialer.ts` | Outbound call initiation |
|
|
15
|
+
| `AutoWrapup` | `task/AutoWrapup.ts` | Auto wrapup timer |
|
|
16
|
+
| `taskDataNormalizer` | `task/taskDataNormalizer.ts` | Normalizes backend task payloads |
|
|
17
|
+
| `TaskUtils` | `task/TaskUtils.ts` | Utility functions |
|
|
18
|
+
| `state-machine` | `task/state-machine/*` | Task state transitions, guards, and UI control computation |
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Task Module Design Overview
|
|
23
|
+
|
|
24
|
+
### `Task` (abstract)
|
|
25
|
+
|
|
26
|
+
**File:** `Task.ts`
|
|
27
|
+
|
|
28
|
+
**Properties**
|
|
29
|
+
|
|
30
|
+
- `data: TaskData`
|
|
31
|
+
- `webCallMap: Record<TaskId, CallId>`
|
|
32
|
+
- `stateMachineService?: ActorRefFrom<TaskStateMachine>`
|
|
33
|
+
- `state?: SnapshotFrom<TaskStateMachine>`
|
|
34
|
+
- `autoWrapup?: AutoWrapup`
|
|
35
|
+
- `uiControls: TaskUIControls` (getter)
|
|
36
|
+
|
|
37
|
+
**Methods**
|
|
38
|
+
|
|
39
|
+
- `accept(): Promise<TaskResponse>` (abstract)
|
|
40
|
+
- `decline(): Promise<TaskResponse>` (default: unsupportedMethodError)
|
|
41
|
+
- `pauseRecording(): Promise<TaskResponse>` (default: unsupportedMethodError)
|
|
42
|
+
- `resumeRecording(resumeRecordingPayload: ResumeRecordingPayload): Promise<TaskResponse>` (default: unsupportedMethodError)
|
|
43
|
+
- `consult(consultPayload: ConsultPayload): Promise<TaskResponse>` (default: unsupportedMethodError)
|
|
44
|
+
- `endConsult(consultEndPayload?: ConsultEndPayload): Promise<TaskResponse>` (default: unsupportedMethodError)
|
|
45
|
+
- `consultTransfer(consultTransferPayload?: ConsultTransferPayLoad): Promise<TaskResponse>` (default: unsupportedMethodError)
|
|
46
|
+
- `consultConference(): Promise<TaskResponse>` (default: unsupportedMethodError)
|
|
47
|
+
- `exitConference(): Promise<TaskResponse>` (default: unsupportedMethodError)
|
|
48
|
+
- `transferConference(): Promise<TaskResponse>` (default: unsupportedMethodError)
|
|
49
|
+
- `switchCall(): Promise<TaskResponse>` (default: unsupportedMethodError)
|
|
50
|
+
- `toggleMute(): Promise<void>` (default: unsupportedMethodError)
|
|
51
|
+
- `unregisterWebCallListeners(): void` (default: no-op + log)
|
|
52
|
+
- `cancelAutoWrapupTimer(): void`
|
|
53
|
+
- `hold(mediaResourceId?: string): Promise<TaskResponse>` (default: unsupportedMethodError)
|
|
54
|
+
- `resume(mediaResourceId?: string): Promise<TaskResponse>` (default: unsupportedMethodError)
|
|
55
|
+
- `holdResume(): Promise<TaskResponse>` (default: unsupportedMethodError)
|
|
56
|
+
- `sendStateMachineEvent(event: TaskEventPayload): void`
|
|
57
|
+
- `updateTaskData(updatedData: TaskData, shouldOverwrite = false): ITask`
|
|
58
|
+
- `transfer(transferPayload: TransferPayLoad): Promise<TaskResponse>`
|
|
59
|
+
- `end(): Promise<TaskResponse>`
|
|
60
|
+
- `wrapup(wrapupPayload: WrapupPayLoad): Promise<TaskResponse>`
|
|
61
|
+
|
|
62
|
+
### `Voice`
|
|
63
|
+
|
|
64
|
+
**File:** `voice/Voice.ts`
|
|
65
|
+
|
|
66
|
+
**Notes**
|
|
67
|
+
|
|
68
|
+
- Extends `Task`.
|
|
69
|
+
- Provides `hold()` and `resume()` that delegate to `holdResume()`.
|
|
70
|
+
- Explicitly overrides `accept()` and `decline()` to throw `unsupportedMethodError`.
|
|
71
|
+
- `WebRTC` then overrides these methods with concrete implementations.
|
|
72
|
+
|
|
73
|
+
### `WebRTC`
|
|
74
|
+
|
|
75
|
+
**File:** `voice/WebRTC.ts`
|
|
76
|
+
|
|
77
|
+
**Notes**
|
|
78
|
+
|
|
79
|
+
- Extends `Voice`.
|
|
80
|
+
- Overrides `accept()` and `decline()` for WebRTC calls.
|
|
81
|
+
- Emits `TASK_EVENTS.TASK_MEDIA` on remote media (`CALL_EVENT_KEYS.REMOTE_MEDIA`).
|
|
82
|
+
- Overrides `unregisterWebCallListeners()`.
|
|
83
|
+
|
|
84
|
+
### `Digital`
|
|
85
|
+
|
|
86
|
+
**File:** `digital/Digital.ts`
|
|
87
|
+
|
|
88
|
+
**Notes**
|
|
89
|
+
|
|
90
|
+
- Extends `Task`.
|
|
91
|
+
- Implements `accept()`.
|
|
92
|
+
- Overrides `updateTaskData()` to refresh digital task data and UI controls.
|
|
93
|
+
|
|
94
|
+
### `TaskFactory`
|
|
95
|
+
|
|
96
|
+
**File:** `TaskFactory.ts`
|
|
97
|
+
|
|
98
|
+
**API**
|
|
99
|
+
|
|
100
|
+
- `createTask(contact, webCallingService, data, configFlags, wrapupData?, agentId?): Task`
|
|
101
|
+
|
|
102
|
+
**Behavior**
|
|
103
|
+
|
|
104
|
+
- Chooses `WebRTC` vs `Voice` for `MEDIA_CHANNEL.TELEPHONY` based on `webCallingService.loginOption`.
|
|
105
|
+
- Chooses `Digital` for `MEDIA_CHANNEL.CHAT`, `MEDIA_CHANNEL.EMAIL`, `MEDIA_CHANNEL.SOCIAL`.
|
|
106
|
+
- Throws `Error` for unknown media types.
|
|
107
|
+
|
|
108
|
+
### Task Class Hierarchy Diagram
|
|
109
|
+
|
|
110
|
+
```mermaid
|
|
111
|
+
classDiagram
|
|
112
|
+
class Task {
|
|
113
|
+
<<abstract>>
|
|
114
|
+
# contact
|
|
115
|
+
# metricsManager
|
|
116
|
+
+ data: TaskData
|
|
117
|
+
+ webCallMap: Record~TaskId, CallId~
|
|
118
|
+
+ stateMachineService
|
|
119
|
+
+ state
|
|
120
|
+
# currentUiControls: TaskUIControls
|
|
121
|
+
# uiControlConfig: UIControlConfig
|
|
122
|
+
+ autoWrapup: AutoWrapup
|
|
123
|
+
+ accept() TaskResponse
|
|
124
|
+
+ transfer(payload) TaskResponse
|
|
125
|
+
+ end() TaskResponse
|
|
126
|
+
+ wrapup(payload) TaskResponse
|
|
127
|
+
+ updateTaskData(updatedData, shouldOverwrite) ITask
|
|
128
|
+
+ sendStateMachineEvent(event) void
|
|
129
|
+
+ hold() TaskResponse
|
|
130
|
+
+ resume() TaskResponse
|
|
131
|
+
+ holdResume() TaskResponse
|
|
132
|
+
+ consult(payload) TaskResponse
|
|
133
|
+
+ endConsult(payload) TaskResponse
|
|
134
|
+
+ consultTransfer(payload) TaskResponse
|
|
135
|
+
+ consultConference() TaskResponse
|
|
136
|
+
+ exitConference() TaskResponse
|
|
137
|
+
+ transferConference() TaskResponse
|
|
138
|
+
+ pauseRecording() TaskResponse
|
|
139
|
+
+ resumeRecording(payload) TaskResponse
|
|
140
|
+
+ toggleMute() void
|
|
141
|
+
+ unregisterWebCallListeners() void
|
|
142
|
+
+ cancelAutoWrapupTimer() void
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
class Voice {
|
|
146
|
+
+ accept() TaskResponse
|
|
147
|
+
+ decline() TaskResponse
|
|
148
|
+
+ hold() TaskResponse
|
|
149
|
+
+ resume() TaskResponse
|
|
150
|
+
+ holdResume() TaskResponse
|
|
151
|
+
+ pauseRecording() TaskResponse
|
|
152
|
+
+ resumeRecording(payload) TaskResponse
|
|
153
|
+
+ consult(payload) TaskResponse
|
|
154
|
+
+ endConsult(payload) TaskResponse
|
|
155
|
+
+ transfer(payload) TaskResponse
|
|
156
|
+
+ consultConference() TaskResponse
|
|
157
|
+
+ exitConference() TaskResponse
|
|
158
|
+
+ transferConference() TaskResponse
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
class WebRTC {
|
|
162
|
+
- localAudioStream: LocalMicrophoneStream
|
|
163
|
+
- webCallingService: WebCallingService
|
|
164
|
+
+ accept() TaskResponse
|
|
165
|
+
+ decline() TaskResponse
|
|
166
|
+
+ toggleMute() void
|
|
167
|
+
+ unregisterWebCallListeners() void
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
class Digital {
|
|
171
|
+
+ accept() TaskResponse
|
|
172
|
+
+ updateTaskData(newData, shouldOverwrite) IDigital
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
class TaskFactory {
|
|
176
|
+
+ createTask(contact, webCallingService, data, configFlags, wrapupData, agentId) Task
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
Task <|-- Voice
|
|
180
|
+
Voice <|-- WebRTC
|
|
181
|
+
Task <|-- Digital
|
|
182
|
+
|
|
183
|
+
TaskFactory ..> Task : creates
|
|
184
|
+
TaskFactory ..> Voice : creates
|
|
185
|
+
TaskFactory ..> WebRTC : creates
|
|
186
|
+
TaskFactory ..> Digital : creates
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## TaskManager Pattern
|
|
192
|
+
|
|
193
|
+
TaskManager is a singleton that:
|
|
194
|
+
|
|
195
|
+
1. Listens for WebSocket task events
|
|
196
|
+
2. Creates/manages Task objects
|
|
197
|
+
3. Routes events to appropriate tasks
|
|
198
|
+
4. Handles WebRTC call mapping
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
// Singleton access
|
|
202
|
+
const taskManager = TaskManager.getTaskManager(contact, webCallingService, webSocketManager);
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## AQM Request Modules
|
|
208
|
+
|
|
209
|
+
### `routingContact(aqm: AqmReqs)` (`contact.ts`)
|
|
210
|
+
|
|
211
|
+
Returns an object of AQM request methods wired to `TASK_API` and `TASK_MESSAGE_TYPE`.
|
|
212
|
+
|
|
213
|
+
**Methods**
|
|
214
|
+
|
|
215
|
+
- `accept`
|
|
216
|
+
- `hold`
|
|
217
|
+
- `unHold`
|
|
218
|
+
- `pauseRecording`
|
|
219
|
+
- `resumeRecording`
|
|
220
|
+
- `consult`
|
|
221
|
+
- `consultEnd`
|
|
222
|
+
- `consultAccept`
|
|
223
|
+
- `blindTransfer`
|
|
224
|
+
- `vteamTransfer`
|
|
225
|
+
- `consultTransfer`
|
|
226
|
+
- `end`
|
|
227
|
+
- `wrapup`
|
|
228
|
+
- `cancelTask`
|
|
229
|
+
- `cancelCtq`
|
|
230
|
+
- `consultConference`
|
|
231
|
+
- `exitConference`
|
|
232
|
+
- `conferenceTransfer`
|
|
233
|
+
|
|
234
|
+
**Notes**
|
|
235
|
+
|
|
236
|
+
- Uses `WCC_API_GATEWAY`.
|
|
237
|
+
- Consult with `DESTINATION_TYPE.QUEUE` uses `TIMEOUT_REQ` = `'disabled'` for the request timeout.
|
|
238
|
+
|
|
239
|
+
### `aqmDialer(aqm: AqmReqs)` (`dialer.ts`)
|
|
240
|
+
|
|
241
|
+
Returns an object of AQM request methods for outbound dialing.
|
|
242
|
+
|
|
243
|
+
**Methods**
|
|
244
|
+
|
|
245
|
+
- `startOutdial` (success: `CC_EVENTS.AGENT_OFFER_CONTACT`, failure: `CC_EVENTS.AGENT_OUTBOUND_FAILED`)
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Usage in Task Classes
|
|
250
|
+
|
|
251
|
+
### `Task` (`Task.ts`)
|
|
252
|
+
|
|
253
|
+
- Constructor accepts `contact: ReturnType<typeof routingContact>`.
|
|
254
|
+
- Uses:
|
|
255
|
+
- `contact.vteamTransfer` / `contact.blindTransfer` in `transfer(...)`.
|
|
256
|
+
- While in consulting state, `transfer(...)` internally routes through consult-transfer behavior.
|
|
257
|
+
- `contact.end` in `end()`.
|
|
258
|
+
- `contact.wrapup` in `wrapup(...)`.
|
|
259
|
+
|
|
260
|
+
### `Voice` (`voice/Voice.ts`)
|
|
261
|
+
|
|
262
|
+
Uses `contact` for:
|
|
263
|
+
|
|
264
|
+
- `hold`, `unHold`
|
|
265
|
+
- `pauseRecording`, `resumeRecording`
|
|
266
|
+
- `consult`, `consultEnd`, `consultTransfer`
|
|
267
|
+
- `consultConference`, `exitConference`, `conferenceTransfer`
|
|
268
|
+
|
|
269
|
+
### `Digital` (`digital/Digital.ts`)
|
|
270
|
+
|
|
271
|
+
Uses `contact.accept` in `accept()`.
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## State Machine Layer
|
|
276
|
+
|
|
277
|
+
`Task` delegates lifecycle transitions and control-state derivation to the state machine:
|
|
278
|
+
|
|
279
|
+
- Transition graph: `state-machine/TaskStateMachine.ts`
|
|
280
|
+
- Transition conditions: `state-machine/guards.ts`
|
|
281
|
+
- Context mutation and integration hooks: `state-machine/actions.ts`
|
|
282
|
+
- UI control derivation: `state-machine/uiControlsComputer.ts`
|
|
283
|
+
|
|
284
|
+
For state-machine-specific implementation guidance, use:
|
|
285
|
+
|
|
286
|
+
- `../state-machine/ai-docs/AGENTS.md`
|
|
287
|
+
- `../state-machine/ai-docs/ARCHITECTURE.md`
|
|
288
|
+
|
|
289
|
+
### State Inventory (from `state-machine/constants.ts`)
|
|
290
|
+
|
|
291
|
+
- **Active lifecycle + intermediate states**:
|
|
292
|
+
- `IDLE`, `OFFERED`, `CONNECTED`
|
|
293
|
+
- `HOLD_INITIATING`, `HELD`, `RESUME_INITIATING`
|
|
294
|
+
- `CONSULT_INITIATING`, `CONSULTING`, `CONF_INITIATING`
|
|
295
|
+
- `CONFERENCING`, `WRAPPING_UP`, `COMPLETED`, `TERMINATED`
|
|
296
|
+
- **Future placeholders (defined, not currently implemented in transitions)**:
|
|
297
|
+
- `CONSULT_INITIATED`, `CONSULT_COMPLETED`, `POST_CALL`, `PARKED`, `MONITORING`
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Event Flow
|
|
302
|
+
|
|
303
|
+
### Incoming Task Flow
|
|
304
|
+
|
|
305
|
+
```mermaid
|
|
306
|
+
sequenceDiagram
|
|
307
|
+
participant BE as Backend
|
|
308
|
+
participant WS as WebSocket
|
|
309
|
+
participant TM as TaskManager
|
|
310
|
+
participant T as Task
|
|
311
|
+
participant CC as ContactCenter
|
|
312
|
+
participant App as Application
|
|
313
|
+
|
|
314
|
+
BE->>WS: AgentOfferContact event
|
|
315
|
+
WS->>TM: message event
|
|
316
|
+
TM->>TM: Check if telephony
|
|
317
|
+
alt BROWSER login
|
|
318
|
+
TM->>TM: Wait for INCOMING_CALL
|
|
319
|
+
WS->>TM: LINE_EVENTS.INCOMING_CALL
|
|
320
|
+
TM->>TM: Map call to task
|
|
321
|
+
end
|
|
322
|
+
TM->>T: new Task(data)
|
|
323
|
+
TM->>TM: Store in taskCollection
|
|
324
|
+
TM->>CC: emit task:incoming
|
|
325
|
+
CC->>App: trigger task:incoming
|
|
326
|
+
App->>T: task.accept()
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### Task Operation Flow
|
|
330
|
+
|
|
331
|
+
```mermaid
|
|
332
|
+
sequenceDiagram
|
|
333
|
+
participant App
|
|
334
|
+
participant T as Task
|
|
335
|
+
participant C as contact service
|
|
336
|
+
participant AQM as AqmReqs
|
|
337
|
+
participant WS as WebSocket
|
|
338
|
+
participant BE as Backend
|
|
339
|
+
|
|
340
|
+
App->>T: task.hold()
|
|
341
|
+
T->>T: Update local state
|
|
342
|
+
T->>C: contact.hold({data})
|
|
343
|
+
C->>AQM: req(config)
|
|
344
|
+
AQM->>BE: POST /v1/tasks/{interactionId}/hold (HTTP via WebexRequest)
|
|
345
|
+
BE-->>AQM: HTTP response (TaskResponse payload)
|
|
346
|
+
AQM-->>C: resolve Promise<TaskResponse>
|
|
347
|
+
C-->>T: return TaskResponse
|
|
348
|
+
T-->>App: Promise resolves
|
|
349
|
+
Note over WS,TM: WebSocket is notification channel, not request transport
|
|
350
|
+
BE-->>WS: AgentContactHeld
|
|
351
|
+
WS-->>TM: message event
|
|
352
|
+
TM-->>T: emit task:hold
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## Task Collection
|
|
358
|
+
|
|
359
|
+
TaskManager maintains a map of active tasks:
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
private taskCollection: Record<TaskId, ITask> = {};
|
|
363
|
+
|
|
364
|
+
// Tasks indexed by interactionId
|
|
365
|
+
this.taskCollection[interactionId] = task;
|
|
366
|
+
|
|
367
|
+
// Retrieve task
|
|
368
|
+
const task = this.taskCollection[interactionId];
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## WebSocket Event Handling
|
|
374
|
+
|
|
375
|
+
TaskManager uses a staged pipeline in `registerTaskListeners()`:
|
|
376
|
+
|
|
377
|
+
```typescript
|
|
378
|
+
this.webSocketManager.on('message', (event) => {
|
|
379
|
+
// 1) Parse and validate message
|
|
380
|
+
const message = TaskManager.parseWebSocketMessage(event);
|
|
381
|
+
if (!message) return;
|
|
382
|
+
|
|
383
|
+
// 2) Build event context (task, payload, mapped state-machine event)
|
|
384
|
+
const eventContext = this.prepareEventContext(message);
|
|
385
|
+
if (!eventContext) return;
|
|
386
|
+
|
|
387
|
+
// 3) Handle lifecycle changes (create/update/remove task)
|
|
388
|
+
const actions = this.handleTaskLifecycleEvent(eventContext);
|
|
389
|
+
const {task} = actions;
|
|
390
|
+
if (!task) return;
|
|
391
|
+
|
|
392
|
+
// 4) Keep task.data synchronized
|
|
393
|
+
const {payload, stateMachineEvent} = eventContext;
|
|
394
|
+
if (payload) this.updateTaskData(task, payload);
|
|
395
|
+
|
|
396
|
+
// 5) Drive state machine (which emits TASK_EVENTS)
|
|
397
|
+
if (stateMachineEvent) {
|
|
398
|
+
task.sendStateMachineEvent(stateMachineEvent);
|
|
399
|
+
}
|
|
400
|
+
});
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
---
|
|
404
|
+
|
|
405
|
+
## WebRTC Integration
|
|
406
|
+
|
|
407
|
+
For BROWSER login, TaskManager integrates with WebCalling:
|
|
408
|
+
|
|
409
|
+
```mermaid
|
|
410
|
+
flowchart TD
|
|
411
|
+
A[AgentOfferContact event] --> B[Determine media + loginOption]
|
|
412
|
+
B --> C[TaskFactory chooses Voice/WebRTC class]
|
|
413
|
+
C --> D[Create Task object]
|
|
414
|
+
D --> E[Store in taskCollection]
|
|
415
|
+
E --> F{BROWSER login?}
|
|
416
|
+
F -->|Yes| G[Wait for INCOMING_CALL]
|
|
417
|
+
G --> H[Map call to task]
|
|
418
|
+
H --> I[Emit task:incoming]
|
|
419
|
+
F -->|No| I
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
### Call Mapping
|
|
423
|
+
|
|
424
|
+
```typescript
|
|
425
|
+
// WebCallingService maps call IDs to interaction IDs
|
|
426
|
+
this.webCallingService.mapCallToTask(callId, interactionId);
|
|
427
|
+
|
|
428
|
+
// Task uses call for media operations
|
|
429
|
+
this.webCallingService.answerCall(localAudioStream: LocalMicrophoneStream, taskId: string);
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
---
|
|
433
|
+
|
|
434
|
+
## Auto Wrapup
|
|
435
|
+
|
|
436
|
+
AutoWrapup handles automatic task completion:
|
|
437
|
+
|
|
438
|
+
```typescript
|
|
439
|
+
// AutoWrapup.ts
|
|
440
|
+
export default class AutoWrapup {
|
|
441
|
+
private timer: ReturnType<typeof setTimeout> | null = null;
|
|
442
|
+
private readonly interval: number;
|
|
443
|
+
|
|
444
|
+
start(onComplete: () => void) {
|
|
445
|
+
this.timer = setTimeout(onComplete, this.interval);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
clear() {
|
|
449
|
+
if (this.timer) {
|
|
450
|
+
clearTimeout(this.timer);
|
|
451
|
+
this.timer = null;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
getTimeLeft() {}
|
|
456
|
+
isRunning() {}
|
|
457
|
+
getTimeLeftSeconds() {}
|
|
458
|
+
}
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
---
|
|
462
|
+
|
|
463
|
+
## Contact Service Operations
|
|
464
|
+
|
|
465
|
+
Each task operation maps to an AQM request:
|
|
466
|
+
|
|
467
|
+
```typescript
|
|
468
|
+
// contact.ts
|
|
469
|
+
export default function routingContact(routing: AqmReqs) {
|
|
470
|
+
return {
|
|
471
|
+
accept: routing.req((p) => ({
|
|
472
|
+
url: '/v1/tasks/.../accept',
|
|
473
|
+
notifSuccess: { bind: { type: CC_EVENTS.AGENT_CONTACT_ASSIGNED }},
|
|
474
|
+
notifFail: { bind: { type: CC_EVENTS.AGENT_CONTACT_ASSIGN_FAILED }},
|
|
475
|
+
})),
|
|
476
|
+
|
|
477
|
+
hold: routing.req((p) => ({...})),
|
|
478
|
+
unHold: routing.req((p) => ({...})),
|
|
479
|
+
consultAccept: routing.req((p) => ({...})),
|
|
480
|
+
cancelTask: routing.req((p) => ({...})),
|
|
481
|
+
cancelCtq: routing.req((p) => ({...})),
|
|
482
|
+
end: routing.req((p) => ({...})),
|
|
483
|
+
wrapup: routing.req((p) => ({...})),
|
|
484
|
+
blindTransfer: routing.req((p) => ({...})),
|
|
485
|
+
consult: routing.req((p) => ({...})),
|
|
486
|
+
consultTransfer: routing.req((p) => ({...})),
|
|
487
|
+
// ... more operations
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
---
|
|
493
|
+
|
|
494
|
+
## Task Utils
|
|
495
|
+
|
|
496
|
+
Helper functions for task state analysis:
|
|
497
|
+
|
|
498
|
+
```typescript
|
|
499
|
+
// TaskUtils.ts
|
|
500
|
+
|
|
501
|
+
// Check if participant is in main interaction
|
|
502
|
+
isParticipantInMainInteraction(task, agentId);
|
|
503
|
+
|
|
504
|
+
// Check if conference is in progress
|
|
505
|
+
getIsConferenceInProgress(taskData);
|
|
506
|
+
|
|
507
|
+
// Check if agent is primary
|
|
508
|
+
isPrimary(task, agentId);
|
|
509
|
+
|
|
510
|
+
// Check if secondary EPDN agent
|
|
511
|
+
isSecondaryEpDnAgent(interaction);
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
---
|
|
515
|
+
|
|
516
|
+
## Metrics Tracking
|
|
517
|
+
|
|
518
|
+
| Metric | Type | When Tracked |
|
|
519
|
+
| ----------------------- | -------------------- | ------------------ |
|
|
520
|
+
| `TASK_ACCEPT_SUCCESS` | behavioral, business | Task accepted |
|
|
521
|
+
| `TASK_HOLD_SUCCESS` | operational | Hold succeeded |
|
|
522
|
+
| `TASK_END_SUCCESS` | behavioral, business | Task ended |
|
|
523
|
+
| `TASK_WRAPUP_SUCCESS` | operational | Wrapup completed |
|
|
524
|
+
| `TASK_TRANSFER_SUCCESS` | behavioral, business | Transfer completed |
|
|
525
|
+
| `TASK_OUTDIAL_SUCCESS` | behavioral, business | Outdial completed |
|
|
526
|
+
|
|
527
|
+
---
|
|
528
|
+
|
|
529
|
+
## Troubleshooting
|
|
530
|
+
|
|
531
|
+
### Issue: task:incoming not received
|
|
532
|
+
|
|
533
|
+
**Cause**: Agent not available or TaskManager not initialized
|
|
534
|
+
|
|
535
|
+
**Solution**:
|
|
536
|
+
|
|
537
|
+
1. Ensure `cc.register()` completed
|
|
538
|
+
2. Ensure `cc.stationLogin()` completed
|
|
539
|
+
3. Ensure agent state is Available
|
|
540
|
+
|
|
541
|
+
### Issue: Task operations fail
|
|
542
|
+
|
|
543
|
+
**Cause**: Task state doesn't allow operation
|
|
544
|
+
|
|
545
|
+
**Solution**: Check task state before operation:
|
|
546
|
+
|
|
547
|
+
```typescript
|
|
548
|
+
if (task.uiControls.hold.isEnabled) {
|
|
549
|
+
await task.hold();
|
|
550
|
+
}
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
### Issue: WebRTC call not connecting
|
|
554
|
+
|
|
555
|
+
**Cause**: Call not mapped to task
|
|
556
|
+
|
|
557
|
+
**Solution**: Ensure BROWSER login and mercury connected:
|
|
558
|
+
|
|
559
|
+
```typescript
|
|
560
|
+
await webex.internal.mercury.connect();
|
|
561
|
+
await cc.stationLogin({ loginOption: 'BROWSER', ... });
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
---
|
|
565
|
+
|
|
566
|
+
## Related Files
|
|
567
|
+
|
|
568
|
+
- [cc.ts](../../../cc.ts) - Main plugin
|
|
569
|
+
- [TaskManager.ts](../TaskManager.ts) - Manager
|
|
570
|
+
- [contact.ts](../contact.ts) - Contact operations
|
|
571
|
+
- [types.ts](../types.ts) - Type definitions
|
|
572
|
+
- [../state-machine/ai-docs/AGENTS.md](../state-machine/ai-docs/AGENTS.md) - State machine guide
|
|
573
|
+
- [../state-machine/ai-docs/ARCHITECTURE.md](../state-machine/ai-docs/ARCHITECTURE.md) - State machine architecture
|
|
@@ -22,10 +22,6 @@ export const END = '/end';
|
|
|
22
22
|
export const CONSULT_CONFERENCE = '/consult/conference';
|
|
23
23
|
export const CONFERENCE_EXIT = '/conference/exit';
|
|
24
24
|
export const CONFERENCE_TRANSFER = '/conference/transfer';
|
|
25
|
-
export const DIALER_API = '/v1/dialer';
|
|
26
|
-
export const CAMPAIGN_PREVIEW_ACCEPT = '/accept';
|
|
27
|
-
/** 80-second timeout for accepting preview contact (outbound call setup takes longer than default 20s) */
|
|
28
|
-
export const TIMEOUT_PREVIEW_ACCEPT = 80000;
|
|
29
25
|
export const TASK_MANAGER_FILE = 'taskManager';
|
|
30
26
|
export const TASK_FILE = 'task';
|
|
31
27
|
|
|
@@ -50,6 +46,10 @@ export const PRESERVED_TASK_DATA_FIELDS = {
|
|
|
50
46
|
*/
|
|
51
47
|
export const KEYS_TO_NOT_DELETE: string[] = Object.values(PRESERVED_TASK_DATA_FIELDS);
|
|
52
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Consultation status constants derived from state machine
|
|
51
|
+
* These values are computed and available in task.data.consultStatus
|
|
52
|
+
*/
|
|
53
53
|
// METHOD NAMES
|
|
54
54
|
export const METHODS = {
|
|
55
55
|
// Task class methods
|
|
@@ -83,6 +83,7 @@ export const METHODS = {
|
|
|
83
83
|
GET_TASK_MANAGER: 'getTaskManager',
|
|
84
84
|
SETUP_AUTO_WRAPUP_TIMER: 'setupAutoWrapupTimer',
|
|
85
85
|
CANCEL_AUTO_WRAPUP_TIMER: 'cancelAutoWrapupTimer',
|
|
86
|
+
REQUEST_REAL_TIME_TRANSCRIPTS: 'requestRealTimeTranscripts',
|
|
86
87
|
};
|
|
87
88
|
|
|
88
89
|
export const TRANSCRIPT_EVENT_MAP = {
|
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
import {CC_EVENTS} from '../config/types';
|
|
2
2
|
import {WCC_API_GATEWAY} from '../constants';
|
|
3
|
-
import {HTTP_METHODS} from '../../types';
|
|
4
3
|
import {createErrDetailsObject as err} from '../core/Utils';
|
|
5
|
-
import {
|
|
6
|
-
TASK_MESSAGE_TYPE,
|
|
7
|
-
TASK_API,
|
|
8
|
-
DIALER_API,
|
|
9
|
-
CAMPAIGN_PREVIEW_ACCEPT,
|
|
10
|
-
TIMEOUT_PREVIEW_ACCEPT,
|
|
11
|
-
} from './constants';
|
|
4
|
+
import {TASK_MESSAGE_TYPE, TASK_API} from './constants';
|
|
12
5
|
import * as Contact from './types';
|
|
13
6
|
import AqmReqs from '../core/aqm-reqs';
|
|
14
7
|
|
|
@@ -55,53 +48,5 @@ export default function aqmDialer(aqm: AqmReqs) {
|
|
|
55
48
|
errId: 'Service.aqm.dialer.startOutdial',
|
|
56
49
|
},
|
|
57
50
|
})),
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Accepts a campaign preview contact, initiating the outbound call.
|
|
61
|
-
*
|
|
62
|
-
* @param {Object} p - Parameters object.
|
|
63
|
-
* @param {Contact.PreviewContactPayload} p.data - Payload containing interactionId and campaignId.
|
|
64
|
-
* @returns {Promise<Contact.AgentContact>} A promise that resolves with agent contact on success.
|
|
65
|
-
*
|
|
66
|
-
* Emits:
|
|
67
|
-
* - `CC_EVENTS.AGENT_CONTACT_ASSIGNED` on success
|
|
68
|
-
* - `CC_EVENTS.CAMPAIGN_PREVIEW_ACCEPT_FAILED` on failure
|
|
69
|
-
* @ignore
|
|
70
|
-
*/
|
|
71
|
-
acceptPreviewContact: aqm.req((p: {data: Contact.PreviewContactPayload}) => ({
|
|
72
|
-
url: `${DIALER_API}/campaign/${encodeURIComponent(p.data.campaignId)}/preview-task/${
|
|
73
|
-
p.data.interactionId
|
|
74
|
-
}${CAMPAIGN_PREVIEW_ACCEPT}`,
|
|
75
|
-
host: WCC_API_GATEWAY,
|
|
76
|
-
data: {},
|
|
77
|
-
method: HTTP_METHODS.POST,
|
|
78
|
-
timeout: TIMEOUT_PREVIEW_ACCEPT,
|
|
79
|
-
err,
|
|
80
|
-
notifSuccess: {
|
|
81
|
-
bind: {
|
|
82
|
-
type: TASK_MESSAGE_TYPE,
|
|
83
|
-
data: {
|
|
84
|
-
type: [CC_EVENTS.AGENT_CONTACT_ASSIGNED, CC_EVENTS.CONTACT_ENDED],
|
|
85
|
-
__typeMap: {
|
|
86
|
-
typeField: 'type',
|
|
87
|
-
conditions: {
|
|
88
|
-
[CC_EVENTS.AGENT_CONTACT_ASSIGNED]: {
|
|
89
|
-
reservationInteractionId: p.data.interactionId,
|
|
90
|
-
},
|
|
91
|
-
[CC_EVENTS.CONTACT_ENDED]: {interactionId: p.data.interactionId},
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
msg: {} as Contact.AgentContact,
|
|
97
|
-
},
|
|
98
|
-
notifFail: {
|
|
99
|
-
bind: {
|
|
100
|
-
type: TASK_MESSAGE_TYPE,
|
|
101
|
-
data: {type: CC_EVENTS.CAMPAIGN_PREVIEW_ACCEPT_FAILED, campaignId: p.data.campaignId},
|
|
102
|
-
},
|
|
103
|
-
errId: 'Service.aqm.dialer.acceptPreviewContact',
|
|
104
|
-
},
|
|
105
|
-
})),
|
|
106
51
|
};
|
|
107
52
|
}
|