@webex/internal-plugin-llm 3.11.0 → 3.12.0-llmrefactor.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/dist/llm.js CHANGED
@@ -7,18 +7,21 @@ _Object$defineProperty(exports, "__esModule", {
7
7
  value: true
8
8
  });
9
9
  exports.default = exports.config = void 0;
10
- var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass"));
10
+ var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
11
+ var _regenerator = _interopRequireDefault(require("@babel/runtime-corejs2/regenerator"));
12
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/asyncToGenerator"));
11
13
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/classCallCheck"));
14
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass"));
12
15
  var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/possibleConstructorReturn"));
13
16
  var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/getPrototypeOf"));
17
+ var _get2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/get"));
14
18
  var _inherits2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/inherits"));
15
19
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty"));
16
20
  var _internalPluginMercury = _interopRequireDefault(require("@webex/internal-plugin-mercury"));
17
21
  var _constants = require("./constants");
18
22
  function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2.default)(o), (0, _possibleConstructorReturn2.default)(t, _isNativeReflectConstruct() ? _Reflect$construct(o, e || [], (0, _getPrototypeOf2.default)(t).constructor) : o.apply(t, e)); }
19
- function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(_Reflect$construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } /* eslint-disable consistent-return */
20
- // eslint-disable-next-line no-unused-vars
21
-
23
+ function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(_Reflect$construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
24
+ function _superPropGet(t, o, e, r) { var p = (0, _get2.default)((0, _getPrototypeOf2.default)(1 & r ? t.prototype : t), o, e); return 2 & r && "function" == typeof p ? function (t) { return p.apply(e, t); } : p; } /* eslint-disable consistent-return */
22
25
  var config = exports.config = {
23
26
  llm: {
24
27
  /**
@@ -51,7 +54,11 @@ var config = exports.config = {
51
54
  };
52
55
 
53
56
  /**
54
- * LLMChannel to provide socket connections
57
+ * LLMChannel — a single WebSocket connection to the LLM data channel.
58
+ *
59
+ * Created via `webex.internal.llm.createChannel()`. The caller owns the
60
+ * channel and is responsible for its lifecycle (connect, disconnect, cleanup).
61
+ * Multiple LLMChannels can exist simultaneously for different meetings.
55
62
  */
56
63
  var LLMChannel = exports.default = /*#__PURE__*/function (_ref) {
57
64
  function LLMChannel() {
@@ -62,49 +69,122 @@ var LLMChannel = exports.default = /*#__PURE__*/function (_ref) {
62
69
  }
63
70
  _this = _callSuper(this, LLMChannel, [].concat(args));
64
71
  (0, _defineProperty2.default)(_this, "namespace", _constants.LLM);
65
- /**
66
- * If the LLM plugin has been registered and listening
67
- * @instance
68
- * @type {Boolean}
69
- * @public
70
- */
71
72
  (0, _defineProperty2.default)(_this, "webSocketUrl", void 0);
72
73
  (0, _defineProperty2.default)(_this, "binding", void 0);
73
74
  (0, _defineProperty2.default)(_this, "locusUrl", void 0);
74
75
  (0, _defineProperty2.default)(_this, "datachannelUrl", void 0);
76
+ (0, _defineProperty2.default)(_this, "datachannelToken", void 0);
77
+ (0, _defineProperty2.default)(_this, "refreshHandler", void 0);
78
+ /** In-flight connection promise for deduplication. */
79
+ (0, _defineProperty2.default)(_this, "connectingPromise", void 0);
75
80
  /**
76
81
  * Register to the websocket
77
82
  * @param {string} llmSocketUrl
83
+ * @param {string} datachannelToken
78
84
  * @returns {Promise<void>}
79
85
  */
80
- (0, _defineProperty2.default)(_this, "register", function (llmSocketUrl) {
81
- return _this.request({
82
- method: 'POST',
83
- url: llmSocketUrl,
84
- body: {
85
- deviceUrl: _this.webex.internal.device.url
86
- }
87
- }).then(function (res) {
88
- _this.webSocketUrl = res.body.webSocketUrl;
89
- _this.binding = res.body.binding;
90
- }).catch(function (error) {
91
- _this.logger.error("Error connecting to websocket: ".concat(error));
92
- throw error;
93
- });
94
- });
86
+ (0, _defineProperty2.default)(_this, "register", /*#__PURE__*/function () {
87
+ var _ref2 = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee(llmSocketUrl, datachannelToken) {
88
+ var isDataChannelTokenEnabled;
89
+ return _regenerator.default.wrap(function (_context) {
90
+ while (1) switch (_context.prev = _context.next) {
91
+ case 0:
92
+ _context.next = 1;
93
+ return _this.isDataChannelTokenEnabled();
94
+ case 1:
95
+ isDataChannelTokenEnabled = _context.sent;
96
+ return _context.abrupt("return", _this.request({
97
+ method: 'POST',
98
+ url: llmSocketUrl,
99
+ body: {
100
+ deviceUrl: _this.webex.internal.device.url
101
+ },
102
+ headers: isDataChannelTokenEnabled && datachannelToken ? {
103
+ 'Data-Channel-Auth-Token': datachannelToken
104
+ } : {}
105
+ }).then(function (res) {
106
+ _this.webSocketUrl = res.body.webSocketUrl;
107
+ _this.binding = res.body.binding;
108
+ }).catch(function (error) {
109
+ _this.logger.error("Error connecting to websocket for : ".concat(error));
110
+ throw error;
111
+ }));
112
+ case 2:
113
+ case "end":
114
+ return _context.stop();
115
+ }
116
+ }, _callee);
117
+ }));
118
+ return function (_x, _x2) {
119
+ return _ref2.apply(this, arguments);
120
+ };
121
+ }());
95
122
  /**
96
- * Register and connect to the websocket
123
+ * Register and connect to the websocket.
124
+ * Handles deduplication: returns existing promise if connection in progress,
125
+ * or resolves immediately if already connected to the same URLs.
97
126
  * @param {string} locusUrl
98
127
  * @param {string} datachannelUrl
99
- * @returns {Promise<void>}
128
+ * @param {string} datachannelToken
129
+ * @returns {Promise<RegisterAndConnectTiming | void>}
100
130
  */
101
- (0, _defineProperty2.default)(_this, "registerAndConnect", function (locusUrl, datachannelUrl) {
102
- return _this.register(datachannelUrl).then(function () {
103
- if (!locusUrl || !datachannelUrl) return undefined;
104
- _this.locusUrl = locusUrl;
105
- _this.datachannelUrl = datachannelUrl;
106
- _this.connect(_this.webSocketUrl);
131
+ (0, _defineProperty2.default)(_this, "registerAndConnect", function (locusUrl, datachannelUrl, datachannelToken) {
132
+ // Deduplicate concurrent calls while a connection is in-flight
133
+ if (_this.connectingPromise) {
134
+ return _this.connectingPromise;
135
+ }
136
+
137
+ // If already connected to the exact same datachannel URL, avoid triggering
138
+ // a reconnect that would cause the server to replace with 4000 Replaced
139
+ if (_this.isConnected() && _this.datachannelUrl === datachannelUrl && _this.locusUrl === locusUrl) {
140
+ return _promise.default.resolve();
141
+ }
142
+ _this.locusUrl = locusUrl;
143
+ _this.datachannelUrl = datachannelUrl;
144
+ var registerStart = performance.now();
145
+ _this.connectingPromise = _this.register(datachannelUrl, datachannelToken).then(/*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee2() {
146
+ var clientLLMDatachannelResponseTime, isDataChannelTokenEnabled, connectUrl, connectStart, clientLLMWebSocketConnectTime, _t;
147
+ return _regenerator.default.wrap(function (_context2) {
148
+ while (1) switch (_context2.prev = _context2.next) {
149
+ case 0:
150
+ clientLLMDatachannelResponseTime = Math.round(performance.now() - registerStart);
151
+ _context2.next = 1;
152
+ return _this.isDataChannelTokenEnabled();
153
+ case 1:
154
+ isDataChannelTokenEnabled = _context2.sent;
155
+ connectUrl = isDataChannelTokenEnabled && _this.webSocketUrl ? LLMChannel.buildUrlWithAwareSubchannels(_this.webSocketUrl, _constants.AWARE_DATA_CHANNEL) : _this.webSocketUrl;
156
+ connectStart = performance.now();
157
+ _context2.prev = 2;
158
+ _context2.next = 3;
159
+ return _this.connect(connectUrl);
160
+ case 3:
161
+ _context2.next = 5;
162
+ break;
163
+ case 4:
164
+ _context2.prev = 4;
165
+ _t = _context2["catch"](2);
166
+ // register() succeeded; only connect() failed. Attach the measured datachannel time so
167
+ // callers don't misreport a websocket failure as a registration that never completed.
168
+ // @ts-ignore
169
+ _t.timing = {
170
+ clientLLMDatachannelResponseTime: clientLLMDatachannelResponseTime
171
+ };
172
+ throw _t;
173
+ case 5:
174
+ clientLLMWebSocketConnectTime = Math.round(performance.now() - connectStart);
175
+ return _context2.abrupt("return", {
176
+ clientLLMDatachannelResponseTime: clientLLMDatachannelResponseTime,
177
+ clientLLMWebSocketConnectTime: clientLLMWebSocketConnectTime
178
+ });
179
+ case 6:
180
+ case "end":
181
+ return _context2.stop();
182
+ }
183
+ }, _callee2, null, [[2, 4]]);
184
+ }))).finally(function () {
185
+ _this.connectingPromise = undefined;
107
186
  });
187
+ return _this.connectingPromise;
108
188
  });
109
189
  /**
110
190
  * Tells if LLM socket is connected
@@ -115,41 +195,193 @@ var LLMChannel = exports.default = /*#__PURE__*/function (_ref) {
115
195
  });
116
196
  /**
117
197
  * Tells if LLM socket is binding
118
- * @returns {string} binding
198
+ * @returns {string | undefined} binding
119
199
  */
120
200
  (0, _defineProperty2.default)(_this, "getBinding", function () {
121
201
  return _this.binding;
122
202
  });
123
203
  /**
124
204
  * Get Locus URL for the connection
125
- * @returns {string} locus Url
205
+ * @returns {string | undefined} locus Url
126
206
  */
127
207
  (0, _defineProperty2.default)(_this, "getLocusUrl", function () {
128
208
  return _this.locusUrl;
129
209
  });
130
210
  /**
131
211
  * Get data channel URL for the connection
132
- * @returns {string} data channel Url
212
+ * @returns {string | undefined} data channel Url
133
213
  */
134
214
  (0, _defineProperty2.default)(_this, "getDatachannelUrl", function () {
135
215
  return _this.datachannelUrl;
136
216
  });
137
217
  /**
138
- * Disconnects websocket connection
139
- * @param {{code: number, reason: string}} options - The disconnect option object with code and reason
140
- * @returns {Promise<void>}
218
+ * Get data channel token for this connection.
219
+ * @returns {string | undefined}
141
220
  */
142
- (0, _defineProperty2.default)(_this, "disconnectLLM", function (options) {
143
- return _this.disconnect(options).then(function () {
144
- _this.locusUrl = undefined;
145
- _this.datachannelUrl = undefined;
146
- _this.binding = undefined;
147
- _this.webSocketUrl = undefined;
148
- });
221
+ (0, _defineProperty2.default)(_this, "getDatachannelToken", function () {
222
+ return _this.datachannelToken;
223
+ });
224
+ /**
225
+ * Store the data channel token for this connection.
226
+ * @param {string} token
227
+ * @returns {void}
228
+ */
229
+ (0, _defineProperty2.default)(_this, "setDatachannelToken", function (token) {
230
+ _this.datachannelToken = token;
231
+ });
232
+ /**
233
+ * Clear the data channel token for this connection.
234
+ * @returns {void}
235
+ */
236
+ (0, _defineProperty2.default)(_this, "clearDatachannelToken", function () {
237
+ _this.datachannelToken = undefined;
238
+ });
239
+ /**
240
+ * Set the handler used to refresh the DataChannel token.
241
+ * @param {function} handler
242
+ * @returns {void}
243
+ */
244
+ (0, _defineProperty2.default)(_this, "setRefreshHandler", function (handler) {
245
+ _this.refreshHandler = handler;
149
246
  });
150
247
  return _this;
151
248
  }
152
249
  (0, _inherits2.default)(LLMChannel, _ref);
153
- return (0, _createClass2.default)(LLMChannel);
250
+ return (0, _createClass2.default)(LLMChannel, [{
251
+ key: "isConnecting",
252
+ value:
253
+ /**
254
+ * Check if a connection is currently in progress.
255
+ * @returns {boolean} True if connecting
256
+ */
257
+ function isConnecting() {
258
+ return !!this.connectingPromise;
259
+ }
260
+ }, {
261
+ key: "refreshDataChannelToken",
262
+ value: (
263
+ /**
264
+ * Refresh the data channel token using the injected handler.
265
+ * @returns {Promise<object | null>}
266
+ */
267
+ function () {
268
+ var _refreshDataChannelToken = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee3() {
269
+ var _t2;
270
+ return _regenerator.default.wrap(function (_context3) {
271
+ while (1) switch (_context3.prev = _context3.next) {
272
+ case 0:
273
+ if (this.refreshHandler) {
274
+ _context3.next = 1;
275
+ break;
276
+ }
277
+ this.logger.warn('llm#refreshDataChannelToken --> LLM refreshHandler is not set, skipping token refresh');
278
+ return _context3.abrupt("return", null);
279
+ case 1:
280
+ _context3.prev = 1;
281
+ _context3.next = 2;
282
+ return this.refreshHandler();
283
+ case 2:
284
+ return _context3.abrupt("return", _context3.sent);
285
+ case 3:
286
+ _context3.prev = 3;
287
+ _t2 = _context3["catch"](1);
288
+ this.logger.warn("llm#refreshDataChannelToken --> DataChannel token refresh failed: ".concat((_t2 === null || _t2 === void 0 ? void 0 : _t2.message) || _t2));
289
+ return _context3.abrupt("return", null);
290
+ case 4:
291
+ case "end":
292
+ return _context3.stop();
293
+ }
294
+ }, _callee3, this, [[1, 3]]);
295
+ }));
296
+ function refreshDataChannelToken() {
297
+ return _refreshDataChannelToken.apply(this, arguments);
298
+ }
299
+ return refreshDataChannelToken;
300
+ }()
301
+ /**
302
+ * Disconnects the WebSocket and clears all connection state.
303
+ * Overrides Mercury's disconnect to also clear LLM-specific state.
304
+ * @param {object} [options]
305
+ * @returns {Promise<void>}
306
+ */
307
+ )
308
+ }, {
309
+ key: "disconnect",
310
+ value: (function () {
311
+ var _disconnect = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee4(options) {
312
+ return _regenerator.default.wrap(function (_context4) {
313
+ while (1) switch (_context4.prev = _context4.next) {
314
+ case 0:
315
+ _context4.next = 1;
316
+ return _superPropGet(LLMChannel, "disconnect", this, 3)([options]);
317
+ case 1:
318
+ this.webSocketUrl = undefined;
319
+ this.binding = undefined;
320
+ this.locusUrl = undefined;
321
+ this.datachannelUrl = undefined;
322
+ this.datachannelToken = undefined;
323
+ this.refreshHandler = undefined;
324
+ this.emit('disconnected');
325
+ case 2:
326
+ case "end":
327
+ return _context4.stop();
328
+ }
329
+ }, _callee4, this);
330
+ }));
331
+ function disconnect(_x3) {
332
+ return _disconnect.apply(this, arguments);
333
+ }
334
+ return disconnect;
335
+ }()
336
+ /**
337
+ * Matches a request URL to a stored datachannel registration URL.
338
+ * Host can differ (e.g. rewritten by hostmap interceptor), so we first
339
+ * try full URL prefix and then fall back to pathname prefix.
340
+ * @param {string} requestUrl
341
+ * @param {string} registrationUrl
342
+ * @returns {boolean}
343
+ */
344
+ )
345
+ }, {
346
+ key: "isDataChannelTokenEnabled",
347
+ value:
348
+ /**
349
+ * Returns true if the data channel token feature flag is enabled.
350
+ * @returns {Promise<boolean>}
351
+ */
352
+ function isDataChannelTokenEnabled() {
353
+ // @ts-ignore
354
+ return this.webex.internal.feature.getFeature('developer', _constants.DATA_CHANNEL_WITH_JWT_TOKEN);
355
+ }
356
+
357
+ /**
358
+ * Builds a WebSocket URL with the `subscriptionAwareSubchannels` query parameter.
359
+ * @param {string} baseUrl
360
+ * @param {string[]} subchannels
361
+ * @returns {string}
362
+ */
363
+ }], [{
364
+ key: "matchesDatachannelRequestUrl",
365
+ value: function matchesDatachannelRequestUrl(requestUrl, registrationUrl) {
366
+ if (!requestUrl || !registrationUrl) {
367
+ return false;
368
+ }
369
+ if (requestUrl.startsWith(registrationUrl)) {
370
+ return true;
371
+ }
372
+ try {
373
+ var request = new URL(requestUrl);
374
+ var registration = new URL(registrationUrl);
375
+ return request.pathname.startsWith(registration.pathname);
376
+ } catch (error) {
377
+ return false;
378
+ }
379
+ }
380
+ }]);
154
381
  }(_internalPluginMercury.default);
382
+ (0, _defineProperty2.default)(LLMChannel, "buildUrlWithAwareSubchannels", function (baseUrl, subchannels) {
383
+ var urlObj = new URL(baseUrl);
384
+ urlObj.searchParams.set(_constants.SUBSCRIPTION_AWARE_SUBCHANNELS_PARAM, subchannels.join(','));
385
+ return urlObj.toString();
386
+ });
155
387
  //# sourceMappingURL=llm.js.map
package/dist/llm.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"names":["_internalPluginMercury","_interopRequireDefault","require","_constants","_callSuper","t","o","e","_getPrototypeOf2","default","_possibleConstructorReturn2","_isNativeReflectConstruct","_Reflect$construct","constructor","apply","Boolean","prototype","valueOf","call","config","exports","llm","pingInterval","process","env","MERCURY_PING_INTERVAL","pongTimeout","MERCURY_PONG_TIMEOUT","backoffTimeMax","MERCURY_BACKOFF_TIME_MAX","backoffTimeReset","MERCURY_BACKOFF_TIME_RESET","forceCloseDelay","MERCURY_FORCE_CLOSE_DELAY","LLMChannel","_ref","_this","_classCallCheck2","_len","arguments","length","args","Array","_key","concat","_defineProperty2","LLM","llmSocketUrl","request","method","url","body","deviceUrl","webex","internal","device","then","res","webSocketUrl","binding","catch","error","logger","locusUrl","datachannelUrl","register","undefined","connect","connected","options","disconnect","_inherits2","_createClass2","Mercury"],"sources":["llm.ts"],"sourcesContent":["/* eslint-disable consistent-return */\n\nimport Mercury from '@webex/internal-plugin-mercury';\n\nimport {LLM} from './constants';\n// eslint-disable-next-line no-unused-vars\nimport {ILLMChannel} from './llm.types';\n\nexport const config = {\n llm: {\n /**\n * Milliseconds between pings sent up the socket\n * @type {number}\n */\n pingInterval: process.env.MERCURY_PING_INTERVAL || 15000,\n /**\n * Milliseconds to wait for a pong before declaring the connection dead\n * @type {number}\n */\n pongTimeout: process.env.MERCURY_PONG_TIMEOUT || 14000,\n /**\n * Maximum milliseconds between connection attempts\n * @type {Number}\n */\n backoffTimeMax: process.env.MERCURY_BACKOFF_TIME_MAX || 32000,\n /**\n * Initial milliseconds between connection attempts\n * @type {Number}\n */\n backoffTimeReset: process.env.MERCURY_BACKOFF_TIME_RESET || 1000,\n /**\n * Milliseconds to wait for a close frame before declaring the socket dead and\n * discarding it\n * @type {[type]}\n */\n forceCloseDelay: process.env.MERCURY_FORCE_CLOSE_DELAY || 2000,\n },\n};\n\n/**\n * LLMChannel to provide socket connections\n */\nexport default class LLMChannel extends (Mercury as any) implements ILLMChannel {\n namespace = LLM;\n\n /**\n * If the LLM plugin has been registered and listening\n * @instance\n * @type {Boolean}\n * @public\n */\n\n private webSocketUrl?: string;\n\n private binding?: string;\n\n private locusUrl?: string;\n\n private datachannelUrl?: string;\n\n /**\n * Register to the websocket\n * @param {string} llmSocketUrl\n * @returns {Promise<void>}\n */\n private register = (llmSocketUrl: string): Promise<void> =>\n this.request({\n method: 'POST',\n url: llmSocketUrl,\n body: {deviceUrl: this.webex.internal.device.url},\n })\n .then((res: {body: {webSocketUrl: string; binding: string}}) => {\n this.webSocketUrl = res.body.webSocketUrl;\n this.binding = res.body.binding;\n })\n .catch((error: any) => {\n this.logger.error(`Error connecting to websocket: ${error}`);\n throw error;\n });\n\n /**\n * Register and connect to the websocket\n * @param {string} locusUrl\n * @param {string} datachannelUrl\n * @returns {Promise<void>}\n */\n public registerAndConnect = (locusUrl: string, datachannelUrl: string): Promise<void> =>\n this.register(datachannelUrl).then(() => {\n if (!locusUrl || !datachannelUrl) return undefined;\n this.locusUrl = locusUrl;\n this.datachannelUrl = datachannelUrl;\n this.connect(this.webSocketUrl);\n });\n\n /**\n * Tells if LLM socket is connected\n * @returns {boolean} connected\n */\n public isConnected = (): boolean => this.connected;\n\n /**\n * Tells if LLM socket is binding\n * @returns {string} binding\n */\n public getBinding = (): string => this.binding;\n\n /**\n * Get Locus URL for the connection\n * @returns {string} locus Url\n */\n public getLocusUrl = (): string => this.locusUrl;\n\n /**\n * Get data channel URL for the connection\n * @returns {string} data channel Url\n */\n public getDatachannelUrl = (): string => this.datachannelUrl;\n\n /**\n * Disconnects websocket connection\n * @param {{code: number, reason: string}} options - The disconnect option object with code and reason\n * @returns {Promise<void>}\n */\n public disconnectLLM = (options: object): Promise<void> =>\n this.disconnect(options).then(() => {\n this.locusUrl = undefined;\n this.datachannelUrl = undefined;\n this.binding = undefined;\n this.webSocketUrl = undefined;\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;AAEA,IAAAA,sBAAA,GAAAC,sBAAA,CAAAC,OAAA;AAEA,IAAAC,UAAA,GAAAD,OAAA;AAAgC,SAAAE,WAAAC,CAAA,EAAAC,CAAA,EAAAC,CAAA,WAAAD,CAAA,OAAAE,gBAAA,CAAAC,OAAA,EAAAH,CAAA,OAAAI,2BAAA,CAAAD,OAAA,EAAAJ,CAAA,EAAAM,yBAAA,KAAAC,kBAAA,CAAAN,CAAA,EAAAC,CAAA,YAAAC,gBAAA,CAAAC,OAAA,EAAAJ,CAAA,EAAAQ,WAAA,IAAAP,CAAA,CAAAQ,KAAA,CAAAT,CAAA,EAAAE,CAAA;AAAA,SAAAI,0BAAA,cAAAN,CAAA,IAAAU,OAAA,CAAAC,SAAA,CAAAC,OAAA,CAAAC,IAAA,CAAAN,kBAAA,CAAAG,OAAA,iCAAAV,CAAA,aAAAM,yBAAA,YAAAA,0BAAA,aAAAN,CAAA,UAJhC;AAKA;;AAGO,IAAMc,MAAM,GAAAC,OAAA,CAAAD,MAAA,GAAG;EACpBE,GAAG,EAAE;IACH;AACJ;AACA;AACA;IACIC,YAAY,EAAEC,OAAO,CAACC,GAAG,CAACC,qBAAqB,IAAI,KAAK;IACxD;AACJ;AACA;AACA;IACIC,WAAW,EAAEH,OAAO,CAACC,GAAG,CAACG,oBAAoB,IAAI,KAAK;IACtD;AACJ;AACA;AACA;IACIC,cAAc,EAAEL,OAAO,CAACC,GAAG,CAACK,wBAAwB,IAAI,KAAK;IAC7D;AACJ;AACA;AACA;IACIC,gBAAgB,EAAEP,OAAO,CAACC,GAAG,CAACO,0BAA0B,IAAI,IAAI;IAChE;AACJ;AACA;AACA;AACA;IACIC,eAAe,EAAET,OAAO,CAACC,GAAG,CAACS,yBAAyB,IAAI;EAC5D;AACF,CAAC;;AAED;AACA;AACA;AAFA,IAGqBC,UAAU,GAAAd,OAAA,CAAAX,OAAA,0BAAA0B,IAAA;EAAA,SAAAD,WAAA;IAAA,IAAAE,KAAA;IAAA,IAAAC,gBAAA,CAAA5B,OAAA,QAAAyB,UAAA;IAAA,SAAAI,IAAA,GAAAC,SAAA,CAAAC,MAAA,EAAAC,IAAA,OAAAC,KAAA,CAAAJ,IAAA,GAAAK,IAAA,MAAAA,IAAA,GAAAL,IAAA,EAAAK,IAAA;MAAAF,IAAA,CAAAE,IAAA,IAAAJ,SAAA,CAAAI,IAAA;IAAA;IAAAP,KAAA,GAAAhC,UAAA,OAAA8B,UAAA,KAAAU,MAAA,CAAAH,IAAA;IAAA,IAAAI,gBAAA,CAAApC,OAAA,EAAA2B,KAAA,eACjBU,cAAG;IAEf;AACF;AACA;AACA;AACA;AACA;IALE,IAAAD,gBAAA,CAAApC,OAAA,EAAA2B,KAAA;IAAA,IAAAS,gBAAA,CAAApC,OAAA,EAAA2B,KAAA;IAAA,IAAAS,gBAAA,CAAApC,OAAA,EAAA2B,KAAA;IAAA,IAAAS,gBAAA,CAAApC,OAAA,EAAA2B,KAAA;IAeA;AACF;AACA;AACA;AACA;IAJE,IAAAS,gBAAA,CAAApC,OAAA,EAAA2B,KAAA,cAKmB,UAACW,YAAoB;MAAA,OACtCX,KAAA,CAAKY,OAAO,CAAC;QACXC,MAAM,EAAE,MAAM;QACdC,GAAG,EAAEH,YAAY;QACjBI,IAAI,EAAE;UAACC,SAAS,EAAEhB,KAAA,CAAKiB,KAAK,CAACC,QAAQ,CAACC,MAAM,CAACL;QAAG;MAClD,CAAC,CAAC,CACCM,IAAI,CAAC,UAACC,GAAoD,EAAK;QAC9DrB,KAAA,CAAKsB,YAAY,GAAGD,GAAG,CAACN,IAAI,CAACO,YAAY;QACzCtB,KAAA,CAAKuB,OAAO,GAAGF,GAAG,CAACN,IAAI,CAACQ,OAAO;MACjC,CAAC,CAAC,CACDC,KAAK,CAAC,UAACC,KAAU,EAAK;QACrBzB,KAAA,CAAK0B,MAAM,CAACD,KAAK,mCAAAjB,MAAA,CAAmCiB,KAAK,CAAE,CAAC;QAC5D,MAAMA,KAAK;MACb,CAAC,CAAC;IAAA;IAEN;AACF;AACA;AACA;AACA;AACA;IALE,IAAAhB,gBAAA,CAAApC,OAAA,EAAA2B,KAAA,wBAM4B,UAAC2B,QAAgB,EAAEC,cAAsB;MAAA,OACnE5B,KAAA,CAAK6B,QAAQ,CAACD,cAAc,CAAC,CAACR,IAAI,CAAC,YAAM;QACvC,IAAI,CAACO,QAAQ,IAAI,CAACC,cAAc,EAAE,OAAOE,SAAS;QAClD9B,KAAA,CAAK2B,QAAQ,GAAGA,QAAQ;QACxB3B,KAAA,CAAK4B,cAAc,GAAGA,cAAc;QACpC5B,KAAA,CAAK+B,OAAO,CAAC/B,KAAA,CAAKsB,YAAY,CAAC;MACjC,CAAC,CAAC;IAAA;IAEJ;AACF;AACA;AACA;IAHE,IAAAb,gBAAA,CAAApC,OAAA,EAAA2B,KAAA,iBAIqB;MAAA,OAAeA,KAAA,CAAKgC,SAAS;IAAA;IAElD;AACF;AACA;AACA;IAHE,IAAAvB,gBAAA,CAAApC,OAAA,EAAA2B,KAAA,gBAIoB;MAAA,OAAcA,KAAA,CAAKuB,OAAO;IAAA;IAE9C;AACF;AACA;AACA;IAHE,IAAAd,gBAAA,CAAApC,OAAA,EAAA2B,KAAA,iBAIqB;MAAA,OAAcA,KAAA,CAAK2B,QAAQ;IAAA;IAEhD;AACF;AACA;AACA;IAHE,IAAAlB,gBAAA,CAAApC,OAAA,EAAA2B,KAAA,uBAI2B;MAAA,OAAcA,KAAA,CAAK4B,cAAc;IAAA;IAE5D;AACF;AACA;AACA;AACA;IAJE,IAAAnB,gBAAA,CAAApC,OAAA,EAAA2B,KAAA,mBAKuB,UAACiC,OAAe;MAAA,OACrCjC,KAAA,CAAKkC,UAAU,CAACD,OAAO,CAAC,CAACb,IAAI,CAAC,YAAM;QAClCpB,KAAA,CAAK2B,QAAQ,GAAGG,SAAS;QACzB9B,KAAA,CAAK4B,cAAc,GAAGE,SAAS;QAC/B9B,KAAA,CAAKuB,OAAO,GAAGO,SAAS;QACxB9B,KAAA,CAAKsB,YAAY,GAAGQ,SAAS;MAC/B,CAAC,CAAC;IAAA;IAAA,OAAA9B,KAAA;EAAA;EAAA,IAAAmC,UAAA,CAAA9D,OAAA,EAAAyB,UAAA,EAAAC,IAAA;EAAA,WAAAqC,aAAA,CAAA/D,OAAA,EAAAyB,UAAA;AAAA,EAvFmCuC,8BAAO","ignoreList":[]}
1
+ {"version":3,"names":["_internalPluginMercury","_interopRequireDefault","require","_constants","_callSuper","t","o","e","_getPrototypeOf2","default","_possibleConstructorReturn2","_isNativeReflectConstruct","_Reflect$construct","constructor","apply","Boolean","prototype","valueOf","call","_superPropGet","r","p","_get2","config","exports","llm","pingInterval","process","env","MERCURY_PING_INTERVAL","pongTimeout","MERCURY_PONG_TIMEOUT","backoffTimeMax","MERCURY_BACKOFF_TIME_MAX","backoffTimeReset","MERCURY_BACKOFF_TIME_RESET","forceCloseDelay","MERCURY_FORCE_CLOSE_DELAY","LLMChannel","_ref","_this","_classCallCheck2","_len","arguments","length","args","Array","_key","concat","_defineProperty2","LLM","_ref2","_asyncToGenerator2","_regenerator","mark","_callee","llmSocketUrl","datachannelToken","isDataChannelTokenEnabled","wrap","_context","prev","next","sent","abrupt","request","method","url","body","deviceUrl","webex","internal","device","headers","then","res","webSocketUrl","binding","catch","error","logger","stop","_x","_x2","locusUrl","datachannelUrl","connectingPromise","isConnected","_promise","resolve","registerStart","performance","now","register","_callee2","clientLLMDatachannelResponseTime","connectUrl","connectStart","clientLLMWebSocketConnectTime","_t","_context2","Math","round","buildUrlWithAwareSubchannels","AWARE_DATA_CHANNEL","connect","timing","finally","undefined","connected","token","handler","refreshHandler","_inherits2","_createClass2","key","value","isConnecting","_refreshDataChannelToken","_callee3","_t2","_context3","warn","message","refreshDataChannelToken","_disconnect","_callee4","options","_context4","emit","disconnect","_x3","feature","getFeature","DATA_CHANNEL_WITH_JWT_TOKEN","matchesDatachannelRequestUrl","requestUrl","registrationUrl","startsWith","URL","registration","pathname","Mercury","baseUrl","subchannels","urlObj","searchParams","set","SUBSCRIPTION_AWARE_SUBCHANNELS_PARAM","join","toString"],"sources":["llm.ts"],"sourcesContent":["/* eslint-disable consistent-return */\nimport Mercury from '@webex/internal-plugin-mercury';\n\nimport {\n LLM,\n DATA_CHANNEL_WITH_JWT_TOKEN,\n AWARE_DATA_CHANNEL,\n SUBSCRIPTION_AWARE_SUBCHANNELS_PARAM,\n} from './constants';\nimport {ILLMChannel, DataChannelTokenType, RegisterAndConnectTiming} from './llm.types';\n\nexport const config = {\n llm: {\n /**\n * Milliseconds between pings sent up the socket\n * @type {number}\n */\n pingInterval: process.env.MERCURY_PING_INTERVAL || 15000,\n /**\n * Milliseconds to wait for a pong before declaring the connection dead\n * @type {number}\n */\n pongTimeout: process.env.MERCURY_PONG_TIMEOUT || 14000,\n /**\n * Maximum milliseconds between connection attempts\n * @type {Number}\n */\n backoffTimeMax: process.env.MERCURY_BACKOFF_TIME_MAX || 32000,\n /**\n * Initial milliseconds between connection attempts\n * @type {Number}\n */\n backoffTimeReset: process.env.MERCURY_BACKOFF_TIME_RESET || 1000,\n /**\n * Milliseconds to wait for a close frame before declaring the socket dead and\n * discarding it\n * @type {[type]}\n */\n forceCloseDelay: process.env.MERCURY_FORCE_CLOSE_DELAY || 2000,\n },\n};\n\n/**\n * LLMChannel — a single WebSocket connection to the LLM data channel.\n *\n * Created via `webex.internal.llm.createChannel()`. The caller owns the\n * channel and is responsible for its lifecycle (connect, disconnect, cleanup).\n * Multiple LLMChannels can exist simultaneously for different meetings.\n */\nexport default class LLMChannel extends (Mercury as any) implements ILLMChannel {\n namespace = LLM;\n\n private webSocketUrl?: string;\n private binding?: string;\n private locusUrl?: string;\n private datachannelUrl?: string;\n private datachannelToken?: string;\n private refreshHandler?: () => Promise<{\n body: {datachannelToken: string; datachannelTokenType: DataChannelTokenType};\n }>;\n\n /** In-flight connection promise for deduplication. */\n private connectingPromise?: Promise<RegisterAndConnectTiming | void>;\n\n /**\n * Check if a connection is currently in progress.\n * @returns {boolean} True if connecting\n */\n public isConnecting(): boolean {\n return !!this.connectingPromise;\n }\n\n /**\n * Register to the websocket\n * @param {string} llmSocketUrl\n * @param {string} datachannelToken\n * @returns {Promise<void>}\n */\n private register = async (llmSocketUrl: string, datachannelToken?: string): Promise<void> => {\n const isDataChannelTokenEnabled = await this.isDataChannelTokenEnabled();\n\n return this.request({\n method: 'POST',\n url: llmSocketUrl,\n body: {deviceUrl: this.webex.internal.device.url},\n headers:\n isDataChannelTokenEnabled && datachannelToken\n ? {'Data-Channel-Auth-Token': datachannelToken}\n : {},\n })\n .then((res: {body: {webSocketUrl: string; binding: string}}) => {\n this.webSocketUrl = res.body.webSocketUrl;\n this.binding = res.body.binding;\n })\n .catch((error: any) => {\n this.logger.error(`Error connecting to websocket for : ${error}`);\n throw error;\n });\n };\n\n /**\n * Register and connect to the websocket.\n * Handles deduplication: returns existing promise if connection in progress,\n * or resolves immediately if already connected to the same URLs.\n * @param {string} locusUrl\n * @param {string} datachannelUrl\n * @param {string} datachannelToken\n * @returns {Promise<RegisterAndConnectTiming | void>}\n */\n public registerAndConnect = (\n locusUrl: string,\n datachannelUrl: string,\n datachannelToken?: string\n ): Promise<RegisterAndConnectTiming | void> => {\n // Deduplicate concurrent calls while a connection is in-flight\n if (this.connectingPromise) {\n return this.connectingPromise;\n }\n\n // If already connected to the exact same datachannel URL, avoid triggering\n // a reconnect that would cause the server to replace with 4000 Replaced\n if (\n this.isConnected() &&\n this.datachannelUrl === datachannelUrl &&\n this.locusUrl === locusUrl\n ) {\n return Promise.resolve();\n }\n\n this.locusUrl = locusUrl;\n this.datachannelUrl = datachannelUrl;\n const registerStart = performance.now();\n\n this.connectingPromise = this.register(datachannelUrl, datachannelToken)\n .then(async () => {\n const clientLLMDatachannelResponseTime = Math.round(performance.now() - registerStart);\n const isDataChannelTokenEnabled = await this.isDataChannelTokenEnabled();\n\n const connectUrl =\n isDataChannelTokenEnabled && this.webSocketUrl\n ? LLMChannel.buildUrlWithAwareSubchannels(this.webSocketUrl, AWARE_DATA_CHANNEL)\n : this.webSocketUrl;\n\n const connectStart = performance.now();\n\n try {\n await this.connect(connectUrl);\n } catch (error) {\n // register() succeeded; only connect() failed. Attach the measured datachannel time so\n // callers don't misreport a websocket failure as a registration that never completed.\n // @ts-ignore\n error.timing = {clientLLMDatachannelResponseTime};\n throw error;\n }\n\n const clientLLMWebSocketConnectTime = Math.round(performance.now() - connectStart);\n\n return {clientLLMDatachannelResponseTime, clientLLMWebSocketConnectTime};\n })\n .finally(() => {\n this.connectingPromise = undefined;\n });\n\n return this.connectingPromise;\n };\n\n /**\n * Tells if LLM socket is connected\n * @returns {boolean} connected\n */\n public isConnected = (): boolean => this.connected;\n\n /**\n * Tells if LLM socket is binding\n * @returns {string | undefined} binding\n */\n public getBinding = (): string | undefined => this.binding;\n\n /**\n * Get Locus URL for the connection\n * @returns {string | undefined} locus Url\n */\n public getLocusUrl = (): string | undefined => this.locusUrl;\n\n /**\n * Get data channel URL for the connection\n * @returns {string | undefined} data channel Url\n */\n public getDatachannelUrl = (): string | undefined => this.datachannelUrl;\n\n /**\n * Get data channel token for this connection.\n * @returns {string | undefined}\n */\n public getDatachannelToken = (): string | undefined => this.datachannelToken;\n\n /**\n * Store the data channel token for this connection.\n * @param {string} token\n * @returns {void}\n */\n public setDatachannelToken = (token: string): void => {\n this.datachannelToken = token;\n };\n\n /**\n * Clear the data channel token for this connection.\n * @returns {void}\n */\n public clearDatachannelToken = (): void => {\n this.datachannelToken = undefined;\n };\n\n /**\n * Set the handler used to refresh the DataChannel token.\n * @param {function} handler\n * @returns {void}\n */\n public setRefreshHandler = (\n handler: () => Promise<{\n body: {datachannelToken: string; datachannelTokenType: DataChannelTokenType};\n }>\n ): void => {\n this.refreshHandler = handler;\n };\n\n /**\n * Refresh the data channel token using the injected handler.\n * @returns {Promise<object | null>}\n */\n public async refreshDataChannelToken() {\n if (!this.refreshHandler) {\n this.logger.warn(\n 'llm#refreshDataChannelToken --> LLM refreshHandler is not set, skipping token refresh'\n );\n\n return null;\n }\n\n try {\n return await this.refreshHandler();\n } catch (error: any) {\n this.logger.warn(\n `llm#refreshDataChannelToken --> DataChannel token refresh failed: ${\n error?.message || error\n }`\n );\n\n return null;\n }\n }\n\n /**\n * Disconnects the WebSocket and clears all connection state.\n * Overrides Mercury's disconnect to also clear LLM-specific state.\n * @param {object} [options]\n * @returns {Promise<void>}\n */\n public async disconnect(options?: {code: number; reason: string}): Promise<void> {\n await super.disconnect(options);\n this.webSocketUrl = undefined;\n this.binding = undefined;\n this.locusUrl = undefined;\n this.datachannelUrl = undefined;\n this.datachannelToken = undefined;\n this.refreshHandler = undefined;\n this.emit('disconnected');\n }\n\n /**\n * Matches a request URL to a stored datachannel registration URL.\n * Host can differ (e.g. rewritten by hostmap interceptor), so we first\n * try full URL prefix and then fall back to pathname prefix.\n * @param {string} requestUrl\n * @param {string} registrationUrl\n * @returns {boolean}\n */\n public static matchesDatachannelRequestUrl(requestUrl: string, registrationUrl: string): boolean {\n if (!requestUrl || !registrationUrl) {\n return false;\n }\n\n if (requestUrl.startsWith(registrationUrl)) {\n return true;\n }\n\n try {\n const request = new URL(requestUrl);\n const registration = new URL(registrationUrl);\n\n return request.pathname.startsWith(registration.pathname);\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Returns true if the data channel token feature flag is enabled.\n * @returns {Promise<boolean>}\n */\n public isDataChannelTokenEnabled(): Promise<boolean> {\n // @ts-ignore\n return this.webex.internal.feature.getFeature('developer', DATA_CHANNEL_WITH_JWT_TOKEN);\n }\n\n /**\n * Builds a WebSocket URL with the `subscriptionAwareSubchannels` query parameter.\n * @param {string} baseUrl\n * @param {string[]} subchannels\n * @returns {string}\n */\n public static buildUrlWithAwareSubchannels = (baseUrl: string, subchannels: string[]) => {\n const urlObj = new URL(baseUrl);\n urlObj.searchParams.set(SUBSCRIPTION_AWARE_SUBCHANNELS_PARAM, subchannels.join(','));\n\n return urlObj.toString();\n };\n}\n"],"mappings":"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","ignoreList":[]}
package/dist/llm.types.js CHANGED
@@ -4,4 +4,22 @@ var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/defi
4
4
  _Object$defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
+ exports.DataChannelTokenType = void 0;
8
+ var DataChannelTokenType = exports.DataChannelTokenType = /*#__PURE__*/function (DataChannelTokenType) {
9
+ DataChannelTokenType["Default"] = "llm-default-session";
10
+ DataChannelTokenType["PracticeSession"] = "llm-practice-session";
11
+ return DataChannelTokenType;
12
+ }({});
13
+ /**
14
+ * Latencies (in milliseconds) captured during register + websocket connect.
15
+ */
16
+ /**
17
+ * ILLMChannel — interface for a single LLM WebSocket connection.
18
+ * Created via `webex.internal.llm.createChannel()`.
19
+ */
20
+ /**
21
+ * ILLMPlugin — interface for the LLM plugin factory.
22
+ * Accessed via `webex.internal.llm`.
23
+ */
24
+ // eslint-disable-next-line import/prefer-default-export
7
25
  //# sourceMappingURL=llm.types.js.map
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["llm.types.ts"],"sourcesContent":["interface ILLMChannel {\n registerAndConnect: (locusUrl: string, datachannelUrl: string) => Promise<void>;\n isConnected: () => boolean;\n getBinding: () => string;\n getLocusUrl: () => string;\n disconnectLLM: (options: {code: number; reason: string}) => Promise<void>;\n}\n// eslint-disable-next-line import/prefer-default-export\nexport type {ILLMChannel};\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"names":["DataChannelTokenType","exports"],"sources":["llm.types.ts"],"sourcesContent":["export enum DataChannelTokenType {\n Default = 'llm-default-session',\n PracticeSession = 'llm-practice-session',\n}\n\ntype DataChannelTokenKey = DataChannelTokenType | string;\n\n/**\n * Latencies (in milliseconds) captured during register + websocket connect.\n */\ntype RegisterAndConnectTiming = {\n clientLLMDatachannelResponseTime?: number;\n clientLLMWebSocketConnectTime?: number;\n};\n\n/**\n * ILLMChannel — interface for a single LLM WebSocket connection.\n * Created via `webex.internal.llm.createChannel()`.\n */\ninterface ILLMChannel {\n /** Register with the server and connect the WebSocket. */\n registerAndConnect: (\n locusUrl: string,\n datachannelUrl: string,\n datachannelToken?: string\n ) => Promise<void>;\n\n /** Returns true if the WebSocket is connected. */\n isConnected: () => boolean;\n\n /** Returns true if a connection is currently in progress. */\n isConnecting: () => boolean;\n\n /** Get the underlying WebSocket. */\n getSocket: () => any;\n\n /** Get the binding ID for this connection. */\n getBinding: () => string | undefined;\n\n /** Get the Locus URL associated with this connection. */\n getLocusUrl: () => string | undefined;\n\n /** Get the datachannel URL for this connection. */\n getDatachannelUrl: () => string | undefined;\n\n /** Get the stored datachannel token. */\n getDatachannelToken: () => string | undefined;\n\n /** Store a datachannel token for this connection. */\n setDatachannelToken: (datachannelToken: string) => void;\n\n /** Clear the stored datachannel token. */\n clearDatachannelToken: () => void;\n\n /** Set the handler used to refresh the datachannel token. */\n setRefreshHandler: (\n handler: () => Promise<{\n body: {datachannelToken: string; datachannelTokenType: DataChannelTokenType};\n }>\n ) => void;\n\n /** Refresh the datachannel token using the injected handler. */\n refreshDataChannelToken: () => Promise<{\n body: {datachannelToken: string; datachannelTokenType: DataChannelTokenType};\n } | null>;\n\n /** Disconnect the WebSocket and clean up state. */\n disconnect: (options?: {code: number; reason: string}) => Promise<void>;\n\n /** Check if the datachannel token feature flag is enabled. */\n isDataChannelTokenEnabled: () => Promise<boolean>;\n}\n\n/**\n * ILLMPlugin — interface for the LLM plugin factory.\n * Accessed via `webex.internal.llm`.\n */\ninterface ILLMPlugin {\n /** Create a new LLM channel instance. */\n createChannel: () => ILLMChannel;\n\n /** Check if the datachannel token feature flag is enabled globally. */\n isDataChannelTokenEnabled: () => Promise<boolean>;\n\n /** Find a channel by matching a request URL to its datachannel URL. */\n getChannelByDatachannelUrl: (url: string) => ILLMChannel | undefined;\n\n /** Get all active channels. */\n getAllChannels: () => Set<ILLMChannel>;\n\n /** Disconnect all active channels. */\n disconnectAllChannels: (options?: {code: number; reason: string}) => Promise<void>;\n}\n\n// eslint-disable-next-line import/prefer-default-export\nexport type {ILLMChannel, ILLMPlugin, DataChannelTokenKey, RegisterAndConnectTiming};\n"],"mappings":";;;;;;;IAAYA,oBAAoB,GAAAC,OAAA,CAAAD,oBAAA,0BAApBA,oBAAoB;EAApBA,oBAAoB;EAApBA,oBAAoB;EAAA,OAApBA,oBAAoB;AAAA;AAOhC;AACA;AACA;AAMA;AACA;AACA;AACA;AAuDA;AACA;AACA;AACA;AAkBA","ignoreList":[]}
package/package.json CHANGED
@@ -13,7 +13,7 @@
13
13
  "node": ">=18"
14
14
  },
15
15
  "dependencies": {
16
- "@webex/internal-plugin-mercury": "3.11.0"
16
+ "@webex/internal-plugin-mercury": "3.12.0-llmrefactor.1"
17
17
  },
18
18
  "browserify": {
19
19
  "transform": [
@@ -27,10 +27,10 @@
27
27
  "@webex/eslint-config-legacy": "0.0.0",
28
28
  "@webex/jest-config-legacy": "0.0.0",
29
29
  "@webex/legacy-tools": "0.0.0",
30
- "@webex/test-helper-chai": "3.11.0",
31
- "@webex/test-helper-mocha": "3.11.0",
32
- "@webex/test-helper-mock-webex": "3.11.0",
33
- "@webex/test-helper-test-users": "3.11.0",
30
+ "@webex/test-helper-chai": "3.12.0-llmrefactor.1",
31
+ "@webex/test-helper-mocha": "3.12.0-llmrefactor.1",
32
+ "@webex/test-helper-mock-webex": "3.12.0-llmrefactor.1",
33
+ "@webex/test-helper-test-users": "3.12.0-llmrefactor.1",
34
34
  "eslint": "^8.24.0",
35
35
  "prettier": "^2.7.1",
36
36
  "sinon": "^9.2.4"
@@ -44,5 +44,5 @@
44
44
  "test:style": "eslint ./src/**/*.*",
45
45
  "test:unit": "webex-legacy-tools test --unit --runner jest"
46
46
  },
47
- "version": "3.11.0"
47
+ "version": "3.12.0-llmrefactor.1"
48
48
  }
package/src/constants.ts CHANGED
@@ -1,2 +1,15 @@
1
1
  // eslint-disable-next-line import/prefer-default-export
2
2
  export const LLM = 'llm';
3
+
4
+ export const LLM_DEFAULT_SESSION = 'llm-default-session';
5
+ export const LLM_PRACTICE_SESSION = 'llm-practice-session';
6
+
7
+ export const DATA_CHANNEL_WITH_JWT_TOKEN = 'data-channel-with-jwt-token';
8
+
9
+ export const SUBSCRIPTION_AWARE_SUBCHANNELS_PARAM = 'subscriptionAwareSubchannels';
10
+
11
+ export const DATA_CHNANEL_TYPE = {
12
+ TRANSCRIPTION: 'transcription',
13
+ };
14
+
15
+ export const AWARE_DATA_CHANNEL = [DATA_CHNANEL_TYPE.TRANSCRIPTION];
package/src/index.ts CHANGED
@@ -1,8 +1,18 @@
1
1
  import * as WebexCore from '@webex/webex-core';
2
- import LLMChannel, {config} from './llm';
2
+ import LLMPlugin, {config} from './llm-plugin';
3
+ import {DataChannelTokenType} from './llm.types';
3
4
 
4
- WebexCore.registerInternalPlugin('llm', LLMChannel, {
5
+ export type {RegisterAndConnectTiming} from './llm.types';
6
+
7
+ WebexCore.registerInternalPlugin('llm', LLMPlugin, {
5
8
  config,
9
+ onBeforeLogout() {
10
+ return this.disconnectAllChannels();
11
+ },
6
12
  });
7
13
 
14
+ export {DataChannelTokenType};
15
+ export {LLM_DEFAULT_SESSION, LLM_PRACTICE_SESSION} from './constants';
8
16
  export {default} from './llm';
17
+ export {default as LLMPlugin} from './llm-plugin';
18
+ export type {ILLMChannel, ILLMPlugin} from './llm.types';