@webex/plugin-meetings 3.12.0-next.9 → 3.12.0-task-refactor.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/annotation/index.js +5 -14
- 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 +2 -8
- package/dist/config.js.map +1 -1
- package/dist/constants.js +6 -29
- package/dist/constants.js.map +1 -1
- package/dist/hashTree/hashTreeParser.js +29 -1563
- package/dist/hashTree/hashTreeParser.js.map +1 -1
- package/dist/hashTree/types.js +3 -13
- package/dist/hashTree/types.js.map +1 -1
- package/dist/index.js +2 -11
- package/dist/index.js.map +1 -1
- package/dist/interceptors/index.js +0 -7
- package/dist/interceptors/index.js.map +1 -1
- package/dist/interceptors/locusRouteToken.js +5 -27
- package/dist/interceptors/locusRouteToken.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 +3 -7
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +247 -642
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/selfUtils.js +0 -1
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/locus-info/types.js.map +1 -1
- package/dist/media/MediaConnectionAwaiter.js +1 -57
- package/dist/media/MediaConnectionAwaiter.js.map +1 -1
- package/dist/media/properties.js +2 -4
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +1 -7
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +1036 -1481
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/request.js +0 -50
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/request.type.js.map +1 -1
- package/dist/meeting/util.js +3 -133
- package/dist/meeting/util.js.map +1 -1
- package/dist/meetings/index.js +59 -142
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/util.js +7 -11
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.js +0 -10
- package/dist/member/index.js.map +1 -1
- package/dist/member/util.js +0 -10
- package/dist/member/util.js.map +1 -1
- package/dist/metrics/constants.js +1 -7
- package/dist/metrics/constants.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +60 -9
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +0 -11
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/multistream/sendSlotManager.js +2 -116
- package/dist/multistream/sendSlotManager.js.map +1 -1
- package/dist/reachability/clusterReachability.js +18 -171
- package/dist/reachability/clusterReachability.js.map +1 -1
- package/dist/reachability/index.js +11 -21
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/reachabilityPeerConnection.js +1 -1
- package/dist/reachability/reachabilityPeerConnection.js.map +1 -1
- package/dist/reactions/reactions.type.js.map +1 -1
- package/dist/reconnection-manager/index.js +1 -0
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/types/common/browser-detection.d.ts +0 -1
- package/dist/types/common/events/events-scope.d.ts +0 -1
- package/dist/types/common/events/events.d.ts +0 -1
- package/dist/types/config.d.ts +0 -5
- package/dist/types/constants.d.ts +1 -24
- package/dist/types/hashTree/hashTreeParser.d.ts +11 -260
- package/dist/types/hashTree/types.d.ts +0 -20
- package/dist/types/index.d.ts +0 -1
- package/dist/types/interceptors/index.d.ts +1 -2
- package/dist/types/interceptors/locusRouteToken.d.ts +0 -2
- package/dist/types/locus-info/index.d.ts +47 -68
- package/dist/types/locus-info/types.d.ts +12 -28
- package/dist/types/media/MediaConnectionAwaiter.d.ts +1 -10
- package/dist/types/media/properties.d.ts +1 -2
- package/dist/types/meeting/in-meeting-actions.d.ts +0 -6
- package/dist/types/meeting/index.d.ts +7 -86
- package/dist/types/meeting/request.d.ts +1 -16
- package/dist/types/meeting/request.type.d.ts +0 -5
- package/dist/types/meeting/util.d.ts +0 -31
- package/dist/types/meeting-info/util.d.ts +0 -1
- package/dist/types/meeting-info/utilv2.d.ts +0 -1
- package/dist/types/meetings/index.d.ts +2 -4
- package/dist/types/member/index.d.ts +0 -1
- package/dist/types/member/types.d.ts +4 -4
- package/dist/types/member/util.d.ts +0 -5
- package/dist/types/metrics/constants.d.ts +0 -6
- package/dist/types/multistream/mediaRequestManager.d.ts +23 -0
- package/dist/types/multistream/sendSlotManager.d.ts +1 -23
- package/dist/types/reachability/clusterReachability.d.ts +3 -30
- package/dist/types/reactions/reactions.type.d.ts +0 -1
- package/dist/types/recording-controller/util.d.ts +5 -5
- package/dist/types/roap/index.d.ts +1 -1
- package/dist/webinar/index.js +163 -438
- package/dist/webinar/index.js.map +1 -1
- package/package.json +24 -26
- package/src/annotation/index.ts +7 -27
- package/src/config.ts +0 -5
- package/src/constants.ts +1 -30
- package/src/hashTree/hashTreeParser.ts +25 -1523
- package/src/hashTree/types.ts +1 -24
- package/src/index.ts +1 -8
- package/src/interceptors/index.ts +1 -2
- package/src/interceptors/locusRouteToken.ts +5 -22
- package/src/interpretation/index.ts +2 -2
- package/src/locus-info/controlsUtils.ts +0 -17
- package/src/locus-info/index.ts +213 -707
- package/src/locus-info/selfUtils.ts +0 -1
- package/src/locus-info/types.ts +12 -27
- package/src/media/MediaConnectionAwaiter.ts +1 -41
- package/src/media/properties.ts +1 -3
- package/src/meeting/in-meeting-actions.ts +0 -12
- package/src/meeting/index.ts +84 -461
- package/src/meeting/request.ts +0 -42
- package/src/meeting/request.type.ts +0 -6
- package/src/meeting/util.ts +2 -160
- package/src/meetings/index.ts +60 -180
- package/src/meetings/util.ts +9 -10
- package/src/member/index.ts +0 -10
- package/src/member/util.ts +0 -12
- package/src/metrics/constants.ts +0 -7
- package/src/multistream/mediaRequestManager.ts +54 -4
- package/src/multistream/remoteMediaManager.ts +0 -13
- package/src/multistream/sendSlotManager.ts +3 -97
- package/src/reachability/clusterReachability.ts +27 -153
- package/src/reachability/index.ts +1 -15
- package/src/reachability/reachabilityPeerConnection.ts +1 -3
- package/src/reactions/reactions.type.ts +0 -1
- package/src/reconnection-manager/index.ts +1 -0
- package/src/webinar/index.ts +6 -265
- package/test/unit/spec/annotation/index.ts +7 -69
- package/test/unit/spec/interceptors/locusRouteToken.ts +0 -44
- package/test/unit/spec/locus-info/controlsUtils.js +1 -56
- package/test/unit/spec/locus-info/index.js +90 -1457
- package/test/unit/spec/media/MediaConnectionAwaiter.ts +1 -41
- package/test/unit/spec/media/properties.ts +3 -12
- package/test/unit/spec/meeting/in-meeting-actions.ts +2 -8
- package/test/unit/spec/meeting/index.js +128 -981
- package/test/unit/spec/meeting/request.js +0 -70
- package/test/unit/spec/meeting/utils.js +26 -438
- package/test/unit/spec/meetings/index.js +33 -845
- package/test/unit/spec/meetings/utils.js +1 -51
- package/test/unit/spec/member/index.js +4 -28
- package/test/unit/spec/member/util.js +27 -65
- package/test/unit/spec/multistream/mediaRequestManager.ts +85 -2
- package/test/unit/spec/multistream/remoteMediaManager.ts +0 -30
- package/test/unit/spec/multistream/sendSlotManager.ts +36 -135
- package/test/unit/spec/reachability/clusterReachability.ts +1 -125
- package/test/unit/spec/reachability/index.ts +3 -26
- package/test/unit/spec/reconnection-manager/index.js +8 -4
- package/test/unit/spec/webinar/index.ts +37 -534
- package/dist/aiEnableRequest/index.js +0 -184
- package/dist/aiEnableRequest/index.js.map +0 -1
- package/dist/aiEnableRequest/utils.js +0 -36
- package/dist/aiEnableRequest/utils.js.map +0 -1
- package/dist/hashTree/constants.js +0 -22
- package/dist/hashTree/constants.js.map +0 -1
- package/dist/hashTree/hashTree.js +0 -533
- package/dist/hashTree/hashTree.js.map +0 -1
- package/dist/hashTree/utils.js +0 -69
- package/dist/hashTree/utils.js.map +0 -1
- package/dist/interceptors/constant.js +0 -12
- package/dist/interceptors/constant.js.map +0 -1
- package/dist/interceptors/dataChannelAuthToken.js +0 -290
- package/dist/interceptors/dataChannelAuthToken.js.map +0 -1
- package/dist/interceptors/utils.js +0 -27
- package/dist/interceptors/utils.js.map +0 -1
- package/dist/types/aiEnableRequest/index.d.ts +0 -5
- package/dist/types/aiEnableRequest/utils.d.ts +0 -2
- package/dist/types/hashTree/constants.d.ts +0 -9
- package/dist/types/hashTree/hashTree.d.ts +0 -136
- package/dist/types/hashTree/utils.d.ts +0 -22
- package/dist/types/interceptors/constant.d.ts +0 -5
- package/dist/types/interceptors/dataChannelAuthToken.d.ts +0 -43
- package/dist/types/interceptors/utils.d.ts +0 -1
- package/dist/types/webinar/utils.d.ts +0 -6
- package/dist/webinar/utils.js +0 -25
- package/dist/webinar/utils.js.map +0 -1
- package/src/aiEnableRequest/README.md +0 -84
- package/src/aiEnableRequest/index.ts +0 -170
- package/src/aiEnableRequest/utils.ts +0 -25
- package/src/hashTree/constants.ts +0 -10
- package/src/hashTree/hashTree.ts +0 -480
- package/src/hashTree/utils.ts +0 -62
- package/src/interceptors/constant.ts +0 -6
- package/src/interceptors/dataChannelAuthToken.ts +0 -170
- package/src/interceptors/utils.ts +0 -16
- package/src/webinar/utils.ts +0 -16
- package/test/unit/spec/aiEnableRequest/index.ts +0 -981
- package/test/unit/spec/aiEnableRequest/utils.ts +0 -130
- package/test/unit/spec/hashTree/hashTree.ts +0 -721
- package/test/unit/spec/hashTree/hashTreeParser.ts +0 -3670
- package/test/unit/spec/hashTree/utils.ts +0 -140
- package/test/unit/spec/interceptors/dataChannelAuthToken.ts +0 -210
- package/test/unit/spec/interceptors/utils.ts +0 -75
- package/test/unit/spec/webinar/utils.ts +0 -39
package/src/webinar/index.ts
CHANGED
|
@@ -4,21 +4,10 @@
|
|
|
4
4
|
import {WebexPlugin, config} from '@webex/webex-core';
|
|
5
5
|
import uuid from 'uuid';
|
|
6
6
|
import {get} from 'lodash';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
_ID_,
|
|
10
|
-
HEADERS,
|
|
11
|
-
HTTP_VERBS,
|
|
12
|
-
MEETINGS,
|
|
13
|
-
SELF_ROLES,
|
|
14
|
-
SHARE_STATUS,
|
|
15
|
-
DEFAULT_LARGE_SCALE_WEBINAR_ATTENDEE_SEARCH_LIMIT,
|
|
16
|
-
LLM_PRACTICE_SESSION,
|
|
17
|
-
} from '../constants';
|
|
7
|
+
import {_ID_, HEADERS, HTTP_VERBS, MEETINGS, SELF_ROLES, SHARE_STATUS} from '../constants';
|
|
18
8
|
|
|
19
9
|
import WebinarCollection from './collection';
|
|
20
10
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
21
|
-
import {sanitizeParams} from './utils';
|
|
22
11
|
|
|
23
12
|
/**
|
|
24
13
|
* @class Webinar
|
|
@@ -39,14 +28,6 @@ const Webinar = WebexPlugin.extend({
|
|
|
39
28
|
meetingId: 'string',
|
|
40
29
|
},
|
|
41
30
|
|
|
42
|
-
/**
|
|
43
|
-
* Calls this to clean up listeners
|
|
44
|
-
* @returns {void}
|
|
45
|
-
*/
|
|
46
|
-
cleanUp() {
|
|
47
|
-
this.cleanupPSDataChannel();
|
|
48
|
-
},
|
|
49
|
-
|
|
50
31
|
/**
|
|
51
32
|
* Update the current locus url of the webinar
|
|
52
33
|
* @param {string} locusUrl
|
|
@@ -115,7 +96,10 @@ const Webinar = WebexPlugin.extend({
|
|
|
115
96
|
meeting?.locusInfo?.updateMediaShares(meeting?.locusInfo?.mediaShares, true);
|
|
116
97
|
}
|
|
117
98
|
|
|
118
|
-
this.
|
|
99
|
+
if (this.practiceSessionEnabled) {
|
|
100
|
+
// may need change data channel in practice session
|
|
101
|
+
meeting?.updateLLMConnection();
|
|
102
|
+
}
|
|
119
103
|
},
|
|
120
104
|
|
|
121
105
|
/**
|
|
@@ -126,215 +110,6 @@ const Webinar = WebexPlugin.extend({
|
|
|
126
110
|
return this.selfIsPanelist && this.practiceSessionEnabled;
|
|
127
111
|
},
|
|
128
112
|
|
|
129
|
-
/**
|
|
130
|
-
* Disconnects the practice session data channel and removes its relay listener.
|
|
131
|
-
* @returns {Promise<void>}
|
|
132
|
-
*/
|
|
133
|
-
async cleanupPSDataChannel() {
|
|
134
|
-
if (this._pendingOnlineListener) {
|
|
135
|
-
// @ts-ignore - Fix type
|
|
136
|
-
this.webex.internal.llm.off('online', this._pendingOnlineListener);
|
|
137
|
-
this._pendingOnlineListener = null;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const meeting = this.webex.meetings.getMeetingByType(_ID_, this.meetingId);
|
|
141
|
-
|
|
142
|
-
// @ts-ignore - Fix type
|
|
143
|
-
await this.webex.internal.llm.disconnectLLM(
|
|
144
|
-
{
|
|
145
|
-
code: 3050,
|
|
146
|
-
reason: 'done (permanent)',
|
|
147
|
-
},
|
|
148
|
-
LLM_PRACTICE_SESSION
|
|
149
|
-
);
|
|
150
|
-
// @ts-ignore - Fix type
|
|
151
|
-
this.webex.internal.llm.off(
|
|
152
|
-
`event:relay.event:${LLM_PRACTICE_SESSION}`,
|
|
153
|
-
meeting?.processRelayEvent
|
|
154
|
-
);
|
|
155
|
-
},
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Ensures practice-session token exists before registering the practice LLM channel.
|
|
159
|
-
* @param {object} meeting
|
|
160
|
-
* @returns {Promise<string|undefined>}
|
|
161
|
-
*/
|
|
162
|
-
async ensurePracticeSessionDatachannelToken(meeting) {
|
|
163
|
-
// @ts-ignore
|
|
164
|
-
const isDataChannelTokenEnabled = await this.webex.internal.llm.isDataChannelTokenEnabled();
|
|
165
|
-
|
|
166
|
-
if (!isDataChannelTokenEnabled) {
|
|
167
|
-
return undefined;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// @ts-ignore
|
|
171
|
-
const cachedToken = this.webex.internal.llm.getDatachannelToken(
|
|
172
|
-
DataChannelTokenType.PracticeSession
|
|
173
|
-
);
|
|
174
|
-
|
|
175
|
-
if (cachedToken) {
|
|
176
|
-
return cachedToken;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
try {
|
|
180
|
-
const refreshResponse = await meeting.refreshDataChannelToken();
|
|
181
|
-
const {datachannelToken, dataChannelTokenType} = refreshResponse?.body ?? {};
|
|
182
|
-
|
|
183
|
-
if (!datachannelToken) {
|
|
184
|
-
return undefined;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// @ts-ignore
|
|
188
|
-
this.webex.internal.llm.setDatachannelToken(
|
|
189
|
-
datachannelToken,
|
|
190
|
-
dataChannelTokenType || DataChannelTokenType.PracticeSession
|
|
191
|
-
);
|
|
192
|
-
|
|
193
|
-
return datachannelToken;
|
|
194
|
-
} catch (error) {
|
|
195
|
-
LoggerProxy.logger.warn(
|
|
196
|
-
`Webinar:index#ensurePracticeSessionDatachannelToken --> failed to proactively refresh practice-session token: ${
|
|
197
|
-
error?.message || String(error)
|
|
198
|
-
}`
|
|
199
|
-
);
|
|
200
|
-
|
|
201
|
-
return undefined;
|
|
202
|
-
}
|
|
203
|
-
},
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Connects to low latency mercury and reconnects if the address has changed
|
|
207
|
-
* It will also disconnect if called when the meeting has ended
|
|
208
|
-
* @returns {Promise}
|
|
209
|
-
*/
|
|
210
|
-
async updatePSDataChannel() {
|
|
211
|
-
this._updatePSDataChannelSequence = (this._updatePSDataChannelSequence || 0) + 1;
|
|
212
|
-
const invocationSequence = this._updatePSDataChannelSequence;
|
|
213
|
-
|
|
214
|
-
const meeting = this.webex.meetings.getMeetingByType(_ID_, this.meetingId);
|
|
215
|
-
const isPracticeSession = meeting?.isJoined() && this.isJoinPracticeSessionDataChannel();
|
|
216
|
-
|
|
217
|
-
if (!isPracticeSession) {
|
|
218
|
-
await this.cleanupPSDataChannel();
|
|
219
|
-
|
|
220
|
-
return undefined;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// @ts-ignore - Fix type
|
|
224
|
-
const {url = undefined, info: {practiceSessionDatachannelUrl = undefined} = {}} =
|
|
225
|
-
meeting?.locusInfo || {};
|
|
226
|
-
|
|
227
|
-
// @ts-ignore
|
|
228
|
-
let practiceSessionDatachannelToken = this.webex.internal.llm.getDatachannelToken(
|
|
229
|
-
DataChannelTokenType.PracticeSession
|
|
230
|
-
);
|
|
231
|
-
|
|
232
|
-
const isCaptionBoxOn = this.webex.internal.voicea.getIsCaptionBoxOn();
|
|
233
|
-
|
|
234
|
-
if (!practiceSessionDatachannelUrl) {
|
|
235
|
-
return undefined;
|
|
236
|
-
}
|
|
237
|
-
// @ts-ignore - Fix type
|
|
238
|
-
if (this.webex.internal.llm.isConnected(LLM_PRACTICE_SESSION)) {
|
|
239
|
-
if (
|
|
240
|
-
// @ts-ignore - Fix type
|
|
241
|
-
url === this.webex.internal.llm.getLocusUrl(LLM_PRACTICE_SESSION) &&
|
|
242
|
-
// @ts-ignore - Fix type
|
|
243
|
-
practiceSessionDatachannelUrl ===
|
|
244
|
-
this.webex.internal.llm.getDatachannelUrl(LLM_PRACTICE_SESSION)
|
|
245
|
-
) {
|
|
246
|
-
return undefined;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
await this.cleanupPSDataChannel();
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// Ensure the default session data channel is connected before connecting the practice session.
|
|
253
|
-
// Subscribe before checking isConnected() to avoid a race where the 'online' event fires
|
|
254
|
-
// between the check and the subscription — Mercury does not replay missed events.
|
|
255
|
-
if (!this._pendingOnlineListener) {
|
|
256
|
-
const onDefaultSessionConnected = () => {
|
|
257
|
-
this._pendingOnlineListener = null;
|
|
258
|
-
// @ts-ignore - Fix type
|
|
259
|
-
this.webex.internal.llm.off('online', onDefaultSessionConnected);
|
|
260
|
-
this.updatePSDataChannel();
|
|
261
|
-
};
|
|
262
|
-
this._pendingOnlineListener = onDefaultSessionConnected;
|
|
263
|
-
// @ts-ignore - Fix type
|
|
264
|
-
this.webex.internal.llm.on('online', onDefaultSessionConnected);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
// @ts-ignore - Fix type
|
|
268
|
-
if (!this.webex.internal.llm.isConnected()) {
|
|
269
|
-
LoggerProxy.logger.info(
|
|
270
|
-
'Webinar:index#updatePSDataChannel --> default session not yet connected, deferring practice session connect.'
|
|
271
|
-
);
|
|
272
|
-
|
|
273
|
-
return undefined;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// Default session is already connected — cancel the pending listener and proceed
|
|
277
|
-
if (this._pendingOnlineListener) {
|
|
278
|
-
// @ts-ignore - Fix type
|
|
279
|
-
this.webex.internal.llm.off('online', this._pendingOnlineListener);
|
|
280
|
-
this._pendingOnlineListener = null;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
const refreshedPracticeSessionToken = await this.ensurePracticeSessionDatachannelToken(meeting);
|
|
284
|
-
|
|
285
|
-
const latestPracticeSessionDatachannelUrl = get(
|
|
286
|
-
meeting,
|
|
287
|
-
'locusInfo.info.practiceSessionDatachannelUrl'
|
|
288
|
-
);
|
|
289
|
-
const isStillPracticeSession = meeting?.isJoined() && this.isJoinPracticeSessionDataChannel();
|
|
290
|
-
|
|
291
|
-
// Skip stale invocations after async refresh to avoid reconnecting a session
|
|
292
|
-
// that was already updated/cleaned by a newer state transition.
|
|
293
|
-
if (
|
|
294
|
-
invocationSequence !== this._updatePSDataChannelSequence ||
|
|
295
|
-
!isStillPracticeSession ||
|
|
296
|
-
!latestPracticeSessionDatachannelUrl ||
|
|
297
|
-
latestPracticeSessionDatachannelUrl !== practiceSessionDatachannelUrl
|
|
298
|
-
) {
|
|
299
|
-
return undefined;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
if (refreshedPracticeSessionToken) {
|
|
303
|
-
practiceSessionDatachannelToken = refreshedPracticeSessionToken;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
// @ts-ignore - Fix type
|
|
307
|
-
return this.webex.internal.llm
|
|
308
|
-
.registerAndConnect(
|
|
309
|
-
url,
|
|
310
|
-
practiceSessionDatachannelUrl,
|
|
311
|
-
practiceSessionDatachannelToken,
|
|
312
|
-
LLM_PRACTICE_SESSION
|
|
313
|
-
)
|
|
314
|
-
.then((registerAndConnectResult) => {
|
|
315
|
-
// @ts-ignore - Fix type
|
|
316
|
-
this.webex.internal.llm.off(
|
|
317
|
-
`event:relay.event:${LLM_PRACTICE_SESSION}`,
|
|
318
|
-
meeting?.processRelayEvent
|
|
319
|
-
);
|
|
320
|
-
// @ts-ignore - Fix type
|
|
321
|
-
this.webex.internal.llm.on(
|
|
322
|
-
`event:relay.event:${LLM_PRACTICE_SESSION}`,
|
|
323
|
-
meeting?.processRelayEvent
|
|
324
|
-
);
|
|
325
|
-
// @ts-ignore - Fix type
|
|
326
|
-
this.webex.internal.voicea?.announce?.();
|
|
327
|
-
if (isCaptionBoxOn) {
|
|
328
|
-
this.webex.internal.voicea.updateSubchannelSubscriptions({subscribe: ['transcription']});
|
|
329
|
-
}
|
|
330
|
-
LoggerProxy.logger.info(
|
|
331
|
-
`Webinar:index#updatePSDataChannel --> enabled to receive relay events for default session for ${LLM_PRACTICE_SESSION}!`
|
|
332
|
-
);
|
|
333
|
-
|
|
334
|
-
return Promise.resolve(registerAndConnectResult);
|
|
335
|
-
});
|
|
336
|
-
},
|
|
337
|
-
|
|
338
113
|
/**
|
|
339
114
|
* start or stop practice session for webinar
|
|
340
115
|
* @param {boolean} enabled
|
|
@@ -362,7 +137,6 @@ const Webinar = WebexPlugin.extend({
|
|
|
362
137
|
*/
|
|
363
138
|
updatePracticeSessionStatus(payload) {
|
|
364
139
|
this.set('practiceSessionEnabled', !!payload?.enabled);
|
|
365
|
-
this.updatePSDataChannel().then(() => {});
|
|
366
140
|
},
|
|
367
141
|
|
|
368
142
|
/**
|
|
@@ -469,6 +243,7 @@ const Webinar = WebexPlugin.extend({
|
|
|
469
243
|
|
|
470
244
|
/**
|
|
471
245
|
* view all webcast attendees
|
|
246
|
+
* @param {string} queryString
|
|
472
247
|
* @returns {Promise}
|
|
473
248
|
*/
|
|
474
249
|
async viewAllWebcastAttendees() {
|
|
@@ -522,40 +297,6 @@ const Webinar = WebexPlugin.extend({
|
|
|
522
297
|
throw error;
|
|
523
298
|
});
|
|
524
299
|
},
|
|
525
|
-
|
|
526
|
-
/**
|
|
527
|
-
* search large scale webinar attendees
|
|
528
|
-
* @param {object} payload
|
|
529
|
-
* @param {string} payload.queryString
|
|
530
|
-
* @param {number} payload.limit
|
|
531
|
-
* @param {string} payload.next
|
|
532
|
-
* @returns {Promise}
|
|
533
|
-
*/
|
|
534
|
-
async searchLargeScaleWebinarAttendees(payload) {
|
|
535
|
-
const meeting = this.webex.meetings.getMeetingByType(_ID_, this.meetingId);
|
|
536
|
-
const rawParams = {
|
|
537
|
-
search_text: payload?.queryString,
|
|
538
|
-
limit: payload?.limit ?? DEFAULT_LARGE_SCALE_WEBINAR_ATTENDEE_SEARCH_LIMIT,
|
|
539
|
-
next: payload?.next,
|
|
540
|
-
};
|
|
541
|
-
const attendeeSearchUrl = meeting?.locusInfo?.links?.resources?.attendeeSearch?.url;
|
|
542
|
-
if (!attendeeSearchUrl) {
|
|
543
|
-
LoggerProxy.logger.error(`Meeting:webinar5k#searchLargeScaleWebinarAttendees failed`);
|
|
544
|
-
throw new Error('Meeting:webinar5k#Attendee search url is not available');
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
return this.request({
|
|
548
|
-
method: HTTP_VERBS.GET,
|
|
549
|
-
uri: `${attendeeSearchUrl}?${new URLSearchParams(sanitizeParams(rawParams)).toString()}`,
|
|
550
|
-
headers: {
|
|
551
|
-
authorization: await this.webex.credentials.getUserToken(),
|
|
552
|
-
trackingId: `${config.trackingIdPrefix}_${uuid.v4().toString()}`,
|
|
553
|
-
},
|
|
554
|
-
}).catch((error) => {
|
|
555
|
-
LoggerProxy.logger.error('Meeting:webinar5k#searchLargeScaleWebinarAttendees failed', error);
|
|
556
|
-
throw error;
|
|
557
|
-
});
|
|
558
|
-
},
|
|
559
300
|
});
|
|
560
301
|
|
|
561
302
|
export default Webinar;
|
|
@@ -7,7 +7,6 @@ import LLMChannel from '@webex/internal-plugin-llm';
|
|
|
7
7
|
|
|
8
8
|
import AnnotationService from '../../../../src/annotation/index';
|
|
9
9
|
import {ANNOTATION_RELAY_TYPES, ANNOTATION_REQUEST_TYPE, EVENT_TRIGGERS} from '../../../../src/annotation/constants';
|
|
10
|
-
import {LLM_PRACTICE_SESSION} from '../../../../src/constants';
|
|
11
10
|
|
|
12
11
|
|
|
13
12
|
describe('live-annotation', () => {
|
|
@@ -29,7 +28,6 @@ describe('live-annotation', () => {
|
|
|
29
28
|
annotationService = webex.internal.annotation;
|
|
30
29
|
annotationService.connect = sinon.stub().resolves(true);
|
|
31
30
|
annotationService.webex.internal.llm.isConnected = sinon.stub().returns(true);
|
|
32
|
-
annotationService.webex.internal.llm.getSocket = sinon.stub().returns(undefined);
|
|
33
31
|
annotationService.webex.internal.llm.getBinding = sinon.stub().returns(undefined);
|
|
34
32
|
annotationService.webex.internal.llm.getLocusUrl = sinon.stub().returns(locusUrl);
|
|
35
33
|
annotationService.approvalUrl = 'url/approval';
|
|
@@ -185,13 +183,7 @@ describe('live-annotation', () => {
|
|
|
185
183
|
|
|
186
184
|
annotationService.listenToEvents();
|
|
187
185
|
|
|
188
|
-
assert.
|
|
189
|
-
assert.calledWithExactly(
|
|
190
|
-
spy.secondCall,
|
|
191
|
-
`event:relay.event:${LLM_PRACTICE_SESSION}`,
|
|
192
|
-
sinon.match.func,
|
|
193
|
-
sinon.match.object
|
|
194
|
-
);
|
|
186
|
+
assert.calledOnceWithExactly(spy, 'event:relay.event', sinon.match.func,sinon.match.object);
|
|
195
187
|
});
|
|
196
188
|
|
|
197
189
|
});
|
|
@@ -234,11 +226,14 @@ describe('live-annotation', () => {
|
|
|
234
226
|
});
|
|
235
227
|
|
|
236
228
|
describe('sendStrokeData', () => {
|
|
237
|
-
let strokeData;
|
|
238
229
|
|
|
239
230
|
beforeEach(async () => {
|
|
240
231
|
annotationService.webex.internal.llm.socket = new MockWebSocket();
|
|
241
|
-
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
it('works on publish Stroke Data', async () => {
|
|
236
|
+
const strokeData = {
|
|
242
237
|
content: {
|
|
243
238
|
"contentsBuffer": [{
|
|
244
239
|
"contentArray": [{
|
|
@@ -254,11 +249,8 @@ describe('live-annotation', () => {
|
|
|
254
249
|
shareInstanceId: '7fa6fe07-dcb1-41ad-973d-7bcf65fab55d',
|
|
255
250
|
encryptionKeyUrl: "encryptionKeyUrl",
|
|
256
251
|
version: '1',
|
|
257
|
-
};
|
|
258
|
-
});
|
|
259
|
-
|
|
252
|
+
} ;
|
|
260
253
|
|
|
261
|
-
it('works on publish Stroke Data', async () => {
|
|
262
254
|
annotationService.publishEncrypted(strokeData.content, strokeData);
|
|
263
255
|
|
|
264
256
|
const sendObject = {
|
|
@@ -291,49 +283,6 @@ describe('live-annotation', () => {
|
|
|
291
283
|
assert.calledOnceWithExactly(annotationService.webex.internal.llm.socket.send, sendObject);
|
|
292
284
|
});
|
|
293
285
|
|
|
294
|
-
it('uses the practice-session socket and binding only when the practice-session session is connected', () => {
|
|
295
|
-
const practiceSocket = new MockWebSocket();
|
|
296
|
-
|
|
297
|
-
annotationService.webex.internal.llm.isConnected.callsFake((sessionId) =>
|
|
298
|
-
sessionId === LLM_PRACTICE_SESSION
|
|
299
|
-
);
|
|
300
|
-
annotationService.webex.internal.llm.getSocket
|
|
301
|
-
.withArgs(LLM_PRACTICE_SESSION)
|
|
302
|
-
.returns(practiceSocket);
|
|
303
|
-
annotationService.webex.internal.llm.getBinding
|
|
304
|
-
.withArgs(LLM_PRACTICE_SESSION)
|
|
305
|
-
.returns('practice-binding');
|
|
306
|
-
|
|
307
|
-
annotationService.publishEncrypted(strokeData.content, strokeData);
|
|
308
|
-
|
|
309
|
-
assert.calledOnce(practiceSocket.send);
|
|
310
|
-
assert.notCalled(annotationService.webex.internal.llm.socket.send);
|
|
311
|
-
|
|
312
|
-
const sent = practiceSocket.send.getCall(0).args[0];
|
|
313
|
-
assert.equal(sent.recipients.route, 'practice-binding');
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
it('falls back to the default socket and binding when the practice-session socket exists but is not connected', () => {
|
|
317
|
-
const practiceSocket = new MockWebSocket();
|
|
318
|
-
|
|
319
|
-
annotationService.webex.internal.llm.isConnected.callsFake((sessionId) => !sessionId);
|
|
320
|
-
annotationService.webex.internal.llm.getSocket
|
|
321
|
-
.withArgs(LLM_PRACTICE_SESSION)
|
|
322
|
-
.returns(practiceSocket);
|
|
323
|
-
annotationService.webex.internal.llm.getBinding
|
|
324
|
-
.withArgs(LLM_PRACTICE_SESSION)
|
|
325
|
-
.returns('practice-binding');
|
|
326
|
-
annotationService.webex.internal.llm.getBinding.returns('default-binding');
|
|
327
|
-
|
|
328
|
-
annotationService.publishEncrypted(strokeData.content, strokeData);
|
|
329
|
-
|
|
330
|
-
assert.notCalled(practiceSocket.send);
|
|
331
|
-
assert.calledOnce(annotationService.webex.internal.llm.socket.send);
|
|
332
|
-
|
|
333
|
-
const sent = annotationService.webex.internal.llm.socket.send.getCall(0).args[0];
|
|
334
|
-
assert.equal(sent.recipients.route, 'default-binding');
|
|
335
|
-
});
|
|
336
|
-
|
|
337
286
|
});
|
|
338
287
|
|
|
339
288
|
|
|
@@ -492,21 +441,10 @@ describe('live-annotation', () => {
|
|
|
492
441
|
annotationService.eventDataProcessor,
|
|
493
442
|
annotationService
|
|
494
443
|
);
|
|
495
|
-
assert.calledWith(
|
|
496
|
-
llmOn,
|
|
497
|
-
`event:relay.event:${LLM_PRACTICE_SESSION}`,
|
|
498
|
-
annotationService.eventDataProcessor,
|
|
499
|
-
annotationService
|
|
500
|
-
);
|
|
501
444
|
assert.match(annotationService.hasSubscribedToEvents, true);
|
|
502
445
|
|
|
503
446
|
annotationService.deregisterEvents();
|
|
504
447
|
assert.calledWith(llmOff, 'event:relay.event', annotationService.eventDataProcessor);
|
|
505
|
-
assert.calledWith(
|
|
506
|
-
llmOff,
|
|
507
|
-
`event:relay.event:${LLM_PRACTICE_SESSION}`,
|
|
508
|
-
annotationService.eventDataProcessor
|
|
509
|
-
);
|
|
510
448
|
assert.calledWith(
|
|
511
449
|
mercuryOff,
|
|
512
450
|
'event:locus.approval_request',
|
|
@@ -54,40 +54,6 @@ describe('LocusRouteTokenInterceptor', () => {
|
|
|
54
54
|
assert.equal(interceptor.getToken(TEST_LOCUS_ID), 'test-token');
|
|
55
55
|
});
|
|
56
56
|
|
|
57
|
-
it('onResponse should store route token when body exists', async () => {
|
|
58
|
-
const response = {
|
|
59
|
-
headers: {
|
|
60
|
-
[X_CISCO_PART_ROUTE_TOKEN]: 'test-token',
|
|
61
|
-
},
|
|
62
|
-
body: {
|
|
63
|
-
locus: {
|
|
64
|
-
url: `https://locus-test.webex.com/locus/api/v1/loci/${TEST_LOCUS_ID}`,
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
const result = await interceptor.onResponse({},response);
|
|
70
|
-
assert.equal(result, response);
|
|
71
|
-
assert.equal(interceptor.getToken(TEST_LOCUS_ID), 'test-token');
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it('get route token case insensitively ', async () => {
|
|
75
|
-
const response = {
|
|
76
|
-
headers: {
|
|
77
|
-
['x-cisco-part-route-token']: 'test-token',
|
|
78
|
-
},
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const result = await interceptor.onResponse(
|
|
82
|
-
{
|
|
83
|
-
uri: `https://locus-test.webex.com/locus/api/v1/loci/${TEST_LOCUS_ID}/foo`,
|
|
84
|
-
},
|
|
85
|
-
response
|
|
86
|
-
);
|
|
87
|
-
assert.equal(result, response);
|
|
88
|
-
assert.equal(interceptor.getToken(TEST_LOCUS_ID), 'test-token');
|
|
89
|
-
});
|
|
90
|
-
|
|
91
57
|
it('onResponse should not store token when header missing', async () => {
|
|
92
58
|
interceptor.updateToken(TEST_LOCUS_ID);
|
|
93
59
|
const response = {headers: {}};
|
|
@@ -118,14 +84,4 @@ describe('LocusRouteTokenInterceptor', () => {
|
|
|
118
84
|
interceptor.updateToken(TEST_LOCUS_ID, 'abc456');
|
|
119
85
|
assert.equal(interceptor.getToken(TEST_LOCUS_ID), 'abc456');
|
|
120
86
|
});
|
|
121
|
-
|
|
122
|
-
it('should delete token when updateToken called with "null"', () => {
|
|
123
|
-
interceptor.updateToken(TEST_LOCUS_ID, 'null');
|
|
124
|
-
assert.isUndefined(interceptor.getToken(TEST_LOCUS_ID));
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it('should delete token when updateToken called with null', () => {
|
|
128
|
-
interceptor.updateToken(TEST_LOCUS_ID, null);
|
|
129
|
-
assert.isUndefined(interceptor.getToken(TEST_LOCUS_ID));
|
|
130
|
-
});
|
|
131
87
|
});
|
|
@@ -164,7 +164,7 @@ describe('plugin-meetings', () => {
|
|
|
164
164
|
|
|
165
165
|
assert.equal(parsedControls.rdcControl.enabled, newControls.rdcControl.enabled);
|
|
166
166
|
});
|
|
167
|
-
|
|
167
|
+
|
|
168
168
|
it('should parse the pollingQAControl control', () => {
|
|
169
169
|
const newControls = {pollingQAControl: {enabled: true}};
|
|
170
170
|
|
|
@@ -173,14 +173,6 @@ describe('plugin-meetings', () => {
|
|
|
173
173
|
assert.equal(parsedControls.pollingQAControl.enabled, newControls.pollingQAControl.enabled);
|
|
174
174
|
});
|
|
175
175
|
|
|
176
|
-
it('should parse the hesiodLlmId in transcribe control', () => {
|
|
177
|
-
const newControls = {transcribe: {hesiodLlmId: 'llm-123', transcribing: true, caption: true, spokenLanguage: 'en-US'}};
|
|
178
|
-
|
|
179
|
-
const parsedControls = ControlsUtils.parse(newControls);
|
|
180
|
-
|
|
181
|
-
assert.equal(parsedControls.transcribe.hesiodLlmId, newControls.transcribe.hesiodLlmId);
|
|
182
|
-
});
|
|
183
|
-
|
|
184
176
|
describe('videoEnabled', () => {
|
|
185
177
|
it('returns expected', () => {
|
|
186
178
|
const result = ControlsUtils.parse({video: {enabled: true}});
|
|
@@ -471,53 +463,6 @@ describe('plugin-meetings', () => {
|
|
|
471
463
|
assert.equal(updates.hasTranscribeSpokenLanguageChanged, true);
|
|
472
464
|
});
|
|
473
465
|
|
|
474
|
-
it('returns false when previous hesiodLlmId is undefined and current is a invalid value', () => {
|
|
475
|
-
const previous = { transcribe: undefined };
|
|
476
|
-
const current = { transcribe: { hesiodLlmId: null } };
|
|
477
|
-
|
|
478
|
-
const {updates} = ControlsUtils.getControls(previous, current);
|
|
479
|
-
|
|
480
|
-
assert.equal(updates.hasHesiodLLMIdChanged, false);
|
|
481
|
-
});
|
|
482
|
-
|
|
483
|
-
it('detects hesiodLlmId change when previous is undefined and current is a valid value', () => {
|
|
484
|
-
const previous = { transcribe: undefined };
|
|
485
|
-
const current = { transcribe: { hesiodLlmId: '123a-456b' } };
|
|
486
|
-
|
|
487
|
-
const {updates} = ControlsUtils.getControls(previous, current);
|
|
488
|
-
|
|
489
|
-
assert.equal(updates.hasHesiodLLMIdChanged, true);
|
|
490
|
-
});
|
|
491
|
-
|
|
492
|
-
describe('hasAiSummaryNotificationChanged', () => {
|
|
493
|
-
it('returns false when aiSummaryNotification has not changed', () => {
|
|
494
|
-
const previous = {transcribe: {aiSummaryNotification: false}};
|
|
495
|
-
const current = {transcribe: {aiSummaryNotification: false}};
|
|
496
|
-
const {updates} = ControlsUtils.getControls(previous, current);
|
|
497
|
-
assert.equal(updates.hasAiSummaryNotificationChanged, false);
|
|
498
|
-
});
|
|
499
|
-
|
|
500
|
-
it('returns true when aiSummaryNotification changes from false to true', () => {
|
|
501
|
-
const previous = {transcribe: {aiSummaryNotification: false}};
|
|
502
|
-
const current = {transcribe: {aiSummaryNotification: true}};
|
|
503
|
-
const {updates} = ControlsUtils.getControls(previous, current);
|
|
504
|
-
assert.equal(updates.hasAiSummaryNotificationChanged, true);
|
|
505
|
-
});
|
|
506
|
-
|
|
507
|
-
it('returns true when aiSummaryNotification changes from undefined to true', () => {
|
|
508
|
-
const previous = {transcribe: undefined};
|
|
509
|
-
const current = {transcribe: {aiSummaryNotification: true}};
|
|
510
|
-
const {updates} = ControlsUtils.getControls(previous, current);
|
|
511
|
-
assert.equal(updates.hasAiSummaryNotificationChanged, true);
|
|
512
|
-
});
|
|
513
|
-
|
|
514
|
-
it('parses aiSummaryNotification into the transcribe block', () => {
|
|
515
|
-
const controls = {transcribe: {transcribing: false, caption: false, aiSummaryNotification: true}};
|
|
516
|
-
const parsed = ControlsUtils.parse(controls);
|
|
517
|
-
assert.equal(parsed.transcribe.aiSummaryNotification, true);
|
|
518
|
-
});
|
|
519
|
-
});
|
|
520
|
-
|
|
521
466
|
describe('videoEnabled', () => {
|
|
522
467
|
const testVideoEnabled = (oldControls, newControls, updatedProperty) => {
|
|
523
468
|
const result = ControlsUtils.getControls(oldControls, newControls);
|