@webex/plugin-meetings 3.8.1 → 3.9.0-multiple-llm.2

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 (319) hide show
  1. package/README.md +26 -13
  2. package/dist/breakouts/breakout.js +1 -1
  3. package/dist/breakouts/index.js +1 -1
  4. package/dist/constants.js +34 -3
  5. package/dist/constants.js.map +1 -1
  6. package/dist/controls-options-manager/enums.js +1 -0
  7. package/dist/controls-options-manager/enums.js.map +1 -1
  8. package/dist/controls-options-manager/types.js.map +1 -1
  9. package/dist/controls-options-manager/util.js +26 -0
  10. package/dist/controls-options-manager/util.js.map +1 -1
  11. package/dist/interpretation/index.js +1 -1
  12. package/dist/interpretation/siLanguage.js +1 -1
  13. package/dist/locus-info/controlsUtils.js +11 -3
  14. package/dist/locus-info/controlsUtils.js.map +1 -1
  15. package/dist/locus-info/index.js +107 -95
  16. package/dist/locus-info/index.js.map +1 -1
  17. package/dist/locus-info/parser.js +4 -1
  18. package/dist/locus-info/parser.js.map +1 -1
  19. package/dist/media/index.js +2 -2
  20. package/dist/media/index.js.map +1 -1
  21. package/dist/media/properties.js +53 -5
  22. package/dist/media/properties.js.map +1 -1
  23. package/dist/meeting/brbState.js +17 -14
  24. package/dist/meeting/brbState.js.map +1 -1
  25. package/dist/meeting/in-meeting-actions.js +13 -1
  26. package/dist/meeting/in-meeting-actions.js.map +1 -1
  27. package/dist/meeting/index.js +555 -296
  28. package/dist/meeting/index.js.map +1 -1
  29. package/dist/meeting/muteState.js +2 -5
  30. package/dist/meeting/muteState.js.map +1 -1
  31. package/dist/meeting/request.js +44 -0
  32. package/dist/meeting/request.js.map +1 -1
  33. package/dist/meeting/request.type.js.map +1 -1
  34. package/dist/{rtcMetrics/constants.js → meeting/type.js} +1 -5
  35. package/dist/meeting/type.js.map +1 -0
  36. package/dist/meeting/util.js +98 -13
  37. package/dist/meeting/util.js.map +1 -1
  38. package/dist/meeting-info/meeting-info-v2.js +29 -21
  39. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  40. package/dist/meetings/index.js +18 -10
  41. package/dist/meetings/index.js.map +1 -1
  42. package/dist/member/types.js.map +1 -1
  43. package/dist/members/collection.js +13 -0
  44. package/dist/members/collection.js.map +1 -1
  45. package/dist/members/index.js +53 -29
  46. package/dist/members/index.js.map +1 -1
  47. package/dist/members/request.js +3 -3
  48. package/dist/members/request.js.map +1 -1
  49. package/dist/members/util.js +25 -8
  50. package/dist/members/util.js.map +1 -1
  51. package/dist/metrics/constants.js +3 -1
  52. package/dist/metrics/constants.js.map +1 -1
  53. package/dist/multistream/mediaRequestManager.js +1 -1
  54. package/dist/multistream/mediaRequestManager.js.map +1 -1
  55. package/dist/multistream/remoteMedia.js +34 -5
  56. package/dist/multistream/remoteMedia.js.map +1 -1
  57. package/dist/multistream/remoteMediaGroup.js +42 -2
  58. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  59. package/dist/multistream/sendSlotManager.js +32 -2
  60. package/dist/multistream/sendSlotManager.js.map +1 -1
  61. package/dist/reachability/index.js +8 -13
  62. package/dist/reachability/index.js.map +1 -1
  63. package/dist/types/constants.d.ts +30 -0
  64. package/dist/types/controls-options-manager/enums.d.ts +2 -1
  65. package/dist/types/controls-options-manager/types.d.ts +4 -1
  66. package/dist/types/locus-info/index.d.ts +54 -10
  67. package/dist/types/media/properties.d.ts +21 -0
  68. package/dist/types/meeting/brbState.d.ts +0 -1
  69. package/dist/types/meeting/in-meeting-actions.d.ts +12 -0
  70. package/dist/types/meeting/index.d.ts +58 -20
  71. package/dist/types/meeting/request.d.ts +18 -1
  72. package/dist/types/meeting/request.type.d.ts +74 -0
  73. package/dist/types/meeting/type.d.ts +9 -0
  74. package/dist/types/meeting/util.d.ts +13 -3
  75. package/dist/types/meeting-info/meeting-info-v2.d.ts +6 -3
  76. package/dist/types/meetings/index.d.ts +3 -1
  77. package/dist/types/member/types.d.ts +1 -0
  78. package/dist/types/members/collection.d.ts +6 -0
  79. package/dist/types/members/index.d.ts +22 -9
  80. package/dist/types/members/request.d.ts +1 -1
  81. package/dist/types/members/util.d.ts +13 -6
  82. package/dist/types/metrics/constants.d.ts +2 -0
  83. package/dist/types/multistream/remoteMedia.d.ts +20 -1
  84. package/dist/types/multistream/remoteMediaGroup.d.ts +11 -0
  85. package/dist/types/multistream/sendSlotManager.d.ts +16 -0
  86. package/dist/types/reachability/index.d.ts +2 -2
  87. package/dist/webinar/index.js +1 -1
  88. package/package.json +25 -26
  89. package/src/constants.ts +34 -2
  90. package/src/controls-options-manager/enums.ts +1 -0
  91. package/src/controls-options-manager/types.ts +6 -1
  92. package/src/controls-options-manager/util.ts +31 -0
  93. package/src/locus-info/controlsUtils.ts +15 -0
  94. package/src/locus-info/index.ts +174 -96
  95. package/src/locus-info/parser.ts +5 -1
  96. package/src/media/index.ts +2 -2
  97. package/src/media/properties.ts +43 -0
  98. package/src/meeting/brbState.ts +13 -9
  99. package/src/meeting/in-meeting-actions.ts +25 -0
  100. package/src/meeting/index.ts +362 -75
  101. package/src/meeting/muteState.ts +2 -6
  102. package/src/meeting/request.ts +39 -0
  103. package/src/meeting/request.type.ts +64 -0
  104. package/src/meeting/type.ts +9 -0
  105. package/src/meeting/util.ts +114 -22
  106. package/src/meeting-info/meeting-info-v2.ts +24 -5
  107. package/src/meetings/index.ts +12 -5
  108. package/src/member/types.ts +1 -0
  109. package/src/members/collection.ts +11 -0
  110. package/src/members/index.ts +51 -15
  111. package/src/members/request.ts +2 -2
  112. package/src/members/util.ts +34 -6
  113. package/src/metrics/constants.ts +2 -0
  114. package/src/multistream/mediaRequestManager.ts +7 -7
  115. package/src/multistream/remoteMedia.ts +34 -4
  116. package/src/multistream/remoteMediaGroup.ts +37 -2
  117. package/src/multistream/sendSlotManager.ts +34 -2
  118. package/src/reachability/index.ts +8 -16
  119. package/test/unit/spec/common/browser-detection.js +0 -24
  120. package/test/unit/spec/controls-options-manager/util.js +58 -0
  121. package/test/unit/spec/locus-info/controlsUtils.js +52 -0
  122. package/test/unit/spec/locus-info/index.js +270 -97
  123. package/test/unit/spec/locus-info/parser.js +3 -2
  124. package/test/unit/spec/media/index.ts +107 -0
  125. package/test/unit/spec/media/properties.ts +137 -0
  126. package/test/unit/spec/meeting/brbState.ts +23 -4
  127. package/test/unit/spec/meeting/in-meeting-actions.ts +12 -0
  128. package/test/unit/spec/meeting/index.js +1194 -97
  129. package/test/unit/spec/meeting/muteState.js +32 -6
  130. package/test/unit/spec/meeting/request.js +92 -0
  131. package/test/unit/spec/meeting/utils.js +167 -17
  132. package/test/unit/spec/meeting-info/meetinginfov2.js +8 -3
  133. package/test/unit/spec/meetings/index.js +12 -5
  134. package/test/unit/spec/members/collection.js +120 -0
  135. package/test/unit/spec/members/index.js +140 -12
  136. package/test/unit/spec/members/request.js +57 -2
  137. package/test/unit/spec/members/utils.js +139 -17
  138. package/test/unit/spec/multistream/mediaRequestManager.ts +19 -6
  139. package/test/unit/spec/multistream/remoteMedia.ts +66 -2
  140. package/test/unit/spec/multistream/sendSlotManager.ts +59 -0
  141. package/test/unit/spec/reachability/index.ts +160 -9
  142. package/test/unit/spec/roap/turnDiscovery.ts +3 -3
  143. package/dist/annotation/annotation.types.d.ts +0 -42
  144. package/dist/annotation/constants.d.ts +0 -31
  145. package/dist/annotation/index.d.ts +0 -117
  146. package/dist/breakouts/breakout.d.ts +0 -8
  147. package/dist/breakouts/collection.d.ts +0 -5
  148. package/dist/breakouts/edit-lock-error.d.ts +0 -15
  149. package/dist/breakouts/events.d.ts +0 -8
  150. package/dist/breakouts/index.d.ts +0 -5
  151. package/dist/breakouts/request.d.ts +0 -22
  152. package/dist/breakouts/utils.d.ts +0 -15
  153. package/dist/common/browser-detection.d.ts +0 -9
  154. package/dist/common/collection.d.ts +0 -48
  155. package/dist/common/config.d.ts +0 -2
  156. package/dist/common/errors/captcha-error.d.ts +0 -15
  157. package/dist/common/errors/intent-to-join.d.ts +0 -16
  158. package/dist/common/errors/join-meeting.d.ts +0 -17
  159. package/dist/common/errors/media.d.ts +0 -15
  160. package/dist/common/errors/no-meeting-info.d.ts +0 -14
  161. package/dist/common/errors/parameter.d.ts +0 -15
  162. package/dist/common/errors/password-error.d.ts +0 -15
  163. package/dist/common/errors/permission.d.ts +0 -14
  164. package/dist/common/errors/reclaim-host-role-error.d.ts +0 -60
  165. package/dist/common/errors/reclaim-host-role-error.js +0 -158
  166. package/dist/common/errors/reclaim-host-role-error.js.map +0 -1
  167. package/dist/common/errors/reclaim-host-role-errors.d.ts +0 -60
  168. package/dist/common/errors/reconnection-in-progress.d.ts +0 -9
  169. package/dist/common/errors/reconnection-in-progress.js +0 -35
  170. package/dist/common/errors/reconnection-in-progress.js.map +0 -1
  171. package/dist/common/errors/reconnection.d.ts +0 -15
  172. package/dist/common/errors/stats.d.ts +0 -15
  173. package/dist/common/errors/webex-errors.d.ts +0 -81
  174. package/dist/common/errors/webex-meetings-error.d.ts +0 -20
  175. package/dist/common/events/events-scope.d.ts +0 -17
  176. package/dist/common/events/events.d.ts +0 -12
  177. package/dist/common/events/trigger-proxy.d.ts +0 -2
  178. package/dist/common/events/util.d.ts +0 -2
  179. package/dist/common/logs/logger-config.d.ts +0 -2
  180. package/dist/common/logs/logger-proxy.d.ts +0 -2
  181. package/dist/common/logs/request.d.ts +0 -34
  182. package/dist/common/queue.d.ts +0 -32
  183. package/dist/config.d.ts +0 -73
  184. package/dist/constants.d.ts +0 -952
  185. package/dist/controls-options-manager/constants.d.ts +0 -4
  186. package/dist/controls-options-manager/enums.d.ts +0 -5
  187. package/dist/controls-options-manager/index.d.ts +0 -120
  188. package/dist/controls-options-manager/types.d.ts +0 -43
  189. package/dist/controls-options-manager/util.d.ts +0 -7
  190. package/dist/index.d.ts +0 -4
  191. package/dist/interceptors/index.d.ts +0 -2
  192. package/dist/interceptors/locusRetry.d.ts +0 -27
  193. package/dist/interpretation/collection.d.ts +0 -5
  194. package/dist/interpretation/index.d.ts +0 -5
  195. package/dist/interpretation/siLanguage.d.ts +0 -5
  196. package/dist/locus-info/controlsUtils.d.ts +0 -2
  197. package/dist/locus-info/embeddedAppsUtils.d.ts +0 -2
  198. package/dist/locus-info/fullState.d.ts +0 -2
  199. package/dist/locus-info/hostUtils.d.ts +0 -2
  200. package/dist/locus-info/index.d.ts +0 -269
  201. package/dist/locus-info/infoUtils.d.ts +0 -2
  202. package/dist/locus-info/mediaSharesUtils.d.ts +0 -2
  203. package/dist/locus-info/parser.d.ts +0 -212
  204. package/dist/locus-info/selfUtils.d.ts +0 -2
  205. package/dist/media/index.d.ts +0 -32
  206. package/dist/media/properties.d.ts +0 -108
  207. package/dist/media/util.d.ts +0 -2
  208. package/dist/mediaQualityMetrics/config.d.ts +0 -233
  209. package/dist/mediaQualityMetrics/config.js +0 -513
  210. package/dist/mediaQualityMetrics/config.js.map +0 -1
  211. package/dist/meeting/effectsState.d.ts +0 -42
  212. package/dist/meeting/effectsState.js +0 -260
  213. package/dist/meeting/effectsState.js.map +0 -1
  214. package/dist/meeting/in-meeting-actions.d.ts +0 -79
  215. package/dist/meeting/index.d.ts +0 -1622
  216. package/dist/meeting/locusMediaRequest.d.ts +0 -74
  217. package/dist/meeting/muteState.d.ts +0 -116
  218. package/dist/meeting/request.d.ts +0 -257
  219. package/dist/meeting/request.type.d.ts +0 -11
  220. package/dist/meeting/state.d.ts +0 -9
  221. package/dist/meeting/util.d.ts +0 -2
  222. package/dist/meeting/voicea-meeting.d.ts +0 -16
  223. package/dist/meeting-info/collection.d.ts +0 -20
  224. package/dist/meeting-info/index.d.ts +0 -57
  225. package/dist/meeting-info/meeting-info-v2.d.ts +0 -93
  226. package/dist/meeting-info/request.d.ts +0 -22
  227. package/dist/meeting-info/util.d.ts +0 -2
  228. package/dist/meeting-info/utilv2.d.ts +0 -2
  229. package/dist/meetings/collection.d.ts +0 -23
  230. package/dist/meetings/index.d.ts +0 -296
  231. package/dist/meetings/meetings.types.d.ts +0 -4
  232. package/dist/meetings/request.d.ts +0 -27
  233. package/dist/meetings/util.d.ts +0 -18
  234. package/dist/member/index.d.ts +0 -148
  235. package/dist/member/member.types.d.ts +0 -11
  236. package/dist/member/member.types.js +0 -18
  237. package/dist/member/member.types.js.map +0 -1
  238. package/dist/member/types.d.ts +0 -32
  239. package/dist/member/util.d.ts +0 -2
  240. package/dist/members/collection.d.ts +0 -24
  241. package/dist/members/index.d.ts +0 -308
  242. package/dist/members/request.d.ts +0 -58
  243. package/dist/members/types.d.ts +0 -25
  244. package/dist/members/util.d.ts +0 -2
  245. package/dist/metrics/config.d.ts +0 -169
  246. package/dist/metrics/config.js +0 -289
  247. package/dist/metrics/config.js.map +0 -1
  248. package/dist/metrics/constants.d.ts +0 -59
  249. package/dist/metrics/index.d.ts +0 -152
  250. package/dist/multistream/mediaRequestManager.d.ts +0 -119
  251. package/dist/multistream/receiveSlot.d.ts +0 -68
  252. package/dist/multistream/receiveSlotManager.d.ts +0 -56
  253. package/dist/multistream/remoteMedia.d.ts +0 -72
  254. package/dist/multistream/remoteMediaGroup.d.ts +0 -49
  255. package/dist/multistream/remoteMediaManager.d.ts +0 -300
  256. package/dist/multistream/sendSlotManager.d.ts +0 -69
  257. package/dist/networkQualityMonitor/index.d.ts +0 -70
  258. package/dist/networkQualityMonitor/index.js +0 -226
  259. package/dist/networkQualityMonitor/index.js.map +0 -1
  260. package/dist/peer-connection-manager/index.d.ts +0 -6
  261. package/dist/peer-connection-manager/index.js +0 -671
  262. package/dist/peer-connection-manager/index.js.map +0 -1
  263. package/dist/peer-connection-manager/util.d.ts +0 -6
  264. package/dist/peer-connection-manager/util.js +0 -110
  265. package/dist/peer-connection-manager/util.js.map +0 -1
  266. package/dist/personal-meeting-room/index.d.ts +0 -47
  267. package/dist/personal-meeting-room/request.d.ts +0 -14
  268. package/dist/personal-meeting-room/util.d.ts +0 -2
  269. package/dist/reachability/clusterReachability.d.ts +0 -109
  270. package/dist/reachability/index.d.ts +0 -139
  271. package/dist/reachability/request.d.ts +0 -35
  272. package/dist/reachability/util.d.ts +0 -8
  273. package/dist/reactions/constants.d.ts +0 -3
  274. package/dist/reactions/reactions.d.ts +0 -4
  275. package/dist/reactions/reactions.type.d.ts +0 -32
  276. package/dist/reconnection-manager/index.d.ts +0 -112
  277. package/dist/recording-controller/enums.d.ts +0 -7
  278. package/dist/recording-controller/index.d.ts +0 -193
  279. package/dist/recording-controller/util.d.ts +0 -13
  280. package/dist/roap/collection.d.ts +0 -10
  281. package/dist/roap/collection.js +0 -63
  282. package/dist/roap/collection.js.map +0 -1
  283. package/dist/roap/handler.d.ts +0 -47
  284. package/dist/roap/handler.js +0 -279
  285. package/dist/roap/handler.js.map +0 -1
  286. package/dist/roap/index.d.ts +0 -116
  287. package/dist/roap/request.d.ts +0 -35
  288. package/dist/roap/state.d.ts +0 -9
  289. package/dist/roap/state.js +0 -127
  290. package/dist/roap/state.js.map +0 -1
  291. package/dist/roap/turnDiscovery.d.ts +0 -81
  292. package/dist/roap/util.d.ts +0 -2
  293. package/dist/roap/util.js +0 -76
  294. package/dist/roap/util.js.map +0 -1
  295. package/dist/rtcMetrics/constants.d.ts +0 -4
  296. package/dist/rtcMetrics/constants.js.map +0 -1
  297. package/dist/rtcMetrics/index.d.ts +0 -61
  298. package/dist/rtcMetrics/index.js +0 -197
  299. package/dist/rtcMetrics/index.js.map +0 -1
  300. package/dist/statsAnalyzer/global.d.ts +0 -118
  301. package/dist/statsAnalyzer/global.js +0 -127
  302. package/dist/statsAnalyzer/global.js.map +0 -1
  303. package/dist/statsAnalyzer/index.d.ts +0 -193
  304. package/dist/statsAnalyzer/index.js +0 -1019
  305. package/dist/statsAnalyzer/index.js.map +0 -1
  306. package/dist/statsAnalyzer/mqaUtil.d.ts +0 -22
  307. package/dist/statsAnalyzer/mqaUtil.js +0 -181
  308. package/dist/statsAnalyzer/mqaUtil.js.map +0 -1
  309. package/dist/transcription/index.d.ts +0 -64
  310. package/dist/types/common/errors/reconnection-in-progress.d.ts +0 -9
  311. package/dist/types/mediaQualityMetrics/config.d.ts +0 -241
  312. package/dist/types/networkQualityMonitor/index.d.ts +0 -70
  313. package/dist/types/rtcMetrics/constants.d.ts +0 -4
  314. package/dist/types/rtcMetrics/index.d.ts +0 -71
  315. package/dist/types/statsAnalyzer/global.d.ts +0 -36
  316. package/dist/types/statsAnalyzer/index.d.ts +0 -217
  317. package/dist/types/statsAnalyzer/mqaUtil.d.ts +0 -48
  318. package/dist/webinar/collection.d.ts +0 -16
  319. package/dist/webinar/index.d.ts +0 -5
