@webex/internal-plugin-mercury 3.8.1-web-workers-keepalive.1 → 3.9.0-multiple-llm.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/mercury.js CHANGED
@@ -1,5 +1,9 @@
1
1
  "use strict";
2
2
 
3
+ var _Array$from = require("@babel/runtime-corejs2/core-js/array/from");
4
+ var _Symbol = require("@babel/runtime-corejs2/core-js/symbol");
5
+ var _Symbol$iterator = require("@babel/runtime-corejs2/core-js/symbol/iterator");
6
+ var _Array$isArray = require("@babel/runtime-corejs2/core-js/array/is-array");
3
7
  var _Object$keys2 = require("@babel/runtime-corejs2/core-js/object/keys");
4
8
  var _Object$getOwnPropertySymbols = require("@babel/runtime-corejs2/core-js/object/get-own-property-symbols");
5
9
  var _Object$getOwnPropertyDescriptor2 = require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptor");
@@ -11,6 +15,7 @@ _Object$defineProperty(exports, "__esModule", {
11
15
  value: true
12
16
  });
13
17
  exports.default = void 0;
18
+ var _map = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/map"));
14
19
  var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
15
20
  var _keys = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/keys"));
16
21
  var _assign = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/assign"));
@@ -34,10 +39,14 @@ var _dec, _dec2, _obj;
34
39
  */
35
40
  function ownKeys(e, r) { var t = _Object$keys2(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return _Object$getOwnPropertyDescriptor2(e, r).enumerable; })), t.push.apply(t, o); } return t; }
