@ai-matrx/meet 0.8.0 → 0.9.0
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 +26 -0
- package/dist/{collab-Bss-_Jfp.d.cts → collab-B6scmSST.d.cts} +18 -12
- package/dist/{collab-Bss-_Jfp.d.ts → collab-B6scmSST.d.ts} +18 -12
- package/dist/{components-BOUmOiPj.d.cts → components-BeCQ9h0h.d.cts} +1 -1
- package/dist/{components-BmgstFx_.d.ts → components-D0TqyeiY.d.ts} +1 -1
- package/dist/core.cjs +113 -50
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +55 -19
- package/dist/core.d.ts +55 -19
- package/dist/core.js +113 -50
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +113 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +113 -50
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +129 -57
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +4 -4
- package/dist/react.d.ts +4 -4
- package/dist/react.js +129 -57
- package/dist/react.js.map +1 -1
- package/dist/skins/meet.cjs +47 -15
- package/dist/skins/meet.cjs.map +1 -1
- package/dist/skins/meet.d.cts +2 -2
- package/dist/skins/meet.d.ts +2 -2
- package/dist/skins/meet.js +47 -15
- package/dist/skins/meet.js.map +1 -1
- package/package.json +4 -4
package/dist/react.cjs
CHANGED
|
@@ -55,6 +55,7 @@ __export(react_exports, {
|
|
|
55
55
|
LISTEN_ONLY_NOTICE: () => LISTEN_ONLY_NOTICE,
|
|
56
56
|
MEETING_INVITE_KIND: () => MEETING_INVITE_KIND,
|
|
57
57
|
MEETING_INVITE_VERSION: () => MEETING_INVITE_VERSION,
|
|
58
|
+
MEETING_PASS_HEADER: () => MEETING_PASS_HEADER,
|
|
58
59
|
MEETING_RECORD_GRACE_MS: () => MEETING_RECORD_GRACE_MS,
|
|
59
60
|
MEET_ANSWER_CONTEXT_EVENT: () => MEET_ANSWER_CONTEXT_EVENT,
|
|
60
61
|
MEET_ANSWER_EVENTS: () => MEET_ANSWER_EVENTS,
|
|
@@ -75,12 +76,12 @@ __export(react_exports, {
|
|
|
75
76
|
ORGANIZATION_HEADER: () => ORGANIZATION_HEADER,
|
|
76
77
|
PARTICIPANT_CAN_RECORD_ATTRIBUTE: () => PARTICIPANT_CAN_RECORD_ATTRIBUTE,
|
|
77
78
|
PARTICIPANT_ROLE_ATTRIBUTE: () => PARTICIPANT_ROLE_ATTRIBUTE,
|
|
79
|
+
PARTICIPANT_STANDING_ATTRIBUTE: () => PARTICIPANT_STANDING_ATTRIBUTE,
|
|
78
80
|
REACTION_TTL_MS: () => REACTION_TTL_MS,
|
|
79
81
|
REFUSED_ABSENCE: () => REFUSED_ABSENCE,
|
|
80
82
|
ROLE_RANK: () => ROLE_RANK,
|
|
81
83
|
ROOM_EVENTS: () => ROOM_EVENTS,
|
|
82
84
|
ROOM_EVENT_PREFIX: () => ROOM_EVENT_PREFIX,
|
|
83
|
-
ROOM_TOKEN_HEADER: () => ROOM_TOKEN_HEADER,
|
|
84
85
|
RPCS: () => RPCS,
|
|
85
86
|
RecordingPlayer: () => RecordingPlayer,
|
|
86
87
|
TABLES: () => TABLES,
|
|
@@ -152,6 +153,7 @@ __export(react_exports, {
|
|
|
152
153
|
isGuest: () => isGuest,
|
|
153
154
|
isGuestIdentity: () => isGuestIdentity,
|
|
154
155
|
isHostRole: () => isHostRole,
|
|
156
|
+
isLinkFollower: () => isLinkFollower,
|
|
155
157
|
isListenOnly: () => isListenOnly,
|
|
156
158
|
isNoteTaker: () => isNoteTaker,
|
|
157
159
|
isRealName: () => isRealName,
|
|
@@ -170,6 +172,7 @@ __export(react_exports, {
|
|
|
170
172
|
meetingInviteAction: () => meetingInviteAction,
|
|
171
173
|
meetingLength: () => meetingLength,
|
|
172
174
|
meetingLink: () => meetingLink,
|
|
175
|
+
meetingPassHeaders: () => meetingPassHeaders,
|
|
173
176
|
meetingPath: () => meetingPath,
|
|
174
177
|
meetingRecordCache: () => meetingRecordCache,
|
|
175
178
|
meetingSlug: () => meetingSlug,
|
|
@@ -214,6 +217,7 @@ __export(react_exports, {
|
|
|
214
217
|
recordingLabel: () => recordingLabel,
|
|
215
218
|
recordingNotice: () => recordingNotice,
|
|
216
219
|
recordingOffsetMs: () => recordingOffsetMs,
|
|
220
|
+
rememberedMeetingPass: () => rememberedMeetingPass,
|
|
217
221
|
roleOf: () => roleOf,
|
|
218
222
|
roomTopic: () => roomTopic,
|
|
219
223
|
rootAttributes: () => rootAttributes,
|
|
@@ -294,11 +298,18 @@ var MeetError = class extends Error {
|
|
|
294
298
|
/** What to DO. Rendered to the user for the device codes. */
|
|
295
299
|
remedy;
|
|
296
300
|
cause;
|
|
297
|
-
|
|
301
|
+
/**
|
|
302
|
+
* The join gate's reason code (CORE-DESIGN §2.5) when the server named one: `not_found`,
|
|
303
|
+
* `cancelled`, `ended`, `locked`, `removed`, `lobby_rejects`, `not_invited`… The phase
|
|
304
|
+
* renders `refused:<reason>` (or `ended`) from it — never from the HTTP status.
|
|
305
|
+
*/
|
|
306
|
+
reason;
|
|
307
|
+
constructor(code, message, remedy, cause, reason) {
|
|
298
308
|
super(message);
|
|
299
309
|
this.name = "MeetError";
|
|
300
310
|
this.code = code;
|
|
301
311
|
this.remedy = remedy;
|
|
312
|
+
this.reason = reason ?? null;
|
|
302
313
|
if (cause !== void 0) this.cause = cause;
|
|
303
314
|
}
|
|
304
315
|
/** True when retrying after the host re-establishes a session is the fix. */
|
|
@@ -516,6 +527,17 @@ function createWebRoomTokenStorage(onDiagnostic) {
|
|
|
516
527
|
}
|
|
517
528
|
};
|
|
518
529
|
}
|
|
530
|
+
function rememberedMeetingPass(roomName, storage = createWebRoomTokenStorage()) {
|
|
531
|
+
const raw = storage.read(roomName);
|
|
532
|
+
if (raw === null) return null;
|
|
533
|
+
try {
|
|
534
|
+
const parsed = JSON.parse(raw);
|
|
535
|
+
if (parsed.standing !== "guest") return null;
|
|
536
|
+
return typeof parsed.meetingPass === "string" && parsed.meetingPass.length > 0 ? parsed.meetingPass : null;
|
|
537
|
+
} catch {
|
|
538
|
+
return null;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
519
541
|
var MEET_ROUTES = {
|
|
520
542
|
token: "/api/v1/meet/token",
|
|
521
543
|
recordingStart: "/api/v1/meet/recording/start",
|
|
@@ -529,7 +551,7 @@ var MEET_ROUTES = {
|
|
|
529
551
|
/**
|
|
530
552
|
* THE POST-MEETING RECORD FOR A READER WITH NO DATABASE (MRF-1). A `GET`,
|
|
531
553
|
* authorized by the room token this device already holds, carried in the
|
|
532
|
-
* `x-meet-
|
|
554
|
+
* `x-meet-pass` header — never a query parameter, because a bearer
|
|
533
555
|
* credential in a URL lands in access logs, referrers and history.
|
|
534
556
|
*/
|
|
535
557
|
record: "/api/v1/meet/record",
|
|
@@ -537,7 +559,7 @@ var MEET_ROUTES = {
|
|
|
537
559
|
recordAccess: "/api/v1/meet/record/access",
|
|
538
560
|
/**
|
|
539
561
|
* KEEP YOUR NOTES (2026-10-01): a guest who just created an account presents
|
|
540
|
-
* their kept pass in `x-meet-
|
|
562
|
+
* their kept pass in `x-meet-pass` with their new session, and the
|
|
541
563
|
* meeting they attended becomes theirs to read. Idempotent; never a grant.
|
|
542
564
|
*/
|
|
543
565
|
claim: "/api/v1/meet/claim",
|
|
@@ -559,7 +581,7 @@ var MEET_ROUTES = {
|
|
|
559
581
|
* Meet wave 2: EVERY in-meeting host power (mute, stop video, mute all, ask to
|
|
560
582
|
* unmute, spotlight, lower hands, co-host, hand over, rename, remove, report).
|
|
561
583
|
* Decided by the server from the meeting itself; a guest's pass rides
|
|
562
|
-
* `x-meet-
|
|
584
|
+
* `x-meet-pass`.
|
|
563
585
|
*/
|
|
564
586
|
moderate: "/api/v1/meet/moderate",
|
|
565
587
|
/** Meet wave 2: the SAVED chat — `POST` sends to everyone, `GET ?meeting_id=` reads history. */
|
|
@@ -575,7 +597,11 @@ var MEET_ROUTES = {
|
|
|
575
597
|
function meetingPath(template, meetingId) {
|
|
576
598
|
return template.replace("{meeting_id}", encodeURIComponent(meetingId));
|
|
577
599
|
}
|
|
578
|
-
var
|
|
600
|
+
var MEETING_PASS_HEADER = "x-meet-pass";
|
|
601
|
+
function meetingPassHeaders(token) {
|
|
602
|
+
const pass = token?.meetingPass ?? null;
|
|
603
|
+
return pass !== null && pass.length > 0 ? { [MEETING_PASS_HEADER]: pass } : {};
|
|
604
|
+
}
|
|
579
605
|
var REFRESH_RATIO = 0.8;
|
|
580
606
|
function readString(source, key) {
|
|
581
607
|
const value = source[key];
|
|
@@ -585,7 +611,12 @@ function readBoolean(source, key, fallback) {
|
|
|
585
611
|
const value = source[key];
|
|
586
612
|
return typeof value === "boolean" ? value : fallback;
|
|
587
613
|
}
|
|
588
|
-
var
|
|
614
|
+
var TOKEN_STANDINGS = ["member", "invited", "outsider", "guest"];
|
|
615
|
+
function readStanding(source, key) {
|
|
616
|
+
const value = source[key];
|
|
617
|
+
return TOKEN_STANDINGS.includes(value) ? value : null;
|
|
618
|
+
}
|
|
619
|
+
var TOKEN_ROLES = ["host", "cohost", "presenter", "participant", "viewer"];
|
|
589
620
|
function readRole(source, key) {
|
|
590
621
|
const value = source[key];
|
|
591
622
|
return TOKEN_ROLES.includes(value) ? value : null;
|
|
@@ -628,7 +659,12 @@ function parseRoomToken(body, roomName) {
|
|
|
628
659
|
// Deriving the role from what DID arrive keeps a host a host against a
|
|
629
660
|
// server that has not landed MRI-A11 — and never invents a host from
|
|
630
661
|
// silence, because both fallbacks below grant nothing.
|
|
631
|
-
|
|
662
|
+
// A word this package does not know grants nothing: `participant`, never a host.
|
|
663
|
+
role: readRole(payload, "role") ?? (isHost ? "host" : "participant"),
|
|
664
|
+
standing: readStanding(payload, "standing"),
|
|
665
|
+
meetingPass: readString(payload, "meeting_pass"),
|
|
666
|
+
meetingPassExpiresAt: readString(payload, "meeting_pass_expires_at"),
|
|
667
|
+
sessionId: readString(payload, "session_id"),
|
|
632
668
|
lobby: readBoolean(payload, "lobby", false),
|
|
633
669
|
breakoutRoomId: readString(payload, "breakout_room_id") ?? null
|
|
634
670
|
};
|
|
@@ -639,7 +675,7 @@ function createTokenClient(options) {
|
|
|
639
675
|
const storage = options.storage;
|
|
640
676
|
function remember(token) {
|
|
641
677
|
if (storage === void 0) return;
|
|
642
|
-
if (
|
|
678
|
+
if (token.standing !== "guest") return;
|
|
643
679
|
storage.write(token.roomName, JSON.stringify(token));
|
|
644
680
|
}
|
|
645
681
|
function recall(roomName) {
|
|
@@ -697,22 +733,28 @@ function createTokenClient(options) {
|
|
|
697
733
|
throw new MeetError(
|
|
698
734
|
"forbidden",
|
|
699
735
|
said?.message ?? "You can't join this meeting.",
|
|
700
|
-
said?.remedy ?? "Ask the person who shared the link to let you in, then open the link again."
|
|
736
|
+
said?.remedy ?? "Ask the person who shared the link to let you in, then open the link again.",
|
|
737
|
+
void 0,
|
|
738
|
+
said?.reason ?? null
|
|
701
739
|
);
|
|
702
740
|
}
|
|
703
741
|
if (response.status === 404) {
|
|
704
742
|
throw new MeetError(
|
|
705
743
|
"not-found",
|
|
706
744
|
"meet.token: no such meeting",
|
|
707
|
-
"The link is wrong or the meeting was deleted. Show the 'meeting not found' screen; a durable link that 404s is never a retry."
|
|
745
|
+
"The link is wrong or the meeting was deleted. Show the 'meeting not found' screen; a durable link that 404s is never a retry.",
|
|
746
|
+
void 0,
|
|
747
|
+
"not_found"
|
|
708
748
|
);
|
|
709
749
|
}
|
|
710
750
|
if (response.status === 410) {
|
|
711
|
-
const
|
|
751
|
+
const said = await serverSentence(response);
|
|
712
752
|
throw new MeetError(
|
|
713
753
|
"cancelled",
|
|
714
|
-
|
|
715
|
-
"Nobody can join a cancelled meeting. Show the cancelled screen with this sentence; ask the host to schedule a new one."
|
|
754
|
+
said?.message ?? "This meeting was cancelled.",
|
|
755
|
+
"Nobody can join a cancelled meeting. Show the cancelled screen with this sentence; ask the host to schedule a new one.",
|
|
756
|
+
void 0,
|
|
757
|
+
said?.reason ?? "cancelled"
|
|
716
758
|
);
|
|
717
759
|
}
|
|
718
760
|
if (response.status === 423) {
|
|
@@ -720,7 +762,9 @@ function createTokenClient(options) {
|
|
|
720
762
|
throw new MeetError(
|
|
721
763
|
"room-locked",
|
|
722
764
|
said?.message ?? "The meeting is locked.",
|
|
723
|
-
said?.remedy ?? "The host locked the room. Ask them to unlock it, then join again."
|
|
765
|
+
said?.remedy ?? "The host locked the room. Ask them to unlock it, then join again.",
|
|
766
|
+
void 0,
|
|
767
|
+
said?.reason ?? "locked"
|
|
724
768
|
);
|
|
725
769
|
}
|
|
726
770
|
if (response.status === 503) {
|
|
@@ -789,6 +833,10 @@ function placeholder(roomName) {
|
|
|
789
833
|
canRecord: false,
|
|
790
834
|
isHost: false,
|
|
791
835
|
role: "participant",
|
|
836
|
+
standing: null,
|
|
837
|
+
meetingPass: null,
|
|
838
|
+
meetingPassExpiresAt: null,
|
|
839
|
+
sessionId: null,
|
|
792
840
|
lobby: false,
|
|
793
841
|
breakoutRoomId: null
|
|
794
842
|
};
|
|
@@ -801,7 +849,8 @@ async function serverSentence(response) {
|
|
|
801
849
|
const message = typeof source.user_message === "string" && source.user_message.trim() !== "" ? source.user_message : typeof source.message === "string" && source.message.trim() !== "" ? source.message : null;
|
|
802
850
|
if (message === null) return null;
|
|
803
851
|
const remedy = typeof source.remedy === "string" && source.remedy.trim() !== "" ? source.remedy : void 0;
|
|
804
|
-
|
|
852
|
+
const reason = typeof source.reason === "string" && source.reason !== "" ? source.reason : null;
|
|
853
|
+
return { message, remedy, reason };
|
|
805
854
|
} catch {
|
|
806
855
|
return null;
|
|
807
856
|
}
|
|
@@ -990,7 +1039,7 @@ function createMeetAi(options) {
|
|
|
990
1039
|
operation: "meet.ai.ask",
|
|
991
1040
|
// A GUEST MAY ASK. The server decides whether it can answer.
|
|
992
1041
|
requireAuth: false,
|
|
993
|
-
...roomToken !== null ? { headers: { [
|
|
1042
|
+
...roomToken !== null ? { headers: { [MEETING_PASS_HEADER]: roomToken } } : {},
|
|
994
1043
|
...signal !== void 0 ? { signal } : {}
|
|
995
1044
|
});
|
|
996
1045
|
if (!response.ok) {
|
|
@@ -1225,11 +1274,15 @@ function isGuest(identity) {
|
|
|
1225
1274
|
return identity.userId === null;
|
|
1226
1275
|
}
|
|
1227
1276
|
var ROLE_RANK = {
|
|
1228
|
-
host:
|
|
1229
|
-
cohost:
|
|
1277
|
+
host: 4,
|
|
1278
|
+
cohost: 3,
|
|
1279
|
+
presenter: 2,
|
|
1230
1280
|
participant: 1,
|
|
1231
|
-
|
|
1281
|
+
viewer: 0
|
|
1232
1282
|
};
|
|
1283
|
+
function isLinkFollower(standing) {
|
|
1284
|
+
return standing === "guest" || standing === "outsider";
|
|
1285
|
+
}
|
|
1233
1286
|
function isHostRole(role) {
|
|
1234
1287
|
return role === "host" || role === "cohost";
|
|
1235
1288
|
}
|
|
@@ -2136,15 +2189,15 @@ var CAPTION_LANGUAGES = [
|
|
|
2136
2189
|
{ tag: "id", name: "Indonesian" },
|
|
2137
2190
|
{ tag: "sv", name: "Swedish" }
|
|
2138
2191
|
];
|
|
2139
|
-
async function loadMeetingActivities(api, meetingId,
|
|
2192
|
+
async function loadMeetingActivities(api, meetingId, meetingPass = null) {
|
|
2140
2193
|
let response;
|
|
2141
2194
|
try {
|
|
2142
2195
|
response = await api.request({
|
|
2143
2196
|
path: `${MEET_ROUTES.collab}?meeting_id=${encodeURIComponent(meetingId)}`,
|
|
2144
2197
|
method: "GET",
|
|
2145
2198
|
operation: "meet.loadMeetingActivities",
|
|
2146
|
-
requireAuth:
|
|
2147
|
-
...
|
|
2199
|
+
requireAuth: meetingPass === null,
|
|
2200
|
+
...meetingPass !== null ? { headers: { [MEETING_PASS_HEADER]: meetingPass } } : {}
|
|
2148
2201
|
});
|
|
2149
2202
|
} catch (error) {
|
|
2150
2203
|
return {
|
|
@@ -2241,6 +2294,7 @@ var DEFAULT_EFFECTS = {
|
|
|
2241
2294
|
};
|
|
2242
2295
|
var NO_GRANTS = {
|
|
2243
2296
|
role: "participant",
|
|
2297
|
+
standing: null,
|
|
2244
2298
|
canRecord: false,
|
|
2245
2299
|
canPublish: false,
|
|
2246
2300
|
canSubscribe: false
|
|
@@ -2287,6 +2341,11 @@ function effectiveRole(snapshot) {
|
|
|
2287
2341
|
const fromToken = snapshot.grants.role;
|
|
2288
2342
|
return ROLE_RANK[fromRoster] >= ROLE_RANK[fromToken] ? fromRoster : fromToken;
|
|
2289
2343
|
}
|
|
2344
|
+
function effectiveStanding(snapshot) {
|
|
2345
|
+
if (snapshot.grants.standing != null) return snapshot.grants.standing;
|
|
2346
|
+
const me = snapshot.participants.find((p) => p.identity === snapshot.localIdentity);
|
|
2347
|
+
return me?.standing ?? null;
|
|
2348
|
+
}
|
|
2290
2349
|
var REACTION_TTL_MS = 5e3;
|
|
2291
2350
|
var CHAT_LIMIT = 200;
|
|
2292
2351
|
function createMeetStore(initial = {}) {
|
|
@@ -2880,7 +2939,6 @@ var RPCS = {
|
|
|
2880
2939
|
meetingBySlug: "meet_meeting_by_slug",
|
|
2881
2940
|
admit: "meet_admit_participant",
|
|
2882
2941
|
setLock: "meet_set_lock",
|
|
2883
|
-
endMeeting: "meet_end_meeting",
|
|
2884
2942
|
recordConsent: "meet_record_consent",
|
|
2885
2943
|
/*
|
|
2886
2944
|
* ── MEET WAVE 1 — management (0.8). Every write is a SECURITY DEFINER door
|
|
@@ -3294,7 +3352,7 @@ function createMeetRepository(options) {
|
|
|
3294
3352
|
const operation = "meet.projectAttendee";
|
|
3295
3353
|
const role = text(row, "role");
|
|
3296
3354
|
const admission = text(row, "admission_state");
|
|
3297
|
-
const known = ["host", "cohost", "participant", "
|
|
3355
|
+
const known = ["host", "cohost", "presenter", "participant", "viewer"];
|
|
3298
3356
|
const states = ["knocking", "admitted", "denied", "removed"];
|
|
3299
3357
|
const userId = text(row, "participant_user_id");
|
|
3300
3358
|
const identity = requireText(row, "identity", operation);
|
|
@@ -3609,16 +3667,6 @@ function createMeetRepository(options) {
|
|
|
3609
3667
|
);
|
|
3610
3668
|
return projectMeeting(row);
|
|
3611
3669
|
},
|
|
3612
|
-
async endMeeting(meetingId, byUserId) {
|
|
3613
|
-
const row = await guard(
|
|
3614
|
-
"meet.endMeeting",
|
|
3615
|
-
() => db.rpc(RPCS.endMeeting, {
|
|
3616
|
-
p_meeting_id: meetingId,
|
|
3617
|
-
p_by_user_id: byUserId
|
|
3618
|
-
})
|
|
3619
|
-
);
|
|
3620
|
-
return projectMeeting(row);
|
|
3621
|
-
},
|
|
3622
3670
|
async transcript(meetingId, limit = 1e3) {
|
|
3623
3671
|
const response = await db.from(TABLES.transcripts).select(SEGMENT_COLUMNS).eq("meeting_id", meetingId).order("started_at", { ascending: true }).order("id", { ascending: true }).limit(limit);
|
|
3624
3672
|
if (response.error !== null) throw normalizeMeetError(response.error, "meet.transcript");
|
|
@@ -4062,7 +4110,7 @@ function applyModeration(store, payload, now) {
|
|
|
4062
4110
|
return ignored(`a moderation kind this version does not know: ${String(kind)}`);
|
|
4063
4111
|
}
|
|
4064
4112
|
}
|
|
4065
|
-
var ROLES = ["host", "cohost", "participant", "
|
|
4113
|
+
var ROLES = ["host", "cohost", "presenter", "participant", "viewer"];
|
|
4066
4114
|
|
|
4067
4115
|
// src/core/note-taker.ts
|
|
4068
4116
|
var NOTE_TAKER_IDENTITY_PREFIX = "agent:note_taker:";
|
|
@@ -4147,7 +4195,12 @@ var TRANSCRIPTION_ATTRIBUTES = {
|
|
|
4147
4195
|
// src/core/room.ts
|
|
4148
4196
|
var PARTICIPANT_ROLE_ATTRIBUTE = "matrx.participant.role";
|
|
4149
4197
|
var PARTICIPANT_CAN_RECORD_ATTRIBUTE = "matrx.participant.can_record";
|
|
4150
|
-
var
|
|
4198
|
+
var PARTICIPANT_STANDING_ATTRIBUTE = "matrx.participant.standing";
|
|
4199
|
+
var KNOWN_STANDINGS = ["member", "invited", "outsider", "guest"];
|
|
4200
|
+
function parseStanding(value) {
|
|
4201
|
+
return KNOWN_STANDINGS.includes(value) ? value : null;
|
|
4202
|
+
}
|
|
4203
|
+
var KNOWN_ROLES = ["host", "cohost", "presenter", "participant", "viewer"];
|
|
4151
4204
|
function parseRole(value) {
|
|
4152
4205
|
return KNOWN_ROLES.includes(value) ? value : "participant";
|
|
4153
4206
|
}
|
|
@@ -4181,6 +4234,9 @@ function projectParticipant(driver, joinedAt) {
|
|
|
4181
4234
|
// ATTRIBUTE FIRST, metadata second — see the constants above. Both are the
|
|
4182
4235
|
// server's; the attribute is simply the one that always arrives.
|
|
4183
4236
|
role: parseRole(driver.attributes[PARTICIPANT_ROLE_ATTRIBUTE] ?? metadata.role),
|
|
4237
|
+
standing: parseStanding(
|
|
4238
|
+
driver.attributes[PARTICIPANT_STANDING_ATTRIBUTE] ?? metadata.standing
|
|
4239
|
+
),
|
|
4184
4240
|
canRecord: driver.attributes[PARTICIPANT_CAN_RECORD_ATTRIBUTE] === "true" || metadata.can_record === true,
|
|
4185
4241
|
isLocal: driver.isLocal,
|
|
4186
4242
|
isAgent: metadata.is_agent === true,
|
|
@@ -4253,7 +4309,7 @@ function createRoomEngine(options) {
|
|
|
4253
4309
|
const normalized = normalizeMeetError(error, operation);
|
|
4254
4310
|
store.patch({
|
|
4255
4311
|
phase: "failed",
|
|
4256
|
-
failure: { message: normalized.message, remedy: normalized.remedy }
|
|
4312
|
+
failure: { message: normalized.message, remedy: normalized.remedy, reason: normalized.reason }
|
|
4257
4313
|
});
|
|
4258
4314
|
report(
|
|
4259
4315
|
normalized.code === "session-unavailable" ? "warn" : "error",
|
|
@@ -4457,6 +4513,7 @@ function createRoomEngine(options) {
|
|
|
4457
4513
|
breakoutRoomId: token.breakoutRoomId ?? null,
|
|
4458
4514
|
grants: {
|
|
4459
4515
|
role: token.role,
|
|
4516
|
+
standing: token.standing,
|
|
4460
4517
|
canRecord: token.canRecord,
|
|
4461
4518
|
canPublish: token.canPublish,
|
|
4462
4519
|
canSubscribe: token.canSubscribe
|
|
@@ -4802,7 +4859,7 @@ function createInRoomClient(options) {
|
|
|
4802
4859
|
}
|
|
4803
4860
|
function headers() {
|
|
4804
4861
|
const token = options.resolveRoomToken();
|
|
4805
|
-
return token === null ? void 0 : { [
|
|
4862
|
+
return token === null ? void 0 : { [MEETING_PASS_HEADER]: token };
|
|
4806
4863
|
}
|
|
4807
4864
|
function refusal2(response, operation, remedy) {
|
|
4808
4865
|
return refusalFromResponse(response, operation, remedy);
|
|
@@ -5563,8 +5620,8 @@ function MeetRuntime(props) {
|
|
|
5563
5620
|
const roomName = store.snapshot().meeting?.roomName;
|
|
5564
5621
|
if (roomName === void 0) return null;
|
|
5565
5622
|
const active = engine.token();
|
|
5566
|
-
if (active?.roomName === roomName && active.
|
|
5567
|
-
return tokens.remembered(roomName)?.
|
|
5623
|
+
if (active?.roomName === roomName && active.meetingPass) return active.meetingPass;
|
|
5624
|
+
return tokens.remembered(roomName)?.meetingPass ?? null;
|
|
5568
5625
|
};
|
|
5569
5626
|
const ai = createMeetAi({ api, store, resolveRoomToken });
|
|
5570
5627
|
const inRoom = createInRoomClient({ api, store, resolveRoomToken });
|
|
@@ -5736,6 +5793,10 @@ function useLocalUserId() {
|
|
|
5736
5793
|
var import_react3 = require("react");
|
|
5737
5794
|
|
|
5738
5795
|
// src/core/observation.ts
|
|
5796
|
+
function observedRole(role, standing) {
|
|
5797
|
+
if (role === "host" || role === "cohost") return role;
|
|
5798
|
+
return isLinkFollower(standing) ? "guest" : "participant";
|
|
5799
|
+
}
|
|
5739
5800
|
function observedDevice(track) {
|
|
5740
5801
|
if (track.enabled) return "on";
|
|
5741
5802
|
const refused = track.unavailable;
|
|
@@ -5763,6 +5824,8 @@ function observedPhase(input) {
|
|
|
5763
5824
|
const raw = snapshot.phase;
|
|
5764
5825
|
const live = raw === "connected" || raw === "reconnecting";
|
|
5765
5826
|
if (endedRecord(snapshot, input.meeting ?? null) && !live) return "ended";
|
|
5827
|
+
const reason = raw === "failed" ? snapshot.failure?.reason ?? null : null;
|
|
5828
|
+
if (reason !== null) return reason === "ended" ? "ended" : `refused:${reason}`;
|
|
5766
5829
|
switch (raw) {
|
|
5767
5830
|
case "idle":
|
|
5768
5831
|
case "failed":
|
|
@@ -5783,12 +5846,13 @@ function observe(input) {
|
|
|
5783
5846
|
const { snapshot } = input;
|
|
5784
5847
|
const phase = observedPhase(input);
|
|
5785
5848
|
const inCall = phase === "in_call";
|
|
5786
|
-
const
|
|
5787
|
-
const canAdmit =
|
|
5849
|
+
const actual = inCall && snapshot !== null ? effectiveRole(snapshot) : "none";
|
|
5850
|
+
const canAdmit = actual !== "none" && ADMITTER_ROLES.has(actual);
|
|
5851
|
+
const role = actual === "none" || snapshot === null ? "none" : observedRole(actual, effectiveStanding(snapshot));
|
|
5788
5852
|
const deviceInPlay = phase === "joining" || inCall;
|
|
5789
5853
|
return {
|
|
5790
5854
|
phase,
|
|
5791
|
-
reason: null,
|
|
5855
|
+
reason: phase.startsWith("refused:") ? phase.slice("refused:".length) : null,
|
|
5792
5856
|
role,
|
|
5793
5857
|
connection: snapshot?.phase === "reconnecting" ? "reconnecting" : "stable",
|
|
5794
5858
|
hostPresent: inCall && snapshot !== null ? snapshot.participants.some((p) => ADMITTER_ROLES.has(p.role)) : null,
|
|
@@ -5854,7 +5918,7 @@ function participantAttributes(p) {
|
|
|
5854
5918
|
"data-meet-participant": "",
|
|
5855
5919
|
"data-meet-participant-identity": p.identity,
|
|
5856
5920
|
"data-meet-participant-name": p.displayName,
|
|
5857
|
-
"data-meet-participant-role": p.role,
|
|
5921
|
+
"data-meet-participant-role": observedRole(p.role, p.standing),
|
|
5858
5922
|
"data-meet-participant-self": String(p.isLocal)
|
|
5859
5923
|
};
|
|
5860
5924
|
const quality = observedQuality(p.quality);
|
|
@@ -6183,7 +6247,7 @@ function summarizeMeetingRecordRestrictions(restrictions) {
|
|
|
6183
6247
|
async function loadGuestMeetingRecord(args) {
|
|
6184
6248
|
const { api, repository, meetingId, meeting, roomToken } = args;
|
|
6185
6249
|
const session = args.session === true;
|
|
6186
|
-
if (roomToken
|
|
6250
|
+
if (roomToken?.meetingPass == null && !session) {
|
|
6187
6251
|
return refusedBundle(
|
|
6188
6252
|
meeting,
|
|
6189
6253
|
"This meeting's record is only readable by the people who were in it.",
|
|
@@ -6193,12 +6257,12 @@ async function loadGuestMeetingRecord(args) {
|
|
|
6193
6257
|
let response;
|
|
6194
6258
|
try {
|
|
6195
6259
|
response = await api.request({
|
|
6196
|
-
path: `${MEET_ROUTES.record}?meeting_id=${encodeURIComponent(meetingId)}
|
|
6260
|
+
path: `${MEET_ROUTES.record}?meeting_id=${encodeURIComponent(meetingId)}` + (args.sessionId ? `&session_id=${encodeURIComponent(args.sessionId)}` : ""),
|
|
6197
6261
|
method: "GET",
|
|
6198
6262
|
// A GUEST HAS NO SESSION AND IS STILL A FIRST-CLASS READER (D6).
|
|
6199
6263
|
requireAuth: session,
|
|
6200
6264
|
operation: "meet.record",
|
|
6201
|
-
headers: roomToken
|
|
6265
|
+
headers: roomToken?.meetingPass != null ? { [MEETING_PASS_HEADER]: roomToken.meetingPass } : {}
|
|
6202
6266
|
});
|
|
6203
6267
|
} catch (error) {
|
|
6204
6268
|
return refusedBundle(
|
|
@@ -7405,7 +7469,6 @@ function kindOf(person) {
|
|
|
7405
7469
|
if (person.isAgent) return "assistant";
|
|
7406
7470
|
if (person.role === "host") return "host";
|
|
7407
7471
|
if (person.role === "cohost") return "cohost";
|
|
7408
|
-
if (person.role === "guest") return person.userId !== null ? "signed-in guest" : "guest";
|
|
7409
7472
|
if (person.userId === null) return "guest";
|
|
7410
7473
|
return "member";
|
|
7411
7474
|
}
|
|
@@ -7690,7 +7753,7 @@ function meetingLength(meeting) {
|
|
|
7690
7753
|
if (start === null || end === null || end < start) return null;
|
|
7691
7754
|
return (0, import_format2.formatDurationMs)(end - start, { style: "long" });
|
|
7692
7755
|
}
|
|
7693
|
-
async function loadMeetingChat(api, meetingId,
|
|
7756
|
+
async function loadMeetingChat(api, meetingId, meetingPass = null) {
|
|
7694
7757
|
const operation = "meet.loadMeetingChat";
|
|
7695
7758
|
let response;
|
|
7696
7759
|
try {
|
|
@@ -7698,8 +7761,8 @@ async function loadMeetingChat(api, meetingId, roomToken = null) {
|
|
|
7698
7761
|
path: `${MEET_ROUTES.chat}?meeting_id=${encodeURIComponent(meetingId)}`,
|
|
7699
7762
|
method: "GET",
|
|
7700
7763
|
operation,
|
|
7701
|
-
requireAuth:
|
|
7702
|
-
...
|
|
7764
|
+
requireAuth: meetingPass === null,
|
|
7765
|
+
...meetingPass !== null ? { headers: { [MEETING_PASS_HEADER]: meetingPass } } : {}
|
|
7703
7766
|
});
|
|
7704
7767
|
} catch (error) {
|
|
7705
7768
|
return {
|
|
@@ -9172,10 +9235,13 @@ function RecordingIndicator() {
|
|
|
9172
9235
|
}
|
|
9173
9236
|
);
|
|
9174
9237
|
}
|
|
9175
|
-
function RoleBadge({
|
|
9238
|
+
function RoleBadge({
|
|
9239
|
+
role,
|
|
9240
|
+
standing
|
|
9241
|
+
}) {
|
|
9176
9242
|
if (role === "host") return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mx-meet__badge", children: "Host" });
|
|
9177
9243
|
if (role === "cohost") return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mx-meet__badge", children: "Co-host" });
|
|
9178
|
-
if (
|
|
9244
|
+
if (isLinkFollower(standing)) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mx-meet__badge", children: "Guest" });
|
|
9179
9245
|
return null;
|
|
9180
9246
|
}
|
|
9181
9247
|
function ParticipantTile({
|
|
@@ -9225,7 +9291,7 @@ function ParticipantTile({
|
|
|
9225
9291
|
participant.displayName,
|
|
9226
9292
|
participant.isLocal ? " (you)" : "",
|
|
9227
9293
|
participant.isAgent ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mx-meet__badge", children: "AI" }) : null,
|
|
9228
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RoleBadge, { role: participant.role })
|
|
9294
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RoleBadge, { role: participant.role, standing: participant.standing })
|
|
9229
9295
|
] }),
|
|
9230
9296
|
!participant.micEnabled ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MicOffIcon, { width: 14, height: 14 }) : null,
|
|
9231
9297
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(QualityBars, { quality: participant.quality })
|
|
@@ -9964,7 +10030,13 @@ function PeoplePanel({
|
|
|
9964
10030
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "mx-meet__person-name", children: [
|
|
9965
10031
|
participant.displayName,
|
|
9966
10032
|
participant.identity === local ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mx-meet__you", children: " (you)" }) : null,
|
|
9967
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
10033
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
10034
|
+
RoleBadge,
|
|
10035
|
+
{
|
|
10036
|
+
role: participant.identity === local ? myRole : participant.role,
|
|
10037
|
+
standing: participant.standing
|
|
10038
|
+
}
|
|
10039
|
+
),
|
|
9968
10040
|
isNoteTaker(participant) ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mx-meet__badge", children: "Meeting assistant" }) : null,
|
|
9969
10041
|
snapshot?.spotlight === participant.identity ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mx-meet__badge", children: "Spotlight" }) : null
|
|
9970
10042
|
] }),
|
|
@@ -11126,7 +11198,7 @@ function MeetingRecordBody({
|
|
|
11126
11198
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "mx-meet__person-name", children: [
|
|
11127
11199
|
displayNameFor(bundle.names, person.identity, person.displayName),
|
|
11128
11200
|
person.role === "host" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "mx-meet__badge", children: "Host" }) : null,
|
|
11129
|
-
person.
|
|
11201
|
+
person.userId === null && !person.isAgent ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "mx-meet__badge", children: "Guest" }) : null,
|
|
11130
11202
|
person.isAgent ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "mx-meet__badge", children: "Meeting assistant" }) : null
|
|
11131
11203
|
] })
|
|
11132
11204
|
] }, person.id)) })
|