@webex/contact-center 3.9.0 → 3.10.0-multi-llms.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.
Files changed (115) hide show
  1. package/dist/cc.js +207 -47
  2. package/dist/cc.js.map +1 -1
  3. package/dist/constants.js +1 -0
  4. package/dist/constants.js.map +1 -1
  5. package/dist/index.js +9 -0
  6. package/dist/index.js.map +1 -1
  7. package/dist/logger-proxy.js +24 -1
  8. package/dist/logger-proxy.js.map +1 -1
  9. package/dist/metrics/MetricsManager.js +1 -1
  10. package/dist/metrics/MetricsManager.js.map +1 -1
  11. package/dist/metrics/behavioral-events.js +89 -0
  12. package/dist/metrics/behavioral-events.js.map +1 -1
  13. package/dist/metrics/constants.js +32 -2
  14. package/dist/metrics/constants.js.map +1 -1
  15. package/dist/services/AddressBook.js +271 -0
  16. package/dist/services/AddressBook.js.map +1 -0
  17. package/dist/services/EntryPoint.js +227 -0
  18. package/dist/services/EntryPoint.js.map +1 -0
  19. package/dist/services/Queue.js +261 -0
  20. package/dist/services/Queue.js.map +1 -0
  21. package/dist/services/config/constants.js +36 -2
  22. package/dist/services/config/constants.js.map +1 -1
  23. package/dist/services/config/index.js +29 -21
  24. package/dist/services/config/index.js.map +1 -1
  25. package/dist/services/config/types.js +33 -1
  26. package/dist/services/config/types.js.map +1 -1
  27. package/dist/services/core/GlobalTypes.js.map +1 -1
  28. package/dist/services/core/Utils.js +181 -2
  29. package/dist/services/core/Utils.js.map +1 -1
  30. package/dist/services/core/aqm-reqs.js +0 -4
  31. package/dist/services/core/aqm-reqs.js.map +1 -1
  32. package/dist/services/core/constants.js +17 -1
  33. package/dist/services/core/constants.js.map +1 -1
  34. package/dist/services/core/websocket/WebSocketManager.js +0 -4
  35. package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
  36. package/dist/services/task/TaskManager.js +151 -7
  37. package/dist/services/task/TaskManager.js.map +1 -1
  38. package/dist/services/task/TaskUtils.js +104 -0
  39. package/dist/services/task/TaskUtils.js.map +1 -0
  40. package/dist/services/task/constants.js +26 -1
  41. package/dist/services/task/constants.js.map +1 -1
  42. package/dist/services/task/contact.js +86 -0
  43. package/dist/services/task/contact.js.map +1 -1
  44. package/dist/services/task/index.js +428 -91
  45. package/dist/services/task/index.js.map +1 -1
  46. package/dist/services/task/types.js +12 -0
  47. package/dist/services/task/types.js.map +1 -1
  48. package/dist/types/cc.d.ts +121 -35
  49. package/dist/types/constants.d.ts +1 -0
  50. package/dist/types/index.d.ts +4 -3
  51. package/dist/types/metrics/constants.d.ts +25 -1
  52. package/dist/types/services/AddressBook.d.ts +74 -0
  53. package/dist/types/services/EntryPoint.d.ts +67 -0
  54. package/dist/types/services/Queue.d.ts +76 -0
  55. package/dist/types/services/config/constants.d.ts +35 -1
  56. package/dist/types/services/config/index.d.ts +6 -9
  57. package/dist/types/services/config/types.d.ts +79 -58
  58. package/dist/types/services/core/GlobalTypes.d.ts +25 -0
  59. package/dist/types/services/core/Utils.d.ts +55 -1
  60. package/dist/types/services/core/constants.d.ts +14 -0
  61. package/dist/types/services/task/TaskUtils.d.ts +42 -0
  62. package/dist/types/services/task/constants.d.ts +23 -0
  63. package/dist/types/services/task/contact.d.ts +10 -0
  64. package/dist/types/services/task/index.d.ts +85 -4
  65. package/dist/types/services/task/types.d.ts +245 -21
  66. package/dist/types/types.d.ts +162 -0
  67. package/dist/types/utils/PageCache.d.ts +173 -0
  68. package/dist/types.js +17 -0
  69. package/dist/types.js.map +1 -1
  70. package/dist/utils/PageCache.js +192 -0
  71. package/dist/utils/PageCache.js.map +1 -0
  72. package/dist/webex.js +1 -1
  73. package/package.json +10 -9
  74. package/src/cc.ts +232 -52
  75. package/src/constants.ts +1 -0
  76. package/src/index.ts +17 -2
  77. package/src/logger-proxy.ts +24 -1
  78. package/src/metrics/MetricsManager.ts +1 -1
  79. package/src/metrics/behavioral-events.ts +94 -0
  80. package/src/metrics/constants.ts +37 -1
  81. package/src/services/AddressBook.ts +291 -0
  82. package/src/services/EntryPoint.ts +241 -0
  83. package/src/services/Queue.ts +277 -0
  84. package/src/services/config/constants.ts +42 -2
  85. package/src/services/config/index.ts +30 -30
  86. package/src/services/config/types.ts +59 -58
  87. package/src/services/core/GlobalTypes.ts +27 -0
  88. package/src/services/core/Utils.ts +215 -1
  89. package/src/services/core/aqm-reqs.ts +0 -5
  90. package/src/services/core/constants.ts +16 -0
  91. package/src/services/core/websocket/WebSocketManager.ts +0 -4
  92. package/src/services/task/TaskManager.ts +182 -9
  93. package/src/services/task/TaskUtils.ts +113 -0
  94. package/src/services/task/constants.ts +25 -0
  95. package/src/services/task/contact.ts +80 -0
  96. package/src/services/task/index.ts +497 -71
  97. package/src/services/task/types.ts +264 -20
  98. package/src/types.ts +180 -0
  99. package/src/utils/PageCache.ts +252 -0
  100. package/test/unit/spec/cc.ts +282 -85
  101. package/test/unit/spec/metrics/MetricsManager.ts +0 -1
  102. package/test/unit/spec/metrics/behavioral-events.ts +42 -0
  103. package/test/unit/spec/services/AddressBook.ts +332 -0
  104. package/test/unit/spec/services/EntryPoint.ts +259 -0
  105. package/test/unit/spec/services/Queue.ts +323 -0
  106. package/test/unit/spec/services/config/index.ts +279 -65
  107. package/test/unit/spec/services/core/Utils.ts +282 -1
  108. package/test/unit/spec/services/core/aqm-reqs.ts +1 -3
  109. package/test/unit/spec/services/core/websocket/WebSocketManager.ts +0 -4
  110. package/test/unit/spec/services/task/TaskManager.ts +760 -2
  111. package/test/unit/spec/services/task/TaskUtils.ts +131 -0
  112. package/test/unit/spec/services/task/contact.ts +31 -1
  113. package/test/unit/spec/services/task/index.ts +873 -163
  114. package/umd/contact-center.min.js +2 -2
  115. package/umd/contact-center.min.js.map +1 -1
