@ai-matrx/meet 0.11.51 → 0.11.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.js CHANGED
@@ -2517,6 +2517,7 @@ function minutesLeft(policy, startedAtMs, nowMs) {
2517
2517
  function mayAdmitNow(role, participants, policy) {
2518
2518
  if (role === "none") return false;
2519
2519
  if (role === "host" || role === "cohost") return true;
2520
+ if (role === "viewer") return false;
2520
2521
  const hostIn = participants.some((p) => p.role === "host" || p.role === "cohost");
2521
2522
  return !hostIn && policy.headlessPowers === "members_admit";
2522
2523
  }
@@ -4329,6 +4330,17 @@ function createMeetingSession(options) {
4329
4330
  }
4330
4331
  return identity.userId;
4331
4332
  }
4333
+ function requireAdmitterUser(operation) {
4334
+ const snapshot = store.snapshot();
4335
+ if (identity.userId === null || !mayAdmitNow(effectiveRole(snapshot), snapshot.participants, snapshot.livePolicy)) {
4336
+ throw new MeetError(
4337
+ "forbidden",
4338
+ `${operation}: this participant may not let people in`,
4339
+ "Only a host or co-host admits people, unless the meeting has no host in it and lets members admit."
4340
+ );
4341
+ }
4342
+ return identity.userId;
4343
+ }
4332
4344
  function requireMeeting(operation) {
4333
4345
  const meeting = store.snapshot().meeting;
4334
4346
  if (meeting === null) {
@@ -4735,7 +4747,7 @@ function createMeetingSession(options) {
4735
4747
  meetingChannel.requestBackfill("manual");
4736
4748
  },
4737
4749
  async admit(entry, admitted) {
4738
- const by = requireHostUser("meet.admit");
4750
+ const by = requireAdmitterUser("meet.admit");
4739
4751
  const meeting = requireMeeting("meet.admit");
4740
4752
  const row = await repository.decideAdmission({
4741
4753
  meetingId: meeting.id,
@@ -4753,7 +4765,7 @@ function createMeetingSession(options) {
4753
4765
  hint();
4754
4766
  },
4755
4767
  async undeny(entry) {
4756
- const by = requireHostUser("meet.undeny");
4768
+ const by = requireAdmitterUser("meet.undeny");
4757
4769
  const meeting = requireMeeting("meet.undeny");
4758
4770
  const row = await repository.decideAdmission({
4759
4771
  meetingId: meeting.id,
@@ -4766,7 +4778,7 @@ function createMeetingSession(options) {
4766
4778
  hint();
4767
4779
  },
4768
4780
  async admitAll() {
4769
- const by = requireHostUser("meet.admitAll");
4781
+ const by = requireAdmitterUser("meet.admitAll");
4770
4782
  const meeting = requireMeeting("meet.admitAll");
4771
4783
  const rows = await repository.admitAll(meeting.id, by);
4772
4784
  for (const row of rows) {
@@ -5784,6 +5796,16 @@ var ALIVE_TOPIC = "mx.alive";
5784
5796
  function encodeBeat(beat) {
5785
5797
  return JSON.stringify({ q: beat.q, vp: beat.vp });
5786
5798
  }
5799
+ function encodeBye() {
5800
+ return JSON.stringify({ bye: true });
5801
+ }
5802
+ function isBye(payload) {
5803
+ try {
5804
+ return JSON.parse(payload).bye === true;
5805
+ } catch {
5806
+ return false;
5807
+ }
5808
+ }
5787
5809
  function decodeBeat(payload) {
5788
5810
  try {
5789
5811
  const raw = JSON.parse(payload);
@@ -6010,6 +6032,7 @@ function createRoomEngine(options) {
6010
6032
  const autoOff = createVideoAutoOff(() => connectionPolicy.videoAutoOffAfterPoorSeconds * 1e3, now);
6011
6033
  const lkQuality = /* @__PURE__ */ new Map();
6012
6034
  let silent = /* @__PURE__ */ new Set();
6035
+ const saidBye = /* @__PURE__ */ new Set();
6013
6036
  let healthTimer = null;
6014
6037
  let lastBeatAt = 0;
6015
6038
  let wasUnstable = false;
@@ -6040,6 +6063,7 @@ function createRoomEngine(options) {
6040
6063
  assessor.reset();
6041
6064
  autoOff.reset();
6042
6065
  silent = /* @__PURE__ */ new Set();
6066
+ saidBye.clear();
6043
6067
  lkQuality.clear();
6044
6068
  lastBeatAt = 0;
6045
6069
  wasUnstable = false;
@@ -6097,6 +6121,13 @@ function createRoomEngine(options) {
6097
6121
  await target?.disconnect();
6098
6122
  }
6099
6123
  async function leaveRoom() {
6124
+ const target = driver;
6125
+ if (target !== null && store.snapshot().phase === "in_call") {
6126
+ await Promise.race([
6127
+ target.publishData(ALIVE_TOPIC, encodeBye()).catch(() => void 0),
6128
+ new Promise((resolve) => setTimeout(resolve, 300))
6129
+ ]);
6130
+ }
6100
6131
  store.dispatch({ type: "leave" });
6101
6132
  await dropRoom();
6102
6133
  options.onLeft?.(null);
@@ -6192,8 +6223,6 @@ function createRoomEngine(options) {
6192
6223
  },
6193
6224
  participantLeft(who, reason) {
6194
6225
  departures.set(who, reason);
6195
- liveness.forget(who);
6196
- silent.delete(who);
6197
6226
  },
6198
6227
  roomMetadata(metadata) {
6199
6228
  let parsed = {};
@@ -6236,8 +6265,12 @@ function createRoomEngine(options) {
6236
6265
  const snap = store.snapshot();
6237
6266
  if (snap.phase !== "in_call" || snap.connection !== "stable") return;
6238
6267
  startHealth();
6268
+ const before = assessor.current();
6239
6269
  const quality = assessor.push(reading);
6240
6270
  const path = pathOf(reading);
6271
+ if (quality !== before) {
6272
+ report("info", `meet: this connection reads ${quality} (round trip ${reading.rttMs ?? "?"} ms, path ${path})`, "Diagnostic only.");
6273
+ }
6241
6274
  patchLocalNetwork({ quality, ...path !== "unknown" ? { path } : {} });
6242
6275
  refreshQualities();
6243
6276
  const cameraOn = snap.media.camera.enabled;
@@ -6252,6 +6285,11 @@ function createRoomEngine(options) {
6252
6285
  connectionState(state) {
6253
6286
  supervisor.driverState(state);
6254
6287
  if (state === "connected" && store.snapshot().phase === "joining") store.dispatch({ type: "connected" });
6288
+ if (state === "connected") {
6289
+ startHealth();
6290
+ lastBeatAt = 0;
6291
+ healthTick();
6292
+ }
6255
6293
  },
6256
6294
  transcription(event) {
6257
6295
  const snapshot = store.snapshot();
@@ -6343,6 +6381,10 @@ function createRoomEngine(options) {
6343
6381
  }
6344
6382
  const sender = personOf(from ?? "");
6345
6383
  if (from !== null) {
6384
+ if (topic === ALIVE_TOPIC && isBye(payload)) {
6385
+ saidBye.add(from);
6386
+ return;
6387
+ }
6346
6388
  const beat = topic === ALIVE_TOPIC ? decodeBeat(payload) : null;
6347
6389
  const before = liveness.reported(from);
6348
6390
  liveness.heard(from, beat);
@@ -6575,10 +6617,17 @@ function createRoomEngine(options) {
6575
6617
  const graceMs = connectionPolicy.reconnectGraceSeconds * 1e3;
6576
6618
  for (const [who, reason] of departures) {
6577
6619
  const last = previous.get(who);
6578
- if (last !== void 0 && !last.isLocal && !present.has(who) && graceMs > 0 && isUnannouncedDeparture(reason)) {
6620
+ const dropped = !saidBye.has(who) && (isUnannouncedDeparture(reason) || silent.has(who));
6621
+ report("info", `meet: ${who} left the room (${reason ?? "no reason"}${dropped ? ", held as reconnecting" : ""})`, "Diagnostic only.");
6622
+ if (last !== void 0 && !last.isLocal && !present.has(who) && graceMs > 0 && dropped) {
6579
6623
  ghosts.set(who, { participant: last, until: at + graceMs });
6580
6624
  }
6581
6625
  }
6626
+ for (const who of departures.keys()) {
6627
+ liveness.forget(who);
6628
+ silent.delete(who);
6629
+ saidBye.delete(who);
6630
+ }
6582
6631
  departures.clear();
6583
6632
  liveRoster = list;
6584
6633
  const localNow = list.find((p) => p.isLocal);