@webex/contact-center 3.12.0-task-refactor.8 → 3.12.0-task-refactor.10

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 (40) hide show
  1. package/dist/cc.js +3 -4
  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/metrics/constants.js +2 -0
  6. package/dist/metrics/constants.js.map +1 -1
  7. package/dist/services/ApiAiAssistant.js +74 -3
  8. package/dist/services/ApiAiAssistant.js.map +1 -1
  9. package/dist/services/config/constants.js +1 -1
  10. package/dist/services/config/constants.js.map +1 -1
  11. package/dist/services/config/types.js +9 -1
  12. package/dist/services/config/types.js.map +1 -1
  13. package/dist/services/task/TaskManager.js +7 -2
  14. package/dist/services/task/TaskManager.js.map +1 -1
  15. package/dist/types/constants.d.ts +1 -0
  16. package/dist/types/metrics/constants.d.ts +2 -0
  17. package/dist/types/services/ApiAiAssistant.d.ts +10 -2
  18. package/dist/types/services/config/types.d.ts +16 -0
  19. package/dist/types/types.d.ts +24 -0
  20. package/dist/types.js +15 -0
  21. package/dist/types.js.map +1 -1
  22. package/dist/webex.js +1 -1
  23. package/package.json +1 -1
  24. package/src/cc.ts +6 -4
  25. package/src/constants.ts +1 -0
  26. package/src/metrics/constants.ts +2 -0
  27. package/src/services/ApiAiAssistant.ts +102 -2
  28. package/src/services/config/constants.ts +1 -1
  29. package/src/services/config/types.ts +8 -0
  30. package/src/services/task/TaskManager.ts +7 -2
  31. package/src/services/task/ai-docs/AGENTS.md +7 -0
  32. package/src/services/task/ai-docs/ARCHITECTURE.md +12 -0
  33. package/src/types.ts +25 -0
  34. package/test/unit/spec/cc.ts +2 -0
  35. package/test/unit/spec/services/ApiAiAssistant.ts +105 -17
  36. package/test/unit/spec/services/config/index.ts +1 -1
  37. package/test/unit/spec/services/task/TaskManager.ts +42 -0
  38. package/test/unit/spec/services/task/voice/WebRTC.ts +99 -106
  39. package/umd/contact-center.min.js +2 -2
  40. package/umd/contact-center.min.js.map +1 -1
package/src/cc.ts CHANGED
@@ -736,11 +736,13 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
736
736
  this.taskManager.setWebRtcEnabled(this.agentConfig.webRtcEnabled);
737
737
  this.apiAIAssistant.setAIFeatureFlags(this.agentConfig.aiFeature);
738
738
  /**
739
- * TODO: We need to re-check this condition if this websocket is only for realtime transcripts
740
- * or other AI Assistant features will also use the same.
741
- * If the latter is true, we need to update this condition.
739
+ * RTD websocket currently supports realtime transcripts and suggested responses.
740
+ * Extend this condition when additional AI RTD features are introduced.
742
741
  */