@@ -0,0 +1,323 @@
1
+ import Queue from '../../../../src/services/Queue';
2
+ import {HTTP_METHODS, WebexSDK, IHttpResponse} from '../../../../src/types';
3
+ import {METRIC_EVENT_NAMES} from '../../../../src/metrics/constants';
4
+ import WebexRequest from '../../../../src/services/core/WebexRequest';
5
+ import MetricsManager from '../../../../src/metrics/MetricsManager';
6
+ import LoggerProxy from '../../../../src/logger-proxy';
7
+
8
+ jest.mock('../../../../src/metrics/MetricsManager');
9
+ jest.mock('../../../../src/logger-proxy');
10
+
11
+ describe('Queue', () => {
12
+ let queueAPI: Queue;
13
+ let mockWebex: WebexSDK;
14
+ let mockMetricsManager: jest.Mocked<MetricsManager>;
15
+
16
+ beforeEach(() => {
17
+ jest.clearAllMocks();
18
+
19
+ (WebexRequest as any).instance = undefined;
20
+ mockWebex = {
21
+ credentials: {
22
+ getOrgId: jest.fn().mockReturnValue('test-org-id'),
23
+ },
24
+ request: jest.fn(),
25
+ internal: {
26
+ newMetrics: {
27
+ submitBehavioralEvent: jest.fn(),
28
+ submitOperationalEvent: jest.fn(),
29
+ submitBusinessEvent: jest.fn(),
30
+ },
31
+ },
32
+ ready: true,
33
+ once: jest.fn(),
34
+ } as unknown as WebexSDK;
35
+
36
+ mockMetricsManager = {
37
+ trackEvent: jest.fn(),
38
+ timeEvent: jest.fn(),
39
+ } as unknown as jest.Mocked<MetricsManager>;
40
+ (MetricsManager.getInstance as jest.Mock).mockReturnValue(mockMetricsManager);
41
+
42
+ queueAPI = new Queue(mockWebex);
43
+ });
44
+
45
+ describe('constructor', () => {
46
+ it('should initialize with all required dependencies', () => {
47
+ expect(WebexRequest.getInstance({webex: mockWebex})).toBeDefined();
48
+ expect(MetricsManager.getInstance).toHaveBeenCalledWith({webex: mockWebex});
49
+ });
50
+ });
51
+
52
+ describe('getQueues', () => {
53
+ const mockQueues = [
54
+ {
55
+ id: 'queue1',
56
+ name: 'Support Queue',
57
+ queueType: 'INBOUND' as const,
58
+ channelType: 'TELEPHONY' as const,
59
+ active: true,
60
+ organizationId: 'test-org-id',
61
+ checkAgentAvailability: true,
62
+ serviceLevelThreshold: 300,
63
+ maxActiveContacts: 10,
64
+ maxTimeInQueue: 3600,
65
+ defaultMusicInQueueMediaFileId: 'media123',
66
+ monitoringPermitted: true,
67
+ parkingPermitted: true,
68
+ recordingPermitted: true,
69
+ recordingAllCallsPermitted: false,
70
+ pauseRecordingPermitted: true,
71
+ controlFlowScriptUrl: 'https://example.com/script',
72
+ ivrRequeueUrl: 'https://example.com/requeue',
73
+ routingType: 'LONGEST_AVAILABLE_AGENT' as const,
74
+ queueRoutingType: 'TEAM_BASED' as const,
75
+ callDistributionGroups: [
76
+ {
77
+ agentGroups: [{teamId: 'team1'}],
78
+ order: 1,
79
+ duration: 30
80
+ }
81
+ ],
82
+ },
83
+ {
84
+ id: 'queue2',
85
+ name: 'Sales Queue',
86
+ queueType: 'INBOUND' as const,
87
+ channelType: 'CHAT' as const,
88
+ active: true,
89
+ organizationId: 'test-org-id',
90
+ checkAgentAvailability: true,
91
+ serviceLevelThreshold: 300,
92
+ maxActiveContacts: 5,
93
+ maxTimeInQueue: 1800,
94
+ defaultMusicInQueueMediaFileId: 'media456',
95
+ monitoringPermitted: true,
96
+ parkingPermitted: false,
97
+ recordingPermitted: false,
98
+ recordingAllCallsPermitted: false,
99
+ pauseRecordingPermitted: false,
100
+ controlFlowScriptUrl: 'https://example.com/script2',
101
+ ivrRequeueUrl: 'https://example.com/requeue2',
102
+ routingType: 'SKILLS_BASED' as const,
103
+ queueRoutingType: 'SKILL_BASED' as const,
104
+ callDistributionGroups: [
105
+ {
106
+ agentGroups: [{teamId: 'team2'}],
107
+ order: 1,
108
+ duration: 60
109
+ }
110
+ ],
111
+ },
112
+ ];
113
+
114
+ const mockResponse: IHttpResponse = {
115
+ statusCode: 200,
116
+ method: 'GET',
117
+ url: '/organization/test-org-id/v2/contact-service-queue',
118
+ headers: {} as any,
119
+ body: {
120
+ data: mockQueues,
121
+ meta: {
122
+ page: 0,
123
+ pageSize: 100,
124
+ totalPages: 1,
125
+ totalRecords: 2,
126
+ orgid: 'test-org-id',
127
+ },
128
+ },
129
+ };
130
+
131
+ beforeEach(() => {
132
+ jest.spyOn(Date, 'now').mockReturnValue(1000);
133
+ });
134
+
135
+ afterEach(() => {
136
+ jest.restoreAllMocks();
137
+ });
138
+
139
+ it('should fetch contact service queues successfully with default parameters', async () => {
140
+ (mockWebex.request as jest.Mock).mockResolvedValue(mockResponse);
141
+
142
+ const result = await queueAPI.getQueues();
143
+
144
+ expect(mockWebex.request).toHaveBeenCalledWith({
145
+ service: 'wcc-api-gateway',
146
+ resource: '/organization/test-org-id/v2/contact-service-queue?page=0&pageSize=100',
147
+ method: HTTP_METHODS.GET,
148
+ });
149
+
150
+ expect(result).toEqual(mockResponse.body);
151
+ expect(mockMetricsManager.timeEvent).toHaveBeenCalledWith(METRIC_EVENT_NAMES.QUEUE_FETCH_SUCCESS);
152
+ expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
153
+ METRIC_EVENT_NAMES.QUEUE_FETCH_SUCCESS,
154
+ {
155
+ orgId: 'test-org-id',
156
+ statusCode: 200,
157
+ recordCount: 2,
158
+ totalRecords: 2,
159
+ isSearchRequest: false,
160
+ isFirstPage: true,
161
+ },
162
+ ['behavioral', 'operational']
163
+ );
164
+ expect(LoggerProxy.info).toHaveBeenCalledWith('Fetching contact service queues', {
165
+ module: 'Queue',
166
+ method: 'getQueues',
167
+ data: expect.objectContaining({
168
+ orgId: 'test-org-id',
169
+ page: 0,
170
+ pageSize: 100,
171
+ isSearchRequest: false,
172
+ }),
173
+ });
174
+ expect(LoggerProxy.log).toHaveBeenCalledWith('Making API request to fetch contact service queues', {
175
+ module: 'Queue',
176
+ method: 'getQueues',
177
+ data: expect.objectContaining({
178
+ resource: '/organization/test-org-id/v2/contact-service-queue?page=0&pageSize=100',
179
+ service: 'wcc-api-gateway',
180
+ }),
181
+ });
182
+ });
183
+
184
+ it('should fetch queues with custom parameters', async () => {
185
+ (mockWebex.request as jest.Mock).mockResolvedValue(mockResponse);
186
+
187
+ const params = {
188
+ page: 1,
189
+ pageSize: 25,
190
+ search: 'support',
191
+ filter: 'queueType=="INBOUND"',
192
+ attributes: 'id,name,queueType',
193
+ sortBy: 'name',
194
+ sortOrder: 'desc' as const,
195
+ desktopProfileFilter: true,
196
+ provisioningView: false,
197
+ singleObjectResponse: true,
198
+ };
199
+
200
+ await queueAPI.getQueues(params);
201
+
202
+ expect(mockWebex.request).toHaveBeenCalledWith({
203
+ service: 'wcc-api-gateway',
204
+ resource: '/organization/test-org-id/v2/contact-service-queue?page=1&pageSize=25&filter=queueType%3D%3D%22INBOUND%22&attributes=id%2Cname%2CqueueType&search=support&sortBy=name&sortOrder=desc&desktopProfileFilter=true&provisioningView=false&singleObjectResponse=true',
205
+ method: HTTP_METHODS.GET,
206
+ });
207
+
208
+ expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
209
+ METRIC_EVENT_NAMES.QUEUE_FETCH_SUCCESS,
210
+ expect.objectContaining({
211
+ isSearchRequest: true,
212
+ isFirstPage: false,
213
+ }),
214
+ ['behavioral', 'operational']
215
+ );
216
+ });
217
+
218
+ it('should handle API errors and track metrics', async () => {
219
+ (mockWebex.request as jest.Mock).mockRejectedValue(new Error('Internal Server Error'));
220
+
221
+ await expect(queueAPI.getQueues()).rejects.toThrow('Internal Server Error');
222
+
223
+ expect(mockWebex.request).toHaveBeenCalledWith({
224
+ service: 'wcc-api-gateway',
225
+ resource: '/organization/test-org-id/v2/contact-service-queue?page=0&pageSize=100',
226
+ method: HTTP_METHODS.GET,
227
+ });
228
+
229
+ expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
230
+ METRIC_EVENT_NAMES.QUEUE_FETCH_FAILED,
231
+ {
232
+ orgId: 'test-org-id',
233
+ error: 'Internal Server Error',
234
+ isSearchRequest: false,
235
+ page: 0,
236
+ pageSize: 100,
237
+ },
238
+ ['behavioral', 'operational']
239
+ );
240
+ expect(LoggerProxy.error).toHaveBeenCalledWith('Failed to fetch contact service queues', {
241
+ module: 'Queue',
242
+ method: 'getQueues',
243
+ data: expect.objectContaining({
244
+ orgId: 'test-org-id',
245
+ error: 'Internal Server Error',
246
+ isSearchRequest: false,
247
+ page: 0,
248
+ pageSize: 100,
249
+ }),
250
+ error: expect.any(Error),
251
+ });
252
+ });
253
+
254
+
255
+
256
+ it('should not track metrics for subsequent pages in simple pagination', async () => {
257
+ (mockWebex.request as jest.Mock).mockResolvedValue(mockResponse);
258
+
259
+ const result = await queueAPI.getQueues({page: 2});
260
+ expect(result).toEqual(mockResponse.body);
261
+
262
+ expect(mockMetricsManager.trackEvent).not.toHaveBeenCalled();
263
+ });
264
+
265
+ it('should track metrics for search requests on any page', async () => {
266
+ (mockWebex.request as jest.Mock).mockResolvedValue(mockResponse);
267
+
268
+ const result2 = await queueAPI.getQueues({page: 2, search: 'test'});
269
+ expect(result2).toEqual(mockResponse.body);
270
+
271
+ expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
272
+ METRIC_EVENT_NAMES.QUEUE_FETCH_SUCCESS,
273
+ expect.objectContaining({
274
+ isSearchRequest: true,
275
+ isFirstPage: false,
276
+ }),
277
+ ['behavioral', 'operational']
278
+ );
279
+ });
280
+
281
+ it('should call API when requested page is not cached (cache miss)', async () => {
282
+ (mockWebex.request as jest.Mock).mockResolvedValueOnce(mockResponse);
283
+
284
+ await queueAPI.getQueues({page: 0});
285
+
286
+ (mockWebex.request as jest.Mock).mockResolvedValueOnce({
287
+ ...mockResponse,
288
+ body: {
289
+ data: mockQueues,
290
+ meta: {
291
+ page: 1,
292
+ pageSize: 100,
293
+ totalPages: 2,
294
+ totalRecords: 2,
295
+ orgid: 'test-org-id',
296
+ },
297
+ },
298
+ });
299
+
300
+ const callsBefore = (mockWebex.request as jest.Mock).mock.calls.length;
301
+ (LoggerProxy.log as jest.Mock).mockClear();
302
+
303
+ const result = await queueAPI.getQueues({page: 1});
304
+ const callsAfter = (mockWebex.request as jest.Mock).mock.calls.length;
305
+
306
+ expect(callsAfter).toBe(callsBefore + 1);
307
+ expect(result.meta.page).toBe(1);
308
+ expect(mockWebex.request).toHaveBeenCalledWith({
309
+ service: 'wcc-api-gateway',
310
+ resource: '/organization/test-org-id/v2/contact-service-queue?page=1&pageSize=100',
311
+ method: HTTP_METHODS.GET,
312
+ });
313
+ expect(LoggerProxy.log).toHaveBeenCalledWith('Making API request to fetch contact service queues', {
314
+ module: 'Queue',
315
+ method: 'getQueues',
316
+ data: expect.objectContaining({
317
+ resource: '/organization/test-org-id/v2/contact-service-queue?page=1&pageSize=100',
318
+ service: 'wcc-api-gateway',
319
+ }),
320
+ });
321
+ });
322
+ });
323
+ });