@webex/plugin-meetings 3.12.0-next.9 → 3.12.0-task-refactor.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.
Files changed (201) hide show
  1. package/dist/annotation/index.js +5 -14
  2. package/dist/annotation/index.js.map +1 -1
  3. package/dist/breakouts/breakout.js +1 -1
  4. package/dist/breakouts/index.js +1 -1
  5. package/dist/config.js +2 -8
  6. package/dist/config.js.map +1 -1
  7. package/dist/constants.js +6 -29
  8. package/dist/constants.js.map +1 -1
  9. package/dist/hashTree/hashTreeParser.js +29 -1563
  10. package/dist/hashTree/hashTreeParser.js.map +1 -1
  11. package/dist/hashTree/types.js +3 -13
  12. package/dist/hashTree/types.js.map +1 -1
  13. package/dist/index.js +2 -11
  14. package/dist/index.js.map +1 -1
  15. package/dist/interceptors/index.js +0 -7
  16. package/dist/interceptors/index.js.map +1 -1
  17. package/dist/interceptors/locusRouteToken.js +5 -27
  18. package/dist/interceptors/locusRouteToken.js.map +1 -1
  19. package/dist/interpretation/index.js +2 -2
  20. package/dist/interpretation/index.js.map +1 -1
  21. package/dist/interpretation/siLanguage.js +1 -1
  22. package/dist/locus-info/controlsUtils.js +3 -7
  23. package/dist/locus-info/controlsUtils.js.map +1 -1
  24. package/dist/locus-info/index.js +247 -642
  25. package/dist/locus-info/index.js.map +1 -1
  26. package/dist/locus-info/selfUtils.js +0 -1
  27. package/dist/locus-info/selfUtils.js.map +1 -1
  28. package/dist/locus-info/types.js.map +1 -1
  29. package/dist/media/MediaConnectionAwaiter.js +1 -57
  30. package/dist/media/MediaConnectionAwaiter.js.map +1 -1
  31. package/dist/media/properties.js +2 -4
  32. package/dist/media/properties.js.map +1 -1
  33. package/dist/meeting/in-meeting-actions.js +1 -7
  34. package/dist/meeting/in-meeting-actions.js.map +1 -1
  35. package/dist/meeting/index.js +1036 -1481
  36. package/dist/meeting/index.js.map +1 -1
  37. package/dist/meeting/request.js +0 -50
  38. package/dist/meeting/request.js.map +1 -1
  39. package/dist/meeting/request.type.js.map +1 -1
  40. package/dist/meeting/util.js +3 -133
  41. package/dist/meeting/util.js.map +1 -1
  42. package/dist/meetings/index.js +59 -142
  43. package/dist/meetings/index.js.map +1 -1
  44. package/dist/meetings/util.js +7 -11
  45. package/dist/meetings/util.js.map +1 -1
  46. package/dist/member/index.js +0 -10
  47. package/dist/member/index.js.map +1 -1
  48. package/dist/member/util.js +0 -10
  49. package/dist/member/util.js.map +1 -1
  50. package/dist/metrics/constants.js +1 -7
  51. package/dist/metrics/constants.js.map +1 -1
  52. package/dist/multistream/mediaRequestManager.js +60 -9
  53. package/dist/multistream/mediaRequestManager.js.map +1 -1
  54. package/dist/multistream/remoteMediaManager.js +0 -11
  55. package/dist/multistream/remoteMediaManager.js.map +1 -1
  56. package/dist/multistream/sendSlotManager.js +2 -116
  57. package/dist/multistream/sendSlotManager.js.map +1 -1
  58. package/dist/reachability/clusterReachability.js +18 -171
  59. package/dist/reachability/clusterReachability.js.map +1 -1
  60. package/dist/reachability/index.js +11 -21
  61. package/dist/reachability/index.js.map +1 -1
  62. package/dist/reachability/reachabilityPeerConnection.js +1 -1
  63. package/dist/reachability/reachabilityPeerConnection.js.map +1 -1
  64. package/dist/reactions/reactions.type.js.map +1 -1
  65. package/dist/reconnection-manager/index.js +1 -0
  66. package/dist/reconnection-manager/index.js.map +1 -1
  67. package/dist/types/common/browser-detection.d.ts +0 -1
  68. package/dist/types/common/events/events-scope.d.ts +0 -1
  69. package/dist/types/common/events/events.d.ts +0 -1
  70. package/dist/types/config.d.ts +0 -5
  71. package/dist/types/constants.d.ts +1 -24
  72. package/dist/types/hashTree/hashTreeParser.d.ts +11 -260
  73. package/dist/types/hashTree/types.d.ts +0 -20
  74. package/dist/types/index.d.ts +0 -1
  75. package/dist/types/interceptors/index.d.ts +1 -2
  76. package/dist/types/interceptors/locusRouteToken.d.ts +0 -2
  77. package/dist/types/locus-info/index.d.ts +47 -68
  78. package/dist/types/locus-info/types.d.ts +12 -28
  79. package/dist/types/media/MediaConnectionAwaiter.d.ts +1 -10
  80. package/dist/types/media/properties.d.ts +1 -2
  81. package/dist/types/meeting/in-meeting-actions.d.ts +0 -6
  82. package/dist/types/meeting/index.d.ts +7 -86
  83. package/dist/types/meeting/request.d.ts +1 -16
  84. package/dist/types/meeting/request.type.d.ts +0 -5
  85. package/dist/types/meeting/util.d.ts +0 -31
  86. package/dist/types/meeting-info/util.d.ts +0 -1
  87. package/dist/types/meeting-info/utilv2.d.ts +0 -1
  88. package/dist/types/meetings/index.d.ts +2 -4
  89. package/dist/types/member/index.d.ts +0 -1
  90. package/dist/types/member/types.d.ts +4 -4
  91. package/dist/types/member/util.d.ts +0 -5
  92. package/dist/types/metrics/constants.d.ts +0 -6
  93. package/dist/types/multistream/mediaRequestManager.d.ts +23 -0
  94. package/dist/types/multistream/sendSlotManager.d.ts +1 -23
  95. package/dist/types/reachability/clusterReachability.d.ts +3 -30
  96. package/dist/types/reactions/reactions.type.d.ts +0 -1
  97. package/dist/types/recording-controller/util.d.ts +5 -5
  98. package/dist/types/roap/index.d.ts +1 -1
  99. package/dist/webinar/index.js +163 -438
  100. package/dist/webinar/index.js.map +1 -1
  101. package/package.json +24 -26
  102. package/src/annotation/index.ts +7 -27
  103. package/src/config.ts +0 -5
  104. package/src/constants.ts +1 -30
  105. package/src/hashTree/hashTreeParser.ts +25 -1523
  106. package/src/hashTree/types.ts +1 -24
  107. package/src/index.ts +1 -8
  108. package/src/interceptors/index.ts +1 -2
  109. package/src/interceptors/locusRouteToken.ts +5 -22
  110. package/src/interpretation/index.ts +2 -2
  111. package/src/locus-info/controlsUtils.ts +0 -17
  112. package/src/locus-info/index.ts +213 -707
  113. package/src/locus-info/selfUtils.ts +0 -1
  114. package/src/locus-info/types.ts +12 -27
  115. package/src/media/MediaConnectionAwaiter.ts +1 -41
  116. package/src/media/properties.ts +1 -3
  117. package/src/meeting/in-meeting-actions.ts +0 -12
  118. package/src/meeting/index.ts +84 -461
  119. package/src/meeting/request.ts +0 -42
  120. package/src/meeting/request.type.ts +0 -6
  121. package/src/meeting/util.ts +2 -160
  122. package/src/meetings/index.ts +60 -180
  123. package/src/meetings/util.ts +9 -10
  124. package/src/member/index.ts +0 -10
  125. package/src/member/util.ts +0 -12
  126. package/src/metrics/constants.ts +0 -7
  127. package/src/multistream/mediaRequestManager.ts +54 -4
  128. package/src/multistream/remoteMediaManager.ts +0 -13
  129. package/src/multistream/sendSlotManager.ts +3 -97
  130. package/src/reachability/clusterReachability.ts +27 -153
  131. package/src/reachability/index.ts +1 -15
  132. package/src/reachability/reachabilityPeerConnection.ts +1 -3
  133. package/src/reactions/reactions.type.ts +0 -1
  134. package/src/reconnection-manager/index.ts +1 -0
  135. package/src/webinar/index.ts +6 -265
  136. package/test/unit/spec/annotation/index.ts +7 -69
  137. package/test/unit/spec/interceptors/locusRouteToken.ts +0 -44
  138. package/test/unit/spec/locus-info/controlsUtils.js +1 -56
  139. package/test/unit/spec/locus-info/index.js +90 -1457
  140. package/test/unit/spec/media/MediaConnectionAwaiter.ts +1 -41
  141. package/test/unit/spec/media/properties.ts +3 -12
  142. package/test/unit/spec/meeting/in-meeting-actions.ts +2 -8
  143. package/test/unit/spec/meeting/index.js +128 -981
  144. package/test/unit/spec/meeting/request.js +0 -70
  145. package/test/unit/spec/meeting/utils.js +26 -438
  146. package/test/unit/spec/meetings/index.js +33 -845
  147. package/test/unit/spec/meetings/utils.js +1 -51
  148. package/test/unit/spec/member/index.js +4 -28
  149. package/test/unit/spec/member/util.js +27 -65
  150. package/test/unit/spec/multistream/mediaRequestManager.ts +85 -2
  151. package/test/unit/spec/multistream/remoteMediaManager.ts +0 -30
  152. package/test/unit/spec/multistream/sendSlotManager.ts +36 -135
  153. package/test/unit/spec/reachability/clusterReachability.ts +1 -125
  154. package/test/unit/spec/reachability/index.ts +3 -26
  155. package/test/unit/spec/reconnection-manager/index.js +8 -4
  156. package/test/unit/spec/webinar/index.ts +37 -534
  157. package/dist/aiEnableRequest/index.js +0 -184
  158. package/dist/aiEnableRequest/index.js.map +0 -1
  159. package/dist/aiEnableRequest/utils.js +0 -36
  160. package/dist/aiEnableRequest/utils.js.map +0 -1
  161. package/dist/hashTree/constants.js +0 -22
  162. package/dist/hashTree/constants.js.map +0 -1
  163. package/dist/hashTree/hashTree.js +0 -533
  164. package/dist/hashTree/hashTree.js.map +0 -1
  165. package/dist/hashTree/utils.js +0 -69
  166. package/dist/hashTree/utils.js.map +0 -1
  167. package/dist/interceptors/constant.js +0 -12
  168. package/dist/interceptors/constant.js.map +0 -1
  169. package/dist/interceptors/dataChannelAuthToken.js +0 -290
  170. package/dist/interceptors/dataChannelAuthToken.js.map +0 -1
  171. package/dist/interceptors/utils.js +0 -27
  172. package/dist/interceptors/utils.js.map +0 -1
  173. package/dist/types/aiEnableRequest/index.d.ts +0 -5
  174. package/dist/types/aiEnableRequest/utils.d.ts +0 -2
  175. package/dist/types/hashTree/constants.d.ts +0 -9
  176. package/dist/types/hashTree/hashTree.d.ts +0 -136
  177. package/dist/types/hashTree/utils.d.ts +0 -22
  178. package/dist/types/interceptors/constant.d.ts +0 -5
  179. package/dist/types/interceptors/dataChannelAuthToken.d.ts +0 -43
  180. package/dist/types/interceptors/utils.d.ts +0 -1
  181. package/dist/types/webinar/utils.d.ts +0 -6
  182. package/dist/webinar/utils.js +0 -25
  183. package/dist/webinar/utils.js.map +0 -1
  184. package/src/aiEnableRequest/README.md +0 -84
  185. package/src/aiEnableRequest/index.ts +0 -170
  186. package/src/aiEnableRequest/utils.ts +0 -25
  187. package/src/hashTree/constants.ts +0 -10
  188. package/src/hashTree/hashTree.ts +0 -480
  189. package/src/hashTree/utils.ts +0 -62
  190. package/src/interceptors/constant.ts +0 -6
  191. package/src/interceptors/dataChannelAuthToken.ts +0 -170
  192. package/src/interceptors/utils.ts +0 -16
  193. package/src/webinar/utils.ts +0 -16
  194. package/test/unit/spec/aiEnableRequest/index.ts +0 -981
  195. package/test/unit/spec/aiEnableRequest/utils.ts +0 -130
  196. package/test/unit/spec/hashTree/hashTree.ts +0 -721
  197. package/test/unit/spec/hashTree/hashTreeParser.ts +0 -3670
  198. package/test/unit/spec/hashTree/utils.ts +0 -140
  199. package/test/unit/spec/interceptors/dataChannelAuthToken.ts +0 -210
  200. package/test/unit/spec/interceptors/utils.ts +0 -75
  201. package/test/unit/spec/webinar/utils.ts +0 -39
