@webex/plugin-meetings 3.12.0-next.9 → 3.12.0-next.91

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 (213) 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 +8 -3
  5. package/dist/breakouts/breakout.js.map +1 -1
  6. package/dist/breakouts/index.js +26 -2
  7. package/dist/breakouts/index.js.map +1 -1
  8. package/dist/config.js +2 -2
  9. package/dist/config.js.map +1 -1
  10. package/dist/constants.js +35 -9
  11. package/dist/constants.js.map +1 -1
  12. package/dist/controls-options-manager/constants.js +11 -1
  13. package/dist/controls-options-manager/constants.js.map +1 -1
  14. package/dist/controls-options-manager/index.js +67 -29
  15. package/dist/controls-options-manager/index.js.map +1 -1
  16. package/dist/controls-options-manager/util.js +91 -0
  17. package/dist/controls-options-manager/util.js.map +1 -1
  18. package/dist/hashTree/constants.js +13 -1
  19. package/dist/hashTree/constants.js.map +1 -1
  20. package/dist/hashTree/hashTreeParser.js +880 -382
  21. package/dist/hashTree/hashTreeParser.js.map +1 -1
  22. package/dist/hashTree/utils.js +42 -0
  23. package/dist/hashTree/utils.js.map +1 -1
  24. package/dist/index.js +7 -0
  25. package/dist/index.js.map +1 -1
  26. package/dist/interceptors/dataChannelAuthToken.js +75 -15
  27. package/dist/interceptors/dataChannelAuthToken.js.map +1 -1
  28. package/dist/interceptors/locusRetry.js +23 -8
  29. package/dist/interceptors/locusRetry.js.map +1 -1
  30. package/dist/interpretation/index.js +10 -1
  31. package/dist/interpretation/index.js.map +1 -1
  32. package/dist/interpretation/interpretation.types.js +7 -0
  33. package/dist/interpretation/interpretation.types.js.map +1 -0
  34. package/dist/interpretation/siLanguage.js +1 -1
  35. package/dist/locus-info/controlsUtils.js +4 -1
  36. package/dist/locus-info/controlsUtils.js.map +1 -1
  37. package/dist/locus-info/index.js +303 -88
  38. package/dist/locus-info/index.js.map +1 -1
  39. package/dist/locus-info/infoUtils.js +36 -5
  40. package/dist/locus-info/infoUtils.js.map +1 -1
  41. package/dist/locus-info/types.js +19 -0
  42. package/dist/locus-info/types.js.map +1 -1
  43. package/dist/media/index.js +3 -1
  44. package/dist/media/index.js.map +1 -1
  45. package/dist/media/properties.js +1 -0
  46. package/dist/media/properties.js.map +1 -1
  47. package/dist/meeting/in-meeting-actions.js +5 -1
  48. package/dist/meeting/in-meeting-actions.js.map +1 -1
  49. package/dist/meeting/index.js +1233 -793
  50. package/dist/meeting/index.js.map +1 -1
  51. package/dist/meeting/locusMediaRequest.js +229 -82
  52. package/dist/meeting/locusMediaRequest.js.map +1 -1
  53. package/dist/meeting/muteState.js +10 -1
  54. package/dist/meeting/muteState.js.map +1 -1
  55. package/dist/meeting/request.js +5 -2
  56. package/dist/meeting/request.js.map +1 -1
  57. package/dist/meeting/util.js +35 -2
  58. package/dist/meeting/util.js.map +1 -1
  59. package/dist/meeting-info/meeting-info-v2.js +2 -2
  60. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  61. package/dist/meetings/index.js +231 -118
  62. package/dist/meetings/index.js.map +1 -1
  63. package/dist/meetings/meetings.types.js +6 -1
  64. package/dist/meetings/meetings.types.js.map +1 -1
  65. package/dist/meetings/request.js +39 -0
  66. package/dist/meetings/request.js.map +1 -1
  67. package/dist/meetings/util.js +79 -5
  68. package/dist/meetings/util.js.map +1 -1
  69. package/dist/member/index.js +10 -0
  70. package/dist/member/index.js.map +1 -1
  71. package/dist/member/types.js.map +1 -1
  72. package/dist/member/util.js +30 -0
  73. package/dist/member/util.js.map +1 -1
  74. package/dist/members/index.js +101 -43
  75. package/dist/members/index.js.map +1 -1
  76. package/dist/members/util.js +8 -1
  77. package/dist/members/util.js.map +1 -1
  78. package/dist/metrics/constants.js +5 -1
  79. package/dist/metrics/constants.js.map +1 -1
  80. package/dist/multistream/codec/constants.js +63 -0
  81. package/dist/multistream/codec/constants.js.map +1 -0
  82. package/dist/multistream/mediaRequestManager.js +62 -15
  83. package/dist/multistream/mediaRequestManager.js.map +1 -1
  84. package/dist/multistream/receiveSlot.js +9 -0
  85. package/dist/multistream/receiveSlot.js.map +1 -1
  86. package/dist/reachability/index.js +10 -13
  87. package/dist/reachability/index.js.map +1 -1
  88. package/dist/reachability/reachability.types.js +2 -0
  89. package/dist/reachability/reachability.types.js.map +1 -1
  90. package/dist/reachability/util.js +45 -0
  91. package/dist/reachability/util.js.map +1 -1
  92. package/dist/reactions/reactions.type.js.map +1 -1
  93. package/dist/recording-controller/index.js +1 -3
  94. package/dist/recording-controller/index.js.map +1 -1
  95. package/dist/types/config.d.ts +2 -2
  96. package/dist/types/constants.d.ts +12 -1
  97. package/dist/types/controls-options-manager/constants.d.ts +6 -1
  98. package/dist/types/controls-options-manager/index.d.ts +16 -0
  99. package/dist/types/hashTree/constants.d.ts +2 -0
  100. package/dist/types/hashTree/hashTreeParser.d.ts +146 -17
  101. package/dist/types/hashTree/utils.d.ts +18 -0
  102. package/dist/types/index.d.ts +3 -0
  103. package/dist/types/interceptors/locusRetry.d.ts +4 -4
  104. package/dist/types/interpretation/interpretation.types.d.ts +10 -0
  105. package/dist/types/locus-info/index.d.ts +50 -6
  106. package/dist/types/locus-info/infoUtils.d.ts +8 -0
  107. package/dist/types/locus-info/types.d.ts +21 -1
  108. package/dist/types/media/properties.d.ts +1 -0
  109. package/dist/types/meeting/in-meeting-actions.d.ts +4 -0
  110. package/dist/types/meeting/index.d.ts +94 -7
  111. package/dist/types/meeting/locusMediaRequest.d.ts +12 -0
  112. package/dist/types/meeting/request.d.ts +1 -0
  113. package/dist/types/meeting/util.d.ts +9 -0
  114. package/dist/types/meetings/index.d.ts +30 -18
  115. package/dist/types/meetings/meetings.types.d.ts +15 -0
  116. package/dist/types/meetings/request.d.ts +14 -0
  117. package/dist/types/member/index.d.ts +1 -0
  118. package/dist/types/member/types.d.ts +1 -0
  119. package/dist/types/member/util.d.ts +9 -0
  120. package/dist/types/members/index.d.ts +15 -2
  121. package/dist/types/members/util.d.ts +1 -5
  122. package/dist/types/metrics/constants.d.ts +4 -0
  123. package/dist/types/multistream/codec/constants.d.ts +7 -0
  124. package/dist/types/multistream/mediaRequestManager.d.ts +22 -5
  125. package/dist/types/reachability/index.d.ts +1 -1
  126. package/dist/types/reachability/reachability.types.d.ts +7 -0
  127. package/dist/types/reachability/util.d.ts +17 -0
  128. package/dist/types/reactions/reactions.type.d.ts +3 -0
  129. package/dist/webinar/index.js +305 -159
  130. package/dist/webinar/index.js.map +1 -1
  131. package/package.json +22 -22
  132. package/src/aiEnableRequest/index.ts +16 -0
  133. package/src/breakouts/breakout.ts +3 -1
  134. package/src/breakouts/index.ts +31 -0
  135. package/src/config.ts +2 -2
  136. package/src/constants.ts +20 -3
  137. package/src/controls-options-manager/constants.ts +14 -1
  138. package/src/controls-options-manager/index.ts +87 -28
  139. package/src/controls-options-manager/util.ts +81 -1
  140. package/src/hashTree/constants.ts +16 -0
  141. package/src/hashTree/hashTreeParser.ts +580 -196
  142. package/src/hashTree/utils.ts +36 -0
  143. package/src/index.ts +6 -0
  144. package/src/interceptors/dataChannelAuthToken.ts +88 -12
  145. package/src/interceptors/locusRetry.ts +25 -4
  146. package/src/interpretation/index.ts +27 -9
  147. package/src/interpretation/interpretation.types.ts +11 -0
  148. package/src/locus-info/controlsUtils.ts +3 -1
  149. package/src/locus-info/index.ts +304 -100
  150. package/src/locus-info/infoUtils.ts +41 -6
  151. package/src/locus-info/types.ts +25 -1
  152. package/src/media/index.ts +3 -0
  153. package/src/media/properties.ts +1 -0
  154. package/src/meeting/in-meeting-actions.ts +8 -0
  155. package/src/meeting/index.ts +494 -67
  156. package/src/meeting/locusMediaRequest.ts +106 -6
  157. package/src/meeting/muteState.ts +10 -1
  158. package/src/meeting/request.ts +11 -0
  159. package/src/meeting/util.ts +47 -5
  160. package/src/meeting-info/meeting-info-v2.ts +4 -2
  161. package/src/meetings/index.ts +133 -78
  162. package/src/meetings/meetings.types.ts +19 -0
  163. package/src/meetings/request.ts +43 -0
  164. package/src/meetings/util.ts +97 -1
  165. package/src/member/index.ts +10 -0
  166. package/src/member/types.ts +1 -0
  167. package/src/member/util.ts +29 -0
  168. package/src/members/index.ts +70 -7
  169. package/src/members/util.ts +12 -4
  170. package/src/metrics/constants.ts +4 -0
  171. package/src/multistream/codec/constants.ts +58 -0
  172. package/src/multistream/mediaRequestManager.ts +119 -28
  173. package/src/multistream/receiveSlot.ts +18 -0
  174. package/src/reachability/index.ts +19 -15
  175. package/src/reachability/reachability.types.ts +11 -0
  176. package/src/reachability/util.ts +36 -0
  177. package/src/reactions/reactions.type.ts +3 -0
  178. package/src/recording-controller/index.ts +1 -2
  179. package/src/webinar/index.ts +214 -36
  180. package/test/unit/spec/aiEnableRequest/index.ts +86 -0
  181. package/test/unit/spec/breakouts/breakout.ts +9 -3
  182. package/test/unit/spec/breakouts/index.ts +49 -0
  183. package/test/unit/spec/controls-options-manager/index.js +244 -29
  184. package/test/unit/spec/controls-options-manager/util.js +165 -0
  185. package/test/unit/spec/hashTree/hashTreeParser.ts +1838 -180
  186. package/test/unit/spec/hashTree/utils.ts +125 -1
  187. package/test/unit/spec/interceptors/dataChannelAuthToken.ts +196 -0
  188. package/test/unit/spec/interceptors/locusRetry.ts +205 -4
  189. package/test/unit/spec/interpretation/index.ts +26 -4
  190. package/test/unit/spec/locus-info/controlsUtils.js +172 -57
  191. package/test/unit/spec/locus-info/index.js +499 -81
  192. package/test/unit/spec/locus-info/infoUtils.js +184 -1
  193. package/test/unit/spec/media/index.ts +31 -0
  194. package/test/unit/spec/meeting/in-meeting-actions.ts +4 -0
  195. package/test/unit/spec/meeting/index.js +1615 -42
  196. package/test/unit/spec/meeting/locusMediaRequest.ts +302 -4
  197. package/test/unit/spec/meeting/muteState.js +81 -0
  198. package/test/unit/spec/meeting/request.js +12 -0
  199. package/test/unit/spec/meeting/utils.js +157 -1
  200. package/test/unit/spec/meeting-info/meetinginfov2.js +19 -10
  201. package/test/unit/spec/meetings/index.js +363 -36
  202. package/test/unit/spec/meetings/request.js +141 -0
  203. package/test/unit/spec/meetings/utils.js +189 -0
  204. package/test/unit/spec/member/index.js +7 -0
  205. package/test/unit/spec/member/util.js +89 -0
  206. package/test/unit/spec/members/index.js +216 -0
  207. package/test/unit/spec/members/request.js +37 -1
  208. package/test/unit/spec/members/utils.js +63 -0
  209. package/test/unit/spec/multistream/mediaRequestManager.ts +501 -37
  210. package/test/unit/spec/reachability/index.ts +59 -46
  211. package/test/unit/spec/reachability/util.ts +31 -0
  212. package/test/unit/spec/recording-controller/index.js +9 -8
  213. package/test/unit/spec/webinar/index.ts +329 -28
