@ai-matrx/meet 0.11.49 → 0.11.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/core.cjs +77 -12
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +14 -0
- package/dist/core.d.ts +14 -0
- package/dist/core.js +77 -12
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +77 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +77 -12
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +140 -48
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +2 -0
- package/dist/react.d.ts +2 -0
- package/dist/react.js +140 -48
- package/dist/react.js.map +1 -1
- package/dist/skins/meet.cjs +63 -36
- package/dist/skins/meet.cjs.map +1 -1
- package/dist/skins/meet.js +63 -36
- package/dist/skins/meet.js.map +1 -1
- package/package.json +5 -5
package/dist/core.d.cts
CHANGED
|
@@ -246,6 +246,8 @@ interface DeviceNotice {
|
|
|
246
246
|
readonly outcome: "switched" | "lost";
|
|
247
247
|
/** The device that went away, by label (empty when the browser hid labels). */
|
|
248
248
|
readonly from: string;
|
|
249
|
+
/** The device that went away, by id, so Undo can go back to it if it is plugged in again. */
|
|
250
|
+
readonly fromId?: string | undefined;
|
|
249
251
|
/** The device now in use (`switched` only). */
|
|
250
252
|
readonly to: string | null;
|
|
251
253
|
}
|
|
@@ -888,6 +890,8 @@ interface MeetSnapshot {
|
|
|
888
890
|
readonly captionsOn: boolean;
|
|
889
891
|
/** Why asking for captions failed, in the server's words (`captions-unavailable`). */
|
|
890
892
|
readonly captionsRefusal: NoteTakerRefusal | null;
|
|
893
|
+
/** `captions_start_timeout_seconds` from the token's knobs; the "Starting captions" ceiling. */
|
|
894
|
+
readonly captionsStartTimeoutSeconds: number;
|
|
891
895
|
/**
|
|
892
896
|
* What the LOCAL participant is actually publishing, and why not when it is
|
|
893
897
|
* not. Attendance never depends on it (see `attendance.ts`): a refused
|
|
@@ -2369,6 +2373,8 @@ interface MeetingSession {
|
|
|
2369
2373
|
readState(): Promise<void>;
|
|
2370
2374
|
/** One read of the meeting's rules now (chat mode, attendee lock, time limit); resolves once they are on the store. */
|
|
2371
2375
|
readLivePolicy(): Promise<void>;
|
|
2376
|
+
/** rec-consent-gate: tell the SERVER this person agreed to being recorded (a row fact; it gives publish back). */
|
|
2377
|
+
acknowledgeConsent(): Promise<void>;
|
|
2372
2378
|
/**
|
|
2373
2379
|
* §3.4 ER: what the server recorded for THIS connection's exit, and the run's phase. null =
|
|
2374
2380
|
* the read failed (offline / unreachable); undefined = no meeting or no pass to ask with.
|
|
@@ -2574,6 +2580,8 @@ interface MediaSupervisor {
|
|
|
2574
2580
|
acceptOffer(): Promise<void>;
|
|
2575
2581
|
dismissOffer(): void;
|
|
2576
2582
|
dismissNotice(): void;
|
|
2583
|
+
/** Undo on a "switched" notice: go back to the device that went away, when it is available again. */
|
|
2584
|
+
undoNotice(): Promise<void>;
|
|
2577
2585
|
}
|
|
2578
2586
|
declare function createMediaSupervisor(options: MediaSupervisorOptions): MediaSupervisor;
|
|
2579
2587
|
|
|
@@ -2766,6 +2774,7 @@ interface RoomEngine {
|
|
|
2766
2774
|
acceptDeviceOffer(): Promise<void>;
|
|
2767
2775
|
dismissDeviceOffer(): void;
|
|
2768
2776
|
dismissDeviceNotice(): void;
|
|
2777
|
+
undoDeviceNotice(): Promise<void>;
|
|
2769
2778
|
/** Choose the speaker (audio output) for this meeting. */
|
|
2770
2779
|
switchDevice(kind: "audioinput" | "videoinput" | "audiooutput", deviceId: string): Promise<void>;
|
|
2771
2780
|
pin(identity: ParticipantIdentity | null): void;
|
|
@@ -2856,6 +2865,11 @@ interface ConnectionPolicy {
|
|
|
2856
2865
|
* camera so their audio survives (`net-video-auto-off`); 0 = never.
|
|
2857
2866
|
*/
|
|
2858
2867
|
readonly videoAutoOffAfterPoorSeconds: number;
|
|
2868
|
+
/**
|
|
2869
|
+
* `captions_start_timeout_seconds`: how long "Starting captions" may last before the person is
|
|
2870
|
+
* told, honestly, that captions are unavailable (and offered Try again).
|
|
2871
|
+
*/
|
|
2872
|
+
readonly captionsStartTimeoutSeconds: number;
|
|
2859
2873
|
}
|
|
2860
2874
|
/** The knob defaults (§4.3) — what an older server that sends nothing gets. */
|
|
2861
2875
|
declare const DEFAULT_CONNECTION_POLICY: ConnectionPolicy;
|
package/dist/core.d.ts
CHANGED
|
@@ -246,6 +246,8 @@ interface DeviceNotice {
|
|
|
246
246
|
readonly outcome: "switched" | "lost";
|
|
247
247
|
/** The device that went away, by label (empty when the browser hid labels). */
|
|
248
248
|
readonly from: string;
|
|
249
|
+
/** The device that went away, by id, so Undo can go back to it if it is plugged in again. */
|
|
250
|
+
readonly fromId?: string | undefined;
|
|
249
251
|
/** The device now in use (`switched` only). */
|
|
250
252
|
readonly to: string | null;
|
|
251
253
|
}
|
|
@@ -888,6 +890,8 @@ interface MeetSnapshot {
|
|
|
888
890
|
readonly captionsOn: boolean;
|
|
889
891
|
/** Why asking for captions failed, in the server's words (`captions-unavailable`). */
|
|
890
892
|
readonly captionsRefusal: NoteTakerRefusal | null;
|
|
893
|
+
/** `captions_start_timeout_seconds` from the token's knobs; the "Starting captions" ceiling. */
|
|
894
|
+
readonly captionsStartTimeoutSeconds: number;
|
|
891
895
|
/**
|
|
892
896
|
* What the LOCAL participant is actually publishing, and why not when it is
|
|
893
897
|
* not. Attendance never depends on it (see `attendance.ts`): a refused
|
|
@@ -2369,6 +2373,8 @@ interface MeetingSession {
|
|
|
2369
2373
|
readState(): Promise<void>;
|
|
2370
2374
|
/** One read of the meeting's rules now (chat mode, attendee lock, time limit); resolves once they are on the store. */
|
|
2371
2375
|
readLivePolicy(): Promise<void>;
|
|
2376
|
+
/** rec-consent-gate: tell the SERVER this person agreed to being recorded (a row fact; it gives publish back). */
|
|
2377
|
+
acknowledgeConsent(): Promise<void>;
|
|
2372
2378
|
/**
|
|
2373
2379
|
* §3.4 ER: what the server recorded for THIS connection's exit, and the run's phase. null =
|
|
2374
2380
|
* the read failed (offline / unreachable); undefined = no meeting or no pass to ask with.
|
|
@@ -2574,6 +2580,8 @@ interface MediaSupervisor {
|
|
|
2574
2580
|
acceptOffer(): Promise<void>;
|
|
2575
2581
|
dismissOffer(): void;
|
|
2576
2582
|
dismissNotice(): void;
|
|
2583
|
+
/** Undo on a "switched" notice: go back to the device that went away, when it is available again. */
|
|
2584
|
+
undoNotice(): Promise<void>;
|
|
2577
2585
|
}
|
|
2578
2586
|
declare function createMediaSupervisor(options: MediaSupervisorOptions): MediaSupervisor;
|
|
2579
2587
|
|
|
@@ -2766,6 +2774,7 @@ interface RoomEngine {
|
|
|
2766
2774
|
acceptDeviceOffer(): Promise<void>;
|
|
2767
2775
|
dismissDeviceOffer(): void;
|
|
2768
2776
|
dismissDeviceNotice(): void;
|
|
2777
|
+
undoDeviceNotice(): Promise<void>;
|
|
2769
2778
|
/** Choose the speaker (audio output) for this meeting. */
|
|
2770
2779
|
switchDevice(kind: "audioinput" | "videoinput" | "audiooutput", deviceId: string): Promise<void>;
|
|
2771
2780
|
pin(identity: ParticipantIdentity | null): void;
|
|
@@ -2856,6 +2865,11 @@ interface ConnectionPolicy {
|
|
|
2856
2865
|
* camera so their audio survives (`net-video-auto-off`); 0 = never.
|
|
2857
2866
|
*/
|
|
2858
2867
|
readonly videoAutoOffAfterPoorSeconds: number;
|
|
2868
|
+
/**
|
|
2869
|
+
* `captions_start_timeout_seconds`: how long "Starting captions" may last before the person is
|
|
2870
|
+
* told, honestly, that captions are unavailable (and offered Try again).
|
|
2871
|
+
*/
|
|
2872
|
+
readonly captionsStartTimeoutSeconds: number;
|
|
2859
2873
|
}
|
|
2860
2874
|
/** The knob defaults (§4.3) — what an older server that sends nothing gets. */
|
|
2861
2875
|
declare const DEFAULT_CONNECTION_POLICY: ConnectionPolicy;
|
package/dist/core.js
CHANGED
|
@@ -216,7 +216,8 @@ var DEFAULT_CONNECTION_POLICY = {
|
|
|
216
216
|
autoRejoin: true,
|
|
217
217
|
autoRejoinMaxAttempts: 5,
|
|
218
218
|
reconnectGraceSeconds: 30,
|
|
219
|
-
videoAutoOffAfterPoorSeconds: 20
|
|
219
|
+
videoAutoOffAfterPoorSeconds: 20,
|
|
220
|
+
captionsStartTimeoutSeconds: 20
|
|
220
221
|
};
|
|
221
222
|
function clampInt(value, min, max, fallback) {
|
|
222
223
|
if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
|
|
@@ -231,7 +232,8 @@ function connectionPolicyFrom(raw) {
|
|
|
231
232
|
autoRejoin: typeof row["auto_rejoin"] === "boolean" ? row["auto_rejoin"] : d.autoRejoin,
|
|
232
233
|
autoRejoinMaxAttempts: clampInt(row["auto_rejoin_max_attempts"], 0, 20, d.autoRejoinMaxAttempts),
|
|
233
234
|
reconnectGraceSeconds: clampInt(row["reconnect_grace_seconds"], 0, 600, d.reconnectGraceSeconds),
|
|
234
|
-
videoAutoOffAfterPoorSeconds: clampInt(row["video_auto_off_after_poor_seconds"], 0, 600, d.videoAutoOffAfterPoorSeconds)
|
|
235
|
+
videoAutoOffAfterPoorSeconds: clampInt(row["video_auto_off_after_poor_seconds"], 0, 600, d.videoAutoOffAfterPoorSeconds),
|
|
236
|
+
captionsStartTimeoutSeconds: clampInt(row["captions_start_timeout_seconds"], 1, 600, d.captionsStartTimeoutSeconds)
|
|
235
237
|
};
|
|
236
238
|
}
|
|
237
239
|
var LIVEKIT_BASE_DELAYS_MS = [0, 300, 1200, 2700, 4800, 7e3];
|
|
@@ -3643,6 +3645,7 @@ var EMPTY = {
|
|
|
3643
3645
|
noteTakerRefusal: null,
|
|
3644
3646
|
captionsOn: false,
|
|
3645
3647
|
captionsRefusal: null,
|
|
3648
|
+
captionsStartTimeoutSeconds: 20,
|
|
3646
3649
|
media: IDLE_MEDIA,
|
|
3647
3650
|
mediaRegion: IDLE_MEDIA_REGION,
|
|
3648
3651
|
failure: null,
|
|
@@ -4078,11 +4081,10 @@ function moderationText(kind, payload) {
|
|
|
4078
4081
|
switch (kind) {
|
|
4079
4082
|
case "muted": {
|
|
4080
4083
|
const source = text2(payload["source"]) ?? "microphone";
|
|
4081
|
-
|
|
4082
|
-
return source === "microphone" ? `You've been muted by ${who}.` : source === "camera" ? `Your camera was turned off by ${who}.` : `Your screen share was stopped by ${who}.`;
|
|
4084
|
+
return source === "microphone" ? `${by} muted you.` : source === "camera" ? `${by} turned off your camera.` : `${by} stopped your screen share.`;
|
|
4083
4085
|
}
|
|
4084
4086
|
case "ask-unmute":
|
|
4085
|
-
return `${by
|
|
4087
|
+
return `${by} is asking you to unmute.`;
|
|
4086
4088
|
case "removed":
|
|
4087
4089
|
return `${by} removed you from this meeting.`;
|
|
4088
4090
|
default:
|
|
@@ -4108,7 +4110,7 @@ function applyModeration(store, payload, now) {
|
|
|
4108
4110
|
grants: { ...snapshot.grants, role },
|
|
4109
4111
|
moderationNotice: {
|
|
4110
4112
|
kind: "role",
|
|
4111
|
-
text: role === "host" ? "You are now the host." : role === "cohost" ? "You
|
|
4113
|
+
text: role === "host" ? "You are now the host." : role === "cohost" ? "You are now a co-host." : role === "presenter" ? "You are now a presenter." : snapshot.grants.role === "presenter" ? "You are now a participant: you can no longer present." : "You are no longer a co-host.",
|
|
4112
4114
|
at: now()
|
|
4113
4115
|
}
|
|
4114
4116
|
});
|
|
@@ -5368,7 +5370,10 @@ function createMeetingSession(options) {
|
|
|
5368
5370
|
const meeting = store.snapshot().meeting;
|
|
5369
5371
|
const pass = options.resolvePass?.() ?? null;
|
|
5370
5372
|
if (meeting === null || pass === null) return;
|
|
5371
|
-
if (policyReading)
|
|
5373
|
+
if (policyReading) {
|
|
5374
|
+
await (policyInFlight ?? void 0);
|
|
5375
|
+
return readLivePolicy();
|
|
5376
|
+
}
|
|
5372
5377
|
policyReading = true;
|
|
5373
5378
|
let done = () => void 0;
|
|
5374
5379
|
policyInFlight = new Promise((resolve) => done = resolve);
|
|
@@ -5389,6 +5394,9 @@ function createMeetingSession(options) {
|
|
|
5389
5394
|
if (!samePolicy(snapshot.livePolicy, next) || startedAt !== snapshot.sessionStartedAt) {
|
|
5390
5395
|
store.patch({ livePolicy: next, sessionStartedAt: startedAt });
|
|
5391
5396
|
}
|
|
5397
|
+
if (read.consent_given === true && !store.snapshot().recordingConsentGiven) {
|
|
5398
|
+
store.patch({ recordingConsentGiven: true });
|
|
5399
|
+
}
|
|
5392
5400
|
} catch {
|
|
5393
5401
|
} finally {
|
|
5394
5402
|
policyReading = false;
|
|
@@ -5693,6 +5701,21 @@ function createMeetingSession(options) {
|
|
|
5693
5701
|
stopWaiting,
|
|
5694
5702
|
readState: readState2,
|
|
5695
5703
|
readLivePolicy,
|
|
5704
|
+
async acknowledgeConsent() {
|
|
5705
|
+
const meeting = requireMeeting("meet.consent");
|
|
5706
|
+
const pass = options.resolvePass?.() ?? null;
|
|
5707
|
+
const response = await options.api.request({
|
|
5708
|
+
path: MEET_ROUTES.consent,
|
|
5709
|
+
method: "POST",
|
|
5710
|
+
requireAuth: false,
|
|
5711
|
+
operation: "meet.consent",
|
|
5712
|
+
body: { meeting_id: meeting.id },
|
|
5713
|
+
...pass !== null ? { headers: { [MEETING_PASS_HEADER]: pass } } : {}
|
|
5714
|
+
});
|
|
5715
|
+
if (!response.ok) {
|
|
5716
|
+
throw new MeetError("transport", `meet.consent: the server answered ${response.status}`, "Your agreement was not saved. Try again.");
|
|
5717
|
+
}
|
|
5718
|
+
},
|
|
5696
5719
|
async readExit(connection, held) {
|
|
5697
5720
|
const meeting = store.snapshot().meeting;
|
|
5698
5721
|
const pass = held ?? options.resolvePass?.() ?? null;
|
|
@@ -6564,7 +6587,9 @@ function createMediaSupervisor(options) {
|
|
|
6564
6587
|
const deviceKind = INPUT_KIND[kind];
|
|
6565
6588
|
const previous = inUse[deviceKind];
|
|
6566
6589
|
const track = store.snapshot().media[kind];
|
|
6567
|
-
const
|
|
6590
|
+
const aliasLabel = previous !== null && isAlias(previous) ? before[deviceKind].get(previous) : void 0;
|
|
6591
|
+
const aliasGone = previous !== null && aliasLabel !== void 0 && aliasLabel !== "" && (!now[deviceKind].has(previous) || now[deviceKind].get(previous) !== aliasLabel);
|
|
6592
|
+
const gone = aliasGone || previous !== null && !isAlias(previous) && before[deviceKind].has(previous) && !now[deviceKind].has(previous);
|
|
6568
6593
|
if (gone) {
|
|
6569
6594
|
const from = before[deviceKind].get(previous) ?? "";
|
|
6570
6595
|
const remaining = [...now[deviceKind].entries()].filter(([id]) => !isAlias(id));
|
|
@@ -6589,7 +6614,7 @@ function createMediaSupervisor(options) {
|
|
|
6589
6614
|
await driver.setCameraEnabled(true);
|
|
6590
6615
|
store.setLocalTrack("camera", { enabled: true, unavailable: null });
|
|
6591
6616
|
}
|
|
6592
|
-
setRegion({ notice: { id: ++noticeId, kind, outcome: "switched", from, to: nextLabel } });
|
|
6617
|
+
setRegion({ notice: { id: ++noticeId, kind, outcome: "switched", from, fromId: previous, to: nextLabel } });
|
|
6593
6618
|
} catch (error) {
|
|
6594
6619
|
const refused = await unavailable(error, "camera", "meet.camera(fallback)");
|
|
6595
6620
|
store.setLocalTrack("camera", { enabled: false, unavailable: refused });
|
|
@@ -6597,8 +6622,24 @@ function createMediaSupervisor(options) {
|
|
|
6597
6622
|
}
|
|
6598
6623
|
} else {
|
|
6599
6624
|
const active = driver.activeDevices().audioinput;
|
|
6600
|
-
|
|
6601
|
-
|
|
6625
|
+
let to = (active !== null && !aliasGone ? now.audioinput.get(active) : void 0) ?? now.audioinput.get("default");
|
|
6626
|
+
if (to === void 0 || aliasGone) {
|
|
6627
|
+
const [nextId, nextLabel] = remaining[0];
|
|
6628
|
+
try {
|
|
6629
|
+
await driver.switchDevice("audioinput", nextId);
|
|
6630
|
+
if (track.enabled || track.unavailable !== null) {
|
|
6631
|
+
await driver.setMicrophoneEnabled(true);
|
|
6632
|
+
store.setLocalTrack("microphone", { enabled: true, unavailable: null });
|
|
6633
|
+
}
|
|
6634
|
+
to = nextLabel;
|
|
6635
|
+
} catch (error) {
|
|
6636
|
+
const refused = await unavailable(error, "microphone", "meet.microphone(fallback)");
|
|
6637
|
+
store.setLocalTrack("microphone", { enabled: false, unavailable: refused });
|
|
6638
|
+
setRegion({ notice: { id: ++noticeId, kind, outcome: "lost", from, to: null } });
|
|
6639
|
+
continue;
|
|
6640
|
+
}
|
|
6641
|
+
}
|
|
6642
|
+
setRegion({ notice: { id: ++noticeId, kind, outcome: "switched", from, fromId: previous, to } });
|
|
6602
6643
|
}
|
|
6603
6644
|
continue;
|
|
6604
6645
|
}
|
|
@@ -6703,6 +6744,21 @@ function createMediaSupervisor(options) {
|
|
|
6703
6744
|
},
|
|
6704
6745
|
dismissNotice() {
|
|
6705
6746
|
setRegion({ notice: null });
|
|
6747
|
+
},
|
|
6748
|
+
async undoNotice() {
|
|
6749
|
+
const notice = region().notice;
|
|
6750
|
+
setRegion({ notice: null });
|
|
6751
|
+
const driver = options.driver();
|
|
6752
|
+
if (notice === null || notice.outcome !== "switched" || notice.fromId === void 0 || driver === null) return;
|
|
6753
|
+
const list = await snapshotDevices();
|
|
6754
|
+
if (!list[INPUT_KIND[notice.kind]].has(notice.fromId)) return;
|
|
6755
|
+
try {
|
|
6756
|
+
await driver.switchDevice(INPUT_KIND[notice.kind], notice.fromId);
|
|
6757
|
+
readInUse();
|
|
6758
|
+
} catch (error) {
|
|
6759
|
+
const refused = await unavailable(error, notice.kind, "meet.undoDeviceSwitch");
|
|
6760
|
+
store.setLocalTrack(notice.kind, { enabled: false, unavailable: refused });
|
|
6761
|
+
}
|
|
6706
6762
|
}
|
|
6707
6763
|
};
|
|
6708
6764
|
return api;
|
|
@@ -6917,7 +6973,14 @@ function createRoomEngine(options) {
|
|
|
6917
6973
|
const latest = store.snapshot().meeting;
|
|
6918
6974
|
if (latest === null) return;
|
|
6919
6975
|
store.patch({ meeting: { ...latest, endedAt: verified.endedAt } });
|
|
6920
|
-
|
|
6976
|
+
const connection = current?.connectionIdentity ?? current?.identity ?? store.snapshot().localIdentity ?? null;
|
|
6977
|
+
let why;
|
|
6978
|
+
try {
|
|
6979
|
+
why = options.readExit !== void 0 && connection !== null ? await options.readExit(connection, current?.meetingPass ?? null) : void 0;
|
|
6980
|
+
} catch {
|
|
6981
|
+
why = null;
|
|
6982
|
+
}
|
|
6983
|
+
store.dispatch({ type: "ended" }, { reason: why?.exitReason === "time_limit" ? "time_limit" : "ended" });
|
|
6921
6984
|
await dropRoom();
|
|
6922
6985
|
options.onLeft?.("ended");
|
|
6923
6986
|
} catch (error) {
|
|
@@ -7245,6 +7308,7 @@ function createRoomEngine(options) {
|
|
|
7245
7308
|
current = token;
|
|
7246
7309
|
lastServerUrl = token.serverUrl;
|
|
7247
7310
|
connectionPolicy = token.connectionPolicy ?? DEFAULT_CONNECTION_POLICY;
|
|
7311
|
+
store.patch({ captionsStartTimeoutSeconds: connectionPolicy.captionsStartTimeoutSeconds });
|
|
7248
7312
|
if (token.leavePolicy !== void 0) store.patch({ leavePolicy: token.leavePolicy });
|
|
7249
7313
|
store.patch({ canReclaim: token.canReclaim === true });
|
|
7250
7314
|
store.patch({
|
|
@@ -7689,6 +7753,7 @@ function createRoomEngine(options) {
|
|
|
7689
7753
|
acceptDeviceOffer: () => media.acceptOffer(),
|
|
7690
7754
|
dismissDeviceOffer: () => media.dismissOffer(),
|
|
7691
7755
|
dismissDeviceNotice: () => media.dismissNotice(),
|
|
7756
|
+
undoDeviceNotice: () => media.undoNotice(),
|
|
7692
7757
|
pin(who) {
|
|
7693
7758
|
store.patch({ pinned: who, layout: who === null ? "grid" : "speaker" });
|
|
7694
7759
|
},
|