@webex/internal-plugin-ai-assistant 0.0.0-next.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/.eslintrc.js +6 -0
- package/README.md +157 -0
- package/babel.config.js +3 -0
- package/dist/ai-assistant.js +491 -0
- package/dist/ai-assistant.js.map +1 -0
- package/dist/config.js +20 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.js +46 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/jest.config.js +3 -0
- package/package.json +53 -0
- package/src/ai-assistant.ts +448 -0
- package/src/config.ts +13 -0
- package/src/constants.ts +38 -0
- package/src/index.ts +8 -0
- package/src/types.ts +46 -0
- package/test/unit/spec/ai-assistant.ts +363 -0
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2022 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
import uuid from 'uuid';
|
|
5
|
+
import {WebexPlugin} from '@webex/webex-core';
|
|
6
|
+
import '@webex/internal-plugin-mercury';
|
|
7
|
+
import {get} from 'lodash';
|
|
8
|
+
import {Timer} from '@webex/common-timers';
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
MakeMeetingRequestOptions,
|
|
12
|
+
RequestOptions,
|
|
13
|
+
RequestResponse,
|
|
14
|
+
SummarizeMeetingOptions,
|
|
15
|
+
} from './types';
|
|
16
|
+
import {
|
|
17
|
+
AI_ASSISTANT_ERROR_CODES,
|
|
18
|
+
AI_ASSISTANT_ERRORS,
|
|
19
|
+
AI_ASSISTANT_REGISTERED,
|
|
20
|
+
AI_ASSISTANT_RESULT,
|
|
21
|
+
AI_ASSISTANT_STREAM,
|
|
22
|
+
AI_ASSISTANT_UNREGISTERED,
|
|
23
|
+
AI_ASSISTANT_SERVICE_NAME,
|
|
24
|
+
ASSISTANT_API_RESPONSE_EVENT,
|
|
25
|
+
ACTION_TYPES,
|
|
26
|
+
CONTENT_TYPES,
|
|
27
|
+
CONTEXT_RESOURCE_TYPES,
|
|
28
|
+
} from './constants';
|
|
29
|
+
|
|
30
|
+
const AIAssistant = WebexPlugin.extend({
|
|
31
|
+
namespace: 'AIAssistant',
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* registered value indicating events registration is successful
|
|
35
|
+
* @instance
|
|
36
|
+
* @type {Boolean}
|
|
37
|
+
* @memberof AIAssistant
|
|
38
|
+
*/
|
|
39
|
+
registered: false,
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Initializer
|
|
43
|
+
* @private
|
|
44
|
+
* @param {Object} attrs
|
|
45
|
+
* @param {Object} options
|
|
46
|
+
* @returns {undefined}
|
|
47
|
+
*/
|
|
48
|
+
initialize(...args) {
|
|
49
|
+
Reflect.apply(WebexPlugin.prototype.initialize, this, args);
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Explicitly sets up the AI assistant plugin by connecting to mercury, and listening for AI assistant events.
|
|
54
|
+
* @returns {Promise}
|
|
55
|
+
* @public
|
|
56
|
+
* @memberof AIAssistant
|
|
57
|
+
*/
|
|
58
|
+
register() {
|
|
59
|
+
if (!this.webex.canAuthorize) {
|
|
60
|
+
this.logger.error('AI assistant->register#ERROR, Unable to register, SDK cannot authorize');
|
|
61
|
+
|
|
62
|
+
return Promise.reject(new Error('SDK cannot authorize'));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (this.registered) {
|
|
66
|
+
this.logger.info('AI assistant->register#INFO, AI assistant plugin already registered');
|
|
67
|
+
|
|
68
|
+
return Promise.resolve();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return this.webex.internal.mercury
|
|
72
|
+
.connect()
|
|
73
|
+
.then(() => {
|
|
74
|
+
this.listenForEvents();
|
|
75
|
+
this.trigger(AI_ASSISTANT_REGISTERED);
|
|
76
|
+
this.registered = true;
|
|
77
|
+
})
|
|
78
|
+
.catch((error) => {
|
|
79
|
+
this.logger.error(`AI assistant->register#ERROR, Unable to register, ${error.message}`);
|
|
80
|
+
|
|
81
|
+
return Promise.reject(error);
|
|
82
|
+
});
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Explicitly tears down the AI assistant plugin by disconnecting from mercury, and stops listening to AI assistant events
|
|
87
|
+
* @returns {Promise}
|
|
88
|
+
* @public
|
|
89
|
+
* @memberof AIAssistant
|
|
90
|
+
*/
|
|
91
|
+
unregister() {
|
|
92
|
+
if (!this.registered) {
|
|
93
|
+
this.logger.info('AI assistant->unregister#INFO, AI assistant plugin already unregistered');
|
|
94
|
+
|
|
95
|
+
return Promise.resolve();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
this.stopListeningForEvents();
|
|
99
|
+
|
|
100
|
+
return this.webex.internal.mercury.disconnect().then(() => {
|
|
101
|
+
this.trigger(AI_ASSISTANT_UNREGISTERED);
|
|
102
|
+
this.registered = false;
|
|
103
|
+
});
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* registers for Assistant API events through mercury
|
|
108
|
+
* @returns {undefined}
|
|
109
|
+
* @private
|
|
110
|
+
*/
|
|
111
|
+
listenForEvents() {
|
|
112
|
+
this.webex.internal.mercury.on(ASSISTANT_API_RESPONSE_EVENT, (envelope) => {
|
|
113
|
+
this._handleEvent(envelope.data);
|
|
114
|
+
});
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* unregisteres all the Assistant API events from mercury
|
|
119
|
+
* @returns {undefined}
|
|
120
|
+
* @private
|
|
121
|
+
*/
|
|
122
|
+
stopListeningForEvents() {
|
|
123
|
+
this.webex.internal.mercury.off(ASSISTANT_API_RESPONSE_EVENT);
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* constructs the event name based on request id
|
|
128
|
+
* This is used by the plugin to listen for the result of a particular request
|
|
129
|
+
* @param {UUID} requestId the id of the request
|
|
130
|
+
* @returns {string}
|
|
131
|
+
*/
|
|
132
|
+
_getResultEventName(requestId: string) {
|
|
133
|
+
return `${AI_ASSISTANT_RESULT}:${requestId}`;
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* constructs the stream event name based on request id
|
|
138
|
+
* This is used by the consumer to listen for the stream (i.e. the data) of a particular request
|
|
139
|
+
* @param {UUID} requestId the id of the request
|
|
140
|
+
* @returns {string}
|
|
141
|
+
*/
|
|
142
|
+
_getStreamEventName(requestId: string) {
|
|
143
|
+
return `${AI_ASSISTANT_STREAM}:${requestId}`;
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Takes incoming data and triggers correct events
|
|
148
|
+
* @param {Object} data the event data
|
|
149
|
+
* @returns {undefined}
|
|
150
|
+
*/
|
|
151
|
+
_handleEvent(data) {
|
|
152
|
+
this.trigger(this._getResultEventName(data.clientRequestId), data);
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Decrypts the encrypted value using the encryption key URL
|
|
157
|
+
* @param {Object} options
|
|
158
|
+
* @param {string} options.value the encrypted value to decrypt
|
|
159
|
+
* @param {string} options.encryptionKeyUrl the encryption key URL to use for
|
|
160
|
+
* @returns {Promise<Object>} returns a promise that resolves with the decrypted value
|
|
161
|
+
*/
|
|
162
|
+
async _decryptData({value, encryptionKeyUrl}) {
|
|
163
|
+
const result = await this.webex.internal.encryption.decryptText(encryptionKeyUrl, value);
|
|
164
|
+
|
|
165
|
+
return result;
|
|
166
|
+
},
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Makes the request to the AI assistant service
|
|
170
|
+
* @param {Object} options
|
|
171
|
+
* @param {string} options.resource the URL to query
|
|
172
|
+
* @param {Mixed} options.params additional params for the body of the request
|
|
173
|
+
* @param {string} options.dataPath the path to get the data in the result object
|
|
174
|
+
* @returns {Promise<Object>} Resolves with an object containing the requestId, sessionId and streamEventName
|
|
175
|
+
*/
|
|
176
|
+
_request(options: RequestOptions): Promise<RequestResponse> {
|
|
177
|
+
const {resource, params, dataPath} = options;
|
|
178
|
+
|
|
179
|
+
const timeout = this.config.requestTimeout;
|
|
180
|
+
const requestId = uuid.v4();
|
|
181
|
+
const eventName = this._getResultEventName(requestId);
|
|
182
|
+
const streamEventName = this._getStreamEventName(requestId);
|
|
183
|
+
let concatenatedMessage = '';
|
|
184
|
+
|
|
185
|
+
// eslint-disable-next-line no-async-promise-executor
|
|
186
|
+
return new Promise((resolve, reject) => {
|
|
187
|
+
const timer = new Timer(() => {
|
|
188
|
+
this.stopListening(this, eventName);
|
|
189
|
+
this.trigger(streamEventName, {
|
|
190
|
+
requestId,
|
|
191
|
+
finished: true,
|
|
192
|
+
errorMessage: AI_ASSISTANT_ERRORS.AI_ASSISTANT_TIMEOUT,
|
|
193
|
+
errorCode: AI_ASSISTANT_ERROR_CODES.AI_ASSISTANT_TIMEOUT,
|
|
194
|
+
});
|
|
195
|
+
}, timeout);
|
|
196
|
+
|
|
197
|
+
this.listenTo(this, eventName, async (data) => {
|
|
198
|
+
timer.reset();
|
|
199
|
+
const resultData = get(data, dataPath, []);
|
|
200
|
+
const errorMessage = get(data, 'response.errorMessage');
|
|
201
|
+
const errorCode = get(data, 'response.errorCode');
|
|
202
|
+
|
|
203
|
+
if (data.finished) {
|
|
204
|
+
// For finished messages, decrypt and emit the final complete message
|
|
205
|
+
timer.cancel();
|
|
206
|
+
|
|
207
|
+
try {
|
|
208
|
+
let decryptedMessage;
|
|
209
|
+
if (resultData?.value) {
|
|
210
|
+
decryptedMessage = await this._decryptData(resultData);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Emit the final message
|
|
214
|
+
this.trigger(streamEventName, {
|
|
215
|
+
message: decryptedMessage || '',
|
|
216
|
+
requestId,
|
|
217
|
+
finished: true,
|
|
218
|
+
errorMessage,
|
|
219
|
+
errorCode,
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
this.stopListening(this, eventName);
|
|
223
|
+
} catch (decryptError) {
|
|
224
|
+
this.trigger(streamEventName, {
|
|
225
|
+
message: concatenatedMessage,
|
|
226
|
+
requestId,
|
|
227
|
+
finished: true,
|
|
228
|
+
errorMessage: errorMessage || decryptError.message,
|
|
229
|
+
errorCode,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
} else {
|
|
233
|
+
// For non-finished messages, concatenate and emit the accumulated message
|
|
234
|
+
try {
|
|
235
|
+
let decryptedMessage = '';
|
|
236
|
+
if (resultData?.value) {
|
|
237
|
+
decryptedMessage = await this._decryptData(resultData);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
concatenatedMessage += decryptedMessage;
|
|
241
|
+
|
|
242
|
+
// Emit the concatenated message so far
|
|
243
|
+
this.trigger(streamEventName, {
|
|
244
|
+
message: concatenatedMessage,
|
|
245
|
+
requestId,
|
|
246
|
+
finished: false,
|
|
247
|
+
errorMessage,
|
|
248
|
+
errorCode,
|
|
249
|
+
});
|
|
250
|
+
} catch (decryptError) {
|
|
251
|
+
// If decryption fails, we still want to continue listening for more messages
|
|
252
|
+
this.trigger(streamEventName, {
|
|
253
|
+
message: concatenatedMessage,
|
|
254
|
+
requestId,
|
|
255
|
+
finished: false,
|
|
256
|
+
errorMessage: errorMessage || decryptError.message,
|
|
257
|
+
errorCode,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
this.webex
|
|
264
|
+
.request({
|
|
265
|
+
service: AI_ASSISTANT_SERVICE_NAME,
|
|
266
|
+
resource,
|
|
267
|
+
method: 'POST',
|
|
268
|
+
contentType: 'application/json',
|
|
269
|
+
body: {clientRequestId: requestId, ...params},
|
|
270
|
+
})
|
|
271
|
+
.catch((error) => {
|
|
272
|
+
reject(error);
|
|
273
|
+
})
|
|
274
|
+
.then(({body}) => {
|
|
275
|
+
const {sessionId} = body;
|
|
276
|
+
|
|
277
|
+
resolve({
|
|
278
|
+
requestId,
|
|
279
|
+
sessionId,
|
|
280
|
+
streamEventName,
|
|
281
|
+
});
|
|
282
|
+
timer.start();
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
},
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Common method to make AI assistant requests for meeting analysis
|
|
289
|
+
* @param {Object} options
|
|
290
|
+
* @param {string} options.contextResources array of context resources to include in the request
|
|
291
|
+
* @param {string} options.sessionId the session ID for subsequent requests, not required for the first request
|
|
292
|
+
* @param {string} options.encryptionKeyUrl the encryption key URL for this meeting summary
|
|
293
|
+
* @param {string} options.contentType the type of content ('action' or 'message')
|
|
294
|
+
* @param {string} options.contentValue the value to use (action name or message text)
|
|
295
|
+
* @param {Object} options.parameters optional parameters to include in the request (for action type only)
|
|
296
|
+
* @param {Object} options.assistant optional parameter to specify the assistant to use
|
|
297
|
+
* @param {Object} options.locale optional locale to use for the request, defaults to 'en_US'
|
|
298
|
+
* @returns {Promise<Object>} Resolves with an object containing the requestId, sessionId and streamEventName
|
|
299
|
+
*/
|
|
300
|
+
async _makeMeetingRequest(options: MakeMeetingRequestOptions): Promise<RequestResponse> {
|
|
301
|
+
let value = options.contentValue;
|
|
302
|
+
|
|
303
|
+
if (options.contentType === 'message') {
|
|
304
|
+
value = await this._encryptData({
|
|
305
|
+
text: options.contentValue,
|
|
306
|
+
encryptionKeyUrl: options.encryptionKeyUrl,
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const content: any = {
|
|
311
|
+
context: {
|
|
312
|
+
resources: options.contextResources,
|
|
313
|
+
},
|
|
314
|
+
encryptionKeyUrl: options.encryptionKeyUrl,
|
|
315
|
+
type: options.contentType,
|
|
316
|
+
value,
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
if (options.contentType === 'action' && options.parameters) {
|
|
320
|
+
content.parameters = options.parameters;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
return this._request({
|
|
324
|
+
resource: options.sessionId ? `sessions/${options.sessionId}/messages` : 'sessions/messages',
|
|
325
|
+
dataPath: 'response.content',
|
|
326
|
+
params: {
|
|
327
|
+
async: 'chunked',
|
|
328
|
+
locale: options.locale || 'en_US',
|
|
329
|
+
content,
|
|
330
|
+
...(options.assistant ? {assistant: options.assistant} : {}),
|
|
331
|
+
},
|
|
332
|
+
});
|
|
333
|
+
},
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Returns the summary of a meeting
|
|
337
|
+
* @param {Object} options
|
|
338
|
+
* @param {string} options.meetingInstanceId the meeting instance ID for the meeting from locus
|
|
339
|
+
* @param {string} options.meetingSite the name.webex.com site for the meeting
|
|
340
|
+
* @param {string} options.sessionId the session ID for subsequent requests, not required for the first request
|
|
341
|
+
* @param {string} options.encryptionKeyUrl the encryption key URL for this meeting summary
|
|
342
|
+
* @param {number} options.lastMinutes Optional number of minutes to summarize from the end of the meeting. If not included, summarizes from the start.
|
|
343
|
+
* @returns {Promise<Object>} Resolves with an object containing the requestId, sessionId and streamEventName
|
|
344
|
+
*/
|
|
345
|
+
summarizeMeeting(options: SummarizeMeetingOptions): Promise<RequestResponse> {
|
|
346
|
+
return this._makeMeetingRequest({
|
|
347
|
+
...options,
|
|
348
|
+
contentType: CONTENT_TYPES.ACTION,
|
|
349
|
+
contentValue: ACTION_TYPES.SUMMARIZE_FOR_ME,
|
|
350
|
+
contextResources: [
|
|
351
|
+
{
|
|
352
|
+
id: options.meetingInstanceId,
|
|
353
|
+
type: CONTEXT_RESOURCE_TYPES.MEETING,
|
|
354
|
+
url: options.meetingSite,
|
|
355
|
+
},
|
|
356
|
+
],
|
|
357
|
+
...(options.lastMinutes ? {parameters: {lastMinutes: options.lastMinutes}} : {}),
|
|
358
|
+
});
|
|
359
|
+
},
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Checks if the user's name was mentioned in a meeting
|
|
363
|
+
* @param {Object} options
|
|
364
|
+
* @param {string} options.meetingInstanceId the meeting instance ID for the meeting from locus
|
|
365
|
+
* @param {string} options.meetingSite the name.webex.com site for the meeting
|
|
366
|
+
* @param {string} options.sessionId the session ID for subsequent requests, not required for the first request
|
|
367
|
+
* @param {string} options.encryptionKeyUrl the encryption key URL for this meeting summary
|
|
368
|
+
* @returns {Promise<Object>} Resolves with an object containing the requestId, sessionId and streamEventName
|
|
369
|
+
*/
|
|
370
|
+
wasMyNameMentioned(options: SummarizeMeetingOptions): Promise<RequestResponse> {
|
|
371
|
+
return this._makeMeetingRequest({
|
|
372
|
+
...options,
|
|
373
|
+
contextResources: [
|
|
374
|
+
{
|
|
375
|
+
id: options.meetingInstanceId,
|
|
376
|
+
type: CONTEXT_RESOURCE_TYPES.MEETING,
|
|
377
|
+
url: options.meetingSite,
|
|
378
|
+
},
|
|
379
|
+
],
|
|
380
|
+
contentType: CONTENT_TYPES.ACTION,
|
|
381
|
+
contentValue: ACTION_TYPES.WAS_MY_NAME_MENTIONED,
|
|
382
|
+
});
|
|
383
|
+
},
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Returns all action items from a meeting
|
|
387
|
+
* @param {Object} options
|
|
388
|
+
* @param {string} options.meetingInstanceId the meeting instance ID for the meeting from locus
|
|
389
|
+
* @param {string} options.meetingSite the name.webex.com site for the meeting
|
|
390
|
+
* @param {string} options.sessionId the session ID for subsequent requests, not required for the first request
|
|
391
|
+
* @param {string} options.encryptionKeyUrl the encryption key URL for this meeting summary
|
|
392
|
+
* @returns {Promise<Object>} Resolves with an object containing the requestId, sessionId and streamEventName
|
|
393
|
+
*/
|
|
394
|
+
showAllActionItems(options: SummarizeMeetingOptions): Promise<RequestResponse> {
|
|
395
|
+
return this._makeMeetingRequest({
|
|
396
|
+
...options,
|
|
397
|
+
contextResources: [
|
|
398
|
+
{
|
|
399
|
+
id: options.meetingInstanceId,
|
|
400
|
+
type: CONTEXT_RESOURCE_TYPES.MEETING,
|
|
401
|
+
url: options.meetingSite,
|
|
402
|
+
},
|
|
403
|
+
],
|
|
404
|
+
contentType: CONTENT_TYPES.ACTION,
|
|
405
|
+
contentValue: ACTION_TYPES.SHOW_ALL_ACTION_ITEMS,
|
|
406
|
+
});
|
|
407
|
+
},
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Helper method to encrypt text using the encryption key URL
|
|
411
|
+
* @param {Object} options
|
|
412
|
+
* @param {string} options.text the text to encrypt
|
|
413
|
+
* @param {string} options.encryptionKeyUrl the encryption key URL to use for encryption
|
|
414
|
+
* @returns {Promise<string>} returns a promise that resolves with the encrypted text
|
|
415
|
+
*/
|
|
416
|
+
async _encryptData({text, encryptionKeyUrl}) {
|
|
417
|
+
const result = await this.webex.internal.encryption.encryptText(encryptionKeyUrl, text);
|
|
418
|
+
|
|
419
|
+
return result;
|
|
420
|
+
},
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Ask any question about the meeting content
|
|
424
|
+
* @param {Object} options
|
|
425
|
+
* @param {string} options.meetingInstanceId the meeting instance ID for the meeting from locus
|
|
426
|
+
* @param {string} options.meetingSite the name.webex.com site for the meeting
|
|
427
|
+
* @param {string} options.sessionId the session ID for subsequent requests, not required for the first request
|
|
428
|
+
* @param {string} options.encryptionKeyUrl the encryption key URL for this meeting summary
|
|
429
|
+
* @param {string} options.question the question to ask about the meeting content
|
|
430
|
+
* @returns {Promise<Object>} Resolves with an object containing the requestId, sessionId and streamEventName
|
|
431
|
+
*/
|
|
432
|
+
askMeAnything(options: SummarizeMeetingOptions & {question: string}): Promise<RequestResponse> {
|
|
433
|
+
return this._makeMeetingRequest({
|
|
434
|
+
...options,
|
|
435
|
+
contextResources: [
|
|
436
|
+
{
|
|
437
|
+
id: options.meetingInstanceId,
|
|
438
|
+
type: CONTEXT_RESOURCE_TYPES.MEETING,
|
|
439
|
+
url: options.meetingSite,
|
|
440
|
+
},
|
|
441
|
+
],
|
|
442
|
+
contentType: CONTENT_TYPES.MESSAGE,
|
|
443
|
+
contentValue: options.question,
|
|
444
|
+
});
|
|
445
|
+
},
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
export default AIAssistant;
|
package/src/config.ts
ADDED
package/src/constants.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export const AI_ASSISTANT_REGISTERED = 'aiassistant:registered';
|
|
2
|
+
export const AI_ASSISTANT_UNREGISTERED = 'aiassistant:unregistered';
|
|
3
|
+
export const ASSISTANT_API_RESPONSE_EVENT = 'event:assistant-api.response';
|
|
4
|
+
export const AI_ASSISTANT_SERVICE_NAME = 'assistant-api';
|
|
5
|
+
export const AI_ASSISTANT_RESULT = 'aiassistant:result';
|
|
6
|
+
export const AI_ASSISTANT_STREAM = 'aiassistant:stream';
|
|
7
|
+
|
|
8
|
+
export enum AI_ASSISTANT_ERRORS {
|
|
9
|
+
NOT_ENOUGH_CONTENT = 'NO_ENOUGH_MEETING_TRANSCRIPT',
|
|
10
|
+
TRANSCRIPT_AUTH_ERROR = 'TRANSCRIPT_AUTH_ERROR',
|
|
11
|
+
AI_ASSISTANT_TIMEOUT = 'AI_ASSISTANT_TIMEOUT', // This one is generated by the plugin
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export enum AI_ASSISTANT_ERROR_CODES {
|
|
15
|
+
AI_ASSISTANT_TIMEOUT = 9408, // This one is generated by the plugin
|
|
16
|
+
NOT_ENOUGH_CONTENT = 204,
|
|
17
|
+
FORBIDDEN = 403,
|
|
18
|
+
LLM_TIMEOUT = 408,
|
|
19
|
+
RATE_LIMIT = 429,
|
|
20
|
+
GENERIC_ERROR = 10000,
|
|
21
|
+
WAIT_PREVIOUS = 10001,
|
|
22
|
+
EMPTY_SEARCH_RESULT = 10002,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export enum ACTION_TYPES {
|
|
26
|
+
SHOW_ALL_ACTION_ITEMS = 'SHOW_ALL_ACTION_ITEMS',
|
|
27
|
+
WAS_MY_NAME_MENTIONED = 'WAS_MY_NAME_MENTIONED',
|
|
28
|
+
SUMMARIZE_FOR_ME = 'SUMMARIZE_FOR_ME',
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export enum CONTENT_TYPES {
|
|
32
|
+
ACTION = 'action',
|
|
33
|
+
MESSAGE = 'message',
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export enum CONTEXT_RESOURCE_TYPES {
|
|
37
|
+
MEETING = 'meeting',
|
|
38
|
+
}
|
package/src/index.ts
ADDED
package/src/types.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export interface RequestResponse {
|
|
2
|
+
sessionId: string;
|
|
3
|
+
requestId: string;
|
|
4
|
+
streamEventName: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface StreamEvent {
|
|
8
|
+
message: string;
|
|
9
|
+
requestId: string;
|
|
10
|
+
finished: boolean;
|
|
11
|
+
error: string | null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface RequestOptions {
|
|
15
|
+
resource: string;
|
|
16
|
+
dataPath: string;
|
|
17
|
+
foundPath?: string;
|
|
18
|
+
notFoundPath?: string;
|
|
19
|
+
params?: Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface ContextResource {
|
|
23
|
+
id: string;
|
|
24
|
+
type: string;
|
|
25
|
+
url: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface SummarizeMeetingOptions {
|
|
29
|
+
assistant?: string;
|
|
30
|
+
meetingInstanceId: string;
|
|
31
|
+
meetingSite: string;
|
|
32
|
+
sessionId: string;
|
|
33
|
+
encryptionKeyUrl: string;
|
|
34
|
+
lastMinutes?: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface MakeMeetingRequestOptions {
|
|
38
|
+
sessionId: string;
|
|
39
|
+
encryptionKeyUrl: string;
|
|
40
|
+
contextResources: ContextResource[];
|
|
41
|
+
contentType: 'action' | 'message';
|
|
42
|
+
contentValue: string;
|
|
43
|
+
parameters?: any;
|
|
44
|
+
assistant?: string;
|
|
45
|
+
locale?: string;
|
|
46
|
+
}
|