@webex/internal-plugin-ai-assistant 3.11.0 → 3.12.0
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/dist/ai-assistant.js +90 -57
- package/dist/ai-assistant.js.map +1 -1
- package/dist/constants.js +3 -1
- package/dist/constants.js.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils.js +28 -2
- package/dist/utils.js.map +1 -1
- package/package.json +8 -8
- package/src/ai-assistant.ts +33 -5
- package/src/constants.ts +2 -0
- package/src/types.ts +2 -0
- package/src/utils.ts +12 -0
- package/test/unit/data/messages.ts +122 -21
- package/test/unit/spec/ai-assistant.ts +232 -43
|
@@ -16,7 +16,14 @@ import {
|
|
|
16
16
|
AI_ASSISTANT_ERROR_CODES,
|
|
17
17
|
AI_ASSISTANT_ERRORS,
|
|
18
18
|
} from '@webex/internal-plugin-ai-assistant/src/constants';
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
jsonResponse,
|
|
21
|
+
messageResponse,
|
|
22
|
+
workspaceResponse,
|
|
23
|
+
scheduleMeetingResponse,
|
|
24
|
+
assistantActivity,
|
|
25
|
+
citedAnswerWithSourcesResponse,
|
|
26
|
+
} from '../data/messages';
|
|
20
27
|
|
|
21
28
|
const waitForAsync = () =>
|
|
22
29
|
new Promise<void>((resolve) =>
|
|
@@ -78,12 +85,15 @@ describe('plugin-ai-assistant', () => {
|
|
|
78
85
|
it('registers correctly', async () => {
|
|
79
86
|
await webex.internal.aiAssistant.register();
|
|
80
87
|
|
|
81
|
-
assert.callCount(webex.internal.mercury.on,
|
|
88
|
+
assert.callCount(webex.internal.mercury.on, 2);
|
|
82
89
|
|
|
83
|
-
const
|
|
90
|
+
const firstCallArgs = webex.internal.mercury.on.getCall(0).args;
|
|
91
|
+
expect(firstCallArgs[0]).to.equal('event:assistant-api.response');
|
|
92
|
+
expect(firstCallArgs[1]).to.be.a('function');
|
|
84
93
|
|
|
85
|
-
|
|
86
|
-
expect(
|
|
94
|
+
const secondCallArgs = webex.internal.mercury.on.getCall(1).args;
|
|
95
|
+
expect(secondCallArgs[0]).to.equal('assistant-api.activity');
|
|
96
|
+
expect(secondCallArgs[1]).to.be.a('function');
|
|
87
97
|
|
|
88
98
|
assert.equal(webex.internal.aiAssistant.registered, true);
|
|
89
99
|
});
|
|
@@ -115,11 +125,13 @@ describe('plugin-ai-assistant', () => {
|
|
|
115
125
|
|
|
116
126
|
await webex.internal.aiAssistant.unregister();
|
|
117
127
|
|
|
118
|
-
assert.callCount(webex.internal.mercury.off,
|
|
128
|
+
assert.callCount(webex.internal.mercury.off, 2);
|
|
119
129
|
|
|
120
|
-
const
|
|
130
|
+
const firstCallOrg = webex.internal.mercury.off.getCall(0).args;
|
|
131
|
+
expect(firstCallOrg[0]).to.equal('event:assistant-api.response');
|
|
121
132
|
|
|
122
|
-
|
|
133
|
+
const secondCallOrg = webex.internal.mercury.off.getCall(1).args;
|
|
134
|
+
expect(secondCallOrg[0]).to.equal('assistant-api.activity');
|
|
123
135
|
|
|
124
136
|
assert.equal(webex.internal.aiAssistant.registered, false);
|
|
125
137
|
});
|
|
@@ -130,7 +142,6 @@ describe('plugin-ai-assistant', () => {
|
|
|
130
142
|
const result = await webex.internal.aiAssistant.unregister();
|
|
131
143
|
|
|
132
144
|
expect(result).to.be.undefined;
|
|
133
|
-
assert.callCount(webex.internal.mercury.disconnect, 0);
|
|
134
145
|
assert.equal(webex.internal.aiAssistant.registered, false);
|
|
135
146
|
});
|
|
136
147
|
});
|
|
@@ -225,6 +236,47 @@ describe('plugin-ai-assistant', () => {
|
|
|
225
236
|
clientRequestId: 'test-request-id',
|
|
226
237
|
param1: 'value1',
|
|
227
238
|
},
|
|
239
|
+
headers: undefined,
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
const result = await requestPromise;
|
|
243
|
+
|
|
244
|
+
expect(result).to.deep.equal({
|
|
245
|
+
id: 'test-message-id',
|
|
246
|
+
url: 'https://assistant-api-a.wbx2.com:443/assistant-api/api/v1/sessions/test-session-id/messages/test-message-id',
|
|
247
|
+
sessionId: 'test-session-id',
|
|
248
|
+
sessionUrl:
|
|
249
|
+
'https://assistant-api-a.wbx2.com:443/assistant-api/api/v1/sessions/test-session-id',
|
|
250
|
+
creatorId: 'test-creator-id',
|
|
251
|
+
createdAt: '2025-08-05T02:11:12.361Z',
|
|
252
|
+
requestId: 'test-request-id',
|
|
253
|
+
streamEventName: 'aiassistant:stream:test-request-id',
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it('makes a request with additional headers', async () => {
|
|
258
|
+
const requestPromise = webex.internal.aiAssistant._request({
|
|
259
|
+
resource: 'test-resource',
|
|
260
|
+
params: {param1: 'value1'},
|
|
261
|
+
headers: {
|
|
262
|
+
'X-Custom-Header': 'foo',
|
|
263
|
+
'X-Another-Header': 'bar',
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
expect(webex.request.getCall(0).args[0]).to.deep.equal({
|
|
268
|
+
service: 'assistant-api',
|
|
269
|
+
resource: 'test-resource',
|
|
270
|
+
method: 'POST',
|
|
271
|
+
contentType: 'application/json',
|
|
272
|
+
body: {
|
|
273
|
+
clientRequestId: 'test-request-id',
|
|
274
|
+
param1: 'value1',
|
|
275
|
+
},
|
|
276
|
+
headers: {
|
|
277
|
+
'X-Custom-Header': 'foo',
|
|
278
|
+
'X-Another-Header': 'bar',
|
|
279
|
+
},
|
|
228
280
|
});
|
|
229
281
|
|
|
230
282
|
const result = await requestPromise;
|
|
@@ -282,6 +334,28 @@ describe('plugin-ai-assistant', () => {
|
|
|
282
334
|
expect(triggerSpy.getCall(2).args[1]).to.deep.equal(expectedResult);
|
|
283
335
|
});
|
|
284
336
|
|
|
337
|
+
it('handles an activity', async () => {
|
|
338
|
+
const triggerSpy = sinon.spy(webex.internal.aiAssistant, 'trigger');
|
|
339
|
+
|
|
340
|
+
webex.internal.encryption.decryptText.callsFake(async (keyUrl, value) => {
|
|
341
|
+
return `decrypted-with-${keyUrl}-${value}`;
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
// assume assistant event is received
|
|
345
|
+
await webex.internal.aiAssistant._handleAssistantActivity(cloneDeep(assistantActivity[0]));
|
|
346
|
+
|
|
347
|
+
await waitForAsync();
|
|
348
|
+
|
|
349
|
+
let expectedResult = set(
|
|
350
|
+
cloneDeep(assistantActivity[0]),
|
|
351
|
+
'activity.content.value.message',
|
|
352
|
+
'decrypted-with-kms://kms-cisco.wbx2.com/keys/9b838423-f31b-49d5-a7c7-182572340a37-message_encrypted_value_for_activity'
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
expect(triggerSpy.getCall(0).args[0]).to.deep.equal('aiassistant:activityReceived');
|
|
356
|
+
expect(triggerSpy.getCall(0).args[1]).to.deep.equal(expectedResult);
|
|
357
|
+
});
|
|
358
|
+
|
|
285
359
|
it('decrypts a chunked json response', async () => {
|
|
286
360
|
const triggerSpy = sinon.spy(webex.internal.aiAssistant, 'trigger');
|
|
287
361
|
webex.internal.encryption.decryptText.callsFake(async (keyUrl, value) => {
|
|
@@ -332,9 +406,7 @@ describe('plugin-ai-assistant', () => {
|
|
|
332
406
|
responseType: 'thought',
|
|
333
407
|
};
|
|
334
408
|
expect(triggerSpy.getCall(1).args[0]).to.deep.equal('aiassistant:stream:test-request-id');
|
|
335
|
-
expect(triggerSpy.getCall(1).args[1]).to.deep.equal(
|
|
336
|
-
expectedResult
|
|
337
|
-
);
|
|
409
|
+
expect(triggerSpy.getCall(1).args[1]).to.deep.equal(expectedResult);
|
|
338
410
|
|
|
339
411
|
triggerSpy.resetHistory();
|
|
340
412
|
|
|
@@ -443,7 +515,8 @@ describe('plugin-ai-assistant', () => {
|
|
|
443
515
|
type: 'json',
|
|
444
516
|
encryptionKeyUrl: 'kms://kms-us.wbx2.com/keys/9565506d-78b1-4742-b0fd-63719748282e',
|
|
445
517
|
value: {
|
|
446
|
-
value:
|
|
518
|
+
value:
|
|
519
|
+
'decrypted-with-kms://kms-us.wbx2.com/keys/9565506d-78b1-4742-b0fd-63719748282e-json_3_encrypted_value',
|
|
447
520
|
type: 'markdown',
|
|
448
521
|
},
|
|
449
522
|
},
|
|
@@ -574,12 +647,10 @@ describe('plugin-ai-assistant', () => {
|
|
|
574
647
|
// Update the clientRequestId to match the test setup
|
|
575
648
|
const firstEvent = cloneDeep(workspaceResponse[0]);
|
|
576
649
|
firstEvent.clientRequestId = 'test-request-id';
|
|
577
|
-
|
|
650
|
+
|
|
578
651
|
await webex.internal.aiAssistant._handleEvent(firstEvent);
|
|
579
652
|
|
|
580
|
-
expect(triggerSpy.getCall(0).args[0]).to.equal(
|
|
581
|
-
`aiassistant:result:test-request-id`
|
|
582
|
-
);
|
|
653
|
+
expect(triggerSpy.getCall(0).args[0]).to.equal(`aiassistant:result:test-request-id`);
|
|
583
654
|
|
|
584
655
|
await waitForAsync();
|
|
585
656
|
|
|
@@ -594,7 +665,7 @@ describe('plugin-ai-assistant', () => {
|
|
|
594
665
|
// second event is another workspace chunk with an encrypted value
|
|
595
666
|
const secondEvent = cloneDeep(workspaceResponse[1]);
|
|
596
667
|
secondEvent.clientRequestId = 'test-request-id';
|
|
597
|
-
|
|
668
|
+
|
|
598
669
|
await webex.internal.aiAssistant._handleEvent(secondEvent);
|
|
599
670
|
|
|
600
671
|
expectedResult = set(
|
|
@@ -604,7 +675,7 @@ describe('plugin-ai-assistant', () => {
|
|
|
604
675
|
);
|
|
605
676
|
|
|
606
677
|
expect(triggerSpy.getCall(2).args[1]).to.deep.equal(expectedResult);
|
|
607
|
-
});
|
|
678
|
+
});
|
|
608
679
|
|
|
609
680
|
it('handles a schedule meeting response', async () => {
|
|
610
681
|
const triggerSpy = sinon.spy(webex.internal.aiAssistant, 'trigger');
|
|
@@ -620,35 +691,130 @@ describe('plugin-ai-assistant', () => {
|
|
|
620
691
|
// Handle schedule meeting event with encrypted fields
|
|
621
692
|
const event = cloneDeep(scheduleMeetingResponse[0]);
|
|
622
693
|
event.clientRequestId = 'test-request-id';
|
|
623
|
-
|
|
694
|
+
|
|
624
695
|
await webex.internal.aiAssistant._handleEvent(event);
|
|
625
696
|
|
|
626
|
-
expect(triggerSpy.getCall(0).args[0]).to.equal(
|
|
627
|
-
`aiassistant:result:test-request-id`
|
|
628
|
-
);
|
|
697
|
+
expect(triggerSpy.getCall(0).args[0]).to.equal(`aiassistant:result:test-request-id`);
|
|
629
698
|
|
|
630
699
|
await waitForAsync();
|
|
631
700
|
|
|
632
701
|
// Verify all encrypted fields were decrypted
|
|
633
702
|
const expectedResult = cloneDeep(event);
|
|
634
|
-
expectedResult.response.content.parameters.commentary =
|
|
703
|
+
expectedResult.response.content.parameters.commentary =
|
|
635
704
|
'decrypted-with-kms://kms-cisco.wbx2.com/keys/dd6053f0-a1b3-428d-8104-317527d73630-schedule_meeting_encrypted_commentary';
|
|
636
|
-
expectedResult.response.content.value.results.data.attendees[0].email =
|
|
705
|
+
expectedResult.response.content.value.results.data.attendees[0].email =
|
|
637
706
|
'decrypted-with-kms://kms-cisco.wbx2.com/keys/dd6053f0-a1b3-428d-8104-317527d73630-schedule_meeting_encrypted_email_0';
|
|
638
|
-
expectedResult.response.content.value.results.data.attendees[1].email =
|
|
707
|
+
expectedResult.response.content.value.results.data.attendees[1].email =
|
|
639
708
|
'decrypted-with-kms://kms-cisco.wbx2.com/keys/dd6053f0-a1b3-428d-8104-317527d73630-schedule_meeting_encrypted_email_1';
|
|
640
|
-
expectedResult.response.content.value.results.data.title =
|
|
709
|
+
expectedResult.response.content.value.results.data.title =
|
|
641
710
|
'decrypted-with-kms://kms-cisco.wbx2.com/keys/dd6053f0-a1b3-428d-8104-317527d73630-schedule_meeting_encrypted_title';
|
|
642
|
-
expectedResult.response.content.value.results.data.description =
|
|
711
|
+
expectedResult.response.content.value.results.data.description =
|
|
643
712
|
'decrypted-with-kms://kms-cisco.wbx2.com/keys/dd6053f0-a1b3-428d-8104-317527d73630-schedule_meeting_encrypted_description';
|
|
644
|
-
expectedResult.response.content.value.results.data.inScopeReply =
|
|
713
|
+
expectedResult.response.content.value.results.data.inScopeReply =
|
|
645
714
|
'decrypted-with-kms://kms-cisco.wbx2.com/keys/dd6053f0-a1b3-428d-8104-317527d73630-schedule_meeting_encrypted_inScopeReply';
|
|
646
|
-
expectedResult.response.content.value.results.data.meetingLink =
|
|
715
|
+
expectedResult.response.content.value.results.data.meetingLink =
|
|
647
716
|
'decrypted-with-kms://kms-cisco.wbx2.com/keys/dd6053f0-a1b3-428d-8104-317527d73630-schedule_meeting_encrypted_meetingLink';
|
|
648
717
|
|
|
649
718
|
expect(triggerSpy.getCall(0).args[1]).to.deep.equal(expectedResult);
|
|
650
719
|
});
|
|
651
720
|
|
|
721
|
+
it('handles a cited answer with sources response', async () => {
|
|
722
|
+
const triggerSpy = sinon.spy(webex.internal.aiAssistant, 'trigger');
|
|
723
|
+
webex.internal.encryption.decryptText.callsFake(async (keyUrl, value) => {
|
|
724
|
+
return `decrypted-with-${keyUrl}-${value}`;
|
|
725
|
+
});
|
|
726
|
+
|
|
727
|
+
await webex.internal.aiAssistant._request({
|
|
728
|
+
resource: 'test-resource',
|
|
729
|
+
params: {param1: 'value1'},
|
|
730
|
+
});
|
|
731
|
+
|
|
732
|
+
const event = cloneDeep(citedAnswerWithSourcesResponse[0]);
|
|
733
|
+
event.clientRequestId = 'test-request-id';
|
|
734
|
+
|
|
735
|
+
await webex.internal.aiAssistant._handleEvent(event);
|
|
736
|
+
|
|
737
|
+
expect(triggerSpy.getCall(0).args[0]).to.equal(`aiassistant:result:test-request-id`);
|
|
738
|
+
|
|
739
|
+
await waitForAsync();
|
|
740
|
+
|
|
741
|
+
const expectedResult = {
|
|
742
|
+
sessionId: '3c1939c0-92fe-11f0-8e9f-1bafc66fbbc5',
|
|
743
|
+
sessionUrl:
|
|
744
|
+
'https://assistant-api-a.wbx2.com:443/assistant-api/api/v1/sessions/3c1939c0-92fe-11f0-8e9f-1bafc66fbbc5',
|
|
745
|
+
messageId: '3c19fd10-92fe-11f0-8e9f-1bafc66fbbc5',
|
|
746
|
+
messageUrl:
|
|
747
|
+
'https://assistant-api-a.wbx2.com:443/assistant-api/api/v1/sessions/3c1939c0-92fe-11f0-8e9f-1bafc66fbbc5/messages/3c19fd10-92fe-11f0-8e9f-1bafc66fbbc5',
|
|
748
|
+
responseId: '3c1a4b30-92fe-11f0-8e9f-1bafc66fbbc5',
|
|
749
|
+
responseUrl:
|
|
750
|
+
'https://assistant-api-a.wbx2.com:443/assistant-api/api/v1/sessions/3c1939c0-92fe-11f0-8e9f-1bafc66fbbc5/messages/3c1a4b30-92fe-11f0-8e9f-1bafc66fbbc5',
|
|
751
|
+
content: {
|
|
752
|
+
name: 'cited_answer',
|
|
753
|
+
type: 'json',
|
|
754
|
+
encryptionKeyUrl: 'kms://kms-us.wbx2.com/keys/9565506d-78b1-4742-b0fd-63719748282e',
|
|
755
|
+
value: {
|
|
756
|
+
value:
|
|
757
|
+
'decrypted-with-kms://kms-us.wbx2.com/keys/9565506d-78b1-4742-b0fd-63719748282e-json_1_encrypted_value',
|
|
758
|
+
type: 'markdown',
|
|
759
|
+
citations: [
|
|
760
|
+
{
|
|
761
|
+
id: '6ccc8286e2084e05a6b9a29faae77095',
|
|
762
|
+
index: 1,
|
|
763
|
+
name: 'decrypted-with-kms://kms-us.wbx2.com/keys/9565506d-78b1-4742-b0fd-63719748282e-json_1_encrypted_citation_0',
|
|
764
|
+
url: 'https://co.webex.com/webappng/sites/co/recording/playback/6ccc8286e2084e05a6b9a29faae77095',
|
|
765
|
+
metadata: {
|
|
766
|
+
provider: 'webex',
|
|
767
|
+
type: 'meeting_recording',
|
|
768
|
+
},
|
|
769
|
+
},
|
|
770
|
+
],
|
|
771
|
+
sources: [
|
|
772
|
+
{
|
|
773
|
+
id: '6ccc8286e2084e05a6b9a29faae77096',
|
|
774
|
+
index: 1,
|
|
775
|
+
type: 'post_meeting',
|
|
776
|
+
name: 'decrypted-with-kms://kms-us.wbx2.com/keys/9565506d-78b1-4742-b0fd-63719748282e-json_1_encrypted_source_0',
|
|
777
|
+
metadata: {
|
|
778
|
+
meetingContainerId: 'mccc8286e2084e05a6b9a29faae77096',
|
|
779
|
+
},
|
|
780
|
+
},
|
|
781
|
+
{
|
|
782
|
+
id: '6ccc8286e2084e05a6b9a29faae77096',
|
|
783
|
+
index: 2,
|
|
784
|
+
type: 'post_call',
|
|
785
|
+
name: 'decrypted-with-kms://kms-us.wbx2.com/keys/9565506d-78b1-4742-b0fd-63719748282e-json_1_encrypted_source_1',
|
|
786
|
+
metadata: {
|
|
787
|
+
callContainerId: 'mccc8286e2084e05a6b9a29faae77096',
|
|
788
|
+
},
|
|
789
|
+
},
|
|
790
|
+
{
|
|
791
|
+
id: '6ccc8286e2084e05a6b9a29faae77096',
|
|
792
|
+
index: 3,
|
|
793
|
+
type: 'message',
|
|
794
|
+
name: 'decrypted-with-kms://kms-us.wbx2.com/keys/9565506d-78b1-4742-b0fd-63719748282e-json_1_encrypted_source_2',
|
|
795
|
+
metadata: {
|
|
796
|
+
spaceId: 'mccc8286e2084e05a6b9a29faae77096',
|
|
797
|
+
},
|
|
798
|
+
},
|
|
799
|
+
],
|
|
800
|
+
},
|
|
801
|
+
},
|
|
802
|
+
createdAt: '2025-09-16T13:08:30.594220705Z',
|
|
803
|
+
creator: {
|
|
804
|
+
role: 'assistant',
|
|
805
|
+
},
|
|
806
|
+
// the below fields are added by the SDK
|
|
807
|
+
errorCode: undefined,
|
|
808
|
+
errorMessage: undefined,
|
|
809
|
+
finished: true,
|
|
810
|
+
requestId: 'test-request-id',
|
|
811
|
+
responseType: 'response',
|
|
812
|
+
};
|
|
813
|
+
|
|
814
|
+
expect(triggerSpy.getCall(1).args[0]).to.deep.equal('aiassistant:stream:test-request-id');
|
|
815
|
+
expect(triggerSpy.getCall(1).args[1]).to.deep.equal(expectedResult);
|
|
816
|
+
});
|
|
817
|
+
|
|
652
818
|
it('decrypts and emits data when receiving event data', async () => {
|
|
653
819
|
const triggerSpy = sinon.spy(webex.internal.aiAssistant, 'trigger');
|
|
654
820
|
|
|
@@ -830,7 +996,8 @@ describe('plugin-ai-assistant', () => {
|
|
|
830
996
|
id: 'test-message-id',
|
|
831
997
|
url: 'https://assistant-api-a.wbx2.com:443/assistant-api/api/v1/sessions/test-session-id/messages/test-message-id',
|
|
832
998
|
sessionId: 'test-session-id',
|
|
833
|
-
sessionUrl:
|
|
999
|
+
sessionUrl:
|
|
1000
|
+
'https://assistant-api-a.wbx2.com:443/assistant-api/api/v1/sessions/test-session-id',
|
|
834
1001
|
creatorId: 'test-creator-id',
|
|
835
1002
|
createdAt: '2025-08-05T02:11:12.361Z',
|
|
836
1003
|
},
|
|
@@ -867,7 +1034,7 @@ describe('plugin-ai-assistant', () => {
|
|
|
867
1034
|
// Verify the request was made correctly
|
|
868
1035
|
expect(webex.request.calledOnce).to.be.true;
|
|
869
1036
|
const requestArgs = webex.request.getCall(0).args[0];
|
|
870
|
-
|
|
1037
|
+
|
|
871
1038
|
expect(requestArgs.service).to.equal('assistant-api');
|
|
872
1039
|
expect(requestArgs.resource).to.equal('sessions/test-session-id/messages');
|
|
873
1040
|
expect(requestArgs.method).to.equal('POST');
|
|
@@ -901,7 +1068,8 @@ describe('plugin-ai-assistant', () => {
|
|
|
901
1068
|
id: 'test-message-id',
|
|
902
1069
|
url: 'https://assistant-api-a.wbx2.com:443/assistant-api/api/v1/sessions/test-session-id/messages/test-message-id',
|
|
903
1070
|
sessionId: 'test-session-id',
|
|
904
|
-
sessionUrl:
|
|
1071
|
+
sessionUrl:
|
|
1072
|
+
'https://assistant-api-a.wbx2.com:443/assistant-api/api/v1/sessions/test-session-id',
|
|
905
1073
|
creatorId: 'test-creator-id',
|
|
906
1074
|
createdAt: '2025-08-05T02:11:12.361Z',
|
|
907
1075
|
requestId: 'custom-request-id',
|
|
@@ -1003,7 +1171,7 @@ describe('plugin-ai-assistant', () => {
|
|
|
1003
1171
|
// Should use the UUID stub
|
|
1004
1172
|
expect(result.requestId).to.equal('test-request-id');
|
|
1005
1173
|
expect(result.streamEventName).to.equal('aiassistant:stream:test-request-id');
|
|
1006
|
-
|
|
1174
|
+
|
|
1007
1175
|
const requestArgs = webex.request.getCall(0).args[0];
|
|
1008
1176
|
expect(requestArgs.body.clientRequestId).to.equal('test-request-id');
|
|
1009
1177
|
});
|
|
@@ -1054,6 +1222,24 @@ describe('plugin-ai-assistant', () => {
|
|
|
1054
1222
|
expect(requestArgs.body.entryPoint).to.be.undefined;
|
|
1055
1223
|
});
|
|
1056
1224
|
|
|
1225
|
+
it('includes AI-Assistant-Render-Protocol in the request header when renderProtocolVersion is provided', async () => {
|
|
1226
|
+
const options = {
|
|
1227
|
+
sessionId: 'test-session-id',
|
|
1228
|
+
encryptionKeyUrl: 'test-key-url',
|
|
1229
|
+
contextResources: [],
|
|
1230
|
+
contentType: 'action' as const,
|
|
1231
|
+
contentValue: 'test_action',
|
|
1232
|
+
renderProtocolVersion: '1.0',
|
|
1233
|
+
};
|
|
1234
|
+
|
|
1235
|
+
await webex.internal.aiAssistant.makeAiAssistantRequest(options);
|
|
1236
|
+
|
|
1237
|
+
const requestArgs = webex.request.getCall(0).args[0];
|
|
1238
|
+
expect(requestArgs.headers).to.deep.equal({
|
|
1239
|
+
'AI-Assistant-Render-Protocol': '1.0',
|
|
1240
|
+
});
|
|
1241
|
+
});
|
|
1242
|
+
|
|
1057
1243
|
it('handles request rejection', async () => {
|
|
1058
1244
|
webex.request.rejects(new Error('Network error'));
|
|
1059
1245
|
|
|
@@ -1065,9 +1251,9 @@ describe('plugin-ai-assistant', () => {
|
|
|
1065
1251
|
contentValue: 'test_action',
|
|
1066
1252
|
};
|
|
1067
1253
|
|
|
1068
|
-
await expect(
|
|
1069
|
-
|
|
1070
|
-
)
|
|
1254
|
+
await expect(webex.internal.aiAssistant.makeAiAssistantRequest(options)).to.be.rejectedWith(
|
|
1255
|
+
'Network error'
|
|
1256
|
+
);
|
|
1071
1257
|
});
|
|
1072
1258
|
|
|
1073
1259
|
it('starts timer when making a request', async () => {
|
|
@@ -1087,7 +1273,7 @@ describe('plugin-ai-assistant', () => {
|
|
|
1087
1273
|
|
|
1088
1274
|
it('handles timeout when no streaming response comes back', async () => {
|
|
1089
1275
|
const triggerSpy = sinon.spy(webex.internal.aiAssistant, 'trigger');
|
|
1090
|
-
|
|
1276
|
+
|
|
1091
1277
|
const options = {
|
|
1092
1278
|
sessionId: 'test-session-id',
|
|
1093
1279
|
encryptionKeyUrl: 'test-key-url',
|
|
@@ -1105,10 +1291,13 @@ describe('plugin-ai-assistant', () => {
|
|
|
1105
1291
|
|
|
1106
1292
|
// Should trigger timeout event on the stream
|
|
1107
1293
|
expect(triggerSpy.calledWith('aiassistant:stream:test-request-id')).to.be.true;
|
|
1108
|
-
const timeoutCall = triggerSpy
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1294
|
+
const timeoutCall = triggerSpy
|
|
1295
|
+
.getCalls()
|
|
1296
|
+
.find(
|
|
1297
|
+
(call) =>
|
|
1298
|
+
call.args[0] === 'aiassistant:stream:test-request-id' &&
|
|
1299
|
+
call.args[1].errorMessage === AI_ASSISTANT_ERRORS.AI_ASSISTANT_TIMEOUT
|
|
1300
|
+
);
|
|
1112
1301
|
expect(timeoutCall).to.exist;
|
|
1113
1302
|
expect(timeoutCall.args[1]).to.deep.include({
|
|
1114
1303
|
requestId: 'test-request-id',
|
|
@@ -1121,7 +1310,7 @@ describe('plugin-ai-assistant', () => {
|
|
|
1121
1310
|
it('resets timer when streaming responses are received', async () => {
|
|
1122
1311
|
const timerResetSpy = sinon.spy(Timer.prototype, 'reset');
|
|
1123
1312
|
const timerCancelSpy = sinon.spy(Timer.prototype, 'cancel');
|
|
1124
|
-
|
|
1313
|
+
|
|
1125
1314
|
const options = {
|
|
1126
1315
|
sessionId: 'test-session-id',
|
|
1127
1316
|
encryptionKeyUrl: 'test-key-url',
|