@webex/plugin-meetings 3.12.0-next.4 → 3.12.0-next.41

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.
Files changed (90) hide show
  1. package/AGENTS.md +9 -0
  2. package/dist/aiEnableRequest/index.js +15 -2
  3. package/dist/aiEnableRequest/index.js.map +1 -1
  4. package/dist/breakouts/breakout.js +6 -2
  5. package/dist/breakouts/breakout.js.map +1 -1
  6. package/dist/breakouts/index.js +1 -1
  7. package/dist/constants.js +1 -1
  8. package/dist/constants.js.map +1 -1
  9. package/dist/controls-options-manager/constants.js +11 -1
  10. package/dist/controls-options-manager/constants.js.map +1 -1
  11. package/dist/controls-options-manager/index.js +23 -21
  12. package/dist/controls-options-manager/index.js.map +1 -1
  13. package/dist/controls-options-manager/util.js +91 -0
  14. package/dist/controls-options-manager/util.js.map +1 -1
  15. package/dist/hashTree/constants.js +10 -1
  16. package/dist/hashTree/constants.js.map +1 -1
  17. package/dist/hashTree/hashTreeParser.js +554 -350
  18. package/dist/hashTree/hashTreeParser.js.map +1 -1
  19. package/dist/hashTree/utils.js +22 -0
  20. package/dist/hashTree/utils.js.map +1 -1
  21. package/dist/interceptors/locusRetry.js +23 -8
  22. package/dist/interceptors/locusRetry.js.map +1 -1
  23. package/dist/interpretation/index.js +1 -1
  24. package/dist/interpretation/siLanguage.js +1 -1
  25. package/dist/locus-info/index.js +274 -85
  26. package/dist/locus-info/index.js.map +1 -1
  27. package/dist/locus-info/types.js +16 -0
  28. package/dist/locus-info/types.js.map +1 -1
  29. package/dist/meeting/index.js +710 -499
  30. package/dist/meeting/index.js.map +1 -1
  31. package/dist/meeting/util.js +1 -0
  32. package/dist/meeting/util.js.map +1 -1
  33. package/dist/meetings/index.js +174 -77
  34. package/dist/meetings/index.js.map +1 -1
  35. package/dist/meetings/util.js +49 -5
  36. package/dist/meetings/util.js.map +1 -1
  37. package/dist/member/index.js +10 -0
  38. package/dist/member/index.js.map +1 -1
  39. package/dist/member/types.js.map +1 -1
  40. package/dist/member/util.js +3 -0
  41. package/dist/member/util.js.map +1 -1
  42. package/dist/types/controls-options-manager/constants.d.ts +6 -1
  43. package/dist/types/hashTree/constants.d.ts +1 -0
  44. package/dist/types/hashTree/hashTreeParser.d.ts +53 -15
  45. package/dist/types/hashTree/utils.d.ts +11 -0
  46. package/dist/types/interceptors/locusRetry.d.ts +4 -4
  47. package/dist/types/locus-info/index.d.ts +46 -6
  48. package/dist/types/locus-info/types.d.ts +17 -1
  49. package/dist/types/meeting/index.d.ts +64 -1
  50. package/dist/types/member/index.d.ts +1 -0
  51. package/dist/types/member/types.d.ts +1 -0
  52. package/dist/types/member/util.d.ts +1 -0
  53. package/dist/webinar/index.js +301 -226
  54. package/dist/webinar/index.js.map +1 -1
  55. package/package.json +22 -22
  56. package/src/aiEnableRequest/index.ts +16 -0
  57. package/src/breakouts/breakout.ts +2 -1
  58. package/src/constants.ts +1 -1
  59. package/src/controls-options-manager/constants.ts +14 -1
  60. package/src/controls-options-manager/index.ts +26 -19
  61. package/src/controls-options-manager/util.ts +81 -1
  62. package/src/hashTree/constants.ts +9 -0
  63. package/src/hashTree/hashTreeParser.ts +278 -160
  64. package/src/hashTree/utils.ts +17 -0
  65. package/src/interceptors/locusRetry.ts +25 -4
  66. package/src/locus-info/index.ts +274 -93
  67. package/src/locus-info/types.ts +19 -1
  68. package/src/meeting/index.ts +206 -22
  69. package/src/meeting/util.ts +1 -0
  70. package/src/meetings/index.ts +77 -43
  71. package/src/meetings/util.ts +56 -1
  72. package/src/member/index.ts +10 -0
  73. package/src/member/types.ts +1 -0
  74. package/src/member/util.ts +3 -0
  75. package/src/webinar/index.ts +75 -1
  76. package/test/unit/spec/aiEnableRequest/index.ts +86 -0
  77. package/test/unit/spec/breakouts/breakout.ts +7 -3
  78. package/test/unit/spec/controls-options-manager/index.js +114 -6
  79. package/test/unit/spec/controls-options-manager/util.js +165 -0
  80. package/test/unit/spec/hashTree/hashTreeParser.ts +996 -51
  81. package/test/unit/spec/hashTree/utils.ts +88 -1
  82. package/test/unit/spec/interceptors/locusRetry.ts +205 -4
  83. package/test/unit/spec/locus-info/index.js +397 -81
  84. package/test/unit/spec/meeting/index.js +271 -44
  85. package/test/unit/spec/meeting/utils.js +4 -0
  86. package/test/unit/spec/meetings/index.js +195 -13
  87. package/test/unit/spec/meetings/utils.js +137 -0
  88. package/test/unit/spec/member/index.js +7 -0
  89. package/test/unit/spec/member/util.js +24 -0
  90. package/test/unit/spec/webinar/index.ts +60 -0