@@ -1,10 +1,10 @@
1
1
  import {camelCase} from 'lodash';
2
+ import ParameterError from '../common/errors/parameter';
2
3
  import PermissionError from '../common/errors/permission';
3
- import {CONTROLS, HTTP_VERBS} from '../constants';
4
4
  import MeetingRequest from '../meeting/request';
5
5
  import LoggerProxy from '../common/logs/logger-proxy';
6
6
  import {Control, Setting} from './enums';
7
- import {ControlConfig} from './types';
7
+ import {ControlConfig, ViewTheParticipantListProperties} from './types';
8
8
  import Util from './util';
9
9
  import {CAN_SET, CAN_UNSET, ENABLED} from './constants';
10
10
 
@@ -56,6 +56,10 @@ export default class ControlsOptionsManager {
56
56
  */
57
57
  private mainLocusUrl: string;
58
58
 
59
+ private getControls: () => Record<string, any> = () => ({});
60
+
61
+ private isWebinar: () => boolean = () => false;
62
+
59
63
  /**
60
64
  * @param {MeetingRequest} request
61
65
  * @param {Object} options
@@ -67,6 +71,8 @@ export default class ControlsOptionsManager {
67
71
  options?: {
68
72
  locusUrl: string;
69
73
  displayHints?: Array<string>;
74
+ getControls?: () => Record<string, any>;
75
+ isWebinar?: () => boolean;
70
76
  }
71
77
  ) {
72
78
  this.initialize(request);
@@ -89,7 +95,12 @@ export default class ControlsOptionsManager {
89
95
  * @public
90
96
  * @memberof ControlsOptionsManager
91
97
  */
92
- public set(options?: {locusUrl: string; displayHints?: Array<string>}) {
98
+ public set(options?: {
99
+ locusUrl: string;
100
+ displayHints?: Array<string>;
101
+ getControls?: () => Record<string, any>;
102
+ isWebinar?: () => boolean;
103
+ }) {
93
104
  this.extract(options);
94
105
  }
95
106
 
@@ -141,9 +152,20 @@ export default class ControlsOptionsManager {
141
152
  * @private
142
153
  * @memberof ControlsOptionsManager
143
154
  */
144
- private extract(options?: {locusUrl: string; displayHints?: Array<string>}) {
155
+ private extract(options?: {
156
+ locusUrl: string;
157
+ displayHints?: Array<string>;
158
+ getControls?: () => Record<string, any>;
159
+ isWebinar?: () => boolean;
160
+ }) {
145
161
  this.setDisplayHints(options?.displayHints);
146
162
  this.setLocusUrl(options?.locusUrl);
163
+ if (options?.getControls) {
164
+ this.getControls = options.getControls;
165
+ }
166
+ if (options?.isWebinar) {
167
+ this.isWebinar = options.isWebinar;
168
+ }
147
169
  }
148
170
 
149
171
  /**
@@ -153,6 +175,12 @@ export default class ControlsOptionsManager {
153
175
  * @returns {Promise<Array<any>>}- Promise resolving if the request was successful.
154
176
  */
155
177
  public update(...controls: Array<ControlConfig>) {
178
+ if (!this.locusUrl) {
179
+ return Promise.reject(
180
+ new ParameterError('The associated locusUrl for update() controls must be defined.')
181
+ );
182
+ }
183
+
156
184
  const payloads = controls.map((control) => {
157
185
  if (!Object.keys(Control).includes(control.scope)) {
158
186
  throw new Error(
@@ -166,25 +194,33 @@ export default class ControlsOptionsManager {
166
194
  );
167
195
  }
168
196
 
197
+ let {properties} = control;
198
+
199
+ if (control.scope === Control.viewTheParticipantList) {
200
+ const props = properties as ViewTheParticipantListProperties;
201
+ const current = this.getControls()?.viewTheParticipantList;
202
+ properties = {
203
+ enabled: props.enabled ?? current?.enabled ?? false,
204
+ ...(this.isWebinar() && {
205
+ panelistEnabled: props.panelistEnabled ?? current?.panelistEnabled ?? false,
206
+ attendeeCount: props.attendeeCount ?? Boolean(current?.attendeeCount) ?? false,
207
+ }),
208
+ };
209
+ }
210
+
169
211
  return {
170
- [control.scope]: control.properties,
212
+ [control.scope]: properties,
171
213
  };
172
214
  });
173
215
 
174
216
  return payloads.reduce((previous, payload) => {
175
- const extraBody =
176
- this.mainLocusUrl && this.mainLocusUrl !== this.locusUrl
177
- ? {authorizingLocusUrl: this.locusUrl}
178
- : {};
179
-
180
- return previous.then(() =>
181
- // @ts-ignore
182
- this.request.request({
183
- uri: `${this.mainLocusUrl || this.locusUrl}/${CONTROLS}`,
184
- body: {...payload, ...extraBody},
185
- method: HTTP_VERBS.PATCH,
186
- })
187
- );
217
+ const requestParams = Util.getControlsRequestParams({
218
+ body: payload,
219
+ locusUrl: this.locusUrl,
220
+ mainLocusUrl: this.mainLocusUrl,
221
+ });
222
+
223
+ return previous.then(() => this.sendControlsRequest(requestParams));
188
224
  }, Promise.resolve());
189
225
  }
190
226
 
@@ -200,6 +236,12 @@ export default class ControlsOptionsManager {
200
236
  [Setting.muteOnEntry]?: boolean;
201
237
  [Setting.roles]?: Array<string>;
202
238
  }): Promise<any> {
239
+ if (!this.locusUrl) {
240
+ return Promise.reject(
241
+ new ParameterError('The associated locusUrl for setControls() must be defined.')
242
+ );
243
+ }
244
+
203
245
  LoggerProxy.logger.log(
204
246
  `ControlsOptionsManager:index#setControls --> ${JSON.stringify(setting)}`
205
247
  );
@@ -258,17 +300,34 @@ export default class ControlsOptionsManager {
258
300
  if (error) {
259
301
  return Promise.reject(error);
260
302
  }
261
- const extraBody =
262
- this.mainLocusUrl && this.mainLocusUrl !== this.locusUrl
263
- ? {authorizingLocusUrl: this.locusUrl}
264
- : {};
265
-
266
- // @ts-ignore
267
- return this.request.request({
268
- uri: `${this.mainLocusUrl || this.locusUrl}/${CONTROLS}`,
269
- body: {...body, ...extraBody},
270
- method: HTTP_VERBS.PATCH,
303
+
304
+ const requestParams = Util.getControlsRequestParams({
305
+ body,
306
+ locusUrl: this.locusUrl,
307
+ mainLocusUrl: this.mainLocusUrl,
271
308
  });
309
+
310
+ return this.sendControlsRequest(requestParams);
311
+ }
312
+
313
+ /**
314
+ * Sends a controls request to Locus. When authorizingLocusUrl is present in the body,
315
+ * we use a plain request() because the response contains the main session Locus DTO
316
+ * instead of the breakout we're in, so we don't want to parse it as a delta.
317
+ * Otherwise we use locusDeltaRequest() for normal delta processing.
318
+ *
319
+ * @param {Object} requestParams - The request parameters from getControlsRequestParams.
320
+ * @returns {Promise<any>}
321
+ */
322
+ private sendControlsRequest(requestParams: {
323
+ uri: string;
324
+ body: Record<string, any>;
325
+ method: string;
326
+ }): Promise<any> {
327
+ return requestParams.body.authorizingLocusUrl
328
+ ? // @ts-ignore
329
+ this.request.request(requestParams)
330
+ : this.request.locusDeltaRequest(requestParams);
272
331
  }
273
332
 
274
333
  /**
@@ -1,5 +1,6 @@
1
- import {DISPLAY_HINTS} from '../constants';
1
+ import {CONTROLS, DISPLAY_HINTS, HTTP_VERBS} from '../constants';
2
2
  import {Control} from './enums';
3
+ import {AUDIO_CONTROL_BODY_KEYS} from './constants';
3
4
  import {
4
5
  ControlConfig,
5
6
  AudioProperties,
@@ -400,6 +401,85 @@ class Utils {
400
401
 
401
402
  return determinant;
402
403
  }
404
+
405
+ /**
406
+ * Check if all body keys represent audio controls.
407
+ *
408
+ * @param {Record<string, any>} body - The request body to inspect.
409
+ * @returns {boolean} - True if every key in the body is an audio control key.
410
+ */
411
+ public static isAudioControl(body: Record<string, any>): boolean {
412
+ return Object.keys(body).every((key) => AUDIO_CONTROL_BODY_KEYS.has(key));
413
+ }
414
+
415
+ /**
416
+ * Check if the current locus URL differs from the main locus URL,
417
+ * indicating a breakout session.
418
+ *
419
+ * @param {string} locusUrl - The current locus URL.
420
+ * @param {string} [mainLocusUrl] - The main locus URL.
421
+ * @returns {boolean} - True if in a breakout session.
422
+ */
423
+ public static isBreakoutLocusUrl(locusUrl: string, mainLocusUrl?: string): boolean {
424
+ return Boolean(mainLocusUrl) && mainLocusUrl !== locusUrl;
425
+ }
426
+
427
+ /**
428
+ * Resolve the target URL and extra body fields for a controls request,
429
+ * handling breakout session routing. Note: This is a pure computation function.
430
+ * It does not validate that locusUrl is
431
+ * defined. Callers must guard against falsy locusUrl before
432
+ * invoking this function.
433
+ * Mixed audio and non-audio keys in a single body (e.g., {audio: {...},
434
+ * raiseHand: {...}}) are treated as non-audio and routed to mainLocusUrl with
435
+ * authorizingLocusUrl. This means the audio portion would go through unsupported
436
+ * cross-locus authorization. Callers must not produce mixed payloads — update()
437
+ * sends each control scope as a separate request, and setControls() only handles
438
+ * audio-related settings.
439
+ *
440
+ * The authorizingLocusUrl mechanism on PATCH /loci/{lid}/controls is not supported
441
+ * for audio control updates (mute/unmute, muteOnEntry, disallowUnmute).
442
+ * Audio controls are not wired into the cross-locus GraphQL authorization path that
443
+ * other control types (raiseHand, viewParticipantList, admit, reactions, etc.) use.
444
+ * Specifically, the GraphQL authorization layer does not recognize audio as a control
445
+ * type eligible for remote locus authorization.
446
+ * This means authorizingLocusUrl is effectively ignored for audio controls and the
447
+ * server evaluates the request against the target locus only, where the host may not
448
+ * be currently joined.
449
+ * Audio control updates must be sent directly to the locus the user is currently in.
450
+ * If the host is in a breakout and wants to mute participants in that breakout, the
451
+ * request should target the breakout locus URL directly, not the main session locus
452
+ * with authorizingLocusUrl.
453
+ * Meeting-wide audio control actions (e.g., muting panelists across all breakouts
454
+ * from a single request) are not currently supported through this mechanism.
455
+ *
456
+ * @param {object} options
457
+ * @param {Record<string, any>} options.body - The request body.
458
+ * @param {string} options.locusUrl - The current locus URL. Must be defined (callers must validate).
459
+ * @param {string} [options.mainLocusUrl] - The main locus URL.
460
+ * @returns {{ uri: string, body: Record<string, any>, method: string }}
461
+ */
462
+ public static getControlsRequestParams(options: {
463
+ body: Record<string, any>;
464
+ locusUrl: string;
465
+ mainLocusUrl?: string;
466
+ }): {
467
+ uri: string;
468
+ body: Record<string, any>;
469
+ method: string;
470
+ } {
471
+ const {body, locusUrl, mainLocusUrl} = options;
472
+
473
+ const isAudio = Utils.isAudioControl(body);
474
+ const inBreakout = Utils.isBreakoutLocusUrl(locusUrl, mainLocusUrl);
475
+ const targetUrl = inBreakout && !isAudio ? mainLocusUrl : locusUrl;
476
+
477
+ return {
478
+ uri: `${targetUrl}/${CONTROLS}`,
479
+ body: inBreakout && !isAudio ? {...body, authorizingLocusUrl: locusUrl} : body,
480
+ method: HTTP_VERBS.PATCH,
481
+ };
482
+ }
403
483
  }
404
484
 
405
485
  export default Utils;
@@ -8,3 +8,19 @@ export const DataSetNames = {
8
8
  SELF: 'self', // sent to web client, over Mercury
9
9
  UNJOINED: 'unjoined', // sent when you are not joined, but can still see some stuff from the meeting (mutually exclusive with "main")
10
10
  };
11
+
12
+ // Priority order for initializing data sets — higher priority names come first.
13
+ // Data sets not listed here will be initialized after all prioritized ones.
14
+ // MAIN must come before SELF because LocusInfo.updateFromHashTree processes the
15
+ // batch of updatedObjects in order, and the SELF handler in updateLocusFromHashTreeObject
16
+ // checks locus.info?.isWebinar (which comes from MAIN) to decide whether to create a
17
+ // participant object for webinar attendees. If SELF were initialized first, locus.info
18
+ // would not yet be populated and the attendee participant would be skipped.
19
+ export const DATA_SET_INIT_PRIORITY: string[] = [DataSetNames.MAIN, DataSetNames.SELF];
20
+
21
+ // Data sets for which we normally receive events over LLM connection
22
+ export const LLM_DATASET_NAMES = [
23
+ DataSetNames.MAIN,
24
+ DataSetNames.ATD_ACTIVE,
25
+ DataSetNames.ATD_UNMUTED,
26
+ ];