@webex/internal-plugin-llm 3.11.0-next.7 → 3.11.0-next.8

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/constants.js CHANGED
@@ -4,7 +4,8 @@ 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.LLM = void 0;
7
+ exports.LLM = exports.DATA_CHANNEL_WITH_JWT_TOKEN = void 0;
8
8
  // eslint-disable-next-line import/prefer-default-export
9
9
  var LLM = exports.LLM = 'llm';
10
+ var DATA_CHANNEL_WITH_JWT_TOKEN = exports.DATA_CHANNEL_WITH_JWT_TOKEN = 'data-channel-with-jwt-token';
10
11
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["LLM","exports"],"sources":["constants.ts"],"sourcesContent":["// eslint-disable-next-line import/prefer-default-export\nexport const LLM = 'llm';\n"],"mappings":";;;;;;;AAAA;AACO,IAAMA,GAAG,GAAAC,OAAA,CAAAD,GAAA,GAAG,KAAK","ignoreList":[]}
1
+ {"version":3,"names":["LLM","exports","DATA_CHANNEL_WITH_JWT_TOKEN"],"sources":["constants.ts"],"sourcesContent":["// eslint-disable-next-line import/prefer-default-export\nexport const LLM = 'llm';\n\nexport const DATA_CHANNEL_WITH_JWT_TOKEN = 'data-channel-with-jwt-token';\n"],"mappings":";;;;;;;AAAA;AACO,IAAMA,GAAG,GAAAC,OAAA,CAAAD,GAAA,GAAG,KAAK;AAEjB,IAAME,2BAA2B,GAAAD,OAAA,CAAAC,2BAAA,GAAG,6BAA6B","ignoreList":[]}
package/dist/index.js CHANGED
@@ -7,6 +7,12 @@ var _Object$getOwnPropertyDescriptor = require("@babel/runtime-corejs2/core-js/o
7
7
  _Object$defineProperty(exports, "__esModule", {
8
8
  value: true
9
9
  });
10
+ _Object$defineProperty(exports, "DataChannelTokenType", {
11
+ enumerable: true,
12
+ get: function get() {
13
+ return _llm2.DataChannelTokenType;
14
+ }
15
+ });
10
16
  _Object$defineProperty(exports, "default", {
11
17
  enumerable: true,
12
18
  get: function get() {
@@ -15,6 +21,7 @@ _Object$defineProperty(exports, "default", {
15
21
  });
16
22
  var WebexCore = _interopRequireWildcard(require("@webex/webex-core"));
17
23
  var _llm = _interopRequireWildcard(require("./llm"));
24
+ var _llm2 = require("./llm.types");
18
25
  function _interopRequireWildcard(e, t) { if ("function" == typeof _WeakMap) var r = new _WeakMap(), n = new _WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = _Object$defineProperty) && _Object$getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
19
26
  WebexCore.registerInternalPlugin('llm', _llm.default, {
20
27
  config: _llm.config
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"names":["WebexCore","_interopRequireWildcard","require","_llm","e","t","_WeakMap","r","n","__esModule","o","i","f","__proto__","default","_typeof","has","get","set","_t","hasOwnProperty","call","_Object$defineProperty","_Object$getOwnPropertyDescriptor","registerInternalPlugin","LLMChannel","config"],"sources":["index.ts"],"sourcesContent":["import * as WebexCore from '@webex/webex-core';\nimport LLMChannel, {config} from './llm';\n\nWebexCore.registerInternalPlugin('llm', LLMChannel, {\n config,\n});\n\nexport {default} from './llm';\n"],"mappings":";;;;;;;;;;;;;;;AAAA,IAAAA,SAAA,GAAAC,uBAAA,CAAAC,OAAA;AACA,IAAAC,IAAA,GAAAF,uBAAA,CAAAC,OAAA;AAAyC,SAAAD,wBAAAG,CAAA,EAAAC,CAAA,6BAAAC,QAAA,MAAAC,CAAA,OAAAD,QAAA,IAAAE,CAAA,OAAAF,QAAA,YAAAL,uBAAA,YAAAA,wBAAAG,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAK,UAAA,SAAAL,CAAA,MAAAM,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAC,OAAA,EAAAV,CAAA,iBAAAA,CAAA,gBAAAW,OAAA,CAAAX,CAAA,0BAAAA,CAAA,SAAAQ,CAAA,MAAAF,CAAA,GAAAL,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAG,CAAA,CAAAM,GAAA,CAAAZ,CAAA,UAAAM,CAAA,CAAAO,GAAA,CAAAb,CAAA,GAAAM,CAAA,CAAAQ,GAAA,CAAAd,CAAA,EAAAQ,CAAA,cAAAO,EAAA,IAAAf,CAAA,gBAAAe,EAAA,OAAAC,cAAA,CAAAC,IAAA,CAAAjB,CAAA,EAAAe,EAAA,OAAAR,CAAA,IAAAD,CAAA,GAAAY,sBAAA,KAAAC,gCAAA,CAAAnB,CAAA,EAAAe,EAAA,OAAAR,CAAA,CAAAM,GAAA,IAAAN,CAAA,CAAAO,GAAA,IAAAR,CAAA,CAAAE,CAAA,EAAAO,EAAA,EAAAR,CAAA,IAAAC,CAAA,CAAAO,EAAA,IAAAf,CAAA,CAAAe,EAAA,WAAAP,CAAA,KAAAR,CAAA,EAAAC,CAAA;AAEzCL,SAAS,CAACwB,sBAAsB,CAAC,KAAK,EAAEC,YAAU,EAAE;EAClDC,MAAM,EAANA;AACF,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["WebexCore","_interopRequireWildcard","require","_llm","_llm2","e","t","_WeakMap","r","n","__esModule","o","i","f","__proto__","default","_typeof","has","get","set","_t","hasOwnProperty","call","_Object$defineProperty","_Object$getOwnPropertyDescriptor","registerInternalPlugin","LLMChannel","config"],"sources":["index.ts"],"sourcesContent":["import * as WebexCore from '@webex/webex-core';\nimport LLMChannel, {config} from './llm';\nimport {DataChannelTokenType} from './llm.types';\n\nWebexCore.registerInternalPlugin('llm', LLMChannel, {\n config,\n});\n\nexport {DataChannelTokenType};\nexport {default} from './llm';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,SAAA,GAAAC,uBAAA,CAAAC,OAAA;AACA,IAAAC,IAAA,GAAAF,uBAAA,CAAAC,OAAA;AACA,IAAAE,KAAA,GAAAF,OAAA;AAAiD,SAAAD,wBAAAI,CAAA,EAAAC,CAAA,6BAAAC,QAAA,MAAAC,CAAA,OAAAD,QAAA,IAAAE,CAAA,OAAAF,QAAA,YAAAN,uBAAA,YAAAA,wBAAAI,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAK,UAAA,SAAAL,CAAA,MAAAM,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAC,OAAA,EAAAV,CAAA,iBAAAA,CAAA,gBAAAW,OAAA,CAAAX,CAAA,0BAAAA,CAAA,SAAAQ,CAAA,MAAAF,CAAA,GAAAL,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAG,CAAA,CAAAM,GAAA,CAAAZ,CAAA,UAAAM,CAAA,CAAAO,GAAA,CAAAb,CAAA,GAAAM,CAAA,CAAAQ,GAAA,CAAAd,CAAA,EAAAQ,CAAA,cAAAO,EAAA,IAAAf,CAAA,gBAAAe,EAAA,OAAAC,cAAA,CAAAC,IAAA,CAAAjB,CAAA,EAAAe,EAAA,OAAAR,CAAA,IAAAD,CAAA,GAAAY,sBAAA,KAAAC,gCAAA,CAAAnB,CAAA,EAAAe,EAAA,OAAAR,CAAA,CAAAM,GAAA,IAAAN,CAAA,CAAAO,GAAA,IAAAR,CAAA,CAAAE,CAAA,EAAAO,EAAA,EAAAR,CAAA,IAAAC,CAAA,CAAAO,EAAA,IAAAf,CAAA,CAAAe,EAAA,WAAAP,CAAA,KAAAR,CAAA,EAAAC,CAAA;AAEjDN,SAAS,CAACyB,sBAAsB,CAAC,KAAK,EAAEC,YAAU,EAAE;EAClDC,MAAM,EAANA;AACF,CAAC,CAAC","ignoreList":[]}
package/dist/llm.js CHANGED
@@ -7,18 +7,19 @@ _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 _regenerator = _interopRequireDefault(require("@babel/runtime-corejs2/regenerator"));
11
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/asyncToGenerator"));
11
12
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/classCallCheck"));
13
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass"));
12
14
  var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/possibleConstructorReturn"));
13
15
  var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/getPrototypeOf"));
14
16
  var _inherits2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/inherits"));
15
- var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty"));
17
+ var _defineProperty3 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty"));
16
18
  var _internalPluginMercury = _interopRequireDefault(require("@webex/internal-plugin-mercury"));
17
19
  var _constants = require("./constants");
20
+ var _llm = require("./llm.types");
18
21
  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
-
22
+ 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 */ // eslint-disable-next-line no-unused-vars
22
23
  var config = exports.config = {
23
24
  llm: {
24
25
  /**
@@ -61,45 +62,71 @@ var LLMChannel = exports.default = /*#__PURE__*/function (_ref) {
61
62
  args[_key] = arguments[_key];
62
63
  }
63
64
  _this = _callSuper(this, LLMChannel, [].concat(args));
64
- (0, _defineProperty2.default)(_this, "namespace", _constants.LLM);
65
+ (0, _defineProperty3.default)(_this, "namespace", _constants.LLM);
65
66
  /**
66
67
  * If the LLM plugin has been registered and listening
67
68
  * @instance
68
69
  * @type {Boolean}
69
70
  * @public
70
71
  */
71
- (0, _defineProperty2.default)(_this, "webSocketUrl", void 0);
72
- (0, _defineProperty2.default)(_this, "binding", void 0);
73
- (0, _defineProperty2.default)(_this, "locusUrl", void 0);
74
- (0, _defineProperty2.default)(_this, "datachannelUrl", void 0);
72
+ (0, _defineProperty3.default)(_this, "webSocketUrl", void 0);
73
+ (0, _defineProperty3.default)(_this, "binding", void 0);
74
+ (0, _defineProperty3.default)(_this, "locusUrl", void 0);
75
+ (0, _defineProperty3.default)(_this, "datachannelUrl", void 0);
76
+ (0, _defineProperty3.default)(_this, "datachannelToken", void 0);
77
+ (0, _defineProperty3.default)(_this, "datachannelTokens", (0, _defineProperty3.default)((0, _defineProperty3.default)({}, _llm.DataChannelTokenType.Default, undefined), _llm.DataChannelTokenType.PracticeSession, undefined));
78
+ (0, _defineProperty3.default)(_this, "refreshHandler", void 0);
75
79
  /**
76
80
  * Register to the websocket
77
81
  * @param {string} llmSocketUrl
82
+ * @param {string} datachannelToken
78
83
  * @returns {Promise<void>}
79
84
  */
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
- });
85
+ (0, _defineProperty3.default)(_this, "register", /*#__PURE__*/function () {
86
+ var _ref2 = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee(llmSocketUrl, datachannelToken) {
87
+ var isDataChannelTokenEnabled;
88
+ return _regenerator.default.wrap(function (_context) {
89
+ while (1) switch (_context.prev = _context.next) {
90
+ case 0:
91
+ _context.next = 1;
92
+ return _this.isDataChannelTokenEnabled();
93
+ case 1:
94
+ isDataChannelTokenEnabled = _context.sent;
95
+ return _context.abrupt("return", _this.request({
96
+ method: 'POST',
97
+ url: llmSocketUrl,
98
+ body: {
99
+ deviceUrl: _this.webex.internal.device.url
100
+ },
101
+ headers: isDataChannelTokenEnabled && datachannelToken ? {
102
+ 'Data-Channel-Auth-Token': datachannelToken
103
+ } : {}
104
+ }).then(function (res) {
105
+ _this.webSocketUrl = res.body.webSocketUrl;
106
+ _this.binding = res.body.binding;
107
+ }).catch(function (error) {
108
+ _this.logger.error("Error connecting to websocket: ".concat(error));
109
+ throw error;
110
+ }));
111
+ case 2:
112
+ case "end":
113
+ return _context.stop();
114
+ }
115
+ }, _callee);
116
+ }));
117
+ return function (_x, _x2) {
118
+ return _ref2.apply(this, arguments);
119
+ };
120
+ }());
95
121
  /**
96
122
  * Register and connect to the websocket
97
123
  * @param {string} locusUrl
98
124
  * @param {string} datachannelUrl
125
+ * @param {string} datachannelToken
99
126
  * @returns {Promise<void>}
100
127
  */
101
- (0, _defineProperty2.default)(_this, "registerAndConnect", function (locusUrl, datachannelUrl) {
102
- return _this.register(datachannelUrl).then(function () {
128
+ (0, _defineProperty3.default)(_this, "registerAndConnect", function (locusUrl, datachannelUrl, datachannelToken) {
129
+ return _this.register(datachannelUrl, datachannelToken).then(function () {
103
130
  if (!locusUrl || !datachannelUrl) return undefined;
104
131
  _this.locusUrl = locusUrl;
105
132
  _this.datachannelUrl = datachannelUrl;
@@ -110,36 +137,53 @@ var LLMChannel = exports.default = /*#__PURE__*/function (_ref) {
110
137
  * Tells if LLM socket is connected
111
138
  * @returns {boolean} connected
112
139
  */
113
- (0, _defineProperty2.default)(_this, "isConnected", function () {
140
+ (0, _defineProperty3.default)(_this, "isConnected", function () {
114
141
  return _this.connected;
115
142
  });
116
143
  /**
117
144
  * Tells if LLM socket is binding
118
145
  * @returns {string} binding
119
146
  */
120
- (0, _defineProperty2.default)(_this, "getBinding", function () {
147
+ (0, _defineProperty3.default)(_this, "getBinding", function () {
121
148
  return _this.binding;
122
149
  });
123
150
  /**
124
151
  * Get Locus URL for the connection
125
152
  * @returns {string} locus Url
126
153
  */
127
- (0, _defineProperty2.default)(_this, "getLocusUrl", function () {
154
+ (0, _defineProperty3.default)(_this, "getLocusUrl", function () {
128
155
  return _this.locusUrl;
129
156
  });
130
157
  /**
131
158
  * Get data channel URL for the connection
132
159
  * @returns {string} data channel Url
133
160
  */
134
- (0, _defineProperty2.default)(_this, "getDatachannelUrl", function () {
161
+ (0, _defineProperty3.default)(_this, "getDatachannelUrl", function () {
135
162
  return _this.datachannelUrl;
136
163
  });
164
+ /**
165
+ * Get data channel token for the connection
166
+ * @param {DataChannelTokenType} dataChannelTokenType
167
+ * @returns {string} data channel token
168
+ */
169
+ (0, _defineProperty3.default)(_this, "getDatachannelToken", function (dataChannelTokenType) {
170
+ return _this.datachannelTokens[dataChannelTokenType];
171
+ });
172
+ /**
173
+ * Set data channel token for the connection
174
+ * @param {string} datachannelToken - data channel token
175
+ * @param {DataChannelTokenType} dataChannelTokenType
176
+ * @returns {void}
177
+ */
178
+ (0, _defineProperty3.default)(_this, "setDatachannelToken", function (datachannelToken, dataChannelTokenType) {
179
+ _this.datachannelTokens[dataChannelTokenType] = datachannelToken;
180
+ });
137
181
  /**
138
182
  * Disconnects websocket connection
139
183
  * @param {{code: number, reason: string}} options - The disconnect option object with code and reason
140
184
  * @returns {Promise<void>}
141
185
  */
142
- (0, _defineProperty2.default)(_this, "disconnectLLM", function (options) {
186
+ (0, _defineProperty3.default)(_this, "disconnectLLM", function (options) {
143
187
  return _this.disconnect(options).then(function () {
144
188
  _this.locusUrl = undefined;
145
189
  _this.datachannelUrl = undefined;
@@ -150,6 +194,74 @@ var LLMChannel = exports.default = /*#__PURE__*/function (_ref) {
150
194
  return _this;
151
195
  }
152
196
  (0, _inherits2.default)(LLMChannel, _ref);
153
- return (0, _createClass2.default)(LLMChannel);
197
+ return (0, _createClass2.default)(LLMChannel, [{
198
+ key: "setRefreshHandler",
199
+ value:
200
+ /**
201
+ * Set the handler used to refresh the DataChannel token
202
+ *
203
+ * @param {function} handler - Function that returns a refreshed token
204
+ * @returns {void}
205
+ */
206
+ function setRefreshHandler(handler) {
207
+ this.refreshHandler = handler;
208
+ }
209
+ }, {
210
+ key: "refreshDataChannelToken",
211
+ value: (
212
+ /**
213
+ * Refresh the data channel token using the injected handler.
214
+ * Logs a descriptive error if the handler is missing or fails.
215
+ *
216
+ * @returns {Promise<string>} The refreshed token.
217
+ */
218
+ function () {
219
+ var _refreshDataChannelToken = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee2() {
220
+ var error, res, _t;
221
+ return _regenerator.default.wrap(function (_context2) {
222
+ while (1) switch (_context2.prev = _context2.next) {
223
+ case 0:
224
+ if (this.refreshHandler) {
225
+ _context2.next = 1;
226
+ break;
227
+ }
228
+ error = new Error('LLM refreshHandler is not set');
229
+ this.logger.error("Error refreshing DataChannel token: ".concat(error.message));
230
+ throw error;
231
+ case 1:
232
+ _context2.prev = 1;
233
+ _context2.next = 2;
234
+ return this.refreshHandler();
235
+ case 2:
236
+ res = _context2.sent;
237
+ return _context2.abrupt("return", res);
238
+ case 3:
239
+ _context2.prev = 3;
240
+ _t = _context2["catch"](1);
241
+ this.logger.error("Error refreshing DataChannel token: ".concat(_t));
242
+ throw _t;
243
+ case 4:
244
+ case "end":
245
+ return _context2.stop();
246
+ }
247
+ }, _callee2, this, [[1, 3]]);
248
+ }));
249
+ function refreshDataChannelToken() {
250
+ return _refreshDataChannelToken.apply(this, arguments);
251
+ }
252
+ return refreshDataChannelToken;
253
+ }()
254
+ /**
255
+ * Returns true if data channel token is enabled, false otherwise
256
+ * @returns {Promise<boolean>} resolves with true if data channel token is enabled
257
+ */
258
+ )
259
+ }, {
260
+ key: "isDataChannelTokenEnabled",
261
+ value: function isDataChannelTokenEnabled() {
262
+ // @ts-ignore
263
+ return this.webex.internal.feature.getFeature('developer', _constants.DATA_CHANNEL_WITH_JWT_TOKEN);
264
+ }
265
+ }]);
154
266
  }(_internalPluginMercury.default);
155
267
  //# 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":"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","ignoreList":[]}
1
+ {"version":3,"names":["_internalPluginMercury","_interopRequireDefault","require","_constants","_llm","_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","_defineProperty3","LLM","DataChannelTokenType","Default","undefined","PracticeSession","_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","register","connect","connected","dataChannelTokenType","datachannelTokens","options","disconnect","_inherits2","_createClass2","key","value","setRefreshHandler","handler","refreshHandler","_refreshDataChannelToken","_callee2","_t","_context2","Error","message","refreshDataChannelToken","feature","getFeature","DATA_CHANNEL_WITH_JWT_TOKEN","Mercury"],"sources":["llm.ts"],"sourcesContent":["/* eslint-disable consistent-return */\n\nimport Mercury from '@webex/internal-plugin-mercury';\n\nimport {LLM, DATA_CHANNEL_WITH_JWT_TOKEN} from './constants';\n// eslint-disable-next-line no-unused-vars\nimport {ILLMChannel, DataChannelTokenType} 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 private datachannelToken?: string;\n\n private datachannelTokens: Record<DataChannelTokenType, string> = {\n [DataChannelTokenType.Default]: undefined,\n [DataChannelTokenType.PracticeSession]: undefined,\n };\n\n private refreshHandler?: () => Promise<{\n body: {datachannelToken: string; datachannelTokenType: DataChannelTokenType};\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: ${error}`);\n throw error;\n });\n };\n\n /**\n * Register and connect to the websocket\n * @param {string} locusUrl\n * @param {string} datachannelUrl\n * @param {string} datachannelToken\n * @returns {Promise<void>}\n */\n public registerAndConnect = (\n locusUrl: string,\n datachannelUrl: string,\n datachannelToken?: string\n ): Promise<void> =>\n this.register(datachannelUrl, datachannelToken).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 * Get data channel token for the connection\n * @param {DataChannelTokenType} dataChannelTokenType\n * @returns {string} data channel token\n */\n public getDatachannelToken = (dataChannelTokenType: DataChannelTokenType): string => {\n return this.datachannelTokens[dataChannelTokenType];\n };\n\n /**\n * Set data channel token for the connection\n * @param {string} datachannelToken - data channel token\n * @param {DataChannelTokenType} dataChannelTokenType\n * @returns {void}\n */\n public setDatachannelToken = (\n datachannelToken: string,\n dataChannelTokenType: DataChannelTokenType\n ): void => {\n this.datachannelTokens[dataChannelTokenType] = datachannelToken;\n };\n\n /**\n * Set the handler used to refresh the DataChannel token\n *\n * @param {function} handler - Function that returns a refreshed token\n * @returns {void}\n */\n public setRefreshHandler(\n handler: () => Promise<{\n body: {datachannelToken: string; datachannelTokenType: DataChannelTokenType};\n }>\n ) {\n this.refreshHandler = handler;\n }\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 /**\n * Refresh the data channel token using the injected handler.\n * Logs a descriptive error if the handler is missing or fails.\n *\n * @returns {Promise<string>} The refreshed token.\n */\n public async refreshDataChannelToken() {\n if (!this.refreshHandler) {\n const error = new Error('LLM refreshHandler is not set');\n this.logger.error(`Error refreshing DataChannel token: ${error.message}`);\n throw error;\n }\n\n try {\n const res = await this.refreshHandler();\n\n return res;\n } catch (error: any) {\n this.logger.error(`Error refreshing DataChannel token: ${error}`);\n throw error;\n }\n }\n\n /**\n * Returns true if data channel token is enabled, false otherwise\n * @returns {Promise<boolean>} resolves with true if data channel token is enabled\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"],"mappings":"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","ignoreList":[]}
package/dist/llm.types.js CHANGED
@@ -4,4 +4,10 @@ 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"] = "default";
10
+ DataChannelTokenType["PracticeSession"] = "practiceSession";
11
+ return DataChannelTokenType;
12
+ }({}); // eslint-disable-next-line import/prefer-default-export
7
13
  //# 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":["interface ILLMChannel {\n registerAndConnect: (\n locusUrl: string,\n datachannelUrl: string,\n datachannelToken?: string\n ) => Promise<void>;\n isConnected: () => boolean;\n getBinding: () => string;\n getLocusUrl: () => string;\n disconnectLLM: (options: {code: number; reason: string}) => Promise<void>;\n}\n\nexport enum DataChannelTokenType {\n Default = 'default',\n PracticeSession = 'practiceSession',\n}\n\n// eslint-disable-next-line import/prefer-default-export\nexport type {ILLMChannel};\n"],"mappings":";;;;;;;IAYYA,oBAAoB,GAAAC,OAAA,CAAAD,oBAAA,0BAApBA,oBAAoB;EAApBA,oBAAoB;EAApBA,oBAAoB;EAAA,OAApBA,oBAAoB;AAAA,OAKhC","ignoreList":[]}
package/package.json CHANGED
@@ -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-next.7"
47
+ "version": "3.11.0-next.8"
48
48
  }
package/src/constants.ts CHANGED
@@ -1,2 +1,4 @@
1
1
  // eslint-disable-next-line import/prefer-default-export
2
2
  export const LLM = 'llm';
3
+
4
+ export const DATA_CHANNEL_WITH_JWT_TOKEN = 'data-channel-with-jwt-token';
package/src/index.ts CHANGED
@@ -1,8 +1,10 @@
1
1
  import * as WebexCore from '@webex/webex-core';
2
2
  import LLMChannel, {config} from './llm';
3
+ import {DataChannelTokenType} from './llm.types';
3
4
 
4
5
  WebexCore.registerInternalPlugin('llm', LLMChannel, {
5
6
  config,
6
7
  });
7
8
 
9
+ export {DataChannelTokenType};
8
10
  export {default} from './llm';
package/src/llm.ts CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  import Mercury from '@webex/internal-plugin-mercury';
4
4
 
5
- import {LLM} from './constants';
5
+ import {LLM, DATA_CHANNEL_WITH_JWT_TOKEN} from './constants';
6
6
  // eslint-disable-next-line no-unused-vars
7
- import {ILLMChannel} from './llm.types';
7
+ import {ILLMChannel, DataChannelTokenType} from './llm.types';
8
8
 
9
9
  export const config = {
10
10
  llm: {
@@ -58,16 +58,34 @@ export default class LLMChannel extends (Mercury as any) implements ILLMChannel
58
58
 
59
59
  private datachannelUrl?: string;
60
60
 
61
+ private datachannelToken?: string;
62
+
63
+ private datachannelTokens: Record<DataChannelTokenType, string> = {
64
+ [DataChannelTokenType.Default]: undefined,
65
+ [DataChannelTokenType.PracticeSession]: undefined,
66
+ };
67
+
68
+ private refreshHandler?: () => Promise<{
69
+ body: {datachannelToken: string; datachannelTokenType: DataChannelTokenType};
70
+ }>;
71
+
61
72
  /**
62
73
  * Register to the websocket
63
74
  * @param {string} llmSocketUrl
75
+ * @param {string} datachannelToken
64
76
  * @returns {Promise<void>}
65
77
  */
66
- private register = (llmSocketUrl: string): Promise<void> =>
67
- this.request({
78
+ private register = async (llmSocketUrl: string, datachannelToken?: string): Promise<void> => {
79
+ const isDataChannelTokenEnabled = await this.isDataChannelTokenEnabled();
80
+
81
+ return this.request({
68
82
  method: 'POST',
69
83
  url: llmSocketUrl,
70
84
  body: {deviceUrl: this.webex.internal.device.url},
85
+ headers:
86
+ isDataChannelTokenEnabled && datachannelToken
87
+ ? {'Data-Channel-Auth-Token': datachannelToken}
88
+ : {},
71
89
  })
72
90
  .then((res: {body: {webSocketUrl: string; binding: string}}) => {
73
91
  this.webSocketUrl = res.body.webSocketUrl;
@@ -77,15 +95,21 @@ export default class LLMChannel extends (Mercury as any) implements ILLMChannel
77
95
  this.logger.error(`Error connecting to websocket: ${error}`);
78
96
  throw error;
79
97
  });
98
+ };
80
99
 
81
100
  /**
82
101
  * Register and connect to the websocket
83
102
  * @param {string} locusUrl
84
103
  * @param {string} datachannelUrl
104
+ * @param {string} datachannelToken
85
105
  * @returns {Promise<void>}
86
106
  */
87
- public registerAndConnect = (locusUrl: string, datachannelUrl: string): Promise<void> =>
88
- this.register(datachannelUrl).then(() => {
107
+ public registerAndConnect = (
108
+ locusUrl: string,
109
+ datachannelUrl: string,
110
+ datachannelToken?: string
111
+ ): Promise<void> =>
112
+ this.register(datachannelUrl, datachannelToken).then(() => {
89
113
  if (!locusUrl || !datachannelUrl) return undefined;
90
114
  this.locusUrl = locusUrl;
91
115
  this.datachannelUrl = datachannelUrl;
@@ -116,6 +140,42 @@ export default class LLMChannel extends (Mercury as any) implements ILLMChannel
116
140
  */
117
141
  public getDatachannelUrl = (): string => this.datachannelUrl;
118
142
 
143
+ /**
144
+ * Get data channel token for the connection
145
+ * @param {DataChannelTokenType} dataChannelTokenType
146
+ * @returns {string} data channel token
147
+ */
148
+ public getDatachannelToken = (dataChannelTokenType: DataChannelTokenType): string => {
149
+ return this.datachannelTokens[dataChannelTokenType];
150
+ };
151
+
152
+ /**
153
+ * Set data channel token for the connection
154
+ * @param {string} datachannelToken - data channel token
155
+ * @param {DataChannelTokenType} dataChannelTokenType
156
+ * @returns {void}
157
+ */
158
+ public setDatachannelToken = (
159
+ datachannelToken: string,
160
+ dataChannelTokenType: DataChannelTokenType
161
+ ): void => {
162
+ this.datachannelTokens[dataChannelTokenType] = datachannelToken;
163
+ };
164
+
165
+ /**
166
+ * Set the handler used to refresh the DataChannel token
167
+ *
168
+ * @param {function} handler - Function that returns a refreshed token
169
+ * @returns {void}
170
+ */
171
+ public setRefreshHandler(
172
+ handler: () => Promise<{
173
+ body: {datachannelToken: string; datachannelTokenType: DataChannelTokenType};
174
+ }>
175
+ ) {
176
+ this.refreshHandler = handler;
177
+ }
178
+
119
179
  /**
120
180
  * Disconnects websocket connection
121
181
  * @param {{code: number, reason: string}} options - The disconnect option object with code and reason
@@ -128,4 +188,36 @@ export default class LLMChannel extends (Mercury as any) implements ILLMChannel
128
188
  this.binding = undefined;
129
189
  this.webSocketUrl = undefined;
130
190
  });
191
+
192
+ /**
193
+ * Refresh the data channel token using the injected handler.
194
+ * Logs a descriptive error if the handler is missing or fails.
195
+ *
196
+ * @returns {Promise<string>} The refreshed token.
197
+ */
198
+ public async refreshDataChannelToken() {
199
+ if (!this.refreshHandler) {
200
+ const error = new Error('LLM refreshHandler is not set');
201
+ this.logger.error(`Error refreshing DataChannel token: ${error.message}`);
202
+ throw error;
203
+ }
204
+
205
+ try {
206
+ const res = await this.refreshHandler();
207
+
208
+ return res;
209
+ } catch (error: any) {
210
+ this.logger.error(`Error refreshing DataChannel token: ${error}`);
211
+ throw error;
212
+ }
213
+ }
214
+
215
+ /**
216
+ * Returns true if data channel token is enabled, false otherwise
217
+ * @returns {Promise<boolean>} resolves with true if data channel token is enabled
218
+ */
219
+ public isDataChannelTokenEnabled(): Promise<boolean> {
220
+ // @ts-ignore
221
+ return this.webex.internal.feature.getFeature('developer', DATA_CHANNEL_WITH_JWT_TOKEN);
222
+ }
131
223
  }
package/src/llm.types.ts CHANGED
@@ -1,9 +1,19 @@
1
1
  interface ILLMChannel {
2
- registerAndConnect: (locusUrl: string, datachannelUrl: string) => Promise<void>;
2
+ registerAndConnect: (
3
+ locusUrl: string,
4
+ datachannelUrl: string,
5
+ datachannelToken?: string
6
+ ) => Promise<void>;
3
7
  isConnected: () => boolean;
4
8
  getBinding: () => string;
5
9
  getLocusUrl: () => string;
6
10
  disconnectLLM: (options: {code: number; reason: string}) => Promise<void>;
7
11
  }
12
+
13
+ export enum DataChannelTokenType {
14
+ Default = 'default',
15
+ PracticeSession = 'practiceSession',
16
+ }
17
+
8
18
  // eslint-disable-next-line import/prefer-default-export
9
19
  export type {ILLMChannel};
@@ -19,6 +19,11 @@ describe('plugin-llm', () => {
19
19
  },
20
20
  });
21
21
 
22
+ webex.internal.feature = {
23
+ setFeature: sinon.stub().resolves({value: true}),
24
+ getFeature: sinon.stub().resolves(true),
25
+ };
26
+
22
27
  llmService = webex.internal.llm;
23
28
  llmService.connect = sinon.stub().callsFake(() => {
24
29
  llmService.connected = true;
@@ -56,10 +61,50 @@ describe('plugin-llm', () => {
56
61
  await llmService.registerAndConnect();
57
62
  assert.equal(llmService.isConnected(), false);
58
63
  });
64
+
65
+ it('registers connection with token', async () => {
66
+ llmService.register = sinon.stub().resolves({
67
+ body: {
68
+ binding: 'binding',
69
+ webSocketUrl: 'url',
70
+ },
71
+ });
72
+
73
+ assert.equal(llmService.isConnected(), false);
74
+
75
+ await llmService.registerAndConnect(locusUrl, datachannelUrl, 'abc123');
76
+
77
+ sinon.assert.calledOnceWithExactly(
78
+ llmService.register,
79
+ datachannelUrl,
80
+ 'abc123'
81
+ );
82
+
83
+ assert.equal(llmService.isConnected(), true);
84
+ });
59
85
  });
60
86
 
61
87
  describe('#register', () => {
62
- it('registers connection', async () => {
88
+ beforeEach(() => {
89
+ llmService.isDataChannelTokenEnabled = sinon.stub();
90
+ });
91
+
92
+ it('registers connection with token header', async () => {
93
+ llmService.isDataChannelTokenEnabled.resolves(true);
94
+ await llmService.register(datachannelUrl, 'abc123');
95
+
96
+ sinon.assert.calledOnceWithExactly(
97
+ llmService.request,
98
+ sinon.match({
99
+ method: 'POST',
100
+ url: `${datachannelUrl}`,
101
+ body: {deviceUrl: webex.internal.device.url},
102
+ headers: {'Data-Channel-Auth-Token': 'abc123'},
103
+ })
104
+ );
105
+ });
106
+
107
+ it('registers connection without token header when none provided', async () => {
63
108
  await llmService.register(datachannelUrl);
64
109
 
65
110
  sinon.assert.calledOnceWithExactly(
@@ -68,13 +113,28 @@ describe('plugin-llm', () => {
68
113
  method: 'POST',
69
114
  url: `${datachannelUrl}`,
70
115
  body: {deviceUrl: webex.internal.device.url},
116
+ headers: {},
71
117
  })
72
118
  );
119
+ });
120
+
121
+ it('registers connection without token header when toggle disabled', async () => {
122
+ llmService.isDataChannelTokenEnabled.resolves(false);
73
123
 
74
- assert.equal(llmService.getBinding(), 'binding');
124
+ await llmService.register(datachannelUrl,'abc123');
125
+ sinon.assert.calledOnceWithExactly(
126
+ llmService.request,
127
+ sinon.match({
128
+ method: 'POST',
129
+ url: `${datachannelUrl}`,
130
+ body: {deviceUrl: webex.internal.device.url},
131
+ headers: {},
132
+ })
133
+ );
75
134
  });
76
135
  });
77
136
 
137
+
78
138
  describe('#getLocusUrl', () => {
79
139
  it('gets LocusUrl', async () => {
80
140
  llmService.register = sinon.stub().resolves({
@@ -149,5 +209,82 @@ describe('plugin-llm', () => {
149
209
  await expect(instance.disconnectLLM({})).rejects.toThrow('Disconnect failed');
150
210
  });
151
211
  });
212
+
213
+ describe('#setRefreshHandler', () => {
214
+ it('stores the provided handler', () => {
215
+ const handler = sinon.stub().resolves({ body: { datachannelToken: 'newToken' } });
216
+ llmService.setRefreshHandler(handler);
217
+
218
+ // @ts-ignore
219
+ assert.equal(llmService.refreshHandler, handler);
220
+ });
221
+ });
222
+
223
+ describe('#isDataChannelTokenEnabled', () => {
224
+ it('works correctly', async () => {
225
+ webex.internal.feature.getFeature.returns(true);
226
+
227
+ const result = await llmService.isDataChannelTokenEnabled();
228
+
229
+ sinon.assert.calledOnceWithExactly(
230
+ webex.internal.feature.getFeature,
231
+ 'developer',
232
+ 'data-channel-with-jwt-token'
233
+ );
234
+
235
+ assert.equal(result, true);
236
+ });
237
+ });
238
+
239
+ describe('#refreshDataChannelToken', () => {
240
+ it('throws if no handler is set', async () => {
241
+ try {
242
+ await llmService.refreshDataChannelToken();
243
+ assert.fail('Should have thrown');
244
+ } catch (err) {
245
+ assert.match(err.message, 'LLM refreshHandler is not set');
246
+ }
247
+ });
248
+
249
+ it('returns token when handler resolves', async () => {
250
+ const mockToken = { body: { datachannelToken: 'newToken' ,isPracticeSession: false} }
251
+ const handler = sinon.stub().resolves(mockToken);
252
+ llmService.setRefreshHandler(handler);
253
+
254
+ const token = await llmService.refreshDataChannelToken();
255
+ assert.equal(token, mockToken);
256
+ sinon.assert.calledOnce(handler);
257
+ });
258
+
259
+ it('logs and rethrows when handler rejects', async () => {
260
+ const handler = sinon.stub().rejects(new Error('throw error'));
261
+
262
+ const loggerSpy = llmService.logger.error;
263
+
264
+ llmService.setRefreshHandler(handler);
265
+
266
+ try {
267
+ await llmService.refreshDataChannelToken();
268
+ assert.fail('Should have thrown');
269
+ } catch (err) {
270
+ assert.match(err.message, /throw error/);
271
+ }
272
+
273
+ sinon.assert.calledOnce(loggerSpy);
274
+ sinon.assert.calledWithMatch(
275
+ loggerSpy,
276
+ sinon.match("Error refreshing DataChannel token: Error: throw error")
277
+ );
278
+ });
279
+ });
280
+
281
+ describe('#getDatachannelToken / #setDatachannelToken', () => {
282
+ it('sets and gets datachannel token', () => {
283
+ llmService.setDatachannelToken('abc123','default');
284
+ assert.equal(llmService.getDatachannelToken('default'), 'abc123');
285
+ llmService.setDatachannelToken('123abc','practiceSession');
286
+ assert.equal(llmService.getDatachannelToken('practiceSession'), '123abc');
287
+ });
288
+ });
152
289
  });
153
290
  });