@@ -45,9 +45,13 @@ export declare const LocusInfoUpdateType: {
45
45
  readonly MEETING_ENDED: "MEETING_ENDED";
46
46
  };
47
47
  export type LocusInfoUpdateType = Enum<typeof LocusInfoUpdateType>;
48
- export type LocusInfoUpdateCallback = (updateType: LocusInfoUpdateType, data?: {
48
+ export type LocusInfoUpdate = {
49
+ updateType: typeof LocusInfoUpdateType.OBJECTS_UPDATED;
49
50
  updatedObjects: HashTreeObject[];
50
- }) => void;
51
+ } | {
52
+ updateType: typeof LocusInfoUpdateType.MEETING_ENDED;
53
+ };
54
+ export type LocusInfoUpdateCallback = (update: LocusInfoUpdate) => void;
51
55
  /**
52
56
  * This error is thrown if we receive information that the meeting has ended while we're processing some hash messages.
53
57
  * It's handled internally by HashTreeParser and results in MEETING_ENDED being sent up.
@@ -67,6 +71,10 @@ declare class HashTreeParser {
67
71
  heartbeatIntervalMs?: number;
68
72
  private excludedDataSets;
69
73
  state: 'active' | 'stopped';
74
+ private syncQueue;
75
+ private isSyncInProgress;
76
+ private isSyncAllInProgress;
77
+ private syncQueueProcessingPromise;
70
78
  /**
71
79
  * Constructor for HashTreeParser
72
80
  * @param {Object} options
@@ -120,14 +128,6 @@ declare class HashTreeParser {
120
128
  * @returns {Promise}
121
129
  */
122
130
  private initializeNewVisibleDataSet;
123
- /**
124
- * Sends a special sync request to Locus with all leaves empty - this is a way to get all the data for a given dataset.
125
- *
126
- * @param {string} datasetName - name of the dataset for which to send the request
127
- * @param {string} debugText - text to include in logs
128
- * @returns {Promise}
129
- */
130
- private sendInitializationSyncRequestToLocus;
131
131
  /**
132
132
  * Queries Locus for all up-to-date information about all visible data sets
133
133
  *
@@ -298,11 +298,35 @@ declare class HashTreeParser {
298
298
  * Performs a sync for the given data set.
299
299
  *
300
300
  * @param {InternalDataSet} dataSet - The data set to sync
301
- * @param {string} rootHash - Our current root hash for this data set
302
301
  * @param {string} reason - The reason for the sync (used for logging)
302
+ * @param {boolean} [isInitialization] - Whether this is an initialization sync (sends empty leaves data instead of comparing hashes)
303
303
  * @returns {Promise<void>}
304
304
  */
