@memberjunction/ng-mj-livekit-room 6.1.4 → 6.2.0-edge.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.
|
@@ -82,37 +82,84 @@ export declare class MJLiveKitRoomComponent extends BaseAngularComponent impleme
|
|
|
82
82
|
/** Active Realtime models + their voices, supplied by the host (for the add-agent dropdowns). */
|
|
83
83
|
AvailableModels: RealtimeModelVoices[];
|
|
84
84
|
/** True briefly after the invite link is copied (drives the "Link copied" pill state). */
|
|
85
|
-
|
|
85
|
+
InviteCopied: boolean;
|
|
86
|
+
/** @deprecated Use {@link InviteCopied}. */
|
|
87
|
+
get inviteCopied(): boolean;
|
|
88
|
+
/** @deprecated Use {@link InviteCopied}. */
|
|
89
|
+
set inviteCopied(value: boolean);
|
|
86
90
|
/** Whether the floating agents panel is open. */
|
|
87
|
-
|
|
91
|
+
ShowAgentsPanel: boolean;
|
|
92
|
+
/** @deprecated Use {@link ShowAgentsPanel}. */
|
|
93
|
+
get showAgentsPanel(): boolean;
|
|
94
|
+
/** @deprecated Use {@link ShowAgentsPanel}. */
|
|
95
|
+
set showAgentsPanel(value: boolean);
|
|
88
96
|
/** The agent bots currently bridged into the room (the first is the one started on join). */
|
|
89
|
-
|
|
97
|
+
AgentsInRoom: AgentInRoom[];
|
|
98
|
+
/** @deprecated Use {@link AgentsInRoom}. */
|
|
99
|
+
get agentsInRoom(): AgentInRoom[];
|
|
100
|
+
/** @deprecated Use {@link AgentsInRoom}. */
|
|
101
|
+
set agentsInRoom(value: AgentInRoom[]);
|
|
90
102
|
/** The target id chosen in the "Add an agent" picker. */
|
|
91
|
-
|
|
103
|
+
AddTargetId: string | null;
|
|
104
|
+
/** @deprecated Use {@link AddTargetId}. */
|
|
105
|
+
get addTargetId(): string | null;
|
|
106
|
+
/** @deprecated Use {@link AddTargetId}. */
|
|
107
|
+
set addTargetId(value: string | null);
|
|
92
108
|
/** The MODEL override chosen in the "Add an agent" picker (dev-only; null = co-agent/target default). */
|
|
93
|
-
|
|
109
|
+
AddModelId: string | null;
|
|
110
|
+
/** @deprecated Use {@link AddModelId}. */
|
|
111
|
+
get addModelId(): string | null;
|
|
112
|
+
/** @deprecated Use {@link AddModelId}. */
|
|
113
|
+
set addModelId(value: string | null);
|
|
94
114
|
/** The VOICE override chosen in the "Add an agent" picker (dev-only; null = co-agent/target default). */
|
|
95
|
-
|
|
115
|
+
AddVoice: string | null;
|
|
116
|
+
/** @deprecated Use {@link AddVoice}. */
|
|
117
|
+
get addVoice(): string | null;
|
|
118
|
+
/** @deprecated Use {@link AddVoice}. */
|
|
119
|
+
set addVoice(value: string | null);
|
|
96
120
|
/** Exposed for template use — platform-safe UUID equality (SQL upper vs PG lower). */
|
|
97
121
|
UUIDsEqual: typeof UUIDsEqual;
|
|
98
122
|
/** True while an Add request is in flight. */
|
|
99
|
-
|
|
123
|
+
AddingAgent: boolean;
|
|
124
|
+
/** @deprecated Use {@link AddingAgent}. */
|
|
125
|
+
get addingAgent(): boolean;
|
|
126
|
+
/** @deprecated Use {@link AddingAgent}. */
|
|
127
|
+
set addingAgent(value: boolean);
|
|
100
128
|
/** Last add error, shown under the picker. */
|
|
101
|
-
|
|
129
|
+
AddError: string | null;
|
|
130
|
+
/** @deprecated Use {@link AddError}. */
|
|
131
|
+
get addError(): string | null;
|
|
132
|
+
/** @deprecated Use {@link AddError}. */
|
|
133
|
+
set addError(value: string | null);
|
|
102
134
|
/** True while an "End meeting" (stop all agents + leave) is in flight. */
|
|
103
|
-
|
|
135
|
+
EndingMeeting: boolean;
|
|
136
|
+
/** @deprecated Use {@link EndingMeeting}. */
|
|
137
|
+
get endingMeeting(): boolean;
|
|
138
|
+
/** @deprecated Use {@link EndingMeeting}. */
|
|
139
|
+
set endingMeeting(value: boolean);
|
|
104
140
|
/** The inner Generic room — used to trigger the local disconnect when ending/leaving the meeting. */
|
|
105
141
|
private roomComponent?;
|
|
106
142
|
/** Available agents not already in the room (by target id) — the "Add" picker options. */
|
|
143
|
+
get AvailableToAdd(): {
|
|
144
|
+
ID: string;
|
|
145
|
+
Name: string;
|
|
146
|
+
}[];
|
|
147
|
+
/** @deprecated Use {@link AvailableToAdd}. */
|
|
107
148
|
get availableToAdd(): {
|
|
108
149
|
ID: string;
|
|
109
150
|
Name: string;
|
|
110
151
|
}[];
|
|
111
152
|
/** Voices for the model chosen in the add-agent picker (empty when no model picked or it has none). */
|
|
153
|
+
get AddVoices(): RealtimeVoiceOption[];
|
|
154
|
+
/** @deprecated Use {@link AddVoices}. */
|
|
112
155
|
get addVoices(): RealtimeVoiceOption[];
|
|
113
156
|
/** Records the add-agent MODEL choice; clears the voice so it can't outlive a model switch. */
|
|
157
|
+
OnAddModelChange(event: Event): void;
|
|
158
|
+
/** @deprecated Use {@link OnAddModelChange}. */
|
|
114
159
|
onAddModelChange(event: Event): void;
|
|
115
160
|
/** Records the add-agent VOICE choice. */
|
|
161
|
+
OnAddVoiceChange(event: Event): void;
|
|
162
|
+
/** @deprecated Use {@link OnAddVoiceChange}. */
|
|
116
163
|
onAddVoiceChange(event: Event): void;
|
|
117
164
|
/** @see LiveKitRoomComponent.Layout */
|
|
118
165
|
Layout: LiveKitRoomLayout;
|
|
@@ -183,19 +230,43 @@ export declare class MJLiveKitRoomComponent extends BaseAngularComponent impleme
|
|
|
183
230
|
/** Emitted on room errors (and on token/session-resolution failures). */
|
|
184
231
|
ErrorOccurred: EventEmitter<LiveKitRoomError>;
|
|
185
232
|
/** Whether the binding is resolving the token/session. */
|
|
186
|
-
|
|
233
|
+
Loading: boolean;
|
|
234
|
+
/** @deprecated Use {@link Loading}. */
|
|
235
|
+
get loading(): boolean;
|
|
236
|
+
/** @deprecated Use {@link Loading}. */
|
|
237
|
+
set loading(value: boolean);
|
|
187
238
|
/** The token/session-resolution error, if any. */
|
|
188
239
|
errorMessage: string | null;
|
|
189
240
|
/** The resolved LiveKit server URL. */
|
|
190
|
-
|
|
241
|
+
ServerUrl: string | null;
|
|
242
|
+
/** @deprecated Use {@link ServerUrl}. */
|
|
243
|
+
get serverUrl(): string | null;
|
|
244
|
+
/** @deprecated Use {@link ServerUrl}. */
|
|
245
|
+
set serverUrl(value: string | null);
|
|
191
246
|
/** The resolved access token. */
|
|
192
|
-
|
|
247
|
+
Token: string | null;
|
|
248
|
+
/** @deprecated Use {@link Token}. */
|
|
249
|
+
get token(): string | null;
|
|
250
|
+
/** @deprecated Use {@link Token}. */
|
|
251
|
+
set token(value: string | null);
|
|
193
252
|
/** The display name passed to the room. */
|
|
194
|
-
|
|
253
|
+
ResolvedDisplayName: string | null;
|
|
254
|
+
/** @deprecated Use {@link ResolvedDisplayName}. */
|
|
255
|
+
get resolvedDisplayName(): string | null;
|
|
256
|
+
/** @deprecated Use {@link ResolvedDisplayName}. */
|
|
257
|
+
set resolvedDisplayName(value: string | null);
|
|
195
258
|
/** The resolved room name (for recording calls). */
|
|
196
|
-
|
|
259
|
+
ResolvedRoomName: string | null;
|
|
260
|
+
/** @deprecated Use {@link ResolvedRoomName}. */
|
|
261
|
+
get resolvedRoomName(): string | null;
|
|
262
|
+
/** @deprecated Use {@link ResolvedRoomName}. */
|
|
263
|
+
set resolvedRoomName(value: string | null);
|
|
197
264
|
/** Whether a recording is currently in progress. */
|
|
198
|
-
|
|
265
|
+
IsRecording: boolean;
|
|
266
|
+
/** @deprecated Use {@link IsRecording}. */
|
|
267
|
+
get isRecording(): boolean;
|
|
268
|
+
/** @deprecated Use {@link IsRecording}. */
|
|
269
|
+
set isRecording(value: boolean);
|
|
199
270
|
/** The active egress id, when recording. */
|
|
200
271
|
private currentEgressId;
|
|
201
272
|
/**
|
|
@@ -203,9 +274,17 @@ export declare class MJLiveKitRoomComponent extends BaseAngularComponent impleme
|
|
|
203
274
|
* (the server registers the egress MP4 and returns its file id) or resolved for an already-recorded room
|
|
204
275
|
* on join. Drives the {@link MJStorageMediaPlayerComponent} playback panel.
|
|
205
276
|
*/
|
|
206
|
-
|
|
277
|
+
RecordingFileId: string | null;
|
|
278
|
+
/** @deprecated Use {@link RecordingFileId}. */
|
|
279
|
+
get recordingFileId(): string | null;
|
|
280
|
+
/** @deprecated Use {@link RecordingFileId}. */
|
|
281
|
+
set recordingFileId(value: string | null);
|
|
207
282
|
/** Whether the recording playback panel is shown (dismissable). */
|
|
208
|
-
|
|
283
|
+
ShowRecordingPanel: boolean;
|
|
284
|
+
/** @deprecated Use {@link ShowRecordingPanel}. */
|
|
285
|
+
get showRecordingPanel(): boolean;
|
|
286
|
+
/** @deprecated Use {@link ShowRecordingPanel}. */
|
|
287
|
+
set showRecordingPanel(value: boolean);
|
|
209
288
|
ngOnInit(): void;
|
|
210
289
|
/**
|
|
211
290
|
* Max time to wait for the connection to start before surfacing a retryable error, so a hung or very
|
|
@@ -223,6 +302,8 @@ export declare class MJLiveKitRoomComponent extends BaseAngularComponent impleme
|
|
|
223
302
|
/** Starts the agent room session and applies the returned client token. */
|
|
224
303
|
private startAgentSession;
|
|
225
304
|
/** Picker selection handler for the in-room "Add an agent" control (native select; no FormsModule dep). */
|
|
305
|
+
OnAddTargetChange(event: Event): void;
|
|
306
|
+
/** @deprecated Use {@link OnAddTargetChange}. */
|
|
226
307
|
onAddTargetChange(event: Event): void;
|
|
227
308
|
/**
|
|
228
309
|
* Adds another agent to the SAME room — starts a new bridge (the co-agent voicing the chosen target)
|
|
@@ -244,12 +325,16 @@ export declare class MJLiveKitRoomComponent extends BaseAngularComponent impleme
|
|
|
244
325
|
* Builds the shareable invite URL for THIS room: the current page URL with a `room=<roomName>` query
|
|
245
326
|
* param. Opening it lands the invitee on the Live Room in join mode for the same room.
|
|
246
327
|
*/
|
|
328
|
+
get InviteUrl(): string;
|
|
329
|
+
/** @deprecated Use {@link InviteUrl}. */
|
|
247
330
|
get inviteUrl(): string;
|
|
248
331
|
/** Copies {@link inviteUrl} to the clipboard and flips the pill to "Link copied" briefly. */
|
|
249
332
|
CopyInvite(): Promise<void>;
|
|
250
333
|
/** Joins an existing room by minting a client token. */
|
|
251
334
|
private joinRoom;
|
|
252
335
|
/** Toggles room recording via the RealtimeBridge GraphQL surface (server-authorized egress). */
|
|
336
|
+
OnToggleRecording(): Promise<void>;
|
|
337
|
+
/** @deprecated Use {@link OnToggleRecording}. */
|
|
253
338
|
onToggleRecording(): Promise<void>;
|
|
254
339
|
/**
|
|
255
340
|
* Resolves this room's already-registered meeting recording (if any) — the `MJ: Conversations` of
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mj-livekit-room.component.d.ts","sourceRoot":"","sources":["../../src/lib/mj-livekit-room.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyD,YAAY,EAAS,MAAM,EAA6B,MAAM,eAAe,CAAC;AAC9I,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,OAAO,EAA6C,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC3I,OAAO,EAAwB,KAAK,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAE/F,OAAO,KAAK,EACV,kBAAkB,EAClB,wBAAwB,EACxB,6BAA6B,EAC7B,2BAA2B,EAC3B,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,mCAAmC,CAAC;;AAE3C,oGAAoG;AACpG,MAAM,MAAM,uBAAuB,GAAG,OAAO,GAAG,MAAM,CAAC;AAEvD,uEAAuE;AACvE,MAAM,WAAW,4BAA4B;IAC3C,yCAAyC;IACzC,eAAe,EAAE,MAAM,CAAC;IACxB,qBAAqB;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,uFAAuF;AACvF,MAAM,WAAW,WAAW;IAC1B,kFAAkF;IAClF,eAAe,EAAE,MAAM,CAAC;IACxB,oDAAoD;IACpD,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,qBA+Ua,sBAAuB,SAAQ,oBAAqB,YAAW,MAAM;IAChF,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA6B;IAGjD,kGAAkG;IAClF,IAAI,EAAE,uBAAuB,CAAW;IACxD,iFAAiF;IACjE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC9C,wDAAwD;IACxC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAQ;IAChD;;;OAGG;IACa,aAAa,EAAE,MAAM,GAAG,IAAI,CAAQ;IACpD,gGAAgG;IAChF,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC/C,gGAAgG;IAChF,WAAW,EAAE,MAAM,GAAG,IAAI,CAAQ;IAClD,sCAAsC;IACtB,QAAQ,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,IAAI,CAAQ;IACxE,oDAAoD;IACpC,SAAS,UAAQ;IAGjC,8EAA8E;IAC9D,qBAAqB,UAAQ;IAC7C,mEAAmE;IACnD,YAAY,UAAQ;IACpC;;;;OAIG;IACa,eAAe,UAAQ;IACvC,gHAAgH;IAChG,eAAe,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAM;IAErE,mGAAmG;IACnF,eAAe,EAAE,MAAM,GAAG,IAAI,CAAQ;IACtD,0FAA0F;IAC1E,aAAa,EAAE,MAAM,GAAG,IAAI,CAAQ;IACpD;;;;OAIG;IACa,iBAAiB,UAAS;IAC1C,iGAAiG;IACjF,eAAe,EAAE,mBAAmB,EAAE,CAAM;IAE5D,0FAA0F;IACnF,YAAY,UAAS;IAE5B,iDAAiD;IAC1C,eAAe,UAAS;IAC/B,6FAA6F;IACtF,YAAY,EAAE,WAAW,EAAE,CAAM;
|
|
1
|
+
{"version":3,"file":"mj-livekit-room.component.d.ts","sourceRoot":"","sources":["../../src/lib/mj-livekit-room.component.ts"],"names":[],"mappings":"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"}
|
|
@@ -297,45 +297,133 @@ export class MJLiveKitRoomComponent extends BaseAngularComponent {
|
|
|
297
297
|
/** Active Realtime models + their voices, supplied by the host (for the add-agent dropdowns). */
|
|
298
298
|
AvailableModels = [];
|
|
299
299
|
/** True briefly after the invite link is copied (drives the "Link copied" pill state). */
|
|
300
|
-
|
|
300
|
+
InviteCopied = false;
|
|
301
|
+
/** @deprecated Use {@link InviteCopied}. */
|
|
302
|
+
get inviteCopied() {
|
|
303
|
+
return this.InviteCopied;
|
|
304
|
+
}
|
|
305
|
+
/** @deprecated Use {@link InviteCopied}. */
|
|
306
|
+
set inviteCopied(value) {
|
|
307
|
+
this.InviteCopied = value;
|
|
308
|
+
}
|
|
301
309
|
/** Whether the floating agents panel is open. */
|
|
302
|
-
|
|
310
|
+
ShowAgentsPanel = false;
|
|
311
|
+
/** @deprecated Use {@link ShowAgentsPanel}. */
|
|
312
|
+
get showAgentsPanel() {
|
|
313
|
+
return this.ShowAgentsPanel;
|
|
314
|
+
}
|
|
315
|
+
/** @deprecated Use {@link ShowAgentsPanel}. */
|
|
316
|
+
set showAgentsPanel(value) {
|
|
317
|
+
this.ShowAgentsPanel = value;
|
|
318
|
+
}
|
|
303
319
|
/** The agent bots currently bridged into the room (the first is the one started on join). */
|
|
304
|
-
|
|
320
|
+
AgentsInRoom = [];
|
|
321
|
+
/** @deprecated Use {@link AgentsInRoom}. */
|
|
322
|
+
get agentsInRoom() {
|
|
323
|
+
return this.AgentsInRoom;
|
|
324
|
+
}
|
|
325
|
+
/** @deprecated Use {@link AgentsInRoom}. */
|
|
326
|
+
set agentsInRoom(value) {
|
|
327
|
+
this.AgentsInRoom = value;
|
|
328
|
+
}
|
|
305
329
|
/** The target id chosen in the "Add an agent" picker. */
|
|
306
|
-
|
|
330
|
+
AddTargetId = null;
|
|
331
|
+
/** @deprecated Use {@link AddTargetId}. */
|
|
332
|
+
get addTargetId() {
|
|
333
|
+
return this.AddTargetId;
|
|
334
|
+
}
|
|
335
|
+
/** @deprecated Use {@link AddTargetId}. */
|
|
336
|
+
set addTargetId(value) {
|
|
337
|
+
this.AddTargetId = value;
|
|
338
|
+
}
|
|
307
339
|
/** The MODEL override chosen in the "Add an agent" picker (dev-only; null = co-agent/target default). */
|
|
308
|
-
|
|
340
|
+
AddModelId = null;
|
|
341
|
+
/** @deprecated Use {@link AddModelId}. */
|
|
342
|
+
get addModelId() {
|
|
343
|
+
return this.AddModelId;
|
|
344
|
+
}
|
|
345
|
+
/** @deprecated Use {@link AddModelId}. */
|
|
346
|
+
set addModelId(value) {
|
|
347
|
+
this.AddModelId = value;
|
|
348
|
+
}
|
|
309
349
|
/** The VOICE override chosen in the "Add an agent" picker (dev-only; null = co-agent/target default). */
|
|
310
|
-
|
|
350
|
+
AddVoice = null;
|
|
351
|
+
/** @deprecated Use {@link AddVoice}. */
|
|
352
|
+
get addVoice() {
|
|
353
|
+
return this.AddVoice;
|
|
354
|
+
}
|
|
355
|
+
/** @deprecated Use {@link AddVoice}. */
|
|
356
|
+
set addVoice(value) {
|
|
357
|
+
this.AddVoice = value;
|
|
358
|
+
}
|
|
311
359
|
/** Exposed for template use — platform-safe UUID equality (SQL upper vs PG lower). */
|
|
312
360
|
UUIDsEqual = UUIDsEqual;
|
|
313
361
|
/** True while an Add request is in flight. */
|
|
314
|
-
|
|
362
|
+
AddingAgent = false;
|
|
363
|
+
/** @deprecated Use {@link AddingAgent}. */
|
|
364
|
+
get addingAgent() {
|
|
365
|
+
return this.AddingAgent;
|
|
366
|
+
}
|
|
367
|
+
/** @deprecated Use {@link AddingAgent}. */
|
|
368
|
+
set addingAgent(value) {
|
|
369
|
+
this.AddingAgent = value;
|
|
370
|
+
}
|
|
315
371
|
/** Last add error, shown under the picker. */
|
|
316
|
-
|
|
372
|
+
AddError = null;
|
|
373
|
+
/** @deprecated Use {@link AddError}. */
|
|
374
|
+
get addError() {
|
|
375
|
+
return this.AddError;
|
|
376
|
+
}
|
|
377
|
+
/** @deprecated Use {@link AddError}. */
|
|
378
|
+
set addError(value) {
|
|
379
|
+
this.AddError = value;
|
|
380
|
+
}
|
|
317
381
|
/** True while an "End meeting" (stop all agents + leave) is in flight. */
|
|
318
|
-
|
|
382
|
+
EndingMeeting = false;
|
|
383
|
+
/** @deprecated Use {@link EndingMeeting}. */
|
|
384
|
+
get endingMeeting() {
|
|
385
|
+
return this.EndingMeeting;
|
|
386
|
+
}
|
|
387
|
+
/** @deprecated Use {@link EndingMeeting}. */
|
|
388
|
+
set endingMeeting(value) {
|
|
389
|
+
this.EndingMeeting = value;
|
|
390
|
+
}
|
|
319
391
|
/** The inner Generic room — used to trigger the local disconnect when ending/leaving the meeting. */
|
|
320
392
|
roomComponent;
|
|
321
393
|
/** Available agents not already in the room (by target id) — the "Add" picker options. */
|
|
322
|
-
get
|
|
323
|
-
const present = new Set(this.
|
|
394
|
+
get AvailableToAdd() {
|
|
395
|
+
const present = new Set(this.AgentsInRoom.map((a) => (a.TargetAgentID ?? '').toLowerCase()));
|
|
324
396
|
return this.AvailableAgents.filter((a) => !present.has(a.ID.toLowerCase()));
|
|
325
397
|
}
|
|
398
|
+
/** @deprecated Use {@link AvailableToAdd}. */
|
|
399
|
+
get availableToAdd() {
|
|
400
|
+
return this.AvailableToAdd;
|
|
401
|
+
}
|
|
326
402
|
/** Voices for the model chosen in the add-agent picker (empty when no model picked or it has none). */
|
|
327
|
-
get
|
|
328
|
-
const model = this.AvailableModels.find((m) => UUIDsEqual(m.ModelID, this.
|
|
403
|
+
get AddVoices() {
|
|
404
|
+
const model = this.AvailableModels.find((m) => UUIDsEqual(m.ModelID, this.AddModelId));
|
|
329
405
|
return model?.Voices ?? [];
|
|
330
406
|
}
|
|
407
|
+
/** @deprecated Use {@link AddVoices}. */
|
|
408
|
+
get addVoices() {
|
|
409
|
+
return this.AddVoices;
|
|
410
|
+
}
|
|
331
411
|
/** Records the add-agent MODEL choice; clears the voice so it can't outlive a model switch. */
|
|
412
|
+
OnAddModelChange(event) {
|
|
413
|
+
this.AddModelId = event.target.value || null;
|
|
414
|
+
this.AddVoice = null;
|
|
415
|
+
}
|
|
416
|
+
/** @deprecated Use {@link OnAddModelChange}. */
|
|
332
417
|
onAddModelChange(event) {
|
|
333
|
-
this.
|
|
334
|
-
this.addVoice = null;
|
|
418
|
+
return this.OnAddModelChange(event);
|
|
335
419
|
}
|
|
336
420
|
/** Records the add-agent VOICE choice. */
|
|
421
|
+
OnAddVoiceChange(event) {
|
|
422
|
+
this.AddVoice = event.target.value || null;
|
|
423
|
+
}
|
|
424
|
+
/** @deprecated Use {@link OnAddVoiceChange}. */
|
|
337
425
|
onAddVoiceChange(event) {
|
|
338
|
-
this.
|
|
426
|
+
return this.OnAddVoiceChange(event);
|
|
339
427
|
}
|
|
340
428
|
// ── Forwarded UI gates (see LiveKitRoomComponent) ────────────────────────────────
|
|
341
429
|
/** @see LiveKitRoomComponent.Layout */
|
|
@@ -409,19 +497,67 @@ export class MJLiveKitRoomComponent extends BaseAngularComponent {
|
|
|
409
497
|
ErrorOccurred = new EventEmitter();
|
|
410
498
|
// ── View state ─────────────────────────────────────────────────────────────────
|
|
411
499
|
/** Whether the binding is resolving the token/session. */
|
|
412
|
-
|
|
500
|
+
Loading = false;
|
|
501
|
+
/** @deprecated Use {@link Loading}. */
|
|
502
|
+
get loading() {
|
|
503
|
+
return this.Loading;
|
|
504
|
+
}
|
|
505
|
+
/** @deprecated Use {@link Loading}. */
|
|
506
|
+
set loading(value) {
|
|
507
|
+
this.Loading = value;
|
|
508
|
+
}
|
|
413
509
|
/** The token/session-resolution error, if any. */
|
|
414
510
|
errorMessage = null;
|
|
415
511
|
/** The resolved LiveKit server URL. */
|
|
416
|
-
|
|
512
|
+
ServerUrl = null;
|
|
513
|
+
/** @deprecated Use {@link ServerUrl}. */
|
|
514
|
+
get serverUrl() {
|
|
515
|
+
return this.ServerUrl;
|
|
516
|
+
}
|
|
517
|
+
/** @deprecated Use {@link ServerUrl}. */
|
|
518
|
+
set serverUrl(value) {
|
|
519
|
+
this.ServerUrl = value;
|
|
520
|
+
}
|
|
417
521
|
/** The resolved access token. */
|
|
418
|
-
|
|
522
|
+
Token = null;
|
|
523
|
+
/** @deprecated Use {@link Token}. */
|
|
524
|
+
get token() {
|
|
525
|
+
return this.Token;
|
|
526
|
+
}
|
|
527
|
+
/** @deprecated Use {@link Token}. */
|
|
528
|
+
set token(value) {
|
|
529
|
+
this.Token = value;
|
|
530
|
+
}
|
|
419
531
|
/** The display name passed to the room. */
|
|
420
|
-
|
|
532
|
+
ResolvedDisplayName = null;
|
|
533
|
+
/** @deprecated Use {@link ResolvedDisplayName}. */
|
|
534
|
+
get resolvedDisplayName() {
|
|
535
|
+
return this.ResolvedDisplayName;
|
|
536
|
+
}
|
|
537
|
+
/** @deprecated Use {@link ResolvedDisplayName}. */
|
|
538
|
+
set resolvedDisplayName(value) {
|
|
539
|
+
this.ResolvedDisplayName = value;
|
|
540
|
+
}
|
|
421
541
|
/** The resolved room name (for recording calls). */
|
|
422
|
-
|
|
542
|
+
ResolvedRoomName = null;
|
|
543
|
+
/** @deprecated Use {@link ResolvedRoomName}. */
|
|
544
|
+
get resolvedRoomName() {
|
|
545
|
+
return this.ResolvedRoomName;
|
|
546
|
+
}
|
|
547
|
+
/** @deprecated Use {@link ResolvedRoomName}. */
|
|
548
|
+
set resolvedRoomName(value) {
|
|
549
|
+
this.ResolvedRoomName = value;
|
|
550
|
+
}
|
|
423
551
|
/** Whether a recording is currently in progress. */
|
|
424
|
-
|
|
552
|
+
IsRecording = false;
|
|
553
|
+
/** @deprecated Use {@link IsRecording}. */
|
|
554
|
+
get isRecording() {
|
|
555
|
+
return this.IsRecording;
|
|
556
|
+
}
|
|
557
|
+
/** @deprecated Use {@link IsRecording}. */
|
|
558
|
+
set isRecording(value) {
|
|
559
|
+
this.IsRecording = value;
|
|
560
|
+
}
|
|
425
561
|
/** The active egress id, when recording. */
|
|
426
562
|
currentEgressId = null;
|
|
427
563
|
/**
|
|
@@ -429,9 +565,25 @@ export class MJLiveKitRoomComponent extends BaseAngularComponent {
|
|
|
429
565
|
* (the server registers the egress MP4 and returns its file id) or resolved for an already-recorded room
|
|
430
566
|
* on join. Drives the {@link MJStorageMediaPlayerComponent} playback panel.
|
|
431
567
|
*/
|
|
432
|
-
|
|
568
|
+
RecordingFileId = null;
|
|
569
|
+
/** @deprecated Use {@link RecordingFileId}. */
|
|
570
|
+
get recordingFileId() {
|
|
571
|
+
return this.RecordingFileId;
|
|
572
|
+
}
|
|
573
|
+
/** @deprecated Use {@link RecordingFileId}. */
|
|
574
|
+
set recordingFileId(value) {
|
|
575
|
+
this.RecordingFileId = value;
|
|
576
|
+
}
|
|
433
577
|
/** Whether the recording playback panel is shown (dismissable). */
|
|
434
|
-
|
|
578
|
+
ShowRecordingPanel = true;
|
|
579
|
+
/** @deprecated Use {@link ShowRecordingPanel}. */
|
|
580
|
+
get showRecordingPanel() {
|
|
581
|
+
return this.ShowRecordingPanel;
|
|
582
|
+
}
|
|
583
|
+
/** @deprecated Use {@link ShowRecordingPanel}. */
|
|
584
|
+
set showRecordingPanel(value) {
|
|
585
|
+
this.ShowRecordingPanel = value;
|
|
586
|
+
}
|
|
435
587
|
ngOnInit() {
|
|
436
588
|
if (this.AutoStart) {
|
|
437
589
|
void this.Start();
|
|
@@ -449,12 +601,12 @@ export class MJLiveKitRoomComponent extends BaseAngularComponent {
|
|
|
449
601
|
ConnectTimeoutMs = 25000;
|
|
450
602
|
/** Resolves the connection (mints a token and, in agent mode, starts the agent session). */
|
|
451
603
|
async Start() {
|
|
452
|
-
this.
|
|
604
|
+
this.Loading = true;
|
|
453
605
|
this.errorMessage = null;
|
|
454
606
|
this.cdr.markForCheck();
|
|
455
607
|
try {
|
|
456
608
|
const client = new GraphQLLiveKitClient(this.ProviderToUse);
|
|
457
|
-
this.
|
|
609
|
+
this.ResolvedDisplayName = this.DisplayName;
|
|
458
610
|
const connect = this.Mode === 'agent' ? this.startAgentSession(client) : this.joinRoom(client);
|
|
459
611
|
await this.withTimeout(connect, this.ConnectTimeoutMs);
|
|
460
612
|
}
|
|
@@ -462,7 +614,7 @@ export class MJLiveKitRoomComponent extends BaseAngularComponent {
|
|
|
462
614
|
this.fail(err instanceof Error ? err.message : String(err));
|
|
463
615
|
}
|
|
464
616
|
finally {
|
|
465
|
-
this.
|
|
617
|
+
this.Loading = false;
|
|
466
618
|
this.cdr.markForCheck();
|
|
467
619
|
}
|
|
468
620
|
}
|
|
@@ -501,62 +653,66 @@ export class MJLiveKitRoomComponent extends BaseAngularComponent {
|
|
|
501
653
|
this.fail(result.ErrorMessage ?? 'Failed to start the agent session.');
|
|
502
654
|
return;
|
|
503
655
|
}
|
|
504
|
-
this.
|
|
505
|
-
this.
|
|
506
|
-
this.
|
|
656
|
+
this.ServerUrl = result.ServerUrl;
|
|
657
|
+
this.Token = result.ClientToken;
|
|
658
|
+
this.ResolvedRoomName = result.RoomName;
|
|
507
659
|
// Surface a prior recording for this resolved room (the server may have generated the room name).
|
|
508
660
|
void this.loadExistingRecording(result.RoomName);
|
|
509
661
|
// Track the agent we just brought in as the first entry in the in-room roster.
|
|
510
|
-
this.
|
|
662
|
+
this.AgentsInRoom = [
|
|
511
663
|
{ SessionBridgeID: result.SessionBridgeID, TargetAgentID: this.TargetAgentID, Name: this.AgentName ?? 'Agent' },
|
|
512
664
|
];
|
|
513
665
|
this.SessionStarted.emit({ SessionBridgeID: result.SessionBridgeID, RoomName: result.RoomName });
|
|
514
666
|
}
|
|
515
667
|
/** Picker selection handler for the in-room "Add an agent" control (native select; no FormsModule dep). */
|
|
668
|
+
OnAddTargetChange(event) {
|
|
669
|
+
this.AddTargetId = event.target.value || null;
|
|
670
|
+
this.AddError = null;
|
|
671
|
+
}
|
|
672
|
+
/** @deprecated Use {@link OnAddTargetChange}. */
|
|
516
673
|
onAddTargetChange(event) {
|
|
517
|
-
this.
|
|
518
|
-
this.addError = null;
|
|
674
|
+
return this.OnAddTargetChange(event);
|
|
519
675
|
}
|
|
520
676
|
/**
|
|
521
677
|
* Adds another agent to the SAME room — starts a new bridge (the co-agent voicing the chosen target)
|
|
522
678
|
* and appends it to the roster. The new bot joins the live room alongside the existing participants.
|
|
523
679
|
*/
|
|
524
680
|
async AddAgent() {
|
|
525
|
-
if (!this.
|
|
681
|
+
if (!this.AddTargetId || !this.ResolvedRoomName || this.AddingAgent) {
|
|
526
682
|
return;
|
|
527
683
|
}
|
|
528
|
-
const target = this.AvailableAgents.find((a) => UUIDsEqual(a.ID, this.
|
|
529
|
-
this.
|
|
530
|
-
this.
|
|
684
|
+
const target = this.AvailableAgents.find((a) => UUIDsEqual(a.ID, this.AddTargetId));
|
|
685
|
+
this.AddingAgent = true;
|
|
686
|
+
this.AddError = null;
|
|
531
687
|
this.cdr.markForCheck();
|
|
532
688
|
try {
|
|
533
689
|
const client = new GraphQLLiveKitClient(this.ProviderToUse);
|
|
534
690
|
const result = await client.StartAgentRoomSession({
|
|
535
691
|
AgentID: this.AgentID ?? undefined,
|
|
536
692
|
AgentName: target?.Name ?? undefined,
|
|
537
|
-
TargetAgentID: this.
|
|
538
|
-
RealtimeModelID: this.
|
|
539
|
-
RealtimeVoice: this.
|
|
540
|
-
RoomName: this.
|
|
693
|
+
TargetAgentID: this.AddTargetId,
|
|
694
|
+
RealtimeModelID: this.AddModelId ?? undefined,
|
|
695
|
+
RealtimeVoice: this.AddVoice ?? undefined,
|
|
696
|
+
RoomName: this.ResolvedRoomName,
|
|
541
697
|
TurnMode: this.TurnMode ?? undefined,
|
|
542
698
|
});
|
|
543
699
|
if (!result.Success) {
|
|
544
|
-
this.
|
|
700
|
+
this.AddError = result.ErrorMessage ?? 'Failed to add the agent.';
|
|
545
701
|
return;
|
|
546
702
|
}
|
|
547
|
-
this.
|
|
548
|
-
...this.
|
|
549
|
-
{ SessionBridgeID: result.SessionBridgeID, TargetAgentID: this.
|
|
703
|
+
this.AgentsInRoom = [
|
|
704
|
+
...this.AgentsInRoom,
|
|
705
|
+
{ SessionBridgeID: result.SessionBridgeID, TargetAgentID: this.AddTargetId, Name: target?.Name ?? 'Agent' },
|
|
550
706
|
];
|
|
551
|
-
this.
|
|
552
|
-
this.
|
|
553
|
-
this.
|
|
707
|
+
this.AddTargetId = null;
|
|
708
|
+
this.AddModelId = null;
|
|
709
|
+
this.AddVoice = null;
|
|
554
710
|
}
|
|
555
711
|
catch (err) {
|
|
556
|
-
this.
|
|
712
|
+
this.AddError = err instanceof Error ? err.message : String(err);
|
|
557
713
|
}
|
|
558
714
|
finally {
|
|
559
|
-
this.
|
|
715
|
+
this.AddingAgent = false;
|
|
560
716
|
this.cdr.markForCheck();
|
|
561
717
|
}
|
|
562
718
|
}
|
|
@@ -571,7 +727,7 @@ export class MJLiveKitRoomComponent extends BaseAngularComponent {
|
|
|
571
727
|
const client = new GraphQLLiveKitClient(this.ProviderToUse);
|
|
572
728
|
const ok = await client.StopAgentRoomSession(agent.SessionBridgeID);
|
|
573
729
|
if (ok) {
|
|
574
|
-
this.
|
|
730
|
+
this.AgentsInRoom = this.AgentsInRoom.filter((a) => a.SessionBridgeID !== agent.SessionBridgeID);
|
|
575
731
|
}
|
|
576
732
|
else {
|
|
577
733
|
agent.Removing = false;
|
|
@@ -593,24 +749,24 @@ export class MJLiveKitRoomComponent extends BaseAngularComponent {
|
|
|
593
749
|
* billable agent sessions in an empty room.
|
|
594
750
|
*/
|
|
595
751
|
async EndMeeting() {
|
|
596
|
-
if (this.
|
|
752
|
+
if (this.EndingMeeting) {
|
|
597
753
|
return;
|
|
598
754
|
}
|
|
599
|
-
this.
|
|
755
|
+
this.EndingMeeting = true;
|
|
600
756
|
this.cdr.markForCheck();
|
|
601
757
|
try {
|
|
602
|
-
if (this.
|
|
758
|
+
if (this.ResolvedRoomName) {
|
|
603
759
|
const client = new GraphQLLiveKitClient(this.ProviderToUse);
|
|
604
|
-
await client.EndRoom(this.
|
|
760
|
+
await client.EndRoom(this.ResolvedRoomName);
|
|
605
761
|
}
|
|
606
|
-
this.
|
|
762
|
+
this.AgentsInRoom = [];
|
|
607
763
|
}
|
|
608
764
|
catch {
|
|
609
765
|
/* best-effort — fall through and still disconnect the local user */
|
|
610
766
|
}
|
|
611
767
|
finally {
|
|
612
768
|
await this.roomComponent?.Leave();
|
|
613
|
-
this.
|
|
769
|
+
this.EndingMeeting = false;
|
|
614
770
|
this.cdr.markForCheck();
|
|
615
771
|
}
|
|
616
772
|
}
|
|
@@ -618,22 +774,26 @@ export class MJLiveKitRoomComponent extends BaseAngularComponent {
|
|
|
618
774
|
* Builds the shareable invite URL for THIS room: the current page URL with a `room=<roomName>` query
|
|
619
775
|
* param. Opening it lands the invitee on the Live Room in join mode for the same room.
|
|
620
776
|
*/
|
|
621
|
-
get
|
|
777
|
+
get InviteUrl() {
|
|
622
778
|
const url = new URL(window.location.href);
|
|
623
|
-
url.searchParams.set('room', this.
|
|
779
|
+
url.searchParams.set('room', this.ResolvedRoomName ?? '');
|
|
624
780
|
return url.toString();
|
|
625
781
|
}
|
|
782
|
+
/** @deprecated Use {@link InviteUrl}. */
|
|
783
|
+
get inviteUrl() {
|
|
784
|
+
return this.InviteUrl;
|
|
785
|
+
}
|
|
626
786
|
/** Copies {@link inviteUrl} to the clipboard and flips the pill to "Link copied" briefly. */
|
|
627
787
|
async CopyInvite() {
|
|
628
|
-
if (!this.
|
|
788
|
+
if (!this.ResolvedRoomName) {
|
|
629
789
|
return;
|
|
630
790
|
}
|
|
631
791
|
try {
|
|
632
|
-
await navigator.clipboard.writeText(this.
|
|
633
|
-
this.
|
|
792
|
+
await navigator.clipboard.writeText(this.InviteUrl);
|
|
793
|
+
this.InviteCopied = true;
|
|
634
794
|
this.cdr.markForCheck();
|
|
635
795
|
setTimeout(() => {
|
|
636
|
-
this.
|
|
796
|
+
this.InviteCopied = false;
|
|
637
797
|
this.cdr.markForCheck();
|
|
638
798
|
}, 2000);
|
|
639
799
|
}
|
|
@@ -652,20 +812,20 @@ export class MJLiveKitRoomComponent extends BaseAngularComponent {
|
|
|
652
812
|
this.fail(result.ErrorMessage ?? 'Failed to obtain a room token.');
|
|
653
813
|
return;
|
|
654
814
|
}
|
|
655
|
-
this.
|
|
656
|
-
this.
|
|
657
|
-
this.
|
|
815
|
+
this.ServerUrl = result.ServerUrl;
|
|
816
|
+
this.Token = result.Token;
|
|
817
|
+
this.ResolvedRoomName = this.RoomName;
|
|
658
818
|
}
|
|
659
819
|
/** Toggles room recording via the RealtimeBridge GraphQL surface (server-authorized egress). */
|
|
660
|
-
async
|
|
661
|
-
if (!this.
|
|
820
|
+
async OnToggleRecording() {
|
|
821
|
+
if (!this.ResolvedRoomName) {
|
|
662
822
|
return;
|
|
663
823
|
}
|
|
664
824
|
const client = new GraphQLLiveKitClient(this.ProviderToUse);
|
|
665
|
-
if (!this.
|
|
666
|
-
const result = await client.StartRecording(this.
|
|
825
|
+
if (!this.IsRecording) {
|
|
826
|
+
const result = await client.StartRecording(this.ResolvedRoomName);
|
|
667
827
|
if (result.Success) {
|
|
668
|
-
this.
|
|
828
|
+
this.IsRecording = true;
|
|
669
829
|
this.currentEgressId = result.EgressID;
|
|
670
830
|
}
|
|
671
831
|
else {
|
|
@@ -674,17 +834,21 @@ export class MJLiveKitRoomComponent extends BaseAngularComponent {
|
|
|
674
834
|
}
|
|
675
835
|
else if (this.currentEgressId) {
|
|
676
836
|
const stopped = await client.StopRecording(this.currentEgressId);
|
|
677
|
-
this.
|
|
837
|
+
this.IsRecording = false;
|
|
678
838
|
this.currentEgressId = null;
|
|
679
839
|
// The server registers the egress MP4 as an MJ: Files row on stop and returns its id — surface it
|
|
680
840
|
// in the playback panel. Absent when meeting-recording storage isn't configured server-side.
|
|
681
841
|
if (stopped.Success && stopped.RecordingFileID) {
|
|
682
|
-
this.
|
|
683
|
-
this.
|
|
842
|
+
this.RecordingFileId = stopped.RecordingFileID;
|
|
843
|
+
this.ShowRecordingPanel = true;
|
|
684
844
|
}
|
|
685
845
|
}
|
|
686
846
|
this.cdr.markForCheck();
|
|
687
847
|
}
|
|
848
|
+
/** @deprecated Use {@link OnToggleRecording}. */
|
|
849
|
+
async onToggleRecording() {
|
|
850
|
+
return this.OnToggleRecording();
|
|
851
|
+
}
|
|
688
852
|
/**
|
|
689
853
|
* Resolves this room's already-registered meeting recording (if any) — the `MJ: Conversations` of
|
|
690
854
|
* `Type='Meeting Room'` keyed by the room name carries the `RecordingFileID`. Best-effort: any failure
|
|
@@ -705,7 +869,7 @@ export class MJLiveKitRoomComponent extends BaseAngularComponent {
|
|
|
705
869
|
}, this.ProviderToUse.CurrentUser);
|
|
706
870
|
const fileId = result.Success ? result.Results[0]?.RecordingFileID ?? null : null;
|
|
707
871
|
if (fileId) {
|
|
708
|
-
this.
|
|
872
|
+
this.RecordingFileId = fileId;
|
|
709
873
|
this.cdr.markForCheck();
|
|
710
874
|
}
|
|
711
875
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mj-livekit-room.component.js","sourceRoot":"","sources":["../../src/lib/mj-livekit-room.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewChild, inject } from '@angular/core';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { RunView } from '@memberjunction/core';\nimport { GraphQLDataProvider, GraphQLLiveKitClient, RealtimeModelVoices, RealtimeVoiceOption } from '@memberjunction/graphql-dataprovider';\nimport { LiveKitRoomComponent, type LiveKitRoomLayout } from '@memberjunction/ng-livekit-room';\nimport { MJStorageMediaPlayerComponent } from '@memberjunction/ng-media-player';\nimport type {\n LiveKitDataMessage,\n LiveKitDisconnectedEvent,\n LiveKitParticipantJoinedEvent,\n LiveKitParticipantLeftEvent,\n LiveKitRoomError,\n LiveKitRoomState,\n} from '@memberjunction/livekit-room-core';\n\n/** How the MJ binding obtains its room: start an agent in a room, or just join an existing room. */\nexport type MJLiveKitConnectionMode = 'agent' | 'join';\n\n/** Emitted when an agent room session has been started server-side. */\nexport interface MJLiveKitSessionStartedEvent {\n /** The durable bridge-session row id. */\n SessionBridgeID: string;\n /** The room name. */\n RoomName: string;\n}\n\n/** One agent bot bridged into the room — tracked for the in-room add/remove roster. */\nexport interface AgentInRoom {\n /** The `MJ: AI Agent Session Bridges` row id (used to stop/remove this agent). */\n SessionBridgeID: string;\n /** The target agent this bot voices, when known. */\n TargetAgentID: string | null;\n /** Display name (the target agent's name). */\n Name: string;\n /** True while a remove request is in flight. */\n Removing?: boolean;\n}\n\n/**\n * `mj-livekit-agent-room` — the MemberJunction binding for the LiveKit room UI. It resolves a scoped\n * access token (and, in `'agent'` mode, starts the agent's presence in the room) via the RealtimeBridge\n * GraphQL surface, then renders {@link LiveKitRoomComponent} with the resolved connection. All the rich\n * feature gates of the generic component are forwarded; MJ user/provider context is threaded in.\n *\n * Public members are PascalCase (MJ convention); private members are camelCase.\n */\n@Component({\n selector: 'mj-livekit-agent-room',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [LiveKitRoomComponent, MJStorageMediaPlayerComponent],\n template: `\n @if (recordingFileId && showRecordingPanel) {\n <div class=\"mj-lk-recording\">\n <div class=\"mj-lk-recording__head\">\n <span class=\"mj-lk-recording__title\"><i class=\"fa-solid fa-circle-play\"></i> Meeting recording</span>\n <button type=\"button\" class=\"mj-lk-recording__close\" title=\"Dismiss\" (click)=\"showRecordingPanel = false\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <mj-storage-media-player [FileID]=\"recordingFileId\" [Provider]=\"Provider\"></mj-storage-media-player>\n </div>\n }\n @if (loading) {\n <div class=\"mj-lk-status\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>{{ Mode === 'agent' ? 'Starting agent session…' : 'Joining room…' }}</span>\n </div>\n } @else if (errorMessage) {\n <div class=\"mj-lk-status mj-lk-status--error\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n <span>{{ errorMessage }}</span>\n <button type=\"button\" class=\"mj-lk-retry\" (click)=\"Start()\">Try again</button>\n </div>\n } @else if (serverUrl && token) {\n <div class=\"mj-lk-room-wrap\">\n <mj-livekit-room\n [ServerUrl]=\"serverUrl\"\n [Token]=\"token\"\n [DisplayName]=\"resolvedDisplayName\"\n [AutoConnect]=\"true\"\n [StartWithMicrophone]=\"StartWithMicrophone\"\n [StartWithCamera]=\"StartWithCamera\"\n [Layout]=\"Layout\"\n [Title]=\"Title\"\n [ShowHeader]=\"ShowHeader\"\n [ShowControlBar]=\"ShowControlBar\"\n [ShowChat]=\"ShowChat\"\n [ShowParticipantsPanel]=\"ShowParticipantsPanel\"\n [EnableMicrophoneControl]=\"EnableMicrophoneControl\"\n [EnableCameraControl]=\"EnableCameraControl\"\n [EnableScreenShareControl]=\"EnableScreenShareControl\"\n [EnableDeviceSettings]=\"EnableDeviceSettings\"\n [EnableLeaveControl]=\"EnableLeaveControl\"\n [EnablePinning]=\"EnablePinning\"\n [EnableLayoutSwitcher]=\"EnableLayoutSwitcher\"\n [EnableNoiseFilter]=\"EnableNoiseFilter\"\n [EnableBackgroundEffects]=\"EnableBackgroundEffects\"\n [ShowAgentState]=\"ShowAgentState\"\n [ShowWhiteboard]=\"ShowWhiteboard\"\n [ShowPreJoin]=\"ShowPreJoin\"\n [ShowRecordingControl]=\"EnableRecording\"\n [IsRecording]=\"isRecording\"\n [E2EEPassphrase]=\"E2EEPassphrase\"\n [E2EEWorker]=\"E2EEWorker\"\n [AgentAvatarUrl]=\"AgentAvatarUrl\"\n [CanEndForAll]=\"EnableEndForAll && !!resolvedRoomName\"\n (Connected)=\"Connected.emit($event)\"\n (Disconnected)=\"Disconnected.emit($event)\"\n (EndForAll)=\"EndMeeting()\"\n (ParticipantJoined)=\"ParticipantJoined.emit($event)\"\n (ParticipantLeft)=\"ParticipantLeft.emit($event)\"\n (DataReceived)=\"DataReceived.emit($event)\"\n (ToggleRecording)=\"onToggleRecording()\"\n (ErrorOccurred)=\"ErrorOccurred.emit($event)\"\n ></mj-livekit-room>\n\n @if (Mode === 'agent' && EnableAgentManagement && resolvedRoomName) {\n <div class=\"mj-lk-agents\">\n @if (showAgentsPanel) {\n <div class=\"mj-lk-agents__panel\">\n <div class=\"mj-lk-agents__head\">In this room</div>\n @for (a of agentsInRoom; track a.SessionBridgeID) {\n <div class=\"mj-lk-agents__row\">\n <span class=\"mj-lk-agents__name\"><i class=\"fa-solid fa-robot\"></i> {{ a.Name }}</span>\n <button type=\"button\" class=\"mj-lk-agents__remove\" title=\"Remove agent\"\n [disabled]=\"a.Removing\" (click)=\"RemoveAgent(a)\">\n <i class=\"fa-solid\" [class.fa-xmark]=\"!a.Removing\" [class.fa-spinner]=\"a.Removing\" [class.fa-spin]=\"a.Removing\"></i>\n </button>\n </div>\n }\n @if (availableToAdd.length) {\n <div class=\"mj-lk-agents__add\">\n <select class=\"mj-input mj-lk-agents__select\" (change)=\"onAddTargetChange($event)\">\n <option value=\"\">Add an agent…</option>\n @for (a of availableToAdd; track a.ID) {\n <option [value]=\"a.ID\" [selected]=\"UUIDsEqual(a.ID, addTargetId)\">{{ a.Name }}</option>\n }\n </select>\n <button type=\"button\" class=\"mj-lk-agents__addbtn\" [disabled]=\"!addTargetId || addingAgent\" (click)=\"AddAgent()\">\n <i class=\"fa-solid\" [class.fa-plus]=\"!addingAgent\" [class.fa-spinner]=\"addingAgent\" [class.fa-spin]=\"addingAgent\"></i>\n </button>\n </div>\n @if (CanPickModelVoice && AvailableModels.length) {\n <div class=\"mj-lk-agents__overrides\">\n <select class=\"mj-input mj-lk-agents__select mj-lk-agents__select--sm\" (change)=\"onAddModelChange($event)\" title=\"Model (dev override)\">\n <option value=\"\">Default model</option>\n @for (m of AvailableModels; track m.ModelID) {\n <option [value]=\"m.ModelID\" [selected]=\"UUIDsEqual(m.ModelID, addModelId)\">{{ m.ModelName }}</option>\n }\n </select>\n @if (addVoices.length) {\n <select class=\"mj-input mj-lk-agents__select mj-lk-agents__select--sm\" (change)=\"onAddVoiceChange($event)\" title=\"Voice (dev override)\">\n <option value=\"\">Default voice</option>\n @for (v of addVoices; track v.ID) {\n <option [value]=\"v.ID\" [selected]=\"v.ID === addVoice\">{{ v.Name }}</option>\n }\n </select>\n }\n </div>\n }\n }\n @if (addError) {\n <div class=\"mj-lk-agents__error\">{{ addError }}</div>\n }\n </div>\n }\n <div class=\"mj-lk-agents__pills\">\n <button type=\"button\" class=\"mj-lk-agents__toggle\" (click)=\"showAgentsPanel = !showAgentsPanel\">\n <i class=\"fa-solid fa-robot\"></i> Agents ({{ agentsInRoom.length }})\n </button>\n @if (EnableInvite) {\n <button type=\"button\" class=\"mj-lk-agents__toggle\" title=\"Copy a link to invite someone to this room\"\n (click)=\"CopyInvite()\">\n <i class=\"fa-solid\" [class.fa-link]=\"!inviteCopied\" [class.fa-check]=\"inviteCopied\"></i>\n {{ inviteCopied ? 'Link copied' : 'Copy link' }}\n </button>\n <button type=\"button\" class=\"mj-lk-agents__toggle\" title=\"Invite people from this workspace\"\n (click)=\"InvitePeopleRequested.emit(resolvedRoomName)\">\n <i class=\"fa-solid fa-user-plus\"></i> Invite people\n </button>\n }\n </div>\n </div>\n }\n </div>\n }\n `,\n styles: [\n `\n :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n .mj-lk-status {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 10px;\n height: 100%;\n min-height: 220px;\n color: var(--mj-text-secondary, #475569);\n background: var(--mj-bg-surface-card, #f1f5f9);\n border-radius: 12px;\n }\n .mj-lk-status i {\n font-size: 1.6rem;\n color: var(--mj-brand-primary, #0076b6);\n }\n .mj-lk-status--error i {\n color: var(--mj-status-error, #ef4444);\n }\n .mj-lk-retry {\n padding: 7px 16px;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n color: var(--mj-text-inverse, #fff);\n background: var(--mj-brand-primary, #0076b6);\n }\n .mj-lk-room-wrap {\n position: relative;\n width: 100%;\n height: 100%;\n }\n .mj-lk-agents {\n position: absolute;\n left: 16px;\n bottom: 84px;\n z-index: 40;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n }\n .mj-lk-agents__pills {\n display: flex;\n gap: 8px;\n }\n .mj-lk-agents__toggle {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 7px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 999px;\n cursor: pointer;\n font-size: 0.8125rem;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-elevated, var(--mj-bg-surface));\n box-shadow: var(--mj-shadow-sm, 0 2px 8px rgba(0, 0, 0, 0.18));\n }\n .mj-lk-agents__panel {\n width: 260px;\n padding: 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n background: var(--mj-bg-surface-elevated, var(--mj-bg-surface));\n box-shadow: var(--mj-shadow-md, 0 6px 20px rgba(0, 0, 0, 0.25));\n }\n .mj-lk-agents__head {\n font-size: 0.6875rem;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-muted);\n margin-bottom: 6px;\n }\n .mj-lk-agents__row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 5px 0;\n }\n .mj-lk-agents__name {\n display: inline-flex;\n align-items: center;\n gap: 7px;\n font-size: 0.8125rem;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .mj-lk-agents__name i {\n color: var(--mj-brand-primary);\n }\n .mj-lk-agents__remove {\n flex: none;\n width: 26px;\n height: 26px;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n color: var(--mj-text-muted);\n background: transparent;\n }\n .mj-lk-agents__remove:hover:not(:disabled) {\n color: var(--mj-status-error);\n background: var(--mj-bg-surface-hover);\n }\n .mj-lk-agents__add {\n display: flex;\n gap: 6px;\n margin-top: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--mj-border-subtle, var(--mj-border-default));\n }\n .mj-lk-agents__select {\n flex: 1;\n min-width: 0;\n font-size: 0.8125rem;\n }\n .mj-lk-agents__overrides {\n display: flex;\n gap: 6px;\n margin-top: 6px;\n }\n .mj-lk-agents__select--sm {\n font-size: 0.75rem;\n }\n .mj-lk-agents__addbtn {\n flex: none;\n width: 32px;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n }\n .mj-lk-agents__addbtn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n .mj-lk-agents__error {\n margin-top: 6px;\n font-size: 0.75rem;\n color: var(--mj-status-error-text, var(--mj-status-error));\n }\n .mj-lk-recording {\n margin-bottom: 12px;\n padding: 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n background: var(--mj-bg-surface-card, var(--mj-bg-surface));\n }\n .mj-lk-recording__head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 8px;\n }\n .mj-lk-recording__title {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n .mj-lk-recording__title i {\n color: var(--mj-brand-primary);\n }\n .mj-lk-recording__close {\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n color: var(--mj-text-muted);\n background: transparent;\n }\n .mj-lk-recording__close:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n }\n `,\n ],\n})\nexport class MJLiveKitRoomComponent extends BaseAngularComponent implements OnInit {\n private readonly cdr = inject(ChangeDetectorRef);\n\n // ── MJ connection inputs ───────────────────────────────────────────────────────\n /** Whether to start an agent in the room (`'agent'`) or just join an existing room (`'join'`). */\n @Input() public Mode: MJLiveKitConnectionMode = 'agent';\n /** The agent to voice (agent mode) — the Realtime Co-Agent / voice front-end. */\n @Input() public AgentID: string | null = null;\n /** The agent's display name (bot name + addressing). */\n @Input() public AgentName: string | null = null;\n /**\n * The TARGET agent the co-agent voices — the one being \"called\". The Realtime Co-Agent delegates to\n * it via `invoke-target-agent`; without it the agent has nobody to speak for and stays idle.\n */\n @Input() public TargetAgentID: string | null = null;\n /** The room name. Required for `'join'` mode; optional for `'agent'` (server generates one). */\n @Input() public RoomName: string | null = null;\n /** The display name the local user joins as. Defaults to the authenticated user server-side. */\n @Input() public DisplayName: string | null = null;\n /** Turn-taking mode for the agent. */\n @Input() public TurnMode: 'Passive' | 'Active' | 'Hybrid' | null = null;\n /** Resolve the connection automatically on init. */\n @Input() public AutoStart = true;\n\n // ── In-room agent management (agent mode) ─────────────────────────────────────────\n /** Show the in-room \"Agents\" panel to add/remove agents (agent mode only). */\n @Input() public EnableAgentManagement = true;\n /** Show the \"Invite\" pill that copies a join link to this room. */\n @Input() public EnableInvite = true;\n /**\n * Offer \"End meeting for everyone\" in the control bar's Zoom-style leave menu. When on (default) and a\n * room is resolved, ending tears down every agent in the room server-side (by name — so it works even\n * when this client only *joined*). Set `false` for contexts where only the local user should ever leave.\n */\n @Input() public EnableEndForAll = true;\n /** Target agents the user can ADD in-room (id + name). The host (e.g. the Explorer resource) supplies these. */\n @Input() public AvailableAgents: { ID: string; Name: string }[] = [];\n\n /** Per-session Realtime MODEL override for the INITIAL agent (from the host's pre-join picker). */\n @Input() public RealtimeModelID: string | null = null;\n /** Per-session VOICE override for the INITIAL agent (from the host's pre-join picker). */\n @Input() public RealtimeVoice: string | null = null;\n /**\n * Whether the dev model/voice pickers are shown in the in-room \"Add an agent\" control. The HOST\n * computes this (the `Realtime: Advanced Session Controls` authorization) and passes it down — this\n * generic component never evaluates authorizations itself.\n */\n @Input() public CanPickModelVoice = false;\n /** Active Realtime models + their voices, supplied by the host (for the add-agent dropdowns). */\n @Input() public AvailableModels: RealtimeModelVoices[] = [];\n\n /** True briefly after the invite link is copied (drives the \"Link copied\" pill state). */\n public inviteCopied = false;\n\n /** Whether the floating agents panel is open. */\n public showAgentsPanel = false;\n /** The agent bots currently bridged into the room (the first is the one started on join). */\n public agentsInRoom: AgentInRoom[] = [];\n /** The target id chosen in the \"Add an agent\" picker. */\n public addTargetId: string | null = null;\n /** The MODEL override chosen in the \"Add an agent\" picker (dev-only; null = co-agent/target default). */\n public addModelId: string | null = null;\n /** The VOICE override chosen in the \"Add an agent\" picker (dev-only; null = co-agent/target default). */\n public addVoice: string | null = null;\n /** Exposed for template use — platform-safe UUID equality (SQL upper vs PG lower). */\n public UUIDsEqual = UUIDsEqual;\n /** True while an Add request is in flight. */\n public addingAgent = false;\n /** Last add error, shown under the picker. */\n public addError: string | null = null;\n /** True while an \"End meeting\" (stop all agents + leave) is in flight. */\n public endingMeeting = false;\n\n /** The inner Generic room — used to trigger the local disconnect when ending/leaving the meeting. */\n @ViewChild(LiveKitRoomComponent) private roomComponent?: LiveKitRoomComponent;\n\n /** Available agents not already in the room (by target id) — the \"Add\" picker options. */\n public get availableToAdd(): { ID: string; Name: string }[] {\n const present = new Set(this.agentsInRoom.map((a) => (a.TargetAgentID ?? '').toLowerCase()));\n return this.AvailableAgents.filter((a) => !present.has(a.ID.toLowerCase()));\n }\n\n /** Voices for the model chosen in the add-agent picker (empty when no model picked or it has none). */\n public get addVoices(): RealtimeVoiceOption[] {\n const model = this.AvailableModels.find((m) => UUIDsEqual(m.ModelID, this.addModelId));\n return model?.Voices ?? [];\n }\n\n /** Records the add-agent MODEL choice; clears the voice so it can't outlive a model switch. */\n public onAddModelChange(event: Event): void {\n this.addModelId = (event.target as HTMLSelectElement).value || null;\n this.addVoice = null;\n }\n\n /** Records the add-agent VOICE choice. */\n public onAddVoiceChange(event: Event): void {\n this.addVoice = (event.target as HTMLSelectElement).value || null;\n }\n\n // ── Forwarded UI gates (see LiveKitRoomComponent) ────────────────────────────────\n /** @see LiveKitRoomComponent.Layout */\n @Input() public Layout: LiveKitRoomLayout = 'grid';\n /** @see LiveKitRoomComponent.Title */\n @Input() public Title: string | null = null;\n /** @see LiveKitRoomComponent.ShowHeader */\n @Input() public ShowHeader = true;\n /** @see LiveKitRoomComponent.ShowControlBar */\n @Input() public ShowControlBar = true;\n /** @see LiveKitRoomComponent.ShowChat */\n @Input() public ShowChat = true;\n /** @see LiveKitRoomComponent.ShowParticipantsPanel */\n @Input() public ShowParticipantsPanel = true;\n /** @see LiveKitRoomComponent.EnableMicrophoneControl */\n @Input() public EnableMicrophoneControl = true;\n /** @see LiveKitRoomComponent.EnableCameraControl */\n @Input() public EnableCameraControl = true;\n /** @see LiveKitRoomComponent.EnableScreenShareControl */\n @Input() public EnableScreenShareControl = true;\n /** @see LiveKitRoomComponent.EnableDeviceSettings */\n @Input() public EnableDeviceSettings = true;\n /** @see LiveKitRoomComponent.EnableLeaveControl */\n @Input() public EnableLeaveControl = true;\n /** @see LiveKitRoomComponent.StartWithMicrophone */\n @Input() public StartWithMicrophone = true;\n /** @see LiveKitRoomComponent.StartWithCamera */\n @Input() public StartWithCamera = false;\n /** @see LiveKitRoomComponent.AgentAvatarUrl */\n @Input() public AgentAvatarUrl: string | null = null;\n /** @see LiveKitRoomComponent.EnablePinning */\n @Input() public EnablePinning = true;\n /** @see LiveKitRoomComponent.EnableLayoutSwitcher */\n @Input() public EnableLayoutSwitcher = true;\n /** @see LiveKitRoomComponent.EnableNoiseFilter */\n @Input() public EnableNoiseFilter = false;\n /** @see LiveKitRoomComponent.EnableBackgroundEffects */\n @Input() public EnableBackgroundEffects = false;\n /** @see LiveKitRoomComponent.ShowAgentState */\n @Input() public ShowAgentState = false;\n /** @see LiveKitRoomComponent.ShowWhiteboard */\n @Input() public ShowWhiteboard = false;\n /** @see LiveKitRoomComponent.ShowPreJoin */\n @Input() public ShowPreJoin = false;\n /** Enable the server-authorized recording control (composite egress). */\n @Input() public EnableRecording = false;\n /** @see LiveKitRoomComponent.E2EEPassphrase */\n @Input() public E2EEPassphrase: string | null = null;\n /** @see LiveKitRoomComponent.E2EEWorker */\n @Input() public E2EEWorker: Worker | null = null;\n\n // ── Outputs ────────────────────────────────────────────────────────────────────\n /** Emitted once the agent room session is started (agent mode). */\n @Output() public SessionStarted = new EventEmitter<MJLiveKitSessionStartedEvent>();\n /**\n * Emitted (with the room name) when the user clicks \"Invite people\". The host (e.g. the Explorer\n * resource) opens an MJ user-picker and calls the invite mutation — kept out of this generic\n * component, which knows nothing about MJ users.\n */\n @Output() public InvitePeopleRequested = new EventEmitter<string>();\n /** Emitted when the room connects. */\n @Output() public Connected = new EventEmitter<LiveKitRoomState>();\n /** Emitted when the room disconnects. */\n @Output() public Disconnected = new EventEmitter<LiveKitDisconnectedEvent>();\n /** Emitted when a participant joins. */\n @Output() public ParticipantJoined = new EventEmitter<LiveKitParticipantJoinedEvent>();\n /** Emitted when a participant leaves. */\n @Output() public ParticipantLeft = new EventEmitter<LiveKitParticipantLeftEvent>();\n /** Emitted for inbound data-channel messages. */\n @Output() public DataReceived = new EventEmitter<LiveKitDataMessage>();\n /** Emitted on room errors (and on token/session-resolution failures). */\n @Output() public ErrorOccurred = new EventEmitter<LiveKitRoomError>();\n\n // ── View state ─────────────────────────────────────────────────────────────────\n /** Whether the binding is resolving the token/session. */\n public loading = false;\n /** The token/session-resolution error, if any. */\n public errorMessage: string | null = null;\n /** The resolved LiveKit server URL. */\n public serverUrl: string | null = null;\n /** The resolved access token. */\n public token: string | null = null;\n /** The display name passed to the room. */\n public resolvedDisplayName: string | null = null;\n /** The resolved room name (for recording calls). */\n public resolvedRoomName: string | null = null;\n /** Whether a recording is currently in progress. */\n public isRecording = false;\n /** The active egress id, when recording. */\n private currentEgressId: string | null = null;\n\n /**\n * The `MJ: Files` id of this room's meeting recording, when one exists — set when a recording is STOPPED\n * (the server registers the egress MP4 and returns its file id) or resolved for an already-recorded room\n * on join. Drives the {@link MJStorageMediaPlayerComponent} playback panel.\n */\n public recordingFileId: string | null = null;\n /** Whether the recording playback panel is shown (dismissable). */\n public showRecordingPanel = true;\n\n public ngOnInit(): void {\n if (this.AutoStart) {\n void this.Start();\n }\n // If this room already has a registered recording (e.g. joining/reviewing a past room), surface it.\n if (this.RoomName) {\n void this.loadExistingRecording(this.RoomName);\n }\n }\n\n /**\n * Max time to wait for the connection to start before surfacing a retryable error, so a hung or very\n * slow server (e.g. an agent bot that can't reach the LiveKit media path) doesn't spin forever. Set\n * `0` to disable the client-side timeout.\n */\n @Input() public ConnectTimeoutMs = 25000;\n\n /** Resolves the connection (mints a token and, in agent mode, starts the agent session). */\n public async Start(): Promise<void> {\n this.loading = true;\n this.errorMessage = null;\n this.cdr.markForCheck();\n try {\n const client = new GraphQLLiveKitClient(this.ProviderToUse as unknown as GraphQLDataProvider);\n this.resolvedDisplayName = this.DisplayName;\n const connect = this.Mode === 'agent' ? this.startAgentSession(client) : this.joinRoom(client);\n await this.withTimeout(connect, this.ConnectTimeoutMs);\n } catch (err) {\n this.fail(err instanceof Error ? err.message : String(err));\n } finally {\n this.loading = false;\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Races `op` against a timeout: if it hasn't settled within `ms`, rejects with a clear, retryable\n * message (the template's \"Try again\" button re-runs {@link Start}). A non-positive `ms` disables it.\n */\n private withTimeout<T>(op: Promise<T>, ms: number): Promise<T> {\n if (!ms || ms <= 0) {\n return op;\n }\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(\n () =>\n reject(\n new Error(\n 'The connection is taking too long — the agent could not join the room. ' +\n 'Check that the LiveKit server is running and reachable, then try again.',\n ),\n ),\n ms,\n );\n op.then(\n (value) => {\n clearTimeout(timer);\n resolve(value);\n },\n (error) => {\n clearTimeout(timer);\n reject(error);\n },\n );\n });\n }\n\n /** Starts the agent room session and applies the returned client token. */\n private async startAgentSession(client: GraphQLLiveKitClient): Promise<void> {\n const result = await client.StartAgentRoomSession({\n AgentID: this.AgentID ?? undefined,\n AgentName: this.AgentName ?? undefined,\n TargetAgentID: this.TargetAgentID ?? undefined,\n RealtimeModelID: this.RealtimeModelID ?? undefined,\n RealtimeVoice: this.RealtimeVoice ?? undefined,\n RoomName: this.RoomName ?? undefined,\n TurnMode: this.TurnMode ?? undefined,\n });\n if (!result.Success) {\n this.fail(result.ErrorMessage ?? 'Failed to start the agent session.');\n return;\n }\n this.serverUrl = result.ServerUrl;\n this.token = result.ClientToken;\n this.resolvedRoomName = result.RoomName;\n // Surface a prior recording for this resolved room (the server may have generated the room name).\n void this.loadExistingRecording(result.RoomName);\n // Track the agent we just brought in as the first entry in the in-room roster.\n this.agentsInRoom = [\n { SessionBridgeID: result.SessionBridgeID, TargetAgentID: this.TargetAgentID, Name: this.AgentName ?? 'Agent' },\n ];\n this.SessionStarted.emit({ SessionBridgeID: result.SessionBridgeID, RoomName: result.RoomName });\n }\n\n /** Picker selection handler for the in-room \"Add an agent\" control (native select; no FormsModule dep). */\n public onAddTargetChange(event: Event): void {\n this.addTargetId = (event.target as HTMLSelectElement).value || null;\n this.addError = null;\n }\n\n /**\n * Adds another agent to the SAME room — starts a new bridge (the co-agent voicing the chosen target)\n * and appends it to the roster. The new bot joins the live room alongside the existing participants.\n */\n public async AddAgent(): Promise<void> {\n if (!this.addTargetId || !this.resolvedRoomName || this.addingAgent) {\n return;\n }\n const target = this.AvailableAgents.find((a) => UUIDsEqual(a.ID, this.addTargetId));\n this.addingAgent = true;\n this.addError = null;\n this.cdr.markForCheck();\n try {\n const client = new GraphQLLiveKitClient(this.ProviderToUse as unknown as GraphQLDataProvider);\n const result = await client.StartAgentRoomSession({\n AgentID: this.AgentID ?? undefined,\n AgentName: target?.Name ?? undefined,\n TargetAgentID: this.addTargetId,\n RealtimeModelID: this.addModelId ?? undefined,\n RealtimeVoice: this.addVoice ?? undefined,\n RoomName: this.resolvedRoomName,\n TurnMode: this.TurnMode ?? undefined,\n });\n if (!result.Success) {\n this.addError = result.ErrorMessage ?? 'Failed to add the agent.';\n return;\n }\n this.agentsInRoom = [\n ...this.agentsInRoom,\n { SessionBridgeID: result.SessionBridgeID, TargetAgentID: this.addTargetId, Name: target?.Name ?? 'Agent' },\n ];\n this.addTargetId = null;\n this.addModelId = null;\n this.addVoice = null;\n } catch (err) {\n this.addError = err instanceof Error ? err.message : String(err);\n } finally {\n this.addingAgent = false;\n this.cdr.markForCheck();\n }\n }\n\n /** Removes an agent from the room — stops its bridge and drops it from the roster. */\n public async RemoveAgent(agent: AgentInRoom): Promise<void> {\n if (agent.Removing) {\n return;\n }\n agent.Removing = true;\n this.cdr.markForCheck();\n try {\n const client = new GraphQLLiveKitClient(this.ProviderToUse as unknown as GraphQLDataProvider);\n const ok = await client.StopAgentRoomSession(agent.SessionBridgeID);\n if (ok) {\n this.agentsInRoom = this.agentsInRoom.filter((a) => a.SessionBridgeID !== agent.SessionBridgeID);\n } else {\n agent.Removing = false;\n }\n } catch {\n agent.Removing = false;\n } finally {\n this.cdr.markForCheck();\n }\n }\n\n /**\n * **End meeting** (the Zoom/Teams \"End for all\", reached from the control-bar leave menu): tears down EVERY\n * agent in the room server-side — *by room name*, so it works even when this client only **joined** the room\n * and never tracked the bridge ids locally — then disconnects the local user. Contrast with **Leave** (the\n * other menu item → {@link LiveKitRoomComponent.Leave}), which only disconnects YOU and lets the meeting\n * continue; the server then auto-leaves the agents once the last human is gone, so neither path strands\n * billable agent sessions in an empty room.\n */\n public async EndMeeting(): Promise<void> {\n if (this.endingMeeting) {\n return;\n }\n this.endingMeeting = true;\n this.cdr.markForCheck();\n try {\n if (this.resolvedRoomName) {\n const client = new GraphQLLiveKitClient(this.ProviderToUse as unknown as GraphQLDataProvider);\n await client.EndRoom(this.resolvedRoomName);\n }\n this.agentsInRoom = [];\n } catch {\n /* best-effort — fall through and still disconnect the local user */\n } finally {\n await this.roomComponent?.Leave();\n this.endingMeeting = false;\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Builds the shareable invite URL for THIS room: the current page URL with a `room=<roomName>` query\n * param. Opening it lands the invitee on the Live Room in join mode for the same room.\n */\n public get inviteUrl(): string {\n const url = new URL(window.location.href);\n url.searchParams.set('room', this.resolvedRoomName ?? '');\n return url.toString();\n }\n\n /** Copies {@link inviteUrl} to the clipboard and flips the pill to \"Link copied\" briefly. */\n public async CopyInvite(): Promise<void> {\n if (!this.resolvedRoomName) {\n return;\n }\n try {\n await navigator.clipboard.writeText(this.inviteUrl);\n this.inviteCopied = true;\n this.cdr.markForCheck();\n setTimeout(() => {\n this.inviteCopied = false;\n this.cdr.markForCheck();\n }, 2000);\n } catch {\n // Clipboard blocked (insecure context / permissions) — leave the pill unchanged.\n }\n }\n\n /** Joins an existing room by minting a client token. */\n private async joinRoom(client: GraphQLLiveKitClient): Promise<void> {\n if (!this.RoomName) {\n this.fail('RoomName is required when Mode is \"join\".');\n return;\n }\n const result = await client.MintClientToken({ RoomName: this.RoomName, DisplayName: this.DisplayName ?? undefined });\n if (!result.Success) {\n this.fail(result.ErrorMessage ?? 'Failed to obtain a room token.');\n return;\n }\n this.serverUrl = result.ServerUrl;\n this.token = result.Token;\n this.resolvedRoomName = this.RoomName;\n }\n\n /** Toggles room recording via the RealtimeBridge GraphQL surface (server-authorized egress). */\n public async onToggleRecording(): Promise<void> {\n if (!this.resolvedRoomName) {\n return;\n }\n const client = new GraphQLLiveKitClient(this.ProviderToUse as unknown as GraphQLDataProvider);\n if (!this.isRecording) {\n const result = await client.StartRecording(this.resolvedRoomName);\n if (result.Success) {\n this.isRecording = true;\n this.currentEgressId = result.EgressID;\n } else {\n this.fail(result.ErrorMessage ?? 'Failed to start recording.');\n }\n } else if (this.currentEgressId) {\n const stopped = await client.StopRecording(this.currentEgressId);\n this.isRecording = false;\n this.currentEgressId = null;\n // The server registers the egress MP4 as an MJ: Files row on stop and returns its id — surface it\n // in the playback panel. Absent when meeting-recording storage isn't configured server-side.\n if (stopped.Success && stopped.RecordingFileID) {\n this.recordingFileId = stopped.RecordingFileID;\n this.showRecordingPanel = true;\n }\n }\n this.cdr.markForCheck();\n }\n\n /**\n * Resolves this room's already-registered meeting recording (if any) — the `MJ: Conversations` of\n * `Type='Meeting Room'` keyed by the room name carries the `RecordingFileID`. Best-effort: any failure\n * just leaves the playback panel hidden.\n *\n * @param roomName The LiveKit room name (= the Meeting-Room Conversation's `ExternalID`).\n */\n private async loadExistingRecording(roomName: string): Promise<void> {\n try {\n const escaped = roomName.replace(/'/g, \"''\");\n const result = await RunView.FromMetadataProvider(this.ProviderToUse).RunView<{ RecordingFileID: string | null }>(\n {\n EntityName: 'MJ: Conversations',\n ExtraFilter: `ExternalID='${escaped}' AND Type='Meeting Room' AND RecordingFileID IS NOT NULL`,\n Fields: ['RecordingFileID'],\n OrderBy: '__mj_CreatedAt DESC',\n MaxRows: 1,\n ResultType: 'simple',\n },\n this.ProviderToUse.CurrentUser,\n );\n const fileId = result.Success ? result.Results[0]?.RecordingFileID ?? null : null;\n if (fileId) {\n this.recordingFileId = fileId;\n this.cdr.markForCheck();\n }\n } catch {\n // best-effort — no recording panel\n }\n }\n\n /** Records a failure and emits an error event. */\n private fail(message: string): void {\n this.errorMessage = message;\n this.ErrorOccurred.emit({ Kind: 'connect', Message: message });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"mj-livekit-room.component.js","sourceRoot":"","sources":["../../src/lib/mj-livekit-room.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewChild, inject } from '@angular/core';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { RunView } from '@memberjunction/core';\nimport { GraphQLDataProvider, GraphQLLiveKitClient, RealtimeModelVoices, RealtimeVoiceOption } from '@memberjunction/graphql-dataprovider';\nimport { LiveKitRoomComponent, type LiveKitRoomLayout } from '@memberjunction/ng-livekit-room';\nimport { MJStorageMediaPlayerComponent } from '@memberjunction/ng-media-player';\nimport type {\n LiveKitDataMessage,\n LiveKitDisconnectedEvent,\n LiveKitParticipantJoinedEvent,\n LiveKitParticipantLeftEvent,\n LiveKitRoomError,\n LiveKitRoomState,\n} from '@memberjunction/livekit-room-core';\n\n/** How the MJ binding obtains its room: start an agent in a room, or just join an existing room. */\nexport type MJLiveKitConnectionMode = 'agent' | 'join';\n\n/** Emitted when an agent room session has been started server-side. */\nexport interface MJLiveKitSessionStartedEvent {\n /** The durable bridge-session row id. */\n SessionBridgeID: string;\n /** The room name. */\n RoomName: string;\n}\n\n/** One agent bot bridged into the room — tracked for the in-room add/remove roster. */\nexport interface AgentInRoom {\n /** The `MJ: AI Agent Session Bridges` row id (used to stop/remove this agent). */\n SessionBridgeID: string;\n /** The target agent this bot voices, when known. */\n TargetAgentID: string | null;\n /** Display name (the target agent's name). */\n Name: string;\n /** True while a remove request is in flight. */\n Removing?: boolean;\n}\n\n/**\n * `mj-livekit-agent-room` — the MemberJunction binding for the LiveKit room UI. It resolves a scoped\n * access token (and, in `'agent'` mode, starts the agent's presence in the room) via the RealtimeBridge\n * GraphQL surface, then renders {@link LiveKitRoomComponent} with the resolved connection. All the rich\n * feature gates of the generic component are forwarded; MJ user/provider context is threaded in.\n *\n * Public members are PascalCase (MJ convention); private members are camelCase.\n */\n@Component({\n selector: 'mj-livekit-agent-room',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [LiveKitRoomComponent, MJStorageMediaPlayerComponent],\n template: `\n @if (recordingFileId && showRecordingPanel) {\n <div class=\"mj-lk-recording\">\n <div class=\"mj-lk-recording__head\">\n <span class=\"mj-lk-recording__title\"><i class=\"fa-solid fa-circle-play\"></i> Meeting recording</span>\n <button type=\"button\" class=\"mj-lk-recording__close\" title=\"Dismiss\" (click)=\"showRecordingPanel = false\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n <mj-storage-media-player [FileID]=\"recordingFileId\" [Provider]=\"Provider\"></mj-storage-media-player>\n </div>\n }\n @if (loading) {\n <div class=\"mj-lk-status\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>{{ Mode === 'agent' ? 'Starting agent session…' : 'Joining room…' }}</span>\n </div>\n } @else if (errorMessage) {\n <div class=\"mj-lk-status mj-lk-status--error\">\n <i class=\"fa-solid fa-triangle-exclamation\"></i>\n <span>{{ errorMessage }}</span>\n <button type=\"button\" class=\"mj-lk-retry\" (click)=\"Start()\">Try again</button>\n </div>\n } @else if (serverUrl && token) {\n <div class=\"mj-lk-room-wrap\">\n <mj-livekit-room\n [ServerUrl]=\"serverUrl\"\n [Token]=\"token\"\n [DisplayName]=\"resolvedDisplayName\"\n [AutoConnect]=\"true\"\n [StartWithMicrophone]=\"StartWithMicrophone\"\n [StartWithCamera]=\"StartWithCamera\"\n [Layout]=\"Layout\"\n [Title]=\"Title\"\n [ShowHeader]=\"ShowHeader\"\n [ShowControlBar]=\"ShowControlBar\"\n [ShowChat]=\"ShowChat\"\n [ShowParticipantsPanel]=\"ShowParticipantsPanel\"\n [EnableMicrophoneControl]=\"EnableMicrophoneControl\"\n [EnableCameraControl]=\"EnableCameraControl\"\n [EnableScreenShareControl]=\"EnableScreenShareControl\"\n [EnableDeviceSettings]=\"EnableDeviceSettings\"\n [EnableLeaveControl]=\"EnableLeaveControl\"\n [EnablePinning]=\"EnablePinning\"\n [EnableLayoutSwitcher]=\"EnableLayoutSwitcher\"\n [EnableNoiseFilter]=\"EnableNoiseFilter\"\n [EnableBackgroundEffects]=\"EnableBackgroundEffects\"\n [ShowAgentState]=\"ShowAgentState\"\n [ShowWhiteboard]=\"ShowWhiteboard\"\n [ShowPreJoin]=\"ShowPreJoin\"\n [ShowRecordingControl]=\"EnableRecording\"\n [IsRecording]=\"isRecording\"\n [E2EEPassphrase]=\"E2EEPassphrase\"\n [E2EEWorker]=\"E2EEWorker\"\n [AgentAvatarUrl]=\"AgentAvatarUrl\"\n [CanEndForAll]=\"EnableEndForAll && !!resolvedRoomName\"\n (Connected)=\"Connected.emit($event)\"\n (Disconnected)=\"Disconnected.emit($event)\"\n (EndForAll)=\"EndMeeting()\"\n (ParticipantJoined)=\"ParticipantJoined.emit($event)\"\n (ParticipantLeft)=\"ParticipantLeft.emit($event)\"\n (DataReceived)=\"DataReceived.emit($event)\"\n (ToggleRecording)=\"onToggleRecording()\"\n (ErrorOccurred)=\"ErrorOccurred.emit($event)\"\n ></mj-livekit-room>\n\n @if (Mode === 'agent' && EnableAgentManagement && resolvedRoomName) {\n <div class=\"mj-lk-agents\">\n @if (showAgentsPanel) {\n <div class=\"mj-lk-agents__panel\">\n <div class=\"mj-lk-agents__head\">In this room</div>\n @for (a of agentsInRoom; track a.SessionBridgeID) {\n <div class=\"mj-lk-agents__row\">\n <span class=\"mj-lk-agents__name\"><i class=\"fa-solid fa-robot\"></i> {{ a.Name }}</span>\n <button type=\"button\" class=\"mj-lk-agents__remove\" title=\"Remove agent\"\n [disabled]=\"a.Removing\" (click)=\"RemoveAgent(a)\">\n <i class=\"fa-solid\" [class.fa-xmark]=\"!a.Removing\" [class.fa-spinner]=\"a.Removing\" [class.fa-spin]=\"a.Removing\"></i>\n </button>\n </div>\n }\n @if (availableToAdd.length) {\n <div class=\"mj-lk-agents__add\">\n <select class=\"mj-input mj-lk-agents__select\" (change)=\"onAddTargetChange($event)\">\n <option value=\"\">Add an agent…</option>\n @for (a of availableToAdd; track a.ID) {\n <option [value]=\"a.ID\" [selected]=\"UUIDsEqual(a.ID, addTargetId)\">{{ a.Name }}</option>\n }\n </select>\n <button type=\"button\" class=\"mj-lk-agents__addbtn\" [disabled]=\"!addTargetId || addingAgent\" (click)=\"AddAgent()\">\n <i class=\"fa-solid\" [class.fa-plus]=\"!addingAgent\" [class.fa-spinner]=\"addingAgent\" [class.fa-spin]=\"addingAgent\"></i>\n </button>\n </div>\n @if (CanPickModelVoice && AvailableModels.length) {\n <div class=\"mj-lk-agents__overrides\">\n <select class=\"mj-input mj-lk-agents__select mj-lk-agents__select--sm\" (change)=\"onAddModelChange($event)\" title=\"Model (dev override)\">\n <option value=\"\">Default model</option>\n @for (m of AvailableModels; track m.ModelID) {\n <option [value]=\"m.ModelID\" [selected]=\"UUIDsEqual(m.ModelID, addModelId)\">{{ m.ModelName }}</option>\n }\n </select>\n @if (addVoices.length) {\n <select class=\"mj-input mj-lk-agents__select mj-lk-agents__select--sm\" (change)=\"onAddVoiceChange($event)\" title=\"Voice (dev override)\">\n <option value=\"\">Default voice</option>\n @for (v of addVoices; track v.ID) {\n <option [value]=\"v.ID\" [selected]=\"v.ID === addVoice\">{{ v.Name }}</option>\n }\n </select>\n }\n </div>\n }\n }\n @if (addError) {\n <div class=\"mj-lk-agents__error\">{{ addError }}</div>\n }\n </div>\n }\n <div class=\"mj-lk-agents__pills\">\n <button type=\"button\" class=\"mj-lk-agents__toggle\" (click)=\"showAgentsPanel = !showAgentsPanel\">\n <i class=\"fa-solid fa-robot\"></i> Agents ({{ agentsInRoom.length }})\n </button>\n @if (EnableInvite) {\n <button type=\"button\" class=\"mj-lk-agents__toggle\" title=\"Copy a link to invite someone to this room\"\n (click)=\"CopyInvite()\">\n <i class=\"fa-solid\" [class.fa-link]=\"!inviteCopied\" [class.fa-check]=\"inviteCopied\"></i>\n {{ inviteCopied ? 'Link copied' : 'Copy link' }}\n </button>\n <button type=\"button\" class=\"mj-lk-agents__toggle\" title=\"Invite people from this workspace\"\n (click)=\"InvitePeopleRequested.emit(resolvedRoomName)\">\n <i class=\"fa-solid fa-user-plus\"></i> Invite people\n </button>\n }\n </div>\n </div>\n }\n </div>\n }\n `,\n styles: [\n `\n :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n .mj-lk-status {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 10px;\n height: 100%;\n min-height: 220px;\n color: var(--mj-text-secondary, #475569);\n background: var(--mj-bg-surface-card, #f1f5f9);\n border-radius: 12px;\n }\n .mj-lk-status i {\n font-size: 1.6rem;\n color: var(--mj-brand-primary, #0076b6);\n }\n .mj-lk-status--error i {\n color: var(--mj-status-error, #ef4444);\n }\n .mj-lk-retry {\n padding: 7px 16px;\n border: none;\n border-radius: 8px;\n cursor: pointer;\n color: var(--mj-text-inverse, #fff);\n background: var(--mj-brand-primary, #0076b6);\n }\n .mj-lk-room-wrap {\n position: relative;\n width: 100%;\n height: 100%;\n }\n .mj-lk-agents {\n position: absolute;\n left: 16px;\n bottom: 84px;\n z-index: 40;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n }\n .mj-lk-agents__pills {\n display: flex;\n gap: 8px;\n }\n .mj-lk-agents__toggle {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 7px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 999px;\n cursor: pointer;\n font-size: 0.8125rem;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-elevated, var(--mj-bg-surface));\n box-shadow: var(--mj-shadow-sm, 0 2px 8px rgba(0, 0, 0, 0.18));\n }\n .mj-lk-agents__panel {\n width: 260px;\n padding: 10px;\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n background: var(--mj-bg-surface-elevated, var(--mj-bg-surface));\n box-shadow: var(--mj-shadow-md, 0 6px 20px rgba(0, 0, 0, 0.25));\n }\n .mj-lk-agents__head {\n font-size: 0.6875rem;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--mj-text-muted);\n margin-bottom: 6px;\n }\n .mj-lk-agents__row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 5px 0;\n }\n .mj-lk-agents__name {\n display: inline-flex;\n align-items: center;\n gap: 7px;\n font-size: 0.8125rem;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .mj-lk-agents__name i {\n color: var(--mj-brand-primary);\n }\n .mj-lk-agents__remove {\n flex: none;\n width: 26px;\n height: 26px;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n color: var(--mj-text-muted);\n background: transparent;\n }\n .mj-lk-agents__remove:hover:not(:disabled) {\n color: var(--mj-status-error);\n background: var(--mj-bg-surface-hover);\n }\n .mj-lk-agents__add {\n display: flex;\n gap: 6px;\n margin-top: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--mj-border-subtle, var(--mj-border-default));\n }\n .mj-lk-agents__select {\n flex: 1;\n min-width: 0;\n font-size: 0.8125rem;\n }\n .mj-lk-agents__overrides {\n display: flex;\n gap: 6px;\n margin-top: 6px;\n }\n .mj-lk-agents__select--sm {\n font-size: 0.75rem;\n }\n .mj-lk-agents__addbtn {\n flex: none;\n width: 32px;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n }\n .mj-lk-agents__addbtn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n .mj-lk-agents__error {\n margin-top: 6px;\n font-size: 0.75rem;\n color: var(--mj-status-error-text, var(--mj-status-error));\n }\n .mj-lk-recording {\n margin-bottom: 12px;\n padding: 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n background: var(--mj-bg-surface-card, var(--mj-bg-surface));\n }\n .mj-lk-recording__head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 8px;\n }\n .mj-lk-recording__title {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n font-size: 0.875rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n .mj-lk-recording__title i {\n color: var(--mj-brand-primary);\n }\n .mj-lk-recording__close {\n width: 28px;\n height: 28px;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n color: var(--mj-text-muted);\n background: transparent;\n }\n .mj-lk-recording__close:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n }\n `,\n ],\n})\nexport class MJLiveKitRoomComponent extends BaseAngularComponent implements OnInit {\n private readonly cdr = inject(ChangeDetectorRef);\n\n // ── MJ connection inputs ───────────────────────────────────────────────────────\n /** Whether to start an agent in the room (`'agent'`) or just join an existing room (`'join'`). */\n @Input() public Mode: MJLiveKitConnectionMode = 'agent';\n /** The agent to voice (agent mode) — the Realtime Co-Agent / voice front-end. */\n @Input() public AgentID: string | null = null;\n /** The agent's display name (bot name + addressing). */\n @Input() public AgentName: string | null = null;\n /**\n * The TARGET agent the co-agent voices — the one being \"called\". The Realtime Co-Agent delegates to\n * it via `invoke-target-agent`; without it the agent has nobody to speak for and stays idle.\n */\n @Input() public TargetAgentID: string | null = null;\n /** The room name. Required for `'join'` mode; optional for `'agent'` (server generates one). */\n @Input() public RoomName: string | null = null;\n /** The display name the local user joins as. Defaults to the authenticated user server-side. */\n @Input() public DisplayName: string | null = null;\n /** Turn-taking mode for the agent. */\n @Input() public TurnMode: 'Passive' | 'Active' | 'Hybrid' | null = null;\n /** Resolve the connection automatically on init. */\n @Input() public AutoStart = true;\n\n // ── In-room agent management (agent mode) ─────────────────────────────────────────\n /** Show the in-room \"Agents\" panel to add/remove agents (agent mode only). */\n @Input() public EnableAgentManagement = true;\n /** Show the \"Invite\" pill that copies a join link to this room. */\n @Input() public EnableInvite = true;\n /**\n * Offer \"End meeting for everyone\" in the control bar's Zoom-style leave menu. When on (default) and a\n * room is resolved, ending tears down every agent in the room server-side (by name — so it works even\n * when this client only *joined*). Set `false` for contexts where only the local user should ever leave.\n */\n @Input() public EnableEndForAll = true;\n /** Target agents the user can ADD in-room (id + name). The host (e.g. the Explorer resource) supplies these. */\n @Input() public AvailableAgents: { ID: string; Name: string }[] = [];\n\n /** Per-session Realtime MODEL override for the INITIAL agent (from the host's pre-join picker). */\n @Input() public RealtimeModelID: string | null = null;\n /** Per-session VOICE override for the INITIAL agent (from the host's pre-join picker). */\n @Input() public RealtimeVoice: string | null = null;\n /**\n * Whether the dev model/voice pickers are shown in the in-room \"Add an agent\" control. The HOST\n * computes this (the `Realtime: Advanced Session Controls` authorization) and passes it down — this\n * generic component never evaluates authorizations itself.\n */\n @Input() public CanPickModelVoice = false;\n /** Active Realtime models + their voices, supplied by the host (for the add-agent dropdowns). */\n @Input() public AvailableModels: RealtimeModelVoices[] = [];\n\n /** True briefly after the invite link is copied (drives the \"Link copied\" pill state). */\n public InviteCopied = false;\n\n /** @deprecated Use {@link InviteCopied}. */\n public get inviteCopied() {\n return this.InviteCopied;\n }\n /** @deprecated Use {@link InviteCopied}. */\n public set inviteCopied(value) {\n this.InviteCopied = value;\n }\n\n /** Whether the floating agents panel is open. */\n public ShowAgentsPanel = false;\n\n /** @deprecated Use {@link ShowAgentsPanel}. */\n public get showAgentsPanel() {\n return this.ShowAgentsPanel;\n }\n /** @deprecated Use {@link ShowAgentsPanel}. */\n public set showAgentsPanel(value) {\n this.ShowAgentsPanel = value;\n }\n /** The agent bots currently bridged into the room (the first is the one started on join). */\n public AgentsInRoom: AgentInRoom[] = [];\n\n /** @deprecated Use {@link AgentsInRoom}. */\n public get agentsInRoom(): AgentInRoom[] {\n return this.AgentsInRoom;\n }\n /** @deprecated Use {@link AgentsInRoom}. */\n public set agentsInRoom(value: AgentInRoom[]) {\n this.AgentsInRoom = value;\n }\n /** The target id chosen in the \"Add an agent\" picker. */\n public AddTargetId: string | null = null;\n\n /** @deprecated Use {@link AddTargetId}. */\n public get addTargetId(): string | null {\n return this.AddTargetId;\n }\n /** @deprecated Use {@link AddTargetId}. */\n public set addTargetId(value: string | null) {\n this.AddTargetId = value;\n }\n /** The MODEL override chosen in the \"Add an agent\" picker (dev-only; null = co-agent/target default). */\n public AddModelId: string | null = null;\n\n /** @deprecated Use {@link AddModelId}. */\n public get addModelId(): string | null {\n return this.AddModelId;\n }\n /** @deprecated Use {@link AddModelId}. */\n public set addModelId(value: string | null) {\n this.AddModelId = value;\n }\n /** The VOICE override chosen in the \"Add an agent\" picker (dev-only; null = co-agent/target default). */\n public AddVoice: string | null = null;\n\n /** @deprecated Use {@link AddVoice}. */\n public get addVoice(): string | null {\n return this.AddVoice;\n }\n /** @deprecated Use {@link AddVoice}. */\n public set addVoice(value: string | null) {\n this.AddVoice = value;\n }\n /** Exposed for template use — platform-safe UUID equality (SQL upper vs PG lower). */\n public UUIDsEqual = UUIDsEqual;\n /** True while an Add request is in flight. */\n public AddingAgent = false;\n\n /** @deprecated Use {@link AddingAgent}. */\n public get addingAgent() {\n return this.AddingAgent;\n }\n /** @deprecated Use {@link AddingAgent}. */\n public set addingAgent(value) {\n this.AddingAgent = value;\n }\n /** Last add error, shown under the picker. */\n public AddError: string | null = null;\n\n /** @deprecated Use {@link AddError}. */\n public get addError(): string | null {\n return this.AddError;\n }\n /** @deprecated Use {@link AddError}. */\n public set addError(value: string | null) {\n this.AddError = value;\n }\n /** True while an \"End meeting\" (stop all agents + leave) is in flight. */\n public EndingMeeting = false;\n\n /** @deprecated Use {@link EndingMeeting}. */\n public get endingMeeting() {\n return this.EndingMeeting;\n }\n /** @deprecated Use {@link EndingMeeting}. */\n public set endingMeeting(value) {\n this.EndingMeeting = value;\n }\n\n /** The inner Generic room — used to trigger the local disconnect when ending/leaving the meeting. */\n @ViewChild(LiveKitRoomComponent) private roomComponent?: LiveKitRoomComponent;\n\n /** Available agents not already in the room (by target id) — the \"Add\" picker options. */\n public get AvailableToAdd(): { ID: string; Name: string }[] {\n const present = new Set(this.AgentsInRoom.map((a) => (a.TargetAgentID ?? '').toLowerCase()));\n return this.AvailableAgents.filter((a) => !present.has(a.ID.toLowerCase()));\n }\n\n /** @deprecated Use {@link AvailableToAdd}. */\n public get availableToAdd(): { ID: string; Name: string }[] {\n return this.AvailableToAdd;\n }\n\n /** Voices for the model chosen in the add-agent picker (empty when no model picked or it has none). */\n public get AddVoices(): RealtimeVoiceOption[] {\n const model = this.AvailableModels.find((m) => UUIDsEqual(m.ModelID, this.AddModelId));\n return model?.Voices ?? [];\n }\n\n /** @deprecated Use {@link AddVoices}. */\n public get addVoices(): RealtimeVoiceOption[] {\n return this.AddVoices;\n }\n\n /** Records the add-agent MODEL choice; clears the voice so it can't outlive a model switch. */\n public OnAddModelChange(event: Event): void {\n this.AddModelId = (event.target as HTMLSelectElement).value || null;\n this.AddVoice = null;\n }\n\n /** @deprecated Use {@link OnAddModelChange}. */\n public onAddModelChange(event: Event): void {\n return this.OnAddModelChange(event);\n }\n\n /** Records the add-agent VOICE choice. */\n public OnAddVoiceChange(event: Event): void {\n this.AddVoice = (event.target as HTMLSelectElement).value || null;\n }\n\n /** @deprecated Use {@link OnAddVoiceChange}. */\n public onAddVoiceChange(event: Event): void {\n return this.OnAddVoiceChange(event);\n }\n\n // ── Forwarded UI gates (see LiveKitRoomComponent) ────────────────────────────────\n /** @see LiveKitRoomComponent.Layout */\n @Input() public Layout: LiveKitRoomLayout = 'grid';\n /** @see LiveKitRoomComponent.Title */\n @Input() public Title: string | null = null;\n /** @see LiveKitRoomComponent.ShowHeader */\n @Input() public ShowHeader = true;\n /** @see LiveKitRoomComponent.ShowControlBar */\n @Input() public ShowControlBar = true;\n /** @see LiveKitRoomComponent.ShowChat */\n @Input() public ShowChat = true;\n /** @see LiveKitRoomComponent.ShowParticipantsPanel */\n @Input() public ShowParticipantsPanel = true;\n /** @see LiveKitRoomComponent.EnableMicrophoneControl */\n @Input() public EnableMicrophoneControl = true;\n /** @see LiveKitRoomComponent.EnableCameraControl */\n @Input() public EnableCameraControl = true;\n /** @see LiveKitRoomComponent.EnableScreenShareControl */\n @Input() public EnableScreenShareControl = true;\n /** @see LiveKitRoomComponent.EnableDeviceSettings */\n @Input() public EnableDeviceSettings = true;\n /** @see LiveKitRoomComponent.EnableLeaveControl */\n @Input() public EnableLeaveControl = true;\n /** @see LiveKitRoomComponent.StartWithMicrophone */\n @Input() public StartWithMicrophone = true;\n /** @see LiveKitRoomComponent.StartWithCamera */\n @Input() public StartWithCamera = false;\n /** @see LiveKitRoomComponent.AgentAvatarUrl */\n @Input() public AgentAvatarUrl: string | null = null;\n /** @see LiveKitRoomComponent.EnablePinning */\n @Input() public EnablePinning = true;\n /** @see LiveKitRoomComponent.EnableLayoutSwitcher */\n @Input() public EnableLayoutSwitcher = true;\n /** @see LiveKitRoomComponent.EnableNoiseFilter */\n @Input() public EnableNoiseFilter = false;\n /** @see LiveKitRoomComponent.EnableBackgroundEffects */\n @Input() public EnableBackgroundEffects = false;\n /** @see LiveKitRoomComponent.ShowAgentState */\n @Input() public ShowAgentState = false;\n /** @see LiveKitRoomComponent.ShowWhiteboard */\n @Input() public ShowWhiteboard = false;\n /** @see LiveKitRoomComponent.ShowPreJoin */\n @Input() public ShowPreJoin = false;\n /** Enable the server-authorized recording control (composite egress). */\n @Input() public EnableRecording = false;\n /** @see LiveKitRoomComponent.E2EEPassphrase */\n @Input() public E2EEPassphrase: string | null = null;\n /** @see LiveKitRoomComponent.E2EEWorker */\n @Input() public E2EEWorker: Worker | null = null;\n\n // ── Outputs ────────────────────────────────────────────────────────────────────\n /** Emitted once the agent room session is started (agent mode). */\n @Output() public SessionStarted = new EventEmitter<MJLiveKitSessionStartedEvent>();\n /**\n * Emitted (with the room name) when the user clicks \"Invite people\". The host (e.g. the Explorer\n * resource) opens an MJ user-picker and calls the invite mutation — kept out of this generic\n * component, which knows nothing about MJ users.\n */\n @Output() public InvitePeopleRequested = new EventEmitter<string>();\n /** Emitted when the room connects. */\n @Output() public Connected = new EventEmitter<LiveKitRoomState>();\n /** Emitted when the room disconnects. */\n @Output() public Disconnected = new EventEmitter<LiveKitDisconnectedEvent>();\n /** Emitted when a participant joins. */\n @Output() public ParticipantJoined = new EventEmitter<LiveKitParticipantJoinedEvent>();\n /** Emitted when a participant leaves. */\n @Output() public ParticipantLeft = new EventEmitter<LiveKitParticipantLeftEvent>();\n /** Emitted for inbound data-channel messages. */\n @Output() public DataReceived = new EventEmitter<LiveKitDataMessage>();\n /** Emitted on room errors (and on token/session-resolution failures). */\n @Output() public ErrorOccurred = new EventEmitter<LiveKitRoomError>();\n\n // ── View state ─────────────────────────────────────────────────────────────────\n /** Whether the binding is resolving the token/session. */\n public Loading = false;\n\n /** @deprecated Use {@link Loading}. */\n public get loading() {\n return this.Loading;\n }\n /** @deprecated Use {@link Loading}. */\n public set loading(value) {\n this.Loading = value;\n }\n /** The token/session-resolution error, if any. */\n public errorMessage: string | null = null;\n /** The resolved LiveKit server URL. */\n public ServerUrl: string | null = null;\n\n /** @deprecated Use {@link ServerUrl}. */\n public get serverUrl(): string | null {\n return this.ServerUrl;\n }\n /** @deprecated Use {@link ServerUrl}. */\n public set serverUrl(value: string | null) {\n this.ServerUrl = value;\n }\n /** The resolved access token. */\n public Token: string | null = null;\n\n /** @deprecated Use {@link Token}. */\n public get token(): string | null {\n return this.Token;\n }\n /** @deprecated Use {@link Token}. */\n public set token(value: string | null) {\n this.Token = value;\n }\n /** The display name passed to the room. */\n public ResolvedDisplayName: string | null = null;\n\n /** @deprecated Use {@link ResolvedDisplayName}. */\n public get resolvedDisplayName(): string | null {\n return this.ResolvedDisplayName;\n }\n /** @deprecated Use {@link ResolvedDisplayName}. */\n public set resolvedDisplayName(value: string | null) {\n this.ResolvedDisplayName = value;\n }\n /** The resolved room name (for recording calls). */\n public ResolvedRoomName: string | null = null;\n\n /** @deprecated Use {@link ResolvedRoomName}. */\n public get resolvedRoomName(): string | null {\n return this.ResolvedRoomName;\n }\n /** @deprecated Use {@link ResolvedRoomName}. */\n public set resolvedRoomName(value: string | null) {\n this.ResolvedRoomName = value;\n }\n /** Whether a recording is currently in progress. */\n public IsRecording = false;\n\n /** @deprecated Use {@link IsRecording}. */\n public get isRecording() {\n return this.IsRecording;\n }\n /** @deprecated Use {@link IsRecording}. */\n public set isRecording(value) {\n this.IsRecording = value;\n }\n /** The active egress id, when recording. */\n private currentEgressId: string | null = null;\n\n /**\n * The `MJ: Files` id of this room's meeting recording, when one exists — set when a recording is STOPPED\n * (the server registers the egress MP4 and returns its file id) or resolved for an already-recorded room\n * on join. Drives the {@link MJStorageMediaPlayerComponent} playback panel.\n */\n public RecordingFileId: string | null = null;\n\n /** @deprecated Use {@link RecordingFileId}. */\n public get recordingFileId(): string | null {\n return this.RecordingFileId;\n }\n /** @deprecated Use {@link RecordingFileId}. */\n public set recordingFileId(value: string | null) {\n this.RecordingFileId = value;\n }\n /** Whether the recording playback panel is shown (dismissable). */\n public ShowRecordingPanel = true;\n\n /** @deprecated Use {@link ShowRecordingPanel}. */\n public get showRecordingPanel() {\n return this.ShowRecordingPanel;\n }\n /** @deprecated Use {@link ShowRecordingPanel}. */\n public set showRecordingPanel(value) {\n this.ShowRecordingPanel = value;\n }\n\n public ngOnInit(): void {\n if (this.AutoStart) {\n void this.Start();\n }\n // If this room already has a registered recording (e.g. joining/reviewing a past room), surface it.\n if (this.RoomName) {\n void this.loadExistingRecording(this.RoomName);\n }\n }\n\n /**\n * Max time to wait for the connection to start before surfacing a retryable error, so a hung or very\n * slow server (e.g. an agent bot that can't reach the LiveKit media path) doesn't spin forever. Set\n * `0` to disable the client-side timeout.\n */\n @Input() public ConnectTimeoutMs = 25000;\n\n /** Resolves the connection (mints a token and, in agent mode, starts the agent session). */\n public async Start(): Promise<void> {\n this.Loading = true;\n this.errorMessage = null;\n this.cdr.markForCheck();\n try {\n const client = new GraphQLLiveKitClient(this.ProviderToUse as unknown as GraphQLDataProvider);\n this.ResolvedDisplayName = this.DisplayName;\n const connect = this.Mode === 'agent' ? this.startAgentSession(client) : this.joinRoom(client);\n await this.withTimeout(connect, this.ConnectTimeoutMs);\n } catch (err) {\n this.fail(err instanceof Error ? err.message : String(err));\n } finally {\n this.Loading = false;\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Races `op` against a timeout: if it hasn't settled within `ms`, rejects with a clear, retryable\n * message (the template's \"Try again\" button re-runs {@link Start}). A non-positive `ms` disables it.\n */\n private withTimeout<T>(op: Promise<T>, ms: number): Promise<T> {\n if (!ms || ms <= 0) {\n return op;\n }\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(\n () =>\n reject(\n new Error(\n 'The connection is taking too long — the agent could not join the room. ' +\n 'Check that the LiveKit server is running and reachable, then try again.',\n ),\n ),\n ms,\n );\n op.then(\n (value) => {\n clearTimeout(timer);\n resolve(value);\n },\n (error) => {\n clearTimeout(timer);\n reject(error);\n },\n );\n });\n }\n\n /** Starts the agent room session and applies the returned client token. */\n private async startAgentSession(client: GraphQLLiveKitClient): Promise<void> {\n const result = await client.StartAgentRoomSession({\n AgentID: this.AgentID ?? undefined,\n AgentName: this.AgentName ?? undefined,\n TargetAgentID: this.TargetAgentID ?? undefined,\n RealtimeModelID: this.RealtimeModelID ?? undefined,\n RealtimeVoice: this.RealtimeVoice ?? undefined,\n RoomName: this.RoomName ?? undefined,\n TurnMode: this.TurnMode ?? undefined,\n });\n if (!result.Success) {\n this.fail(result.ErrorMessage ?? 'Failed to start the agent session.');\n return;\n }\n this.ServerUrl = result.ServerUrl;\n this.Token = result.ClientToken;\n this.ResolvedRoomName = result.RoomName;\n // Surface a prior recording for this resolved room (the server may have generated the room name).\n void this.loadExistingRecording(result.RoomName);\n // Track the agent we just brought in as the first entry in the in-room roster.\n this.AgentsInRoom = [\n { SessionBridgeID: result.SessionBridgeID, TargetAgentID: this.TargetAgentID, Name: this.AgentName ?? 'Agent' },\n ];\n this.SessionStarted.emit({ SessionBridgeID: result.SessionBridgeID, RoomName: result.RoomName });\n }\n\n /** Picker selection handler for the in-room \"Add an agent\" control (native select; no FormsModule dep). */\n public OnAddTargetChange(event: Event): void {\n this.AddTargetId = (event.target as HTMLSelectElement).value || null;\n this.AddError = null;\n }\n\n /** @deprecated Use {@link OnAddTargetChange}. */\n public onAddTargetChange(event: Event): void {\n return this.OnAddTargetChange(event);\n }\n\n /**\n * Adds another agent to the SAME room — starts a new bridge (the co-agent voicing the chosen target)\n * and appends it to the roster. The new bot joins the live room alongside the existing participants.\n */\n public async AddAgent(): Promise<void> {\n if (!this.AddTargetId || !this.ResolvedRoomName || this.AddingAgent) {\n return;\n }\n const target = this.AvailableAgents.find((a) => UUIDsEqual(a.ID, this.AddTargetId));\n this.AddingAgent = true;\n this.AddError = null;\n this.cdr.markForCheck();\n try {\n const client = new GraphQLLiveKitClient(this.ProviderToUse as unknown as GraphQLDataProvider);\n const result = await client.StartAgentRoomSession({\n AgentID: this.AgentID ?? undefined,\n AgentName: target?.Name ?? undefined,\n TargetAgentID: this.AddTargetId,\n RealtimeModelID: this.AddModelId ?? undefined,\n RealtimeVoice: this.AddVoice ?? undefined,\n RoomName: this.ResolvedRoomName,\n TurnMode: this.TurnMode ?? undefined,\n });\n if (!result.Success) {\n this.AddError = result.ErrorMessage ?? 'Failed to add the agent.';\n return;\n }\n this.AgentsInRoom = [\n ...this.AgentsInRoom,\n { SessionBridgeID: result.SessionBridgeID, TargetAgentID: this.AddTargetId, Name: target?.Name ?? 'Agent' },\n ];\n this.AddTargetId = null;\n this.AddModelId = null;\n this.AddVoice = null;\n } catch (err) {\n this.AddError = err instanceof Error ? err.message : String(err);\n } finally {\n this.AddingAgent = false;\n this.cdr.markForCheck();\n }\n }\n\n /** Removes an agent from the room — stops its bridge and drops it from the roster. */\n public async RemoveAgent(agent: AgentInRoom): Promise<void> {\n if (agent.Removing) {\n return;\n }\n agent.Removing = true;\n this.cdr.markForCheck();\n try {\n const client = new GraphQLLiveKitClient(this.ProviderToUse as unknown as GraphQLDataProvider);\n const ok = await client.StopAgentRoomSession(agent.SessionBridgeID);\n if (ok) {\n this.AgentsInRoom = this.AgentsInRoom.filter((a) => a.SessionBridgeID !== agent.SessionBridgeID);\n } else {\n agent.Removing = false;\n }\n } catch {\n agent.Removing = false;\n } finally {\n this.cdr.markForCheck();\n }\n }\n\n /**\n * **End meeting** (the Zoom/Teams \"End for all\", reached from the control-bar leave menu): tears down EVERY\n * agent in the room server-side — *by room name*, so it works even when this client only **joined** the room\n * and never tracked the bridge ids locally — then disconnects the local user. Contrast with **Leave** (the\n * other menu item → {@link LiveKitRoomComponent.Leave}), which only disconnects YOU and lets the meeting\n * continue; the server then auto-leaves the agents once the last human is gone, so neither path strands\n * billable agent sessions in an empty room.\n */\n public async EndMeeting(): Promise<void> {\n if (this.EndingMeeting) {\n return;\n }\n this.EndingMeeting = true;\n this.cdr.markForCheck();\n try {\n if (this.ResolvedRoomName) {\n const client = new GraphQLLiveKitClient(this.ProviderToUse as unknown as GraphQLDataProvider);\n await client.EndRoom(this.ResolvedRoomName);\n }\n this.AgentsInRoom = [];\n } catch {\n /* best-effort — fall through and still disconnect the local user */\n } finally {\n await this.roomComponent?.Leave();\n this.EndingMeeting = false;\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Builds the shareable invite URL for THIS room: the current page URL with a `room=<roomName>` query\n * param. Opening it lands the invitee on the Live Room in join mode for the same room.\n */\n public get InviteUrl(): string {\n const url = new URL(window.location.href);\n url.searchParams.set('room', this.ResolvedRoomName ?? '');\n return url.toString();\n }\n\n /** @deprecated Use {@link InviteUrl}. */\n public get inviteUrl(): string {\n return this.InviteUrl;\n }\n\n /** Copies {@link inviteUrl} to the clipboard and flips the pill to \"Link copied\" briefly. */\n public async CopyInvite(): Promise<void> {\n if (!this.ResolvedRoomName) {\n return;\n }\n try {\n await navigator.clipboard.writeText(this.InviteUrl);\n this.InviteCopied = true;\n this.cdr.markForCheck();\n setTimeout(() => {\n this.InviteCopied = false;\n this.cdr.markForCheck();\n }, 2000);\n } catch {\n // Clipboard blocked (insecure context / permissions) — leave the pill unchanged.\n }\n }\n\n /** Joins an existing room by minting a client token. */\n private async joinRoom(client: GraphQLLiveKitClient): Promise<void> {\n if (!this.RoomName) {\n this.fail('RoomName is required when Mode is \"join\".');\n return;\n }\n const result = await client.MintClientToken({ RoomName: this.RoomName, DisplayName: this.DisplayName ?? undefined });\n if (!result.Success) {\n this.fail(result.ErrorMessage ?? 'Failed to obtain a room token.');\n return;\n }\n this.ServerUrl = result.ServerUrl;\n this.Token = result.Token;\n this.ResolvedRoomName = this.RoomName;\n }\n\n /** Toggles room recording via the RealtimeBridge GraphQL surface (server-authorized egress). */\n public async OnToggleRecording(): Promise<void> {\n if (!this.ResolvedRoomName) {\n return;\n }\n const client = new GraphQLLiveKitClient(this.ProviderToUse as unknown as GraphQLDataProvider);\n if (!this.IsRecording) {\n const result = await client.StartRecording(this.ResolvedRoomName);\n if (result.Success) {\n this.IsRecording = true;\n this.currentEgressId = result.EgressID;\n } else {\n this.fail(result.ErrorMessage ?? 'Failed to start recording.');\n }\n } else if (this.currentEgressId) {\n const stopped = await client.StopRecording(this.currentEgressId);\n this.IsRecording = false;\n this.currentEgressId = null;\n // The server registers the egress MP4 as an MJ: Files row on stop and returns its id — surface it\n // in the playback panel. Absent when meeting-recording storage isn't configured server-side.\n if (stopped.Success && stopped.RecordingFileID) {\n this.RecordingFileId = stopped.RecordingFileID;\n this.ShowRecordingPanel = true;\n }\n }\n this.cdr.markForCheck();\n }\n\n /** @deprecated Use {@link OnToggleRecording}. */\n public async onToggleRecording(): Promise<void> {\n return this.OnToggleRecording();\n }\n\n /**\n * Resolves this room's already-registered meeting recording (if any) — the `MJ: Conversations` of\n * `Type='Meeting Room'` keyed by the room name carries the `RecordingFileID`. Best-effort: any failure\n * just leaves the playback panel hidden.\n *\n * @param roomName The LiveKit room name (= the Meeting-Room Conversation's `ExternalID`).\n */\n private async loadExistingRecording(roomName: string): Promise<void> {\n try {\n const escaped = roomName.replace(/'/g, \"''\");\n const result = await RunView.FromMetadataProvider(this.ProviderToUse).RunView<{ RecordingFileID: string | null }>(\n {\n EntityName: 'MJ: Conversations',\n ExtraFilter: `ExternalID='${escaped}' AND Type='Meeting Room' AND RecordingFileID IS NOT NULL`,\n Fields: ['RecordingFileID'],\n OrderBy: '__mj_CreatedAt DESC',\n MaxRows: 1,\n ResultType: 'simple',\n },\n this.ProviderToUse.CurrentUser,\n );\n const fileId = result.Success ? result.Results[0]?.RecordingFileID ?? null : null;\n if (fileId) {\n this.RecordingFileId = fileId;\n this.cdr.markForCheck();\n }\n } catch {\n // best-effort — no recording panel\n }\n }\n\n /** Records a failure and emits an error event. */\n private fail(message: string): void {\n this.errorMessage = message;\n this.ErrorOccurred.emit({ Kind: 'connect', Message: message });\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-mj-livekit-room",
|
|
3
|
-
"version": "6.1
|
|
3
|
+
"version": "6.2.0-edge.1",
|
|
4
4
|
"description": "MemberJunction: MJ binding layer for the LiveKit room UI. Wraps @memberjunction/ng-livekit-room and connects it to the MJ realtime-bridge infrastructure — mints scoped tokens and starts agent room sessions via the RealtimeBridge GraphQL surface, threading MJ user/provider/agent context.",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
@@ -27,13 +27,13 @@
|
|
|
27
27
|
"rxjs": "^7.8.2"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@memberjunction/core": "6.1
|
|
31
|
-
"@memberjunction/global": "6.1
|
|
32
|
-
"@memberjunction/graphql-dataprovider": "6.1
|
|
33
|
-
"@memberjunction/livekit-room-core": "6.1
|
|
34
|
-
"@memberjunction/ng-base-types": "6.1
|
|
35
|
-
"@memberjunction/ng-livekit-room": "6.1
|
|
36
|
-
"@memberjunction/ng-media-player": "6.1
|
|
30
|
+
"@memberjunction/core": "6.2.0-edge.1",
|
|
31
|
+
"@memberjunction/global": "6.2.0-edge.1",
|
|
32
|
+
"@memberjunction/graphql-dataprovider": "6.2.0-edge.1",
|
|
33
|
+
"@memberjunction/livekit-room-core": "6.2.0-edge.1",
|
|
34
|
+
"@memberjunction/ng-base-types": "6.2.0-edge.1",
|
|
35
|
+
"@memberjunction/ng-livekit-room": "6.2.0-edge.1",
|
|
36
|
+
"@memberjunction/ng-media-player": "6.2.0-edge.1",
|
|
37
37
|
"tslib": "^2.8.1"
|
|
38
38
|
},
|
|
39
39
|
"sideEffects": false,
|