@webex/plugin-meetings 3.10.0-next.3 → 3.10.0-next.30

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 (274) hide show
  1. package/dist/annotation/annotation.types.js.map +1 -1
  2. package/dist/annotation/constants.js.map +1 -1
  3. package/dist/annotation/index.js +19 -22
  4. package/dist/annotation/index.js.map +1 -1
  5. package/dist/breakouts/breakout.js +6 -6
  6. package/dist/breakouts/breakout.js.map +1 -1
  7. package/dist/breakouts/collection.js.map +1 -1
  8. package/dist/breakouts/edit-lock-error.js +9 -11
  9. package/dist/breakouts/edit-lock-error.js.map +1 -1
  10. package/dist/breakouts/events.js.map +1 -1
  11. package/dist/breakouts/index.js +126 -127
  12. package/dist/breakouts/index.js.map +1 -1
  13. package/dist/breakouts/request.js +6 -8
  14. package/dist/breakouts/request.js.map +1 -1
  15. package/dist/breakouts/utils.js.map +1 -1
  16. package/dist/common/browser-detection.js.map +1 -1
  17. package/dist/common/collection.js +1 -2
  18. package/dist/common/collection.js.map +1 -1
  19. package/dist/common/config.js.map +1 -1
  20. package/dist/common/errors/captcha-error.js +9 -11
  21. package/dist/common/errors/captcha-error.js.map +1 -1
  22. package/dist/common/errors/intent-to-join.js +10 -12
  23. package/dist/common/errors/intent-to-join.js.map +1 -1
  24. package/dist/common/errors/join-forbidden-error.js +10 -12
  25. package/dist/common/errors/join-forbidden-error.js.map +1 -1
  26. package/dist/common/errors/join-meeting.js +10 -12
  27. package/dist/common/errors/join-meeting.js.map +1 -1
  28. package/dist/common/errors/join-webinar-error.js +9 -11
  29. package/dist/common/errors/join-webinar-error.js.map +1 -1
  30. package/dist/common/errors/media.js +9 -11
  31. package/dist/common/errors/media.js.map +1 -1
  32. package/dist/common/errors/multistream-not-supported-error.js +9 -11
  33. package/dist/common/errors/multistream-not-supported-error.js.map +1 -1
  34. package/dist/common/errors/no-meeting-info.js +9 -11
  35. package/dist/common/errors/no-meeting-info.js.map +1 -1
  36. package/dist/common/errors/parameter.js +11 -14
  37. package/dist/common/errors/parameter.js.map +1 -1
  38. package/dist/common/errors/password-error.js +9 -11
  39. package/dist/common/errors/password-error.js.map +1 -1
  40. package/dist/common/errors/permission.js +9 -11
  41. package/dist/common/errors/permission.js.map +1 -1
  42. package/dist/common/errors/reclaim-host-role-errors.js +32 -38
  43. package/dist/common/errors/reclaim-host-role-errors.js.map +1 -1
  44. package/dist/common/errors/reconnection-not-started.js +5 -6
  45. package/dist/common/errors/reconnection-not-started.js.map +1 -1
  46. package/dist/common/errors/reconnection.js +9 -11
  47. package/dist/common/errors/reconnection.js.map +1 -1
  48. package/dist/common/errors/stats.js +9 -11
  49. package/dist/common/errors/stats.js.map +1 -1
  50. package/dist/common/errors/webex-errors.js +20 -29
  51. package/dist/common/errors/webex-errors.js.map +1 -1
  52. package/dist/common/errors/webex-meetings-error.js +9 -12
  53. package/dist/common/errors/webex-meetings-error.js.map +1 -1
  54. package/dist/common/events/events-scope.js +9 -10
  55. package/dist/common/events/events-scope.js.map +1 -1
  56. package/dist/common/events/events.js +9 -10
  57. package/dist/common/events/events.js.map +1 -1
  58. package/dist/common/events/trigger-proxy.js.map +1 -1
  59. package/dist/common/events/util.js.map +1 -1
  60. package/dist/common/logs/logger-config.js.map +1 -1
  61. package/dist/common/logs/logger-proxy.js.map +1 -1
  62. package/dist/common/logs/request.js +17 -17
  63. package/dist/common/logs/request.js.map +1 -1
  64. package/dist/common/queue.js +1 -2
  65. package/dist/common/queue.js.map +1 -1
  66. package/dist/config.js +2 -2
  67. package/dist/config.js.map +1 -1
  68. package/dist/constants.js +11 -8
  69. package/dist/constants.js.map +1 -1
  70. package/dist/controls-options-manager/constants.js.map +1 -1
  71. package/dist/controls-options-manager/enums.js.map +1 -1
  72. package/dist/controls-options-manager/index.js +1 -2
  73. package/dist/controls-options-manager/index.js.map +1 -1
  74. package/dist/controls-options-manager/types.js.map +1 -1
  75. package/dist/controls-options-manager/util.js +1 -2
  76. package/dist/controls-options-manager/util.js.map +1 -1
  77. package/dist/hashTree/constants.js +20 -0
  78. package/dist/hashTree/constants.js.map +1 -0
  79. package/dist/hashTree/hashTree.js +515 -0
  80. package/dist/hashTree/hashTree.js.map +1 -0
  81. package/dist/hashTree/hashTreeParser.js +1250 -0
  82. package/dist/hashTree/hashTreeParser.js.map +1 -0
  83. package/dist/hashTree/types.js +23 -0
  84. package/dist/hashTree/types.js.map +1 -0
  85. package/dist/hashTree/utils.js +59 -0
  86. package/dist/hashTree/utils.js.map +1 -0
  87. package/dist/index.js +1 -2
  88. package/dist/index.js.map +1 -1
  89. package/dist/interceptors/index.js.map +1 -1
  90. package/dist/interceptors/locusRetry.js +6 -8
  91. package/dist/interceptors/locusRetry.js.map +1 -1
  92. package/dist/interceptors/locusRouteToken.js +26 -12
  93. package/dist/interceptors/locusRouteToken.js.map +1 -1
  94. package/dist/interpretation/collection.js.map +1 -1
  95. package/dist/interpretation/index.js +1 -2
  96. package/dist/interpretation/index.js.map +1 -1
  97. package/dist/interpretation/siLanguage.js +1 -1
  98. package/dist/interpretation/siLanguage.js.map +1 -1
  99. package/dist/locus-info/controlsUtils.js.map +1 -1
  100. package/dist/locus-info/embeddedAppsUtils.js.map +1 -1
  101. package/dist/locus-info/fullState.js.map +1 -1
  102. package/dist/locus-info/hostUtils.js.map +1 -1
  103. package/dist/locus-info/index.js +609 -177
  104. package/dist/locus-info/index.js.map +1 -1
  105. package/dist/locus-info/infoUtils.js.map +1 -1
  106. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  107. package/dist/locus-info/parser.js +3 -4
  108. package/dist/locus-info/parser.js.map +1 -1
  109. package/dist/locus-info/selfUtils.js.map +1 -1
  110. package/dist/locus-info/types.js +7 -0
  111. package/dist/locus-info/types.js.map +1 -0
  112. package/dist/media/MediaConnectionAwaiter.js +1 -2
  113. package/dist/media/MediaConnectionAwaiter.js.map +1 -1
  114. package/dist/media/index.js +0 -2
  115. package/dist/media/index.js.map +1 -1
  116. package/dist/media/properties.js +15 -17
  117. package/dist/media/properties.js.map +1 -1
  118. package/dist/media/util.js.map +1 -1
  119. package/dist/meeting/brbState.js +8 -9
  120. package/dist/meeting/brbState.js.map +1 -1
  121. package/dist/meeting/connectionStateHandler.js +10 -13
  122. package/dist/meeting/connectionStateHandler.js.map +1 -1
  123. package/dist/meeting/in-meeting-actions.js.map +1 -1
  124. package/dist/meeting/index.js +1576 -1533
  125. package/dist/meeting/index.js.map +1 -1
  126. package/dist/meeting/locusMediaRequest.js +13 -17
  127. package/dist/meeting/locusMediaRequest.js.map +1 -1
  128. package/dist/meeting/muteState.js +11 -12
  129. package/dist/meeting/muteState.js.map +1 -1
  130. package/dist/meeting/request.js +101 -104
  131. package/dist/meeting/request.js.map +1 -1
  132. package/dist/meeting/request.type.js.map +1 -1
  133. package/dist/meeting/state.js.map +1 -1
  134. package/dist/meeting/type.js.map +1 -1
  135. package/dist/meeting/util.js +24 -23
  136. package/dist/meeting/util.js.map +1 -1
  137. package/dist/meeting/voicea-meeting.js +3 -3
  138. package/dist/meeting/voicea-meeting.js.map +1 -1
  139. package/dist/meeting-info/collection.js +7 -10
  140. package/dist/meeting-info/collection.js.map +1 -1
  141. package/dist/meeting-info/index.js +1 -2
  142. package/dist/meeting-info/index.js.map +1 -1
  143. package/dist/meeting-info/meeting-info-v2.js +135 -146
  144. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  145. package/dist/meeting-info/request.js +1 -2
  146. package/dist/meeting-info/request.js.map +1 -1
  147. package/dist/meeting-info/util.js +36 -37
  148. package/dist/meeting-info/util.js.map +1 -1
  149. package/dist/meeting-info/utilv2.js +30 -31
  150. package/dist/meeting-info/utilv2.js.map +1 -1
  151. package/dist/meetings/collection.js +6 -8
  152. package/dist/meetings/collection.js.map +1 -1
  153. package/dist/meetings/index.js +200 -148
  154. package/dist/meetings/index.js.map +1 -1
  155. package/dist/meetings/meetings.types.js.map +1 -1
  156. package/dist/meetings/request.js +6 -8
  157. package/dist/meetings/request.js.map +1 -1
  158. package/dist/meetings/util.js +36 -30
  159. package/dist/meetings/util.js.map +1 -1
  160. package/dist/member/index.js +1 -2
  161. package/dist/member/index.js.map +1 -1
  162. package/dist/member/types.js +6 -3
  163. package/dist/member/types.js.map +1 -1
  164. package/dist/member/util.js.map +1 -1
  165. package/dist/members/collection.js +1 -2
  166. package/dist/members/collection.js.map +1 -1
  167. package/dist/members/index.js +18 -21
  168. package/dist/members/index.js.map +1 -1
  169. package/dist/members/request.js +8 -11
  170. package/dist/members/request.js.map +1 -1
  171. package/dist/members/types.js.map +1 -1
  172. package/dist/members/util.js.map +1 -1
  173. package/dist/metrics/constants.js +3 -1
  174. package/dist/metrics/constants.js.map +1 -1
  175. package/dist/metrics/index.js +3 -4
  176. package/dist/metrics/index.js.map +1 -1
  177. package/dist/multistream/mediaRequestManager.js +1 -2
  178. package/dist/multistream/mediaRequestManager.js.map +1 -1
  179. package/dist/multistream/receiveSlot.js +34 -45
  180. package/dist/multistream/receiveSlot.js.map +1 -1
  181. package/dist/multistream/receiveSlotManager.js +8 -9
  182. package/dist/multistream/receiveSlotManager.js.map +1 -1
  183. package/dist/multistream/remoteMedia.js +12 -15
  184. package/dist/multistream/remoteMedia.js.map +1 -1
  185. package/dist/multistream/remoteMediaGroup.js +1 -2
  186. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  187. package/dist/multistream/remoteMediaManager.js +122 -123
  188. package/dist/multistream/remoteMediaManager.js.map +1 -1
  189. package/dist/multistream/sendSlotManager.js +29 -30
  190. package/dist/multistream/sendSlotManager.js.map +1 -1
  191. package/dist/personal-meeting-room/index.js +16 -19
  192. package/dist/personal-meeting-room/index.js.map +1 -1
  193. package/dist/personal-meeting-room/request.js +7 -10
  194. package/dist/personal-meeting-room/request.js.map +1 -1
  195. package/dist/personal-meeting-room/util.js.map +1 -1
  196. package/dist/reachability/clusterReachability.js +188 -352
  197. package/dist/reachability/clusterReachability.js.map +1 -1
  198. package/dist/reachability/index.js +206 -206
  199. package/dist/reachability/index.js.map +1 -1
  200. package/dist/reachability/reachability.types.js +14 -1
  201. package/dist/reachability/reachability.types.js.map +1 -1
  202. package/dist/reachability/reachabilityPeerConnection.js +445 -0
  203. package/dist/reachability/reachabilityPeerConnection.js.map +1 -0
  204. package/dist/reachability/request.js.map +1 -1
  205. package/dist/reachability/util.js.map +1 -1
  206. package/dist/reactions/constants.js.map +1 -1
  207. package/dist/reactions/reactions.js.map +1 -1
  208. package/dist/reactions/reactions.type.js.map +1 -1
  209. package/dist/reconnection-manager/index.js +178 -176
  210. package/dist/reconnection-manager/index.js.map +1 -1
  211. package/dist/recording-controller/enums.js.map +1 -1
  212. package/dist/recording-controller/index.js +1 -2
  213. package/dist/recording-controller/index.js.map +1 -1
  214. package/dist/recording-controller/util.js.map +1 -1
  215. package/dist/roap/index.js +12 -15
  216. package/dist/roap/index.js.map +1 -1
  217. package/dist/roap/request.js +24 -26
  218. package/dist/roap/request.js.map +1 -1
  219. package/dist/roap/turnDiscovery.js +75 -76
  220. package/dist/roap/turnDiscovery.js.map +1 -1
  221. package/dist/roap/types.js.map +1 -1
  222. package/dist/transcription/index.js +4 -5
  223. package/dist/transcription/index.js.map +1 -1
  224. package/dist/types/config.d.ts +1 -0
  225. package/dist/types/constants.d.ts +26 -21
  226. package/dist/types/hashTree/constants.d.ts +8 -0
  227. package/dist/types/hashTree/hashTree.d.ts +129 -0
  228. package/dist/types/hashTree/hashTreeParser.d.ts +250 -0
  229. package/dist/types/hashTree/types.d.ts +33 -0
  230. package/dist/types/hashTree/utils.d.ts +16 -0
  231. package/dist/types/interceptors/locusRouteToken.d.ts +1 -0
  232. package/dist/types/locus-info/index.d.ts +98 -80
  233. package/dist/types/locus-info/types.d.ts +54 -0
  234. package/dist/types/meeting/index.d.ts +22 -9
  235. package/dist/types/meetings/index.d.ts +9 -2
  236. package/dist/types/metrics/constants.d.ts +2 -0
  237. package/dist/types/reachability/clusterReachability.d.ts +33 -84
  238. package/dist/types/reachability/reachability.types.d.ts +12 -1
  239. package/dist/types/reachability/reachabilityPeerConnection.d.ts +111 -0
  240. package/dist/webinar/collection.js +1 -2
  241. package/dist/webinar/collection.js.map +1 -1
  242. package/dist/webinar/index.js +148 -158
  243. package/dist/webinar/index.js.map +1 -1
  244. package/package.json +23 -22
  245. package/src/config.ts +1 -0
  246. package/src/constants.ts +13 -1
  247. package/src/hashTree/constants.ts +9 -0
  248. package/src/hashTree/hashTree.ts +463 -0
  249. package/src/hashTree/hashTreeParser.ts +1143 -0
  250. package/src/hashTree/types.ts +39 -0
  251. package/src/hashTree/utils.ts +53 -0
  252. package/src/interceptors/locusRouteToken.ts +16 -4
  253. package/src/locus-info/index.ts +625 -164
  254. package/src/locus-info/types.ts +53 -0
  255. package/src/meeting/index.ts +78 -27
  256. package/src/meeting/util.ts +1 -0
  257. package/src/meetings/index.ts +119 -59
  258. package/src/meetings/util.ts +10 -9
  259. package/src/metrics/constants.ts +2 -0
  260. package/src/reachability/clusterReachability.ts +159 -330
  261. package/src/reachability/index.ts +6 -1
  262. package/src/reachability/reachability.types.ts +15 -1
  263. package/src/reachability/reachabilityPeerConnection.ts +418 -0
  264. package/test/unit/spec/hashTree/hashTree.ts +655 -0
  265. package/test/unit/spec/hashTree/hashTreeParser.ts +1524 -0
  266. package/test/unit/spec/hashTree/utils.ts +140 -0
  267. package/test/unit/spec/interceptors/locusRouteToken.ts +27 -0
  268. package/test/unit/spec/locus-info/index.js +851 -16
  269. package/test/unit/spec/meeting/index.js +120 -20
  270. package/test/unit/spec/meeting/utils.js +77 -0
  271. package/test/unit/spec/meetings/index.js +263 -27
  272. package/test/unit/spec/meetings/utils.js +51 -1
  273. package/test/unit/spec/reachability/clusterReachability.ts +404 -137
  274. package/test/unit/spec/reachability/index.ts +3 -3