@@ -31,6 +31,51 @@ import LocusDeltaParser from './parser';
31
31
  import Metrics from '../metrics';
32
32
  import BEHAVIORAL_METRICS from '../metrics/constants';
33
33
 
34
+ export type LocusDTO = {
35
+ controls?: any;
36
+ fullState?: {
37
+ active: boolean;
38
+ count: number;
39
+ lastActive: string;
40
+ locked: boolean;
41
+ sessionId: string;
42
+ seessionIds: string[];
43
+ startTime: number;
44
+ state: string;
45
+ type: string;
46
+ };
47
+ host?: {
48
+ id: string;
49
+ incomingCallProtocols: any[];
50
+ isExternal: boolean;
51
+ name: string;
52
+ orgId: string;
53
+ };
54
+ info?: any;
55
+ links?: any;
56
+ mediaShares?: any[];
57
+ meetings?: any[];
58
+ participants: any[];
59
+ replaces?: any[];
60
+ self?: any;
61
+ sequence?: {
62
+ dirtyParticipants: number;
63
+ entries: number[];
64
+ rangeEnd: number;
65
+ rangeStart: number;
66
+ sequenceHash: number;
67
+ sessionToken: string;
68
+ since: string;
69
+ totalParticipants: number;
70
+ };
71
+ syncUrl?: string;
72
+ url?: string;
73
+ };
74
+
75
+ export type LocusApiResponseBody = {
76
+ locus: LocusDTO; // this LocusDTO here might not be the full one (for example it won't have all the participants, but it should have self)
77
+ };
78
+
34
79
  /**
35
80
  * @description LocusInfo extends ChildEmitter to convert locusInfo info a private emitter to parent object
36
81
  * @export
@@ -48,7 +93,6 @@ export default class LocusInfo extends EventsScope {
48
93
  aclUrl: any;
49
94
  baseSequence: any;
50
95
  created: any;
51
- deltaParticipants: any;
52
96
  identities: any;
53
97
  membership: any;
54
98
  participants: any;
@@ -94,18 +138,26 @@ export default class LocusInfo extends EventsScope {
94
138
  * Does a Locus sync. It tries to get the latest delta DTO or if it can't, it falls back to getting the full Locus DTO.
95
139
  *
96
140
  * @param {Meeting} meeting
141
+ * @param {boolean} isLocusUrlChanged
142
+ * @param {Locus} locus
97
143
  * @returns {undefined}
98
144
  */
