@webex/plugin-meetings 3.12.0-next.44 → 3.12.0-next.45

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.
@@ -191,7 +191,7 @@ var AIEnableRequest = _webexCore.WebexPlugin.extend({
191
191
  method: _constants.HTTP_VERBS.PUT
192
192
  });
193
193
  },
194
- version: "3.12.0-next.44"
194
+ version: "3.12.0-next.45"
195
195
  });
196
196
  var _default = exports.default = AIEnableRequest;
197
197
  //# sourceMappingURL=index.js.map
@@ -213,7 +213,7 @@ var Breakout = _webexCore.WebexPlugin.extend({
213
213
  sessionId: this.sessionId
214
214
  });
215
215
  },
216
- version: "3.12.0-next.44"
216
+ version: "3.12.0-next.45"
217
217
  });
218
218
  var _default = exports.default = Breakout;
219
219
  //# sourceMappingURL=breakout.js.map
@@ -1109,7 +1109,7 @@ var Breakouts = _webexCore.WebexPlugin.extend({
1109
1109
  this.trigger(_constants.BREAKOUTS.EVENTS.ASK_RETURN_TO_MAIN);
1110
1110
  }
1111
1111
  },
1112
- version: "3.12.0-next.44"
1112
+ version: "3.12.0-next.45"
1113
1113
  });
1114
1114
  var _default = exports.default = Breakouts;
1115
1115
  //# sourceMappingURL=index.js.map
@@ -372,7 +372,7 @@ var SimultaneousInterpretation = _webexCore.WebexPlugin.extend({
372
372
  throw error;
373
373
  });
374
374
  },
375
- version: "3.12.0-next.44"
375
+ version: "3.12.0-next.45"
376
376
  });
377
377
  var _default = exports.default = SimultaneousInterpretation;
378
378
  //# sourceMappingURL=index.js.map
@@ -18,7 +18,7 @@ var SILanguage = _webexCore.WebexPlugin.extend({
18
18
  languageCode: 'number',
19
19
  languageName: 'string'
20
20
  },
21
- version: "3.12.0-next.44"
21
+ version: "3.12.0-next.45"
22
22
  });
23
23
  var _default = exports.default = SILanguage;
24
24
  //# sourceMappingURL=siLanguage.js.map
@@ -689,6 +689,12 @@ var Meeting = exports.default = /*#__PURE__*/function (_StatelessWebexPlugin) {
689
689
  });