@@ -33,7 +33,6 @@ import {
33
33
  ToggleReactionsOptions,
34
34
  PostMeetingDataConsentOptions,
35
35
  SynchronizeVideoLayout,
36
- fetchDataChannelTokenOptions,
37
36
  } from './request.type';
38
37
  import MeetingUtil from './util';
39
38
  import {AnnotationInfo} from '../annotation/annotation.types';
@@ -1127,45 +1126,4 @@ export default class MeetingRequest extends StatelessWebexPlugin {
1127
1126
  throw err;
1128
1127
  }
1129
1128
  }
1130
-
1131
- /**
1132
- * Sends a request to retrieve the datachannel authorization token for a participant.
1133
- *
1134
- * For regular meeting data channel:
1135
- * GET /locus/api/v1/loci/{uuid:lid}/participant/{uuid:pid}/datachannel/token
1136
- *
1137
- * For practice session data channel:
1138
- * GET /locus/api/v1/loci/{uuid:lid}/participant/{uuid:pid}/practiceSession/datachannel/token
1139
- *
1140
- * @param {string} locusUrl - The locus url.
1141
- * @param {string} requestingParticipantId - The participant UUID.
1142
- * @param {boolean} [isPracticeSession=false] - Whether to get the practice session token.
1143
- * @returns {Promise<{datachannelToken: string}>}
1144
- */
1145
- public async fetchDatachannelToken({
1146
- locusUrl,
1147
- requestingParticipantId,
1148
- isPracticeSession = false,
1149
- }: fetchDataChannelTokenOptions) {
1150
- if (!locusUrl || !requestingParticipantId) {
1151
- return Promise.reject(new Error('locusUrl and participantId are required'));
1152
- }
1153
- const practicePrefix = isPracticeSession ? '/practiceSession' : '';
1154
-
1155
- const uri = `${locusUrl}/${PARTICIPANT}/${requestingParticipantId}${practicePrefix}/datachannel/token`;
1156
-
1157
- // @ts-ignore
1158
- return this.locusDeltaRequest({
1159
- method: HTTP_VERBS.GET,
1160
- uri,
1161
- }).catch((err) => {
1162
- LoggerProxy.logger.warn(
1163
- `Meeting:request#fetchDatachannelToken --> Failed to retrieve ${
1164
- isPracticeSession ? 'practice session ' : ''
1165
- }datachannel token: ${err?.message || err}`
1166
- );
1167
-
1168
- return null;
1169
- });
1170
- }
1171
1129
  }
