@webex/internal-plugin-llm 3.12.0-next.2 → 3.12.0-next.20
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/README.md +2 -2
- package/dist/constants.js +2 -1
- package/dist/constants.js.map +1 -1
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -1
- package/dist/llm.js +278 -39
- package/dist/llm.js.map +1 -1
- package/dist/llm.types.js.map +1 -1
- package/package.json +6 -6
- package/src/constants.ts +1 -0
- package/src/index.ts +1 -0
- package/src/llm.ts +306 -41
- package/src/llm.types.ts +45 -8
- package/test/unit/spec/llm.js +282 -19
package/README.md
CHANGED
|
@@ -91,7 +91,7 @@ webex.internal.llm.setRefreshHandler(async () => {
|
|
|
91
91
|
datachannelTokenType: 'llm-default-session',
|
|
92
92
|
},
|
|
93
93
|
};
|
|
94
|
-
});
|
|
94
|
+
}, 'llm-default-session');
|
|
95
95
|
|
|
96
96
|
// Optional: manually trigger refresh (if needed by your flow)
|
|
97
97
|
await webex.internal.llm.refreshDataChannelToken();
|
|
@@ -106,7 +106,7 @@ webex.internal.llm.getDatachannelUrl('session-a');
|
|
|
106
106
|
webex.internal.llm.getAllConnections();
|
|
107
107
|
|
|
108
108
|
// Disconnect one session
|
|
109
|
-
await webex.internal.llm.disconnectLLM({code: 1000, reason: 'done'}, 'session-a');
|
|
109
|
+
await webex.internal.llm.disconnectLLM({code: 1000, reason: 'done'}, 'session-a', 'meeting-id');
|
|
110
110
|
|
|
111
111
|
// Disconnect all sessions
|
|
112
112
|
await webex.internal.llm.disconnectAllLLM({code: 1000, reason: 'shutdown'});
|
package/dist/constants.js
CHANGED
|
@@ -4,10 +4,11 @@ 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.SUBSCRIPTION_AWARE_SUBCHANNELS_PARAM = exports.LLM_DEFAULT_SESSION = exports.LLM = exports.DATA_CHNANEL_TYPE = exports.DATA_CHANNEL_WITH_JWT_TOKEN = exports.AWARE_DATA_CHANNEL = void 0;
|
|
7
|
+
exports.SUBSCRIPTION_AWARE_SUBCHANNELS_PARAM = exports.LLM_PRACTICE_SESSION = exports.LLM_DEFAULT_SESSION = exports.LLM = exports.DATA_CHNANEL_TYPE = exports.DATA_CHANNEL_WITH_JWT_TOKEN = exports.AWARE_DATA_CHANNEL = void 0;
|
|
8
8
|
// eslint-disable-next-line import/prefer-default-export
|
|
9
9
|
var LLM = exports.LLM = 'llm';
|
|
10
10
|
var LLM_DEFAULT_SESSION = exports.LLM_DEFAULT_SESSION = 'llm-default-session';
|
|
11
|
+
var LLM_PRACTICE_SESSION = exports.LLM_PRACTICE_SESSION = 'llm-practice-session';
|
|
11
12
|
var DATA_CHANNEL_WITH_JWT_TOKEN = exports.DATA_CHANNEL_WITH_JWT_TOKEN = 'data-channel-with-jwt-token';
|
|
12
13
|
var SUBSCRIPTION_AWARE_SUBCHANNELS_PARAM = exports.SUBSCRIPTION_AWARE_SUBCHANNELS_PARAM = 'subscriptionAwareSubchannels';
|
|
13
14
|
var DATA_CHNANEL_TYPE = exports.DATA_CHNANEL_TYPE = {
|
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["LLM","exports","LLM_DEFAULT_SESSION","DATA_CHANNEL_WITH_JWT_TOKEN","SUBSCRIPTION_AWARE_SUBCHANNELS_PARAM","DATA_CHNANEL_TYPE","TRANSCRIPTION","AWARE_DATA_CHANNEL"],"sources":["constants.ts"],"sourcesContent":["// eslint-disable-next-line import/prefer-default-export\nexport const LLM = 'llm';\n\nexport const LLM_DEFAULT_SESSION = 'llm-default-session';\n\nexport const DATA_CHANNEL_WITH_JWT_TOKEN = 'data-channel-with-jwt-token';\n\nexport const SUBSCRIPTION_AWARE_SUBCHANNELS_PARAM = 'subscriptionAwareSubchannels';\n\nexport const DATA_CHNANEL_TYPE = {\n TRANSCRIPTION: 'transcription',\n};\n\nexport const AWARE_DATA_CHANNEL = [DATA_CHNANEL_TYPE.TRANSCRIPTION];\n"],"mappings":";;;;;;;AAAA;AACO,IAAMA,GAAG,GAAAC,OAAA,CAAAD,GAAA,GAAG,KAAK;AAEjB,IAAME,mBAAmB,GAAAD,OAAA,CAAAC,mBAAA,GAAG,qBAAqB;
|
|
1
|
+
{"version":3,"names":["LLM","exports","LLM_DEFAULT_SESSION","LLM_PRACTICE_SESSION","DATA_CHANNEL_WITH_JWT_TOKEN","SUBSCRIPTION_AWARE_SUBCHANNELS_PARAM","DATA_CHNANEL_TYPE","TRANSCRIPTION","AWARE_DATA_CHANNEL"],"sources":["constants.ts"],"sourcesContent":["// eslint-disable-next-line import/prefer-default-export\nexport const LLM = 'llm';\n\nexport const LLM_DEFAULT_SESSION = 'llm-default-session';\nexport const LLM_PRACTICE_SESSION = 'llm-practice-session';\n\nexport const DATA_CHANNEL_WITH_JWT_TOKEN = 'data-channel-with-jwt-token';\n\nexport const SUBSCRIPTION_AWARE_SUBCHANNELS_PARAM = 'subscriptionAwareSubchannels';\n\nexport const DATA_CHNANEL_TYPE = {\n TRANSCRIPTION: 'transcription',\n};\n\nexport const AWARE_DATA_CHANNEL = [DATA_CHNANEL_TYPE.TRANSCRIPTION];\n"],"mappings":";;;;;;;AAAA;AACO,IAAMA,GAAG,GAAAC,OAAA,CAAAD,GAAA,GAAG,KAAK;AAEjB,IAAME,mBAAmB,GAAAD,OAAA,CAAAC,mBAAA,GAAG,qBAAqB;AACjD,IAAMC,oBAAoB,GAAAF,OAAA,CAAAE,oBAAA,GAAG,sBAAsB;AAEnD,IAAMC,2BAA2B,GAAAH,OAAA,CAAAG,2BAAA,GAAG,6BAA6B;AAEjE,IAAMC,oCAAoC,GAAAJ,OAAA,CAAAI,oCAAA,GAAG,8BAA8B;AAE3E,IAAMC,iBAAiB,GAAAL,OAAA,CAAAK,iBAAA,GAAG;EAC/BC,aAAa,EAAE;AACjB,CAAC;AAEM,IAAMC,kBAAkB,GAAAP,OAAA,CAAAO,kBAAA,GAAG,CAACF,iBAAiB,CAACC,aAAa,CAAC","ignoreList":[]}
|
package/dist/index.js
CHANGED
|
@@ -13,6 +13,18 @@ _Object$defineProperty(exports, "DataChannelTokenType", {
|
|
|
13
13
|
return _llm2.DataChannelTokenType;
|
|
14
14
|
}
|
|
15
15
|
});
|
|
16
|
+
_Object$defineProperty(exports, "LLM_DEFAULT_SESSION", {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: function get() {
|
|
19
|
+
return _constants.LLM_DEFAULT_SESSION;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
_Object$defineProperty(exports, "LLM_PRACTICE_SESSION", {
|
|
23
|
+
enumerable: true,
|
|
24
|
+
get: function get() {
|
|
25
|
+
return _constants.LLM_PRACTICE_SESSION;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
16
28
|
_Object$defineProperty(exports, "default", {
|
|
17
29
|
enumerable: true,
|
|
18
30
|
get: function get() {
|
|
@@ -22,6 +34,7 @@ _Object$defineProperty(exports, "default", {
|
|
|
22
34
|
var WebexCore = _interopRequireWildcard(require("@webex/webex-core"));
|
|
23
35
|
var _llm = _interopRequireWildcard(require("./llm"));
|
|
24
36
|
var _llm2 = require("./llm.types");
|
|
37
|
+
var _constants = require("./constants");
|
|
25
38
|
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); }
|
|
26
39
|
WebexCore.registerInternalPlugin('llm', _llm.default, {
|
|
27
40
|
config: _llm.config
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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":"
|
|
1
|
+
{"version":3,"names":["WebexCore","_interopRequireWildcard","require","_llm","_llm2","_constants","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 {LLM_DEFAULT_SESSION, LLM_PRACTICE_SESSION} from './constants';\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;AAOA,IAAAG,UAAA,GAAAH,OAAA;AAAsE,SAAAD,wBAAAK,CAAA,EAAAC,CAAA,6BAAAC,QAAA,MAAAC,CAAA,OAAAD,QAAA,IAAAE,CAAA,OAAAF,QAAA,YAAAP,uBAAA,YAAAA,wBAAAK,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;AALtEP,SAAS,CAAC0B,sBAAsB,CAAC,KAAK,EAAEC,YAAU,EAAE;EAClDC,MAAM,EAANA;AACF,CAAC,CAAC","ignoreList":[]}
|
package/dist/llm.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
var _Reflect$construct = require("@babel/runtime-corejs2/core-js/reflect/construct");
|
|
4
|
+
var _Array$from = require("@babel/runtime-corejs2/core-js/array/from");
|
|
5
|
+
var _Symbol = require("@babel/runtime-corejs2/core-js/symbol");
|
|
6
|
+
var _Symbol$iterator = require("@babel/runtime-corejs2/core-js/symbol/iterator");
|
|
7
|
+
var _Array$isArray = require("@babel/runtime-corejs2/core-js/array/is-array");
|
|
4
8
|
var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
|
|
5
9
|
var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
|
|
6
10
|
_Object$defineProperty(exports, "__esModule", {
|
|
@@ -9,6 +13,8 @@ _Object$defineProperty(exports, "__esModule", {
|
|
|
9
13
|
exports.default = exports.config = void 0;
|
|
10
14
|
var _regenerator = _interopRequireDefault(require("@babel/runtime-corejs2/regenerator"));
|
|
11
15
|
var _map = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/map"));
|
|
16
|
+
var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
|
|
17
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/slicedToArray"));
|
|
12
18
|
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/asyncToGenerator"));
|
|
13
19
|
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/classCallCheck"));
|
|
14
20
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass"));
|
|
@@ -19,6 +25,9 @@ var _defineProperty3 = _interopRequireDefault(require("@babel/runtime-corejs2/he
|
|
|
19
25
|
var _internalPluginMercury = _interopRequireDefault(require("@webex/internal-plugin-mercury"));
|
|
20
26
|
var _constants = require("./constants");
|
|
21
27
|
var _llm = require("./llm.types");
|
|
28
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof _Symbol && r[_Symbol$iterator] || r["@@iterator"]; if (!t) { if (_Array$isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
29
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? _Array$from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
30
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
22
31
|
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)); }
|
|
23
32
|
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
|
|
24
33
|
var config = exports.config = {
|
|
@@ -67,12 +76,14 @@ var LLMChannel = exports.default = /*#__PURE__*/function (_ref) {
|
|
|
67
76
|
(0, _defineProperty3.default)(_this, "defaultSessionId", _constants.LLM_DEFAULT_SESSION);
|
|
68
77
|
/**
|
|
69
78
|
* Map to store connection-specific data for multiple LLM connections
|
|
79
|
+
* Key: sessionId
|
|
70
80
|
* @private
|
|
71
81
|
* @type {Map<string, {webSocketUrl?: string; binding?: string; locusUrl?: string; datachannelUrl?: string}>}
|
|
72
82
|
*/
|
|
73
83
|
(0, _defineProperty3.default)(_this, "connections", new _map.default());
|
|
84
|
+
// Session-keyed token cache is intentionally decoupled from connection state.
|
|
85
|
+
// Disconnecting a socket session must not implicitly wipe token cache.
|
|
74
86
|
(0, _defineProperty3.default)(_this, "datachannelTokens", (0, _defineProperty3.default)((0, _defineProperty3.default)({}, _llm.DataChannelTokenType.Default, undefined), _llm.DataChannelTokenType.PracticeSession, undefined));
|
|
75
|
-
(0, _defineProperty3.default)(_this, "refreshHandler", void 0);
|
|
76
87
|
/**
|
|
77
88
|
* Register to the websocket
|
|
78
89
|
* @param {string} llmSocketUrl
|
|
@@ -132,6 +143,15 @@ var LLMChannel = exports.default = /*#__PURE__*/function (_ref) {
|
|
|
132
143
|
*/
|
|
133
144
|
(0, _defineProperty3.default)(_this, "registerAndConnect", function (locusUrl, datachannelUrl, datachannelToken) {
|
|
134
145
|
var sessionId = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : _constants.LLM_DEFAULT_SESSION;
|
|
146
|
+
// Pre-populate locusUrl and datachannelUrl before register() fires the
|
|
147
|
+
// HTTP POST, so that any token refresh triggered during registration can
|
|
148
|
+
// be routed via connections without falling back to a locusInfo URL scan.
|
|
149
|
+
if (locusUrl && datachannelUrl) {
|
|
150
|
+
var sessionData = _this.connections.get(sessionId) || {};
|
|
151
|
+
sessionData.locusUrl = locusUrl;
|
|
152
|
+
sessionData.datachannelUrl = datachannelUrl;
|
|
153
|
+
_this.connections.set(sessionId, sessionData);
|
|
154
|
+
}
|
|
135
155
|
return _this.register(datachannelUrl, datachannelToken, sessionId).then(/*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee2() {
|
|
136
156
|
var sessionData, isDataChannelTokenEnabled, connectUrl;
|
|
137
157
|
return _regenerator.default.wrap(function (_context2) {
|
|
@@ -143,12 +163,10 @@ var LLMChannel = exports.default = /*#__PURE__*/function (_ref) {
|
|
|
143
163
|
}
|
|
144
164
|
return _context2.abrupt("return", undefined);
|
|
145
165
|
case 1:
|
|
146
|
-
//
|
|
166
|
+
// locusUrl and datachannelUrl were pre-populated before register(); here
|
|
167
|
+
// we only need to read the existing session data to get webSocketUrl/binding
|
|
168
|
+
// that register() filled in.
|
|
147
169
|
sessionData = _this.connections.get(sessionId) || {};
|
|
148
|
-
sessionData.locusUrl = locusUrl;
|
|
149
|
-
sessionData.datachannelUrl = datachannelUrl;
|
|
150
|
-
sessionData.datachannelToken = datachannelToken;
|
|
151
|
-
_this.connections.set(sessionId, sessionData);
|
|
152
170
|
_context2.next = 2;
|
|
153
171
|
return _this.isDataChannelTokenEnabled();
|
|
154
172
|
case 2:
|
|
@@ -202,36 +220,149 @@ var LLMChannel = exports.default = /*#__PURE__*/function (_ref) {
|
|
|
202
220
|
var sessionData = _this.connections.get(sessionId);
|
|
203
221
|
return sessionData === null || sessionData === void 0 ? void 0 : sessionData.datachannelUrl;
|
|
204
222
|
});
|
|
223
|
+
/**
|
|
224
|
+
* Set the owner meeting ID for a given LLM session. Used by the meetings
|
|
225
|
+
* plugin to tag which Meeting instance currently owns the (default) LLM
|
|
226
|
+
* connection so that other Meeting instances can avoid disconnecting or
|
|
227
|
+
* re-initializing a connection they do not own.
|
|
228
|
+
*
|
|
229
|
+
* Does NOT create a connections entry if one does not already exist — this
|
|
230
|
+
* method is a no-op when there is no active session data. Callers should
|
|
231
|
+
* invoke it after a successful `registerAndConnect` or during an explicit
|
|
232
|
+
* ownership handoff.
|
|
233
|
+
*
|
|
234
|
+
* @param {string | undefined} ownerMeetingId - Meeting ID (or undefined to clear)
|
|
235
|
+
* @param {string} sessionId - Connection identifier (defaults to default session)
|
|
236
|
+
* @returns {void}
|
|
237
|
+
*/
|
|
238
|
+
(0, _defineProperty3.default)(_this, "setOwnerMeetingId", function (ownerMeetingId) {
|
|
239
|
+
var sessionId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _constants.LLM_DEFAULT_SESSION;
|
|
240
|
+
var sessionData = _this.connections.get(sessionId);
|
|
241
|
+
if (!sessionData) {
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
sessionData.ownerMeetingId = ownerMeetingId;
|
|
245
|
+
_this.connections.set(sessionId, sessionData);
|
|
246
|
+
});
|
|
247
|
+
/**
|
|
248
|
+
* Get the owner meeting ID currently associated with an LLM session.
|
|
249
|
+
* Returns undefined when no owner has been assigned (e.g. before the
|
|
250
|
+
* first successful `registerAndConnect`, or after `disconnectLLM`).
|
|
251
|
+
*
|
|
252
|
+
* @param {string} sessionId - Connection identifier (defaults to default session)
|
|
253
|
+
* @returns {string | undefined} ownerMeetingId
|
|
254
|
+
*/
|
|
255
|
+
(0, _defineProperty3.default)(_this, "getOwnerMeetingId", function () {
|
|
256
|
+
var sessionId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _constants.LLM_DEFAULT_SESSION;
|
|
257
|
+
var sessionData = _this.connections.get(sessionId);
|
|
258
|
+
return sessionData === null || sessionData === void 0 ? void 0 : sessionData.ownerMeetingId;
|
|
259
|
+
});
|
|
260
|
+
/**
|
|
261
|
+
* Resolve ownership information for an LLM session.
|
|
262
|
+
*
|
|
263
|
+
* Rules:
|
|
264
|
+
* - no current owner => caller may proceed
|
|
265
|
+
* - caller has no identity to assert => treat as owner
|
|
266
|
+
* - otherwise caller must match current owner
|
|
267
|
+
*
|
|
268
|
+
* @param {string | undefined} ownerMeetingId - Candidate owner to evaluate
|
|
269
|
+
* @param {string} sessionId - Connection identifier (defaults to default session)
|
|
270
|
+
* @returns {{currentOwner: (string|undefined), isOwner: boolean}}
|
|
271
|
+
*/
|
|
272
|
+
(0, _defineProperty3.default)(_this, "resolveSessionOwnership", function (ownerMeetingId) {
|
|
273
|
+
var sessionId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _constants.LLM_DEFAULT_SESSION;
|
|
274
|
+
var currentOwner = _this.getOwnerMeetingId(sessionId);
|
|
275
|
+
var isOwner = !currentOwner || !ownerMeetingId || currentOwner === ownerMeetingId;
|
|
276
|
+
return {
|
|
277
|
+
currentOwner: currentOwner,
|
|
278
|
+
isOwner: isOwner
|
|
279
|
+
};
|
|
280
|
+
});
|
|
205
281
|
/**
|
|
206
282
|
* Get data channel token for the connection
|
|
207
|
-
* @param {DataChannelTokenType}
|
|
208
|
-
* @
|
|
283
|
+
* @param {DataChannelTokenType|string} tokenKey
|
|
284
|
+
* @param {string | undefined} ownerMeetingId - Meeting id asserting read ownership
|
|
285
|
+
* @returns {string | undefined} data channel token
|
|
209
286
|
*/
|
|
210
|
-
(0, _defineProperty3.default)(_this, "getDatachannelToken", function () {
|
|
211
|
-
var
|
|
212
|
-
|
|
287
|
+
(0, _defineProperty3.default)(_this, "getDatachannelToken", function (tokenKey, ownerMeetingId) {
|
|
288
|
+
var resolvedTokenKey = tokenKey !== null && tokenKey !== void 0 ? tokenKey : _llm.DataChannelTokenType.Default;
|
|
289
|
+
var _this$resolveSessionO = _this.resolveSessionOwnership(ownerMeetingId, resolvedTokenKey),
|
|
290
|
+
currentOwner = _this$resolveSessionO.currentOwner,
|
|
291
|
+
isOwner = _this$resolveSessionO.isOwner;
|
|
292
|
+
if (!isOwner) {
|
|
293
|
+
_this.logger.info("llm#getDatachannelToken --> skip read for session ".concat(resolvedTokenKey, "; owned by ").concat(currentOwner, ", candidate ").concat(ownerMeetingId));
|
|
294
|
+
return undefined;
|
|
295
|
+
}
|
|
296
|
+
return _this.datachannelTokens[resolvedTokenKey];
|
|
213
297
|
});
|
|
214
298
|
/**
|
|
215
299
|
* Set data channel token for the connection
|
|
216
300
|
* @param {string} datachannelToken - data channel token
|
|
217
|
-
* @param {DataChannelTokenType}
|
|
301
|
+
* @param {DataChannelTokenType|string} [tokenKey]
|
|
302
|
+
* @param {string | undefined} ownerMeetingId - Meeting id asserting write ownership
|
|
303
|
+
* @returns {void}
|
|
304
|
+
*/
|
|
305
|
+
(0, _defineProperty3.default)(_this, "setDatachannelToken", function (datachannelToken, tokenKey, ownerMeetingId) {
|
|
306
|
+
var resolvedTokenKey = tokenKey !== null && tokenKey !== void 0 ? tokenKey : _llm.DataChannelTokenType.Default;
|
|
307
|
+
var _this$resolveSessionO2 = _this.resolveSessionOwnership(ownerMeetingId, resolvedTokenKey),
|
|
308
|
+
currentOwner = _this$resolveSessionO2.currentOwner,
|
|
309
|
+
isOwner = _this$resolveSessionO2.isOwner;
|
|
310
|
+
if (!isOwner) {
|
|
311
|
+
_this.logger.info("llm#setDatachannelToken --> skip write for session ".concat(resolvedTokenKey, "; owned by ").concat(currentOwner, ", candidate ").concat(ownerMeetingId));
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
_this.datachannelTokens[resolvedTokenKey] = datachannelToken;
|
|
315
|
+
});
|
|
316
|
+
/**
|
|
317
|
+
* Clears a single session's data channel token.
|
|
318
|
+
* @param {DataChannelTokenType|string} tokenKey
|
|
319
|
+
* @param {string} ownerMeetingId - Meeting id asserting delete ownership
|
|
218
320
|
* @returns {void}
|
|
219
321
|
*/
|
|
220
|
-
(0, _defineProperty3.default)(_this, "
|
|
221
|
-
var
|
|
222
|
-
_this
|
|
322
|
+
(0, _defineProperty3.default)(_this, "clearDatachannelToken", function (tokenKey, ownerMeetingId) {
|
|
323
|
+
var resolvedTokenKey = tokenKey;
|
|
324
|
+
var _this$resolveSessionO3 = _this.resolveSessionOwnership(ownerMeetingId, resolvedTokenKey),
|
|
325
|
+
currentOwner = _this$resolveSessionO3.currentOwner,
|
|
326
|
+
isOwner = _this$resolveSessionO3.isOwner;
|
|
327
|
+
if (!isOwner) {
|
|
328
|
+
_this.logger.info("llm#clearDatachannelToken --> skip clear for session ".concat(resolvedTokenKey, "; owned by ").concat(currentOwner, ", candidate ").concat(ownerMeetingId));
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
_this.datachannelTokens[resolvedTokenKey] = undefined;
|
|
332
|
+
delete _this.datachannelTokens[resolvedTokenKey];
|
|
223
333
|
});
|
|
224
334
|
/**
|
|
225
335
|
* Disconnects websocket connection
|
|
226
336
|
* @param {{code: number, reason: string}} options - The disconnect option object with code and reason
|
|
227
337
|
* @param {string} sessionId - Connection identifier
|
|
228
|
-
* @
|
|
338
|
+
* @param {string} ownerMeetingId - Meeting id asserting disconnect ownership
|
|
339
|
+
* @returns {Promise<boolean>} True when disconnect was performed, false when skipped
|
|
229
340
|
*/
|
|
230
|
-
(0, _defineProperty3.default)(_this, "disconnectLLM", function (options) {
|
|
231
|
-
var
|
|
232
|
-
|
|
341
|
+
(0, _defineProperty3.default)(_this, "disconnectLLM", function (options, sessionId, ownerMeetingId) {
|
|
342
|
+
var resolvedSessionId = sessionId !== null && sessionId !== void 0 ? sessionId : _constants.LLM_DEFAULT_SESSION;
|
|
343
|
+
|
|
344
|
+
// Backward-compat path: historically callers could omit ownerMeetingId
|
|
345
|
+
// (and sometimes sessionId). Reuse current owner when available so legacy
|
|
346
|
+
// calls remain best-effort without throwing at teardown time.
|
|
347
|
+
var resolvedOwnerMeetingId = ownerMeetingId || _this.getOwnerMeetingId(resolvedSessionId);
|
|
348
|
+
if (!ownerMeetingId) {
|
|
349
|
+
_this.logger.warn("llm#disconnectLLM --> ownerMeetingId is omitted for session ".concat(resolvedSessionId, "; using legacy compatibility path"));
|
|
350
|
+
}
|
|
351
|
+
var _this$resolveSessionO4 = _this.resolveSessionOwnership(resolvedOwnerMeetingId, resolvedSessionId),
|
|
352
|
+
currentOwner = _this$resolveSessionO4.currentOwner,
|
|
353
|
+
isOwner = _this$resolveSessionO4.isOwner;
|
|
354
|
+
if (!isOwner) {
|
|
355
|
+
_this.logger.info("llm#disconnectLLM --> skip disconnect for session ".concat(resolvedSessionId, "; owned by ").concat(currentOwner, ", candidate ").concat(resolvedOwnerMeetingId));
|
|
356
|
+
return _promise.default.resolve(false);
|
|
357
|
+
}
|
|
358
|
+
return _this.disconnect(options, resolvedSessionId).then(function () {
|
|
359
|
+
// Clear owner tag before cleanup to ensure it's not lingering
|
|
360
|
+
// if another meeting claimed it during disconnect
|
|
361
|
+
_this.setOwnerMeetingId(undefined, resolvedSessionId);
|
|
362
|
+
|
|
233
363
|
// Clean up sessions data
|
|
234
|
-
_this.connections.delete(
|
|
364
|
+
_this.connections.delete(resolvedSessionId);
|
|
365
|
+
return true;
|
|
235
366
|
});
|
|
236
367
|
});
|
|
237
368
|
/**
|
|
@@ -256,53 +387,76 @@ var LLMChannel = exports.default = /*#__PURE__*/function (_ref) {
|
|
|
256
387
|
}
|
|
257
388
|
(0, _inherits2.default)(LLMChannel, _ref);
|
|
258
389
|
return (0, _createClass2.default)(LLMChannel, [{
|
|
259
|
-
key: "
|
|
390
|
+
key: "setRefreshHandler",
|
|
260
391
|
value:
|
|
261
|
-
/**
|
|
262
|
-
* Resets all data‑channel tokens to their initial undefined values.
|
|
263
|
-
* Used when leaving or disconnecting from a meeting.
|
|
264
|
-
* @returns {void}
|
|
265
|
-
*/
|
|
266
|
-
function resetDatachannelTokens() {
|
|
267
|
-
this.datachannelTokens = (0, _defineProperty3.default)((0, _defineProperty3.default)({}, _llm.DataChannelTokenType.Default, undefined), _llm.DataChannelTokenType.PracticeSession, undefined);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
392
|
/**
|
|
271
393
|
* Set the handler used to refresh the DataChannel token
|
|
272
394
|
*
|
|
273
395
|
* @param {function} handler - Function that returns a refreshed token
|
|
396
|
+
* @param {string} [sessionId] - Connection identifier
|
|
397
|
+
* @param {string | undefined} ownerMeetingId - Meeting id asserting refresh-handler ownership
|
|
274
398
|
* @returns {void}
|
|
275
399
|
*/
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
400
|
+
function setRefreshHandler(handler, sessionId, ownerMeetingId) {
|
|
401
|
+
var resolvedSessionId = sessionId !== null && sessionId !== void 0 ? sessionId : _constants.LLM_DEFAULT_SESSION;
|
|
402
|
+
var _this$resolveSessionO5 = this.resolveSessionOwnership(ownerMeetingId, resolvedSessionId),
|
|
403
|
+
currentOwner = _this$resolveSessionO5.currentOwner,
|
|
404
|
+
isOwner = _this$resolveSessionO5.isOwner;
|
|
405
|
+
if (!isOwner) {
|
|
406
|
+
this.logger.info("llm#setRefreshHandler --> skip write for session ".concat(resolvedSessionId, "; owned by ").concat(currentOwner, ", candidate ").concat(ownerMeetingId));
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
var sessionData = this.connections.get(resolvedSessionId);
|
|
410
|
+
if (sessionData) {
|
|
411
|
+
sessionData.refreshHandler = handler;
|
|
412
|
+
if (ownerMeetingId) {
|
|
413
|
+
sessionData.ownerMeetingId = ownerMeetingId;
|
|
414
|
+
}
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Intentionally allow a pre-connection session shape here.
|
|
419
|
+
// Some flows inject refreshHandler before register/connect so token refresh
|
|
420
|
+
// is already wired when the socket lifecycle starts. register()/
|
|
421
|
+
// registerAndConnect() will later fill webSocketUrl/binding/locusUrl/
|
|
422
|
+
// datachannelUrl into this same session entry.
|
|
423
|
+
this.connections.set(resolvedSessionId, {
|
|
424
|
+
refreshHandler: handler,
|
|
425
|
+
ownerMeetingId: ownerMeetingId
|
|
426
|
+
});
|
|
280
427
|
}
|
|
281
428
|
|
|
282
429
|
/**
|
|
283
430
|
* Refresh the data channel token using the injected handler.
|
|
284
431
|
* Logs a descriptive error if the handler is missing or fails.
|
|
285
|
-
*
|
|
432
|
+
* @param {string} sessionId - Connection identifier (defaults to default session)
|
|
286
433
|
* @returns {Promise<string>} The refreshed token.
|
|
287
434
|
*/
|
|
288
435
|
}, {
|
|
289
436
|
key: "refreshDataChannelToken",
|
|
290
437
|
value: (function () {
|
|
291
438
|
var _refreshDataChannelToken = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee3() {
|
|
292
|
-
var
|
|
439
|
+
var _this$connections$get;
|
|
440
|
+
var sessionId,
|
|
441
|
+
refreshHandler,
|
|
442
|
+
res,
|
|
443
|
+
_args3 = arguments,
|
|
444
|
+
_t;
|
|
293
445
|
return _regenerator.default.wrap(function (_context3) {
|
|
294
446
|
while (1) switch (_context3.prev = _context3.next) {
|
|
295
447
|
case 0:
|
|
296
|
-
|
|
448
|
+
sessionId = _args3.length > 0 && _args3[0] !== undefined ? _args3[0] : _constants.LLM_DEFAULT_SESSION;
|
|
449
|
+
refreshHandler = (_this$connections$get = this.connections.get(sessionId)) === null || _this$connections$get === void 0 ? void 0 : _this$connections$get.refreshHandler;
|
|
450
|
+
if (refreshHandler) {
|
|
297
451
|
_context3.next = 1;
|
|
298
452
|
break;
|
|
299
453
|
}
|
|
300
|
-
this.logger.warn(
|
|
454
|
+
this.logger.warn("llm#refreshDataChannelToken --> LLM refreshHandler is not set for session ".concat(sessionId, ", skipping token refresh"));
|
|
301
455
|
return _context3.abrupt("return", null);
|
|
302
456
|
case 1:
|
|
303
457
|
_context3.prev = 1;
|
|
304
458
|
_context3.next = 2;
|
|
305
|
-
return
|
|
459
|
+
return refreshHandler();
|
|
306
460
|
case 2:
|
|
307
461
|
res = _context3.sent;
|
|
308
462
|
return _context3.abrupt("return", res);
|
|
@@ -322,6 +476,74 @@ var LLMChannel = exports.default = /*#__PURE__*/function (_ref) {
|
|
|
322
476
|
}
|
|
323
477
|
return refreshDataChannelToken;
|
|
324
478
|
}())
|
|
479
|
+
}, {
|
|
480
|
+
key: "getLocusUrlByDatachannelUrl",
|
|
481
|
+
value:
|
|
482
|
+
/**
|
|
483
|
+
* Look up the locusUrl associated with a datachannel request URL.
|
|
484
|
+
* Iterates all active LLM sessions and returns the locusUrl of the
|
|
485
|
+
* session whose stored datachannelUrl is a prefix of the given request URL.
|
|
486
|
+
*
|
|
487
|
+
* @param {string} requestUrl - The in-flight request URL to match
|
|
488
|
+
* @returns {string | undefined} The matching locusUrl, or undefined if not found
|
|
489
|
+
*/
|
|
490
|
+
function getLocusUrlByDatachannelUrl(requestUrl) {
|
|
491
|
+
var _iterator = _createForOfIteratorHelper(this.connections),
|
|
492
|
+
_step;
|
|
493
|
+
try {
|
|
494
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
495
|
+
var _step$value = (0, _slicedToArray2.default)(_step.value, 2),
|
|
496
|
+
connection = _step$value[1];
|
|
497
|
+
if (connection.datachannelUrl && LLMChannel.matchesDatachannelRequestUrl(requestUrl, connection.datachannelUrl)) {
|
|
498
|
+
return connection.locusUrl;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
} catch (err) {
|
|
502
|
+
_iterator.e(err);
|
|
503
|
+
} finally {
|
|
504
|
+
_iterator.f();
|
|
505
|
+
}
|
|
506
|
+
return undefined;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Look up the sessionId associated with a datachannel request URL.
|
|
511
|
+
* Iterates all active LLM sessions and returns the sessionId whose
|
|
512
|
+
* stored datachannelUrl is a prefix of the given request URL.
|
|
513
|
+
*
|
|
514
|
+
* @param {string} requestUrl - The in-flight request URL to match
|
|
515
|
+
* @returns {string | undefined} The matching sessionId, or undefined if not found
|
|
516
|
+
*/
|
|
517
|
+
}, {
|
|
518
|
+
key: "getSessionIdByDatachannelUrl",
|
|
519
|
+
value: function getSessionIdByDatachannelUrl(requestUrl) {
|
|
520
|
+
var _iterator2 = _createForOfIteratorHelper(this.connections),
|
|
521
|
+
_step2;
|
|
522
|
+
try {
|
|
523
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
524
|
+
var _step2$value = (0, _slicedToArray2.default)(_step2.value, 2),
|
|
525
|
+
sessionId = _step2$value[0],
|
|
526
|
+
connection = _step2$value[1];
|
|
527
|
+
if (connection.datachannelUrl && LLMChannel.matchesDatachannelRequestUrl(requestUrl, connection.datachannelUrl)) {
|
|
528
|
+
return sessionId;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
} catch (err) {
|
|
532
|
+
_iterator2.e(err);
|
|
533
|
+
} finally {
|
|
534
|
+
_iterator2.f();
|
|
535
|
+
}
|
|
536
|
+
return undefined;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* Matches a request URL to a stored datachannel registration URL.
|
|
541
|
+
* Host can differ (e.g. rewritten by hostmap interceptor), so we first
|
|
542
|
+
* try full URL prefix and then fall back to pathname prefix.
|
|
543
|
+
* @param {string} requestUrl
|
|
544
|
+
* @param {string} registrationUrl
|
|
545
|
+
* @returns {boolean}
|
|
546
|
+
*/
|
|
325
547
|
}, {
|
|
326
548
|
key: "isDataChannelTokenEnabled",
|
|
327
549
|
value:
|
|
@@ -341,6 +563,23 @@ var LLMChannel = exports.default = /*#__PURE__*/function (_ref) {
|
|
|
341
563
|
* @param {string[]} subchannels - List of subchannels to declare as subscription-aware.
|
|
342
564
|
* @returns {string} The final URL with updated query parameters.
|
|
343
565
|
*/
|
|
566
|
+
}], [{
|
|
567
|
+
key: "matchesDatachannelRequestUrl",
|
|
568
|
+
value: function matchesDatachannelRequestUrl(requestUrl, registrationUrl) {
|
|
569
|
+
if (!requestUrl || !registrationUrl) {
|
|
570
|
+
return false;
|
|
571
|
+
}
|
|
572
|
+
if (requestUrl.startsWith(registrationUrl)) {
|
|
573
|
+
return true;
|
|
574
|
+
}
|
|
575
|
+
try {
|
|
576
|
+
var request = new URL(requestUrl);
|
|
577
|
+
var registration = new URL(registrationUrl);
|
|
578
|
+
return request.pathname.startsWith(registration.pathname);
|
|
579
|
+
} catch (error) {
|
|
580
|
+
return false;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
344
583
|
}]);
|
|
345
584
|
}(_internalPluginMercury.default);
|
|
346
585
|
(0, _defineProperty3.default)(LLMChannel, "buildUrlWithAwareSubchannels", function (baseUrl, subchannels) {
|