690
690
  /**
691
691
  * Disconnects and cleans up the default LLM session listeners/timers.
692
+ *
693
+ * Ownership-aware: only calls `disconnectLLM` when this meeting is the
694
+ * current owner of the default LLM session (or when no owner is recorded).
695
+ * Event listeners belonging to this meeting instance are always detached
696
+ * so they do not receive another meeting's relay events.
697
+ *
692
698
  * @param {Object} options
693
699
  * @param {boolean} [options.removeOnlineListener=true] removes the one-time online listener
694
700
  * @param {boolean} [options.throwOnError=true] rethrows disconnect errors when true
@@ -700,13 +706,24 @@ var Meeting = exports.default = /*#__PURE__*/function (_StatelessWebexPlugin) {
700
706
  removeOnlineListener,
701
707
  _ref3$throwOnError,
702
708
  throwOnError,
709
+ currentOwner,
710
+ isOwner,
711
+ _this$webex$internal$,
712
+ _this$webex$internal$2,
703
713
  _args = arguments,
704
714
  _t;
705
715
  return _regenerator.default.wrap(function (_context) {
706
716
  while (1) switch (_context.prev = _context.next) {
707
717
  case 0:
708
718
  _ref3 = _args.length > 0 && _args[0] !== undefined ? _args[0] : {}, _ref3$removeOnlineLis = _ref3.removeOnlineListener, removeOnlineListener = _ref3$removeOnlineLis === void 0 ? true : _ref3$removeOnlineLis, _ref3$throwOnError = _ref3.throwOnError, throwOnError = _ref3$throwOnError === void 0 ? true : _ref3$throwOnError;
719
+ // @ts-ignore - Fix type
720
+ currentOwner = _this.webex.internal.llm.getOwnerMeetingId();
721
+ isOwner = !currentOwner || currentOwner === _this.id;
709
722
  _context.prev = 1;
723
+ if (!isOwner) {
724
+ _context.next = 3;
725
+ break;
726
+ }
710
727
  _context.next = 2;
711
728
  return _this.webex.internal.llm.disconnectLLM({
712
729
  code: 3050,
@@ -716,27 +733,43 @@ var Meeting = exports.default = /*#__PURE__*/function (_StatelessWebexPlugin) {
716
733
  _context.next = 4;
717
734
  break;
718
735
  case 3:
719
- _context.prev = 3;
736
+ _loggerProxy.default.logger.info("Meeting:index#cleanupLLMConneciton --> skipping disconnect; LLM owned by meeting ".concat(currentOwner, ", not ").concat(_this.id));
737
+ case 4:
738
+ _context.next = 6;
739
+ break;
740
+ case 5:
741
+ _context.prev = 5;
720
742
  _t = _context["catch"](1);
721
743
  _loggerProxy.default.logger.error('Meeting:index#cleanupLLMConneciton --> Failed to disconnect default LLM session', _t);
722
744
  if (!throwOnError) {
723
- _context.next = 4;
745
+ _context.next = 6;
724
746
  break;
725
747
  }
726
748
  throw _t;
727
- case 4:
728
- _context.prev = 4;
749
+ case 6:
750
+ _context.prev = 6;
729
751
  if (removeOnlineListener) {
730
752
  // @ts-ignore - Fix type
731
753
  _this.webex.internal.llm.off('online', _this.handleLLMOnline);
732
754
  }
733
755
  _this.stopListeningForLLMEvents();
734
- return _context.finish(4);
735
- case 5:
756
+
757
+ // If this meeting owned (or could have owned) the default LLM session,
758
+ // always release the owner tag here regardless of whether disconnectLLM
759
+ // resolved. `disconnectLLM` only clears the owner on its success path,
760
+ // so a failed disconnect would otherwise leave a stale owner pointing
761
+ // at a torn-down meeting and permanently block other meetings'
762
+ // `updateLLMConnection` calls via the ownership guard.
763
+ if (isOwner) {
764
+ // @ts-ignore - Fix type
765
+ (_this$webex$internal$ = (_this$webex$internal$2 = _this.webex.internal.llm).setOwnerMeetingId) === null || _this$webex$internal$ === void 0 ? void 0 : _this$webex$internal$.call(_this$webex$internal$2, undefined);
766
+ }
767
+ return _context.finish(6);
768
+ case 7:
736
769
  case "end":
737
770
  return _context.stop();
738
771
  }
739
- }, _callee, null, [[1, 3, 4, 5]]);
772
+ }, _callee, null, [[1, 5, 6, 7]]);
740
773
  })));