@@ -88,10 +88,4 @@ export type UnsetStageVideoLayout = {
88
88
  overrideDefault: false;
89
89
  };
90
90
 
91
- export type fetchDataChannelTokenOptions = {
92
- locusUrl: string;
93
- requestingParticipantId: string;
94
- isPracticeSession: boolean;
95
- };
96
-
97
91
  export type SynchronizeVideoLayout = SetStageVideoLayout | UnsetStageVideoLayout;
@@ -1,5 +1,4 @@
1
1
  import {LocalCameraStream, LocalMicrophoneStream} from '@webex/media-helpers';
2
- import url from 'url';
3
2
 
4
3
  import {cloneDeep} from 'lodash';
5
4
  import {MeetingNotActiveError, UserNotJoinedError} from '../common/errors/webex-errors';
@@ -25,7 +24,6 @@ import PermissionError from '../common/errors/permission';
25
24
  import PasswordError from '../common/errors/password-error';
26
25
  import CaptchaError from '../common/errors/captcha-error';
27
26
  import Trigger from '../common/events/trigger-proxy';
28
- import {ServerRoles} from '../member/types';
29
27
 
30
28
  const MeetingUtil = {
31
29
  parseLocusJoin: (response) => {
@@ -34,7 +32,6 @@ const MeetingUtil = {
34
32
  // First todo: add check for existance
35
33
  parsed.locus = response.body.locus;
36
34
  parsed.dataSets = response.body.dataSets;
37
- parsed.metadata = response.body.metaData;
38
35
  parsed.mediaConnections = response.body.mediaConnections;
39
36
  parsed.locusUrl = parsed.locus.url;
40
37
  parsed.locusId = parsed.locus.url.split('/').pop();
@@ -50,124 +47,6 @@ const MeetingUtil = {
50
47
  return parsed;
51
48
  },
52
49
 
53
- /**
54
- * Sanitizes a WebSocket URL by extracting only protocol, host, and pathname
55
- * Returns concatenated protocol + host + pathname for safe logging
56
- * Note: This is used for logging only; URL matching uses partial matching via _urlsPartiallyMatch
57
- * @param {string} urlString - The URL to sanitize
58
- * @returns {string} Sanitized URL or empty string if parsing fails
59
- */
60
- sanitizeWebSocketUrl: (urlString: string): string => {
61
- if (!urlString || typeof urlString !== 'string') {
62
- return '';
63
- }
64
-
65
- try {
66
- const parsedUrl = url.parse(urlString);
67
- const protocol = parsedUrl.protocol || '';
68
- const host = parsedUrl.host || '';
69
-
70
- // If we don't have at least protocol and host, it's not a valid URL
71
- if (!protocol || !host) {
72
- return '';
73
- }
74
-
75
- const pathname = parsedUrl.pathname || '';
76
-
77
- // Strip trailing slash if pathname is just '/'
78
- const normalizedPathname = pathname === '/' ? '' : pathname;
79
-
80
- return `${protocol}//${host}${normalizedPathname}`;
81
- } catch (error) {
82
- LoggerProxy.logger.warn(
83
- `Meeting:util#sanitizeWebSocketUrl --> unable to parse URL: ${error}`
84
- );
85
-
86
- return '';
87
- }
88
- },
89
-
90
- /**
91
- * Checks if two URLs partially match using an endsWith approach
92
- * Combines host and pathname, then checks if one ends with the other
93
- * This handles cases where one URL goes through a proxy (e.g., /webproxy/) while the other is direct
94
- * @param {string} url1 - First URL to compare
95
- * @param {string} url2 - Second URL to compare
96
- * @returns {boolean} True if one URL path ends with the other (partial match), false otherwise
97
- */
98
- _urlsPartiallyMatch: (url1: string, url2: string): boolean => {
99
- if (!url1 || !url2) {
100
- return false;
101
- }
102
-
103
- try {
104
- const parsedUrl1 = url.parse(url1);
105
- const parsedUrl2 = url.parse(url2);
106
-
107
- const host1 = parsedUrl1.host || '';
108
- const host2 = parsedUrl2.host || '';
109
- const pathname1 = parsedUrl1.pathname || '';
110
- const pathname2 = parsedUrl2.pathname || '';
111
-
112
- // If either failed to parse, they don't match
113
- if (!host1 || !host2 || !pathname1 || !pathname2) {
114
- return false;
115
- }
116
-
117
- // Combine host and pathname for comparison
118
- const combined1 = host1 + pathname1;
119
- const combined2 = host2 + pathname2;
120
-
121
- // Check if one combined path ends with the other (handles proxy URLs)
122
- return combined1.endsWith(combined2) || combined2.endsWith(combined1);
123
- } catch (e) {
124
- LoggerProxy.logger.warn('Meeting:util#_urlsPartiallyMatch --> error comparing URLs', e);
125
-
126
- return false;
127
- }
128
- },
129
-
130
- /**
131
- * Gets socket URL information for metrics, including whether the socket URLs match
132
- * Uses partial matching to handle proxy URLs (e.g., URLs with /webproxy/ prefix)
133
- * @param {Object} webex - The webex instance
134
- * @returns {Object} Object with hasMismatchedSocket, mercurySocketUrl, and deviceSocketUrl properties
135
- */
136
- getSocketUrlInfo: (
137
- webex: any
138
- ): {hasMismatchedSocket: boolean; mercurySocketUrl: string; deviceSocketUrl: string} => {
139
- try {
140
- const mercuryUrl = webex?.internal?.mercury?.socket?.url;
141
- const deviceUrl = webex?.internal?.device?.webSocketUrl;
142
-
143
- const sanitizedMercuryUrl = MeetingUtil.sanitizeWebSocketUrl(mercuryUrl);
144
- const sanitizedDeviceUrl = MeetingUtil.sanitizeWebSocketUrl(deviceUrl);
145
-
146
- // Only report a mismatch if both URLs are present and they don't match
147
- // If either URL is missing, we can't determine if there's a mismatch, so return false
148
- let hasMismatchedSocket = false;
149
- if (sanitizedMercuryUrl && sanitizedDeviceUrl) {
150
- hasMismatchedSocket = !MeetingUtil._urlsPartiallyMatch(mercuryUrl, deviceUrl);
151
- }
152
-
153
- return {
154
- hasMismatchedSocket,
155
- mercurySocketUrl: sanitizedMercuryUrl,
156
- deviceSocketUrl: sanitizedDeviceUrl,
157
- };
158
- } catch (error) {
159
- LoggerProxy.logger.warn(
160
- `Meeting:util#getSocketUrlInfo --> error getting socket URL info: ${error}`
161
- );
162
-
163
- return {
164
- hasMismatchedSocket: false,
165
- mercurySocketUrl: '',
166
- deviceSocketUrl: '',
167
- };
168
- }
169
- },
170
-
171
50
  remoteUpdateAudioVideo: (meeting, audioMuted?: boolean, videoMuted?: boolean) => {
172
51
  if (!meeting) {
173
52
  return Promise.reject(new ParameterError('You need a meeting object.'));
@@ -324,7 +203,6 @@ const MeetingUtil = {
324
203
  const parsed = MeetingUtil.parseLocusJoin(res);
325
204
  meeting.setLocus(parsed);
326
205
  meeting.isoLocalClientMeetingJoinTime = res?.headers?.date; // read from header if exist, else fall back to system clock : https://jira-eng-gpk2.cisco.com/jira/browse/SPARK-555657
327
- const socketUrlInfo = MeetingUtil.getSocketUrlInfo(webex);
328
206
  webex.internal.newMetrics.submitClientEvent({
329
207
  name: 'client.locus.join.response',
330
208
  payload: {
@@ -332,9 +210,6 @@ const MeetingUtil = {
332
210
  identifiers: {
333
211
  trackingId: res.headers.trackingid,
334
212
  },
335
- eventData: {
336
- ...socketUrlInfo,
337
- },
338
213
  },
339
214
  options: {
340
215
  meetingId: meeting.id,
@@ -345,19 +220,12 @@ const MeetingUtil = {
345
220
  return parsed;
346
221
  })
347
222
  .catch((err) => {
348
- const socketUrlInfo = MeetingUtil.getSocketUrlInfo(webex);
349
223
  webex.internal.newMetrics.submitClientEvent({
350
224
  name: 'client.locus.join.response',
351
225
  payload: {
352
226
  identifiers: {meetingLookupUrl: meeting.meetingInfo?.meetingLookupUrl},
353
- eventData: {
354
- ...socketUrlInfo,
355
- },
356
- },
357
- options: {
358
- meetingId: meeting.id,
359
- rawError: err,
360
227
  },
228
+ options: {meetingId: meeting.id, rawError: err},
361
229
  });
362
230
 
363
231
  throw err;
@@ -369,7 +237,6 @@ const MeetingUtil = {
369
237
  meeting.stopPeriodicLogUpload();
370
238
 
371
239
  meeting.breakouts.cleanUp();
372
- meeting.webinar.cleanUp();
373
240
  meeting.simultaneousInterpretation.cleanUp();
374
241
  meeting.locusMediaRequest = undefined;
375
242
 
@@ -394,10 +261,8 @@ const MeetingUtil = {
394
261
  .then(() => meeting.stopKeepAlive())
395
262
  .then(() => {
396
263
  if (meeting.config?.enableAutomaticLLM) {
397
- return meeting.cleanupLLMConneciton({throwOnError: false});
264
+ meeting.updateLLMConnection();
398
265
  }
399
-
400
- return undefined;
401
266
  });
402
267
  },
403
268
 
@@ -663,11 +528,6 @@ const MeetingUtil = {
663
528
  displayHints.includes(DISPLAY_HINTS.LEAVE_TRANSFER_HOST_END_MEETING) ||
664
529
  displayHints.includes(DISPLAY_HINTS.LEAVE_END_MEETING),
665
530
 
666
- requireHostEndMeetingBeforeLeave: (displayHints) =>
667
- displayHints.includes(DISPLAY_HINTS.REQUIRE_HOST_END_MEETING_BEFORE_LEAVE) ||
668
- (!displayHints.includes(DISPLAY_HINTS.LEAVE_TRANSFER_HOST_END_MEETING) &&
669
- displayHints.includes(DISPLAY_HINTS.END_MEETING)),
670
-
671
531
  canManageBreakout: (displayHints) => displayHints.includes(DISPLAY_HINTS.BREAKOUT_MANAGEMENT),
672
532
 
673
533
  canStartBreakout: (displayHints) => !displayHints.includes(DISPLAY_HINTS.DISABLE_BREAKOUT_START),
@@ -912,24 +772,6 @@ const MeetingUtil = {
912
772
  return locusDeltaRequest;
913
773
  },
914
774
 
915
- canAttendeeRequestAiAssistantEnabled: (displayHints = [], roles: any[] = []) => {
916
- const isHostOrCoHost =
917
- roles.includes(ServerRoles.Cohost) || roles.includes(ServerRoles.Moderator);
918
-
919
- if (isHostOrCoHost) {
920
- return false;
921
- }
922
-
923
- if (displayHints.includes(DISPLAY_HINTS.ATTENDEE_REQUEST_AI_ASSISTANT_ENABLED)) {
924
- return true;
925
- }
926
-
927
- return false;
928
- },
929
-
930
- attendeeRequestAiAssistantDeclinedAll: (displayHints = []) =>
931
- displayHints.includes(DISPLAY_HINTS.ATTENDEE_REQUEST_AI_ASSISTANT_DECLINED_ALL),
932
-
933
775
  selfSupportsFeature: (feature: SELF_POLICY, userPolicies: Record<SELF_POLICY, boolean>) => {
934
776
  if (!userPolicies) {
935
777
  return true;
@@ -47,7 +47,7 @@ import {
47
47
  import BEHAVIORAL_METRICS from '../metrics/constants';
48
48
  import MeetingInfo from '../meeting-info';
49
49
  import MeetingInfoV2 from '../meeting-info/meeting-info-v2';
50
- import Meeting, {CallStateForMetrics, storeEventForDebugging} from '../meeting';
50
+ import Meeting, {CallStateForMetrics} from '../meeting';
51
51
  import PersonalMeetingRoom from '../personal-meeting-room';
52
52
  import Reachability from '../reachability';
53
53
  import Request from './request';
@@ -67,9 +67,6 @@ import {SpaceIDDeprecatedError} from '../common/errors/webex-errors';
67
67
  import NoMeetingInfoError from '../common/errors/no-meeting-info';
68
68
  import JoinForbiddenError from '../common/errors/join-forbidden-error';
69
69
  import {HashTreeMessage} from '../hashTree/hashTreeParser';
70
- import {HashTreeObject} from '../hashTree/types';
71
- import {isSelf} from '../hashTree/utils';
72
- import {createLocusFromHashTreeMessage, findMeetingForHashTreeMessage} from '../locus-info';
73
70
 
74
71
  let mediaLogger;
75
72
 
@@ -196,8 +193,6 @@ export default class Meetings extends WebexPlugin {
196
193
  preferredWebexSite: any;
197
194
  reachability: Reachability;
198
195
  registered: any;
199
- registrationPromise: Promise<void>;
200
- unregistrationPromise: Promise<void>;
201
196
  request: any;
202
197
  geoHintInfo: any;
203
198
  meetingInfo: any;
@@ -425,50 +420,31 @@ export default class Meetings extends WebexPlugin {
425
420
  * @memberof Meetings
426
421
  */
427
422
  getCorrespondingMeetingByLocus(data: LocusEvent) {
428
- const locusUrl =
429
- data.stateElementsMessage?.locusUrl || // hash tree event
430
- data.locusUrl; // classic event
431
-
432
- // first try to find by locusUrl - that's the simplest and quickest way
433
- const existingMeeting = this.meetingCollection.getByKey(MEETING_KEY.LOCUS_URL, locusUrl);
434
-
435
- if (existingMeeting) {
436
- return existingMeeting;
437
- }
438
-
439
- if (data.eventType === LOCUSEVENT.HASH_TREE_DATA_UPDATED) {
440
- // need to check if maybe this event indicates a move to/from breakout
441
- const meetingForHashTreeMessage = findMeetingForHashTreeMessage(
442
- data.stateElementsMessage,
443
- this.meetingCollection,
444
- // @ts-ignore
445
- this.webex.internal.device.url
423
+ if (
424
+ data.eventType === LOCUSEVENT.HASH_TREE_DATA_UPDATED &&
425
+ data.stateElementsMessage?.locusUrl
426
+ ) {
427
+ return this.meetingCollection.getByKey(
428
+ MEETING_KEY.LOCUS_URL,
429
+ data.stateElementsMessage.locusUrl
446
430
  );
447
-
448
- if (meetingForHashTreeMessage) {
449
- return meetingForHashTreeMessage;
450
- }
451
431
  }
452
432
 
453
- // if that didn't work, fallback to other fields like correlationId, sipUri, etc
454
-
455
- // If the event is a hash tree event, we need to extract "self" object from it
456
- // We don't care about the version, just need to find the meeting this event is for,
457
- // so any hash tree object of type "self" will do
458
- const hashTreeEventSelf = data.stateElementsMessage?.locusStateElements?.find(
459
- (obj: HashTreeObject) => isSelf(obj)
460
- )?.data;
461
-
462
- const self = hashTreeEventSelf || data.locus?.self;
463
-
433
+ // getting meeting by correlationId. This will happen for the new event
434
+ // Either the locus
435
+ // TODO : Add check for the callBack Address
464
436
  return (
437
+ this.meetingCollection.getByKey(MEETING_KEY.LOCUS_URL, data.locusUrl) ||
465
438
  // @ts-ignore
466
439
  this.meetingCollection.getByKey(
467
440
  MEETING_KEY.CORRELATION_ID,
468
441
  // @ts-ignore
469
- MeetingsUtil.getCorrelationIdForDevice(this.webex.internal.device.url, self)
442
+ MeetingsUtil.checkForCorrelationId(this.webex.internal.device.url, data.locus)
443
+ ) ||
444
+ this.meetingCollection.getByKey(
445
+ MEETING_KEY.SIP_URI,
446
+ data.locus?.self?.callbackInfo?.callbackAddress
470
447
  ) ||
471
- this.meetingCollection.getByKey(MEETING_KEY.SIP_URI, self?.callbackInfo?.callbackAddress) ||
472
448
  (data.locus?.info?.isUnifiedSpaceMeeting
473
449
  ? undefined
474
450
  : this.meetingCollection.getByKey(
@@ -493,11 +469,6 @@ export default class Meetings extends WebexPlugin {
493
469
  private handleLocusEvent(data: LocusEvent, useRandomDelayForInfo = false) {
494
470
  let meeting = this.getCorrespondingMeetingByLocus(data);
495
471
 
496
- // @ts-ignore
497
- if (this.config.experimental.storeLocusHashTreeEventsForDebugging) {
498
- storeEventForDebugging('mercury', data);
499
- }
500
-
501
472
  // Special case when locus has got replaced, This only happend once if a replace locus exists
502
473
  // https://sqbu-github.cisco.com/WebExSquared/locus/wiki/Locus-changing-mid-call
503
474
 
@@ -511,7 +482,7 @@ export default class Meetings extends WebexPlugin {
511
482
  }
512
483
 
513
484
  if (meeting && !MeetingsUtil.isBreakoutLocusDTO(data.locus)) {
514
- meeting.locusInfo.updateMainSessionLocusCache(data.locus); // here data.locus will never be a complete locus
485
+ meeting.locusInfo.updateMainSessionLocusCache(data.locus);
515
486
  }
516
487
  if (!this.isNeedHandleLocusDTO(meeting, data.locus)) {
517
488
  LoggerProxy.logger.log(
@@ -542,45 +513,41 @@ export default class Meetings extends WebexPlugin {
542
513
  // };
543
514
  // rather then locus object change to locus url
544
515
 
545
- if (data.eventType === LOCUSEVENT.HASH_TREE_DATA_UPDATED) {
546
- // We're about to create a new meeting object from this hash tree message.
547
- // There is some existing (pre-hash trees) SDK logic here that requires a locus object
548
- // (at the very minimum we need locus.url to be set)
549
- // so we try to create locus from the received hash tree message
550
- // it will not be complete, in most cases it will only have the self part, but that's still better than nothing
551
- const {locus} = createLocusFromHashTreeMessage(data.stateElementsMessage);
552
-
553
- data.locus = locus;
554
- }
555
-
556
- if (
557
- data.locus &&
558
- data.locus.fullState &&
559
- data.locus.fullState.state === LOCUS.STATE.INACTIVE
560
- ) {
561
- // just ignore the event as its already ended and not active
562
- LoggerProxy.logger.warn(
563
- 'Meetings:index#handleLocusEvent --> Locus event received for meeting, after it was ended.'
564
- );
516
+ if (data.eventType !== LOCUSEVENT.HASH_TREE_DATA_UPDATED) {
517
+ if (
518
+ data.locus &&
519
+ data.locus.fullState &&
520
+ data.locus.fullState.state === LOCUS.STATE.INACTIVE
521
+ ) {
522
+ // just ignore the event as its already ended and not active
523
+ LoggerProxy.logger.warn(
524
+ 'Meetings:index#handleLocusEvent --> Locus event received for meeting, after it was ended.'
525
+ );
565
526
 
566
- return;
567
- }
527
+ return;
528
+ }
568
529
 
569
- // When its wireless share or guest and user leaves the meeting we dont have to keep the meeting object
570
- // Any future events will be neglected
530
+ // When its wireless share or guest and user leaves the meeting we dont have to keep the meeting object
531
+ // Any future events will be neglected
532
+
533
+ if (
534
+ data.locus &&
535
+ data.locus.self &&
536
+ data.locus.self.state === _LEFT_ &&
537
+ data.locus.self.removed === true
538
+ ) {
539
+ // just ignore the event as its already ended and not active
540
+ LoggerProxy.logger.warn(
541
+ 'Meetings:index#handleLocusEvent --> Locus event received for meeting, after it was ended.'
542
+ );
571
543
 
572
- if (
573
- data.locus &&
574
- data.locus.self &&
575
- data.locus.self.state === _LEFT_ &&
576
- data.locus.self.removed === true
577
- ) {
578
- // just ignore the event as its already ended and not active
579
- LoggerProxy.logger.warn(
580
- 'Meetings:index#handleLocusEvent --> Locus event received for meeting, after it was ended.'
581
- );
544
+ return;
545
+ }
546
+ }
582
547
 
583
- return;
548
+ if (data.eventType === LOCUSEVENT.HASH_TREE_DATA_UPDATED) {
549
+ // in hash tree messages we don't ge the locus object, but the meeting constructor needs at least locus.url
550
+ set(data, 'locus.url', data.stateElementsMessage.locusUrl);
584
551
  }
585
552
 
586
553
  this.create(data.locus, DESTINATION_TYPE.LOCUS_ID, useRandomDelayForInfo)
@@ -650,7 +617,7 @@ export default class Meetings extends WebexPlugin {
650
617
  }
651
618
 
652
619
  /**
653
- * handles locus events through mercury that are not roap or approval request events
620
+ * handles locus events through mercury that are not roap
654
621
  * @param {Object} envelope
655
622
  * @param {Object} envelope.data
656
623
  * @param {String} envelope.data.eventType
@@ -663,11 +630,7 @@ export default class Meetings extends WebexPlugin {
663
630
  // eslint-disable-next-line @typescript-eslint/no-shadow
664
631
  const {eventType} = data;
665
632
 
666
- if (
667
- eventType &&
668
- eventType !== LOCUSEVENT.MESSAGE_ROAP &&
669
- eventType !== LOCUSEVENT.APPROVAL_REQUEST
670
- ) {
633
+ if (eventType && eventType !== LOCUSEVENT.MESSAGE_ROAP) {
671
634
  this.handleLocusEvent(data, true);
672
635
  }
673
636
  }
@@ -959,20 +922,9 @@ export default class Meetings extends WebexPlugin {
959
922
  * @returns {Promise} A promise that resolves when the step is completed.
960
923
  */
961
924
  executeRegistrationStep(step: () => Promise<any>, stepName: string) {
962
- return step()
963
- .then(() => {
964
- LoggerProxy.logger.info(
965
- `Meetings:index#executeRegistrationStep --> INFO, ${stepName} completed`
966
- );
967
- this.registrationStatus[stepName] = true;
968
- })
969
- .catch((error) => {
970
- LoggerProxy.logger.error(
971
- `Meetings:index#executeRegistrationStep --> ERROR, ${stepName} failed: ${error.message}`
972
- );
973
-
974
- return Promise.reject(error);
975
- });
925
+ return step().then(() => {
926
+ this.registrationStatus[stepName] = true;
927
+ });
976
928
  }
977
929
 
978
930
  /**
@@ -985,33 +937,7 @@ export default class Meetings extends WebexPlugin {
985
937
  * @memberof Meetings
986
938
  */
987
939
  public register(deviceRegistrationOptions?: DeviceRegistrationOptions): Promise<any> {
988
- if (this.unregistrationPromise) {
989
- LoggerProxy.logger.info(
990
- 'Meetings:index#register --> INFO, Meetings plugin unregistration in progress, waiting to register'
991
- );
992
-
993
- this.registrationPromise = this.unregistrationPromise
994
- .catch(() => {}) // It doesn't matter what happened during unregistration
995
- .finally(() => {
996
- LoggerProxy.logger.info(
997
- 'Meetings:index#register --> INFO, Meetings plugin unregistration completed, proceeding to register'
998
- );
999
-
1000
- this.registrationPromise = null;
1001
-
1002
- return this.register(deviceRegistrationOptions);
1003
- });
1004
-
1005
- return this.registrationPromise;
1006
- }
1007
-
1008
- if (this.registrationPromise) {
1009
- LoggerProxy.logger.info(
1010
- 'Meetings:index#register --> INFO, Meetings plugin registration in progress, returning existing promise'
1011
- );
1012
-
1013
- return this.registrationPromise;
1014
- }
940
+ this.registrationStatus = clone(INITIAL_REGISTRATION_STATUS);
1015
941
 
1016
942
  // @ts-ignore
1017
943
  if (!this.webex.canAuthorize) {
@@ -1030,11 +956,7 @@ export default class Meetings extends WebexPlugin {
1030
956
  return Promise.resolve();
1031
957
  }
1032
958
 
1033
- LoggerProxy.logger.info('Meetings:index#register --> INFO, Registering Meetings plugin');
1034
-
1035
- this.registrationStatus = clone(INITIAL_REGISTRATION_STATUS);
1036
-
1037
- this.registrationPromise = Promise.all([
959
+ return Promise.all([
1038
960
  this.executeRegistrationStep(() => this.fetchUserPreferredWebexSite(), 'fetchWebexSite'),
1039
961
  this.executeRegistrationStep(() => this.getGeoHint(), 'getGeoHint'),
1040
962
  this.executeRegistrationStep(
@@ -1093,12 +1015,7 @@ export default class Meetings extends WebexPlugin {
1093
1015
  });
1094
1016
 
1095
1017
  return Promise.reject(error);
1096
- })
1097
- .finally(() => {
1098
- this.registrationPromise = null;
1099
1018
  });
1100
-
1101
- return this.registrationPromise;
1102
1019
  }
1103
1020
 
1104
1021
  /**
@@ -1110,35 +1027,6 @@ export default class Meetings extends WebexPlugin {
1110
1027
  * @memberof Meetings
1111
1028
  */
1112
1029
  unregister() {
1113
- if (this.unregistrationPromise) {
1114
- LoggerProxy.logger.info(
1115
- 'Meetings:index#unregister --> INFO, Meetings plugin unregistration in progress, returning existing promise'
1116
- );
1117
-
1118
- return this.unregistrationPromise;
1119
- }
1120
-
1121
- if (this.registrationPromise) {
1122
- LoggerProxy.logger.info(
1123
- 'Meetings:index#unregister --> INFO, Meetings plugin registration in progress, waiting to unregister'
1124
- );
1125
-
1126
- // Wait for registration to complete (success or failure), then call unregister again
1127
- this.unregistrationPromise = this.registrationPromise
1128
- .catch(() => {}) // It doesn't matter what happened during registration
1129
- .finally(() => {
1130
- LoggerProxy.logger.info(
1131
- 'Meetings:index#unregister --> INFO, Meetings plugin registration completed, proceeding to unregister'
1132
- );
1133
-
1134
- this.unregistrationPromise = null;
1135
-
1136
- return this.unregister();
1137
- });
1138
-
1139
- return this.unregistrationPromise;
1140
- }
1141
-
1142
1030
  if (!this.registered) {
1143
1031
  LoggerProxy.logger.info(
1144
1032
  'Meetings:index#unregister --> INFO, Meetings plugin already unregistered'
@@ -1149,14 +1037,10 @@ export default class Meetings extends WebexPlugin {
1149
1037
 
1150
1038
  this.stopListeningForEvents();
1151
1039
 
1152
- this.unregistrationPromise =
1040
+ return (
1153
1041
  // @ts-ignore
1154
1042
  this.webex.internal.mercury
1155
- // Use code 3050 with a non-reconnecting reason to prevent Mercury auto-reconnect
1156
- // during unregister. Without this, disconnect() defaults to code 1000/"Done" which
1157
- // force-closes as "Done (forced)" - a normalReconnectReason that triggers auto-reconnect,
1158
- // causing a race condition with device.unregister().
1159
- .disconnect({code: 3050, reason: 'meetings unregister'})
1043
+ .disconnect()
1160
1044
  // @ts-ignore
1161
1045
  .then(() => this.webex.internal.device.unregister())
1162
1046
  .catch((error) => {
@@ -1186,11 +1070,7 @@ export default class Meetings extends WebexPlugin {
1186
1070
  this.registered = false;
1187
1071
  this.registrationStatus = clone(INITIAL_REGISTRATION_STATUS);
1188
1072
  })
1189
- .finally(() => {
1190
- this.unregistrationPromise = null;
1191
- });
1192
-
1193
- return this.unregistrationPromise;
1073
+ );
1194
1074
  }
1195
1075
 
1196
1076
  /**
@@ -2001,7 +1881,7 @@ export default class Meetings extends WebexPlugin {
2001
1881
 
2002
1882
  const associateBreakoutLocus = this.breakoutLocusForHandleLater[existIndex];
2003
1883
  this.handleLocusEvent({
2004
- eventType: LOCUSEVENT.SDK_LOCUS_FROM_SYNC_MEETINGS,
1884
+ eventType: LOCUSEVENT.SDK_NO_EVENT,
2005
1885
  locus: associateBreakoutLocus,
2006
1886
  locusUrl: associateBreakoutLocus.url,
2007
1887
  });