@@ -0,0 +1,53 @@
1
+ import {HtMeta} from '../hashTree/types';
2
+
3
+ export type LocusFullState = {
4
+ active: boolean;
5
+ count: number;
6
+ lastActive: string;
7
+ locked: boolean;
8
+ sessionId: string;
9
+ seessionIds: string[];
10
+ startTime: number;
11
+ state: string;
12
+ type: string;
13
+ };
14
+
15
+ export type Links = {
16
+ services: Record<'breakout' | 'record', {url: string}>; // there exist also other services, but these are the ones we currently use
17
+ resources: Record<'webcastInstance' | 'visibleDataSets', {url: string}>; // there exist also other resources, but these are the ones we currently use
18
+ };
19
+
20
+ export type LocusDTO = {
21
+ controls?: any;
22
+ fullState?: LocusFullState;
23
+ host?: {
24
+ id: string;
25
+ incomingCallProtocols: any[];
26
+ isExternal: boolean;
27
+ name: string;
28
+ orgId: string;
29
+ };
30
+ htMeta?: HtMeta;
31
+ info?: any;
32
+ jsSdkMeta?: {
33
+ removedParticipantIds: string[]; // list of ids of participants that are removed in the last update
34
+ };
35
+ links?: Links;
36
+ mediaShares?: any[];
37
+ meetings?: any[];
38
+ participants: any[];
39
+ replaces?: any[];
40
+ self?: any;
41
+ sequence?: {
42
+ dirtyParticipants: number;
43
+ entries: number[];
44
+ rangeEnd: number;
45
+ rangeStart: number;
46
+ sequenceHash: number;
47
+ sessionToken: string;
48
+ since: string;
49
+ totalParticipants: number;
50
+ };
51
+ syncUrl?: string;
52
+ url?: string;
53
+ };
@@ -1,5 +1,5 @@
1
1
  import uuid from 'uuid';