741
774
  /**
742
775
  * Handles ROAP_FAILURE event from the webrtc media connection
@@ -1568,6 +1601,7 @@ var Meeting = exports.default = /*#__PURE__*/function (_StatelessWebexPlugin) {
1568
1601
  * @memberof Meeting
1569
1602
  */
1570
1603
  (0, _defineProperty3.default)(_this, "clearMeetingData", /*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee5() {
1604
+ var currentOwner, isOwner;
1571
1605
  return _regenerator.default.wrap(function (_context5) {
1572
1606
  while (1) switch (_context5.prev = _context5.next) {
1573
1607
  case 0:
@@ -1584,7 +1618,19 @@ var Meeting = exports.default = /*#__PURE__*/function (_StatelessWebexPlugin) {
1584
1618
  // received mid-teardown do not trigger Locus syncs. Calling it here
1585
1619
  // again would double-emit MEETING_STOPPED_RECEIVING_TRANSCRIPTION
1586
1620
  // because stopTranscription() always fires its trigger.
1587
- _this.clearDataChannelToken();
1621
+ //
1622
+ // Ownership-aware token clear: only clear the shared LLM data channel
1623
+ // tokens when this meeting owns (or no meeting owns) the default LLM
1624
+ // session. Otherwise we would wipe tokens still in use by another
1625
+ // meeting's active LLM connection.
1626
+ // @ts-ignore - Fix type
1627
+ currentOwner = _this.webex.internal.llm.getOwnerMeetingId();
1628
+ isOwner = !currentOwner || currentOwner === _this.id;
1629
+ if (isOwner) {
1630
+ _this.clearDataChannelToken();
1631
+ } else {
1632
+ _loggerProxy.default.logger.info("Meeting:index#clearMeetingData --> skipping clearDataChannelToken; LLM owned by meeting ".concat(currentOwner, ", not ").concat(_this.id));
1633
+ }
1588
1634
  _context5.next = 1;
1589
1635
  return _this.cleanupLLMConneciton({
1590
1636
  throwOnError: false
@@ -6554,9 +6600,9 @@ var Meeting = exports.default = /*#__PURE__*/function (_StatelessWebexPlugin) {
6554
6600
  key: "restoreLLMSubscriptionsIfNeeded",
6555
6601
  value: function restoreLLMSubscriptionsIfNeeded() {
6556
6602
  try {
6557
- var _this$webex$internal$, _this$webex$internal$2;
6603
+ var _this$webex$internal$3, _this$webex$internal$4;
6558
6604
  // @ts-ignore
6559
- var isCaptionBoxOn = (_this$webex$internal$ = this.webex.internal.voicea) === null || _this$webex$internal$ === void 0 ? void 0 : (_this$webex$internal$2 = _this$webex$internal$.getIsCaptionBoxOn) === null || _this$webex$internal$2 === void 0 ? void 0 : _this$webex$internal$2.call(_this$webex$internal$);
6605
+ var isCaptionBoxOn = (_this$webex$internal$3 = this.webex.internal.voicea) === null || _this$webex$internal$3 === void 0 ? void 0 : (_this$webex$internal$4 = _this$webex$internal$3.getIsCaptionBoxOn) === null || _this$webex$internal$4 === void 0 ? void 0 : _this$webex$internal$4.call(_this$webex$internal$3);
6560
6606
  if (!isCaptionBoxOn) {
6561
6607
  return;
6562
6608
  }
@@ -6999,7 +7045,7 @@ var Meeting = exports.default = /*#__PURE__*/function (_StatelessWebexPlugin) {
6999
7045
  value: (function () {
7000
7046
  var _updateLLMConnection = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee21() {
7001
7047
  var _this36 = this;
7002
- var _ref39, _ref39$url, url, _ref39$info, _ref39$info2, _ref39$info2$datachan, datachannelUrl, isJoined, datachannelToken, dataChannelUrl;
7048
+ var _ref39, _ref39$url, url, _ref39$info, _ref39$info2, _ref39$info2$datachan, datachannelUrl, isJoined, datachannelToken, dataChannelUrl, currentOwner;
7003
7049
  return _regenerator.default.wrap(function (_context21) {
7004
7050
  while (1) switch (_context21.prev = _context21.next) {
7005
7051
  case 0:
@@ -7007,33 +7053,61 @@ var Meeting = exports.default = /*#__PURE__*/function (_StatelessWebexPlugin) {
7007
7053
  _ref39 = this.locusInfo || {}, _ref39$url = _ref39.url, url = _ref39$url === void 0 ? undefined : _ref39$url, _ref39$info = _ref39.info, _ref39$info2 = _ref39$info === void 0 ? {} : _ref39$info, _ref39$info2$datachan = _ref39$info2.datachannelUrl, datachannelUrl = _ref39$info2$datachan === void 0 ? undefined : _ref39$info2$datachan;
7008
7054
  isJoined = this.isJoined(); // @ts-ignore
7009
7055
  datachannelToken = this.webex.internal.llm.getDatachannelToken(_internalPluginLlm.DataChannelTokenType.Default);
7010
- dataChannelUrl = datachannelUrl; // @ts-ignore - Fix type
7056
+ dataChannelUrl = datachannelUrl; // Ownership guard: when the default LLM session is already connected and
7057
+ // owned by a *different* Meeting instance, do not disconnect or reconfigure
7058
+ // it. Another meeting's `updateLLMConnection` must be ignored here to
7059
+ // avoid killing the socket it relies on. We only proceed to manage the
7060
+ // connection when this meeting is the current owner, or when no owner is
7061
+ // set yet (first claim).
7062
+ // @ts-ignore - Fix type
7063
+ currentOwner = this.webex.internal.llm.getOwnerMeetingId(); // @ts-ignore - Fix type
7011
7064
  if (!this.webex.internal.llm.isConnected()) {
7012
- _context21.next = 2;
7065
+ _context21.next = 3;
7013
7066
  break;
7014
7067
  }
7068
+ if (!(currentOwner && currentOwner !== this.id)) {
7069
+ _context21.next = 1;
7070
+ break;
7071
+ }
7072
+ // Another meeting owns the live LLM socket. We must not disconnect
7073
+ // or reconfigure it -- doing so would tear down a session the
7074
+ // owning meeting still relies on. Locus/datachannel URL mismatch is
7075
+ // expected here (each meeting has its own locus URL) and is NOT a
7076
+ // valid signal of staleness, so we never reclaim from this path.
7077
+ // The only safe reclaim mechanism is the `finally`-block owner-tag
7078
+ // release in `cleanupLLMConneciton`, which fires when this meeting
7079
+ // itself is being torn down.
7080
+ _loggerProxy.default.logger.info("Meeting:index#updateLLMConnection --> skipping; LLM owned by meeting ".concat(currentOwner, ", not ").concat(this.id));
7081
+ return _context21.abrupt("return", undefined);
7082
+ case 1:
7015
7083
  if (!(
7016
7084
  // @ts-ignore - Fix type
7017
7085
  url === this.webex.internal.llm.getLocusUrl() &&
7018
7086
  // @ts-ignore - Fix type
7019
7087
  dataChannelUrl === this.webex.internal.llm.getDatachannelUrl() && isJoined)) {
7020
- _context21.next = 1;
7088
+ _context21.next = 2;
7021
7089
  break;
7022
7090
  }
7023
7091
  return _context21.abrupt("return", undefined);
7024
- case 1:
7025
- _context21.next = 2;
7092
+ case 2:
7093
+ _context21.next = 3;
7026
7094
  return this.cleanupLLMConneciton({
7027
7095
  removeOnlineListener: false
7028
7096
  });
7029
- case 2:
7097
+ case 3:
7030
7098
  if (isJoined) {
7031
- _context21.next = 3;
7099
+ _context21.next = 4;
7032
7100
  break;
7033
7101
  }
7034
7102
  return _context21.abrupt("return", undefined);
7035
- case 3:
7103
+ case 4:
7036
7104
  return _context21.abrupt("return", this.webex.internal.llm.registerAndConnect(url, dataChannelUrl, datachannelToken).then(function (registerAndConnectResult) {
7105
+ var _this36$webex$interna, _this36$webex$interna2;
7106
+ // Record ownership of the default LLM session for this meeting so
7107
+ // subsequent cross-meeting `updateLLMConnection` / `cleanupLLMConneciton`
7108
+ // calls can detect and skip work that doesn't belong to them.
7109
+ // @ts-ignore - Fix type
7110
+ (_this36$webex$interna = (_this36$webex$interna2 = _this36.webex.internal.llm).setOwnerMeetingId) === null || _this36$webex$interna === void 0 ? void 0 : _this36$webex$interna.call(_this36$webex$interna2, _this36.id);
7037
7111
  // @ts-ignore - Fix type
7038
7112
  _this36.webex.internal.llm.off('event:relay.event', _this36.processRelayEvent);
7039
7113
  // @ts-ignore - Fix type
@@ -7046,7 +7120,7 @@ var Meeting = exports.default = /*#__PURE__*/function (_StatelessWebexPlugin) {
7046
7120
  _this36.startLLMHealthCheckTimer();
7047
7121
  return _promise.default.resolve(registerAndConnectResult);
7048
7122
  }));
7049
- case 4:
7123
+ case 5:
7050
7124
  case "end":
7051
7125
  return _context21.stop();
7052
7126
  }