@webex/contact-center 3.12.0-next.147 → 3.12.0-next.149
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 +4 -2
- package/ai-docs/CONTRACTS.md +2 -0
- package/dist/cc.js +3 -1
- package/dist/cc.js.map +1 -1
- package/dist/constants.js +10 -1
- package/dist/constants.js.map +1 -1
- package/dist/index.js +9 -2
- package/dist/index.js.map +1 -1
- package/dist/metrics/constants.js +9 -0
- package/dist/metrics/constants.js.map +1 -1
- package/dist/services/ApiAiAssistant.js +87 -10
- package/dist/services/ApiAiAssistant.js.map +1 -1
- package/dist/services/config/types.js +10 -4
- package/dist/services/config/types.js.map +1 -1
- package/dist/services/core/types.js.map +1 -1
- package/dist/services/task/Task.js +202 -1
- package/dist/services/task/Task.js.map +1 -1
- package/dist/services/task/TaskFactory.js +4 -4
- package/dist/services/task/TaskFactory.js.map +1 -1
- package/dist/services/task/TaskManager.js +113 -26
- package/dist/services/task/TaskManager.js.map +1 -1
- package/dist/services/task/TaskUtils.js +11 -1
- package/dist/services/task/TaskUtils.js.map +1 -1
- package/dist/services/task/constants.js +11 -2
- package/dist/services/task/constants.js.map +1 -1
- package/dist/services/task/digital/Digital.js +2 -2
- package/dist/services/task/digital/Digital.js.map +1 -1
- package/dist/services/task/types.js +31 -0
- package/dist/services/task/types.js.map +1 -1
- package/dist/services/task/voice/Voice.js +2 -2
- package/dist/services/task/voice/Voice.js.map +1 -1
- package/dist/services/task/voice/WebRTC.js +2 -2
- package/dist/services/task/voice/WebRTC.js.map +1 -1
- package/dist/types/constants.d.ts +9 -0
- package/dist/types/index.d.ts +4 -5
- package/dist/types/metrics/constants.d.ts +8 -0
- package/dist/types/services/ApiAiAssistant.d.ts +4 -2
- package/dist/types/services/config/types.d.ts +17 -7
- package/dist/types/services/task/Task.d.ts +15 -4
- package/dist/types/services/task/TaskFactory.d.ts +3 -2
- package/dist/types/services/task/TaskUtils.d.ts +6 -0
- package/dist/types/services/task/constants.d.ts +9 -0
- package/dist/types/services/task/digital/Digital.d.ts +3 -2
- package/dist/types/services/task/types.d.ts +109 -1
- package/dist/types/services/task/voice/Voice.d.ts +3 -2
- package/dist/types/services/task/voice/WebRTC.d.ts +3 -2
- package/dist/types/types.d.ts +10 -4
- package/dist/types.js +8 -4
- package/dist/types.js.map +1 -1
- package/dist/webex.js +1 -1
- package/package.json +3 -3
- package/src/cc.ts +4 -0
- package/src/constants.ts +12 -0
- package/src/index.ts +10 -2
- package/src/metrics/ai-docs/metrics-spec.md +12 -4
- package/src/metrics/constants.ts +10 -0
- package/src/services/ApiAiAssistant.ts +120 -12
- package/src/services/config/types.ts +10 -4
- package/src/services/core/types.ts +31 -1
- package/src/services/task/Task.ts +308 -5
- package/src/services/task/TaskFactory.ts +26 -5
- package/src/services/task/TaskManager.ts +148 -29
- package/src/services/task/TaskUtils.ts +13 -0
- package/src/services/task/ai-docs/task-spec.md +30 -5
- package/src/services/task/constants.ts +10 -0
- package/src/services/task/digital/Digital.ts +8 -3
- package/src/services/task/types.ts +139 -0
- package/src/services/task/voice/Voice.ts +8 -3
- package/src/services/task/voice/WebRTC.ts +6 -3
- package/src/types.ts +10 -4
- package/test/unit/fixtures/aiSummaryTestUtils.ts +40 -0
- package/test/unit/spec/cc.ts +1314 -32
- package/test/unit/spec/index.ts +881 -0
- package/test/unit/spec/services/ApiAiAssistant.ts +122 -6
- package/test/unit/spec/services/core/WebexRequest.ts +5 -6
- package/test/unit/spec/services/task/Task.ts +1988 -10
- package/test/unit/spec/services/task/TaskFactory.ts +17 -0
- package/test/unit/spec/services/task/TaskManager.ts +2327 -180
- package/test/unit/spec/services/task/TaskUtils.ts +72 -0
- package/test/unit/spec/services/task/voice/Voice.ts +353 -18
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
|
@@ -13,10 +13,12 @@ import {
|
|
|
13
13
|
WebSocketMessage,
|
|
14
14
|
TaskEventActions,
|
|
15
15
|
EventContext,
|
|
16
|
+
AISummaryFeatureEnablement,
|
|
17
|
+
AISummary,
|
|
16
18
|
} from './types';
|
|
17
19
|
import {TASK_MANAGER_FILE} from '../../constants';
|
|
18
20
|
import {METHODS, TRANSCRIPT_EVENT_MAP} from './constants';
|
|
19
|
-
import {CC_EVENTS, WrapupData} from '../config/types';
|
|
21
|
+
import {CC_EVENTS, CC_TASK_EVENTS, WrapupData} from '../config/types';
|
|
20
22
|
import {ConfigFlags, LoginOption, AIAssistantEventType, AIAssistantEventName} from '../../types';
|
|
21
23
|
import LoggerProxy from '../../logger-proxy';
|
|
22
24
|
import {
|
|
@@ -77,9 +79,15 @@ export default class TaskManager extends EventEmitter {
|
|
|
77
79
|
private configFlags?: ConfigFlags;
|
|
78
80
|
private wrapupData: WrapupData;
|
|
79
81
|
private agentId: string;
|
|
82
|
+
private agentName: string;
|
|
80
83
|
private webRtcEnabled: boolean;
|
|
81
84
|
private answerCallOnWebexService?: AnswerCallOnWebexService;
|
|
82
85
|
private apiAIAssistant?: ApiAIAssistant;
|
|
86
|
+
private receivingSummaryBuffer = new Map<string, AISummary>();
|
|
87
|
+
|
|
88
|
+
// RTD feature frames can arrive before AQM creates the task.
|
|
89
|
+
private pendingFeatureEnablement = new Map<string, AISummaryFeatureEnablement>();
|
|
90
|
+
|
|
83
91
|
/**
|
|
84
92
|
* @param contact - Routing Contact layer. Talks to AQMReq layer to convert events to promises
|
|
85
93
|
* @param webCallingService - Webrtc Service Layer
|
|
@@ -100,7 +108,6 @@ export default class TaskManager extends EventEmitter {
|
|
|
100
108
|
this.rtdWebSocketManager = rtdWebSocketManager;
|
|
101
109
|
this.taskCollection = {};
|
|
102
110
|
this.webRtcEnabled = false;
|
|
103
|
-
|
|
104
111
|
this.registerTaskListeners();
|
|
105
112
|
this.registerIncomingCallEvent();
|
|
106
113
|
}
|
|
@@ -109,6 +116,56 @@ export default class TaskManager extends EventEmitter {
|
|
|
109
116
|
try {
|
|
110
117
|
const payload = JSON.parse(event);
|
|
111
118
|
|
|
119
|
+
switch (payload?.type) {
|
|
120
|
+
case CC_TASK_EVENTS.FEATURE_ENABLEMENT: {
|
|
121
|
+
const enablement: AISummaryFeatureEnablement = payload?.data?.data;
|
|
122
|
+
if (!enablement?.interactionId) return;
|
|
123
|
+
|
|
124
|
+
const task = this.taskCollection[enablement.interactionId];
|
|
125
|
+
if (task) {
|
|
126
|
+
this.pendingFeatureEnablement.delete(enablement.interactionId);
|
|
127
|
+
task.setFeatureEnablement?.(enablement);
|
|
128
|
+
task.emit(TASK_EVENTS.TASK_FEATURE_ENABLEMENT, enablement);
|
|
129
|
+
} else {
|
|
130
|
+
this.pendingFeatureEnablement.set(enablement.interactionId, enablement);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
case CC_TASK_EVENTS.POST_CALL_SUMMARY:
|
|
136
|
+
case CC_TASK_EVENTS.MID_CALL_SUMMARY: {
|
|
137
|
+
if (!payload?.data?.data?.conversationId) return;
|
|
138
|
+
|
|
139
|
+
this.apiAIAssistant?.resolveFromRtdEvent(
|
|
140
|
+
payload.type,
|
|
141
|
+
payload.data.data.conversationId,
|
|
142
|
+
payload.data.data
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
case CC_TASK_EVENTS.MID_CALL_SUMMARY_RESPONSE_SUBSEQUENT_AGENT: {
|
|
148
|
+
if (!payload?.data?.data?.conversationId) return;
|
|
149
|
+
|
|
150
|
+
const summary: AISummary = payload.data.data;
|
|
151
|
+
const {conversationId} = summary;
|
|
152
|
+
const task = this.taskCollection[conversationId];
|
|
153
|
+
const taskState = task?.state?.value;
|
|
154
|
+
|
|
155
|
+
// Emit only once the task is answered; until then it waits for the answer event.
|
|
156
|
+
if (task && taskState !== TaskState.IDLE && taskState !== TaskState.OFFERED) {
|
|
157
|
+
this.receivingSummaryBuffer.delete(conversationId);
|
|
158
|
+
task.emit(TASK_EVENTS.TASK_MID_CALL_SUMMARY_RECEIVED, summary);
|
|
159
|
+
} else {
|
|
160
|
+
this.receivingSummaryBuffer.set(conversationId, summary);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
default:
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
|
|
112
169
|
const interactionId = payload?.data?.data?.conversationId;
|
|
113
170
|
if (!interactionId) return;
|
|
114
171
|
|
|
@@ -128,6 +185,8 @@ export default class TaskManager extends EventEmitter {
|
|
|
128
185
|
case CC_EVENTS.SUGGESTED_RESPONSE:
|
|
129
186
|
task.emit(payload.type, payload.data);
|
|
130
187
|
break;
|
|
188
|
+
default:
|
|
189
|
+
break;
|
|
131
190
|
}
|
|
132
191
|
} catch (error) {
|
|
133
192
|
LoggerProxy.error('Failed to parse RTD WebSocket message', {
|
|
@@ -145,6 +204,13 @@ export default class TaskManager extends EventEmitter {
|
|
|
145
204
|
this.configFlags = configFlags;
|
|
146
205
|
}
|
|
147
206
|
|
|
207
|
+
public clearAISummaryState(): void {
|
|
208
|
+
this.apiAIAssistant?.clearAllRtdRequests();
|
|
209
|
+
Object.values(this.taskCollection).forEach((task) => task.clearFeatureEnablement?.());
|
|
210
|
+
this.receivingSummaryBuffer.clear();
|
|
211
|
+
this.pendingFeatureEnablement.clear();
|
|
212
|
+
}
|
|
213
|
+
|
|
148
214
|
/**
|
|
149
215
|
* Set wrapup configuration data
|
|
150
216
|
*/
|
|
@@ -159,6 +225,10 @@ export default class TaskManager extends EventEmitter {
|
|
|
159
225
|
this.agentId = agentId;
|
|
160
226
|
}
|
|
161
227
|
|
|
228
|
+
public setAgentName(agentName: string) {
|
|
229
|
+
this.agentName = agentName;
|
|
230
|
+
}
|
|
231
|
+
|
|
162
232
|
/**
|
|
163
233
|
* Gets the current agent ID
|
|
164
234
|
* @returns {string} The agent ID set for this task manager instance
|
|
@@ -723,6 +793,15 @@ export default class TaskManager extends EventEmitter {
|
|
|
723
793
|
task.sendStateMachineEvent(stateMachineEvent);
|
|
724
794
|
}
|
|
725
795
|
|
|
796
|
+
// A receiving summary held while the task rang is emitted right after the answer
|
|
797
|
+
// event above (AgentContactAssigned / AgentConsulting) has been emitted.
|
|
798
|
+
const bufferedSummary = this.receivingSummaryBuffer.get(task.data.interactionId);
|
|
799
|
+
const taskState = task.state?.value;
|
|
800
|
+
if (bufferedSummary && taskState !== TaskState.IDLE && taskState !== TaskState.OFFERED) {
|
|
801
|
+
this.receivingSummaryBuffer.delete(task.data.interactionId);
|
|
802
|
+
task.emit(TASK_EVENTS.TASK_MID_CALL_SUMMARY_RECEIVED, bufferedSummary);
|
|
803
|
+
}
|
|
804
|
+
|
|
726
805
|
// Emit TASK_POST_CALL_ACTIVITY for ParticipantPostCallActivity events so
|
|
727
806
|
// consumers (Widgets) can detect the interaction state change to post_call.
|
|
728
807
|
if (eventContext.eventType === CC_EVENTS.PARTICIPANT_POST_CALL_ACTIVITY) {
|
|
@@ -789,6 +868,7 @@ export default class TaskManager extends EventEmitter {
|
|
|
789
868
|
// Re-key the task under the new interaction ID and remove the old entry
|
|
790
869
|
delete this.taskCollection[reservationInteractionId];
|
|
791
870
|
this.taskCollection[interactionId] = task;
|
|
871
|
+
this.pendingFeatureEnablement.delete(reservationInteractionId);
|
|
792
872
|
}
|
|
793
873
|
}
|
|
794
874
|
|
|
@@ -1161,7 +1241,9 @@ export default class TaskManager extends EventEmitter {
|
|
|
1161
1241
|
this.configFlags,
|
|
1162
1242
|
this.wrapupData,
|
|
1163
1243
|
this.agentId,
|
|
1164
|
-
this.
|
|
1244
|
+
this.agentName,
|
|
1245
|
+
this.answerCallOnWebexService,
|
|
1246
|
+
this.apiAIAssistant
|
|
1165
1247
|
);
|
|
1166
1248
|
|
|
1167
1249
|
this.taskCollection[stableInteractionId] = task;
|
|
@@ -1272,7 +1354,9 @@ export default class TaskManager extends EventEmitter {
|
|
|
1272
1354
|
this.configFlags,
|
|
1273
1355
|
this.wrapupData,
|
|
1274
1356
|
this.agentId,
|
|
1275
|
-
this.
|
|
1357
|
+
this.agentName,
|
|
1358
|
+
this.answerCallOnWebexService,
|
|
1359
|
+
this.apiAIAssistant
|
|
1276
1360
|
);
|
|
1277
1361
|
this.setupTaskListeners(task);
|
|
1278
1362
|
this.taskCollection[payload.interactionId] = task;
|
|
@@ -1311,7 +1395,9 @@ export default class TaskManager extends EventEmitter {
|
|
|
1311
1395
|
this.configFlags,
|
|
1312
1396
|
this.wrapupData,
|
|
1313
1397
|
this.agentId,
|
|
1314
|
-
this.
|
|
1398
|
+
this.agentName,
|
|
1399
|
+
this.answerCallOnWebexService,
|
|
1400
|
+
this.apiAIAssistant
|
|
1315
1401
|
);
|
|
1316
1402
|
|
|
1317
1403
|
this.setupTaskListeners(task);
|
|
@@ -1352,7 +1438,9 @@ export default class TaskManager extends EventEmitter {
|
|
|
1352
1438
|
this.configFlags,
|
|
1353
1439
|
this.wrapupData,
|
|
1354
1440
|
this.agentId,
|
|
1355
|
-
this.
|
|
1441
|
+
this.agentName,
|
|
1442
|
+
this.answerCallOnWebexService,
|
|
1443
|
+
this.apiAIAssistant
|
|
1356
1444
|
);
|
|
1357
1445
|
this.setupTaskListeners(task);
|
|
1358
1446
|
this.taskCollection[payload.interactionId] = task;
|
|
@@ -1389,6 +1477,10 @@ export default class TaskManager extends EventEmitter {
|
|
|
1389
1477
|
}
|
|
1390
1478
|
});
|
|
1391
1479
|
this.taskCollection[taskData.interactionId] = task;
|
|
1480
|
+
const enablement = this.pendingFeatureEnablement.get(task.data.interactionId);
|
|
1481
|
+
if (enablement) {
|
|
1482
|
+
task.setFeatureEnablement?.(enablement);
|
|
1483
|
+
}
|
|
1392
1484
|
|
|
1393
1485
|
return task;
|
|
1394
1486
|
}
|
|
@@ -1398,31 +1490,46 @@ export default class TaskManager extends EventEmitter {
|
|
|
1398
1490
|
* This replaces the previous callback injection pattern
|
|
1399
1491
|
*/
|
|
1400
1492
|
private setupTaskListeners(task: ITask): void {
|
|
1401
|
-
//
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
interactionId: t.data?.interactionId,
|
|
1407
|
-
});
|
|
1408
|
-
|
|
1409
|
-
this.emit(TASK_EVENTS.TASK_INCOMING, t);
|
|
1410
|
-
});
|
|
1493
|
+
// Apply flags before publication; retain the frame until consumers can attach listeners.
|
|
1494
|
+
const enablement = this.pendingFeatureEnablement.get(task.data.interactionId);
|
|
1495
|
+
if (enablement) {
|
|
1496
|
+
task.setFeatureEnablement?.(enablement);
|
|
1497
|
+
}
|
|
1411
1498
|
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1499
|
+
[
|
|
1500
|
+
TASK_EVENTS.TASK_INCOMING,
|
|
1501
|
+
TASK_EVENTS.TASK_CAMPAIGN_PREVIEW_RESERVATION,
|
|
1502
|
+
TASK_EVENTS.TASK_HYDRATE,
|
|
1503
|
+
TASK_EVENTS.TASK_ASSIGNED,
|
|
1504
|
+
].forEach((eventName) => {
|
|
1505
|
+
task.on(eventName, (t: ITask) => {
|
|
1506
|
+
if (
|
|
1507
|
+
eventName === TASK_EVENTS.TASK_INCOMING ||
|
|
1508
|
+
eventName === TASK_EVENTS.TASK_CAMPAIGN_PREVIEW_RESERVATION
|
|
1509
|
+
) {
|
|
1510
|
+
LoggerProxy.log(
|
|
1511
|
+
eventName === TASK_EVENTS.TASK_INCOMING
|
|
1512
|
+
? 'Task incoming event received'
|
|
1513
|
+
: 'Campaign preview reservation event received',
|
|
1514
|
+
{
|
|
1515
|
+
module: TASK_MANAGER_FILE,
|
|
1516
|
+
method: METHODS.REGISTER_TASK_LISTENERS,
|
|
1517
|
+
interactionId: t.data?.interactionId,
|
|
1518
|
+
}
|
|
1519
|
+
);
|
|
1520
|
+
}
|
|
1418
1521
|
|
|
1419
|
-
|
|
1420
|
-
|
|
1522
|
+
// Assignment is already emitted on the task; the other events publish it to consumers.
|
|
1523
|
+
if (eventName !== TASK_EVENTS.TASK_ASSIGNED) {
|
|
1524
|
+
this.emit(eventName, t);
|
|
1525
|
+
}
|
|
1421
1526
|
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1527
|
+
const pendingEnablement = this.pendingFeatureEnablement.get(task.data.interactionId);
|
|
1528
|
+
if (pendingEnablement) {
|
|
1529
|
+
this.pendingFeatureEnablement.delete(task.data.interactionId);
|
|
1530
|
+
task.emit(TASK_EVENTS.TASK_FEATURE_ENABLEMENT, pendingEnablement);
|
|
1531
|
+
}
|
|
1532
|
+
});
|
|
1426
1533
|
});
|
|
1427
1534
|
|
|
1428
1535
|
task.on(TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE, (t: ITask) => {
|
|
@@ -1444,11 +1551,16 @@ export default class TaskManager extends EventEmitter {
|
|
|
1444
1551
|
}
|
|
1445
1552
|
|
|
1446
1553
|
private removeTaskFromCollection(task: ITask) {
|
|
1554
|
+
task.clearFeatureEnablement?.();
|
|
1447
1555
|
task.disposeWxAppOfferObservability?.();
|
|
1448
1556
|
if (typeof task.cancelAutoWrapupTimer === 'function') {
|
|
1449
1557
|
task.cancelAutoWrapupTimer();
|
|
1450
1558
|
}
|
|
1451
1559
|
if (task?.data?.interactionId) {
|
|
1560
|
+
this.pendingFeatureEnablement.delete(task.data.interactionId);
|
|
1561
|
+
// An offer that ends unanswered (RONA, declined, consult cancelled) is removed here,
|
|
1562
|
+
// so its held receiving summary is dropped instead of being emitted.
|
|
1563
|
+
this.receivingSummaryBuffer.delete(task.data.interactionId);
|
|
1452
1564
|
Object.entries(this.taskCollection).forEach(([taskId, candidate]) => {
|
|
1453
1565
|
if (candidate === task) {
|
|
1454
1566
|
delete this.taskCollection[taskId];
|
|
@@ -1507,7 +1619,9 @@ export default class TaskManager extends EventEmitter {
|
|
|
1507
1619
|
this.configFlags,
|
|
1508
1620
|
this.wrapupData,
|
|
1509
1621
|
this.agentId,
|
|
1510
|
-
this.
|
|
1622
|
+
this.agentName,
|
|
1623
|
+
this.answerCallOnWebexService,
|
|
1624
|
+
this.apiAIAssistant
|
|
1511
1625
|
);
|
|
1512
1626
|
this.taskCollection[payload.interactionId] = task;
|
|
1513
1627
|
|
|
@@ -1527,6 +1641,11 @@ export default class TaskManager extends EventEmitter {
|
|
|
1527
1641
|
|
|
1528
1642
|
if (task) {
|
|
1529
1643
|
this.emit(TASK_EVENTS.TASK_MERGED, task);
|
|
1644
|
+
const enablement = this.pendingFeatureEnablement.get(task.data.interactionId);
|
|
1645
|
+
if (enablement) {
|
|
1646
|
+
this.pendingFeatureEnablement.delete(task.data.interactionId);
|
|
1647
|
+
task.emit(TASK_EVENTS.TASK_FEATURE_ENABLEMENT, enablement);
|
|
1648
|
+
}
|
|
1530
1649
|
}
|
|
1531
1650
|
|
|
1532
1651
|
return {task};
|
|
@@ -12,6 +12,19 @@ import {TaskContext} from './state-machine/types';
|
|
|
12
12
|
import {CC_EVENTS} from '../config/types';
|
|
13
13
|
import {OUTBOUND_TYPE, OUTDIAL_DIRECTION, OUTDIAL_MEDIA_TYPE} from '../../constants';
|
|
14
14
|
|
|
15
|
+
type AISummaryError = Error & {data?: Record<string, unknown>};
|
|
16
|
+
|
|
17
|
+
export const isNonEmptyString = (value: unknown): value is string =>
|
|
18
|
+
typeof value === 'string' && value.length > 0;
|
|
19
|
+
|
|
20
|
+
export const createSummaryError = (errorCode: string): AISummaryError => {
|
|
21
|
+
const error = new Error(errorCode) as AISummaryError;
|
|
22
|
+
|
|
23
|
+
error.data = {errorCode};
|
|
24
|
+
|
|
25
|
+
return error;
|
|
26
|
+
};
|
|
27
|
+
|
|
15
28
|
const CAMPAIGN_PREVIEW_OUTBOUND_TYPES = ['STANDARD_PREVIEW_CAMPAIGN', 'DIRECT_PREVIEW_CAMPAIGN'];
|
|
16
29
|
const CAMPAIGN_PREVIEW_CAMPAIGN_TYPES = ['preview_standard', 'preview_direct'];
|
|
17
30
|
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
| Doc kind | Module spec |
|
|
12
12
|
| Coverage score | Partial (manifest-authoritative); 15/15 required document fields present |
|
|
13
13
|
| Generated from | `module-spec` @ SDLC template library `0.2.1` |
|
|
14
|
-
| generated_by / approved_by / updated_at | Codex generator / developer-approved follow-up review remediation / 2026-
|
|
15
|
-
| Validation status |
|
|
14
|
+
| generated_by / approved_by / updated_at | Codex generator / developer-approved follow-up review remediation / 2026-10-06 |
|
|
15
|
+
| Validation status | AI summary methods, delivery, and cleanup updates pending independent review (2026-10-06); prior follow-up validation passed (independent Claude fallback, 2026-07-21); 1 existing test-coverage gap; coverage remains Partial |
|
|
16
16
|
|
|
17
17
|
## Evidence Rules
|
|
18
18
|
Every requirement cites stable source and test file paths. Code/tests are the behavioral referee; routed source text supplies explicit intent and rationale. Missing or contradictory evidence blocks promotion.
|
|
@@ -143,6 +143,7 @@ services/task/
|
|
|
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
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
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` |
|
|
146
|
+
| `task.ai-summary` | SDK/RTD API | Post-call and mid-call summary request/response methods, feature enablement, and receiving-agent summary events. | Provide task-scoped generated summaries without exposing RTD correlation to SDK consumers. | Additive semver-public methods, types, and events; removals or signature changes are breaking. | `src/services/task/Task.ts`, `src/services/task/TaskManager.ts`, `src/services/task/types.ts`, `src/services/ApiAiAssistant.ts` | `../../../../ai-docs/CONTRACTS.md` |
|
|
146
147
|
|
|
147
148
|
Compatibility notes:
|
|
148
149
|
- Do not remove or reinterpret exported symbols/events without a documented consumer migration.
|
|
@@ -151,6 +152,8 @@ Compatibility notes:
|
|
|
151
152
|
|
|
152
153
|
- `TaskData`, `TaskId`, `TaskResponse`, `TaskUIControls` (`types.ts`)
|
|
153
154
|
|
|
155
|
+
- `AISummary`, `AISummaryResponse`, `AISummaryAction`, `AISummaryFeatureEnablement`, and `AISummaryCapabilities` (`types.ts`)
|
|
156
|
+
|
|
154
157
|
- `PreviewContactPayload` (`types.ts`) with `interactionId` and campaign-name `campaignId`
|
|
155
158
|
|
|
156
159
|
- `DropConferenceParticipantPayload` (`types.ts`) with a runtime-validated non-empty `participantId`
|
|
@@ -191,6 +194,8 @@ Compatibility notes:
|
|
|
191
194
|
| `task:switchCall` | Switched between consult and main call |
|
|
192
195
|
| `task:outdialFailed` | Outdial operation failed |
|
|
193
196
|
| `task:ui-controls-updated` | UI controls changed due to state transition |
|
|
197
|
+
| `task:midCallSummaryReceived` | Mid-call summary delivered to a receiving agent |
|
|
198
|
+
| `task:featureEnablement` | Per-task AI summary enablement flags received |
|
|
194
199
|
| `task:cleanup` | Internal cleanup signal emitted by state machine |
|
|
195
200
|
|
|
196
201
|
> Full list is defined in `TASK_EVENTS` (`types.ts`).
|
|
@@ -200,6 +205,23 @@ Compatibility notes:
|
|
|
200
205
|
| `REAL_TIME_TRANSCRIPTION` | A realtime transcript payload is received for the task interaction |
|
|
201
206
|
| `SUGGESTED_RESPONSE` | A final AI Assistant suggestion payload is received for the task interaction |
|
|
202
207
|
|
|
208
|
+
### AI summary APIs
|
|
209
|
+
|
|
210
|
+
- `requestPostCallSummary(): Promise<AISummary>` requests a post-call summary.
|
|
211
|
+
- `sendPostCallSummaryResponse(response: AISummaryResponse): Promise<void>` reports the agent's post-call summary outcome.
|
|
212
|
+
- `requestMidCallSummary(action: AISummaryAction): Promise<AISummary>` requests a consult or transfer summary.
|
|
213
|
+
- `sendMidCallSummaryResponse(response: AISummaryResponse, action: AISummaryAction): Promise<void>` reports the corresponding mid-call outcome.
|
|
214
|
+
|
|
215
|
+
Summary requests require both the organization-level generated-summary flag and the task-level feature enablement flag. The dedicated request methods read the current organization flags directly from the existing `ApiAIAssistant.aiFeature` field, populated by ContactCenter from the agent configuration. They check `generatedSummaries.wrapUpSummariesEnabled` or `generatedSummaries.consultTransferSummariesEnabled`; missing flags disable the corresponding request. No separate feature-flags argument or task-local organization configuration is needed. A request resolves only after the event POST succeeds and the matching RTD payload arrives; otherwise it rejects with the applicable disabled, transport, or timeout error. Receiving-agent summaries are delivered separately through `task:midCallSummaryReceived`. Summary content is application data and must not be written to logs or metrics.
|
|
216
|
+
|
|
217
|
+
Task-level feature flags survive `updateTaskData()`, including interaction ID changes during consults or task re-keying. Flags remain available throughout wrapup for post-call summary requests, and TaskManager clears them when the task is removed after wrapup completion or another terminal lifecycle event. Session cleanup also clears them.
|
|
218
|
+
|
|
219
|
+
Each dedicated Task summary method owns its event selection, payload construction, metrics, and error handling. The request methods call `ApiAIAssistant.requestAndWaitForRtd()`. Both response methods read `interactionId` from the current task data and use `interaction.mainInteractionId` as `conversationId`, falling back to `interactionId`. They call `ApiAIAssistant.sendEvent()` directly without caching request IDs on the task.
|
|
220
|
+
|
|
221
|
+
TaskManager reads the receiving task directly from `taskCollection[summary.conversationId]`; the RTD conversation ID is the task's collection key (`task.data.interactionId`). It emits `task:midCallSummaryReceived` immediately when that task exists. Otherwise it stores the latest summary for that ID in an in-memory map without an expiry timer, so an RTD frame can wait for task creation. The common AQM event-processing path replays the stored payload after task creation, updates that register the task under that ID, or merge publication. Replay after creation or merge follows the public task event so consumers can attach listeners. Delivery removes the stored summary, and session cleanup clears all pending summaries.
|
|
222
|
+
|
|
223
|
+
`clearAISummaryState()` cancels pending summary requests, clears task feature enablement, and empties both pending maps. ContactCenter's `deregister()` removes the RTD message listener synchronously before asynchronous teardown. RTD listener registration and removal control inbound delivery; `setConfigFlags()` only supplies task configuration.
|
|
224
|
+
|
|
203
225
|
Initiate outbound call.
|
|
204
226
|
|
|
205
227
|
**Parameters**:
|
|
@@ -366,7 +388,7 @@ await task.dropConferenceParticipant({participantId});
|
|
|
366
388
|
|
|
367
389
|
### Complete TASK_EVENTS inventory
|
|
368
390
|
|
|
369
|
-
The public `TASK_EVENTS` enum contains
|
|
391
|
+
The public `TASK_EVENTS` enum contains 52 members; every member is listed below from `src/services/task/types.ts`.
|
|
370
392
|
|
|
371
393
|
| Constant | Event string |
|
|
372
394
|
|---|---|
|
|
@@ -380,6 +402,7 @@ The public `TASK_EVENTS` enum contains 49 members; every member is listed below
|
|
|
380
402
|
| `TASK_CONSULT_QUEUE_CANCELLED` | `task:consultQueueCancelled` |
|
|
381
403
|
| `TASK_CONSULT_QUEUE_FAILED` | `task:consultQueueFailed` |
|
|
382
404
|
| `TASK_UI_CONTROLS_UPDATED` | `task:ui-controls-updated` |
|
|
405
|
+
| `TASK_WXAPP_MUTE_STATE_UPDATED` | `task:wxapp-mute-state-updated` |
|
|
383
406
|
| `TASK_CONSULT_ACCEPTED` | `task:consultAccepted` |
|
|
384
407
|
| `TASK_CONSULTING` | `task:consulting` |
|
|
385
408
|
| `TASK_CONSULT_CREATED` | `task:consultCreated` |
|
|
@@ -419,6 +442,8 @@ The public `TASK_EVENTS` enum contains 49 members; every member is listed below
|
|
|
419
442
|
| `TASK_CAMPAIGN_PREVIEW_SKIP_FAILED` | `task:campaignPreviewSkipFailed` |
|
|
420
443
|
| `TASK_CAMPAIGN_PREVIEW_REMOVE_FAILED` | `task:campaignPreviewRemoveFailed` |
|
|
421
444
|
| `TASK_CAMPAIGN_CONTACT_UPDATED` | `task:campaignContactUpdated` |
|
|
445
|
+
| `TASK_MID_CALL_SUMMARY_RECEIVED` | `task:midCallSummaryReceived` |
|
|
446
|
+
| `TASK_FEATURE_ENABLEMENT` | `task:featureEnablement` |
|
|
422
447
|
|
|
423
448
|
## Requires (dependencies)
|
|
424
449
|
- Services contact/dialer AQM factories
|
|
@@ -1153,7 +1178,7 @@ sequenceDiagram
|
|
|
1153
1178
|
|
|
1154
1179
|
**API**
|
|
1155
1180
|
|
|
1156
|
-
- `createTask(contact, webCallingService, data, configFlags, wrapupData?, agentId?): Task`
|
|
1181
|
+
- `createTask(contact, webCallingService, data, configFlags, wrapupData?, agentId?, agentName?): Task`
|
|
1157
1182
|
|
|
1158
1183
|
**Behavior**
|
|
1159
1184
|
|
|
@@ -1229,7 +1254,7 @@ classDiagram
|
|
|
1229
1254
|
}
|
|
1230
1255
|
|
|
1231
1256
|
class TaskFactory {
|
|
1232
|
-
+ createTask(contact, webCallingService, data, configFlags, wrapupData, agentId) Task
|
|
1257
|
+
+ createTask(contact, webCallingService, data, configFlags, wrapupData, agentId, agentName) Task
|
|
1233
1258
|
}
|
|
1234
1259
|
|
|
1235
1260
|
Task <|-- Voice
|
|
@@ -30,6 +30,10 @@ export const CAMPAIGN_PREVIEW_SKIP = '/skip';
|
|
|
30
30
|
export const CAMPAIGN_PREVIEW_REMOVE = '/remove';
|
|
31
31
|
/** 80-second timeout for accepting preview contact (outbound call setup takes longer than default 20s) */
|
|
32
32
|
export const TIMEOUT_PREVIEW_ACCEPT = 80000;
|
|
33
|
+
/** RTD result deadline; the initiating HTTP acknowledgement uses the 20-second service timeout. */
|
|
34
|
+
export const AI_SUMMARY_DURATION_MS = 15000;
|
|
35
|
+
export const AI_SUMMARY_REQUEST_CANCELLED = 'AI_SUMMARY_REQUEST_CANCELLED' as const;
|
|
36
|
+
|
|
33
37
|
export const TASK_MANAGER_FILE = 'taskManager';
|
|
34
38
|
export const TASK_FILE = 'task';
|
|
35
39
|
|
|
@@ -93,6 +97,12 @@ export const METHODS = {
|
|
|
93
97
|
SETUP_AUTO_WRAPUP_TIMER: 'setupAutoWrapupTimer',
|
|
94
98
|
CANCEL_AUTO_WRAPUP_TIMER: 'cancelAutoWrapupTimer',
|
|
95
99
|
REQUEST_REAL_TIME_TRANSCRIPTS: 'requestRealTimeTranscripts',
|
|
100
|
+
REQUEST_POST_CALL_SUMMARY: 'requestPostCallSummary',
|
|
101
|
+
SEND_POST_CALL_SUMMARY_RESPONSE: 'sendPostCallSummaryResponse',
|
|
102
|
+
REQUEST_MID_CALL_SUMMARY: 'requestMidCallSummary',
|
|
103
|
+
SEND_MID_CALL_SUMMARY_RESPONSE: 'sendMidCallSummaryResponse',
|
|
104
|
+
HANDLE_AI_SUMMARY_EVENT: 'handleAISummaryEvent',
|
|
105
|
+
CLEAR_AI_SUMMARY_STATE: 'clearAISummaryState',
|
|
96
106
|
};
|
|
97
107
|
|
|
98
108
|
export const TRANSCRIPT_EVENT_MAP = {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import {CC_FILE, METHODS} from '../../../constants';
|
|
2
2
|
import {getErrorDetails} from '../../core/Utils';
|
|
3
3
|
import {ConsultTransferDestinationConfig, IDigital, TaskResponse, TaskData} from '../types';
|
|
4
|
-
import {WrapupData} from '../../config/types';
|
|
4
|
+
import type {WrapupData} from '../../config/types';
|
|
5
|
+
import type ApiAIAssistant from '../../ApiAiAssistant';
|
|
5
6
|
import Task from '../Task';
|
|
6
7
|
import routingContact from '../contact';
|
|
7
8
|
import LoggerProxy from '../../../logger-proxy';
|
|
@@ -14,7 +15,9 @@ export default class Digital extends Task implements IDigital {
|
|
|
14
15
|
data: TaskData,
|
|
15
16
|
wrapupData?: WrapupData,
|
|
16
17
|
agentId?: string,
|
|
17
|
-
consultTransferConfig?: ConsultTransferDestinationConfig
|
|
18
|
+
consultTransferConfig?: ConsultTransferDestinationConfig,
|
|
19
|
+
agentName?: string,
|
|
20
|
+
apiAIAssistant?: ApiAIAssistant
|
|
18
21
|
) {
|
|
19
22
|
super(
|
|
20
23
|
contact,
|
|
@@ -26,7 +29,9 @@ export default class Digital extends Task implements IDigital {
|
|
|
26
29
|
consultTransferConfig,
|
|
27
30
|
},
|
|
28
31
|
wrapupData,
|
|
29
|
-
agentId
|
|
32
|
+
agentId,
|
|
33
|
+
agentName,
|
|
34
|
+
apiAIAssistant
|
|
30
35
|
);
|
|
31
36
|
}
|
|
32
37
|
|
|
@@ -716,6 +716,27 @@ export enum TASK_EVENTS {
|
|
|
716
716
|
* ```
|
|
717
717
|
*/
|
|
718
718
|
TASK_CAMPAIGN_CONTACT_UPDATED = 'task:campaignContactUpdated',
|
|
719
|
+
|
|
720
|
+
/**
|
|
721
|
+
* Triggered when a mid-call summary is received for the task.
|
|
722
|
+
*/
|
|
723
|
+
TASK_MID_CALL_SUMMARY_RECEIVED = 'task:midCallSummaryReceived',
|
|
724
|
+
|
|
725
|
+
/**
|
|
726
|
+
* Triggered on the task object when AI feature enablement flags arrive for that task's interaction.
|
|
727
|
+
* Fires immediately if the frame arrived after the task was registered, or at registration time
|
|
728
|
+
* if the frame arrived before the task (orphan retention). Consumers should use this event
|
|
729
|
+
* instead of the cc-level `FEATURE_ENABLEMENT` event so they do not need to maintain an
|
|
730
|
+
* interactionId → flags map manually.
|
|
731
|
+
* @example
|
|
732
|
+
* ```typescript
|
|
733
|
+
* task.on(TASK_EVENTS.TASK_FEATURE_ENABLEMENT, (enablement: AISummaryFeatureEnablement) => {
|
|
734
|
+
* const { midCallEnabled, postCallEnabled } = enablement;
|
|
735
|
+
* // gate summary UI on these flags
|
|
736
|
+
* });
|
|
737
|
+
* ```
|
|
738
|
+
*/
|
|
739
|
+
TASK_FEATURE_ENABLEMENT = 'task:featureEnablement',
|
|
719
740
|
}
|
|
720
741
|
|
|
721
742
|
/**
|
|
@@ -1669,6 +1690,78 @@ export type ParticipantBooleanKey =
|
|
|
1669
1690
|
*/
|
|
1670
1691
|
export type TaskResponse = AgentContact | Error | void;
|
|
1671
1692
|
|
|
1693
|
+
/** AI-assisted mid-call summary action. @public */
|
|
1694
|
+
export type AISummaryAction = 'CONSULT' | 'TRANSFER';
|
|
1695
|
+
|
|
1696
|
+
/** Feedback value sent with an AI summary response. @public */
|
|
1697
|
+
export type AISummaryFeedback = 'none' | 'thumbs_up' | 'thumbs_down';
|
|
1698
|
+
|
|
1699
|
+
/** AI summary response state for post-call and mid-call flows. @public */
|
|
1700
|
+
export type AISummaryState =
|
|
1701
|
+
| 'DEFAULT'
|
|
1702
|
+
| 'EXCLUDED'
|
|
1703
|
+
| 'IGNORED'
|
|
1704
|
+
| 'MID_CALL_CANCELLED'
|
|
1705
|
+
| 'NOT_RECEIVED';
|
|
1706
|
+
|
|
1707
|
+
/** Structured fields shared by post-call and mid-call summaries. @public */
|
|
1708
|
+
export type AISummarySections = {
|
|
1709
|
+
initialContactReason?: string;
|
|
1710
|
+
additionalContactReasons?: string;
|
|
1711
|
+
additionalContext?: string;
|
|
1712
|
+
keyActionsTaken?: string;
|
|
1713
|
+
nextSteps?: string;
|
|
1714
|
+
reasonForTransferOrConsult?: string;
|
|
1715
|
+
};
|
|
1716
|
+
|
|
1717
|
+
/** RTD payload returned or delivered for an AI summary. @public */
|
|
1718
|
+
export type AISummary = {
|
|
1719
|
+
conversationId: string;
|
|
1720
|
+
adaptiveCard?: Record<string, unknown>;
|
|
1721
|
+
adaptiveCardId?: string;
|
|
1722
|
+
editAdaptiveCard?: Record<string, unknown>;
|
|
1723
|
+
editAdaptiveCardId?: string;
|
|
1724
|
+
areTranscriptsAvailable?: boolean;
|
|
1725
|
+
languageCode?: string;
|
|
1726
|
+
resolution?: string;
|
|
1727
|
+
sections?: AISummarySections;
|
|
1728
|
+
suggestedWrapUpCodes?: Array<{name: string; [key: string]: unknown}>;
|
|
1729
|
+
suggestedWrapUpCodesMessage?: string;
|
|
1730
|
+
summaryText?: string;
|
|
1731
|
+
timestamp?: number;
|
|
1732
|
+
[key: string]: unknown;
|
|
1733
|
+
};
|
|
1734
|
+
|
|
1735
|
+
/** RTD payload describing AI-summary feature enablement for an interaction. @public */
|
|
1736
|
+
export type AISummaryFeatureEnablement = {
|
|
1737
|
+
interactionId: string;
|
|
1738
|
+
midCallEnabled?: boolean;
|
|
1739
|
+
postCallEnabled?: boolean;
|
|
1740
|
+
actionTimestamp?: number;
|
|
1741
|
+
[key: string]: unknown;
|
|
1742
|
+
};
|
|
1743
|
+
|
|
1744
|
+
/** Current AI-summary capabilities for a task. @public */
|
|
1745
|
+
export type AISummaryCapabilities = Required<
|
|
1746
|
+
Pick<AISummaryFeatureEnablement, 'midCallEnabled' | 'postCallEnabled'>
|
|
1747
|
+
>;
|
|
1748
|
+
|
|
1749
|
+
/**
|
|
1750
|
+
* Payload sent when reporting a post-call or mid-call summary result.
|
|
1751
|
+
* Transport timestamps are generated by the SDK when the response is sent.
|
|
1752
|
+
* @public
|
|
1753
|
+
*/
|
|
1754
|
+
export type AISummaryResponse = {
|
|
1755
|
+
summary: AISummarySections | string;
|
|
1756
|
+
feedback: AISummaryFeedback;
|
|
1757
|
+
state: AISummaryState;
|
|
1758
|
+
numberOfTimesViewed: number;
|
|
1759
|
+
numberOfTimesEdited: number;
|
|
1760
|
+
numberOfTimesCopied: number;
|
|
1761
|
+
summaryReceived?: boolean;
|
|
1762
|
+
wrapUpCode?: string;
|
|
1763
|
+
};
|
|
1764
|
+
|
|
1672
1765
|
/**
|
|
1673
1766
|
* Request payload for removing a supported participant from an active conference.
|
|
1674
1767
|
* @public
|
|
@@ -1717,6 +1810,12 @@ export interface ITask extends IEventEmitter {
|
|
|
1717
1810
|
*/
|
|
1718
1811
|
data: TaskData;
|
|
1719
1812
|
|
|
1813
|
+
/**
|
|
1814
|
+
* Current AI-summary capabilities for this task. Both flags are false until
|
|
1815
|
+
* the matching feature-enablement event is received.
|
|
1816
|
+
*/
|
|
1817
|
+
readonly aiSummaryCapabilities: Readonly<AISummaryCapabilities>;
|
|
1818
|
+
|
|
1720
1819
|
/**
|
|
1721
1820
|
* Map associating tasks with their corresponding call identifiers.
|
|
1722
1821
|
*/
|
|
@@ -1804,6 +1903,46 @@ export interface ITask extends IEventEmitter {
|
|
|
1804
1903
|
*/
|
|
1805
1904
|
cancelAutoWrapupTimer(): void;
|
|
1806
1905
|
|
|
1906
|
+
/**
|
|
1907
|
+
* Applies the AI-summary feature flags received for this task's interaction.
|
|
1908
|
+
* @internal
|
|
1909
|
+
*/
|
|
1910
|
+
setFeatureEnablement?(enablement: AISummaryFeatureEnablement): void;
|
|
1911
|
+
|
|
1912
|
+
/**
|
|
1913
|
+
* Clears the task-local AI-summary feature flags on task removal or session cleanup.
|
|
1914
|
+
* @internal
|
|
1915
|
+
*/
|
|
1916
|
+
clearFeatureEnablement?(): void;
|
|
1917
|
+
|
|
1918
|
+
/**
|
|
1919
|
+
* Requests an AI-generated post-call summary for this task.
|
|
1920
|
+
* @returns Promise resolving with the matching post-call summary payload.
|
|
1921
|
+
*/
|
|
1922
|
+
requestPostCallSummary(): Promise<AISummary>;
|
|
1923
|
+
|
|
1924
|
+
/**
|
|
1925
|
+
* Sends the consumer's post-call summary response.
|
|
1926
|
+
* @param response - Validated post-call response observations and summary state.
|
|
1927
|
+
* @returns Promise resolving when AI Assistant acknowledges the response.
|
|
1928
|
+
*/
|
|
1929
|
+
sendPostCallSummaryResponse(response: AISummaryResponse): Promise<void>;
|
|
1930
|
+
|
|
1931
|
+
/**
|
|
1932
|
+
* Requests an AI-generated mid-call summary for a consult or transfer flow.
|
|
1933
|
+
* @param action - The consult or transfer flow requesting the summary.
|
|
1934
|
+
* @returns Promise resolving with the matching mid-call summary payload.
|
|
1935
|
+
*/
|
|
1936
|
+
requestMidCallSummary(action: AISummaryAction): Promise<AISummary>;
|
|
1937
|
+
|
|
1938
|
+
/**
|
|
1939
|
+
* Sends the consumer's mid-call summary response for a consult or transfer flow.
|
|
1940
|
+
* @param response - Validated mid-call response observations and summary state.
|
|
1941
|
+
* @param action - The consult or transfer flow responding to the summary.
|
|
1942
|
+
* @returns Promise resolving when AI Assistant acknowledges the response.
|
|
1943
|
+
*/
|
|
1944
|
+
sendMidCallSummaryResponse(response: AISummaryResponse, action: AISummaryAction): Promise<void>;
|
|
1945
|
+
|
|
1807
1946
|
/**
|
|
1808
1947
|
* Deregisters all web call event listeners.
|
|
1809
1948
|
* Used when cleaning up task resources.
|