@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.cjs CHANGED
@@ -2844,6 +2844,7 @@ function minutesLeft(policy, startedAtMs, nowMs) {
2844
2844
  function mayAdmitNow(role, participants, policy) {
2845
2845
  if (role === "none") return false;
2846
2846
  if (role === "host" || role === "cohost") return true;
2847
+ if (role === "viewer") return false;
2847
2848
  const hostIn = participants.some((p) => p.role === "host" || p.role === "cohost");
2848
2849
  return !hostIn && policy.headlessPowers === "members_admit";
2849
2850
  }
@@ -4656,6 +4657,17 @@ function createMeetingSession(options) {
4656
4657
  }
4657
4658
  return identity.userId;
4658
4659
  }
4660
+ function requireAdmitterUser(operation) {
4661
+ const snapshot = store.snapshot();
4662
+ if (identity.userId === null || !mayAdmitNow(effectiveRole(snapshot), snapshot.participants, snapshot.livePolicy)) {
4663
+ throw new MeetError(
4664
+ "forbidden",
4665
+ `${operation}: this participant may not let people in`,
4666
+ "Only a host or co-host admits people, unless the meeting has no host in it and lets members admit."
4667
+ );
4668
+ }
4669
+ return identity.userId;
4670
+ }
4659
4671
  function requireMeeting(operation) {
4660
4672
  const meeting = store.snapshot().meeting;
4661
4673
  if (meeting === null) {
@@ -5062,7 +5074,7 @@ function createMeetingSession(options) {
5062
5074
  meetingChannel.requestBackfill("manual");
5063
5075
  },
5064
5076
  async admit(entry, admitted) {
5065
- const by = requireHostUser("meet.admit");
5077
+ const by = requireAdmitterUser("meet.admit");
5066
5078
  const meeting = requireMeeting("meet.admit");
5067
5079
  const row = await repository.decideAdmission({
5068
5080
  meetingId: meeting.id,
@@ -5080,7 +5092,7 @@ function createMeetingSession(options) {
5080
5092
  hint();
5081
5093
  },
5082
5094
  async undeny(entry) {
5083
- const by = requireHostUser("meet.undeny");
5095
+ const by = requireAdmitterUser("meet.undeny");
5084
5096
  const meeting = requireMeeting("meet.undeny");
5085
5097
  const row = await repository.decideAdmission({
5086
5098
  meetingId: meeting.id,
@@ -5093,7 +5105,7 @@ function createMeetingSession(options) {
5093
5105
  hint();
5094
5106
  },
5095
5107
  async admitAll() {
5096
- const by = requireHostUser("meet.admitAll");
5108
+ const by = requireAdmitterUser("meet.admitAll");
5097
5109
  const meeting = requireMeeting("meet.admitAll");
5098
5110
  const rows = await repository.admitAll(meeting.id, by);
5099
5111
  for (const row of rows) {
@@ -6109,6 +6121,16 @@ var ALIVE_TOPIC = "mx.alive";
6109
6121
  function encodeBeat(beat) {
6110
6122
  return JSON.stringify({ q: beat.q, vp: beat.vp });
6111
6123
  }
6124
+ function encodeBye() {
6125
+ return JSON.stringify({ bye: true });
6126
+ }
6127
+ function isBye(payload) {
6128
+ try {
6129
+ return JSON.parse(payload).bye === true;
6130
+ } catch {
6131
+ return false;
6132
+ }
6133
+ }
6112
6134
  function decodeBeat(payload) {
6113
6135
  try {
6114
6136
  const raw = JSON.parse(payload);
@@ -6335,6 +6357,7 @@ function createRoomEngine(options) {
6335
6357
  const autoOff = createVideoAutoOff(() => connectionPolicy.videoAutoOffAfterPoorSeconds * 1e3, now);
6336
6358
  const lkQuality = /* @__PURE__ */ new Map();
6337
6359
  let silent = /* @__PURE__ */ new Set();
6360
+ const saidBye = /* @__PURE__ */ new Set();
6338
6361
  let healthTimer = null;
6339
6362
  let lastBeatAt = 0;
6340
6363
  let wasUnstable = false;
@@ -6365,6 +6388,7 @@ function createRoomEngine(options) {
6365
6388
  assessor.reset();
6366
6389
  autoOff.reset();
6367
6390
  silent = /* @__PURE__ */ new Set();
6391
+ saidBye.clear();
6368
6392
  lkQuality.clear();
6369
6393
  lastBeatAt = 0;
6370
6394
  wasUnstable = false;
@@ -6422,6 +6446,13 @@ function createRoomEngine(options) {
6422
6446
  await target?.disconnect();
6423
6447
  }
6424
6448
  async function leaveRoom() {
6449
+ const target = driver;
6450
+ if (target !== null && store.snapshot().phase === "in_call") {
6451
+ await Promise.race([
6452
+ target.publishData(ALIVE_TOPIC, encodeBye()).catch(() => void 0),
6453
+ new Promise((resolve) => setTimeout(resolve, 300))
6454
+ ]);
6455
+ }
6425
6456
  store.dispatch({ type: "leave" });
6426
6457
  await dropRoom();
6427
6458
  options.onLeft?.(null);
@@ -6517,8 +6548,6 @@ function createRoomEngine(options) {
6517
6548
  },
6518
6549
  participantLeft(who, reason) {
6519
6550
  departures.set(who, reason);
6520
- liveness.forget(who);
6521
- silent.delete(who);
6522
6551
  },
6523
6552
  roomMetadata(metadata) {
6524
6553
  let parsed = {};
@@ -6561,8 +6590,12 @@ function createRoomEngine(options) {
6561
6590
  const snap = store.snapshot();
6562
6591
  if (snap.phase !== "in_call" || snap.connection !== "stable") return;
6563
6592
  startHealth();
6593
+ const before = assessor.current();
6564
6594
  const quality = assessor.push(reading);
6565
6595
  const path = pathOf(reading);
6596
+ if (quality !== before) {
6597
+ report("info", `meet: this connection reads ${quality} (round trip ${reading.rttMs ?? "?"} ms, path ${path})`, "Diagnostic only.");
6598
+ }
6566
6599
  patchLocalNetwork({ quality, ...path !== "unknown" ? { path } : {} });
6567
6600
  refreshQualities();
6568
6601
  const cameraOn = snap.media.camera.enabled;
@@ -6577,6 +6610,11 @@ function createRoomEngine(options) {
6577
6610
  connectionState(state) {
6578
6611
  supervisor.driverState(state);
6579
6612
  if (state === "connected" && store.snapshot().phase === "joining") store.dispatch({ type: "connected" });
6613
+ if (state === "connected") {
6614
+ startHealth();
6615
+ lastBeatAt = 0;
6616
+ healthTick();
6617
+ }
6580
6618
  },
6581
6619
  transcription(event) {
6582
6620
  const snapshot = store.snapshot();
@@ -6668,6 +6706,10 @@ function createRoomEngine(options) {
6668
6706
  }
6669
6707
  const sender = personOf(from ?? "");
6670
6708
  if (from !== null) {
6709
+ if (topic === ALIVE_TOPIC && isBye(payload)) {
6710
+ saidBye.add(from);
6711
+ return;
6712
+ }
6671
6713
  const beat = topic === ALIVE_TOPIC ? decodeBeat(payload) : null;
6672
6714
  const before = liveness.reported(from);
6673
6715
  liveness.heard(from, beat);
@@ -6900,10 +6942,17 @@ function createRoomEngine(options) {
6900
6942
  const graceMs = connectionPolicy.reconnectGraceSeconds * 1e3;
6901
6943
  for (const [who, reason] of departures) {
6902
6944
  const last = previous.get(who);
6903
- if (last !== void 0 && !last.isLocal && !present.has(who) && graceMs > 0 && isUnannouncedDeparture(reason)) {
6945
+ const dropped = !saidBye.has(who) && (isUnannouncedDeparture(reason) || silent.has(who));
6946
+ report("info", `meet: ${who} left the room (${reason ?? "no reason"}${dropped ? ", held as reconnecting" : ""})`, "Diagnostic only.");
6947
+ if (last !== void 0 && !last.isLocal && !present.has(who) && graceMs > 0 && dropped) {
6904
6948
  ghosts.set(who, { participant: last, until: at + graceMs });
6905
6949
  }
6906
6950
  }
6951
+ for (const who of departures.keys()) {
6952
+ liveness.forget(who);
6953
+ silent.delete(who);
6954
+ saidBye.delete(who);
6955
+ }
6907
6956
  departures.clear();
6908
6957
  liveRoster = list;
6909
6958
  const localNow = list.find((p) => p.isLocal);