2
- import {cloneDeep, isEqual, isEmpty} from 'lodash';
2
+ import {cloneDeep, isEqual, isEmpty, merge} from 'lodash';
3
3
  import jwtDecode from 'jwt-decode';
4
4
  // @ts-ignore - Fix this
5
5
  import {StatelessWebexPlugin} from '@webex/webex-core';
@@ -50,6 +50,11 @@ import {
50
50
  type MeetingTranscriptPayload,
51
51
  } from '@webex/internal-plugin-voicea';
52
52
 
53
+ import {
54
+ getBrowserMediaErrorCode,
55
+ isBrowserMediaError,
56
+ isBrowserMediaErrorName,
57
+ } from '@webex/internal-plugin-metrics/src/call-diagnostic/call-diagnostic-metrics.util';
53
58
  import {processNewCaptions} from './voicea-meeting';
54
59
 
55
60
  import {
@@ -70,7 +75,7 @@ import Media, {type BundlePolicy} from '../media';
70
75
  import MediaProperties from '../media/properties';
71
76
  import MeetingStateMachine from './state';
72
77
  import {createMuteState} from './muteState';
73
- import LocusInfo from '../locus-info';
78
+ import LocusInfo, {LocusLLMEvent} from '../locus-info';
74
79
  import Metrics from '../metrics';
75
80
  import ReconnectionManager from '../reconnection-manager';
76
81
  import ReconnectionNotStartedError from '../common/errors/reconnection-not-started';
@@ -126,6 +131,8 @@ import {
126
131
  JOIN_BEFORE_HOST,
127
132
  REGISTRATION_ID_STATUS,
128
133
  STAGE_MANAGER_TYPE,
134
+ LOCUSEVENT,
135
+ LOCUS_LLM_EVENT,
129
136
  } from '../constants';
130
137
  import BEHAVIORAL_METRICS from '../metrics/constants';
131
138
  import ParameterError from '../common/errors/parameter';
@@ -171,6 +178,8 @@ import JoinForbiddenError from '../common/errors/join-forbidden-error';
171
178
  import {ReachabilityMetrics} from '../reachability/reachability.types';
172
179
  import {SetStageOptions, SetStageVideoLayout, UnsetStageVideoLayout} from './request.type';
173
180
  import {Invitee} from './type';
181
+ import {DataSet} from '../hashTree/hashTreeParser';
182
+ import {LocusDTO} from '../locus-info/types';
174
183
 
175
184
  // default callback so we don't call an undefined function, but in practice it should never be used
176
185
  const DEFAULT_ICE_PHASE_CALLBACK = () => 'JOIN_MEETING_FINAL';
@@ -4551,40 +4560,45 @@ export default class Meeting extends StatelessWebexPlugin {
4551
4560
  }
4552
4561
 
4553
4562
  /**
4554
- * Set the locus info the class instance
4555
- * @param {Object} locus
4556
- * @param {Array} locus.mediaConnections
4557
- * @param {String} locus.locusUrl
4558
- * @param {String} locus.locusId
4559
- * @param {String} locus.mediaId
4560
- * @param {Object} locus.host
4563
+ * Set the locus info the class instance. Should be called with the parsed locus
4564
+ * we got in the join response.
4565
+ *
4566
+ * @param {Object} data
4567
+ * @param {Array} data.mediaConnections
4568
+ * @param {String} data.locusUrl
4569
+ * @param {String} data.locusId
4570
+ * @param {String} data.mediaId
4571
+ * @param {Object} data.host
4561
4572
  * @todo change name to genertic parser
4562
4573
  * @returns {undefined}
4563
4574
  * @private
4564
4575
  * @memberof Meeting
4565
4576
  */
4566
- setLocus(
4567
- locus:
4568
- | {
4569
- mediaConnections: Array<any>;
4570
- locusUrl: string;
4571
- locusId: string;
4572
- mediaId: string;
4573
- host: object;
4574
- }
4575
- | any
4576
- ) {
4577
- const mtgLocus: any = locus.locus || locus;
4577
+ setLocus(data: {
4578
+ locus: LocusDTO;
4579
+ mediaConnections: Array<any>;
4580
+ locusUrl: string;
4581
+ locusId: string;
4582
+ mediaId: string;
4583
+ host: object;
4584
+ selfId: string;
4585
+ dataSets: DataSet[];
4586
+ }) {
4587
+ const mtgLocus: any = data.locus;
4578
4588
 
4579
4589
  // LocusInfo object saves the locus object
4580
4590
  // this.locus = mtgLocus;
4581
- this.mediaConnections = locus.mediaConnections;
4582
- this.locusUrl = locus.locusUrl || locus.url;
4583
- this.locusId = locus.locusId;
4584
- this.selfId = locus.selfId;
4585
- this.mediaId = locus.mediaId;
4591
+ this.mediaConnections = data.mediaConnections;
4592
+ this.locusUrl = data.locusUrl;
4593
+ this.locusId = data.locusId;
4594
+ this.selfId = data.selfId;
4595
+ this.mediaId = data.mediaId;
4586
4596
  this.hostId = mtgLocus.host ? mtgLocus.host.id : this.hostId;
4587
- this.locusInfo.initialSetup(mtgLocus);
4597
+ this.locusInfo.initialSetup({
4598
+ trigger: 'join-response',
4599
+ locus: mtgLocus,
4600
+ dataSets: data.dataSets,
4601
+ });
4588
4602
  }
4589
4603
 
4590
4604
  /**
@@ -5431,6 +5445,20 @@ export default class Meeting extends StatelessWebexPlugin {
5431
5445
  shouldRetry = false;
5432
5446
  }
5433
5447
 
5448
+ if (CallDiagnosticUtils.isBrowserMediaError(error)) {
5449
+ shouldRetry = false;
5450
+ // eslint-disable-next-line no-ex-assign
5451
+ error = merge({
5452
+ error: {
5453
+ body: {
5454
+ errorCode: CallDiagnosticUtils.getBrowserMediaErrorCode(error),
5455
+ message: error?.message,
5456
+ name: error?.name,
5457
+ },
5458
+ },
5459
+ });
5460
+ }
5461
+
5434
5462
  // we only want to call leave if join was successful and this was a retry or we won't be doing any more retries
5435
5463
  if (joined && (isRetry || !shouldRetry)) {
5436
5464
  try {
@@ -5697,6 +5725,21 @@ export default class Meeting extends StatelessWebexPlugin {
5697
5725
  }
5698
5726
  }
5699
5727
 
5728
+ /** Handles Locus LLM events
5729
+ *
5730
+ * @param {LocusLLMEvent} event - The Locus LLM event to process
5731
+ * @returns {void}
5732
+ */
5733
+ private processLocusLLMEvent = (event: LocusLLMEvent): void => {
5734
+ if (event.data.eventType === LOCUSEVENT.HASH_TREE_DATA_UPDATED) {
5735
+ this.locusInfo.parse(this, event.data);
5736
+ } else {
5737
+ LoggerProxy.logger.warn(
5738
+ `Meeting:index#processLocusLLMEvent --> Unknown event type: ${event.data.eventType}`
5739
+ );
5740
+ }
5741
+ };
5742
+
5700
5743
  /**
5701
5744
  * Callback called when a relay event is received from meeting LLM Connection
5702
5745
  * @param {RelayEvent} e Event object coming from LLM Connection
@@ -6108,6 +6151,8 @@ export default class Meeting extends StatelessWebexPlugin {
6108
6151
  );
6109
6152
  // @ts-ignore - Fix type
6110
6153
  this.webex.internal.llm.off('event:relay.event', this.processRelayEvent);
6154
+ // @ts-ignore - Fix type
6155
+ this.webex.internal.llm.off(LOCUS_LLM_EVENT, this.processLocusLLMEvent);
6111
6156
  }
6112
6157
 
6113
6158
  if (!isJoined) {
@@ -6122,6 +6167,10 @@ export default class Meeting extends StatelessWebexPlugin {
6122
6167
  this.webex.internal.llm.off('event:relay.event', this.processRelayEvent);
6123
6168
  // @ts-ignore - Fix type
6124
6169
  this.webex.internal.llm.on('event:relay.event', this.processRelayEvent);
6170
+ // @ts-ignore - Fix type
6171
+ this.webex.internal.llm.off(LOCUS_LLM_EVENT, this.processLocusLLMEvent);
6172
+ // @ts-ignore - Fix type
6173
+ this.webex.internal.llm.on(LOCUS_LLM_EVENT, this.processLocusLLMEvent);
6125
6174
  LoggerProxy.logger.info(
6126
6175
  'Meeting:index#updateLLMConnection --> enabled to receive relay events!'
6127
6176
  );
@@ -9373,6 +9422,8 @@ export default class Meeting extends StatelessWebexPlugin {
9373
9422
 
9374
9423
  // @ts-ignore - fix types
9375
9424
  this.webex.internal.llm.off('event:relay.event', this.processRelayEvent);
9425
+ // @ts-ignore - Fix type
9426
+ this.webex.internal.llm.off(LOCUS_LLM_EVENT, this.processLocusLLMEvent);
9376
9427
  };
9377
9428
 
9378
9429
  /**
@@ -31,6 +31,7 @@ const MeetingUtil = {
31
31
 
32
32
  // First todo: add check for existance
33
33
  parsed.locus = response.body.locus;
34
+ parsed.dataSets = response.body.dataSets;
34
35
  parsed.mediaConnections = response.body.mediaConnections;
35
36
  parsed.locusUrl = parsed.locus.url;
36
37
  parsed.locusId = parsed.locus.url.split('/').pop();
@@ -1,5 +1,5 @@
1
1
  /* eslint no-shadow: ["error", { "allow": ["eventType"] }] */
2
- import {cloneDeep, clone} from 'lodash';
2
+ import {cloneDeep, clone, set} from 'lodash';
3
3
  import '@webex/internal-plugin-mercury';
4
4
  import '@webex/internal-plugin-conversation';
5
5
  import '@webex/internal-plugin-metrics';
@@ -66,6 +66,9 @@ import JoinWebinarError from '../common/errors/join-webinar-error';
66
66
  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
+ import {HashTreeMessage} from '../hashTree/hashTreeParser';
70
+ import {HashTreeObject} from '../hashTree/types';
71
+ import {isSelf} from '../hashTree/utils';
69
72
 
70
73
  let mediaLogger;
71
74
 
@@ -94,6 +97,18 @@ class MediaLogger {
94
97
  LoggerProxy.logger.debug(...args);
95
98
  }
96
99
  }
100
+
101
+ export type LocusEvent = {
102
+ eventType: LOCUSEVENT;
103
+
104
+ // fields populated for "classic" locus events (eventType = 'locus.difference' and others, see LOCUSEVENT)
105
+ locusUrl?: string;
106
+ locus?: any;
107
+
108
+ // fields populated for "hash tree" locus events (eventType = 'locus.state_message' - see LOCUSEVENT.HASH_TREE_DATA_UPDATED)
109
+ stateElementsMessage?: HashTreeMessage;
110
+ };
111
+
97
112
  /**
98
113
  * Meetings Ready Event
99
114
  * Emitted when the meetings instance on webex is ready
@@ -406,29 +421,42 @@ export default class Meetings extends WebexPlugin {
406
421
  * @private
407
422
  * @memberof Meetings
408
423
  */
409
- getCorrespondingMeetingByLocus(data) {
410
- // getting meeting by correlationId. This will happen for the new event
411
- // Either the locus
412
- // TODO : Add check for the callBack Address
424
+ getCorrespondingMeetingByLocus(data: LocusEvent) {
425
+ const locusUrl =
426
+ data.stateElementsMessage?.locusUrl || // hash tree event
427
+ data.locusUrl; // classic event
428
+
429
+ // first try to find by locusUrl - that's the simplest and quickest way
430
+ const existingMeeting = this.meetingCollection.getByKey(MEETING_KEY.LOCUS_URL, locusUrl);
431
+
432
+ if (existingMeeting) {
433
+ return existingMeeting;
434
+ }
435
+
436
+ // if that didn't work, fallback to other fields like correlationId, sipUri, etc
437
+
438
+ // If the event is a hash tree event, we need to extract "self" object from it
439
+ // We don't care about the version, just need to find the meeting this event is for,
440
+ // so any hash tree object of type "self" will do
441
+ const hashTreeEventSelf = data.stateElementsMessage?.locusStateElements?.find(
442
+ (obj: HashTreeObject) => isSelf(obj)
443
+ )?.data;
444
+
445
+ const self = hashTreeEventSelf || data.locus?.self;
446
+
413
447
  return (
414
- this.meetingCollection.getByKey(MEETING_KEY.LOCUS_URL, data.locusUrl) ||
415
448
  // @ts-ignore
416
449
  this.meetingCollection.getByKey(
417
450
  MEETING_KEY.CORRELATION_ID,
418
451
  // @ts-ignore
419
- MeetingsUtil.checkForCorrelationId(this.webex.internal.device.url, data.locus)
452
+ MeetingsUtil.getCorrelationIdForDevice(this.webex.internal.device.url, self)
420
453
  ) ||
421
- this.meetingCollection.getByKey(
422
- MEETING_KEY.SIP_URI,
423
- data.locus.self &&
424
- data.locus.self.callbackInfo &&
425
- data.locus.self.callbackInfo.callbackAddress
426
- ) ||
427
- (data.locus.info?.isUnifiedSpaceMeeting
454
+ this.meetingCollection.getByKey(MEETING_KEY.SIP_URI, self?.callbackInfo?.callbackAddress) ||
455
+ (data.locus?.info?.isUnifiedSpaceMeeting
428
456
  ? undefined
429
457
  : this.meetingCollection.getByKey(
430
458
  MEETING_KEY.CONVERSATION_URL,
431
- data.locus.conversationUrl
459
+ data.locus?.conversationUrl
432
460
  )) ||
433
461
  this.meetingCollection.getByKey(MEETING_KEY.MEETINGNUMBER, data.locus?.info?.webExMeetingId)
434
462
  );
@@ -445,30 +473,33 @@ export default class Meetings extends WebexPlugin {
445
473
  * @private
446
474
  * @memberof Meetings
447
475
  */
448
- private handleLocusEvent(data: {locusUrl: string; locus: any}, useRandomDelayForInfo = false) {
476
+ private handleLocusEvent(data: LocusEvent, useRandomDelayForInfo = false) {
449
477
  let meeting = this.getCorrespondingMeetingByLocus(data);
450
478
 
451
479
  // Special case when locus has got replaced, This only happend once if a replace locus exists
452
480
  // https://sqbu-github.cisco.com/WebExSquared/locus/wiki/Locus-changing-mid-call
453
481
 
454
- if (!meeting && data.locus?.replaces?.length > 0) {
455
- // Always the last element in the replace is the active one
456
- meeting = this.meetingCollection.getByKey(
457
- MEETING_KEY.LOCUS_URL,
458
- data.locus.replaces[data.locus.replaces.length - 1].locusUrl
459
- );
460
- }
482
+ if (data.eventType !== LOCUSEVENT.HASH_TREE_DATA_UPDATED) {
483
+ if (!meeting && data.locus?.replaces?.length > 0) {
484
+ // Always the last element in the replace is the active one
485
+ meeting = this.meetingCollection.getByKey(
486
+ MEETING_KEY.LOCUS_URL,
487
+ data.locus.replaces[data.locus.replaces.length - 1].locusUrl
488
+ );
489
+ }
461
490
 
462
- if (meeting && !MeetingsUtil.isBreakoutLocusDTO(data.locus)) {
463
- meeting.locusInfo.updateMainSessionLocusCache(data.locus);
464
- }
465
- if (!this.isNeedHandleLocusDTO(meeting, data.locus)) {
466
- LoggerProxy.logger.log(
467
- `Meetings:index#handleLocusEvent --> doesn't need to process locus event`
468
- );
491
+ if (meeting && !MeetingsUtil.isBreakoutLocusDTO(data.locus)) {
492
+ meeting.locusInfo.updateMainSessionLocusCache(data.locus);
493
+ }
494
+ if (!this.isNeedHandleLocusDTO(meeting, data.locus)) {
495
+ LoggerProxy.logger.log(
496
+ `Meetings:index#handleLocusEvent --> doesn't need to process locus event`
497
+ );
469
498
 
470
- return;
499
+ return;
500
+ }
471
501
  }
502
+
472
503
  if (!meeting) {
473
504
  // TODO: create meeting when we get a meeting object
474
505
  // const checkForEnded = (locus) => {
@@ -489,42 +520,65 @@ export default class Meetings extends WebexPlugin {
489
520
  // };
490
521
  // rather then locus object change to locus url
491
522
 
492
- if (
493
- data.locus &&
494
- data.locus.fullState &&
495
- data.locus.fullState.state === LOCUS.STATE.INACTIVE
496
- ) {
497
- // just ignore the event as its already ended and not active
498
- LoggerProxy.logger.warn(
499
- 'Meetings:index#handleLocusEvent --> Locus event received for meeting, after it was ended.'
500
- );
523
+ if (data.eventType !== LOCUSEVENT.HASH_TREE_DATA_UPDATED) {
524
+ if (
525
+ data.locus &&
526
+ data.locus.fullState &&
527
+ data.locus.fullState.state === LOCUS.STATE.INACTIVE
528
+ ) {
529
+ // just ignore the event as its already ended and not active
530
+ LoggerProxy.logger.warn(
531
+ 'Meetings:index#handleLocusEvent --> Locus event received for meeting, after it was ended.'
532
+ );
501
533
 
502
- return;
503
- }
534
+ return;
535
+ }
504
536
 
505
- // When its wireless share or guest and user leaves the meeting we dont have to keep the meeting object
506
- // Any future events will be neglected
537
+ // When its wireless share or guest and user leaves the meeting we dont have to keep the meeting object
538
+ // Any future events will be neglected
539
+
540
+ if (
541
+ data.locus &&
542
+ data.locus.self &&
543
+ data.locus.self.state === _LEFT_ &&
544
+ data.locus.self.removed === true
545
+ ) {
546
+ // just ignore the event as its already ended and not active
547
+ LoggerProxy.logger.warn(
548
+ 'Meetings:index#handleLocusEvent --> Locus event received for meeting, after it was ended.'
549
+ );
507
550
 
508
- if (
509
- data.locus &&
510
- data.locus.self &&
511
- data.locus.self.state === _LEFT_ &&
512
- data.locus.self.removed === true
513
- ) {
514
- // just ignore the event as its already ended and not active
515
- LoggerProxy.logger.warn(
516
- 'Meetings:index#handleLocusEvent --> Locus event received for meeting, after it was ended.'
517
- );
551
+ return;
552
+ }
553
+ }
518
554
 
519
- return;
555
+ if (data.eventType === LOCUSEVENT.HASH_TREE_DATA_UPDATED) {
556
+ // in hash tree messages we don't ge the locus object, but the meeting constructor needs at least locus.url
557
+ set(data, 'locus.url', data.stateElementsMessage.locusUrl);
520
558
  }
521
559
 
522
560
  this.create(data.locus, DESTINATION_TYPE.LOCUS_ID, useRandomDelayForInfo)
523
- .then((newMeeting) => {
561
+ .then(async (newMeeting) => {
524
562
  meeting = newMeeting;
525
563
 
526
- // It's a new meeting so initialize the locus data
527
- meeting.locusInfo.initialSetup(data.locus);
564
+ try {
565
+ // It's a new meeting so initialize the locus data
566
+ await meeting.locusInfo.initialSetup({
567
+ trigger:
568
+ data.eventType === LOCUSEVENT.SDK_LOCUS_FROM_SYNC_MEETINGS
569
+ ? 'get-loci-response'
570
+ : 'locus-message',
571
+ locus: data.locus,
572
+ hashTreeMessage: data.stateElementsMessage,
573
+ });
574
+ } catch (error) {
575
+ LoggerProxy.logger.warn(
576
+ `Meetings:index#handleLocusEvent --> Error initializing locus data: ${error.message}`
577
+ );
578
+ // @ts-ignore
579
+ this.destroy(meeting, MEETING_REMOVED_REASON.LOCUS_DTO_SYNC_FAILED);
580
+ }
581
+
528
582
  this.checkHandleBreakoutLocus(data.locus);
529
583
  })
530
584
  .catch((e) => {
@@ -1739,6 +1793,7 @@ export default class Meetings extends WebexPlugin {
1739
1793
  lociToUpdate.forEach((locus) => {
1740
1794
  activeLocusUrl.push(locus.url);
1741
1795
  this.handleLocusEvent({
1796
+ eventType: LOCUSEVENT.SDK_LOCUS_FROM_SYNC_MEETINGS,
1742
1797
  locus,
1743
1798
  locusUrl: locus.url,
1744
1799
  });
@@ -1786,6 +1841,7 @@ export default class Meetings extends WebexPlugin {
1786
1841
  (mainLocus) => mainLocus.controls?.breakout?.url === breakoutLocus.controls?.breakout?.url
1787
1842
  );
1788
1843
  const existCorrespondingMeeting = this.getCorrespondingMeetingByLocus({
1844
+ eventType: LOCUSEVENT.SDK_NO_EVENT,
1789
1845
  locus: breakoutLocus,
1790
1846
  locusUrl: breakoutLocus.url,
1791
1847
  });
@@ -1831,7 +1887,11 @@ export default class Meetings extends WebexPlugin {
1831
1887
  }
1832
1888
 
1833
1889
  const associateBreakoutLocus = this.breakoutLocusForHandleLater[existIndex];
1834
- this.handleLocusEvent({locus: associateBreakoutLocus, locusUrl: associateBreakoutLocus.url});
1890
+ this.handleLocusEvent({
1891
+ eventType: LOCUSEVENT.SDK_NO_EVENT,
1892
+ locus: associateBreakoutLocus,
1893
+ locusUrl: associateBreakoutLocus.url,
1894
+ });
1835
1895
  this.breakoutLocusForHandleLater.splice(existIndex, 1);
1836
1896
  }
1837
1897
 
@@ -117,15 +117,16 @@ MeetingsUtil.getMediaServerIp = (sdp) => {
117
117
  return mediaServerIp;
118
118
  };
119
119
 
120
- MeetingsUtil.checkForCorrelationId = (deviceUrl, locus) => {
121
- let devices = [];
122
-
123
- if (locus) {
124
- if (locus && locus.self && locus.self.devices) {
125
- devices = locus.self.devices;
126
- }
127
-
128
- const foundDevice = devices.find((device) => device.url === deviceUrl);
120
+ /**
121
+ * Finds correlationId of a device from locus self devices array
122
+ * that matches the given deviceUrl
123
+ * @param {string} deviceUrl
124
+ * @param {object} locusSelf
125
+ * @returns {string|false} correlationId or false if not found
126
+ */
127
+ MeetingsUtil.getCorrelationIdForDevice = (deviceUrl: string, locusSelf: any) => {
128
+ if (locusSelf?.devices) {
129
+ const foundDevice = locusSelf?.devices.find((device) => device.url === deviceUrl);
129
130
 
130
131
  if (foundDevice && foundDevice.correlationId) {
131
132
  return foundDevice.correlationId;
@@ -87,6 +87,8 @@ const BEHAVIORAL_METRICS = {
87
87
  VERIFY_REGISTRATION_ID_ERROR: 'js_sdk_verify_registrationId_error',
88
88
  JOIN_FORBIDDEN_ERROR: 'js_sdk_join_forbidden_error',
89
89
  MEDIA_ISSUE_DETECTED: 'js_sdk_media_issue_detected',
90
+ LOCUS_CLASSIC_VS_HASH_TREE_MISMATCH: 'js_sdk_locus_classic_vs_hash_tree_mismatch',
91
+ LOCUS_HASH_TREE_UNSUPPORTED_OPERATION: 'js_sdk_locus_hash_tree_unsupported_operation',
90
92
  };
91
93
 
92
94
  export {BEHAVIORAL_METRICS as default};