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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/dist/aiEnableRequest/index.js +184 -0
  2. package/dist/aiEnableRequest/index.js.map +1 -0
  3. package/dist/aiEnableRequest/utils.js +36 -0
  4. package/dist/aiEnableRequest/utils.js.map +1 -0
  5. package/dist/annotation/index.js +3 -3
  6. package/dist/annotation/index.js.map +1 -1
  7. package/dist/breakouts/breakout.js +1 -1
  8. package/dist/breakouts/index.js +1 -1
  9. package/dist/config.js +5 -1
  10. package/dist/config.js.map +1 -1
  11. package/dist/constants.js +26 -6
  12. package/dist/constants.js.map +1 -1
  13. package/dist/hashTree/constants.js +3 -1
  14. package/dist/hashTree/constants.js.map +1 -1
  15. package/dist/hashTree/hashTree.js +18 -0
  16. package/dist/hashTree/hashTree.js.map +1 -1
  17. package/dist/hashTree/hashTreeParser.js +709 -380
  18. package/dist/hashTree/hashTreeParser.js.map +1 -1
  19. package/dist/hashTree/types.js +4 -2
  20. package/dist/hashTree/types.js.map +1 -1
  21. package/dist/hashTree/utils.js +10 -0
  22. package/dist/hashTree/utils.js.map +1 -1
  23. package/dist/index.js +11 -2
  24. package/dist/index.js.map +1 -1
  25. package/dist/interceptors/constant.js +12 -0
  26. package/dist/interceptors/constant.js.map +1 -0
  27. package/dist/interceptors/dataChannelAuthToken.js +233 -0
  28. package/dist/interceptors/dataChannelAuthToken.js.map +1 -0
  29. package/dist/interceptors/index.js +7 -0
  30. package/dist/interceptors/index.js.map +1 -1
  31. package/dist/interpretation/index.js +2 -2
  32. package/dist/interpretation/index.js.map +1 -1
  33. package/dist/interpretation/siLanguage.js +1 -1
  34. package/dist/locus-info/controlsUtils.js +5 -3
  35. package/dist/locus-info/controlsUtils.js.map +1 -1
  36. package/dist/locus-info/index.js +125 -68
  37. package/dist/locus-info/index.js.map +1 -1
  38. package/dist/locus-info/selfUtils.js +1 -0
  39. package/dist/locus-info/selfUtils.js.map +1 -1
  40. package/dist/locus-info/types.js.map +1 -1
  41. package/dist/media/MediaConnectionAwaiter.js +57 -1
  42. package/dist/media/MediaConnectionAwaiter.js.map +1 -1
  43. package/dist/media/properties.js +4 -2
  44. package/dist/media/properties.js.map +1 -1
  45. package/dist/meeting/in-meeting-actions.js +7 -1
  46. package/dist/meeting/in-meeting-actions.js.map +1 -1
  47. package/dist/meeting/index.js +209 -90
  48. package/dist/meeting/index.js.map +1 -1
  49. package/dist/meeting/request.js +50 -0
  50. package/dist/meeting/request.js.map +1 -1
  51. package/dist/meeting/request.type.js.map +1 -1
  52. package/dist/meeting/util.js +128 -2
  53. package/dist/meeting/util.js.map +1 -1
  54. package/dist/meetings/index.js +78 -36
  55. package/dist/meetings/index.js.map +1 -1
  56. package/dist/member/index.js +10 -0
  57. package/dist/member/index.js.map +1 -1
  58. package/dist/member/util.js +10 -0
  59. package/dist/member/util.js.map +1 -1
  60. package/dist/metrics/constants.js +2 -1
  61. package/dist/metrics/constants.js.map +1 -1
  62. package/dist/multistream/mediaRequestManager.js +1 -1
  63. package/dist/multistream/mediaRequestManager.js.map +1 -1
  64. package/dist/multistream/remoteMediaManager.js +11 -0
  65. package/dist/multistream/remoteMediaManager.js.map +1 -1
  66. package/dist/reactions/reactions.type.js.map +1 -1
  67. package/dist/types/aiEnableRequest/index.d.ts +5 -0
  68. package/dist/types/aiEnableRequest/utils.d.ts +2 -0
  69. package/dist/types/config.d.ts +3 -0
  70. package/dist/types/constants.d.ts +21 -1
  71. package/dist/types/hashTree/constants.d.ts +1 -0
  72. package/dist/types/hashTree/hashTree.d.ts +7 -0
  73. package/dist/types/hashTree/hashTreeParser.d.ts +99 -14
  74. package/dist/types/hashTree/types.d.ts +3 -0
  75. package/dist/types/hashTree/utils.d.ts +6 -0
  76. package/dist/types/index.d.ts +1 -0
  77. package/dist/types/interceptors/constant.d.ts +5 -0
  78. package/dist/types/interceptors/dataChannelAuthToken.d.ts +35 -0
  79. package/dist/types/interceptors/index.d.ts +2 -1
  80. package/dist/types/locus-info/index.d.ts +9 -2
  81. package/dist/types/locus-info/types.d.ts +1 -0
  82. package/dist/types/media/MediaConnectionAwaiter.d.ts +10 -1
  83. package/dist/types/media/properties.d.ts +2 -1
  84. package/dist/types/meeting/in-meeting-actions.d.ts +6 -0
  85. package/dist/types/meeting/index.d.ts +24 -2
  86. package/dist/types/meeting/request.d.ts +16 -1
  87. package/dist/types/meeting/request.type.d.ts +5 -0
  88. package/dist/types/meeting/util.d.ts +31 -0
  89. package/dist/types/meetings/index.d.ts +4 -2
  90. package/dist/types/member/index.d.ts +1 -0
  91. package/dist/types/member/util.d.ts +5 -0
  92. package/dist/types/metrics/constants.d.ts +1 -0
  93. package/dist/types/reactions/reactions.type.d.ts +1 -0
  94. package/dist/webinar/index.js +1 -1
  95. package/package.json +22 -22
  96. package/src/aiEnableRequest/README.md +84 -0
  97. package/src/aiEnableRequest/index.ts +170 -0
  98. package/src/aiEnableRequest/utils.ts +25 -0
  99. package/src/annotation/index.ts +7 -4
  100. package/src/config.ts +3 -0
  101. package/src/constants.ts +26 -1
  102. package/src/hashTree/constants.ts +1 -0
  103. package/src/hashTree/hashTree.ts +17 -0
  104. package/src/hashTree/hashTreeParser.ts +627 -249
  105. package/src/hashTree/types.ts +4 -0
  106. package/src/hashTree/utils.ts +9 -0
  107. package/src/index.ts +8 -1
  108. package/src/interceptors/constant.ts +6 -0
  109. package/src/interceptors/dataChannelAuthToken.ts +142 -0
  110. package/src/interceptors/index.ts +2 -1
  111. package/src/interpretation/index.ts +2 -2
  112. package/src/locus-info/controlsUtils.ts +11 -0
  113. package/src/locus-info/index.ts +146 -58
  114. package/src/locus-info/selfUtils.ts +1 -0
  115. package/src/locus-info/types.ts +1 -0
  116. package/src/media/MediaConnectionAwaiter.ts +41 -1
  117. package/src/media/properties.ts +3 -1
  118. package/src/meeting/in-meeting-actions.ts +12 -0
  119. package/src/meeting/index.ts +127 -17
  120. package/src/meeting/request.ts +42 -0
  121. package/src/meeting/request.type.ts +6 -0
  122. package/src/meeting/util.ts +156 -1
  123. package/src/meetings/index.ts +94 -9
  124. package/src/member/index.ts +10 -0
  125. package/src/member/util.ts +12 -0
  126. package/src/metrics/constants.ts +1 -0
  127. package/src/multistream/mediaRequestManager.ts +1 -1
  128. package/src/multistream/remoteMediaManager.ts +13 -0
  129. package/src/reactions/reactions.type.ts +1 -0
  130. package/test/unit/spec/aiEnableRequest/index.ts +981 -0
  131. package/test/unit/spec/aiEnableRequest/utils.ts +130 -0
  132. package/test/unit/spec/hashTree/hashTree.ts +66 -0
  133. package/test/unit/spec/hashTree/hashTreeParser.ts +1869 -189
  134. package/test/unit/spec/interceptors/dataChannelAuthToken.ts +141 -0
  135. package/test/unit/spec/locus-info/controlsUtils.js +29 -0
  136. package/test/unit/spec/locus-info/index.js +201 -45
  137. package/test/unit/spec/media/MediaConnectionAwaiter.ts +41 -1
  138. package/test/unit/spec/media/properties.ts +12 -3
  139. package/test/unit/spec/meeting/in-meeting-actions.ts +8 -2
  140. package/test/unit/spec/meeting/index.js +441 -75
  141. package/test/unit/spec/meeting/request.js +64 -0
  142. package/test/unit/spec/meeting/utils.js +433 -22
  143. package/test/unit/spec/meetings/index.js +550 -10
  144. package/test/unit/spec/member/index.js +28 -4
  145. package/test/unit/spec/member/util.js +65 -27
  146. package/test/unit/spec/multistream/remoteMediaManager.ts +30 -0