305
305
  private performSync;
306
+ /**
307
+ * Enqueues a sync for the given data set. If the data set is already in the queue, the request is ignored.
308
+ * This ensures that all syncs are executed sequentially and no more than 1 sync runs at a time.
309
+ *
310
+ * @param {string} dataSetName - The name of the data set to sync
311
+ * @param {string} reason - The reason for the sync (used for logging)
312
+ * @param {boolean} [isInitialization=false] - Whether this is an initialization sync (uses empty leaves data instead of hash comparison)
313
+ * @returns {void}
314
+ */
315
+ private enqueueSyncForDataset;
316
+ /**
317
+ * Processes the sync queue sequentially. Only one instance of this method runs at a time.
318
+ *
319
+ * @returns {Promise<void>}
320
+ */
321
+ private processSyncQueue;
322
+ /**
323
+ * Syncs all data sets that have hash trees, one by one in sequence, using the priority order
324
+ * provided by sortByInitPriority(). Does nothing if the parser is stopped or if a syncAllDatasets
325
+ * call is already in progress.
326
+ *
327
+ * @returns {Promise<void>}
328
+ */
329
+ syncAllDatasets(): Promise<void>;
306
330
  /**
307
331
  * Runs the sync algorithm for the given data set.
308
332
  *
@@ -333,24 +357,38 @@ declare class HashTreeParser {
333
357
  */
334
358
  stop(): void;
335
359
  /**
336
- * Resumes the HashTreeParser that was previously stopped.
360
+ * Cleans up the HashTreeParser, stopping all timers and clearing all internal state.
361
+ * After calling this, the parser should not be used anymore.
362
+ * @returns {void}
363
+ */
364
+ cleanUp(): void;
365
+ /**
366
+ * Resumes the HashTreeParser that was previously stopped, using a hash tree message.
337
367
  * @param {HashTreeMessage} message - The message to resume with, it must contain metadata with visible data sets info
338
368
  * @returns {void}
339
369
  */
340
- resume(message: HashTreeMessage): void;
370
+ resumeFromMessage(message: HashTreeMessage): void;
371
+ /**
372
+ * Resumes the HashTreeParser that was previously stopped, using a Locus API response.
373
+ * Unlike resumeFromMessage(), this does not require metadata/dataSets in the input,
374
+ * as it fetches all necessary information from Locus via initializeFromGetLociResponse.
375
+ * @param {LocusDTO} locus - locus object from an API response
376
+ * @returns {Promise}
377
+ */
378
+ resumeFromApiResponse(locus: LocusDTO): Promise<void>;
341
379
  private checkForSentinelHttpResponse;
342
380
  /**
343
381
  * Gets the current hashes from the locus for a specific data set.
344
382
  * @param {string} dataSetName
345
383
  * @param {string} currentRootHash
346
- * @returns {string[]}
384
+ * @returns {Object|null} An object containing the hashes and leaf count, or null if the hashes match and no sync is needed
347
385
  */
348
386
  private getHashesFromLocus;
349
387
  /**
350
388
  * Sends a sync request to Locus for the specified data set.
351
389
  *
352
390
  * @param {InternalDataSet} dataSet The data set to sync.
353
- * @param {Record<number, LeafDataItem[]>} mismatchedLeavesData The mismatched leaves data to include in the sync request.
391
+ * @param {Object} options Either `{ isInitialization: true }` for init syncs (uses leafCount=1 with empty leaf data) or `{ mismatchedLeavesData }` for normal syncs.
354
392
  * @returns {Promise<HashTreeMessage|null>}
355
393
  */
356
394
  private sendSyncRequestToLocus;
@@ -20,3 +20,14 @@ export declare function isMetadata(object: HashTreeObject): boolean;
20
20
  * @returns {void}
21
21
  */