36
41
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor2(t, r)); }); } return e; }
42
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof _Symbol !== "undefined" && o[_Symbol$iterator] || o["@@iterator"]; if (!it) { if (_Array$isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, 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 normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
43
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return _Array$from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
44
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
37
45
  var normalReconnectReasons = ['idle', 'done (forced)', 'pong not received', 'pong mismatch'];
38
46
  var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mercury#listen(): Use Mercury#connect() instead'), _dec2 = (0, _common.deprecated)('Mercury#stopListening(): Use Mercury#disconnect() instead'), (_obj = {
39
47
  namespace: 'Mercury',
40
48
  lastError: undefined,
49
+ defaultSessionId: 'mercury-default-session',
41
50
  session: {
42
51
  connected: {
43
52
  default: false,
@@ -51,7 +60,18 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
51
60
  default: false,
52
61
  type: 'boolean'
53
62
  },
54
- socket: 'object',
63
+ sockets: {
64
+ default: function _default() {
65
+ return new _map.default();
66
+ },
67
+ type: 'object'
68
+ },
69
+ backoffCalls: {
70
+ default: function _default() {
71
+ return new _map.default();
72
+ },
73
+ type: 'object'
74
+ },
55
75
  localClusterServiceUrls: 'object',
56
76
  mercuryTimeOffset: {
57
77
  default: undefined,
@@ -87,41 +107,159 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
87
107
  getLastError: function getLastError() {
88
108
  return this.lastError;
89
109
  },
110
+ /**
111
+ * Get all active socket connections
112
+ * @returns {Map} Map of sessionId to socket instances
113
+ */
114
+ getSockets: function getSockets() {
115
+ return this.sockets;
116
+ },
117
+ /**
118
+ * Get a specific socket by connection ID
119
+ * @param {string} sessionId - The connection identifier
120
+ * @returns {Socket|undefined} The socket instance or undefined if not found
121
+ */
122
+ getSocket: function getSocket() {
123
+ var sessionId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.defaultSessionId;
124
+ return this.sockets.get(sessionId);
125
+ },
126
+ /**
127
+ * Check if any sockets are connected
128
+ * @returns {boolean} True if at least one socket is connected
129
+ */
130
+ hasConnectedSockets: function hasConnectedSockets() {
131
+ var _iterator = _createForOfIteratorHelper(this.sockets.values()),
132
+ _step;
133
+ try {
134
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
135
+ var socket = _step.value;
136
+ if (socket && socket.connected) {
137
+ return true;
138
+ }
139
+ }
140
+ } catch (err) {
141
+ _iterator.e(err);
142
+ } finally {
143
+ _iterator.f();
144
+ }
145
+ return false;
146
+ },
147
+ /**
148
+ * Check if any sockets are connecting
149
+ * @returns {boolean} True if at least one socket is connected
150
+ */
151
+ hasConnectingSockets: function hasConnectingSockets() {
152
+ var _iterator2 = _createForOfIteratorHelper(this.sockets.values()),
153
+ _step2;
154
+ try {
155
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
156
+ var socket = _step2.value;
157
+ if (socket && socket.connecting) {
158
+ return true;
159
+ }
160
+ }
161
+ } catch (err) {
162
+ _iterator2.e(err);
163
+ } finally {
164
+ _iterator2.f();
165
+ }
166
+ return false;
167
+ },
168
+ // @oneFlight
90
169
  connect: function connect(webSocketUrl) {
91
170
  var _this2 = this;
92
- if (this.connected) {
93
- this.logger.info("".concat(this.namespace, ": already connected, will not connect again"));
171
+ var sessionId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.defaultSessionId;
172
+ if (!this._connectPromises) this._connectPromises = new _map.default();
173
+
174
+ // First check if there's already a connection promise for this session
175
+ if (this._connectPromises.has(sessionId)) {
176
+ this.logger.info("".concat(this.namespace, ": connection ").concat(sessionId, " already in progress, returning existing promise"));
177
+ return this._connectPromises.get(sessionId);
178
+ }
179
+ var sessionSocket = this.sockets.get(sessionId);
180
+ if (sessionSocket !== null && sessionSocket !== void 0 && sessionSocket.connected || sessionSocket !== null && sessionSocket !== void 0 && sessionSocket.connecting) {
181
+ this.logger.info("".concat(this.namespace, ": connection ").concat(sessionId, " already connected, will not connect again"));
94
182
  return _promise.default.resolve();
95
183
  }
96
184
  this.connecting = true;
97
- this.logger.info("".concat(this.namespace, ": starting connection attempt"));
185
+ this.logger.info("".concat(this.namespace, ": starting connection attempt for ").concat(sessionId));
98
186
  this.logger.info("".concat(this.namespace, ": debug_mercury_logging stack: "), new Error('debug_mercury_logging').stack);
99
- return _promise.default.resolve(this.webex.internal.device.registered || this.webex.internal.device.register()).then(function () {
100
- _this2.logger.info("".concat(_this2.namespace, ": connecting"));
101
- return _this2._connectWithBackoff(webSocketUrl);
187
+ var connectPromise = _promise.default.resolve(this.webex.internal.device.registered || this.webex.internal.device.register()).then(function () {
188
+ _this2.logger.info("".concat(_this2.namespace, ": connecting ").concat(sessionId));
189
+ return _this2._connectWithBackoff(webSocketUrl, sessionId);
190
+ }).finally(function () {
191
+ _this2._connectPromises.delete(sessionId);
102
192
  });
193
+ this._connectPromises.set(sessionId, connectPromise);
194
+ return connectPromise;
103
195
  },
104
196
  logout: function logout() {
105
197
  this.logger.info("".concat(this.namespace, ": logout() called"));
106
198
  this.logger.info("".concat(this.namespace, ": debug_mercury_logging stack: "), new Error('debug_mercury_logging').stack);
107
- return this.disconnect(this.config.beforeLogoutOptionsCloseReason && !normalReconnectReasons.includes(this.config.beforeLogoutOptionsCloseReason) ? {
199
+ return this.disconnectAll(this.config.beforeLogoutOptionsCloseReason && !normalReconnectReasons.includes(this.config.beforeLogoutOptionsCloseReason) ? {
108
200
  code: 3050,
109
201
  reason: this.config.beforeLogoutOptionsCloseReason
110
202
  } : undefined);
111
203
  },
204
+ // @oneFlight
112
205
  disconnect: function disconnect(options) {
113
206
  var _this3 = this;
207
+ var sessionId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.defaultSessionId;
114
208
  return new _promise.default(function (resolve) {
115
- if (_this3.backoffCall) {
116
- _this3.logger.info("".concat(_this3.namespace, ": aborting connection"));
117
- _this3.backoffCall.abort();
209
+ var backoffCall = _this3.backoffCalls.get(sessionId);
210
+ if (backoffCall) {
211
+ _this3.logger.info("".concat(_this3.namespace, ": aborting connection ").concat(sessionId));
212
+ backoffCall.abort();
213
+ _this3.backoffCalls.delete(sessionId);
118
214
  }
119
- if (_this3.socket) {
120
- _this3.socket.removeAllListeners('message');
121
- _this3.once('offline', resolve);
122
- resolve(_this3.socket.close(options || undefined));
215
+
216
+ // Clean up any pending connection promises
217
+ if (_this3._connectPromises) {
218
+ _this3._connectPromises.delete(sessionId);
219
+ }
220
+ var sessionSocket = _this3.sockets.get(sessionId);
221
+ var suffix = sessionId === _this3.defaultSessionId ? '' : ":".concat(sessionId);
222
+ if (sessionSocket) {
223
+ sessionSocket.removeAllListeners('message');
224
+ sessionSocket.connecting = false;
225
+ sessionSocket.connected = false;
226
+ _this3.once(sessionId === _this3.defaultSessionId ? 'offline' : "offline".concat(suffix), resolve);
227
+ resolve(sessionSocket.close(options || undefined));
123
228
  }
124
229
  resolve();
230
+
231
+ // Update overall connected status
232
+ _this3.connected = _this3.hasConnectedSockets();
233
+ });
234
+ },
235
+ /**
236
+ * Disconnect all socket connections
237
+ * @param {object} options - Close options
238
+ * @returns {Promise} Promise that resolves when all connections are closed
239
+ */
240
+ disconnectAll: function disconnectAll(options) {
241
+ var _this4 = this;
242
+ var disconnectPromises = [];
243
+ var _iterator3 = _createForOfIteratorHelper(this.sockets.keys()),
244
+ _step3;
245
+ try {
246
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
247
+ var sessionId = _step3.value;
248
+ disconnectPromises.push(this.disconnect(options, sessionId));
249
+ }
250
+ } catch (err) {
251
+ _iterator3.e(err);
252
+ } finally {
253
+ _iterator3.f();
254
+ }
255
+ return _promise.default.all(disconnectPromises).then(function () {
256
+ _this4.connected = false;
257
+ _this4.sockets.clear();
258
+ _this4.backoffCalls.clear();
259
+ // Clear connection promises to prevent stale promises
260
+ if (_this4._connectPromises) {
261
+ _this4._connectPromises.clear();
262
+ }
125
263
  });
126
264
  },
127
265
  listen: function listen() {
@@ -145,19 +283,19 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
145
283
  });
146
284
  },
147
285
  _prepareUrl: function _prepareUrl(webSocketUrl) {
148
- var _this4 = this;
286
+ var _this5 = this;
149
287
  if (!webSocketUrl) {
150
288
  webSocketUrl = this.webex.internal.device.webSocketUrl;
151
289
  }
152
290
  return this.webex.internal.feature.getFeature('developer', 'web-high-availability').then(function (haMessagingEnabled) {
153
291
  if (haMessagingEnabled) {
154
- return _this4.webex.internal.services.convertUrlToPriorityHostUrl(webSocketUrl);
292
+ return _this5.webex.internal.services.convertUrlToPriorityHostUrl(webSocketUrl);
155
293
  }
156
294
  return webSocketUrl;
157
295
  }).then(function (wsUrl) {
158
296
  webSocketUrl = wsUrl;
159
297
  }).then(function () {
160
- return _this4.webex.internal.feature.getFeature('developer', 'web-shared-mercury');
298
+ return _this5.webex.internal.feature.getFeature('developer', 'web-shared-mercury');
161
299
  }).then(function (webSharedMercury) {
162
300
  webSocketUrl = _url.default.parse(webSocketUrl, true);
163
301
  (0, _assign.default)(webSocketUrl.query, {
@@ -172,104 +310,117 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
172
310
  });
173
311
  (0, _deleteProperty.default)(webSocketUrl.query, 'bufferStates');
174
312
  }
175
- if ((0, _lodash.get)(_this4, 'webex.config.device.ephemeral', false)) {
313
+ if ((0, _lodash.get)(_this5, 'webex.config.device.ephemeral', false)) {
176
314
  webSocketUrl.query.multipleConnections = true;
177
315
  }
178
316
  webSocketUrl.query.clientTimestamp = (0, _now.default)();
179
317
  return _url.default.format(webSocketUrl);
180
318
  });
181
319
  },
182
- _attemptConnection: function _attemptConnection(socketUrl, callback) {
183
- var _this5 = this;
320
+ _attemptConnection: function _attemptConnection(socketUrl, sessionId, callback) {
321
+ var _this6 = this;
184
322
  var socket = new _socket.default();
323
+ socket.connecting = true;
185
324
  var attemptWSUrl;
325
+ var suffix = sessionId === this.defaultSessionId ? '' : ":".concat(sessionId);
186
326
  socket.on('close', function () {
187
- return _this5._onclose.apply(_this5, arguments);
327
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
328
+ args[_key] = arguments[_key];
329
+ }
330
+ return _this6._onclose.apply(_this6, [sessionId].concat(args));
188
331
  });
189
332
  socket.on('message', function () {
190
- return _this5._onmessage.apply(_this5, arguments);
333
+ for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
334
+ args[_key2] = arguments[_key2];
335
+ }
336
+ return _this6._onmessage.apply(_this6, [sessionId].concat(args));
191
337
  });
192
338
  socket.on('pong', function () {
193
- return _this5._setTimeOffset.apply(_this5, arguments);
339
+ for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
340
+ args[_key3] = arguments[_key3];
341
+ }
342
+ return _this6._setTimeOffset.apply(_this6, [sessionId].concat(args));
194
343
  });
195
344
  socket.on('sequence-mismatch', function () {
196
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
197
- args[_key] = arguments[_key];
345
+ for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
346
+ args[_key4] = arguments[_key4];
198
347
  }
199
- return _this5._emit.apply(_this5, ['sequence-mismatch'].concat(args));
348
+ return _this6._emit.apply(_this6, ["sequence-mismatch".concat(suffix)].concat(args));
200
349
  });
201
350
  socket.on('ping-pong-latency', function () {
202
- for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
203
- args[_key2] = arguments[_key2];
351
+ for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
352
+ args[_key5] = arguments[_key5];
204
353
  }
205
- return _this5._emit.apply(_this5, ['ping-pong-latency'].concat(args));
354
+ return _this6._emit.apply(_this6, ["ping-pong-latency".concat(suffix)].concat(args));
206
355
  });
207
356
  _promise.default.all([this._prepareUrl(socketUrl), this.webex.credentials.getUserToken()]).then(function (_ref) {
208
357
  var _ref2 = (0, _slicedToArray2.default)(_ref, 2),
209
358
  webSocketUrl = _ref2[0],
210
359
  token = _ref2[1];
211
- if (!_this5.backoffCall) {
212
- var msg = "".concat(_this5.namespace, ": prevent socket open when backoffCall no longer defined");
213
- _this5.logger.info(msg);
360
+ var backoffCall = _this6.backoffCalls.get(sessionId);
361
+ if (!backoffCall) {
362
+ var msg = "".concat(_this6.namespace, ": prevent socket open when backoffCall no longer defined for ").concat(sessionId);
363
+ _this6.logger.info(msg);
214
364
  return _promise.default.reject(new Error(msg));
215
365
  }
216
366
  attemptWSUrl = webSocketUrl;
217
367
  var options = {
218
- forceCloseDelay: _this5.config.forceCloseDelay,
219
- pingInterval: _this5.config.pingInterval,
220
- pongTimeout: _this5.config.pongTimeout,
368
+ forceCloseDelay: _this6.config.forceCloseDelay,
369
+ pingInterval: _this6.config.pingInterval,
370
+ pongTimeout: _this6.config.pongTimeout,
221
371
  token: token.toString(),
222
- trackingId: "".concat(_this5.webex.sessionId, "_").concat((0, _now.default)()),
223
- logger: _this5.logger
372
+ trackingId: "".concat(_this6.webex.sessionId, "_").concat(sessionId, "_").concat((0, _now.default)()),
373
+ logger: _this6.logger
224
374
  };
225
375
 
226
376
  // if the consumer has supplied request options use them
227
- if (_this5.webex.config.defaultMercuryOptions) {
228
- _this5.logger.info("".concat(_this5.namespace, ": setting custom options"));
229
- options = _objectSpread(_objectSpread({}, options), _this5.webex.config.defaultMercuryOptions);
377
+ if (_this6.webex.config.defaultMercuryOptions) {
378
+ _this6.logger.info("".concat(_this6.namespace, ": setting custom options for ").concat(sessionId));
379
+ options = _objectSpread(_objectSpread({}, options), _this6.webex.config.defaultMercuryOptions);
230
380
  }
231
381
 
232
382
  // Set the socket before opening it. This allows a disconnect() to close
233
383
  // the socket if it is in the process of being opened.
234
- _this5.socket = socket;
235
- _this5.logger.info("".concat(_this5.namespace, " connection url: ").concat(webSocketUrl));
384
+ _this6.sockets.set(sessionId, socket);
385
+ _this6.socket = _this6.sockets.get(_this6.defaultSessionId) || socket;
386
+ _this6.logger.info("".concat(_this6.namespace, " connection url for ").concat(sessionId, ": ").concat(webSocketUrl));
236
387
  return socket.open(webSocketUrl, options);
237
388
  }).then(function () {
238
- _this5.logger.info("".concat(_this5.namespace, ": connected to mercury, success, action: connected, url: ").concat(attemptWSUrl));
389
+ _this6.logger.info("".concat(_this6.namespace, ": connected to mercury, success, action: connected, sessionId: ").concat(sessionId, ", url: ").concat(attemptWSUrl));
239
390
  callback();
240
- return _this5.webex.internal.feature.getFeature('developer', 'web-high-availability').then(function (haMessagingEnabled) {
391
+ return _this6.webex.internal.feature.getFeature('developer', 'web-high-availability').then(function (haMessagingEnabled) {
241
392
  if (haMessagingEnabled) {
242
- return _this5.webex.internal.device.refresh();
393
+ return _this6.webex.internal.device.refresh();
243
394
  }
244
395
  return _promise.default.resolve();
245
396
  });
246
397
  }).catch(function (reason) {
247
- var _this5$backoffCall, _this5$backoffCall3;
248
- _this5.lastError = reason; // remember the last error
398
+ _this6.lastError = reason; // remember the last error
249
399
 
400
+ var backoffCall = _this6.backoffCalls.get(sessionId);
250
401
  // Suppress connection errors that appear to be network related. This
251
402
  // may end up suppressing metrics during outages, but we might not care
252
403
  // (especially since many of our outages happen in a way that client
253
404
  // metrics can't be trusted).
254
- if (reason.code !== 1006 && _this5.backoffCall && ((_this5$backoffCall = _this5.backoffCall) === null || _this5$backoffCall === void 0 ? void 0 : _this5$backoffCall.getNumRetries()) > 0) {
255
- var _this5$backoffCall2;
256
- _this5._emit('connection_failed', reason, {
257
- retries: (_this5$backoffCall2 = _this5.backoffCall) === null || _this5$backoffCall2 === void 0 ? void 0 : _this5$backoffCall2.getNumRetries()
405
+ if (reason.code !== 1006 && backoffCall && (backoffCall === null || backoffCall === void 0 ? void 0 : backoffCall.getNumRetries()) > 0) {
406
+ _this6._emit("connection_failed".concat(suffix), reason, {
407
+ sessionId: sessionId,
408
+ retries: backoffCall === null || backoffCall === void 0 ? void 0 : backoffCall.getNumRetries()
258
409
  });
259
410
  }
260
- _this5.logger.info("".concat(_this5.namespace, ": connection attempt failed"), reason, ((_this5$backoffCall3 = _this5.backoffCall) === null || _this5$backoffCall3 === void 0 ? void 0 : _this5$backoffCall3.getNumRetries()) === 0 ? reason.stack : '');
411
+ _this6.logger.info("".concat(_this6.namespace, ": connection attempt failed for ").concat(sessionId), reason, (backoffCall === null || backoffCall === void 0 ? void 0 : backoffCall.getNumRetries()) === 0 ? reason.stack : '');
261
412
  // UnknownResponse is produced by IE for any 4XXX; treated it like a bad
262
413
  // web socket url and let WDM handle the token checking
263
414
  if (reason instanceof _errors.UnknownResponse) {
264
- _this5.logger.info("".concat(_this5.namespace, ": received unknown response code, refreshing device registration"));
265
- return _this5.webex.internal.device.refresh().then(function () {
415
+ _this6.logger.info("".concat(_this6.namespace, ": received unknown response code for ").concat(sessionId, ", refreshing device registration"));
416
+ return _this6.webex.internal.device.refresh().then(function () {
266
417
  return callback(reason);
267
418
  });
268
419
  }
269
420
  // NotAuthorized implies expired token
270
421
  if (reason instanceof _errors.NotAuthorized) {
271
- _this5.logger.info("".concat(_this5.namespace, ": received authorization error, reauthorizing"));
272
- return _this5.webex.credentials.refresh({
422
+ _this6.logger.info("".concat(_this6.namespace, ": received authorization error for ").concat(sessionId, ", reauthorizing"));
423
+ return _this6.webex.credentials.refresh({
273
424
  force: true
274
425
  }).then(function () {
275
426
  return callback(reason);
@@ -284,15 +435,15 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
284
435
  // BadRequest implies current credentials are for a Service Account
285
436
  // Forbidden implies current user is not entitle for Webex
286
437
  if (reason instanceof _errors.BadRequest || reason instanceof _errors.Forbidden) {
287
- _this5.logger.warn("".concat(_this5.namespace, ": received unrecoverable response from mercury"));
288
- _this5.backoffCall.abort();
438
+ _this6.logger.warn("".concat(_this6.namespace, ": received unrecoverable response from mercury for ").concat(sessionId));
439
+ backoffCall === null || backoffCall === void 0 ? void 0 : backoffCall.abort();
289
440
  return callback(reason);
290
441
  }
291
442
  if (reason instanceof _errors.ConnectionError) {
292
- return _this5.webex.internal.feature.getFeature('developer', 'web-high-availability').then(function (haMessagingEnabled) {
443
+ return _this6.webex.internal.feature.getFeature('developer', 'web-high-availability').then(function (haMessagingEnabled) {
293
444
  if (haMessagingEnabled) {
294
- _this5.logger.info("".concat(_this5.namespace, ": received a generic connection error, will try to connect to another datacenter. failed, action: 'failed', url: ").concat(attemptWSUrl, " error: ").concat(reason.message));
295
- return _this5.webex.internal.services.markFailedUrl(attemptWSUrl);
445
+ _this6.logger.info("".concat(_this6.namespace, ": received a generic connection error for ").concat(sessionId, ", will try to connect to another datacenter. failed, action: 'failed', url: ").concat(attemptWSUrl, " error: ").concat(reason.message));
446
+ return _this6.webex.internal.services.markFailedUrl(attemptWSUrl);
296
447
  }
297
448
  return null;
298
449
  }).then(function () {
@@ -301,73 +452,96 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
301
452
  }
302
453
  return callback(reason);
303
454
  }).catch(function (reason) {
304
- _this5.logger.error("".concat(_this5.namespace, ": failed to handle connection failure"), reason);
455
+ _this6.logger.error("".concat(_this6.namespace, ": failed to handle connection failure for ").concat(sessionId), reason);
305
456
  callback(reason);
306
457
  });
307
458
  },
308
- _connectWithBackoff: function _connectWithBackoff(webSocketUrl) {
309
- var _this6 = this;
459
+ _connectWithBackoff: function _connectWithBackoff(webSocketUrl, sessionId) {
460
+ var _this7 = this;
310
461
  return new _promise.default(function (resolve, reject) {
311
462
  // eslint gets confused about whether or not call is actually used
312
463
  // eslint-disable-next-line prefer-const
313
464
  var call;
314
465
  var onComplete = function onComplete(err) {
315
- _this6.connecting = false;
316
- _this6.backoffCall = undefined;
466
+ var sid = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : sessionId;
467
+ _this7.backoffCalls.delete(sid);
317
468
  if (err) {
318
- _this6.logger.info("".concat(_this6.namespace, ": failed to connect after ").concat(call.getNumRetries(), " retries; log statement about next retry was inaccurate; ").concat(err));
469
+ _this7.logger.info("".concat(_this7.namespace, ": failed to connect ").concat(sid, " after ").concat(call.getNumRetries(), " retries; log statement about next retry was inaccurate; ").concat(err));
319
470
  return reject(err);
320
471
  }
321
- _this6.connected = true;
322
- _this6.hasEverConnected = true;
323
- _this6._emit('online');
324
- _this6.webex.internal.newMetrics.callDiagnosticMetrics.setMercuryConnectedStatus(true);
472
+ // Update overall connected status
473
+ var sessionSocket = _this7.sockets.get(sid);
474
+ if (sessionSocket) {
475
+ sessionSocket.connecting = false;
476
+ sessionSocket.connected = true;
477
+ }
478
+ // @ts-ignore
479
+ _this7.connecting = _this7.hasConnectingSockets();
480
+ _this7.connected = _this7.hasConnectedSockets();
481
+ _this7.hasEverConnected = true;
482
+ var suffix = sid === _this7.defaultSessionId ? '' : ":".concat(sid);
483
+ _this7._emit("online".concat(suffix), {
484
+ sessionId: sid
485
+ });
486
+ _this7.webex.internal.newMetrics.callDiagnosticMetrics.setMercuryConnectedStatus(true);
325
487
  return resolve();
326
488
  };
327
-
328
489
  // eslint-disable-next-line prefer-reflect
329
490
  call = _backoff.default.call(function (callback) {
330
- _this6.logger.info("".concat(_this6.namespace, ": executing connection attempt ").concat(call.getNumRetries()));
331
- _this6._attemptConnection(webSocketUrl, callback);
332
- }, onComplete);
491
+ _this7.logger.info("".concat(_this7.namespace, ": executing connection attempt ").concat(call.getNumRetries(), " for ").concat(sessionId));
492
+ _this7._attemptConnection(webSocketUrl, sessionId, callback);
493
+ }, function (err) {
494
+ return onComplete(err, sessionId);
495
+ });
333
496
  call.setStrategy(new _backoff.default.ExponentialStrategy({
334
- initialDelay: _this6.config.backoffTimeReset,
335
- maxDelay: _this6.config.backoffTimeMax
497
+ initialDelay: _this7.config.backoffTimeReset,
498
+ maxDelay: _this7.config.backoffTimeMax
336
499
  }));
337
- if (_this6.config.initialConnectionMaxRetries && !_this6.hasEverConnected) {
338
- call.failAfter(_this6.config.initialConnectionMaxRetries);
339
- } else if (_this6.config.maxRetries) {
340
- call.failAfter(_this6.config.maxRetries);
500
+ if (_this7.config.initialConnectionMaxRetries && !_this7.hasEverConnected) {
501
+ call.failAfter(_this7.config.initialConnectionMaxRetries);
502
+ } else if (_this7.config.maxRetries) {
503
+ call.failAfter(_this7.config.maxRetries);
341
504
  }
505
+
506
+ // Store the call BEFORE setting up event handlers to prevent race conditions
507
+ _this7.backoffCalls.set(sessionId, call);
342
508
  call.on('abort', function () {
343
- _this6.logger.info("".concat(_this6.namespace, ": connection aborted"));
344
- reject(new Error('Mercury Connection Aborted'));
509
+ _this7.logger.info("".concat(_this7.namespace, ": connection aborted for ").concat(sessionId));
510
+ reject(new Error("Mercury Connection Aborted for ".concat(sessionId)));
345
511
  });
346
512
  call.on('callback', function (err) {
347
513
  if (err) {
348
514
  var number = call.getNumRetries();
349
- var delay = Math.min(call.strategy_.nextBackoffDelay_, _this6.config.backoffTimeMax);
350
- _this6.logger.info("".concat(_this6.namespace, ": failed to connect; attempting retry ").concat(number + 1, " in ").concat(delay, " ms"));
515
+ var delay = Math.min(call.strategy_.nextBackoffDelay_, _this7.config.backoffTimeMax);
516
+ _this7.logger.info("".concat(_this7.namespace, ": failed to connect ").concat(sessionId, "; attempting retry ").concat(number + 1, " in ").concat(delay, " ms"));
351
517
  /* istanbul ignore if */
352
518
  if (process.env.NODE_ENV === 'development') {
353
- _this6.logger.debug("".concat(_this6.namespace, ": "), err, err.stack);
519
+ _this7.logger.debug("".concat(_this7.namespace, ": "), err, err.stack);
354
520
  }
355
521
  return;
356
522
  }
357
- _this6.logger.info("".concat(_this6.namespace, ": connected"));
523
+ _this7.logger.info("".concat(_this7.namespace, ": connected ").concat(sessionId));
358
524
  });
359
525
  call.start();
360
- _this6.backoffCall = call;
361
526
  });
362
527
  },
363
528
  _emit: function _emit() {
364
- for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
365
- args[_key3] = arguments[_key3];
529
+ for (var _len6 = arguments.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {
530
+ args[_key6] = arguments[_key6];
366
531
  }
367
532
  try {
368
- this.trigger.apply(this, args);
533
+ // Validate args before processing
534
+ if (args && args.length > 0) {
535
+ this.trigger.apply(this, args);
536
+ }
369
537
  } catch (error) {
370
- this.logger.error("".concat(this.namespace, ": error occurred in event handler:"), error, ' with args: ', args);
538
+ // Safely handle errors without causing additional issues during cleanup
539
+ try {
540
+ this.logger.error("".concat(this.namespace, ": error occurred in event handler:"), error, ' with args: ', args);
541
+ } catch (logError) {
542
+ // If even logging fails, just ignore to prevent cascading errors during cleanup
543
+ this.logger.error('Mercury _emit error handling failed:', logError);
544
+ }
371
545
  }
372
546
  },
373
547
  _getEventHandlers: function _getEventHandlers(eventType) {
@@ -388,36 +562,48 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
388
562
  }
389
563
  return handlers;
390
564
  },
391
- _onclose: function _onclose(event) {
565
+ _onclose: function _onclose(sessionId, event) {
392
566
  // I don't see any way to avoid the complexity or statement count in here.
393
567
  /* eslint complexity: [0] */
394
568
 
395
569
  try {
570
+ var _sessionSocket;
396
571
  var reason = event.reason && event.reason.toLowerCase();
397
- var socketUrl = this.socket.url;
398
- this.socket.removeAllListeners();
399
- this.unset('socket');
400
- this.connected = false;
401
- this._emit('offline', event);
402
- this.webex.internal.newMetrics.callDiagnosticMetrics.setMercuryConnectedStatus(false);
572
+ var sessionSocket = this.sockets.get(sessionId);
573
+ var socketUrl = (_sessionSocket = sessionSocket) === null || _sessionSocket === void 0 ? void 0 : _sessionSocket.url;
574
+ var suffix = sessionId === this.defaultSessionId ? '' : ":".concat(sessionId);
575
+ event.sessionId = sessionId;
576
+ this.sockets.delete(sessionId);
577
+ if (sessionSocket) {
578
+ sessionSocket.removeAllListeners();
579
+ sessionSocket = null;
580
+ this._emit("offline".concat(suffix), event);
581
+ }
582
+
583
+ // Update overall connected status
584
+ this.connecting = this.hasConnectingSockets();
585
+ this.connected = this.hasConnectedSockets();
586
+ if (!this.connected) {
587
+ this.webex.internal.newMetrics.callDiagnosticMetrics.setMercuryConnectedStatus(false);
588
+ }
403
589
  switch (event.code) {
404
590
  case 1003:
405
591
  // metric: disconnect
406
- this.logger.info("".concat(this.namespace, ": Mercury service rejected last message; will not reconnect: ").concat(event.reason));
407
- this._emit('offline.permanent', event);
592
+ this.logger.info("".concat(this.namespace, ": Mercury service rejected last message for ").concat(sessionId, "; will not reconnect: ").concat(event.reason));
593
+ this._emit("offline.permanent".concat(suffix), event);
408
594
  break;
409
595
  case 4000:
410
596
  // metric: disconnect
411
- this.logger.info("".concat(this.namespace, ": socket replaced; will not reconnect"));
412
- this._emit('offline.replaced', event);
597
+ this.logger.info("".concat(this.namespace, ": socket ").concat(sessionId, " replaced; will not reconnect"));
598
+ this._emit("offline.replaced".concat(suffix), event);
413
599
  break;
414
600
  case 1001:
415
601
  case 1005:
416
602
  case 1006:
417
603
  case 1011:
418
- this.logger.info("".concat(this.namespace, ": socket disconnected; reconnecting"));
419
- this._emit('offline.transient', event);
420
- this._reconnect(socketUrl);
604
+ this.logger.info("".concat(this.namespace, ": socket ").concat(sessionId, " disconnected; reconnecting"));
605
+ this._emit("offline.transient".concat(suffix), event);
606
+ this._reconnect(socketUrl, sessionId);
421
607
  // metric: disconnect
422
608
  // if (code == 1011 && reason !== ping error) metric: unexpected disconnect
423
609
  break;
@@ -425,32 +611,33 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
425
611
  case 3050:
426
612
  // 3050 indicates logout form of closure, default to old behavior, use config reason defined by consumer to proceed with the permanent block
427
613
  if (normalReconnectReasons.includes(reason)) {
428
- this.logger.info("".concat(this.namespace, ": socket disconnected; reconnecting"));
429
- this._emit('offline.transient', event);
430
- this._reconnect(socketUrl);
614
+ this.logger.info("".concat(this.namespace, ": socket ").concat(sessionId, " disconnected; reconnecting"));
615
+ this._emit("offline.transient".concat(suffix), event);
616
+ this._reconnect(socketUrl, sessionId);
431
617
  // metric: disconnect
432
618
  // if (reason === done forced) metric: force closure
433
619
  } else {
434
- this.logger.info("".concat(this.namespace, ": socket disconnected; will not reconnect: ").concat(event.reason));
435
- this._emit('offline.permanent', event);
620
+ this.logger.info("".concat(this.namespace, ": socket ").concat(sessionId, " disconnected; will not reconnect: ").concat(event.reason));
621
+ this._emit("offline.permanent".concat(suffix), event);
436
622
  }
437
623
  break;
438
624
  default:
439
- this.logger.info("".concat(this.namespace, ": socket disconnected unexpectedly; will not reconnect"));
625
+ this.logger.info("".concat(this.namespace, ": socket ").concat(sessionId, " disconnected unexpectedly; will not reconnect"));
440
626
  // unexpected disconnect
441
- this._emit('offline.permanent', event);
627
+ this._emit("offline.permanent".concat(suffix), event);
442
628
  }
443
629
  } catch (error) {
444
- this.logger.error("".concat(this.namespace, ": error occurred in close handler"), error);
630
+ this.logger.error("".concat(this.namespace, ": error occurred in close handler for ").concat(sessionId), error);
445
631
  }
446
632
  },
447
- _onmessage: function _onmessage(event) {
448
- var _this7 = this;
449
- this._setTimeOffset(event);
633
+ _onmessage: function _onmessage(sessionId, event) {
634
+ var _this8 = this;
635
+ this._setTimeOffset(sessionId, event);
450
636
  var envelope = event.data;
451
637
  if (process.env.ENABLE_MERCURY_LOGGING) {
452
- this.logger.debug("".concat(this.namespace, ": message envelope: "), envelope);
638
+ this.logger.debug("".concat(this.namespace, ": message envelope from ").concat(sessionId, ": "), envelope);
453
639
  }
640
+ envelope.sessionId = sessionId;
454
641
  var data = envelope.data;
455
642
  this._applyOverrides(data);
456
643
  return this._getEventHandlers(data.eventType).reduce(function (promise, handler) {
@@ -458,37 +645,39 @@ var Mercury = _webexCore.WebexPlugin.extend((_dec = (0, _common.deprecated)('Mer
458
645
  var namespace = handler.namespace,
459
646
  name = handler.name;
460
647
  return new _promise.default(function (resolve) {
461
- return resolve((_this7.webex[namespace] || _this7.webex.internal[namespace])[name](data));
648
+ return resolve((_this8.webex[namespace] || _this8.webex.internal[namespace])[name](data));
462
649
  }).catch(function (reason) {
463
- return _this7.logger.error("".concat(_this7.namespace, ": error occurred in autowired event handler for ").concat(data.eventType), reason);
650
+ return _this8.logger.error("".concat(_this8.namespace, ": error occurred in autowired event handler for ").concat(data.eventType, " from ").concat(sessionId), reason);
464
651
  });
465
652
  });
466
653
  }, _promise.default.resolve()).then(function () {
467
- _this7._emit('event', event.data);
654
+ var suffix = sessionId === _this8.defaultSessionId ? '' : ":".concat(sessionId);
655
+ _this8._emit("event".concat(suffix), envelope);
468
656
  var _data$eventType$split = data.eventType.split('.'),
469
657
  _data$eventType$split2 = (0, _slicedToArray2.default)(_data$eventType$split, 1),
470
658
  namespace = _data$eventType$split2[0];
471
659
  if (namespace === data.eventType) {
472
- _this7._emit("event:".concat(namespace), envelope);
660
+ _this8._emit("event:".concat(namespace).concat(suffix), envelope);
473
661
  } else {
474
- _this7._emit("event:".concat(namespace), envelope);
475
- _this7._emit("event:".concat(data.eventType), envelope);
662
+ _this8._emit("event:".concat(namespace).concat(suffix), envelope);
663
+ _this8._emit("event:".concat(data.eventType).concat(suffix), envelope);
476
664
  }
477
665
  }).catch(function (reason) {
478
- _this7.logger.error("".concat(_this7.namespace, ": error occurred processing socket message"), reason);
666
+ _this8.logger.error("".concat(_this8.namespace, ": error occurred processing socket message from ").concat(sessionId), reason);
479
667
  });
480
668
  },
481
- _setTimeOffset: function _setTimeOffset(event) {
669
+ _setTimeOffset: function _setTimeOffset(sessionId, event) {
482
670
  var wsWriteTimestamp = event.data.wsWriteTimestamp;
483
671
  if (typeof wsWriteTimestamp === 'number' && wsWriteTimestamp > 0) {
484
672
  this.mercuryTimeOffset = (0, _now.default)() - wsWriteTimestamp;
485
673
  }
486
674
  },
487
675
  _reconnect: function _reconnect(webSocketUrl) {
488
- this.logger.info("".concat(this.namespace, ": reconnecting"));
489
- return this.connect(webSocketUrl);
676
+ var sessionId = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.defaultSessionId;
677
+ this.logger.info("".concat(this.namespace, ": reconnecting ").concat(sessionId));
678
+ return this.connect(webSocketUrl, sessionId);
490
679
  },
491
- version: "3.8.1-web-workers-keepalive.1"
492
- }, ((0, _applyDecoratedDescriptor2.default)(_obj, "connect", [_common.oneFlight], (0, _getOwnPropertyDescriptor.default)(_obj, "connect"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "disconnect", [_common.oneFlight], (0, _getOwnPropertyDescriptor.default)(_obj, "disconnect"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "listen", [_dec], (0, _getOwnPropertyDescriptor.default)(_obj, "listen"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "stopListening", [_dec2], (0, _getOwnPropertyDescriptor.default)(_obj, "stopListening"), _obj)), _obj)));
493
- var _default = exports.default = Mercury;
680
+ version: "3.9.0-multiple-llm.1"
681
+ }, ((0, _applyDecoratedDescriptor2.default)(_obj, "listen", [_dec], (0, _getOwnPropertyDescriptor.default)(_obj, "listen"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "stopListening", [_dec2], (0, _getOwnPropertyDescriptor.default)(_obj, "stopListening"), _obj)), _obj)));
682
+ var _default2 = exports.default = Mercury;
494
683
  //# sourceMappingURL=mercury.js.map