@ai-matrx/meet 0.11.44 → 0.11.46
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 +12 -0
- package/dist/{collab-BNJNgXFB.d.cts → collab-D1TX5uf9.d.cts} +7 -0
- package/dist/{collab-BNJNgXFB.d.ts → collab-D1TX5uf9.d.ts} +7 -0
- package/dist/{components-BDtGzHf4.d.ts → components-CNwBgmYU.d.ts} +1 -1
- package/dist/{components-BxK993iW.d.cts → components-CkyDos0f.d.cts} +1 -1
- package/dist/core.cjs +70 -10
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +33 -9
- package/dist/core.d.ts +33 -9
- package/dist/core.js +70 -10
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +70 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +70 -10
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +197 -30
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +3 -3
- package/dist/react.d.ts +3 -3
- package/dist/react.js +197 -30
- package/dist/react.js.map +1 -1
- package/dist/skins/meet.cjs +131 -28
- 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 +131 -28
- package/dist/skins/meet.js.map +1 -1
- package/dist/styles.css +16 -0
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog — `@ai-matrx/meet`
|
|
2
2
|
|
|
3
|
+
## 0.11.46
|
|
4
|
+
|
|
5
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
6
|
+
`git diff npm/meet/v0.11.45..npm/meet/v0.11.46 -- apps/shared/meet`).
|
|
7
|
+
No source changes intended and no consumer action required.
|
|
8
|
+
|
|
9
|
+
## 0.11.45
|
|
10
|
+
|
|
11
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
12
|
+
`git diff npm/meet/v0.11.44..npm/meet/v0.11.45 -- apps/shared/meet`).
|
|
13
|
+
No source changes intended and no consumer action required.
|
|
14
|
+
|
|
3
15
|
## 0.11.44
|
|
4
16
|
|
|
5
17
|
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
@@ -107,6 +107,11 @@ interface LobbyEntry {
|
|
|
107
107
|
readonly knockExpiresAt?: string | null | undefined;
|
|
108
108
|
readonly decidedAt: string | null;
|
|
109
109
|
readonly decidedBy: UserId | null;
|
|
110
|
+
/**
|
|
111
|
+
* The server's flag on this knock (`mod-removed-bypass`): `previously_removed` when its coarse
|
|
112
|
+
* signals match someone a host removed from this meeting. Advice for the host, never a block.
|
|
113
|
+
*/
|
|
114
|
+
readonly flag?: string | null | undefined;
|
|
110
115
|
}
|
|
111
116
|
type ConnectionQuality = "excellent" | "good" | "poor" | "lost" | "unknown";
|
|
112
117
|
/** One person in the room, as the UI needs them. Media state is a FACT here. */
|
|
@@ -403,6 +408,8 @@ interface MeetingAttendee {
|
|
|
403
408
|
/** When this person knocked, and when an unanswered knock lapses (null = never). */
|
|
404
409
|
readonly knockedAt?: string | null | undefined;
|
|
405
410
|
readonly knockExpiresAt?: string | null | undefined;
|
|
411
|
+
/** The server's flag on a knock (`metadata.knock_flag`), e.g. `previously_removed`. */
|
|
412
|
+
readonly knockFlag?: string | null | undefined;
|
|
406
413
|
readonly isAgent: boolean;
|
|
407
414
|
/** FIRST arrival in the room — a rejoin never moves it. */
|
|
408
415
|
readonly joinedAt: string | null;
|
|
@@ -107,6 +107,11 @@ interface LobbyEntry {
|
|
|
107
107
|
readonly knockExpiresAt?: string | null | undefined;
|
|
108
108
|
readonly decidedAt: string | null;
|
|
109
109
|
readonly decidedBy: UserId | null;
|
|
110
|
+
/**
|
|
111
|
+
* The server's flag on this knock (`mod-removed-bypass`): `previously_removed` when its coarse
|
|
112
|
+
* signals match someone a host removed from this meeting. Advice for the host, never a block.
|
|
113
|
+
*/
|
|
114
|
+
readonly flag?: string | null | undefined;
|
|
110
115
|
}
|
|
111
116
|
type ConnectionQuality = "excellent" | "good" | "poor" | "lost" | "unknown";
|
|
112
117
|
/** One person in the room, as the UI needs them. Media state is a FACT here. */
|
|
@@ -403,6 +408,8 @@ interface MeetingAttendee {
|
|
|
403
408
|
/** When this person knocked, and when an unanswered knock lapses (null = never). */
|
|
404
409
|
readonly knockedAt?: string | null | undefined;
|
|
405
410
|
readonly knockExpiresAt?: string | null | undefined;
|
|
411
|
+
/** The server's flag on a knock (`metadata.knock_flag`), e.g. `previously_removed`. */
|
|
412
|
+
readonly knockFlag?: string | null | undefined;
|
|
406
413
|
readonly isAgent: boolean;
|
|
407
414
|
/** FIRST arrival in the room — a rejoin never moves it. */
|
|
408
415
|
readonly joinedAt: string | null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
import { M as MeetingRecord, P as ParticipantIdentity, R as RoomName, a as MeetParticipant } from './collab-
|
|
2
|
+
import { M as MeetingRecord, P as ParticipantIdentity, R as RoomName, a as MeetParticipant } from './collab-D1TX5uf9.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* THE PRODUCT UI (R6/R7). Not a headless kernel with a note telling the host to
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
import { M as MeetingRecord, P as ParticipantIdentity, R as RoomName, a as MeetParticipant } from './collab-
|
|
2
|
+
import { M as MeetingRecord, P as ParticipantIdentity, R as RoomName, a as MeetParticipant } from './collab-D1TX5uf9.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* THE PRODUCT UI (R6/R7). Not a headless kernel with a note telling the host to
|
package/dist/core.cjs
CHANGED
|
@@ -607,7 +607,8 @@ function createWebResumeStorage() {
|
|
|
607
607
|
}
|
|
608
608
|
};
|
|
609
609
|
}
|
|
610
|
-
var CLEARS_RESUME = (phase) => phase === "left" || phase === "removed" || phase === "superseded" || phase === "inactive" || phase === "ended" || phase === "record" || phase === "prejoin" || phase
|
|
610
|
+
var CLEARS_RESUME = (phase) => phase === "left" || phase === "removed" || phase === "superseded" || phase === "inactive" || phase === "ended" || phase === "record" || phase === "prejoin" || phase === "denied" || phase === "knock_expired" || phase.startsWith("refused:");
|
|
611
|
+
var WAITING_RESUMES = (phase) => phase.startsWith("waiting:");
|
|
611
612
|
function autoRejoinDelayMs(attempt, random = Math.random) {
|
|
612
613
|
const base = Math.min(15e3, 1e3 * 2 ** Math.max(0, attempt));
|
|
613
614
|
return Math.round(base * (0.5 + random()));
|
|
@@ -739,6 +740,10 @@ function createConnectionSupervisor(options) {
|
|
|
739
740
|
rejoinAttempts = 0;
|
|
740
741
|
stopRejoin();
|
|
741
742
|
saveMarker(true);
|
|
743
|
+
} else if (WAITING_RESUMES(phase)) {
|
|
744
|
+
stopRejoin();
|
|
745
|
+
driverRegion = null;
|
|
746
|
+
saveMarker(true);
|
|
742
747
|
} else if (phase === "disconnected") {
|
|
743
748
|
driverRegion = null;
|
|
744
749
|
saveMarker(true);
|
|
@@ -914,10 +919,10 @@ var MEET_ROUTES = {
|
|
|
914
919
|
recordingStop: "/api/v1/meet/recording/stop",
|
|
915
920
|
noteTakerStart: "/api/v1/meet/agent/start",
|
|
916
921
|
noteTakerStop: "/api/v1/meet/agent/stop",
|
|
917
|
-
/** In-meeting Q&A. Streams NDJSON; body is `{meeting_id, question}` only. */
|
|
918
|
-
intelligenceAsk: "/api/v1/meet/intelligence/ask",
|
|
919
922
|
/** Anyone in the meeting (guests with the room pass included) asks for captions for themselves. */
|
|
920
923
|
noteTakerCaptions: "/api/v1/meet/agent/captions",
|
|
924
|
+
/** In-meeting Q&A. Streams NDJSON; body is `{meeting_id, question}` only. */
|
|
925
|
+
intelligenceAsk: "/api/v1/meet/intelligence/ask",
|
|
921
926
|
/** A host ends the meeting for everyone. Served by MRI-A6. */
|
|
922
927
|
meetingEnd: "/api/v1/meet/end",
|
|
923
928
|
/**
|
|
@@ -1042,6 +1047,7 @@ function parseRoomToken(body, roomName) {
|
|
|
1042
1047
|
connectionIdentity: readString(payload, "connection_identity") ?? personKey,
|
|
1043
1048
|
connectionKind: readString(payload, "connection_kind") === "companion" ? "companion" : "main",
|
|
1044
1049
|
secondDeviceChoice,
|
|
1050
|
+
secondDeviceRule: readString(payload, "second_device_rule"),
|
|
1045
1051
|
displayName: readString(payload, "display_name") ?? readString(payload, "displayName") ?? identity,
|
|
1046
1052
|
expiresAt,
|
|
1047
1053
|
canPublish: readBoolean(payload, "can_publish", true),
|
|
@@ -1586,6 +1592,7 @@ var STATES = [
|
|
|
1586
1592
|
"ended"
|
|
1587
1593
|
];
|
|
1588
1594
|
function readState(value) {
|
|
1595
|
+
if (value === "dispatching") return "joining";
|
|
1589
1596
|
return typeof value === "string" && STATES.includes(value) ? value : null;
|
|
1590
1597
|
}
|
|
1591
1598
|
function isNoteTaker(participant) {
|
|
@@ -1780,6 +1787,12 @@ var JOINABLE_FROM = /* @__PURE__ */ new Set([
|
|
|
1780
1787
|
// allows the press; the server's gate decides whether it knocks or is refused again.
|
|
1781
1788
|
"refused:lobby_rejects"
|
|
1782
1789
|
]);
|
|
1790
|
+
var RETRYABLE_REFUSALS = /* @__PURE__ */ new Set([
|
|
1791
|
+
"refused:locked",
|
|
1792
|
+
"refused:too_early",
|
|
1793
|
+
"refused:meeting_full",
|
|
1794
|
+
"refused:platform_capacity"
|
|
1795
|
+
]);
|
|
1783
1796
|
var NOT_ENDABLE = /* @__PURE__ */ new Set([
|
|
1784
1797
|
"ended",
|
|
1785
1798
|
"record",
|
|
@@ -1845,7 +1858,7 @@ function nextPhase(from, event) {
|
|
|
1845
1858
|
case "link_state":
|
|
1846
1859
|
return from === "resolving" && event.reason !== null && isJoinRefusalReason(event.reason) ? refusalPhase(event.reason) : null;
|
|
1847
1860
|
case "join":
|
|
1848
|
-
return JOINABLE_FROM.has(from) ? "joining" : null;
|
|
1861
|
+
return JOINABLE_FROM.has(from) || RETRYABLE_REFUSALS.has(from) ? "joining" : null;
|
|
1849
1862
|
case "auto_rejoin":
|
|
1850
1863
|
return from === "disconnected" ? "joining" : null;
|
|
1851
1864
|
case "resumed":
|
|
@@ -2270,6 +2283,10 @@ var RPCS = {
|
|
|
2270
2283
|
admitAll: "meet_admit_all",
|
|
2271
2284
|
setLock: "meet_set_lock",
|
|
2272
2285
|
recordConsent: "meet_record_consent",
|
|
2286
|
+
/** One meeting rule as the gate obeys it (the knob ladder, this meeting's rung included). */
|
|
2287
|
+
meetingRule: "meet_policy",
|
|
2288
|
+
/** A host sets one rule for THIS meeting (the `meet_meeting` rung); refusals come back as `{ok:false}`. */
|
|
2289
|
+
setMeetingRule: "meet_policy_set",
|
|
2273
2290
|
/*
|
|
2274
2291
|
* ── MEET WAVE 1 — management (0.8). Every write is a SECURITY DEFINER door
|
|
2275
2292
|
* authorized by the meeting's host or a real iam grant (editor to change,
|
|
@@ -2316,7 +2333,7 @@ var INVITEE_COLUMNS = "id,meeting_id,invitee_user_id,email,display_name,role,rsv
|
|
|
2316
2333
|
var RECORDING_COLUMNS = "id,meeting_id,state,started_at,ended_at,started_by,file_id,failure_reason";
|
|
2317
2334
|
var SEGMENT_COLUMNS = "id,meeting_id,identity,speaker,text,started_at,is_final,metadata";
|
|
2318
2335
|
var NOTE_COLUMNS = "id,meeting_id,text,kind,assignee_user_id,created_at,metadata";
|
|
2319
|
-
var ATTENDEE_COLUMNS = "id,meeting_id,identity,participant_user_id,display_name,avatar_url,role,admission_state,knocked_at,knock_expires_at,is_agent,joined_at,left_at,sessions:metadata->sessions";
|
|
2336
|
+
var ATTENDEE_COLUMNS = "id,meeting_id,identity,participant_user_id,display_name,avatar_url,role,admission_state,knocked_at,knock_expires_at,is_agent,joined_at,left_at,sessions:metadata->sessions,knock_flag:metadata->>knock_flag";
|
|
2320
2337
|
function projectStays(value) {
|
|
2321
2338
|
if (!Array.isArray(value)) return [];
|
|
2322
2339
|
const stays = [];
|
|
@@ -2716,6 +2733,8 @@ function createMeetRepository(options) {
|
|
|
2716
2733
|
admissionState: states.includes(admission) ? admission : "admitted",
|
|
2717
2734
|
knockedAt: text(row, "knocked_at"),
|
|
2718
2735
|
knockExpiresAt: text(row, "knock_expires_at"),
|
|
2736
|
+
// The list read selects `metadata->>knock_flag`; a Postgres Changes row carries `metadata`.
|
|
2737
|
+
knockFlag: text(row, "knock_flag") ?? (typeof row["metadata"] === "object" && row["metadata"] !== null ? text(row["metadata"], "knock_flag") : null),
|
|
2719
2738
|
isAgent: bool(row, "is_agent", false),
|
|
2720
2739
|
joinedAt: text(row, "joined_at"),
|
|
2721
2740
|
leftAt: text(row, "left_at"),
|
|
@@ -3039,6 +3058,25 @@ function createMeetRepository(options) {
|
|
|
3039
3058
|
);
|
|
3040
3059
|
return projectMeeting(row);
|
|
3041
3060
|
},
|
|
3061
|
+
async meetingRule(meetingId, key) {
|
|
3062
|
+
const response = await db.rpc(RPCS.meetingRule, { p_meeting_id: meetingId, p_key: key });
|
|
3063
|
+
if (response.error !== null) throw normalizeMeetError(response.error, "meet.meetingRule");
|
|
3064
|
+
return response.data;
|
|
3065
|
+
},
|
|
3066
|
+
async setMeetingRule(meetingId, key, value) {
|
|
3067
|
+
const response = await db.rpc(RPCS.setMeetingRule, { p_meeting_id: meetingId, p_key: key, p_value: value });
|
|
3068
|
+
if (response.error !== null) throw normalizeMeetError(response.error, "meet.setMeetingRule");
|
|
3069
|
+
const answer = response.data ?? {};
|
|
3070
|
+
if (answer["ok"] !== true) {
|
|
3071
|
+
throw new MeetError(
|
|
3072
|
+
"forbidden",
|
|
3073
|
+
typeof answer["detail"] === "string" ? answer["detail"] : "This meeting's rule was not changed.",
|
|
3074
|
+
"Only the meeting's host or a co-host sets its rules; an organization can lock a rule for everyone.",
|
|
3075
|
+
answer
|
|
3076
|
+
);
|
|
3077
|
+
}
|
|
3078
|
+
return answer["effective_value"];
|
|
3079
|
+
},
|
|
3042
3080
|
async transcript(meetingId, limit = 1e3) {
|
|
3043
3081
|
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);
|
|
3044
3082
|
if (response.error !== null) throw normalizeMeetError(response.error, "meet.transcript");
|
|
@@ -5204,7 +5242,8 @@ function lobbyEntryFrom(attendee, now = Date.now()) {
|
|
|
5204
5242
|
knockedAt: attendee.knockedAt ?? attendee.joinedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
5205
5243
|
knockExpiresAt: attendee.knockExpiresAt ?? null,
|
|
5206
5244
|
decidedAt: null,
|
|
5207
|
-
decidedBy: null
|
|
5245
|
+
decidedBy: null,
|
|
5246
|
+
flag: attendee.knockFlag ?? null
|
|
5208
5247
|
};
|
|
5209
5248
|
}
|
|
5210
5249
|
function deniedEntryFrom(attendee) {
|
|
@@ -5376,11 +5415,15 @@ function createMeetingSession(options) {
|
|
|
5376
5415
|
}
|
|
5377
5416
|
let policyTimer = null;
|
|
5378
5417
|
let policyReading = false;
|
|
5418
|
+
let policyInFlight = null;
|
|
5379
5419
|
async function readLivePolicy() {
|
|
5380
5420
|
const meeting = store.snapshot().meeting;
|
|
5381
5421
|
const pass = options.resolvePass?.() ?? null;
|
|
5382
|
-
if (meeting === null || pass === null
|
|
5422
|
+
if (meeting === null || pass === null) return;
|
|
5423
|
+
if (policyReading) return policyInFlight ?? void 0;
|
|
5383
5424
|
policyReading = true;
|
|
5425
|
+
let done = () => void 0;
|
|
5426
|
+
policyInFlight = new Promise((resolve) => done = resolve);
|
|
5384
5427
|
try {
|
|
5385
5428
|
const response = await options.api.request({
|
|
5386
5429
|
path: `${MEET_ROUTES.state}?meeting_id=${encodeURIComponent(meeting.id)}`,
|
|
@@ -5401,6 +5444,8 @@ function createMeetingSession(options) {
|
|
|
5401
5444
|
} catch {
|
|
5402
5445
|
} finally {
|
|
5403
5446
|
policyReading = false;
|
|
5447
|
+
policyInFlight = null;
|
|
5448
|
+
done();
|
|
5404
5449
|
}
|
|
5405
5450
|
}
|
|
5406
5451
|
function syncLivePolicyTimer() {
|
|
@@ -5699,6 +5744,7 @@ function createMeetingSession(options) {
|
|
|
5699
5744
|
},
|
|
5700
5745
|
stopWaiting,
|
|
5701
5746
|
readState: readState2,
|
|
5747
|
+
readLivePolicy,
|
|
5702
5748
|
async readExit(connection, held) {
|
|
5703
5749
|
const meeting = store.snapshot().meeting;
|
|
5704
5750
|
const pass = held ?? options.resolvePass?.() ?? null;
|
|
@@ -5736,6 +5782,17 @@ function createMeetingSession(options) {
|
|
|
5736
5782
|
async askAgain() {
|
|
5737
5783
|
await options.rejoin?.();
|
|
5738
5784
|
},
|
|
5785
|
+
async meetingRule(key) {
|
|
5786
|
+
const meeting = requireMeeting("meet.meetingRule");
|
|
5787
|
+
return repository.meetingRule(meeting.id, key);
|
|
5788
|
+
},
|
|
5789
|
+
async setMeetingRule(key, value) {
|
|
5790
|
+
requireHostUser("meet.setMeetingRule");
|
|
5791
|
+
const meeting = requireMeeting("meet.setMeetingRule");
|
|
5792
|
+
const effective = await repository.setMeetingRule(meeting.id, key, value);
|
|
5793
|
+
hint();
|
|
5794
|
+
return effective;
|
|
5795
|
+
},
|
|
5739
5796
|
async setLock(locked) {
|
|
5740
5797
|
const by = requireHostUser("meet.setLock");
|
|
5741
5798
|
const meeting = requireMeeting("meet.setLock");
|
|
@@ -7127,7 +7184,7 @@ function createRoomEngine(options) {
|
|
|
7127
7184
|
const { secondDevice: _answered, ...rest } = lastRequest;
|
|
7128
7185
|
lastRequest = rest;
|
|
7129
7186
|
}
|
|
7130
|
-
options.tabClaim?.inRoom(String(request.roomName), String(token.identity));
|
|
7187
|
+
options.tabClaim?.inRoom(String(request.roomName), String(token.identity), token.secondDeviceRule ?? null);
|
|
7131
7188
|
current = token;
|
|
7132
7189
|
lastServerUrl = token.serverUrl;
|
|
7133
7190
|
connectionPolicy = token.connectionPolicy ?? DEFAULT_CONNECTION_POLICY;
|
|
@@ -7439,10 +7496,12 @@ function createRoomEngine(options) {
|
|
|
7439
7496
|
if (claim === void 0 || userId === null) return false;
|
|
7440
7497
|
const before = store.snapshot();
|
|
7441
7498
|
if (before.phase !== "prejoin" || before.secondDevice !== null) return false;
|
|
7442
|
-
|
|
7499
|
+
const person = `user:${String(userId)}`;
|
|
7500
|
+
const found = claim.presenceElsewhere !== void 0 ? await claim.presenceElsewhere(String(roomName), person) : await claim.presentElsewhere(String(roomName), person) ? { rule: null } : null;
|
|
7501
|
+
if (found === null || found.rule === "allow_both") return false;
|
|
7443
7502
|
const now2 = store.snapshot();
|
|
7444
7503
|
if (now2.phase !== "prejoin" || now2.secondDevice !== null) return false;
|
|
7445
|
-
store.patch({ secondDevice: { rule: "ask_switch_or_join" } });
|
|
7504
|
+
store.patch({ secondDevice: { rule: found.rule ?? "ask_switch_or_join" } });
|
|
7446
7505
|
report("info", "meet: this browser already has you in this meeting \u2014 offering the choice before Join");
|
|
7447
7506
|
return true;
|
|
7448
7507
|
},
|
|
@@ -7698,6 +7757,7 @@ function createInRoomClient(options) {
|
|
|
7698
7757
|
action: request.action,
|
|
7699
7758
|
...request.identity != null ? { identity: request.identity } : {},
|
|
7700
7759
|
...request.name !== void 0 ? { name: request.name } : {},
|
|
7760
|
+
...request.value !== void 0 ? { value: request.value } : {},
|
|
7701
7761
|
...request.reason !== void 0 ? { reason: request.reason } : {}
|
|
7702
7762
|
},
|
|
7703
7763
|
...hdrs !== void 0 ? { headers: hdrs } : {}
|