99
- private doLocusSync(meeting: any) {
100
- let isDelta;
145
+ private doLocusSync(meeting: any, isLocusUrlChanged: boolean, locus: any) {
101
146
  let url;
102
-
103
- if (this.locusParser.workingCopy.syncUrl) {
147
+ let isDelta = false;
148
+ let meetingDestroyed = false;
149
+
150
+ if (isLocusUrlChanged) {
151
+ // for the locus url changed case from breakout to main session, we should always do a full sync, in this case, the url from locus is always on main session,
152
+ // so use the main session locus url to get the full locus(full participants list in the response).
153
+ // for the locus url changed case from main session to breakout, we don't need to care about it here,
154
+ // because it is a USE_INCOMING case, it will not be executed here.
155
+ url = locus.url;
156
+ } else if (this.locusParser.workingCopy?.syncUrl) {
104
157
  url = this.locusParser.workingCopy.syncUrl;
105
158
  isDelta = true;
106
159
  } else {
107
160
  url = meeting.locusUrl;
108
- isDelta = false;
109
161
  }
110
162
 
111
163
  LoggerProxy.logger.info(
@@ -134,35 +186,77 @@ export default class LocusInfo extends EventsScope {
134
186
 
135
187
  isDelta = false;
136
188
 
137
- return meeting.meetingRequest.getLocusDTO({url: meeting.locusUrl}).catch((err) => {
138
- LoggerProxy.logger.info(
139
- 'Locus-info:index#doLocusSync --> fallback full sync failed, destroying the meeting'
140
- );
141
- this.webex.meetings.destroy(meeting, MEETING_REMOVED_REASON.LOCUS_DTO_SYNC_FAILED);
142
- throw err;
143
- });
189
+ // Locus sometimes returns 403, for example if meeting has ended, no point trying the fallback to full sync in that case
190
+ if (e.statusCode !== 403) {
191
+ return meeting.meetingRequest.getLocusDTO({url: meeting.locusUrl}).catch((err) => {
192
+ LoggerProxy.logger.info(
193
+ 'Locus-info:index#doLocusSync --> fallback full sync failed, destroying the meeting'
194
+ );
195
+ this.webex.meetings.destroy(meeting, MEETING_REMOVED_REASON.LOCUS_DTO_SYNC_FAILED);
196
+ meetingDestroyed = true;
197
+ throw err;
198
+ });
199
+ }
200
+ LoggerProxy.logger.info(
201
+ 'Locus-info:index#doLocusSync --> got 403 from Locus, skipping fallback to full sync, destroying the meeting'
202
+ );
203
+ } else {
204
+ LoggerProxy.logger.info(
205
+ 'Locus-info:index#doLocusSync --> fallback full sync failed, destroying the meeting'
206
+ );
144
207
  }
145
- LoggerProxy.logger.info(
146
- 'Locus-info:index#doLocusSync --> fallback full sync failed, destroying the meeting'
147
- );
148
208
  this.webex.meetings.destroy(meeting, MEETING_REMOVED_REASON.LOCUS_DTO_SYNC_FAILED);
209
+ meetingDestroyed = true;
149
210
  throw e;
150
211
  })
151
212
  .then((res) => {
152
- if (isDelta) {
153
- if (!isEmpty(res.body)) {
154
- meeting.locusInfo.handleLocusDelta(res.body, meeting);
155
- } else {
213
+ if (isEmpty(res.body)) {
214
+ if (isDelta) {
156
215
  LoggerProxy.logger.info(
157
216
  'Locus-info:index#doLocusSync --> received empty body from syncUrl, so we already have latest Locus DTO'
158
217
  );
218
+ } else {
219
+ LoggerProxy.logger.info(
220
+ 'Locus-info:index#doLocusSync --> received empty body from full DTO sync request'
221
+ );
159
222
  }
160
- } else {
161
- meeting.locusInfo.onFullLocus(res.body);
223
+
224
+ return;
225
+ }
226
+
227
+ if (isDelta) {
228
+ if (res.body.baseSequence) {
229
+ meeting.locusInfo.handleLocusDelta(res.body, meeting);
230
+
231
+ return;
232
+ }
233
+ // in some cases Locus might return us full DTO even when we asked for a delta
234
+ LoggerProxy.logger.info(
235
+ 'Locus-info:index#doLocusSync --> got full DTO when we asked for delta'
236
+ );
237
+ }
238
+ meeting.locusInfo.onFullLocus(res.body);
239
+ })
240
+ .catch((e) => {
241
+ LoggerProxy.logger.info(
242
+ `Locus-info:index#doLocusSync --> getLocusDTO succeeded but failed to handle result, locus parser will resume but not all data may be synced (${e.toString()})`
243
+ );
244
+
245
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.LOCUS_SYNC_HANDLING_FAILED, {
246
+ correlationId: meeting.correlationId,
247
+ url,
248
+ reason: e.message,
249
+ errorName: e.name,
250
+ stack: e.stack,
251
+ code: e.code,
252
+ });
253
+ })
254
+ .finally(() => {
255
+ if (!meetingDestroyed) {
256
+ // Notify parser to resume processing delta events.
257
+ // Any deltas in the queue that have now been superseded by this sync will simply be ignored
258
+ this.locusParser.resume();
162
259
  }
163
- // Notify parser to resume processing delta events.
164
- // Any deltas in the queue that have now been superseded by this sync will simply be ignored
165
- this.locusParser.resume();
166
260
  });
167
261
  }
168
262
 
@@ -175,6 +269,7 @@ export default class LocusInfo extends EventsScope {
175
269
  */
176
270
  applyLocusDeltaData(action: string, locus: any, meeting: any) {
177
271
  const {DESYNC, USE_CURRENT, USE_INCOMING, WAIT, LOCUS_URL_CHANGED} = LocusDeltaParser.loci;
272
+ const isLocusUrlChanged = action === LOCUS_URL_CHANGED;
178
273
 
179
274
  switch (action) {
180
275
  case USE_INCOMING:
@@ -186,7 +281,7 @@ export default class LocusInfo extends EventsScope {
186
281
  break;
187
282
  case DESYNC:
188
283
  case LOCUS_URL_CHANGED:
189
- this.doLocusSync(meeting);
284
+ this.doLocusSync(meeting, isLocusUrlChanged, locus);
190
285
  break;
191
286
  default:
192
287
  LoggerProxy.logger.info(
@@ -241,21 +336,10 @@ export default class LocusInfo extends EventsScope {
241
336
  * @property {Object} person - Contains person data.
242
337
  */
243
338
 
244
- /**
245
- * Stored participant changes between the last event and the current event.
246
- * All previously stored events are overwritten between events.
247
- *
248
- * @instance
249
- * @type {Array<DeltaParticipant>}
250
- * @private
251
- * @member LocusInfo
252
- */
253
- this.deltaParticipants = [];
254
-
255
339
  this.updateLocusCache(locus);
256
340
  // above section only updates the locusInfo object
257
341
  // The below section makes sure it updates the locusInfo as well as updates the meeting object
258
- this.updateParticipants(locus.participants);
342
+ this.updateParticipants(locus.participants, []);
259
343
  // For 1:1 space meeting the conversation Url does not exist in locus.conversation
260
344
  this.updateConversationUrl(locus.conversationUrl, locus.info);
261
345
  this.updateControls(locus.controls, locus.self);
@@ -284,6 +368,16 @@ export default class LocusInfo extends EventsScope {
284
368
  this.emitChange = true;
285
369
  }
286
370
 
371
+ /**
372
+ * Handles HTTP response from Locus API call.
373
+ * @param {Meeting} meeting meeting object
374
+ * @param {LocusApiResponseBody} responseBody body of the http response from Locus API call
375
+ * @returns {void}
376
+ */
377
+ handleLocusAPIResponse(meeting, responseBody: LocusApiResponseBody): void {
378
+ this.handleLocusDelta(responseBody.locus, meeting);
379
+ }
380
+
287
381
  /**
288
382
  * @param {Meeting} meeting
289
383
  * @param {Object} data
@@ -296,6 +390,8 @@ export default class LocusInfo extends EventsScope {
296
390
  const locus = this.getTheLocusToUpdate(data.locus);
297
391
  LoggerProxy.logger.info(`Locus-info:index#parse --> received locus data: ${eventType}`);
298
392
 
393
+ locus.jsSdkMeta = {removedParticipantIds: []};
394
+
299
395
  switch (eventType) {
300
396
  case LOCUSEVENT.PARTICIPANT_JOIN:
301
397
  case LOCUSEVENT.PARTICIPANT_LEFT:
@@ -357,12 +453,15 @@ export default class LocusInfo extends EventsScope {
357
453
  return;
358
454
  }
359
455
 
360
- this.updateParticipantDeltas(locus.participants);
361
456
  this.scheduledMeeting = locus.meeting || null;
362
457
  this.participants = locus.participants;
363
458
  const isReplaceMembers = ControlsUtils.isNeedReplaceMembers(this.controls, locus.controls);
364
459
  this.updateLocusInfo(locus);
365
- this.updateParticipants(locus.participants, isReplaceMembers);
460
+ this.updateParticipants(
461
+ locus.participants,
462
+ locus.jsSdkMeta?.removedParticipantIds,
463
+ isReplaceMembers
464
+ );
366
465
  this.isMeetingActive();
367
466
  this.handleOneOnOneEvent(eventType);
368
467
  this.updateEmbeddedApps(locus.embeddedApps);
@@ -424,7 +523,11 @@ export default class LocusInfo extends EventsScope {
424
523
  const isReplaceMembers = ControlsUtils.isNeedReplaceMembers(this.controls, locus.controls);
425
524
  this.mergeParticipants(this.participants, locus.participants);
426
525
  this.updateLocusInfo(locus);
427
- this.updateParticipants(locus.participants, isReplaceMembers);
526
+ this.updateParticipants(
527
+ locus.participants,
528
+ locus.jsSdkMeta?.removedParticipantIds,
529
+ isReplaceMembers
530
+ );
428
531
  this.isMeetingActive();
429
532
  }
430
533
 
@@ -446,12 +549,12 @@ export default class LocusInfo extends EventsScope {
446
549
  this.updateCreated(locus.created);
447
550
  this.updateFullState(locus.fullState);
448
551
  this.updateHostInfo(locus.host);
552
+ this.updateLocusUrl(locus.url);
449
553
  this.updateMeetingInfo(locus.info, locus.self);
450
554
  this.updateMediaShares(locus.mediaShares);
451
555
  this.updateParticipantsUrl(locus.participantsUrl);
452
556
  this.updateReplace(locus.replace);
453
557
  this.updateSelf(locus.self);
454
- this.updateLocusUrl(locus.url);
455
558
  this.updateAclUrl(locus.aclUrl);
456
559
  this.updateBasequence(locus.baseSequence);
457
560
  this.updateSequence(locus.sequence);
@@ -712,63 +815,15 @@ export default class LocusInfo extends EventsScope {
712
815
  }
713
816
  }
714
817
 
715
- /**
716
- * Update the deltaParticipants property of this object based on a list of
717
- * provided participants.
718
- *
719
- * @param {Array} [participants] - The participants to update against.
720
- * @returns {void}
721
- */
722
- updateParticipantDeltas(participants: Array<any> = []) {
723
- // Used to find a participant within a participants collection.
724
- const findParticipant = (participant, collection) =>
725
- collection.find((item) => item.person.id === participant.person.id);
726
-
727
- // Generates an object that indicates which state properties have changed.
728
- const generateDelta = (prevState: any = {}, newState: any = {}) => {
729
- // Setup deltas.
730
- const deltas = {
731
- audioStatus: prevState.audioStatus !== newState.audioStatus,
732
- videoSlidesStatus: prevState.videoSlidesStatus !== newState.videoSlidesStatus,
733
- videoStatus: prevState.videoStatus !== newState.videoStatus,
734
- };
735
-
736
- // Clean the object
737
- Object.keys(deltas).forEach((key) => {
738
- if (deltas[key] !== true) {
739
- delete deltas[key];
740
- }
741
- });
742
-
743
- return deltas;
744
- };
745
-
746
- this.deltaParticipants = participants.reduce((collection, participant) => {
747
- const existingParticipant = findParticipant(participant, this.participants || []) || {};
748
-
749
- const delta = generateDelta(existingParticipant.status, participant.status);
750
-
751
- const changed = Object.keys(delta).length > 0;
752
-
753
- if (changed) {
754
- collection.push({
755
- person: participant.person,
756
- delta,
757
- });
758
- }
759
-
760
- return collection;
761
- }, []);
762
- }
763
-
764
818
  /**
765
819
  * update meeting's members
766
820
  * @param {Object} participants new participants object
821
+ * @param {Array} removedParticipantIds list of removed participants
767
822
  * @param {Boolean} isReplace is replace the whole members
768
823
  * @returns {Array} updatedParticipants
769
824
  * @memberof LocusInfo
770
825
  */
771
- updateParticipants(participants: object, isReplace?: boolean) {
826
+ updateParticipants(participants: object, removedParticipantIds?: string[], isReplace?: boolean) {
772
827
  this.emitScoped(
773
828
  {
774
829
  file: 'locus-info',
@@ -777,6 +832,7 @@ export default class LocusInfo extends EventsScope {
777
832
  EVENTS.LOCUS_INFO_UPDATE_PARTICIPANTS,
778
833
  {
779
834
  participants,
835
+ removedParticipantIds,
780
836
  recordingId: this.parsedLocus.controls && this.parsedLocus.controls.record?.modifiedBy,
781
837
  selfIdentity: this.parsedLocus.self && this.parsedLocus.self.selfIdentity,
782
838
  selfId: this.parsedLocus.self && this.parsedLocus.self.selfId,
@@ -818,6 +874,7 @@ export default class LocusInfo extends EventsScope {
818
874
  hasRecordingPausedChanged,
819
875
  hasMeetingContainerChanged,
820
876
  hasTranscribeChanged,
877
+ hasTranscribeSpokenLanguageChanged,
821
878
  hasManualCaptionChanged,
822
879
  hasEntryExitToneChanged,
823
880
  hasBreakoutChanged,
@@ -837,6 +894,7 @@ export default class LocusInfo extends EventsScope {
837
894
  hasStageViewChanged,
838
895
  hasAnnotationControlChanged,
839
896
  hasRemoteDesktopControlChanged,
897
+ hasPollingQAControlChanged,
840
898
  },
841
899
  current,
842
900
  } = ControlsUtils.getControls(this.controls, controls);
@@ -956,6 +1014,21 @@ export default class LocusInfo extends EventsScope {
956
1014
  );
957
1015
  }
958
1016
 
1017
+ if (hasTranscribeSpokenLanguageChanged) {
1018
+ const {spokenLanguage} = current.transcribe;
1019
+
1020
+ this.emitScoped(
1021
+ {
1022
+ file: 'locus-info',
1023
+ function: 'updateControls',
1024
+ },
1025
+ LOCUSINFO.EVENTS.CONTROLS_MEETING_TRANSCRIPTION_SPOKEN_LANGUAGE_UPDATED,
1026
+ {
1027
+ spokenLanguage,
1028
+ }
1029
+ );
1030
+ }
1031
+
959
1032
  if (hasManualCaptionChanged) {
960
1033
  const {enabled} = current.manualCaptionControl;
961
1034
 
@@ -1088,6 +1161,14 @@ export default class LocusInfo extends EventsScope {
1088
1161
  );
1089
1162
  }
1090
1163
 
1164
+ if (hasPollingQAControlChanged) {
1165
+ this.emitScoped(
1166
+ {file: 'locus-info', function: 'updateControls'},
1167
+ LOCUSINFO.EVENTS.CONTROLS_POLLING_QA_CHANGED,
1168
+ {state: current.pollingQAControl}
1169
+ );
1170
+ }
1171
+
1091
1172
  this.controls = controls;
1092
1173
  }
1093
1174
  }
@@ -1248,10 +1329,7 @@ export default class LocusInfo extends EventsScope {
1248
1329
  */
1249
1330
  updateMeetingInfo(info: object, self?: object) {
1250
1331
  const roles = self ? SelfUtils.getRoles(self) : this.parsedLocus.self?.roles || [];
1251
- if (
1252
- (info && !isEqual(this.info, info)) ||
1253
- (roles.length && !isEqual(this.roles, roles) && info)
1254
- ) {
1332
+ if ((info && !isEqual(this.info, info)) || (!isEqual(this.roles, roles) && info)) {
1255
1333
  const isJoined = SelfUtils.isJoined(self || this.parsedLocus.self);
1256
1334
  const parsedInfo = InfoUtils.getInfos(this.parsedLocus.info, info, roles, isJoined);
1257
1335
 
@@ -728,13 +728,17 @@ export default class Parser {
728
728
  break;
729
729
 
730
730
  case USE_INCOMING:
731
- case LOCUS_URL_CHANGED:
732
731
  // update working copy for future comparisons.
733
732
  // Note: The working copy of parser gets updated in .onFullLocus()
734
733
  // and here when USE_INCOMING or LOCUS_URL_CHANGED locus.
735
734
  this.workingCopy = newLoci;
736
735
  break;
737
736
 
737
+ case LOCUS_URL_CHANGED:
738
+ // clear the working copy completely, do a full locus sync
739
+ this.workingCopy = null;
740
+ break;
741
+
738
742
  case WAIT:
739
743
  // we've taken newLoci from the front of the queue, so put it back there as we have to wait
740
744
  // for the one that should be in front of it, before we can process it
@@ -239,8 +239,8 @@ Media.createMediaConnection = (
239
239
  screenShareAudio: shareAudioStream?.outputStream?.getTracks()[0], // TODO: add type for screenShareAudio in internal-media-core SPARK-446923
240
240
  } as unknown,
241
241
  direction: {
242
- audio: Media.getDirection(true, mediaDirection.receiveAudio, mediaDirection.sendAudio),
243
- video: Media.getDirection(true, mediaDirection.receiveVideo, mediaDirection.sendVideo),
242
+ audio: Media.getDirection(false, mediaDirection.receiveAudio, mediaDirection.sendAudio),
243
+ video: Media.getDirection(false, mediaDirection.receiveVideo, mediaDirection.sendVideo),
244
244
  screenShareVideo: Media.getDirection(
245
245
  false,
246
246
  mediaDirection.receiveShare,
@@ -9,9 +9,12 @@ import {
9
9
 
10
10
  import {parse} from '@webex/ts-sdp';
11
11
  import {ClientEvent} from '@webex/internal-plugin-metrics';
12
+ import {throttle} from 'lodash';
13
+ import Metrics from '../metrics';
12
14
  import {MEETINGS, QUALITY_LEVELS} from '../constants';
13
15
  import LoggerProxy from '../common/logs/logger-proxy';
14
16
  import MediaConnectionAwaiter from './MediaConnectionAwaiter';
17
+ import BEHAVIORAL_METRICS from '../metrics/constants';
15
18
 
16
19
  export type MediaDirection = {
17
20
  sendAudio: boolean;
@@ -41,6 +44,8 @@ export default class MediaProperties {
41
44
  videoDeviceId: any;
42
45
  videoStream?: LocalCameraStream;
43
46
  namespace = MEETINGS;
47
+ mediaIssueCounters: {[key: string]: number} = {};
48
+ throttledSendMediaIssueMetric: ReturnType<typeof throttle>;
44
49
 
45
50
  /**
46
51
  * @param {Object} [options] -- to auto construct
@@ -66,6 +71,15 @@ export default class MediaProperties {
66
71
  this.remoteQualityLevel = QUALITY_LEVELS.HIGH;
67
72
  this.mediaSettings = {};
68
73
  this.videoDeviceId = null;
74
+
75
+ this.throttledSendMediaIssueMetric = throttle((eventPayload) => {
76
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEDIA_ISSUE_DETECTED, {
77
+ ...eventPayload,
78
+ });
79
+ Object.keys(this.mediaIssueCounters).forEach((key) => {
80
+ this.mediaIssueCounters[key] = 0;
81
+ });
82
+ }, 1000 * 60 * 5); // at most once every 5 minutes
69
83
  }
70
84
 
71
85
  /**
@@ -139,8 +153,14 @@ export default class MediaProperties {
139
153
  this.videoDeviceId = deviceId;
140
154
  }
141
155
 
156
+ /**
157
+ * Clears the webrtcMediaConnection. This method should be called after
158
+ * peer connection is closed and no longer needed.
159
+ * @returns {void}
160
+ */
142
161
  unsetPeerConnection() {
143
162
  this.webrtcMediaConnection = null;
163
+ this.throttledSendMediaIssueMetric.flush();
144
164
  }
145
165
 
146
166
  /**
@@ -424,4 +444,27 @@ export default class MediaProperties {
424
444
  };
425
445
  }
426
446
  }
447
+
448
+ /**
449
+ * Sends a metric about a media issue. Metrics are throttled so that we don't
450
+ * send too many of them, but include a count so that we know how many issues
451
+ * were detected.
452
+ *
453
+ * @param {string} issueType
454
+ * @param {string} issueSubType
455
+ * @param {string} correlationId
456
+ * @returns {void}
457
+ */
458
+ public sendMediaIssueMetric(issueType: string, issueSubType: string, correlationId) {
459
+ const key = `${issueType}_${issueSubType}`;
460
+
461
+ const count = (this.mediaIssueCounters[key] || 0) + 1;
462
+
463
+ this.mediaIssueCounters[key] = count;
464
+
465
+ this.throttledSendMediaIssueMetric({
466
+ correlationId,
467
+ ...this.mediaIssueCounters,
468
+ });
469
+ }
427
470
  }
@@ -58,7 +58,13 @@ export class BrbState {
58
58
  public enable(enabled: boolean, sendSlotManager: SendSlotManager) {
59
59
  this.state.client.enabled = enabled;
60
60
 
61
- return this.applyClientStateToServer(sendSlotManager);
61
+ // Don't set the source state override if enabling brb fails
62
+ return this.applyClientStateToServer(sendSlotManager).then(() => {
63
+ sendSlotManager.setSourceStateOverride(
64
+ MediaType.VideoMain,
65
+ this.state.client.enabled ? 'away' : null
66
+ );
67
+ });
62
68
  }
63
69
 
64
70
  /**
@@ -92,7 +98,7 @@ export class BrbState {
92
98
 
93
99
  this.state.syncToServerInProgress = true;
94
100
 
95
- return this.sendLocalBrbStateToServer(sendSlotManager)
101
+ return this.sendLocalBrbStateToServer()
96
102
  .then(() => {
97
103
  this.state.syncToServerInProgress = false;
98
104
 
@@ -109,19 +115,20 @@ export class BrbState {
109
115
  // need to check if a new sync is required, because this.state.client may have changed while we were doing the current sync
110
116
  this.applyClientStateToServer(sendSlotManager);
111
117
  })
112
- .catch((e) => {
118
+ .catch((error) => {
113
119
  this.state.syncToServerInProgress = false;
114
- LoggerProxy.logger.warn(`Meeting:brbState#applyClientStateToServer: error: ${e}`);
120
+ LoggerProxy.logger.warn(`Meeting:brbState#applyClientStateToServer: Error: ${error}`);
121
+
122
+ return Promise.reject(error);
115
123
  });
116
124
  }
117
125
 
118
126
  /**
119
127
  * Send the local brb state to the server
120
128
  *
121
- * @param {SendSlotManager} sendSlotManager
122
129
  * @returns {Promise}
123
130
  */
124
- private async sendLocalBrbStateToServer(sendSlotManager: SendSlotManager) {
131
+ private async sendLocalBrbStateToServer() {
125
132
  const {enabled} = this.state.client;
126
133
 
127
134
  if (!this.meeting.isMultistream) {
@@ -151,9 +158,6 @@ export class BrbState {
151
158
  deviceUrl: this.meeting.deviceUrl,
152
159
  selfId: this.meeting.selfId,
153
160
  })
154
- .then(() => {
155
- sendSlotManager.setSourceStateOverride(MediaType.VideoMain, enabled ? 'away' : null);
156
- })
157
161
  .catch((error) => {
158
162
  LoggerProxy.logger.error('Meeting:brbState#sendLocalBrbStateToServer: Error ', error);
159
163
 
@@ -38,8 +38,13 @@ interface IInMeetingActions {
38
38
  isClosedCaptionActive?: boolean;
39
39
  canStartManualCaption?: boolean;
40
40
  canStopManualCaption?: boolean;
41
+ isLocalRecordingStarted?: boolean;
42
+ isLocalRecordingStopped?: boolean;
43
+ isLocalRecordingPaused?: boolean;
44
+
41
45
  isManualCaptionActive?: boolean;
42
46
  isSaveTranscriptsEnabled?: boolean;
47
+ isSpokenLanguageAutoDetectionEnabled?: boolean;
43
48
  isWebexAssistantActive?: boolean;
44
49
  canViewCaptionPanel?: boolean;
45
50
  isRealTimeTranslationEnabled?: boolean;
@@ -107,6 +112,8 @@ interface IInMeetingActions {
107
112
  canEnableRemoteDesktopControl?: boolean;
108
113
  canDisableRemoteDesktopControl?: boolean;
109
114
  canMoveToLobby?: boolean;
115
+ canEnablePollingQA?: boolean;
116
+ canDisablePollingQA?: boolean;
110
117
  }
111
118
 
112
119
  /**
@@ -171,10 +178,18 @@ export default class InMeetingActions implements IInMeetingActions {
171
178
 
172
179
  canStopManualCaption = null;
173
180
 
181
+ isLocalRecordingStopped = null;
182
+
183
+ isLocalRecordingStarted = null;
184
+
185
+ isLocalRecordingPaused = null;
186
+
174
187
  isManualCaptionActive = null;
175
188
 
176
189
  isSaveTranscriptsEnabled = null;
177
190
 
191
+ isSpokenLanguageAutoDetectionEnabled = null;
192
+
178
193
  isWebexAssistantActive = null;
179
194
 
180
195
  canViewCaptionPanel = null;
@@ -309,6 +324,10 @@ export default class InMeetingActions implements IInMeetingActions {
309
324
 
310
325
  canMoveToLobby = null;
311
326
 
327
+ canEnablePollingQA = null;
328
+
329
+ canDisablePollingQA = null;
330
+
312
331
  /**
313
332
  * Returns all meeting action options
314
333
  * @returns {Object}
@@ -341,9 +360,13 @@ export default class InMeetingActions implements IInMeetingActions {
341
360
  canStopTranscribing: this.canStopTranscribing,
342
361
  isClosedCaptionActive: this.isClosedCaptionActive,
343
362
  canStartManualCaption: this.canStartManualCaption,
363
+ isLocalRecordingStarted: this.isLocalRecordingStarted,
364
+ isLocalRecordingStopped: this.isLocalRecordingStopped,
365
+ isLocalRecordingPaused: this.isLocalRecordingPaused,
344
366
  canStopManualCaption: this.canStopManualCaption,
345
367
  isManualCaptionActive: this.isManualCaptionActive,
346
368
  isSaveTranscriptsEnabled: this.isSaveTranscriptsEnabled,
369
+ isSpokenLanguageAutoDetectionEnabled: this.isSpokenLanguageAutoDetectionEnabled,
347
370
  isWebexAssistantActive: this.isWebexAssistantActive,
348
371
  canViewCaptionPanel: this.canViewCaptionPanel,
349
372
  isRealTimeTranslationEnabled: this.isRealTimeTranslationEnabled,
@@ -411,6 +434,8 @@ export default class InMeetingActions implements IInMeetingActions {
411
434
  canEnableRemoteDesktopControl: this.canEnableRemoteDesktopControl,
412
435
  canDisableRemoteDesktopControl: this.canDisableRemoteDesktopControl,
413
436
  canMoveToLobby: this.canMoveToLobby,
437
+ canEnablePollingQA: this.canEnablePollingQA,
438
+ canDisablePollingQA: this.canDisablePollingQA,
414
439
  });
415
440
 
416
441
  /**