22
22
  export declare const deleteNestedObjectsWithHtMeta: (currentLocusPart: any, parent?: any, currentKey?: string | number) => void;
23
+ /**
24
+ * Reorders items so that those matching the given priority list come first (in priority order),
25
+ * followed by everything else in their original order.
26
+ *
27
+ * @param {Array<T>} items - The items to reorder
28
+ * @param {string[]} priority - Ordered list of names that should come first
29
+ * @returns {Array<T>} A new array with prioritized items first
30
+ */
31
+ export declare function sortByInitPriority<T extends {
32
+ name: string;
33
+ }>(items: T[], priority: string[]): T[];
@@ -11,11 +11,11 @@ export default class LocusRetryStatusInterceptor extends Interceptor {
11
11
  */
12
12
  static create(): LocusRetryStatusInterceptor;
13
13
  /**
14
- * Handle response errors
15
- * @param {Object} options
16
- * @param {WebexHttpError} reason
17
- * @returns {Promise<WebexHttpError>}
14
+ * Check whether a URI is a Locus /hashtree or /sync endpoint.
15
+ * @param {string} uri
16
+ * @returns {boolean}
18
17
  */
18
+ private static isLocusHashtreeOrSync;
19
19
  onResponseError(options: any, reason: any): Promise<unknown>;
20
20
  /**
21
21
  * Handle retries for locus service unavailable errors
@@ -25,10 +25,9 @@ export type HashTreeParserEntry = {
25
25
  *
26
26
  * @param {HashTreeMessage} message - The hash tree message to find the meeting for
27
27
  * @param {MeetingCollection} meetingCollection - The collection of meetings to search
28
- * @param {string} deviceUrl - The URL of the user's device
29
28
  * @returns {any} The meeting if found, otherwise undefined
30
29
  */
31
- export declare function findMeetingForHashTreeMessage(message: HashTreeMessage, meetingCollection: MeetingCollection, deviceUrl: string): any;
30
+ export declare function findMeetingForHashTreeMessage(message: HashTreeMessage | undefined, meetingCollection: MeetingCollection): any;
32
31
  /**
33
32
  * Creates a locus object from the objects received in a hash tree message. It usually will be
34
33
  * incomplete, because hash tree messages only contain the parts of locus that have changed,
@@ -130,6 +129,7 @@ export default class LocusInfo extends EventsScope {
130
129
  private createHashTreeParser;
131
130
  /**
132
131
  * @param {Object} data - data to initialize locus info with. It may be from a join or GET /loci response or from a Mercury event that triggers a creation of meeting object
132
+ * @param {Function} [onLocusSynced] - optional callback that will be called at the end of initial setup, when locus info is fully synced. It will be called with the full locus snapshot as an argument (which may be null if we haven't received any full locus DTOs during the initial setup, for example in case we receive only hash tree messages without full locus DTOs)
133
133
  * @returns {undefined}
134
134
  * @memberof LocusInfo
135
135
  */
@@ -145,7 +145,13 @@ export default class LocusInfo extends EventsScope {
145
145
  } | {
146
146
  trigger: 'get-loci-response';
147
147
  locus?: LocusDTO;
148
- }): Promise<void>;
148
+ }, onLocusSynced?: (locus: LocusDTO) => void): Promise<void>;
149
+ /**
150
+ * Builds a full locus DTO snapshot from current internal locus state.
151
+ *
152
+ * @returns {LocusDTO}
153
+ */
154
+ private getCurrentLocusSnapshot;
149
155
  /**
150
156
  * Handles HTTP response from Locus API call.
151
157
  * @param {Meeting} meeting meeting object
@@ -167,6 +173,28 @@ export default class LocusInfo extends EventsScope {
167
173
  * @returns {void}
168
174
  */
169
175
  sendClassicVsHashTreeMismatchMetric(meeting: any, message: string): void;
