@ai-matrx/meet 0.11.53 → 0.11.55

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/index.js CHANGED
@@ -3333,6 +3333,10 @@ function personOf(identity) {
3333
3333
  const cut = value.indexOf(CONNECTION_SEPARATOR);
3334
3334
  return cut === -1 ? value : value.slice(0, cut);
3335
3335
  }
3336
+ function userIdOfIdentity(identity) {
3337
+ const person = personOf(identity);
3338
+ return person.startsWith("user:") ? person.slice("user:".length) : null;
3339
+ }
3336
3340
  function isGuestIdentity(identity) {
3337
3341
  return personOf(identity).startsWith("guest:");
3338
3342
  }
@@ -4638,21 +4642,35 @@ function heartbeatIntervalMs(roomSize) {
4638
4642
  function staleAfterMs(roomSize) {
4639
4643
  return heartbeatIntervalMs(roomSize) * 3 + 1e3;
4640
4644
  }
4645
+ function firstBeatAllowanceMs(roomSize) {
4646
+ return staleAfterMs(roomSize) * 2;
4647
+ }
4641
4648
  function createLivenessTracker(now) {
4642
4649
  const lastHeard = /* @__PURE__ */ new Map();
4650
+ const firstSeen = /* @__PURE__ */ new Map();
4643
4651
  const beats = /* @__PURE__ */ new Map();
4644
4652
  return {
4645
4653
  heard(who, beat) {
4646
4654
  lastHeard.set(who, now());
4655
+ firstSeen.delete(who);
4647
4656
  if (beat !== null) beats.set(who, beat);
4648
4657
  },
4658
+ expect(who) {
4659
+ if (!lastHeard.has(who) && !firstSeen.has(who)) firstSeen.set(who, now());
4660
+ },
4649
4661
  stale(present, roomSize) {
4650
4662
  const limit = staleAfterMs(roomSize);
4663
+ const firstLimit = firstBeatAllowanceMs(roomSize);
4651
4664
  const at = now();
4652
4665
  const out = /* @__PURE__ */ new Set();
4653
4666
  for (const who of present) {
4654
4667
  const heard = lastHeard.get(who);
4655
- if (heard !== void 0 && at - heard > limit) out.add(who);
4668
+ if (heard !== void 0) {
4669
+ if (at - heard > limit) out.add(who);
4670
+ continue;
4671
+ }
4672
+ const seen = firstSeen.get(who);
4673
+ if (seen !== void 0 && at - seen > firstLimit) out.add(who);
4656
4674
  }
4657
4675
  return out;
4658
4676
  },
@@ -4660,13 +4678,16 @@ function createLivenessTracker(now) {
4660
4678
  restartClock() {
4661
4679
  const at = now();
4662
4680
  for (const who of lastHeard.keys()) lastHeard.set(who, at);
4681
+ for (const who of firstSeen.keys()) firstSeen.set(who, at);
4663
4682
  },
4664
4683
  forget(who) {
4665
4684
  lastHeard.delete(who);
4685
+ firstSeen.delete(who);
4666
4686
  beats.delete(who);
4667
4687
  },
4668
4688
  clear() {
4669
4689
  lastHeard.clear();
4690
+ firstSeen.clear();
4670
4691
  beats.clear();
4671
4692
  }
4672
4693
  };
@@ -4889,14 +4910,22 @@ function createLiveKitDriver(handlers, options = {}) {
4889
4910
  ...options.roomOptions
4890
4911
  });
4891
4912
  const reasonName = (reason) => reason === void 0 || reason === null ? null : module.DisconnectReason?.[reason] ?? String(reason);
4892
- const roster = () => {
4913
+ const emitRoster = () => {
4914
+ rosterQueued = false;
4915
+ if (room !== created) return;
4893
4916
  const local = snapshotParticipant(created.localParticipant, true);
4894
4917
  const remotes = [...created.remoteParticipants.values()].map(
4895
4918
  (participant) => snapshotParticipant(participant, false)
4896
4919
  );
4897
4920
  handlers.participants([local, ...remotes]);
4898
4921
  };
4899
- projectRoster = roster;
4922
+ let rosterQueued = false;
4923
+ const roster = () => {
4924
+ if (rosterQueued) return;
4925
+ rosterQueued = true;
4926
+ queueMicrotask(emitRoster);
4927
+ };
4928
+ projectRoster = emitRoster;
4900
4929
  created.on(RoomEvent.TrackSubscribed, (track) => {
4901
4930
  if (track.kind !== Track.Kind.Audio || typeof document === "undefined") return;
4902
4931
  if (!remoteAudioPlayback) return;
@@ -7466,6 +7495,13 @@ function createRoomEngine(options) {
7466
7495
  const previous = new Map(liveRoster.map((p) => [p.identity, p]));
7467
7496
  const present = new Set(list.map((p) => p.identity));
7468
7497
  const graceMs = connectionPolicy.reconnectGraceSeconds * 1e3;
7498
+ if (store.snapshot().phase === "in_call") {
7499
+ for (const [who, last] of previous) {
7500
+ if (last.isLocal || present.has(who) || departures.has(who)) continue;
7501
+ departures.set(who, null);
7502
+ report("warn", `meet: ${who} vanished from the room's roster with no departure event; held as reconnecting`, "The media layer dropped a participant silently; the tile is kept for the reconnect grace.");
7503
+ }
7504
+ }
7469
7505
  for (const [who, reason] of departures) {
7470
7506
  const last = previous.get(who);
7471
7507
  const dropped = !saidBye.has(who) && (isUnannouncedDeparture(reason) || silent.has(who));
@@ -7481,6 +7517,9 @@ function createRoomEngine(options) {
7481
7517
  }
7482
7518
  departures.clear();
7483
7519
  liveRoster = list;
7520
+ for (const p of list) {
7521
+ if (!p.isLocal && (isGuestIdentity(p.identity) || userIdOfIdentity(p.identity) !== null)) liveness.expect(p.identity);
7522
+ }
7484
7523
  const localNow = list.find((p) => p.isLocal);
7485
7524
  if (localNow !== void 0 && !localNow.screenSharing && store.snapshot().share.state === "presenting") {
7486
7525
  store.patch({ share: NO_SHARE });
@@ -7501,7 +7540,7 @@ function createRoomEngine(options) {
7501
7540
  store.setParticipants(
7502
7541
  [...people.values()].map(({ entry }) => {
7503
7542
  const projected = projectParticipant(entry, joinedAt);
7504
- if (entry.reconnecting === true || !entry.isLocal && silent.has(entry.identity)) {
7543
+ if (entry.reconnecting === true || !entry.isLocal && silent.has(entry.identity) && !saidBye.has(entry.identity)) {
7505
7544
  return { ...projected, reconnecting: true, quality: "lost" };
7506
7545
  }
7507
7546
  const videoPaused = entry.isLocal ? store.snapshot().localNetwork.videoPaused : liveness.reported(entry.identity)?.vp === true;