@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.
- package/dist/aiEnableRequest/index.js +184 -0
- package/dist/aiEnableRequest/index.js.map +1 -0
- package/dist/aiEnableRequest/utils.js +36 -0
- package/dist/aiEnableRequest/utils.js.map +1 -0
- package/dist/annotation/index.js +3 -3
- package/dist/annotation/index.js.map +1 -1
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/config.js +5 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.js +26 -6
- package/dist/constants.js.map +1 -1
- package/dist/hashTree/constants.js +3 -1
- package/dist/hashTree/constants.js.map +1 -1
- package/dist/hashTree/hashTree.js +18 -0
- package/dist/hashTree/hashTree.js.map +1 -1
- package/dist/hashTree/hashTreeParser.js +709 -380
- package/dist/hashTree/hashTreeParser.js.map +1 -1
- package/dist/hashTree/types.js +4 -2
- package/dist/hashTree/types.js.map +1 -1
- package/dist/hashTree/utils.js +10 -0
- package/dist/hashTree/utils.js.map +1 -1
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -1
- package/dist/interceptors/constant.js +12 -0
- package/dist/interceptors/constant.js.map +1 -0
- package/dist/interceptors/dataChannelAuthToken.js +233 -0
- package/dist/interceptors/dataChannelAuthToken.js.map +1 -0
- package/dist/interceptors/index.js +7 -0
- package/dist/interceptors/index.js.map +1 -1
- package/dist/interpretation/index.js +2 -2
- package/dist/interpretation/index.js.map +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.js +5 -3
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +125 -68
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/selfUtils.js +1 -0
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/locus-info/types.js.map +1 -1
- package/dist/media/MediaConnectionAwaiter.js +57 -1
- package/dist/media/MediaConnectionAwaiter.js.map +1 -1
- package/dist/media/properties.js +4 -2
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +7 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +209 -90
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/request.js +50 -0
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/request.type.js.map +1 -1
- package/dist/meeting/util.js +128 -2
- package/dist/meeting/util.js.map +1 -1
- package/dist/meetings/index.js +78 -36
- package/dist/meetings/index.js.map +1 -1
- package/dist/member/index.js +10 -0
- package/dist/member/index.js.map +1 -1
- package/dist/member/util.js +10 -0
- package/dist/member/util.js.map +1 -1
- package/dist/metrics/constants.js +2 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +1 -1
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +11 -0
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/reactions/reactions.type.js.map +1 -1
- package/dist/types/aiEnableRequest/index.d.ts +5 -0
- package/dist/types/aiEnableRequest/utils.d.ts +2 -0
- package/dist/types/config.d.ts +3 -0
- package/dist/types/constants.d.ts +21 -1
- package/dist/types/hashTree/constants.d.ts +1 -0
- package/dist/types/hashTree/hashTree.d.ts +7 -0
- package/dist/types/hashTree/hashTreeParser.d.ts +99 -14
- package/dist/types/hashTree/types.d.ts +3 -0
- package/dist/types/hashTree/utils.d.ts +6 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/interceptors/constant.d.ts +5 -0
- package/dist/types/interceptors/dataChannelAuthToken.d.ts +35 -0
- package/dist/types/interceptors/index.d.ts +2 -1
- package/dist/types/locus-info/index.d.ts +9 -2
- package/dist/types/locus-info/types.d.ts +1 -0
- package/dist/types/media/MediaConnectionAwaiter.d.ts +10 -1
- package/dist/types/media/properties.d.ts +2 -1
- package/dist/types/meeting/in-meeting-actions.d.ts +6 -0
- package/dist/types/meeting/index.d.ts +24 -2
- package/dist/types/meeting/request.d.ts +16 -1
- package/dist/types/meeting/request.type.d.ts +5 -0
- package/dist/types/meeting/util.d.ts +31 -0
- package/dist/types/meetings/index.d.ts +4 -2
- package/dist/types/member/index.d.ts +1 -0
- package/dist/types/member/util.d.ts +5 -0
- package/dist/types/metrics/constants.d.ts +1 -0
- package/dist/types/reactions/reactions.type.d.ts +1 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +22 -22
- package/src/aiEnableRequest/README.md +84 -0
- package/src/aiEnableRequest/index.ts +170 -0
- package/src/aiEnableRequest/utils.ts +25 -0
- package/src/annotation/index.ts +7 -4
- package/src/config.ts +3 -0
- package/src/constants.ts +26 -1
- package/src/hashTree/constants.ts +1 -0
- package/src/hashTree/hashTree.ts +17 -0
- package/src/hashTree/hashTreeParser.ts +627 -249
- package/src/hashTree/types.ts +4 -0
- package/src/hashTree/utils.ts +9 -0
- package/src/index.ts +8 -1
- package/src/interceptors/constant.ts +6 -0
- package/src/interceptors/dataChannelAuthToken.ts +142 -0
- package/src/interceptors/index.ts +2 -1
- package/src/interpretation/index.ts +2 -2
- package/src/locus-info/controlsUtils.ts +11 -0
- package/src/locus-info/index.ts +146 -58
- package/src/locus-info/selfUtils.ts +1 -0
- package/src/locus-info/types.ts +1 -0
- package/src/media/MediaConnectionAwaiter.ts +41 -1
- package/src/media/properties.ts +3 -1
- package/src/meeting/in-meeting-actions.ts +12 -0
- package/src/meeting/index.ts +127 -17
- package/src/meeting/request.ts +42 -0
- package/src/meeting/request.type.ts +6 -0
- package/src/meeting/util.ts +156 -1
- package/src/meetings/index.ts +94 -9
- package/src/member/index.ts +10 -0
- package/src/member/util.ts +12 -0
- package/src/metrics/constants.ts +1 -0
- package/src/multistream/mediaRequestManager.ts +1 -1
- package/src/multistream/remoteMediaManager.ts +13 -0
- package/src/reactions/reactions.type.ts +1 -0
- package/test/unit/spec/aiEnableRequest/index.ts +981 -0
- package/test/unit/spec/aiEnableRequest/utils.ts +130 -0
- package/test/unit/spec/hashTree/hashTree.ts +66 -0
- package/test/unit/spec/hashTree/hashTreeParser.ts +1869 -189
- package/test/unit/spec/interceptors/dataChannelAuthToken.ts +141 -0
- package/test/unit/spec/locus-info/controlsUtils.js +29 -0
- package/test/unit/spec/locus-info/index.js +201 -45
- package/test/unit/spec/media/MediaConnectionAwaiter.ts +41 -1
- package/test/unit/spec/media/properties.ts +12 -3
- package/test/unit/spec/meeting/in-meeting-actions.ts +8 -2
- package/test/unit/spec/meeting/index.js +441 -75
- package/test/unit/spec/meeting/request.js +64 -0
- package/test/unit/spec/meeting/utils.js +433 -22
- package/test/unit/spec/meetings/index.js +550 -10
- package/test/unit/spec/member/index.js +28 -4
- package/test/unit/spec/member/util.js +65 -27
- package/test/unit/spec/multistream/remoteMediaManager.ts +30 -0
package/src/hashTree/types.ts
CHANGED
|
@@ -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;
|
package/src/hashTree/utils.ts
CHANGED
|
@@ -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 {
|
|
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,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,
|
|
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) &&
|