@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
package/.eslintrc.js
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# @webex/internal-plugin-ai-assistant
|
|
2
|
+
|
|
3
|
+
[](https://github.com/RichardLitt/standard-readme)
|
|
4
|
+
|
|
5
|
+
> Plugin for AI Assistant functionality
|
|
6
|
+
|
|
7
|
+
This is an internal Cisco Webex plugin. As such, it does not strictly adhere to semantic versioning. Use at your own risk. If you're not working on one of our first party clients, please look at our [developer api](https://developer.webex.com/) and stick to our public plugins.
|
|
8
|
+
|
|
9
|
+
- [Install](#install)
|
|
10
|
+
- [Usage](#usage)
|
|
11
|
+
- [Maintainers](#maintainers)
|
|
12
|
+
- [Contribute](#contribute)
|
|
13
|
+
- [License](#license)
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install --save @webex/internal-plugin-ai-assistant
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
The responses from the AI assistant service are delivered asynchronously via mercury. The methods in this plugin return a stream ID which can then be used to listen to the updates for a given request. The service will return preliminary versions of a response. The latest response for a given request should be used.
|
|
24
|
+
|
|
25
|
+
The data used for the arguments to the methods in this plugin is obtained from either Locus or the Meeting Container.
|
|
26
|
+
```js
|
|
27
|
+
import '@webex/internal-plugin-ai-assistant';
|
|
28
|
+
|
|
29
|
+
import WebexCore from '@webex/webex-core';
|
|
30
|
+
|
|
31
|
+
const webex = new WebexCore();
|
|
32
|
+
|
|
33
|
+
// Namespace.
|
|
34
|
+
webex.internal.aiAssistant
|
|
35
|
+
|
|
36
|
+
// Register the plugin (connects to mercury).
|
|
37
|
+
webex.internal.aiAssistant.register()
|
|
38
|
+
.then(() => {}) // On successful registration.
|
|
39
|
+
.catch(() => {}); // On failed registration.
|
|
40
|
+
|
|
41
|
+
// Unregister the plugin (disconnects from mercury).
|
|
42
|
+
webex.internal.aiAssistant.unregister()
|
|
43
|
+
.then(() => {}) // On successful unregistration.
|
|
44
|
+
.catch(() => {}); // On failed unregistration.
|
|
45
|
+
|
|
46
|
+
// Methods
|
|
47
|
+
|
|
48
|
+
// Get a summary of a meeting
|
|
49
|
+
webex.internal.aiAssistant.summarizeMeeting({
|
|
50
|
+
meetingInstanceId: '<meeting-instance-id>',
|
|
51
|
+
meetingSite: 'company.webex.com',
|
|
52
|
+
sessionId: '<session-id>', // Optional for first request
|
|
53
|
+
encryptionKeyUrl: '<encryption-key-url>',
|
|
54
|
+
lastMinutes: 30 // Optional: summarize only last 30 minutes
|
|
55
|
+
}).then((response) => {
|
|
56
|
+
const { requestId, sessionId, streamEventName } = response;
|
|
57
|
+
|
|
58
|
+
// Listen for streaming responses
|
|
59
|
+
webex.internal.aiAssistant.on(streamEventName, (data) => {
|
|
60
|
+
console.log('AI Response:', data.message);
|
|
61
|
+
if (data.finished) {
|
|
62
|
+
console.log('Summary complete');
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Check if your name was mentioned in a meeting
|
|
68
|
+
webex.internal.aiAssistant.wasMyNameMentioned({
|
|
69
|
+
meetingInstanceId: '<meeting-instance-id>',
|
|
70
|
+
meetingSite: 'company.webex.com',
|
|
71
|
+
sessionId: '<session-id>', // Optional for first request
|
|
72
|
+
encryptionKeyUrl: '<encryption-key-url>'
|
|
73
|
+
}).then((response) => {
|
|
74
|
+
const { requestId, sessionId, streamEventName } = response;
|
|
75
|
+
|
|
76
|
+
// Listen for streaming responses
|
|
77
|
+
webex.internal.aiAssistant.on(streamEventName, (data) => {
|
|
78
|
+
console.log('Mention check result:', data.message);
|
|
79
|
+
if (data.finished) {
|
|
80
|
+
console.log('Check complete');
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Get all action items from a meeting
|
|
86
|
+
webex.internal.aiAssistant.showAllActionItems({
|
|
87
|
+
meetingInstanceId: '<meeting-instance-id>',
|
|
88
|
+
meetingSite: 'company.webex.com',
|
|
89
|
+
sessionId: '<session-id>', // Optional for first request
|
|
90
|
+
encryptionKeyUrl: '<encryption-key-url>'
|
|
91
|
+
}).then((response) => {
|
|
92
|
+
const { requestId, sessionId, streamEventName } = response;
|
|
93
|
+
|
|
94
|
+
// Listen for streaming responses
|
|
95
|
+
webex.internal.aiAssistant.on(streamEventName, (data) => {
|
|
96
|
+
console.log('Action items:', data.message);
|
|
97
|
+
if (data.finished) {
|
|
98
|
+
console.log('Action items retrieval complete');
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// Ask any question about the meeting content
|
|
104
|
+
webex.internal.aiAssistant.askMeAnything({
|
|
105
|
+
meetingInstanceId: '<meeting-instance-id>',
|
|
106
|
+
meetingSite: 'company.webex.com',
|
|
107
|
+
sessionId: '<session-id>', // Optional for first request
|
|
108
|
+
encryptionKeyUrl: '<encryption-key-url>',
|
|
109
|
+
question: 'What were the main decisions made in this meeting?'
|
|
110
|
+
}).then((response) => {
|
|
111
|
+
const { requestId, sessionId, streamEventName } = response;
|
|
112
|
+
|
|
113
|
+
// Listen for streaming responses
|
|
114
|
+
webex.internal.aiAssistant.on(streamEventName, (data) => {
|
|
115
|
+
console.log('AI Answer:', data.message);
|
|
116
|
+
if (data.finished) {
|
|
117
|
+
console.log('Question answered');
|
|
118
|
+
}
|
|
119
|
+
if (data.errorMessage) {
|
|
120
|
+
console.error('Error:', data.errorMessage);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Response Format
|
|
127
|
+
|
|
128
|
+
All AI Assistant methods return a Promise that resolves with:
|
|
129
|
+
- `requestId`: Unique identifier for the request
|
|
130
|
+
- `sessionId`: Session identifier for maintaining conversation context
|
|
131
|
+
- `streamEventName`: Event name to listen for streaming responses
|
|
132
|
+
|
|
133
|
+
### Stream Events
|
|
134
|
+
|
|
135
|
+
Listen to the returned `streamEventName` for real-time AI responses:
|
|
136
|
+
|
|
137
|
+
```js
|
|
138
|
+
webex.internal.aiAssistant.on(streamEventName, (data) => {
|
|
139
|
+
console.log(data.message); // Current message content
|
|
140
|
+
console.log(data.finished); // Boolean indicating if response is complete
|
|
141
|
+
console.log(data.requestId); // Request identifier
|
|
142
|
+
console.log(data.errorMessage); // Error message if any
|
|
143
|
+
console.log(data.errorCode); // Error code if any
|
|
144
|
+
});
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Maintainers
|
|
148
|
+
|
|
149
|
+
This package is maintained by [Cisco Webex for Developers](https://developer.webex.com/).
|
|
150
|
+
|
|
151
|
+
## Contribute
|
|
152
|
+
|
|
153
|
+
Pull requests welcome. Please see [CONTRIBUTING.md](https://github.com/webex/webex-js-sdk/blob/master/CONTRIBUTING.md) for more details.
|
|
154
|
+
|
|
155
|
+
## License
|
|
156
|
+
|
|
157
|
+
© 2016-2025 Cisco and/or its affiliates. All Rights Reserved.
|
package/babel.config.js
ADDED
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _Object$keys = require("@babel/runtime-corejs2/core-js/object/keys");
|
|
4
|
+
var _Object$getOwnPropertySymbols = require("@babel/runtime-corejs2/core-js/object/get-own-property-symbols");
|
|
5
|
+
var _Object$getOwnPropertyDescriptor = require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptor");
|
|
6
|
+
var _Object$getOwnPropertyDescriptors = require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptors");
|
|
7
|
+
var _Object$defineProperties = require("@babel/runtime-corejs2/core-js/object/define-properties");
|
|
8
|
+
var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
|
|
9
|
+
var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
|
|
10
|
+
_Object$defineProperty(exports, "__esModule", {
|
|
11
|
+
value: true
|
|
12
|
+
});
|
|
13
|
+
exports.default = void 0;
|
|
14
|
+
var _regenerator = _interopRequireDefault(require("@babel/runtime-corejs2/regenerator"));
|
|
15
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty"));
|
|
16
|
+
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/asyncToGenerator"));
|
|
17
|
+
var _apply = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/reflect/apply"));
|
|
18
|
+
var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
|
|
19
|
+
var _uuid = _interopRequireDefault(require("uuid"));
|
|
20
|
+
var _webexCore = require("@webex/webex-core");
|
|
21
|
+
require("@webex/internal-plugin-mercury");
|
|
22
|
+
var _lodash = require("lodash");
|
|
23
|
+
var _commonTimers = require("@webex/common-timers");
|
|
24
|
+
var _constants = require("./constants");
|
|
25
|
+
function ownKeys(e, r) { var t = _Object$keys(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return _Object$getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
26
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; } /*!
|
|
27
|
+
* Copyright (c) 2015-2022 Cisco Systems, Inc. See LICENSE file.
|
|
28
|
+
*/
|
|
29
|
+
var AIAssistant = _webexCore.WebexPlugin.extend({
|
|
30
|
+
namespace: 'AIAssistant',
|
|
31
|
+
/**
|
|
32
|
+
* registered value indicating events registration is successful
|
|
33
|
+
* @instance
|
|
34
|
+
* @type {Boolean}
|
|
35
|
+
* @memberof AIAssistant
|
|
36
|
+
*/
|
|
37
|
+
registered: false,
|
|
38
|
+
/**
|
|
39
|
+
* Initializer
|
|
40
|
+
* @private
|
|
41
|
+
* @param {Object} attrs
|
|
42
|
+
* @param {Object} options
|
|
43
|
+
* @returns {undefined}
|
|
44
|
+
*/
|
|
45
|
+
initialize: function initialize() {
|
|
46
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
47
|
+
args[_key] = arguments[_key];
|
|
48
|
+
}
|
|
49
|
+
(0, _apply.default)(_webexCore.WebexPlugin.prototype.initialize, this, args);
|
|
50
|
+
},
|
|
51
|
+
/**
|
|
52
|
+
* Explicitly sets up the AI assistant plugin by connecting to mercury, and listening for AI assistant events.
|
|
53
|
+
* @returns {Promise}
|
|
54
|
+
* @public
|
|
55
|
+
* @memberof AIAssistant
|
|
56
|
+
*/
|
|
57
|
+
register: function register() {
|
|
58
|
+
var _this = this;
|
|
59
|
+
if (!this.webex.canAuthorize) {
|
|
60
|
+
this.logger.error('AI assistant->register#ERROR, Unable to register, SDK cannot authorize');
|
|
61
|
+
return _promise.default.reject(new Error('SDK cannot authorize'));
|
|
62
|
+
}
|
|
63
|
+
if (this.registered) {
|
|
64
|
+
this.logger.info('AI assistant->register#INFO, AI assistant plugin already registered');
|
|
65
|
+
return _promise.default.resolve();
|
|
66
|
+
}
|
|
67
|
+
return this.webex.internal.mercury.connect().then(function () {
|
|
68
|
+
_this.listenForEvents();
|
|
69
|
+
_this.trigger(_constants.AI_ASSISTANT_REGISTERED);
|
|
70
|
+
_this.registered = true;
|
|
71
|
+
}).catch(function (error) {
|
|
72
|
+
_this.logger.error("AI assistant->register#ERROR, Unable to register, ".concat(error.message));
|
|
73
|
+
return _promise.default.reject(error);
|
|
74
|
+
});
|
|
75
|
+
},
|
|
76
|
+
/**
|
|
77
|
+
* Explicitly tears down the AI assistant plugin by disconnecting from mercury, and stops listening to AI assistant events
|
|
78
|
+
* @returns {Promise}
|
|
79
|
+
* @public
|
|
80
|
+
* @memberof AIAssistant
|
|
81
|
+
*/
|
|
82
|
+
unregister: function unregister() {
|
|
83
|
+
var _this2 = this;
|
|
84
|
+
if (!this.registered) {
|
|
85
|
+
this.logger.info('AI assistant->unregister#INFO, AI assistant plugin already unregistered');
|
|
86
|
+
return _promise.default.resolve();
|
|
87
|
+
}
|
|
88
|
+
this.stopListeningForEvents();
|
|
89
|
+
return this.webex.internal.mercury.disconnect().then(function () {
|
|
90
|
+
_this2.trigger(_constants.AI_ASSISTANT_UNREGISTERED);
|
|
91
|
+
_this2.registered = false;
|
|
92
|
+
});
|
|
93
|
+
},
|
|
94
|
+
/**
|
|
95
|
+
* registers for Assistant API events through mercury
|
|
96
|
+
* @returns {undefined}
|
|
97
|
+
* @private
|
|
98
|
+
*/
|
|
99
|
+
listenForEvents: function listenForEvents() {
|
|
100
|
+
var _this3 = this;
|
|
101
|
+
this.webex.internal.mercury.on(_constants.ASSISTANT_API_RESPONSE_EVENT, function (envelope) {
|
|
102
|
+
_this3._handleEvent(envelope.data);
|
|
103
|
+
});
|
|
104
|
+
},
|
|
105
|
+
/**
|
|
106
|
+
* unregisteres all the Assistant API events from mercury
|
|
107
|
+
* @returns {undefined}
|
|
108
|
+
* @private
|
|
109
|
+
*/
|
|
110
|
+
stopListeningForEvents: function stopListeningForEvents() {
|
|
111
|
+
this.webex.internal.mercury.off(_constants.ASSISTANT_API_RESPONSE_EVENT);
|
|
112
|
+
},
|
|
113
|
+
/**
|
|
114
|
+
* constructs the event name based on request id
|
|
115
|
+
* This is used by the plugin to listen for the result of a particular request
|
|
116
|
+
* @param {UUID} requestId the id of the request
|
|
117
|
+
* @returns {string}
|
|
118
|
+
*/
|
|
119
|
+
_getResultEventName: function _getResultEventName(requestId) {
|
|
120
|
+
return "".concat(_constants.AI_ASSISTANT_RESULT, ":").concat(requestId);
|
|
121
|
+
},
|
|
122
|
+
/**
|
|
123
|
+
* constructs the stream event name based on request id
|
|
124
|
+
* This is used by the consumer to listen for the stream (i.e. the data) of a particular request
|
|
125
|
+
* @param {UUID} requestId the id of the request
|
|
126
|
+
* @returns {string}
|
|
127
|
+
*/
|
|
128
|
+
_getStreamEventName: function _getStreamEventName(requestId) {
|
|
129
|
+
return "".concat(_constants.AI_ASSISTANT_STREAM, ":").concat(requestId);
|
|
130
|
+
},
|
|
131
|
+
/**
|
|
132
|
+
* Takes incoming data and triggers correct events
|
|
133
|
+
* @param {Object} data the event data
|
|
134
|
+
* @returns {undefined}
|
|
135
|
+
*/
|
|
136
|
+
_handleEvent: function _handleEvent(data) {
|
|
137
|
+
this.trigger(this._getResultEventName(data.clientRequestId), data);
|
|
138
|
+
},
|
|
139
|
+
/**
|
|
140
|
+
* Decrypts the encrypted value using the encryption key URL
|
|
141
|
+
* @param {Object} options
|
|
142
|
+
* @param {string} options.value the encrypted value to decrypt
|
|
143
|
+
* @param {string} options.encryptionKeyUrl the encryption key URL to use for
|
|
144
|
+
* @returns {Promise<Object>} returns a promise that resolves with the decrypted value
|
|
145
|
+
*/
|
|
146
|
+
_decryptData: function _decryptData(_ref) {
|
|
147
|
+
var _this4 = this;
|
|
148
|
+
return (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
|
|
149
|
+
var value, encryptionKeyUrl, result;
|
|
150
|
+
return _regenerator.default.wrap(function _callee$(_context) {
|
|
151
|
+
while (1) switch (_context.prev = _context.next) {
|
|
152
|
+
case 0:
|
|
153
|
+
value = _ref.value, encryptionKeyUrl = _ref.encryptionKeyUrl;
|
|
154
|
+
_context.next = 3;
|
|
155
|
+
return _this4.webex.internal.encryption.decryptText(encryptionKeyUrl, value);
|
|
156
|
+
case 3:
|
|
157
|
+
result = _context.sent;
|
|
158
|
+
return _context.abrupt("return", result);
|
|
159
|
+
case 5:
|
|
160
|
+
case "end":
|
|
161
|
+
return _context.stop();
|
|
162
|
+
}
|
|
163
|
+
}, _callee);
|
|
164
|
+
}))();
|
|
165
|
+
},
|
|
166
|
+
/**
|
|
167
|
+
* Makes the request to the AI assistant service
|
|
168
|
+
* @param {Object} options
|
|
169
|
+
* @param {string} options.resource the URL to query
|
|
170
|
+
* @param {Mixed} options.params additional params for the body of the request
|
|
171
|
+
* @param {string} options.dataPath the path to get the data in the result object
|
|
172
|
+
* @returns {Promise<Object>} Resolves with an object containing the requestId, sessionId and streamEventName
|
|
173
|
+
*/
|
|
174
|
+
_request: function _request(options) {
|
|
175
|
+
var _this5 = this;
|
|
176
|
+
var resource = options.resource,
|
|
177
|
+
params = options.params,
|
|
178
|
+
dataPath = options.dataPath;
|
|
179
|
+
var timeout = this.config.requestTimeout;
|
|
180
|
+
var requestId = _uuid.default.v4();
|
|
181
|
+
var eventName = this._getResultEventName(requestId);
|
|
182
|
+
var streamEventName = this._getStreamEventName(requestId);
|
|
183
|
+
var concatenatedMessage = '';
|
|
184
|
+
|
|
185
|
+
// eslint-disable-next-line no-async-promise-executor
|
|
186
|
+
return new _promise.default(function (resolve, reject) {
|
|
187
|
+
var timer = new _commonTimers.Timer(function () {
|
|
188
|
+
_this5.stopListening(_this5, eventName);
|
|
189
|
+
_this5.trigger(streamEventName, {
|
|
190
|
+
requestId: requestId,
|
|
191
|
+
finished: true,
|
|
192
|
+
errorMessage: _constants.AI_ASSISTANT_ERRORS.AI_ASSISTANT_TIMEOUT,
|
|
193
|
+
errorCode: _constants.AI_ASSISTANT_ERROR_CODES.AI_ASSISTANT_TIMEOUT
|
|
194
|
+
});
|
|
195
|
+
}, timeout);
|
|
196
|
+
_this5.listenTo(_this5, eventName, /*#__PURE__*/function () {
|
|
197
|
+
var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(data) {
|
|
198
|
+
var resultData, errorMessage, errorCode, decryptedMessage, _decryptedMessage;
|
|
199
|
+
return _regenerator.default.wrap(function _callee2$(_context2) {
|
|
200
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
201
|
+
case 0:
|
|
202
|
+
timer.reset();
|
|
203
|
+
resultData = (0, _lodash.get)(data, dataPath, []);
|
|
204
|
+
errorMessage = (0, _lodash.get)(data, 'response.errorMessage');
|
|
205
|
+
errorCode = (0, _lodash.get)(data, 'response.errorCode');
|
|
206
|
+
if (!data.finished) {
|
|
207
|
+
_context2.next = 20;
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
// For finished messages, decrypt and emit the final complete message
|
|
211
|
+
timer.cancel();
|
|
212
|
+
_context2.prev = 6;
|
|
213
|
+
if (!(resultData !== null && resultData !== void 0 && resultData.value)) {
|
|
214
|
+
_context2.next = 11;
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
_context2.next = 10;
|
|
218
|
+
return _this5._decryptData(resultData);
|
|
219
|
+
case 10:
|
|
220
|
+
decryptedMessage = _context2.sent;
|
|
221
|
+
case 11:
|
|
222
|
+
// Emit the final message
|
|
223
|
+
_this5.trigger(streamEventName, {
|
|
224
|
+
message: decryptedMessage || '',
|
|
225
|
+
requestId: requestId,
|
|
226
|
+
finished: true,
|
|
227
|
+
errorMessage: errorMessage,
|
|
228
|
+
errorCode: errorCode
|
|
229
|
+
});
|
|
230
|
+
_this5.stopListening(_this5, eventName);
|
|
231
|
+
_context2.next = 18;
|
|
232
|
+
break;
|
|
233
|
+
case 15:
|
|
234
|
+
_context2.prev = 15;
|
|
235
|
+
_context2.t0 = _context2["catch"](6);
|
|
236
|
+
_this5.trigger(streamEventName, {
|
|
237
|
+
message: concatenatedMessage,
|
|
238
|
+
requestId: requestId,
|
|
239
|
+
finished: true,
|
|
240
|
+
errorMessage: errorMessage || _context2.t0.message,
|
|
241
|
+
errorCode: errorCode
|
|
242
|
+
});
|
|
243
|
+
case 18:
|
|
244
|
+
_context2.next = 33;
|
|
245
|
+
break;
|
|
246
|
+
case 20:
|
|
247
|
+
_context2.prev = 20;
|
|
248
|
+
_decryptedMessage = '';
|
|
249
|
+
if (!(resultData !== null && resultData !== void 0 && resultData.value)) {
|
|
250
|
+
_context2.next = 26;
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
_context2.next = 25;
|
|
254
|
+
return _this5._decryptData(resultData);
|
|
255
|
+
case 25:
|
|
256
|
+
_decryptedMessage = _context2.sent;
|
|
257
|
+
case 26:
|
|
258
|
+
concatenatedMessage += _decryptedMessage;
|
|
259
|
+
|
|
260
|
+
// Emit the concatenated message so far
|
|
261
|
+
_this5.trigger(streamEventName, {
|
|
262
|
+
message: concatenatedMessage,
|
|
263
|
+
requestId: requestId,
|
|
264
|
+
finished: false,
|
|
265
|
+
errorMessage: errorMessage,
|
|
266
|
+
errorCode: errorCode
|
|
267
|
+
});
|
|
268
|
+
_context2.next = 33;
|
|
269
|
+
break;
|
|
270
|
+
case 30:
|
|
271
|
+
_context2.prev = 30;
|
|
272
|
+
_context2.t1 = _context2["catch"](20);
|
|
273
|
+
// If decryption fails, we still want to continue listening for more messages
|
|
274
|
+
_this5.trigger(streamEventName, {
|
|
275
|
+
message: concatenatedMessage,
|
|
276
|
+
requestId: requestId,
|
|
277
|
+
finished: false,
|
|
278
|
+
errorMessage: errorMessage || _context2.t1.message,
|
|
279
|
+
errorCode: errorCode
|
|
280
|
+
});
|
|
281
|
+
case 33:
|
|
282
|
+
case "end":
|
|
283
|
+
return _context2.stop();
|
|
284
|
+
}
|
|
285
|
+
}, _callee2, null, [[6, 15], [20, 30]]);
|
|
286
|
+
}));
|
|
287
|
+
return function (_x) {
|
|
288
|
+
return _ref2.apply(this, arguments);
|
|
289
|
+
};
|
|
290
|
+
}());
|
|
291
|
+
_this5.webex.request({
|
|
292
|
+
service: _constants.AI_ASSISTANT_SERVICE_NAME,
|
|
293
|
+
resource: resource,
|
|
294
|
+
method: 'POST',
|
|
295
|
+
contentType: 'application/json',
|
|
296
|
+
body: _objectSpread({
|
|
297
|
+
clientRequestId: requestId
|
|
298
|
+
}, params)
|
|
299
|
+
}).catch(function (error) {
|
|
300
|
+
reject(error);
|
|
301
|
+
}).then(function (_ref3) {
|
|
302
|
+
var body = _ref3.body;
|
|
303
|
+
var sessionId = body.sessionId;
|
|
304
|
+
resolve({
|
|
305
|
+
requestId: requestId,
|
|
306
|
+
sessionId: sessionId,
|
|
307
|
+
streamEventName: streamEventName
|
|
308
|
+
});
|
|
309
|
+
timer.start();
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
},
|
|
313
|
+
/**
|
|
314
|
+
* Common method to make AI assistant requests for meeting analysis
|
|
315
|
+
* @param {Object} options
|
|
316
|
+
* @param {string} options.contextResources array of context resources to include in the request
|
|
317
|
+
* @param {string} options.sessionId the session ID for subsequent requests, not required for the first request
|
|
318
|
+
* @param {string} options.encryptionKeyUrl the encryption key URL for this meeting summary
|
|
319
|
+
* @param {string} options.contentType the type of content ('action' or 'message')
|
|
320
|
+
* @param {string} options.contentValue the value to use (action name or message text)
|
|
321
|
+
* @param {Object} options.parameters optional parameters to include in the request (for action type only)
|
|
322
|
+
* @param {Object} options.assistant optional parameter to specify the assistant to use
|
|
323
|
+
* @param {Object} options.locale optional locale to use for the request, defaults to 'en_US'
|
|
324
|
+
* @returns {Promise<Object>} Resolves with an object containing the requestId, sessionId and streamEventName
|
|
325
|
+
*/
|
|
326
|
+
_makeMeetingRequest: function _makeMeetingRequest(options) {
|
|
327
|
+
var _this6 = this;
|
|
328
|
+
return (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3() {
|
|
329
|
+
var value, content;
|
|
330
|
+
return _regenerator.default.wrap(function _callee3$(_context3) {
|
|
331
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
332
|
+
case 0:
|
|
333
|
+
value = options.contentValue;
|
|
334
|
+
if (!(options.contentType === 'message')) {
|
|
335
|
+
_context3.next = 5;
|
|
336
|
+
break;
|
|
337
|
+
}
|
|
338
|
+
_context3.next = 4;
|
|
339
|
+
return _this6._encryptData({
|
|
340
|
+
text: options.contentValue,
|
|
341
|
+
encryptionKeyUrl: options.encryptionKeyUrl
|
|
342
|
+
});
|
|
343
|
+
case 4:
|
|
344
|
+
value = _context3.sent;
|
|
345
|
+
case 5:
|
|
346
|
+
content = {
|
|
347
|
+
context: {
|
|
348
|
+
resources: options.contextResources
|
|
349
|
+
},
|
|
350
|
+
encryptionKeyUrl: options.encryptionKeyUrl,
|
|
351
|
+
type: options.contentType,
|
|
352
|
+
value: value
|
|
353
|
+
};
|
|
354
|
+
if (options.contentType === 'action' && options.parameters) {
|
|
355
|
+
content.parameters = options.parameters;
|
|
356
|
+
}
|
|
357
|
+
return _context3.abrupt("return", _this6._request({
|
|
358
|
+
resource: options.sessionId ? "sessions/".concat(options.sessionId, "/messages") : 'sessions/messages',
|
|
359
|
+
dataPath: 'response.content',
|
|
360
|
+
params: _objectSpread({
|
|
361
|
+
async: 'chunked',
|
|
362
|
+
locale: options.locale || 'en_US',
|
|
363
|
+
content: content
|
|
364
|
+
}, options.assistant ? {
|
|
365
|
+
assistant: options.assistant
|
|
366
|
+
} : {})
|
|
367
|
+
}));
|
|
368
|
+
case 8:
|
|
369
|
+
case "end":
|
|
370
|
+
return _context3.stop();
|
|
371
|
+
}
|
|
372
|
+
}, _callee3);
|
|
373
|
+
}))();
|
|
374
|
+
},
|
|
375
|
+
/**
|
|
376
|
+
* Returns the summary of a meeting
|
|
377
|
+
* @param {Object} options
|
|
378
|
+
* @param {string} options.meetingInstanceId the meeting instance ID for the meeting from locus
|
|
379
|
+
* @param {string} options.meetingSite the name.webex.com site for the meeting
|
|
380
|
+
* @param {string} options.sessionId the session ID for subsequent requests, not required for the first request
|
|
381
|
+
* @param {string} options.encryptionKeyUrl the encryption key URL for this meeting summary
|
|
382
|
+
* @param {number} options.lastMinutes Optional number of minutes to summarize from the end of the meeting. If not included, summarizes from the start.
|
|
383
|
+
* @returns {Promise<Object>} Resolves with an object containing the requestId, sessionId and streamEventName
|
|
384
|
+
*/
|
|
385
|
+
summarizeMeeting: function summarizeMeeting(options) {
|
|
386
|
+
return this._makeMeetingRequest(_objectSpread(_objectSpread({}, options), {}, {
|
|
387
|
+
contentType: _constants.CONTENT_TYPES.ACTION,
|
|
388
|
+
contentValue: _constants.ACTION_TYPES.SUMMARIZE_FOR_ME,
|
|
389
|
+
contextResources: [{
|
|
390
|
+
id: options.meetingInstanceId,
|
|
391
|
+
type: _constants.CONTEXT_RESOURCE_TYPES.MEETING,
|
|
392
|
+
url: options.meetingSite
|
|
393
|
+
}]
|
|
394
|
+
}, options.lastMinutes ? {
|
|
395
|
+
parameters: {
|
|
396
|
+
lastMinutes: options.lastMinutes
|
|
397
|
+
}
|
|
398
|
+
} : {}));
|
|
399
|
+
},
|
|
400
|
+
/**
|
|
401
|
+
* Checks if the user's name was mentioned in a meeting
|
|
402
|
+
* @param {Object} options
|
|
403
|
+
* @param {string} options.meetingInstanceId the meeting instance ID for the meeting from locus
|
|
404
|
+
* @param {string} options.meetingSite the name.webex.com site for the meeting
|
|
405
|
+
* @param {string} options.sessionId the session ID for subsequent requests, not required for the first request
|
|
406
|
+
* @param {string} options.encryptionKeyUrl the encryption key URL for this meeting summary
|
|
407
|
+
* @returns {Promise<Object>} Resolves with an object containing the requestId, sessionId and streamEventName
|
|
408
|
+
*/
|
|
409
|
+
wasMyNameMentioned: function wasMyNameMentioned(options) {
|
|
410
|
+
return this._makeMeetingRequest(_objectSpread(_objectSpread({}, options), {}, {
|
|
411
|
+
contextResources: [{
|
|
412
|
+
id: options.meetingInstanceId,
|
|
413
|
+
type: _constants.CONTEXT_RESOURCE_TYPES.MEETING,
|
|
414
|
+
url: options.meetingSite
|
|
415
|
+
}],
|
|
416
|
+
contentType: _constants.CONTENT_TYPES.ACTION,
|
|
417
|
+
contentValue: _constants.ACTION_TYPES.WAS_MY_NAME_MENTIONED
|
|
418
|
+
}));
|
|
419
|
+
},
|
|
420
|
+
/**
|
|
421
|
+
* Returns all action items from a meeting
|
|
422
|
+
* @param {Object} options
|
|
423
|
+
* @param {string} options.meetingInstanceId the meeting instance ID for the meeting from locus
|
|
424
|
+
* @param {string} options.meetingSite the name.webex.com site for the meeting
|
|
425
|
+
* @param {string} options.sessionId the session ID for subsequent requests, not required for the first request
|
|
426
|
+
* @param {string} options.encryptionKeyUrl the encryption key URL for this meeting summary
|
|
427
|
+
* @returns {Promise<Object>} Resolves with an object containing the requestId, sessionId and streamEventName
|
|
428
|
+
*/
|
|
429
|
+
showAllActionItems: function showAllActionItems(options) {
|
|
430
|
+
return this._makeMeetingRequest(_objectSpread(_objectSpread({}, options), {}, {
|
|
431
|
+
contextResources: [{
|
|
432
|
+
id: options.meetingInstanceId,
|
|
433
|
+
type: _constants.CONTEXT_RESOURCE_TYPES.MEETING,
|
|
434
|
+
url: options.meetingSite
|
|
435
|
+
}],
|
|
436
|
+
contentType: _constants.CONTENT_TYPES.ACTION,
|
|
437
|
+
contentValue: _constants.ACTION_TYPES.SHOW_ALL_ACTION_ITEMS
|
|
438
|
+
}));
|
|
439
|
+
},
|
|
440
|
+
/**
|
|
441
|
+
* Helper method to encrypt text using the encryption key URL
|
|
442
|
+
* @param {Object} options
|
|
443
|
+
* @param {string} options.text the text to encrypt
|
|
444
|
+
* @param {string} options.encryptionKeyUrl the encryption key URL to use for encryption
|
|
445
|
+
* @returns {Promise<string>} returns a promise that resolves with the encrypted text
|
|
446
|
+
*/
|
|
447
|
+
_encryptData: function _encryptData(_ref4) {
|
|
448
|
+
var _this7 = this;
|
|
449
|
+
return (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee4() {
|
|
450
|
+
var text, encryptionKeyUrl, result;
|
|
451
|
+
return _regenerator.default.wrap(function _callee4$(_context4) {
|
|
452
|
+
while (1) switch (_context4.prev = _context4.next) {
|
|
453
|
+
case 0:
|
|
454
|
+
text = _ref4.text, encryptionKeyUrl = _ref4.encryptionKeyUrl;
|
|
455
|
+
_context4.next = 3;
|
|
456
|
+
return _this7.webex.internal.encryption.encryptText(encryptionKeyUrl, text);
|
|
457
|
+
case 3:
|
|
458
|
+
result = _context4.sent;
|
|
459
|
+
return _context4.abrupt("return", result);
|
|
460
|
+
case 5:
|
|
461
|
+
case "end":
|
|
462
|
+
return _context4.stop();
|
|
463
|
+
}
|
|
464
|
+
}, _callee4);
|
|
465
|
+
}))();
|
|
466
|
+
},
|
|
467
|
+
/**
|
|
468
|
+
* Ask any question about the meeting content
|
|
469
|
+
* @param {Object} options
|
|
470
|
+
* @param {string} options.meetingInstanceId the meeting instance ID for the meeting from locus
|
|
471
|
+
* @param {string} options.meetingSite the name.webex.com site for the meeting
|
|
472
|
+
* @param {string} options.sessionId the session ID for subsequent requests, not required for the first request
|
|
473
|
+
* @param {string} options.encryptionKeyUrl the encryption key URL for this meeting summary
|
|
474
|
+
* @param {string} options.question the question to ask about the meeting content
|
|
475
|
+
* @returns {Promise<Object>} Resolves with an object containing the requestId, sessionId and streamEventName
|
|
476
|
+
*/
|
|
477
|
+
askMeAnything: function askMeAnything(options) {
|
|
478
|
+
return this._makeMeetingRequest(_objectSpread(_objectSpread({}, options), {}, {
|
|
479
|
+
contextResources: [{
|
|
480
|
+
id: options.meetingInstanceId,
|
|
481
|
+
type: _constants.CONTEXT_RESOURCE_TYPES.MEETING,
|
|
482
|
+
url: options.meetingSite
|
|
483
|
+
}],
|
|
484
|
+
contentType: _constants.CONTENT_TYPES.MESSAGE,
|
|
485
|
+
contentValue: options.question
|
|
486
|
+
}));
|
|
487
|
+
},
|
|
488
|
+
version: "0.0.0-next.1"
|
|
489
|
+
});
|
|
490
|
+
var _default = exports.default = AIAssistant;
|
|
491
|
+
//# sourceMappingURL=ai-assistant.js.map
|