743
- if (this.agentConfig.aiFeature?.realtimeTranscripts?.enable) {
742
+ if (
743
+ this.agentConfig.aiFeature?.realtimeTranscripts?.enable ||
744
+ this.agentConfig.aiFeature?.suggestedResponses?.enable
745
+ ) {
744
746
  LoggerProxy.info('Connecting to RTD websocket', {
745
747
  module: CC_FILE,
746
748
  method: METHODS.CONNECT_WEBSOCKET,
package/src/constants.ts CHANGED
@@ -63,5 +63,6 @@ export const METHODS = {
63
63
  GET_OUTDIAL_ANI_ENTRIES: 'getOutdialAniEntries',
64
64
  GET_BASE_URL: 'getBaseUrl',
65
65
  SEND_EVENT: 'sendEvent',
66
+ GET_SUGGESTED_RESPONSE: 'getSuggestedResponse',
66
67
  FETCH_HISTORIC_TRANSCRIPTS: 'fetchHistoricTranscripts',
67
68
  };
@@ -166,6 +166,8 @@ export const METRIC_EVENT_NAMES = {
166
166
  // AI Assistant events
167
167
  AI_ASSISTANT_SEND_EVENT_SUCCESS: 'AI Assistant Send Event Success',
168
168
  AI_ASSISTANT_SEND_EVENT_FAILED: 'AI Assistant Send Event Failed',
169
+ AI_ASSISTANT_GET_SUGGESTED_RESPONSE_SUCCESS: 'AI Assistant Get Suggested Response Success',
170
+ AI_ASSISTANT_GET_SUGGESTED_RESPONSE_FAILED: 'AI Assistant Get Suggested Response Failed',
169
171
  AI_ASSISTANT_FETCH_HISTORIC_TRANSCRIPTS_SUCCESS:
170
172
  'AI Assistant Fetch Historic Transcripts Success',
171
173
  AI_ASSISTANT_FETCH_HISTORIC_TRANSCRIPTS_FAILED: 'AI Assistant Fetch Historic Transcripts Failed',
@@ -1,3 +1,4 @@
1
+ import {v4 as uuidv4} from 'uuid';
1
2
  import LoggerProxy from '../logger-proxy';
2
3
  import MetricsManager from '../metrics/MetricsManager';
3
4
  import {METRIC_EVENT_NAMES} from '../metrics/constants';
@@ -10,6 +11,7 @@ import {
10
11
  AIAssistantEventType,
11
12
  AIAssistantEventName,
12
13
  HistoricTranscriptsResponse,
14
+ SuggestedResponseParams,
13
15
  } from '../types';
14
16
  import {getErrorDetails} from './core/Utils';
15
17
  import {
@@ -83,13 +85,16 @@ export class ApiAIAssistant {
83
85
  interactionId: string,
84
86
  eventType: AIAssistantEventType,
85
87
  eventName: AIAssistantEventName,
86
- action: TranscriptAction
88
+ action?: TranscriptAction,
89
+ context?: string,
90
+ languageCode?: string,
91
+ trackingId?: string
87
92
  ): Promise<Record<string, unknown>> {
88
93
  LoggerProxy.info('Sending event', {
89
94
  module: CC_FILE,
90
95
  method: METHODS.SEND_EVENT,
91
96
  interactionId,
92
- data: {eventType, eventName, action},
97
+ data: {eventType, eventName, action, context},
93
98
  });
94
99
  this.metricsManager.timeEvent([
95
100
  METRIC_EVENT_NAMES.AI_ASSISTANT_SEND_EVENT_SUCCESS,
@@ -112,7 +117,10 @@ export class ApiAIAssistant {
112
117
  data: {
113
118
  interactionId,
114
119
  action,
120
+ context,
115
121
  actionTimeStamp: String(Date.now()),
122
+ languageCode,
123
+ trackingId,
116
124
  },
117
125
  },
118
126
  },
@@ -143,6 +151,98 @@ export class ApiAIAssistant {
143
151
  }
144
152
  }
145
153
 
154
+ /**
155
+ * Requests a suggested response for an interaction.
156
+ *
157
+ * @param params - Suggestion request parameters
158
+ * @returns HTTP response body from the AI Assistant event API
159
+ * @public
160
+ */
161
+ public async getSuggestedResponse(params: SuggestedResponseParams): Promise<any> {
162
+ const {agentId, interactionId, context} = params;
163
+ const trimmedContext = context?.trim();
164
+ const languageCode = params.languageCode ?? 'en';
165
+ const trackingId = `WX_CC_SDK_${uuidv4()}`;
166
+ const eventName = trimmedContext
167
+ ? AIAssistantEventName.ADD_SUGGESTIONS_EXTRA_CONTEXT
168
+ : AIAssistantEventName.GET_SUGGESTIONS;
169
+
170
+ const loggerContext = {
171
+ module: CC_FILE,
172
+ method: METHODS.GET_SUGGESTED_RESPONSE,
173
+ interactionId,
174
+ trackingId,
175
+ data: {eventName},
176
+ };
177
+
178
+ LoggerProxy.info('Requesting suggested response', loggerContext);
179
+
180
+ this.metricsManager.timeEvent([
181
+ METRIC_EVENT_NAMES.AI_ASSISTANT_GET_SUGGESTED_RESPONSE_SUCCESS,
182
+ METRIC_EVENT_NAMES.AI_ASSISTANT_GET_SUGGESTED_RESPONSE_FAILED,
183
+ ]);
184
+
185
+ try {
186
+ if (!this.aiFeature?.suggestedResponses?.enable) {
187
+ const {error: detailedError} = getErrorDetails(
188
+ new Error('SUGGESTED_RESPONSES_NOT_ENABLED'),
189
+ METHODS.GET_SUGGESTED_RESPONSE,
190
+ CC_FILE
191
+ );
192
+ throw detailedError;
193
+ }
194
+
195
+ const orgId = this.webex.credentials.getOrgId();
196
+
197
+ const response = await this.sendEvent(
198
+ agentId,
199
+ interactionId,
200
+ AIAssistantEventType.CUSTOM_EVENT,
201
+ eventName,
202
+ undefined,
203
+ trimmedContext,
204
+ languageCode,
205
+ trackingId
206
+ );
207
+
208
+ this.metricsManager.trackEvent(
209
+ METRIC_EVENT_NAMES.AI_ASSISTANT_GET_SUGGESTED_RESPONSE_SUCCESS,
210
+ {
211
+ agentId,
212
+ orgId,
213
+ interactionId,
214
+ eventName,
215
+ trackingId,
216
+ context,
217
+ },
218
+ ['operational']
219
+ );
220
+ LoggerProxy.log('Suggested response request succeeded', loggerContext);
221
+
222
+ return response;
223
+ } catch (error) {
224
+ LoggerProxy.error('Suggested response request failed', {...loggerContext, error});
225
+ this.metricsManager.trackEvent(
226
+ METRIC_EVENT_NAMES.AI_ASSISTANT_GET_SUGGESTED_RESPONSE_FAILED,
227
+ {
228
+ agentId,
229
+ interactionId,
230
+ trackingId,
231
+ eventName,
232
+ error: error instanceof Error ? error.message : String(error),
233
+ },
234
+ ['operational']
235
+ );
236
+
237
+ const {error: detailedError} = getErrorDetails(
238
+ error,
239
+ METHODS.GET_SUGGESTED_RESPONSE,
240
+ CC_FILE
241
+ );
242
+ throw detailedError;
243
+ }
244
+ }
245
+
146
246
  /**
147
247
  * Fetches historic transcripts for an interaction.
148
248
  * This API is allowed only when real-time transcription feature is enabled.
@@ -166,7 +166,7 @@ export const endPointMap = {
166
166
  ) =>
167
167
  `organization/${orgId}/v2/auxiliary-code?page=${page}&pageSize=${pageSize}${
168
168
  filter && filter.length > 0 ? `&filter=id=in=(${filter})` : ''
169
- }&attributes=${attributes}`,
169
+ }&attributes=${attributes}&desktopProfileFilter=true`,
170
170
 
171
171
  /**
172
172
  * Gets the endpoint for organization info.
@@ -121,6 +121,14 @@ export const CC_TASK_EVENTS = {
121
121
  AGENT_INVITE_FAILED: 'AgentInviteFailed',
122
122
  /** Event emitted when a real-time transcript chunk is received */
123
123
  REAL_TIME_TRANSCRIPTION: 'REAL_TIME_TRANSCRIPTION',
124
+ /** Event emitted when an AI assistant suggested response is available */
125
+ SUGGESTED_RESPONSE: 'SUGGESTED_RESPONSE',
126
+ /** Event emitted when backend acknowledges it is listening for more context */
127
+ SUGGESTED_RESPONSE_ACKNOWLEDGE: 'SUGGESTED_RESPONSE_ACKNOWLEDGE',
128
+ /** Event emitted when a mid-call summary is available */
129
+ MID_CALL_SUMMARY: 'MID_CALL_SUMMARY',
130
+ /** Event emitted when a post-call summary is available */
131
+ POST_CALL_SUMMARY: 'POST_CALL_SUMMARY',
124
132
  } as const;
125
133
 
126
134
  /**
@@ -93,7 +93,12 @@ export default class TaskManager extends EventEmitter {
93
93
  return;
94
94
  }
95
95
 
96
- task.emit(payload.type, payload.data);
96
+ switch (payload.type) {
97
+ case CC_EVENTS.REAL_TIME_TRANSCRIPTION:
98
+ case CC_EVENTS.SUGGESTED_RESPONSE:
99
+ task.emit(payload.type, payload.data);
100
+ break;
101
+ }
97
102
  } catch (error) {
98
103
  LoggerProxy.error('Failed to parse RTD WebSocket message', {
99
104
  module: TASK_MANAGER_FILE,
@@ -755,7 +760,7 @@ export default class TaskManager extends EventEmitter {
755
760
  private requestRealTimeTranscripts(eventType: string, interactionId: string): void {
756
761
  const action = TRANSCRIPT_EVENT_MAP[eventType];
757
762
  if (!action || !this.apiAIAssistant) return;
758
- if (this.configFlags?.aiFeature?.realtimeTranscripts?.enable === false) return;
763
+ if (this.configFlags?.aiFeature?.realtimeTranscripts?.enable !== true) return;
759
764
 
760
765
  this.apiAIAssistant
761
766
  .sendEvent(
@@ -217,6 +217,13 @@ cc.on('task:incoming', async (task) => {
217
217
 
218
218
  > Full list is defined in `TASK_EVENTS` (`types.ts`).
219
219
 
220
+ ### AI Assistant events on `task`
221
+
222
+ | Event | When Emitted |
223
+ | --- | --- |
224
+ | `REAL_TIME_TRANSCRIPTION` | A realtime transcript payload is received for the task interaction |
225
+ | `SUGGESTED_RESPONSE` | A final AI Assistant suggestion payload is received for the task interaction |
226
+
220
227
  ---
221
228
 
222
229
  ## API Reference
@@ -400,6 +400,18 @@ this.webSocketManager.on('message', (event) => {
400
400
  });
401
401
  ```
402
402
 
403
+ ### RTD / AI Assistant event routing
404
+
405
+ `TaskManager.handleRealtimeWebsocketEvent()` handles payloads arriving on the realtime subscription socket used for AI features. It:
406
+
407
+ 1. Normalizes the websocket envelope (`payload.data` vs direct payload form)
408
+ 2. Resolves the owning task via `conversationId`
409
+ 3. Emits `REAL_TIME_TRANSCRIPTION` on the task for transcript payloads
410
+ 4. Emits `SUGGESTED_RESPONSE` on the task only when the backend payload is a final suggestion (`data.type === 'SUGGESTION'`)
411
+ 5. Ignores `SUGGESTED_RESPONSE_ACKNOWLEDGE` for public SDK emission
412
+
413
+ This keeps transcript and suggestion delivery aligned on the same per-task event surface.
414
+
403
415
  ---
404
416
 
405
417
  ## WebRTC Integration
package/src/types.ts CHANGED
@@ -846,6 +846,27 @@ export type UpdateDeviceTypeResponse = Agent.DeviceTypeUpdateSuccess | Error;
846
846
  */
847
847
  export type TranscriptAction = 'START' | 'STOP';
848
848
 
849
+ /**
850
+ * Parameters used to request an AI Assistant suggested response.
851
+ * @public
852
+ * @example
853
+ * const params: SuggestedResponseParams = {
854
+ * interactionId: 'interaction-123',
855
+ * actionTimeStamp: Date.now(),
856
+ * context: 'Need help with credit card payment due date',
857
+ * };
858
+ */
859
+ export type SuggestedResponseParams = {
860
+ /** Agent identifier */
861
+ agentId: string;
862
+ /** Interaction identifier for which suggestion should be generated */
863
+ interactionId: string;
864
+ /** Optional additional context that should refine the suggestion */
865
+ context?: string;
866
+ /** Optional language code for suggestions (for example, 'en'). Defaults to 'en'. */
867
+ languageCode?: string;
868
+ };
869
+
849
870
  /**
850
871
  * Supported AI Assistant event categories.
851
872
  * @public
@@ -879,6 +900,10 @@ export type AIAssistantEventType = Enum<typeof AIAssistantEventType>;
879
900
  export const AIAssistantEventName = {
880
901
  /** Request transcript streaming for an interaction */
881
902
  GET_TRANSCRIPTS: 'GET_TRANSCRIPTS',
903
+ /** Request a suggested response for an interaction */
904
+ GET_SUGGESTIONS: 'GET_SUGGESTIONS',
905
+ /** Add extra context to refine a suggested response */
906
+ ADD_SUGGESTIONS_EXTRA_CONTEXT: 'ADD_SUGGESTIONS_EXTRA_CONTEXT',
882
907
  /** Request mid-call summary generation */
883
908
  GET_MID_CALL_SUMMARY: 'GET_MID_CALL_SUMMARY',
884
909
  /** Request post-call summary generation */
@@ -110,8 +110,10 @@ describe('webex.cc', () => {
110
110
 
111
111
  mockApiAIAssistant = {
112
112
  sendEvent: jest.fn(),
113
+ getSuggestedResponse: jest.fn(),
113
114
  fetchHistoricTranscripts: jest.fn(),
114
115
  setAIFeatureFlags: jest.fn(),
116
+ setAgentId: jest.fn(),
115
117
  };
116
118
 
117
119
  // Mock Services instance
@@ -57,23 +57,18 @@ describe('ApiAIAssistant', () => {
57
57
  'START'
58
58
  );
59
59
 
60
- expect(mockWebex.request).toHaveBeenCalledWith({
61
- uri: 'https://api-ai-assistant.produs1.ciscoccservice.com/event',
62
- method: HTTP_METHODS.POST,
63
- addAuthHeader: true,
64
- body: {
65
- agentId: 'test-agent-id',
66
- orgId: 'test-org-id',
67
- eventType: 'CUSTOM_EVENT',
68
- eventName: 'GET_TRANSCRIPTS',
69
- eventDetails: {
70
- data: expect.objectContaining({
71
- interactionId: 'interaction-1',
72
- action: 'START',
73
- }),
74
- },
75
- },
76
- });
60
+ expect(mockWebex.request).toHaveBeenCalledTimes(1);
61
+ const requestArgs = (mockWebex.request as jest.Mock).mock.calls[0][0];
62
+
63
+ expect(requestArgs.uri).toBe('https://api-ai-assistant.produs1.ciscoccservice.com/event');
64
+ expect(requestArgs.method).toBe(HTTP_METHODS.POST);
65
+ expect(requestArgs.addAuthHeader).toBe(true);
66
+ expect(requestArgs.body.agentId).toBe('test-agent-id');
67
+ expect(requestArgs.body.orgId).toBe('test-org-id');
68
+ expect(requestArgs.body.eventType).toBe('CUSTOM_EVENT');
69
+ expect(requestArgs.body.eventName).toBe('GET_TRANSCRIPTS');
70
+ expect(requestArgs.body.eventDetails.data.interactionId).toBe('interaction-1');
71
+ expect(requestArgs.body.eventDetails.data.action).toBe('START');
77
72
  expect(result).toEqual({ok: true});
78
73
  });
79
74
 
@@ -97,6 +92,83 @@ describe('ApiAIAssistant', () => {
97
92
  expect(result).toEqual(responseBody as any);
98
93
  });
99
94
 
95
+ it('should request suggested response without extra context using sendEvent', async () => {
96
+ const sendEventSpy = jest.spyOn(apiAIAssistant, 'sendEvent').mockResolvedValue({ok: true});
97
+ apiAIAssistant.setAIFeatureFlags({suggestedResponses: {enable: true}} as any);
98
+
99
+ const result = await apiAIAssistant.getSuggestedResponse({
100
+ agentId: 'test-agent-id',
101
+ interactionId: 'interaction-1',
102
+ });
103
+
104
+ expect(sendEventSpy).toHaveBeenCalledTimes(1);
105
+ const [agentId, interactionId, eventType, eventName, action, context, languageCode, trackingId] =
106
+ sendEventSpy.mock.calls[0];
107
+
108
+ expect(agentId).toBe('test-agent-id');
109
+ expect(interactionId).toBe('interaction-1');
110
+ expect(eventType).toBe('CUSTOM_EVENT');
111
+ expect(eventName).toBe('GET_SUGGESTIONS');
112
+ expect(action).toBeUndefined();
113
+ expect(context).toBeUndefined();
114
+ expect(languageCode).toBe('en');
115
+ expect(typeof trackingId).toBe('string');
116
+ expect(trackingId.startsWith('WX_CC_SDK_')).toBe(true);
117
+ expect(result).toEqual({ok: true});
118
+ });
119
+
120
+ it('should request suggested response with extra context using sendEvent', async () => {
121
+ const sendEventSpy = jest.spyOn(apiAIAssistant, 'sendEvent').mockResolvedValue({ok: true});
122
+ apiAIAssistant.setAIFeatureFlags({suggestedResponses: {enable: true}} as any);
123
+
124
+ const result = await apiAIAssistant.getSuggestedResponse({
125
+ agentId: 'test-agent-id',
126
+ interactionId: 'interaction-1',
127
+ context: 'Need assistance with credit card payment due date',
128
+ });
129
+
130
+ expect(sendEventSpy).toHaveBeenCalledTimes(1);
131
+ const [agentId, interactionId, eventType, eventName, action, context, languageCode, trackingId] =
132
+ sendEventSpy.mock.calls[0];
133
+
134
+ expect(agentId).toBe('test-agent-id');
135
+ expect(interactionId).toBe('interaction-1');
136
+ expect(eventType).toBe('CUSTOM_EVENT');
137
+ expect(eventName).toBe('ADD_SUGGESTIONS_EXTRA_CONTEXT');
138
+ expect(action).toBeUndefined();
139
+ expect(context).toBe('Need assistance with credit card payment due date');
140
+ expect(languageCode).toBe('en');
141
+ expect(typeof trackingId).toBe('string');
142
+ expect(trackingId.startsWith('WX_CC_SDK_')).toBe(true);
143
+ expect(result).toEqual({ok: true});
144
+ });
145
+
146
+ it('should treat whitespace-only context as GET_SUGGESTIONS', async () => {
147
+ const sendEventSpy = jest.spyOn(apiAIAssistant, 'sendEvent').mockResolvedValue({ok: true});
148
+ apiAIAssistant.setAIFeatureFlags({suggestedResponses: {enable: true}} as any);
149
+
150
+ const result = await apiAIAssistant.getSuggestedResponse({
151
+ agentId: 'test-agent-id',
152
+ interactionId: 'interaction-1',
153
+ context: ' ',
154
+ });
155
+
156
+ expect(sendEventSpy).toHaveBeenCalledTimes(1);
157
+ const [agentId, interactionId, eventType, eventName, action, context, languageCode, trackingId] =
158
+ sendEventSpy.mock.calls[0];
159
+
160
+ expect(agentId).toBe('test-agent-id');
161
+ expect(interactionId).toBe('interaction-1');
162
+ expect(eventType).toBe('CUSTOM_EVENT');
163
+ expect(eventName).toBe('GET_SUGGESTIONS');
164
+ expect(action).toBeUndefined();
165
+ expect(context).toBe('');
166
+ expect(languageCode).toBe('en');
167
+ expect(typeof trackingId).toBe('string');
168
+ expect(trackingId.startsWith('WX_CC_SDK_')).toBe(true);
169
+ expect(result).toEqual({ok: true});
170
+ });
171
+
100
172
  it('should fail when base URL mapping is not available', async () => {
101
173
  (mockWebex.internal.services.get as jest.Mock).mockReturnValue('https://unknown-host.invalid');
102
174
 
@@ -129,4 +201,20 @@ describe('ApiAIAssistant', () => {
129
201
 
130
202
  expect(errorMessage).toBe('Error while performing fetchHistoricTranscripts');
131
203
  });
204
+
205
+ it('should fail when suggested responses feature is disabled', async () => {
206
+ apiAIAssistant.setAIFeatureFlags({suggestedResponses: {enable: false}} as any);
207
+ let errorMessage = '';
208
+
209
+ try {
210
+ await apiAIAssistant.getSuggestedResponse({
211
+ agentId: 'test-agent-id',
212
+ interactionId: 'interaction-1',
213
+ });
214
+ } catch (error) {
215
+ errorMessage = (error as Error)?.message || '';
216
+ }
217
+
218
+ expect(errorMessage).toBe('Error while performing getSuggestedResponse');
219
+ });
132
220
  });
@@ -260,7 +260,7 @@ describe('AgentConfigService', () => {
260
260
 
261
261
  expect(mockWebexRequest.request).toHaveBeenCalledWith({
262
262
  service: mockWccAPIURL,
263
- resource: `organization/${mockOrgId}/v2/auxiliary-code?page=${page}&pageSize=${pageSize}&filter=id=in=(${filter})&attributes=${attributes}`,
263
+ resource: `organization/${mockOrgId}/v2/auxiliary-code?page=${page}&pageSize=${pageSize}&filter=id=in=(${filter})&attributes=${attributes}&desktopProfileFilter=true`,
264
264
  method: 'GET',
265
265
  });
266
266
  expect(result).toEqual(mockResponse.body);
@@ -253,6 +253,19 @@ describe('TaskManager', () => {
253
253
  });
254
254
 
255
255
  it('should invoke sendEvent for configured start/stop backend events', () => {
256
+ taskManager.setConfigFlags({
257
+ isEndTaskEnabled: true,
258
+ isEndConsultEnabled: true,
259
+ webRtcEnabled: true,
260
+ autoWrapup: false,
261
+ aiFeature: {
262
+ id: 'ai-feature-1',
263
+ realtimeTranscripts: {
264
+ enable: true,
265
+ },
266
+ },
267
+ });
268
+
256
269
  const interactionId = taskId;
257
270
  const message = (type: CC_EVENTS) =>
258
271
  JSON.stringify({
@@ -316,6 +329,35 @@ describe('TaskManager', () => {
316
329
  expect(mockApiAIAssistant.sendEvent).not.toHaveBeenCalled();
317
330
  });
318
331
 
332
+ it('should not invoke sendEvent when realtime transcripts config is missing', () => {
333
+ taskManager.setConfigFlags({
334
+ isEndTaskEnabled: true,
335
+ isEndConsultEnabled: true,
336
+ webRtcEnabled: true,
337
+ autoWrapup: false,
338
+ aiFeature: {
339
+ id: 'ai-feature-1',
340
+ suggestedResponses: {
341
+ enable: true,
342
+ },
343
+ },
344
+ });
345
+
346
+ const message = (type: CC_EVENTS) =>
347
+ JSON.stringify({
348
+ data: {
349
+ ...taskDataMock,
350
+ interactionId: taskId,
351
+ type,
352
+ },
353
+ });
354
+
355
+ webSocketManagerMock.emit('message', message(CC_EVENTS.AGENT_CONTACT_ASSIGNED));
356
+ webSocketManagerMock.emit('message', message(CC_EVENTS.AGENT_CONSULTING));
357
+
358
+ expect(mockApiAIAssistant.sendEvent).not.toHaveBeenCalled();
359
+ });
360
+
319
361
  it('should emit REAL_TIME_TRANSCRIPTION from RTD websocket payload', () => {
320
362
  const task = taskManager.getTask(taskId);
321
363
  const taskEmitSpy = jest.spyOn(task, 'emit');