176
+ /**
177
+ * Helper that handles the common logic for reactivating a stopped HashTreeParser when
178
+ * a newer "replaces" is detected. Used by both the message and API response parser switch methods.
179
+ *
180
+ * @param {string} callerName - name of the calling method, used in log messages
181
+ * @param {string} locusUrl - the locus URL of the stopped parser
182
+ * @param {HashTreeParserEntry} stoppedEntry - the stopped parser entry
183
+ * @param {ReplacesInfo} replaces - replacement info extracted from self
184
+ * @param {Function} resumeCallback - callback to invoke after reactivation to resume the parser
185
+ * @returns {void}
186
+ */
187
+ private resumeStoppedParser;
188
+ /**
189
+ * Handles an API response whose locusUrl doesn't match any active HashTreeParser
190
+ * (either no entry exists, or the existing entry is stopped).
191
+ * Creates a new parser or reactivates a stopped one using initializeFromGetLociResponse.
192
+ *
193
+ * @param {string} locusUrl - the locus URL from the API response
194
+ * @param {LocusDTO} locus - the locus DTO from the API response
195
+ * @returns {void}
196
+ */
197
+ private handleHashTreeParserSwitchForAPIResponse;
170
198
  /**
171
199
  * Checks if the hash tree message should trigger a switch to a different HashTreeParser
172
200
  *
@@ -183,13 +211,19 @@ export default class LocusInfo extends EventsScope {
183
211
  * @returns {void}
184
212
  */
185
213
  private handleHashTreeMessage;
214
+ /**
215
+ * Triggers a sync of all hash tree datasets for all hash tree parsers associated with this meeting.
216
+ * The syncs are executed sequentially within each parser.
217
+ *
218
+ * @returns {Promise<void>}
219
+ */
220
+ syncAllHashTreeDatasets(): Promise<void>;
186
221
  /**
187
222
  * Callback registered with HashTreeParser to receive locus info updates.
188
223
  * Updates our locus info based on the data parsed by the hash tree parser.
189
224
  *
190
225
  * @param {string} locusUrl - the locus URL for which the update is received
191
- * @param {LocusInfoUpdateType} updateType - The type of update received.
192
- * @param {Object} [data] - Additional data for the update, if applicable.
226
+ * @param {LocusInfoUpdate} update - Details about the update.
193
227
  * @returns {void}
194
228
  */
195
229
  private updateFromHashTree;
