@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
|
@@ -352,6 +352,34 @@ const eventTaxonomyMap: Record<string, BehavioralEventTaxonomy> = {
|
|
|
352
352
|
verb: 'fail',
|
|
353
353
|
},
|
|
354
354
|
|
|
355
|
+
// Conference Exit
|
|
356
|
+
[METRIC_EVENT_NAMES.TASK_CONFERENCE_EXIT_SUCCESS]: {
|
|
357
|
+
product,
|
|
358
|
+
agent: 'user',
|
|
359
|
+
target: 'task_conference_exit',
|
|
360
|
+
verb: 'complete',
|
|
361
|
+
},
|
|
362
|
+
[METRIC_EVENT_NAMES.TASK_CONFERENCE_EXIT_FAILED]: {
|
|
363
|
+
product,
|
|
364
|
+
agent: 'user',
|
|
365
|
+
target: 'task_conference_exit',
|
|
366
|
+
verb: 'fail',
|
|
367
|
+
},
|
|
368
|
+
|
|
369
|
+
// Switch Call
|
|
370
|
+
[METRIC_EVENT_NAMES.TASK_SWITCH_CALL_SUCCESS]: {
|
|
371
|
+
product,
|
|
372
|
+
agent: 'user',
|
|
373
|
+
target: 'task_switch_call',
|
|
374
|
+
verb: 'complete',
|
|
375
|
+
},
|
|
376
|
+
[METRIC_EVENT_NAMES.TASK_SWITCH_CALL_FAILED]: {
|
|
377
|
+
product,
|
|
378
|
+
agent: 'user',
|
|
379
|
+
target: 'task_switch_call',
|
|
380
|
+
verb: 'fail',
|
|
381
|
+
},
|
|
382
|
+
|
|
355
383
|
// upload logs
|
|
356
384
|
[METRIC_EVENT_NAMES.UPLOAD_LOGS_SUCCESS]: {
|
|
357
385
|
product,
|
|
@@ -435,20 +463,6 @@ const eventTaxonomyMap: Record<string, BehavioralEventTaxonomy> = {
|
|
|
435
463
|
target: 'outdial_ani_ep_fetch',
|
|
436
464
|
verb: 'fail',
|
|
437
465
|
},
|
|
438
|
-
|
|
439
|
-
// Campaign Preview API Events
|
|
440
|
-
[METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_ACCEPT_SUCCESS]: {
|
|
441
|
-
product,
|
|
442
|
-
agent: 'user',
|
|
443
|
-
target: 'campaign_preview_accept',
|
|
444
|
-
verb: 'complete',
|
|
445
|
-
},
|
|
446
|
-
[METRIC_EVENT_NAMES.CAMPAIGN_PREVIEW_ACCEPT_FAILED]: {
|
|
447
|
-
product,
|
|
448
|
-
agent: 'user',
|
|
449
|
-
target: 'campaign_preview_accept',
|
|
450
|
-
verb: 'fail',
|
|
451
|
-
},
|
|
452
466
|
};
|
|
453
467
|
|
|
454
468
|
/**
|
package/src/metrics/constants.ts
CHANGED
|
@@ -129,6 +129,10 @@ export const METRIC_EVENT_NAMES = {
|
|
|
129
129
|
TASK_CONFERENCE_END_FAILED: 'Task Conference End Failed',
|
|
130
130
|
TASK_CONFERENCE_TRANSFER_SUCCESS: 'Task Conference Transfer Success',
|
|
131
131
|
TASK_CONFERENCE_TRANSFER_FAILED: 'Task Conference Transfer Failed',
|
|
132
|
+
TASK_CONFERENCE_EXIT_SUCCESS: 'Task Conference Exit Success',
|
|
133
|
+
TASK_CONFERENCE_EXIT_FAILED: 'Task Conference Exit Failed',
|
|
134
|
+
TASK_SWITCH_CALL_SUCCESS: 'Task Switch Call Success',
|
|
135
|
+
TASK_SWITCH_CALL_FAILED: 'Task Switch Call Failed',
|
|
132
136
|
|
|
133
137
|
TASK_OUTDIAL_SUCCESS: 'Task Outdial Success',
|
|
134
138
|
TASK_OUTDIAL_FAILED: 'Task Outdial Failed',
|
|
@@ -138,11 +142,10 @@ export const METRIC_EVENT_NAMES = {
|
|
|
138
142
|
WEBSOCKET_DEREGISTER_SUCCESS: 'Websocket Deregister Success',
|
|
139
143
|
WEBSOCKET_DEREGISTER_FAIL: 'Websocket Deregister Failed',
|
|
140
144
|
|
|
141
|
-
// WebSocket message events
|
|
142
|
-
WEBSOCKET_EVENT_RECEIVED: 'Websocket Event Received',
|
|
143
|
-
|
|
144
145
|
AGENT_DEVICE_TYPE_UPDATE_SUCCESS: 'Agent Device Type Update Success',
|
|
145
146
|
AGENT_DEVICE_TYPE_UPDATE_FAILED: 'Agent Device Type Update Failed',
|
|
147
|
+
// WebSocket message events
|
|
148
|
+
WEBSOCKET_EVENT_RECEIVED: 'Websocket Event Received',
|
|
146
149
|
|
|
147
150
|
// EntryPoint API Events
|
|
148
151
|
ENTRYPOINT_FETCH_SUCCESS: 'Entrypoint Fetch Success',
|
|
@@ -160,11 +163,7 @@ export const METRIC_EVENT_NAMES = {
|
|
|
160
163
|
OUTDIAL_ANI_EP_FETCH_SUCCESS: 'Outdial ANI Entries Fetch Success',
|
|
161
164
|
OUTDIAL_ANI_EP_FETCH_FAILED: 'Outdial ANI Entries Fetch Failed',
|
|
162
165
|
|
|
163
|
-
//
|
|
164
|
-
CAMPAIGN_PREVIEW_ACCEPT_SUCCESS: 'Campaign Preview Accept Success',
|
|
165
|
-
CAMPAIGN_PREVIEW_ACCEPT_FAILED: 'Campaign Preview Accept Failed',
|
|
166
|
-
|
|
167
|
-
// AI Assistant transcript events
|
|
166
|
+
// AI Assistant events
|
|
168
167
|
AI_ASSISTANT_SEND_EVENT_SUCCESS: 'AI Assistant Send Event Success',
|
|
169
168
|
AI_ASSISTANT_SEND_EVENT_FAILED: 'AI Assistant Send Event Failed',
|
|
170
169
|
AI_ASSISTANT_FETCH_HISTORIC_TRANSCRIPTS_SUCCESS:
|
|
@@ -27,7 +27,7 @@ import {AIFeatureFlags} from './config/types';
|
|
|
27
27
|
export class ApiAIAssistant {
|
|
28
28
|
private webex: WebexSDK;
|
|
29
29
|
private metricsManager: MetricsManager;
|
|
30
|
-
|
|
30
|
+
private aiFeature: AIFeatureFlags;
|
|
31
31
|
|
|
32
32
|
constructor(webex: WebexSDK) {
|
|
33
33
|
this.webex = webex;
|
|
@@ -201,9 +201,7 @@ export class ApiAIAssistant {
|
|
|
201
201
|
},
|
|
202
202
|
['operational']
|
|
203
203
|
);
|
|
204
|
-
|
|
205
|
-
throw error;
|
|
206
|
-
}
|
|
204
|
+
|
|
207
205
|
const {error: detailedError} = getErrorDetails(
|
|
208
206
|
error,
|
|
209
207
|
METHODS.FETCH_HISTORIC_TRANSCRIPTS,
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# Agent Service - AI Agent Guide
|
|
2
|
+
|
|
3
|
+
> **Purpose**: Manage agent lifecycle including login, logout, state changes, and buddy agent queries.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
const cc = webex.cc;
|
|
11
|
+
|
|
12
|
+
// Register and login
|
|
13
|
+
const profile = await cc.register();
|
|
14
|
+
await cc.stationLogin({
|
|
15
|
+
teamId: profile.teams[0].teamId,
|
|
16
|
+
loginOption: 'BROWSER',
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// Set state to Available
|
|
20
|
+
await cc.setAgentState({
|
|
21
|
+
state: 'Available',
|
|
22
|
+
auxCodeId: '0',
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Get available agents for transfer
|
|
26
|
+
const buddies = await cc.getBuddyAgents({
|
|
27
|
+
state: 'Available',
|
|
28
|
+
mediaType: 'telephony',
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Key Capabilities
|
|
35
|
+
|
|
36
|
+
- **Station Login**: Login with browser (WebRTC), extension, or dial number
|
|
37
|
+
- **Station Logout**: Logout from current station with reason
|
|
38
|
+
- **State Management**: Toggle between Available/Idle states with aux codes
|
|
39
|
+
- **Buddy Agents**: Query available agents for consult/transfer
|
|
40
|
+
- **Silent Relogin**: Automatic re-authentication on reconnection
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## API Reference
|
|
45
|
+
|
|
46
|
+
### Login Options
|
|
47
|
+
|
|
48
|
+
| Option | Description | Requires dialNumber |
|
|
49
|
+
|--------|-------------|---------------------|
|
|
50
|
+
| `BROWSER` | WebRTC softphone in browser | No |
|
|
51
|
+
| `EXTENSION` | Desk phone extension | Yes |
|
|
52
|
+
| `AGENT_DN` | Direct dial number | Yes |
|
|
53
|
+
|
|
54
|
+
### Methods
|
|
55
|
+
|
|
56
|
+
#### `cc.stationLogin(params)`
|
|
57
|
+
|
|
58
|
+
Login agent to a station.
|
|
59
|
+
|
|
60
|
+
**Parameters**:
|
|
61
|
+
- `teamId` (string): Team to login to
|
|
62
|
+
- `loginOption` ('BROWSER' | 'EXTENSION' | 'AGENT_DN'): Device type
|
|
63
|
+
- `dialNumber` (string, optional): Required for EXTENSION/AGENT_DN
|
|
64
|
+
|
|
65
|
+
**Returns**: `Promise<StationLoginResponse>`
|
|
66
|
+
|
|
67
|
+
**Example**:
|
|
68
|
+
```typescript
|
|
69
|
+
// Browser login
|
|
70
|
+
const response = await cc.stationLogin({
|
|
71
|
+
teamId: 'team-123',
|
|
72
|
+
loginOption: 'BROWSER',
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Extension login
|
|
76
|
+
const response = await cc.stationLogin({
|
|
77
|
+
teamId: 'team-123',
|
|
78
|
+
loginOption: 'EXTENSION',
|
|
79
|
+
dialNumber: '1234',
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
#### `cc.stationLogout(params)`
|
|
86
|
+
|
|
87
|
+
Logout agent from station.
|
|
88
|
+
|
|
89
|
+
**Parameters**:
|
|
90
|
+
- `logoutReason` (string, optional): 'User requested logout' | 'Inactivity Logout' | 'User requested agent profile update'
|
|
91
|
+
|
|
92
|
+
**Returns**: `Promise<StationLogoutResponse>`
|
|
93
|
+
|
|
94
|
+
**Example**:
|
|
95
|
+
```typescript
|
|
96
|
+
await cc.stationLogout({
|
|
97
|
+
logoutReason: 'User requested logout',
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
#### `cc.setAgentState(params)`
|
|
104
|
+
|
|
105
|
+
Change agent state (Available/Idle).
|
|
106
|
+
|
|
107
|
+
**Parameters**:
|
|
108
|
+
- `state` ('Available' | 'Idle'): New state
|
|
109
|
+
- `auxCodeId` (string): Auxiliary code ID
|
|
110
|
+
- `lastStateChangeReason` (string, optional): Reason for change
|
|
111
|
+
- `agentId` (string, optional): Agent ID (defaults to current agent)
|
|
112
|
+
|
|
113
|
+
**Returns**: `Promise<SetStateResponse>`
|
|
114
|
+
|
|
115
|
+
**Example**:
|
|
116
|
+
```typescript
|
|
117
|
+
// Go Available
|
|
118
|
+
await cc.setAgentState({
|
|
119
|
+
state: 'Available',
|
|
120
|
+
auxCodeId: '0',
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Go to Idle with specific code
|
|
124
|
+
await cc.setAgentState({
|
|
125
|
+
state: 'Idle',
|
|
126
|
+
auxCodeId: 'break-code-123',
|
|
127
|
+
lastStateChangeReason: 'Coffee break',
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
#### `cc.getBuddyAgents(params)`
|
|
134
|
+
|
|
135
|
+
Get list of agents for consult/transfer.
|
|
136
|
+
|
|
137
|
+
**Parameters**:
|
|
138
|
+
- `state` (string, optional): Filter by state ('Available', 'Idle')
|
|
139
|
+
- `mediaType` (string): Media type filter ('telephony', 'chat', 'social', 'email')
|
|
140
|
+
**Returns**: `Promise<BuddyAgentsResponse>`
|
|
141
|
+
|
|
142
|
+
**Example**:
|
|
143
|
+
```typescript
|
|
144
|
+
const response = await cc.getBuddyAgents({
|
|
145
|
+
state: 'Available',
|
|
146
|
+
mediaType: 'telephony',
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
response.data.agentList.forEach(agent => {
|
|
150
|
+
console.log(`${agent.agentName} (${agent.state})`);
|
|
151
|
+
});
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Events
|
|
157
|
+
|
|
158
|
+
| Event | Type | Description |
|
|
159
|
+
|-------|------|-------------|
|
|
160
|
+
| `agent:stationLoginSuccess` | `StationLoginSuccessResponse` | Login succeeded |
|
|
161
|
+
| `agent:stationLoginFailed` | Error | Login failed |
|
|
162
|
+
| `agent:logoutSuccess` | `LogoutSuccess` | Logout succeeded |
|
|
163
|
+
| `agent:logoutFailed` | Error | Logout failed |
|
|
164
|
+
| `agent:stateChange` | `StateChangeSuccess` | State changed (any source) |
|
|
165
|
+
| `agent:stateChangeSuccess` | `StateChangeSuccess` | State change succeeded |
|
|
166
|
+
| `agent:stateChangeFailed` | Error | State change failed |
|
|
167
|
+
| `agent:multiLogin` | Object | Multi-login detected |
|
|
168
|
+
| `agent:reloginSuccess` | `ReloginSuccess` | Silent relogin succeeded |
|
|
169
|
+
| `agent:dnRegistered` | Object | DN registration complete |
|
|
170
|
+
|
|
171
|
+
### Event Usage
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
cc.on('agent:stateChange', (event) => {
|
|
175
|
+
console.log(`State: ${event.subStatus}, AuxCode: ${event.auxCodeId}`);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
cc.on('agent:multiLogin', (event) => {
|
|
179
|
+
console.warn('Another session detected');
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Agent States
|
|
186
|
+
|
|
187
|
+
The `AgentState` type (`'Available' | 'Idle' | 'RONA' | string`) is extensible -- the `string` union member allows backend-defined states beyond the known values listed below.
|
|
188
|
+
|
|
189
|
+
| State | SubStatus | Description |
|
|
190
|
+
|-------|-----------|-------------|
|
|
191
|
+
| LoggedIn | Available | Ready to receive tasks |
|
|
192
|
+
| LoggedIn | Idle | On break or not ready (uses aux code for sub-reason) |
|
|
193
|
+
| RONA | - | Rang but no answer; agent failed to accept offered task |
|
|
194
|
+
| LoggedOut | - | Not logged in |
|
|
195
|
+
| LoggedIn | *(custom)* | Additional org-specific states defined via aux codes |
|
|
196
|
+
|
|
197
|
+
> **Note**: `AgentState` is a union with `string`, so consumers should handle unknown state values gracefully rather than exhaustively matching only the known literals.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Error Handling
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
try {
|
|
205
|
+
await cc.stationLogin(params);
|
|
206
|
+
} catch (error) {
|
|
207
|
+
console.error('Login failed:', error.message);
|
|
208
|
+
// Access error details
|
|
209
|
+
if (error.data) {
|
|
210
|
+
console.error('Field:', error.data.fieldName);
|
|
211
|
+
console.error('Message:', error.data.message);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Common Error Reasons
|
|
217
|
+
|
|
218
|
+
| Reason | Description |
|
|
219
|
+
|--------|-------------|
|
|
220
|
+
| `DUPLICATE_LOCATION` | Extension/DN already in use |
|
|
221
|
+
| `INVALID_DIAL_NUMBER` | Invalid phone number format |
|
|
222
|
+
| `AGENT_NOT_FOUND` | Agent doesn't exist (silent relogin) |
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Dependencies
|
|
227
|
+
|
|
228
|
+
- Requires `cc.register()` to be called first
|
|
229
|
+
- Agent profile must be fetched before login
|
|
230
|
+
- WebRTC (BROWSER option) requires mercury connection
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Related
|
|
235
|
+
|
|
236
|
+
- [ARCHITECTURE.md](ARCHITECTURE.md) - Technical deep-dive
|
|
237
|
+
- [`cc.ts`](../../../cc.ts) - Main plugin implementation
|
|
238
|
+
- [`types.ts`](../types.ts) - Type definitions
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
# Agent Service - Architecture
|
|
2
|
+
|
|
3
|
+
> **Purpose**: Technical documentation for agent lifecycle operations.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Component Overview
|
|
8
|
+
|
|
9
|
+
| Component | File | Responsibility |
|
|
10
|
+
| --------------- | --------------------------- | --------------------------------------------------------------- |
|
|
11
|
+
| `ContactCenter` | `src/cc.ts` | Plugin class exposing agent methods |
|
|
12
|
+
| `routingAgent` | `services/agent/index.ts` | AQM request definitions |
|
|
13
|
+
| `Services` | `services/index.ts` | Service singleton with agent service |
|
|
14
|
+
| `AqmReqs` | `services/core/aqm-reqs.ts` | HTTP requests to backend; responses via WebSocket notifications |
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## File Structure
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
services/agent/
|
|
22
|
+
├── index.ts # Agent service factory
|
|
23
|
+
├── types.ts # Agent types and events
|
|
24
|
+
└── ai-docs/
|
|
25
|
+
├── AGENTS.md # Usage documentation
|
|
26
|
+
└── ARCHITECTURE.md # This file
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Service Factory Pattern
|
|
32
|
+
|
|
33
|
+
The agent service uses a factory pattern:
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
// services/agent/index.ts
|
|
37
|
+
export default function routingAgent(routing: AqmReqs) {
|
|
38
|
+
return {
|
|
39
|
+
stationLogin: routing.req((p: {data: UserStationLogin}) => ({
|
|
40
|
+
url: '/v1/agents/login',
|
|
41
|
+
host: WCC_API_GATEWAY,
|
|
42
|
+
data: p.data,
|
|
43
|
+
notifSuccess: {
|
|
44
|
+
bind: {type: CC_EVENTS.AGENT_STATION_LOGIN, ...},
|
|
45
|
+
msg: {} as StationLoginSuccess,
|
|
46
|
+
},
|
|
47
|
+
notifFail: {...},
|
|
48
|
+
})),
|
|
49
|
+
logout: routing.req((p: {data: Logout}) => ({...})),
|
|
50
|
+
stateChange: routing.req((p: {data: StateChange}) => ({...})),
|
|
51
|
+
buddyAgents: routing.req((p: {data: BuddyAgents}) => ({...})),
|
|
52
|
+
reload: routing.reqEmpty(() => ({...})),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Data Flow
|
|
60
|
+
|
|
61
|
+
### Station Login Flow
|
|
62
|
+
|
|
63
|
+
```mermaid
|
|
64
|
+
flowchart TD
|
|
65
|
+
A[cc.stationLogin] --> B[Validate input]
|
|
66
|
+
B --> C[services.agent.stationLogin]
|
|
67
|
+
C --> D[AqmReqs.req]
|
|
68
|
+
D --> E[HTTP REST request to backend]
|
|
69
|
+
E --> F[Backend processes]
|
|
70
|
+
F --> G{Success?}
|
|
71
|
+
G -->|Yes| H[StationLoginSuccess event]
|
|
72
|
+
G -->|No| I[StationLoginFailed event]
|
|
73
|
+
H --> J[Register WebCalling if BROWSER]
|
|
74
|
+
J --> K[Track metrics]
|
|
75
|
+
K --> L[Return response]
|
|
76
|
+
I --> M[getErrorDetails]
|
|
77
|
+
M --> N[Throw error]
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Sequence Diagrams
|
|
83
|
+
|
|
84
|
+
### Station Login
|
|
85
|
+
|
|
86
|
+
```mermaid
|
|
87
|
+
sequenceDiagram
|
|
88
|
+
participant App
|
|
89
|
+
participant CC as ContactCenter
|
|
90
|
+
participant Svc as Services.agent
|
|
91
|
+
participant AQM as AqmReqs
|
|
92
|
+
participant WS as WebSocket
|
|
93
|
+
participant BE as Backend
|
|
94
|
+
App->>CC: stationLogin(params)
|
|
95
|
+
CC->>CC: Validate dial number
|
|
96
|
+
CC->>CC: timeEvent(LOGIN_SUCCESS, LOGIN_FAILED)
|
|
97
|
+
CC->>Svc: stationLogin({data})
|
|
98
|
+
Svc->>AQM: req(config)
|
|
99
|
+
AQM->>BE: HTTP POST /v1/agents/login
|
|
100
|
+
BE-->>WS: AgentStationLoginSuccess
|
|
101
|
+
WS-->>AQM: Resolve with response
|
|
102
|
+
AQM-->>Svc: Return response
|
|
103
|
+
Svc-->>CC: Login response
|
|
104
|
+
CC->>CC: Register WebCalling (if BROWSER)
|
|
105
|
+
CC->>CC: trackEvent(LOGIN_SUCCESS)
|
|
106
|
+
CC-->>App: StationLoginResponse
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### State Change
|
|
110
|
+
|
|
111
|
+
```mermaid
|
|
112
|
+
sequenceDiagram
|
|
113
|
+
participant App
|
|
114
|
+
participant CC as ContactCenter
|
|
115
|
+
participant Svc as Services.agent
|
|
116
|
+
participant WS as WebSocket
|
|
117
|
+
participant BE as Backend
|
|
118
|
+
|
|
119
|
+
App->>CC: setAgentState(params)
|
|
120
|
+
CC->>CC: timeEvent(STATE_SUCCESS, STATE_FAILED)
|
|
121
|
+
CC->>Svc: stateChange({data})
|
|
122
|
+
Svc->>BE: HTTP PUT /v1/agents/session/state
|
|
123
|
+
BE-->>WS: AgentStateChangeSuccess
|
|
124
|
+
WS-->>CC: Emit via handleWebsocketMessage
|
|
125
|
+
CC->>CC: emit(agent:stateChange)
|
|
126
|
+
CC->>CC: trackEvent(STATE_SUCCESS)
|
|
127
|
+
CC-->>App: SetStateResponse
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Request Configuration
|
|
133
|
+
|
|
134
|
+
Each agent method defines:
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
{
|
|
138
|
+
url: '/v1/agents/...', // API endpoint
|
|
139
|
+
host: WCC_API_GATEWAY, // Base URL
|
|
140
|
+
data: p.data, // Request payload
|
|
141
|
+
method: HTTP_METHODS.POST, // HTTP method (POST if data present, GET otherwise)
|
|
142
|
+
err: errorHandler, // Error transformer
|
|
143
|
+
notifSuccess: {
|
|
144
|
+
bind: {
|
|
145
|
+
type: CC_EVENTS.SUCCESS_TYPE,
|
|
146
|
+
data: {type: CC_EVENTS.SUCCESS_TYPE},
|
|
147
|
+
},
|
|
148
|
+
msg: {} as SuccessType, // Response type hint
|
|
149
|
+
},
|
|
150
|
+
notifFail: {
|
|
151
|
+
bind: {
|
|
152
|
+
type: CC_EVENTS.FAIL_TYPE,
|
|
153
|
+
data: {type: CC_EVENTS.FAIL_TYPE},
|
|
154
|
+
},
|
|
155
|
+
errId: 'Service.aqm.agent.method',
|
|
156
|
+
},
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Event Flow
|
|
163
|
+
|
|
164
|
+
### WebSocket to Application
|
|
165
|
+
|
|
166
|
+
```mermaid
|
|
167
|
+
flowchart LR
|
|
168
|
+
A[WebSocket Message] --> B[WebSocketManager]
|
|
169
|
+
B --> C[cc.handleWebsocketMessage]
|
|
170
|
+
C --> D{Event Type?}
|
|
171
|
+
D -->|AGENT_STATE_CHANGE| E[emit agent:stateChange]
|
|
172
|
+
D -->|data.type check| F{Nested Type?}
|
|
173
|
+
F -->|STATION_LOGIN_SUCCESS| G[Transform channelsMap]
|
|
174
|
+
G --> H[emit agent:stationLoginSuccess]
|
|
175
|
+
F -->|LOGOUT_SUCCESS| I[emit agent:logoutSuccess]
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### ChannelsMap Transformation
|
|
179
|
+
|
|
180
|
+
The login success event transforms `channelsMap` to `mmProfile`:
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
// Incoming
|
|
184
|
+
channelsMap: {
|
|
185
|
+
chat: ['channel-1', 'channel-2'],
|
|
186
|
+
email: ['channel-3'],
|
|
187
|
+
telephony: ['channel-4'],
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Transformed
|
|
191
|
+
mmProfile: {
|
|
192
|
+
chat: 2, // Length of arrays
|
|
193
|
+
email: 1,
|
|
194
|
+
social: 0,
|
|
195
|
+
telephony: 1,
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Silent Relogin
|
|
202
|
+
|
|
203
|
+
Automatic relogin on WebSocket reconnection:
|
|
204
|
+
|
|
205
|
+
```mermaid
|
|
206
|
+
flowchart TD
|
|
207
|
+
A[WebSocket Reconnected] --> B[handleConnectionLost]
|
|
208
|
+
B --> C{allowAutomatedRelogin?}
|
|
209
|
+
C -->|Yes| D[silentRelogin]
|
|
210
|
+
D --> E[services.agent.reload]
|
|
211
|
+
E --> F{Success?}
|
|
212
|
+
F -->|Yes| G[Update agentConfig]
|
|
213
|
+
G --> H{lastStateChangeReason?}
|
|
214
|
+
H -->|agent-wss-disconnect| I[setAgentState Available]
|
|
215
|
+
H -->|Other| J[Keep current state]
|
|
216
|
+
F -->|No, AGENT_NOT_FOUND| K[Handle silently]
|
|
217
|
+
F -->|No, Other| L[Throw error]
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Error Handling
|
|
223
|
+
|
|
224
|
+
### Login Error Details
|
|
225
|
+
|
|
226
|
+
For `stationLogin`, special error handling extracts field-specific messages:
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
// Utils.ts - getStationLoginErrorData
|
|
230
|
+
const errorCodeMessageMap = {
|
|
231
|
+
DUPLICATE_LOCATION: {
|
|
232
|
+
message: 'This extension is already in use',
|
|
233
|
+
fieldName: loginOption,
|
|
234
|
+
},
|
|
235
|
+
INVALID_DIAL_NUMBER: {
|
|
236
|
+
message: 'Enter a valid US dial number...',
|
|
237
|
+
fieldName: loginOption,
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Metrics Tracking
|
|
245
|
+
|
|
246
|
+
| Metric | Type | When Tracked |
|
|
247
|
+
| ---------------------------- | --------------------------------- | ------------------------ |
|
|
248
|
+
| `STATION_LOGIN_SUCCESS` | behavioral, business, operational | Login succeeds |
|
|
249
|
+
| `STATION_LOGIN_FAILED` | behavioral, business, operational | Login fails |
|
|
250
|
+
| `STATION_LOGOUT_SUCCESS` | behavioral, business, operational | Logout succeeds |
|
|
251
|
+
| `STATION_LOGOUT_FAILED` | behavioral, business, operational | Logout fails |
|
|
252
|
+
| `AGENT_STATE_CHANGE_SUCCESS` | behavioral, business, operational | State change succeeds |
|
|
253
|
+
| `AGENT_STATE_CHANGE_FAILED` | behavioral, business, operational | State change fails |
|
|
254
|
+
| `FETCH_BUDDY_AGENTS_SUCCESS` | operational | Buddy agents fetched |
|
|
255
|
+
| `FETCH_BUDDY_AGENTS_FAILED` | operational | Buddy agents fetch fails |
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Troubleshooting
|
|
260
|
+
|
|
261
|
+
### Issue: Login fails with DUPLICATE_LOCATION
|
|
262
|
+
|
|
263
|
+
**Cause**: Extension/DN already in use by another session
|
|
264
|
+
|
|
265
|
+
**Solution**:
|
|
266
|
+
|
|
267
|
+
1. Logout from other session
|
|
268
|
+
2. Use different extension
|
|
269
|
+
3. Contact admin if stuck
|
|
270
|
+
|
|
271
|
+
### Issue: State change fails
|
|
272
|
+
|
|
273
|
+
**Cause**: Agent may be in a call or transitioning state
|
|
274
|
+
|
|
275
|
+
**Solution**:
|
|
276
|
+
1. Complete current interaction
|
|
277
|
+
2. Wait for state to stabilize
|
|
278
|
+
3. Retry state change
|
|
279
|
+
|
|
280
|
+
### Issue: Silent relogin not working
|
|
281
|
+
|
|
282
|
+
**Cause**: `allowAutomatedRelogin` config not set
|
|
283
|
+
|
|
284
|
+
**Solution**:
|
|
285
|
+
```typescript
|
|
286
|
+
const webex = Webex.init({
|
|
287
|
+
config: {
|
|
288
|
+
cc: {
|
|
289
|
+
allowAutomatedRelogin: true,
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
});
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Related Files
|
|
298
|
+
|
|
299
|
+
- [cc.ts](../../../cc.ts) - Main plugin
|
|
300
|
+
- [agent/index.ts](../index.ts) - Service implementation
|
|
301
|
+
- [agent/types.ts](../types.ts) - Type definitions
|
|
302
|
+
- [cc.ts test](../../../../test/unit/spec/cc.ts) - Test file
|