@ai-matrx/meet 0.11.50 → 0.11.52
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 +6 -0
- package/dist/core.cjs +46 -5
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +7 -0
- package/dist/core.d.ts +7 -0
- package/dist/core.js +46 -5
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +46 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +46 -5
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +97 -31
- 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 +97 -31
- package/dist/react.js.map +1 -1
- package/dist/skins/meet.cjs +51 -26
- package/dist/skins/meet.cjs.map +1 -1
- package/dist/skins/meet.js +51 -26
- package/dist/skins/meet.js.map +1 -1
- package/package.json +2 -2
package/dist/react.d.cts
CHANGED
|
@@ -341,6 +341,8 @@ interface UseCaptionsResult {
|
|
|
341
341
|
readonly reason: string | null;
|
|
342
342
|
readonly remedy: string | null;
|
|
343
343
|
readonly toggle: () => void;
|
|
344
|
+
/** Try again after `unavailable`: asks for captions afresh and restarts the start ceiling. */
|
|
345
|
+
readonly retry: () => void;
|
|
344
346
|
}
|
|
345
347
|
declare function useCaptions(): UseCaptionsResult;
|
|
346
348
|
/**
|
package/dist/react.d.ts
CHANGED
|
@@ -341,6 +341,8 @@ interface UseCaptionsResult {
|
|
|
341
341
|
readonly reason: string | null;
|
|
342
342
|
readonly remedy: string | null;
|
|
343
343
|
readonly toggle: () => void;
|
|
344
|
+
/** Try again after `unavailable`: asks for captions afresh and restarts the start ceiling. */
|
|
345
|
+
readonly retry: () => void;
|
|
344
346
|
}
|
|
345
347
|
declare function useCaptions(): UseCaptionsResult;
|
|
346
348
|
/**
|
package/dist/react.js
CHANGED
|
@@ -151,7 +151,8 @@ var DEFAULT_CONNECTION_POLICY = {
|
|
|
151
151
|
autoRejoin: true,
|
|
152
152
|
autoRejoinMaxAttempts: 5,
|
|
153
153
|
reconnectGraceSeconds: 30,
|
|
154
|
-
videoAutoOffAfterPoorSeconds: 20
|
|
154
|
+
videoAutoOffAfterPoorSeconds: 20,
|
|
155
|
+
captionsStartTimeoutSeconds: 20
|
|
155
156
|
};
|
|
156
157
|
function clampInt(value, min, max, fallback) {
|
|
157
158
|
if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
|
|
@@ -166,7 +167,8 @@ function connectionPolicyFrom(raw) {
|
|
|
166
167
|
autoRejoin: typeof row["auto_rejoin"] === "boolean" ? row["auto_rejoin"] : d.autoRejoin,
|
|
167
168
|
autoRejoinMaxAttempts: clampInt(row["auto_rejoin_max_attempts"], 0, 20, d.autoRejoinMaxAttempts),
|
|
168
169
|
reconnectGraceSeconds: clampInt(row["reconnect_grace_seconds"], 0, 600, d.reconnectGraceSeconds),
|
|
169
|
-
videoAutoOffAfterPoorSeconds: clampInt(row["video_auto_off_after_poor_seconds"], 0, 600, d.videoAutoOffAfterPoorSeconds)
|
|
170
|
+
videoAutoOffAfterPoorSeconds: clampInt(row["video_auto_off_after_poor_seconds"], 0, 600, d.videoAutoOffAfterPoorSeconds),
|
|
171
|
+
captionsStartTimeoutSeconds: clampInt(row["captions_start_timeout_seconds"], 1, 600, d.captionsStartTimeoutSeconds)
|
|
170
172
|
};
|
|
171
173
|
}
|
|
172
174
|
var LIVEKIT_BASE_DELAYS_MS = [0, 300, 1200, 2700, 4800, 7e3];
|
|
@@ -4030,6 +4032,7 @@ var EMPTY = {
|
|
|
4030
4032
|
noteTakerRefusal: null,
|
|
4031
4033
|
captionsOn: false,
|
|
4032
4034
|
captionsRefusal: null,
|
|
4035
|
+
captionsStartTimeoutSeconds: 20,
|
|
4033
4036
|
media: IDLE_MEDIA,
|
|
4034
4037
|
mediaRegion: IDLE_MEDIA_REGION,
|
|
4035
4038
|
failure: null,
|
|
@@ -5781,6 +5784,16 @@ var ALIVE_TOPIC = "mx.alive";
|
|
|
5781
5784
|
function encodeBeat(beat) {
|
|
5782
5785
|
return JSON.stringify({ q: beat.q, vp: beat.vp });
|
|
5783
5786
|
}
|
|
5787
|
+
function encodeBye() {
|
|
5788
|
+
return JSON.stringify({ bye: true });
|
|
5789
|
+
}
|
|
5790
|
+
function isBye(payload) {
|
|
5791
|
+
try {
|
|
5792
|
+
return JSON.parse(payload).bye === true;
|
|
5793
|
+
} catch {
|
|
5794
|
+
return false;
|
|
5795
|
+
}
|
|
5796
|
+
}
|
|
5784
5797
|
function decodeBeat(payload) {
|
|
5785
5798
|
try {
|
|
5786
5799
|
const raw = JSON.parse(payload);
|
|
@@ -6007,6 +6020,7 @@ function createRoomEngine(options) {
|
|
|
6007
6020
|
const autoOff = createVideoAutoOff(() => connectionPolicy.videoAutoOffAfterPoorSeconds * 1e3, now);
|
|
6008
6021
|
const lkQuality = /* @__PURE__ */ new Map();
|
|
6009
6022
|
let silent = /* @__PURE__ */ new Set();
|
|
6023
|
+
const saidBye = /* @__PURE__ */ new Set();
|
|
6010
6024
|
let healthTimer = null;
|
|
6011
6025
|
let lastBeatAt = 0;
|
|
6012
6026
|
let wasUnstable = false;
|
|
@@ -6037,6 +6051,7 @@ function createRoomEngine(options) {
|
|
|
6037
6051
|
assessor.reset();
|
|
6038
6052
|
autoOff.reset();
|
|
6039
6053
|
silent = /* @__PURE__ */ new Set();
|
|
6054
|
+
saidBye.clear();
|
|
6040
6055
|
lkQuality.clear();
|
|
6041
6056
|
lastBeatAt = 0;
|
|
6042
6057
|
wasUnstable = false;
|
|
@@ -6094,6 +6109,13 @@ function createRoomEngine(options) {
|
|
|
6094
6109
|
await target?.disconnect();
|
|
6095
6110
|
}
|
|
6096
6111
|
async function leaveRoom() {
|
|
6112
|
+
const target = driver;
|
|
6113
|
+
if (target !== null && store.snapshot().phase === "in_call") {
|
|
6114
|
+
await Promise.race([
|
|
6115
|
+
target.publishData(ALIVE_TOPIC, encodeBye()).catch(() => void 0),
|
|
6116
|
+
new Promise((resolve) => setTimeout(resolve, 300))
|
|
6117
|
+
]);
|
|
6118
|
+
}
|
|
6097
6119
|
store.dispatch({ type: "leave" });
|
|
6098
6120
|
await dropRoom();
|
|
6099
6121
|
options.onLeft?.(null);
|
|
@@ -6189,8 +6211,6 @@ function createRoomEngine(options) {
|
|
|
6189
6211
|
},
|
|
6190
6212
|
participantLeft(who, reason) {
|
|
6191
6213
|
departures.set(who, reason);
|
|
6192
|
-
liveness.forget(who);
|
|
6193
|
-
silent.delete(who);
|
|
6194
6214
|
},
|
|
6195
6215
|
roomMetadata(metadata) {
|
|
6196
6216
|
let parsed = {};
|
|
@@ -6233,8 +6253,12 @@ function createRoomEngine(options) {
|
|
|
6233
6253
|
const snap = store.snapshot();
|
|
6234
6254
|
if (snap.phase !== "in_call" || snap.connection !== "stable") return;
|
|
6235
6255
|
startHealth();
|
|
6256
|
+
const before = assessor.current();
|
|
6236
6257
|
const quality = assessor.push(reading);
|
|
6237
6258
|
const path = pathOf(reading);
|
|
6259
|
+
if (quality !== before) {
|
|
6260
|
+
report("info", `meet: this connection reads ${quality} (round trip ${reading.rttMs ?? "?"} ms, path ${path})`, "Diagnostic only.");
|
|
6261
|
+
}
|
|
6238
6262
|
patchLocalNetwork({ quality, ...path !== "unknown" ? { path } : {} });
|
|
6239
6263
|
refreshQualities();
|
|
6240
6264
|
const cameraOn = snap.media.camera.enabled;
|
|
@@ -6249,6 +6273,11 @@ function createRoomEngine(options) {
|
|
|
6249
6273
|
connectionState(state) {
|
|
6250
6274
|
supervisor.driverState(state);
|
|
6251
6275
|
if (state === "connected" && store.snapshot().phase === "joining") store.dispatch({ type: "connected" });
|
|
6276
|
+
if (state === "connected") {
|
|
6277
|
+
startHealth();
|
|
6278
|
+
lastBeatAt = 0;
|
|
6279
|
+
healthTick();
|
|
6280
|
+
}
|
|
6252
6281
|
},
|
|
6253
6282
|
transcription(event) {
|
|
6254
6283
|
const snapshot = store.snapshot();
|
|
@@ -6340,6 +6369,10 @@ function createRoomEngine(options) {
|
|
|
6340
6369
|
}
|
|
6341
6370
|
const sender = personOf(from ?? "");
|
|
6342
6371
|
if (from !== null) {
|
|
6372
|
+
if (topic === ALIVE_TOPIC && isBye(payload)) {
|
|
6373
|
+
saidBye.add(from);
|
|
6374
|
+
return;
|
|
6375
|
+
}
|
|
6343
6376
|
const beat = topic === ALIVE_TOPIC ? decodeBeat(payload) : null;
|
|
6344
6377
|
const before = liveness.reported(from);
|
|
6345
6378
|
liveness.heard(from, beat);
|
|
@@ -6454,6 +6487,7 @@ function createRoomEngine(options) {
|
|
|
6454
6487
|
current = token;
|
|
6455
6488
|
lastServerUrl = token.serverUrl;
|
|
6456
6489
|
connectionPolicy = token.connectionPolicy ?? DEFAULT_CONNECTION_POLICY;
|
|
6490
|
+
store.patch({ captionsStartTimeoutSeconds: connectionPolicy.captionsStartTimeoutSeconds });
|
|
6457
6491
|
if (token.leavePolicy !== void 0) store.patch({ leavePolicy: token.leavePolicy });
|
|
6458
6492
|
store.patch({ canReclaim: token.canReclaim === true });
|
|
6459
6493
|
store.patch({
|
|
@@ -6571,10 +6605,17 @@ function createRoomEngine(options) {
|
|
|
6571
6605
|
const graceMs = connectionPolicy.reconnectGraceSeconds * 1e3;
|
|
6572
6606
|
for (const [who, reason] of departures) {
|
|
6573
6607
|
const last = previous.get(who);
|
|
6574
|
-
|
|
6608
|
+
const dropped = !saidBye.has(who) && (isUnannouncedDeparture(reason) || silent.has(who));
|
|
6609
|
+
report("info", `meet: ${who} left the room (${reason ?? "no reason"}${dropped ? ", held as reconnecting" : ""})`, "Diagnostic only.");
|
|
6610
|
+
if (last !== void 0 && !last.isLocal && !present.has(who) && graceMs > 0 && dropped) {
|
|
6575
6611
|
ghosts.set(who, { participant: last, until: at + graceMs });
|
|
6576
6612
|
}
|
|
6577
6613
|
}
|
|
6614
|
+
for (const who of departures.keys()) {
|
|
6615
|
+
liveness.forget(who);
|
|
6616
|
+
silent.delete(who);
|
|
6617
|
+
saidBye.delete(who);
|
|
6618
|
+
}
|
|
6578
6619
|
departures.clear();
|
|
6579
6620
|
liveRoster = list;
|
|
6580
6621
|
const localNow = list.find((p) => p.isLocal);
|
|
@@ -8901,6 +8942,22 @@ function createMeetingRecordCache(options = {}) {
|
|
|
8901
8942
|
};
|
|
8902
8943
|
}
|
|
8903
8944
|
|
|
8945
|
+
// src/core/captions-state.ts
|
|
8946
|
+
var CAPTIONS_TIMEOUT_REASON = "Captions are unavailable right now.";
|
|
8947
|
+
function resolveCaptionsState(i) {
|
|
8948
|
+
if (!i.on) return { state: "off", reason: null, remedy: null };
|
|
8949
|
+
if (i.takerState === "transcribing" && i.takerPresent) return { state: "live", reason: null, remedy: null };
|
|
8950
|
+
if (i.takerState === "joining" && !i.timedOut) return { state: "starting", reason: null, remedy: null };
|
|
8951
|
+
if (i.refusal !== null && i.refusal.reason.length > 0) {
|
|
8952
|
+
return { state: "unavailable", reason: i.refusal.reason, remedy: i.refusal.remedy.length > 0 ? i.refusal.remedy : null };
|
|
8953
|
+
}
|
|
8954
|
+
if (i.takerState === "ended" || i.takerState === "handoff_pending") {
|
|
8955
|
+
return { state: "unavailable", reason: i.takerLabel, remedy: null };
|
|
8956
|
+
}
|
|
8957
|
+
if (i.timedOut) return { state: "unavailable", reason: CAPTIONS_TIMEOUT_REASON, remedy: null };
|
|
8958
|
+
return { state: "starting", reason: null, remedy: null };
|
|
8959
|
+
}
|
|
8960
|
+
|
|
8904
8961
|
// src/core/layout.ts
|
|
8905
8962
|
var DEFAULT_PAGE_SIZE = 12;
|
|
8906
8963
|
function orderParticipants(participants, activeSpeakers) {
|
|
@@ -8991,7 +9048,8 @@ function useRoom() {
|
|
|
8991
9048
|
local,
|
|
8992
9049
|
// An observer (role `viewer`) publishes nothing: no Share screen to press and be refused (MD-16).
|
|
8993
9050
|
sharingAllowed: snapshot === null || canShareUnder(snapshot.livePolicy, effectiveRole(snapshot), effectiveStanding(snapshot)),
|
|
8994
|
-
canShareScreen: (engine?.supportsScreenShare() ?? true) && !isObserverRole(snapshot?.grants.role ?? null) &&
|
|
9051
|
+
canShareScreen: (engine?.supportsScreenShare() ?? true) && !isObserverRole(snapshot?.grants.role ?? null) && // The server's word that sharing was taken away arrives before the rules refresh does: the control goes at once.
|
|
9052
|
+
!(snapshot?.share.state === "ended" && snapshot.share.reason === "not_allowed") && (snapshot === null || canShareUnder(snapshot.livePolicy, effectiveRole(snapshot), effectiveStanding(snapshot))),
|
|
8995
9053
|
otherPresenter: otherPresenterOf(snapshot),
|
|
8996
9054
|
join: useCallback2(
|
|
8997
9055
|
async (request) => requireEngine(engine, "join").join(request),
|
|
@@ -9388,32 +9446,37 @@ function useCaptions() {
|
|
|
9388
9446
|
if (host === null || meeting === null) return;
|
|
9389
9447
|
void host.ai.requestCaptions({ meetingId: meeting.id });
|
|
9390
9448
|
}, [host, meeting]);
|
|
9449
|
+
const [timedOut, setTimedOut] = useState3(false);
|
|
9450
|
+
const timeoutSeconds = snapshot?.captionsStartTimeoutSeconds ?? 20;
|
|
9451
|
+
const live = taker.state === "transcribing" && taker.present;
|
|
9452
|
+
const [attempt, setAttempt] = useState3(0);
|
|
9453
|
+
useEffect3(() => {
|
|
9454
|
+
setTimedOut(false);
|
|
9455
|
+
if (!on || live) return void 0;
|
|
9456
|
+
const id = setTimeout(() => setTimedOut(true), timeoutSeconds * 1e3);
|
|
9457
|
+
return () => clearTimeout(id);
|
|
9458
|
+
}, [on, live, timeoutSeconds, attempt]);
|
|
9391
9459
|
const toggle = useCallback2(() => {
|
|
9392
9460
|
if (host === null) return;
|
|
9393
9461
|
const next = !on;
|
|
9394
9462
|
host.store.patch({ captionsOn: next, captionsRefusal: null });
|
|
9395
9463
|
if (next && taker.state !== "joining" && taker.state !== "transcribing") request();
|
|
9396
9464
|
}, [host, on, taker.state, request]);
|
|
9397
|
-
|
|
9398
|
-
|
|
9399
|
-
|
|
9400
|
-
|
|
9401
|
-
|
|
9402
|
-
|
|
9403
|
-
|
|
9404
|
-
|
|
9405
|
-
|
|
9406
|
-
|
|
9407
|
-
|
|
9408
|
-
|
|
9409
|
-
|
|
9410
|
-
|
|
9411
|
-
|
|
9412
|
-
} else {
|
|
9413
|
-
state = "starting";
|
|
9414
|
-
}
|
|
9415
|
-
}
|
|
9416
|
-
return { on, state, reason, remedy, toggle };
|
|
9465
|
+
const retry = useCallback2(() => {
|
|
9466
|
+
if (host === null) return;
|
|
9467
|
+
host.store.patch({ captionsOn: true, captionsRefusal: null });
|
|
9468
|
+
setAttempt((n) => n + 1);
|
|
9469
|
+
request();
|
|
9470
|
+
}, [host, request]);
|
|
9471
|
+
const view = resolveCaptionsState({
|
|
9472
|
+
on,
|
|
9473
|
+
takerState: taker.state,
|
|
9474
|
+
takerPresent: taker.present,
|
|
9475
|
+
refusal: refusal2,
|
|
9476
|
+
takerLabel: on ? noteTakerLabel(taker) : "",
|
|
9477
|
+
timedOut
|
|
9478
|
+
});
|
|
9479
|
+
return { on, state: view.state, reason: view.reason, remedy: view.remedy, toggle, retry };
|
|
9417
9480
|
}
|
|
9418
9481
|
function useEndMeeting() {
|
|
9419
9482
|
const host = useMeetHost();
|
|
@@ -13932,11 +13995,14 @@ function Captions({ lines = 3 }) {
|
|
|
13932
13995
|
const captions = useCaptions();
|
|
13933
13996
|
if (!captions.on) return null;
|
|
13934
13997
|
if (captions.state === "unavailable") {
|
|
13935
|
-
return /* @__PURE__ */
|
|
13936
|
-
"
|
|
13937
|
-
|
|
13938
|
-
|
|
13939
|
-
|
|
13998
|
+
return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__captions", role: "status", "data-meet-notice": "captions-unavailable", children: [
|
|
13999
|
+
/* @__PURE__ */ jsxs4("p", { className: "mx-meet__caption", children: [
|
|
14000
|
+
(captions.reason ?? "").startsWith("Captions are unavailable") ? "" : "Captions are unavailable. ",
|
|
14001
|
+
captions.reason,
|
|
14002
|
+
captions.remedy !== null ? ` ${captions.remedy}` : ""
|
|
14003
|
+
] }),
|
|
14004
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__caption-retry", onClick: captions.retry, children: "Try again" })
|
|
14005
|
+
] });
|
|
13940
14006
|
}
|
|
13941
14007
|
if (visible.length === 0) {
|
|
13942
14008
|
return /* @__PURE__ */ jsx6("div", { className: "mx-meet__captions", "aria-live": "polite", "aria-label": "Live captions", "data-meet-caption": captions.state, children: /* @__PURE__ */ jsx6("p", { className: "mx-meet__caption mx-meet__caption--interim", children: captions.state === "starting" ? "Starting captions. They appear as people speak." : "Captions are on. They appear as people speak." }) });
|