@@ -10,6 +10,8 @@ export const ObjectType = {
10
10
  fullState: 'fullstate',
11
11
  links: 'links',
12
12
  control: 'controlentry',
13
+ metadata: 'metadata',
14
+ embeddedApp: 'embeddedapp',
13
15
  } as const;
14
16
 
15
17
  export type ObjectType = Enum<typeof ObjectType>;
@@ -23,7 +25,9 @@ export const ObjectTypeToLocusKeyMap = {
23
25
  [ObjectType.participant]: 'participants', // note: each object is a single participant in participants array
24
26
  [ObjectType.mediaShare]: 'mediaShares', // note: each object is a single mediaShare in mediaShares array
25
27
  [ObjectType.control]: 'controls', // note: each object is a single control entry in controls object
28
+ [ObjectType.embeddedApp]: 'embeddedApps', // note: each object is a single embedded app in embeddedApps array
26
29
  };
30
+
27
31
  export interface HtMeta {
28
32
  elementId: {
29
33
  type: ObjectType;
@@ -11,6 +11,15 @@ export function isSelf(object: HashTreeObject) {
11
11
  return object.htMeta.elementId.type.toLowerCase() === ObjectType.self;
12
12
  }
13
13
 
14
+ /**
15
+ * Checks if the given hash tree object is of type "Metadata"
16
+ * @param {HashTreeObject} object object to check
17
+ * @returns {boolean} True if the object is of type "Metadata", false otherwise
18
+ */
19
+ export function isMetadata(object: HashTreeObject) {
20
+ return object.htMeta.elementId.type.toLowerCase() === ObjectType.metadata;
21
+ }
22
+
14
23
  /**
15
24
  * Analyzes given part of Locus DTO recursively and delete any nested objects that have their own htMeta
16
25
  *
package/src/index.ts CHANGED
@@ -3,7 +3,11 @@ import {registerPlugin} from '@webex/webex-core';
3
3
 
4
4
  import Meetings from './meetings';
5
5
  import config from './config';
6
- import {LocusRetryStatusInterceptor, LocusRouteTokenInterceptor} from './interceptors';
6
+ import {
7
+ LocusRetryStatusInterceptor,
8
+ LocusRouteTokenInterceptor,
9
+ DataChannelAuthTokenInterceptor,
10
+ } from './interceptors';
7
11
  import CaptchaError from './common/errors/captcha-error';
8
12
  import IntentToJoinError from './common/errors/intent-to-join';
9
13
  import PasswordError from './common/errors/password-error';
@@ -25,6 +29,7 @@ registerPlugin('meetings', Meetings, {
25
29
  interceptors: {
26
30
  LocusRetryStatusInterceptor: LocusRetryStatusInterceptor.create,
27
31
  LocusRouteTokenInterceptor: LocusRouteTokenInterceptor.create,
32
+ DataChannelAuthTokenInterceptor: DataChannelAuthTokenInterceptor.create,
28
33
  },
29
34
  });
30
35
 
@@ -80,3 +85,5 @@ export {
80
85
  export {RemoteMedia} from './multistream/remoteMedia';
81
86
 
82
87
  export {default as TriggerProxy} from './common/events/trigger-proxy';
88
+
89
+ export {getAIEnablementApprover} from './aiEnableRequest/utils';
@@ -0,0 +1,6 @@
1
+ const DATA_CHANNEL_AUTH_HEADER = 'Data-Channel-Auth-Token';
2
+ const MAX_RETRY = 1;
3
+ const RETRY_INTERVAL = 2000;
4
+ const RETRY_KEY = '_dcRetryKey';
5
+
6
+ export {DATA_CHANNEL_AUTH_HEADER, MAX_RETRY, RETRY_INTERVAL, RETRY_KEY};
@@ -0,0 +1,142 @@
1
+ /*!
2
+ * Copyright (c) 2015-2026 Cisco Systems, Inc. See LICENSE file.
3
+ */
4
+
5
+ import {Interceptor} from '@webex/http-core';
6
+ import LoggerProxy from '../common/logs/logger-proxy';
7
+ import {DATA_CHANNEL_AUTH_HEADER, MAX_RETRY, RETRY_INTERVAL, RETRY_KEY} from './constant';
8
+
9
+ /*!
10
+ * Copyright (c) 2015-2026 Cisco Systems, Inc. See LICENSE file.
11
+ */
12
+
13
+ const retryCountMap = new Map();
14
+ interface HttpLikeError extends Error {
15
+ statusCode?: number;
16
+ original?: any;
17
+ }
18
+ /**
19
+ * @class
20
+ */
21
+ export default class DataChannelAuthTokenInterceptor extends Interceptor {
22
+ private _refreshDataChannelToken: () => Promise<string>;
23
+ private _isDataChannelTokenEnabled: () => Promise<boolean>;
24
+ constructor(options) {
25
+ super(options);
26
+
27
+ this._refreshDataChannelToken = options.refreshDataChannelToken;
28
+ this._isDataChannelTokenEnabled = options.isDataChannelTokenEnabled;
29
+ }
30
+
31
+ /**
32
+ * @returns {DataChannelAuthTokenInterceptor}
33
+ */
34
+ static create() {
35
+ // @ts-ignore
36
+ return new DataChannelAuthTokenInterceptor({
37
+ webex: this,
38
+
39
+ isDataChannelTokenEnabled: async () => {
40
+ // @ts-ignore
41
+ return this.internal.llm.isDataChannelTokenEnabled();
42
+ },
43
+
44
+ refreshDataChannelToken: async () => {
45
+ // @ts-ignore
46
+ const {body} = await this.internal.llm.refreshDataChannelToken();
47
+ const {datachannelToken, dataChannelTokenType} = body ?? {};
48
+
49
+ // @ts-ignore
50
+ this.internal.llm.setDatachannelToken(datachannelToken, dataChannelTokenType);
51
+
52
+ return datachannelToken;
53
+ },
54
+ });
55
+ }
56
+
57
+ private getRetryKey(options) {
58
+ if (!options[RETRY_KEY]) {
59
+ options[RETRY_KEY] = `${Date.now()}-${Math.random()}`;
60
+ }
61
+
62
+ return options[RETRY_KEY];
63
+ }
64
+
65
+ // Helper function to get header value case insensitively
66
+ private getHeader(headers: Record<string, string>, name: string) {
67
+ const key = Object.keys(headers).find((k) => k.toLowerCase() === name.toLowerCase());
68
+
69
+ return key ? headers[key] : undefined;
70
+ }
71
+
72
+ /**
73
+ * Intercept responses and, on 401/403 with `Data-Channel-Auth-Token` header,
74
+ * attempt to refresh the data channel token and retry the original request once.
75
+ *
76
+ * @param {Object} options
77
+ * @param {Object} reason
78
+ * @returns {Promise<HttpResponse>}
79
+ */
80
+ async onResponseError(options, reason) {
81
+ const token = this.getHeader(options.headers, DATA_CHANNEL_AUTH_HEADER);
82
+ const enabled = await this._isDataChannelTokenEnabled();
83
+
84
+ if (!token || !enabled) {
85
+ return Promise.reject(reason);
86
+ }
87
+
88
+ if (reason.statusCode !== 401 && reason.statusCode !== 403) {
89
+ return Promise.reject(reason);
90
+ }
91
+
92
+ const key = this.getRetryKey(options);
93
+ const retryCount = retryCountMap.get(key) || 0;
94
+
95
+ if (retryCount >= MAX_RETRY) {
96
+ LoggerProxy.logger.error(`data channel token refresh exceeded max retry (${MAX_RETRY})`);
97
+ retryCountMap.delete(key);
98
+
99
+ return Promise.reject(reason);
100
+ }
101
+
102
+ retryCountMap.set(key, retryCount + 1);
103
+
104
+ return this.refreshTokenAndRetryWithDelay(options);
105
+ }
106
+
107
+ /**
108
+ * Retry the failed data channel request after a delay.
109
+ * Refreshes the Data-Channel-Auth-Token and re-sends the original request.
110
+ *
111
+ * @param {Object} options - Original request options.
112
+ * @returns {Promise<HttpResponse>} - Resolves on successful retry.
113
+ */
114
+ refreshTokenAndRetryWithDelay(options) {
115
+ return new Promise((resolve, reject) => {
116
+ setTimeout(async () => {
117
+ const key = this.getRetryKey(options);
118
+ try {
119
+ const newToken = await this._refreshDataChannelToken();
120
+
121
+ options.headers[DATA_CHANNEL_AUTH_HEADER] = newToken;
122
+
123
+ // @ts-ignore
124
+ const res = await this.webex.request(options);
125
+ retryCountMap.delete(key);
126
+
127
+ resolve(res);
128
+ } catch (e) {
129
+ retryCountMap.delete(key);
130
+
131
+ const msg = e?.message || String(e);
132
+
133
+ const err: HttpLikeError = new Error(`DataChannel token refresh failed: ${msg}`);
134
+ err.statusCode = e?.statusCode;
135
+ err.original = e;
136
+
137
+ reject(err);
138
+ }
139
+ }, RETRY_INTERVAL);
140
+ });
141
+ }
142
+ }
@@ -1,4 +1,5 @@
1
1
  import LocusRetryStatusInterceptor from './locusRetry';
2
2
  import LocusRouteTokenInterceptor from './locusRouteToken';
3
+ import DataChannelAuthTokenInterceptor from './dataChannelAuthToken';
3
4
 
4
- export {LocusRetryStatusInterceptor, LocusRouteTokenInterceptor};
5
+ export {LocusRetryStatusInterceptor, LocusRouteTokenInterceptor, DataChannelAuthTokenInterceptor};
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import {WebexPlugin} from '@webex/webex-core';
5
5
  import LoggerProxy from '../common/logs/logger-proxy';
6
- import {HTTP_VERBS, INTERPRETATION, MEETINGS} from '../constants';
6
+ import {HTTP_VERBS, INTERPRETATION, LOCUSEVENT, MEETINGS} from '../constants';
7
7
 
8
8
  import SILanguageCollection from './collection';
9
9
 
@@ -230,7 +230,7 @@ const SimultaneousInterpretation = WebexPlugin.extend({
230
230
  * @returns {void}
231
231
  */
232
232
  listenToHandoffRequests() {
233
- this.listenTo(this.webex.internal.mercury, 'event:locus.approval_request', (event) => {
233
+ this.listenTo(this.webex.internal.mercury, `event:${LOCUSEVENT.APPROVAL_REQUEST}`, (event) => {
234
234
  if (event?.data?.approval?.resourceType === INTERPRETATION.RESOURCE_TYPE) {
235
235
  const {receivers, initiator, actionType, url} = event.data.approval;
236
236
  const receiverId = receivers?.[0]?.participantId;
@@ -42,6 +42,7 @@ ControlsUtils.parse = (controls: any) => {
42
42
  caption: controls.transcribe.caption,
43
43
  spokenLanguage: controls.transcribe.spokenLanguage,
44
44
  hesiodLlmId: controls.transcribe.hesiodLlmId,
45
+ aiSummaryNotification: controls.transcribe.aiSummaryNotification,
45
46
  };
46
47
  }
47
48
 
@@ -208,6 +209,16 @@ ControlsUtils.getControls = (oldControls: any, newControls: any) => {
208
209
  !isEqual(previous?.transcribe?.hesiodLlmId, current?.transcribe?.hesiodLlmId) &&
209
210
  !!(previous?.transcribe?.hesiodLlmId || current?.transcribe?.hesiodLlmId),
210
211
 
212
+ hasAiSummaryNotificationChanged:
213
+ current?.transcribe &&
214
+ !isEqual(
215
+ previous?.transcribe?.aiSummaryNotification,
216
+ current?.transcribe?.aiSummaryNotification
217
+ ) &&
218
+ !!(
219
+ previous?.transcribe?.aiSummaryNotification || current?.transcribe?.aiSummaryNotification
220
+ ),
221
+
211
222
  hasTranscribeSpokenLanguageChanged:
212
223
  current?.transcribe &&
213
224
  !isEqual(previous?.transcribe?.spokenLanguage, current?.transcribe?.spokenLanguage) &&