@@ -214,8 +248,8 @@ export default class LocusInfo extends EventsScope {
214
248
  * @param {string} debugText string explaining the trigger for this call, added to logs for debugging purposes
215
249
  * @param {object} locus locus object
216
250
  * @param {object} metadata locus hash trees metadata
217
- * @param {string} eventType locus event
218
251
  * @param {DataSet[]} dataSets
252
+ * @param {string} eventType locus event
219
253
  * @returns {void}
220
254
  */
221
255
  private onFullLocusWithHashTrees;
@@ -444,4 +478,10 @@ export default class LocusInfo extends EventsScope {
444
478
  * @memberof LocusInfo
445
479
  */
446
480
  clearMainSessionLocusCache(): void;
481
+ /**
482
+ * Cleans up all hash tree parsers and clears internal maps.
483
+ * @returns {void}
484
+ * @memberof LocusInfo
485
+ */
486
+ cleanUp(): void;
447
487
  }
@@ -1,14 +1,30 @@
1
+ import { Enum } from '../constants';
1
2
  import { HtMeta } from '../hashTree/types';
3
+ export declare const EndMeetingReason: {
4
+ readonly maxMeetingDuration: "MAX_MEETING_DURATION";
5
+ readonly allParticipantsLeft: "ALL_PARTICIPANTS_LEFT";
6
+ readonly sipHostLeft: "SIP_HOST_LEFT";
7
+ readonly noHost: "NO_HOST";
8
+ readonly waitingForMpsEndMeetingTimeout: "WAITING_FOR_MPS_END_MEETING_TIMEOUT";
9
+ readonly fraudDetection: "FRAUD_DETECTION";
10
+ readonly meetingEndedByHost: "MEETING_ENDED_BY_HOST";
11
+ readonly meetingUpdated: "MEETING_UPDATED";
12
+ readonly meetingCancelled: "MEETING_CANCELLED";
13
+ readonly autoEndWithSingleParticipant: "AUTO_END_WITH_SINGLE_PARTICIPANT";
14
+ readonly breakoutEnded: "BREAKOUT_ENDED";
15
+ };
16
+ export type EndMeetingReason = Enum<typeof EndMeetingReason>;
2
17
  export type LocusFullState = {
3
18
  active: boolean;
4
19
  count: number;
5
20
  lastActive: string;
6
21
  locked: boolean;
7
22
  sessionId: string;
8
- seessionIds: string[];
23
+ sessionIds: string[];
9
24
  startTime: number;
10
25
  state: string;
11
26
  type: string;
27
+ endMeetingReason?: EndMeetingReason;
12
28
  };
13
29
  export type Links = {
14
30
  services: Record<'breakout' | 'record', {
@@ -374,7 +374,7 @@ export default class Meeting extends StatelessWebexPlugin {
374
374
  webinar: any;
375
375
  conversationUrl: string;
376
376
  callStateForMetrics: CallStateForMetrics;
377
- destination: string;
377
+ destination: string | LocusDTO;
378
378
  destinationType: DESTINATION_TYPE;
379
379
  deviceUrl: string;
380
380
  hostId: string;
@@ -412,6 +412,8 @@ export default class Meeting extends StatelessWebexPlugin {
412
412
  floorGrantPending: boolean;
413
413
  hasJoinedOnce: boolean;
414
414
  hasWebsocketConnected: boolean;
415
+ private mercuryOnlineHandler?;
416
+ private mercuryOfflineHandler?;
415
417
  inMeetingActions: InMeetingActions;
416
418
  isLocalShareLive: boolean;
417
419
  isRoapInProgress: boolean;
@@ -1051,6 +1053,13 @@ export default class Meeting extends StatelessWebexPlugin {
1051
1053
  * @memberof Meeting
1052
1054
  */
1053
1055
  setSipUri(sipUri: string): void;
1056
+ /**
1057
+ * After initial locus setup, refreshes destination with synced locus data and optionally
1058
+ * performs deferred meeting info fetch when initial locus was incomplete.
1059
+ * @param {LocusDTO} locus
1060
+ * @returns {void}
1061
+ */
1062
+ finalizeMeetingAfterInitialLocusSetup(locus: LocusDTO): Promise<void>;
1054
1063
  /**
1055
1064
  * Set the locus info the class instance. Should be called with the parsed locus
1056
1065
  * we got in the join response.
@@ -1163,6 +1172,22 @@ export default class Meeting extends StatelessWebexPlugin {
1163
1172
  * @memberof Meeting
1164
1173
  */
1165
1174
  setMercuryListener(): void;
1175
+ /**
1176
+ * Removes this meeting's Mercury ONLINE/OFFLINE event listeners registered
1177
+ * by setMercuryListener(). Must be called before Locus /leave to avoid
1178
+ * unnecessary syncs/metrics triggered by events received while leaving
1179
+ * (per Locus team recommendation).
1180
+ *
1181
+ * Mercury is a process-wide singleton shared with other plugins, so we
1182
+ * pass the bound handler refs to .off() to avoid clearing every listener
1183
+ * for ONLINE/OFFLINE on the shared emitter.
1184
+ *
1185
+ * Idempotent: subsequent calls are no-ops because the handler refs are
1186
+ * cleared after detaching.
1187
+ * @private
1188
+ * @returns {void}
1189
+ */
1190
+ private stopListeningForMercuryEvents;
1166
1191
  /**
1167
1192
  * Close the peer connections and remove them from the class.
1168
1193
  * Cleanup any media connection related things.
@@ -1318,6 +1343,11 @@ export default class Meeting extends StatelessWebexPlugin {
1318
1343
  * @returns{void}
1319
1344
  */
1320
1345
  private triggerStopReceivingTranscriptionEvent;
1346
+ /**
1347
+ * Restores LLM subchannel subscriptions after reconnect when captions are active.
1348
+ * @returns {void}
1349
+ */
1350
+ private restoreLLMSubscriptionsIfNeeded;
1321
1351
  /**
1322
1352
  * This is a callback for the LLM event that is triggered when it comes online
1323
1353
  * This method in turn will trigger an event to the developers that the LLM is connected
@@ -1351,6 +1381,33 @@ export default class Meeting extends StatelessWebexPlugin {
1351
1381
  * @returns {void}
1352
1382
  */
1353
1383
  private clearLLMHealthCheckTimer;
1384
+ /**
1385
+ * Removes LLM event listeners and clears the health check timer.
1386
+ * Must be called before Locus /leave to avoid unnecessary syncs triggered
1387
+ * by events received while leaving (per Locus team recommendation).
1388
+ * Idempotent: safe to call multiple times; .off() is a no-op when no
1389
+ * matching listener is registered.
1390
+ * @private
1391
+ * @returns {void}
1392
+ */
1393
+ private stopListeningForLLMEvents;
1394
+ /**
1395
+ * Stops listening on every event bus (LLM, Mercury, voicea/transcription,
1396
+ * annotation) that could otherwise deliver events to this meeting while
1397
+ * Locus is processing /leave or /end. Per the Locus team recommendation,
1398
+ * this must run before the Locus request is dispatched to avoid
1399
+ * unnecessary syncs triggered by in-flight events.
1400
+ *
1401
+ * Voicea (transcription) subscribes to llm 'event:relay.event' internally,
1402
+ * and the annotation plugin subscribes to both mercury and llm, so both
1403
+ * must be torn down alongside the direct LLM/Mercury listeners.
1404
+ *
1405
+ * Idempotent: safe to call multiple times; .off() is a no-op when no
1406
+ * matching listener is registered, and stopTranscription is guarded.
1407
+ * @private
1408
+ * @returns {void}
1409
+ */
1410
+ private stopListeningForMeetingEvents;
1354
1411
  /**
1355
1412
  * Disconnects and cleans up the default LLM session listeners/timers.
1356
1413
  * @param {Object} options
@@ -1372,6 +1429,12 @@ export default class Meeting extends StatelessWebexPlugin {
1372
1429
  * @returns {void}
1373
1430
  */
1374
1431
  saveDataChannelToken(join: any): void;
1432
+ /**
1433
+ * Ensures default-session data channel token exists after lobby admission.
1434
+ * Some lobby users do not receive a token until they are admitted.
1435
+ * @returns {Promise<boolean>} true when a new token is fetched and cached
1436
+ */
1437
+ private ensureDefaultDatachannelTokenAfterAdmit;
1375
1438
  /**
1376
1439
  * Connects to low latency mercury and reconnects if the address has changed
1377
1440
  * It will also disconnect if called when the meeting has ended
@@ -20,6 +20,7 @@ export default class Member {
20
20
  isModerator: any;
21
21
  isModeratorAssignmentProhibited: any;
22
22
  isPresenterAssignmentProhibited: any;
23
+ isAttendeeAssignmentProhibited: any;
23
24
  isMutable: any;
24
25
  isNotAdmitted: any;
25
26
  isRecording: any;
@@ -89,6 +89,7 @@ export interface Participant {
89
89
  moderator: boolean;
90
90
  moderatorAssignmentNotAllowed: boolean;
91
91
  presenterAssignmentNotAllowed: boolean;
92
+ attendeeAssignmentNotAllowed?: boolean;
92
93
  person: ParticipantPerson;
93
94
  resourceGuest: boolean;
94
95
  state: string;
@@ -66,6 +66,7 @@ declare const MemberUtil: {
66
66
  isDevice: (participant: Participant) => boolean;
67
67
  isModeratorAssignmentProhibited: (participant: Participant) => boolean;
68
68
  isPresenterAssignmentProhibited: (participant: Participant) => boolean;
69
+ isAttendeeAssignmentProhibited: (participant: Participant) => boolean;
69
70
  /**
70
71
  * checks to see if the participant id is the same as the passed id
71
72
  * there are multiple ids that can be used