@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/dist/core.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as ParticipantIdentity, e as ParticipantRole, k as AdmissionState, a1 as NoteTakerState, a as MeetParticipant, M as MeetingRecord, R as RoomName, d as CallInvite, a6 as ParticipantStanding, a3 as ObserversVisibleTo, S as StageLayout, L as LobbyEntry, aa as RecordingState, U as UserId, aF as RecordingSource, ae as TranscriptSegment, g as MeetingNote, W as WrapUpAnnouncement, j as CollabSnapshot, p as ConnectionQuality, h as MeetingId, b as MeetApi, f as CallMode, O as OrganizationId, m as CallId, n as CallState, Z as MeetingKind, a8 as RecordingPolicy, V as MeetingAttendee, a9 as RecordingRecord, a0 as MeetingSettings, X as MeetingChanges, a4 as OccurrenceOverride, $ as MeetingOccurrence, af as UpcomingOccurrence, Y as MeetingInvitee, I as InviteeInput, q as InviteeRole, ab as RsvpAnswer, ac as RsvpInvitation, c as MeetIdentity, C as CollabPanel } from './collab-BNJNgXFB.cjs';
2
- export { A as AccessTokenSource, l as CAPTION_LANGUAGES, o as CallablePerson, E as EMPTY_COLLAB, F as FILE_SESSION_PATH, J as JsonObject, r as JsonValue, s as MeetApiOptions, t as MeetApiRequest, u as MeetAppFocus, v as MeetBreakoutBroadcast, w as MeetBreakoutPlan, x as MeetBreakoutRoom, y as MeetCollabSettings, z as MeetFileMedia, B as MeetPoll, D as MeetPollOption, G as MeetPollState, H as MeetQuestion, K as MeetQuestionState, N as MeetStroke, Q as MeetingActivities, i as MeetingAppPanel, _ as MeetingNoteKind, a2 as ORGANIZATION_HEADER, a5 as OccurrenceState, a7 as ROLE_RANK, ad as RsvpState, T as TranscriptSource, ag as appPanelOf, ah as applyCollabPacket, ai as asCallId, aj as asMeetingId, ak as asOrganizationId, al as asParticipantIdentity, am as asRoomName, an as asUserId, ao as assignedRoom, ap as autoAssign, aq as breakoutClosingMs, ar as breakoutRemainingMs, as as captureHeldOf, at as collabFromState, au as createMeetApi, av as defaultCaptionLanguage, aw as fileDownloadPath, ax as focusFromRow, ay as isGuest, az as isHostRole, aA as isLinkFollower, aB as isObserverRole, aC as loadMeetingActivities, aD as scheduleSettingsPatch, aE as withItem } from './collab-BNJNgXFB.cjs';
1
+ import { P as ParticipantIdentity, e as ParticipantRole, k as AdmissionState, a1 as NoteTakerState, a as MeetParticipant, M as MeetingRecord, R as RoomName, d as CallInvite, a6 as ParticipantStanding, a3 as ObserversVisibleTo, S as StageLayout, L as LobbyEntry, aa as RecordingState, U as UserId, aF as RecordingSource, ae as TranscriptSegment, g as MeetingNote, W as WrapUpAnnouncement, j as CollabSnapshot, p as ConnectionQuality, h as MeetingId, b as MeetApi, f as CallMode, O as OrganizationId, m as CallId, n as CallState, Z as MeetingKind, a8 as RecordingPolicy, V as MeetingAttendee, a9 as RecordingRecord, a0 as MeetingSettings, X as MeetingChanges, a4 as OccurrenceOverride, $ as MeetingOccurrence, af as UpcomingOccurrence, Y as MeetingInvitee, I as InviteeInput, q as InviteeRole, ab as RsvpAnswer, ac as RsvpInvitation, c as MeetIdentity, C as CollabPanel } from './collab-D1TX5uf9.cjs';
2
+ export { A as AccessTokenSource, l as CAPTION_LANGUAGES, o as CallablePerson, E as EMPTY_COLLAB, F as FILE_SESSION_PATH, J as JsonObject, r as JsonValue, s as MeetApiOptions, t as MeetApiRequest, u as MeetAppFocus, v as MeetBreakoutBroadcast, w as MeetBreakoutPlan, x as MeetBreakoutRoom, y as MeetCollabSettings, z as MeetFileMedia, B as MeetPoll, D as MeetPollOption, G as MeetPollState, H as MeetQuestion, K as MeetQuestionState, N as MeetStroke, Q as MeetingActivities, i as MeetingAppPanel, _ as MeetingNoteKind, a2 as ORGANIZATION_HEADER, a5 as OccurrenceState, a7 as ROLE_RANK, ad as RsvpState, T as TranscriptSource, ag as appPanelOf, ah as applyCollabPacket, ai as asCallId, aj as asMeetingId, ak as asOrganizationId, al as asParticipantIdentity, am as asRoomName, an as asUserId, ao as assignedRoom, ap as autoAssign, aq as breakoutClosingMs, ar as breakoutRemainingMs, as as captureHeldOf, at as collabFromState, au as createMeetApi, av as defaultCaptionLanguage, aw as fileDownloadPath, ax as focusFromRow, ay as isGuest, az as isHostRole, aA as isLinkFollower, aB as isObserverRole, aC as loadMeetingActivities, aD as scheduleSettingsPatch, aE as withItem } from './collab-D1TX5uf9.cjs';
3
3
  import { RealtimeManager } from '@ai-matrx/realtime';
4
4
  import { MessagingSupabaseClient, ActionHandler } from '@ai-matrx/messaging';
5
5
  import { RoomOptions, ConnectionQuality as ConnectionQuality$1, Participant } from 'livekit-client';
@@ -859,6 +859,10 @@ interface MeetSnapshot {
859
859
  * Rendered verbatim; never replaced by a spinner or a house sentence.
860
860
  */
861
861
  readonly noteTakerRefusal: NoteTakerRefusal | null;
862
+ /** `captions-toggle`: THIS viewer wants captions. Local to the viewer; never sent to the room. */
863
+ readonly captionsOn: boolean;
864
+ /** Why asking for captions failed, in the server's words (`captions-unavailable`). */
865
+ readonly captionsRefusal: NoteTakerRefusal | null;
862
866
  /**
863
867
  * What the LOCAL participant is actually publishing, and why not when it is
864
868
  * not. Attendance never depends on it (see `attendance.ts`): a refused
@@ -870,10 +874,6 @@ interface MeetSnapshot {
870
874
  * last device change and an offered new device. Written only by `media-supervisor.ts`.
871
875
  */
872
876
  readonly mediaRegion: MediaRegionState;
873
- /** `captions-toggle`: THIS viewer wants captions. Local to the viewer; never sent to the room. */
874
- readonly captionsOn: boolean;
875
- /** Why asking for captions failed, in the server's words (`captions-unavailable`). */
876
- readonly captionsRefusal: NoteTakerRefusal | null;
877
877
  /** The last failure, with its remedy. Never null-and-hoping. */
878
878
  readonly failure: {
879
879
  readonly message: string;
@@ -1206,6 +1206,10 @@ declare const RPCS: {
1206
1206
  readonly admitAll: "meet_admit_all";
1207
1207
  readonly setLock: "meet_set_lock";
1208
1208
  readonly recordConsent: "meet_record_consent";
1209
+ /** One meeting rule as the gate obeys it (the knob ladder, this meeting's rung included). */
1210
+ readonly meetingRule: "meet_policy";
1211
+ /** A host sets one rule for THIS meeting (the `meet_meeting` rung); refusals come back as `{ok:false}`. */
1212
+ readonly setMeetingRule: "meet_policy_set";
1209
1213
  /** Schedule with every setting at create; unset settings come from the knobs. */
1210
1214
  readonly scheduleMeeting: "meet_schedule_meeting";
1211
1215
  /** Edit / reschedule — a JSON patch with a version compare-and-swap. */
@@ -1297,6 +1301,10 @@ interface MeetRepository {
1297
1301
  /** S4: admit everyone still waiting (not expired); returns the admitted rows. */
1298
1302
  admitAll(meetingId: MeetingId, byUserId: UserId): Promise<readonly MeetingAttendee[]>;
1299
1303
  setLock(meetingId: MeetingId, locked: boolean, byUserId: UserId): Promise<MeetingRecord>;
1304
+ /** `wr-policy-who-waits`: read one rule of this meeting (`lobby_bypass`, `access_type`…). */
1305
+ meetingRule(meetingId: MeetingId, key: string): Promise<unknown>;
1306
+ /** A host sets one rule for this meeting; a refusal throws with the server's sentence. */
1307
+ setMeetingRule(meetingId: MeetingId, key: string, value: string | number | boolean): Promise<unknown>;
1300
1308
  projectSegment(row: Row): TranscriptSegment;
1301
1309
  projectNote(row: Row): MeetingNote;
1302
1310
  /** One `meet_recordings` row, however it arrived (row or room packet). */
@@ -2290,6 +2298,8 @@ interface MeetingSession {
2290
2298
  stopWaiting(): void;
2291
2299
  /** One state read now (idempotent while one is in flight). */
2292
2300
  readState(): Promise<void>;
2301
+ /** One read of the meeting's rules now (chat mode, attendee lock, time limit); resolves once they are on the store. */
2302
+ readLivePolicy(): Promise<void>;
2293
2303
  /**
2294
2304
  * §3.4 ER: what the server recorded for THIS connection's exit, and the run's phase. null =
2295
2305
  * the read failed (offline / unreachable); undefined = no meeting or no pass to ask with.
@@ -2308,6 +2318,10 @@ interface MeetingSession {
2308
2318
  readonly assignTo: string;
2309
2319
  }): Promise<void>;
2310
2320
  setLock(locked: boolean): Promise<MeetingRecord>;
2321
+ /** `wr-policy-who-waits`: one rule of the meeting on screen (null when unreadable). */
2322
+ meetingRule(key: string): Promise<unknown>;
2323
+ /** A host changes one rule for this meeting; waiting people are told to read again. */
2324
+ setMeetingRule(key: string, value: string | number | boolean): Promise<unknown>;
2311
2325
  /** End it for everyone, through the server (MRI-A6). */
2312
2326
  endForEveryone(): Promise<EndMeetingResult>;
2313
2327
  dispose(): void;
@@ -2498,10 +2512,18 @@ interface TabClaim {
2498
2512
  /** This page's claimed tab id (resolves once the claim settles). */
2499
2513
  readonly tabId: Promise<string>;
2500
2514
  /** Announce that this tab is in `room` as `person` (until `left`); answers presence questions. */
2501
- inRoom(room: string, person: string): void;
2515
+ inRoom(room: string, person: string, rule?: string | null): void;
2502
2516
  left(): void;
2503
2517
  /** Is `person` in `room` on ANOTHER tab of this browser? Answers within `TAB_ANSWER_MS`. */
2504
2518
  presentElsewhere(room: string, person: string): Promise<boolean>;
2519
+ /**
2520
+ * The same question, with the meeting's `second_device` rule the live tab holds — so the second
2521
+ * tab offers the PROFILE's choice (Meet: Switch here / Join here too; Teams: Transfer here / Add
2522
+ * this device) before anybody presses Join. Null when no other tab has the person live.
2523
+ */
2524
+ presenceElsewhere?(room: string, person: string): Promise<{
2525
+ readonly rule: string | null;
2526
+ } | null>;
2505
2527
  dispose(): void;
2506
2528
  }
2507
2529
 
@@ -2907,6 +2929,8 @@ interface RoomToken {
2907
2929
  * LiveKit token was issued (`token` is empty); the pre-join offers the choice.
2908
2930
  */
2909
2931
  readonly secondDeviceChoice?: string | null | undefined;
2932
+ /** S7: the meeting's `second_device` rule, always — told to a second tab of this browser. */
2933
+ readonly secondDeviceRule?: string | null | undefined;
2910
2934
  readonly displayName: string;
2911
2935
  /** ISO. The package refreshes at 80% of the remaining life. */
2912
2936
  readonly expiresAt: string;
@@ -3056,10 +3080,10 @@ declare const MEET_ROUTES: {
3056
3080
  readonly recordingStop: "/api/v1/meet/recording/stop";
3057
3081
  readonly noteTakerStart: "/api/v1/meet/agent/start";
3058
3082
  readonly noteTakerStop: "/api/v1/meet/agent/stop";
3059
- /** In-meeting Q&A. Streams NDJSON; body is `{meeting_id, question}` only. */
3060
- readonly intelligenceAsk: "/api/v1/meet/intelligence/ask";
3061
3083
  /** Anyone in the meeting (guests with the room pass included) asks for captions for themselves. */
3062
3084
  readonly noteTakerCaptions: "/api/v1/meet/agent/captions";
3085
+ /** In-meeting Q&A. Streams NDJSON; body is `{meeting_id, question}` only. */
3086
+ readonly intelligenceAsk: "/api/v1/meet/intelligence/ask";
3063
3087
  /** A host ends the meeting for everyone. Served by MRI-A6. */
3064
3088
  readonly meetingEnd: "/api/v1/meet/end";
3065
3089
  /**
package/dist/core.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as ParticipantIdentity, e as ParticipantRole, k as AdmissionState, a1 as NoteTakerState, a as MeetParticipant, M as MeetingRecord, R as RoomName, d as CallInvite, a6 as ParticipantStanding, a3 as ObserversVisibleTo, S as StageLayout, L as LobbyEntry, aa as RecordingState, U as UserId, aF as RecordingSource, ae as TranscriptSegment, g as MeetingNote, W as WrapUpAnnouncement, j as CollabSnapshot, p as ConnectionQuality, h as MeetingId, b as MeetApi, f as CallMode, O as OrganizationId, m as CallId, n as CallState, Z as MeetingKind, a8 as RecordingPolicy, V as MeetingAttendee, a9 as RecordingRecord, a0 as MeetingSettings, X as MeetingChanges, a4 as OccurrenceOverride, $ as MeetingOccurrence, af as UpcomingOccurrence, Y as MeetingInvitee, I as InviteeInput, q as InviteeRole, ab as RsvpAnswer, ac as RsvpInvitation, c as MeetIdentity, C as CollabPanel } from './collab-BNJNgXFB.js';
2
- export { A as AccessTokenSource, l as CAPTION_LANGUAGES, o as CallablePerson, E as EMPTY_COLLAB, F as FILE_SESSION_PATH, J as JsonObject, r as JsonValue, s as MeetApiOptions, t as MeetApiRequest, u as MeetAppFocus, v as MeetBreakoutBroadcast, w as MeetBreakoutPlan, x as MeetBreakoutRoom, y as MeetCollabSettings, z as MeetFileMedia, B as MeetPoll, D as MeetPollOption, G as MeetPollState, H as MeetQuestion, K as MeetQuestionState, N as MeetStroke, Q as MeetingActivities, i as MeetingAppPanel, _ as MeetingNoteKind, a2 as ORGANIZATION_HEADER, a5 as OccurrenceState, a7 as ROLE_RANK, ad as RsvpState, T as TranscriptSource, ag as appPanelOf, ah as applyCollabPacket, ai as asCallId, aj as asMeetingId, ak as asOrganizationId, al as asParticipantIdentity, am as asRoomName, an as asUserId, ao as assignedRoom, ap as autoAssign, aq as breakoutClosingMs, ar as breakoutRemainingMs, as as captureHeldOf, at as collabFromState, au as createMeetApi, av as defaultCaptionLanguage, aw as fileDownloadPath, ax as focusFromRow, ay as isGuest, az as isHostRole, aA as isLinkFollower, aB as isObserverRole, aC as loadMeetingActivities, aD as scheduleSettingsPatch, aE as withItem } from './collab-BNJNgXFB.js';
1
+ import { P as ParticipantIdentity, e as ParticipantRole, k as AdmissionState, a1 as NoteTakerState, a as MeetParticipant, M as MeetingRecord, R as RoomName, d as CallInvite, a6 as ParticipantStanding, a3 as ObserversVisibleTo, S as StageLayout, L as LobbyEntry, aa as RecordingState, U as UserId, aF as RecordingSource, ae as TranscriptSegment, g as MeetingNote, W as WrapUpAnnouncement, j as CollabSnapshot, p as ConnectionQuality, h as MeetingId, b as MeetApi, f as CallMode, O as OrganizationId, m as CallId, n as CallState, Z as MeetingKind, a8 as RecordingPolicy, V as MeetingAttendee, a9 as RecordingRecord, a0 as MeetingSettings, X as MeetingChanges, a4 as OccurrenceOverride, $ as MeetingOccurrence, af as UpcomingOccurrence, Y as MeetingInvitee, I as InviteeInput, q as InviteeRole, ab as RsvpAnswer, ac as RsvpInvitation, c as MeetIdentity, C as CollabPanel } from './collab-D1TX5uf9.js';
2
+ export { A as AccessTokenSource, l as CAPTION_LANGUAGES, o as CallablePerson, E as EMPTY_COLLAB, F as FILE_SESSION_PATH, J as JsonObject, r as JsonValue, s as MeetApiOptions, t as MeetApiRequest, u as MeetAppFocus, v as MeetBreakoutBroadcast, w as MeetBreakoutPlan, x as MeetBreakoutRoom, y as MeetCollabSettings, z as MeetFileMedia, B as MeetPoll, D as MeetPollOption, G as MeetPollState, H as MeetQuestion, K as MeetQuestionState, N as MeetStroke, Q as MeetingActivities, i as MeetingAppPanel, _ as MeetingNoteKind, a2 as ORGANIZATION_HEADER, a5 as OccurrenceState, a7 as ROLE_RANK, ad as RsvpState, T as TranscriptSource, ag as appPanelOf, ah as applyCollabPacket, ai as asCallId, aj as asMeetingId, ak as asOrganizationId, al as asParticipantIdentity, am as asRoomName, an as asUserId, ao as assignedRoom, ap as autoAssign, aq as breakoutClosingMs, ar as breakoutRemainingMs, as as captureHeldOf, at as collabFromState, au as createMeetApi, av as defaultCaptionLanguage, aw as fileDownloadPath, ax as focusFromRow, ay as isGuest, az as isHostRole, aA as isLinkFollower, aB as isObserverRole, aC as loadMeetingActivities, aD as scheduleSettingsPatch, aE as withItem } from './collab-D1TX5uf9.js';
3
3
  import { RealtimeManager } from '@ai-matrx/realtime';
4
4
  import { MessagingSupabaseClient, ActionHandler } from '@ai-matrx/messaging';
5
5
  import { RoomOptions, ConnectionQuality as ConnectionQuality$1, Participant } from 'livekit-client';
@@ -859,6 +859,10 @@ interface MeetSnapshot {
859
859
  * Rendered verbatim; never replaced by a spinner or a house sentence.
860
860
  */
861
861
  readonly noteTakerRefusal: NoteTakerRefusal | null;
862
+ /** `captions-toggle`: THIS viewer wants captions. Local to the viewer; never sent to the room. */
863
+ readonly captionsOn: boolean;
864
+ /** Why asking for captions failed, in the server's words (`captions-unavailable`). */
865
+ readonly captionsRefusal: NoteTakerRefusal | null;
862
866
  /**
863
867
  * What the LOCAL participant is actually publishing, and why not when it is
864
868
  * not. Attendance never depends on it (see `attendance.ts`): a refused
@@ -870,10 +874,6 @@ interface MeetSnapshot {
870
874
  * last device change and an offered new device. Written only by `media-supervisor.ts`.
871
875
  */
872
876
  readonly mediaRegion: MediaRegionState;
873
- /** `captions-toggle`: THIS viewer wants captions. Local to the viewer; never sent to the room. */
874
- readonly captionsOn: boolean;
875
- /** Why asking for captions failed, in the server's words (`captions-unavailable`). */
876
- readonly captionsRefusal: NoteTakerRefusal | null;
877
877
  /** The last failure, with its remedy. Never null-and-hoping. */
878
878
  readonly failure: {
879
879
  readonly message: string;
@@ -1206,6 +1206,10 @@ declare const RPCS: {
1206
1206
  readonly admitAll: "meet_admit_all";
1207
1207
  readonly setLock: "meet_set_lock";
1208
1208
  readonly recordConsent: "meet_record_consent";
1209
+ /** One meeting rule as the gate obeys it (the knob ladder, this meeting's rung included). */
1210
+ readonly meetingRule: "meet_policy";
1211
+ /** A host sets one rule for THIS meeting (the `meet_meeting` rung); refusals come back as `{ok:false}`. */
1212
+ readonly setMeetingRule: "meet_policy_set";
1209
1213
  /** Schedule with every setting at create; unset settings come from the knobs. */
1210
1214
  readonly scheduleMeeting: "meet_schedule_meeting";
1211
1215
  /** Edit / reschedule — a JSON patch with a version compare-and-swap. */
@@ -1297,6 +1301,10 @@ interface MeetRepository {
1297
1301
  /** S4: admit everyone still waiting (not expired); returns the admitted rows. */
1298
1302
  admitAll(meetingId: MeetingId, byUserId: UserId): Promise<readonly MeetingAttendee[]>;
1299
1303
  setLock(meetingId: MeetingId, locked: boolean, byUserId: UserId): Promise<MeetingRecord>;
1304
+ /** `wr-policy-who-waits`: read one rule of this meeting (`lobby_bypass`, `access_type`…). */
1305
+ meetingRule(meetingId: MeetingId, key: string): Promise<unknown>;
1306
+ /** A host sets one rule for this meeting; a refusal throws with the server's sentence. */
1307
+ setMeetingRule(meetingId: MeetingId, key: string, value: string | number | boolean): Promise<unknown>;
1300
1308
  projectSegment(row: Row): TranscriptSegment;
1301
1309
  projectNote(row: Row): MeetingNote;
1302
1310
  /** One `meet_recordings` row, however it arrived (row or room packet). */
@@ -2290,6 +2298,8 @@ interface MeetingSession {
2290
2298
  stopWaiting(): void;
2291
2299
  /** One state read now (idempotent while one is in flight). */
2292
2300
  readState(): Promise<void>;
2301
+ /** One read of the meeting's rules now (chat mode, attendee lock, time limit); resolves once they are on the store. */
2302
+ readLivePolicy(): Promise<void>;
2293
2303
  /**
2294
2304
  * §3.4 ER: what the server recorded for THIS connection's exit, and the run's phase. null =
2295
2305
  * the read failed (offline / unreachable); undefined = no meeting or no pass to ask with.
@@ -2308,6 +2318,10 @@ interface MeetingSession {
2308
2318
  readonly assignTo: string;
2309
2319
  }): Promise<void>;
2310
2320
  setLock(locked: boolean): Promise<MeetingRecord>;
2321
+ /** `wr-policy-who-waits`: one rule of the meeting on screen (null when unreadable). */
2322
+ meetingRule(key: string): Promise<unknown>;
2323
+ /** A host changes one rule for this meeting; waiting people are told to read again. */
2324
+ setMeetingRule(key: string, value: string | number | boolean): Promise<unknown>;
2311
2325
  /** End it for everyone, through the server (MRI-A6). */
2312
2326
  endForEveryone(): Promise<EndMeetingResult>;
2313
2327
  dispose(): void;
@@ -2498,10 +2512,18 @@ interface TabClaim {
2498
2512
  /** This page's claimed tab id (resolves once the claim settles). */
2499
2513
  readonly tabId: Promise<string>;
2500
2514
  /** Announce that this tab is in `room` as `person` (until `left`); answers presence questions. */
2501
- inRoom(room: string, person: string): void;
2515
+ inRoom(room: string, person: string, rule?: string | null): void;
2502
2516
  left(): void;
2503
2517
  /** Is `person` in `room` on ANOTHER tab of this browser? Answers within `TAB_ANSWER_MS`. */
2504
2518
  presentElsewhere(room: string, person: string): Promise<boolean>;
2519
+ /**
2520
+ * The same question, with the meeting's `second_device` rule the live tab holds — so the second
2521
+ * tab offers the PROFILE's choice (Meet: Switch here / Join here too; Teams: Transfer here / Add
2522
+ * this device) before anybody presses Join. Null when no other tab has the person live.
2523
+ */
2524
+ presenceElsewhere?(room: string, person: string): Promise<{
2525
+ readonly rule: string | null;
2526
+ } | null>;
2505
2527
  dispose(): void;
2506
2528
  }
2507
2529
 
@@ -2907,6 +2929,8 @@ interface RoomToken {
2907
2929
  * LiveKit token was issued (`token` is empty); the pre-join offers the choice.
2908
2930
  */
2909
2931
  readonly secondDeviceChoice?: string | null | undefined;
2932
+ /** S7: the meeting's `second_device` rule, always — told to a second tab of this browser. */
2933
+ readonly secondDeviceRule?: string | null | undefined;
2910
2934
  readonly displayName: string;
2911
2935
  /** ISO. The package refreshes at 80% of the remaining life. */
2912
2936
  readonly expiresAt: string;
@@ -3056,10 +3080,10 @@ declare const MEET_ROUTES: {
3056
3080
  readonly recordingStop: "/api/v1/meet/recording/stop";
3057
3081
  readonly noteTakerStart: "/api/v1/meet/agent/start";
3058
3082
  readonly noteTakerStop: "/api/v1/meet/agent/stop";
3059
- /** In-meeting Q&A. Streams NDJSON; body is `{meeting_id, question}` only. */
3060
- readonly intelligenceAsk: "/api/v1/meet/intelligence/ask";
3061
3083
  /** Anyone in the meeting (guests with the room pass included) asks for captions for themselves. */
3062
3084
  readonly noteTakerCaptions: "/api/v1/meet/agent/captions";
3085
+ /** In-meeting Q&A. Streams NDJSON; body is `{meeting_id, question}` only. */
3086
+ readonly intelligenceAsk: "/api/v1/meet/intelligence/ask";
3063
3087
  /** A host ends the meeting for everyone. Served by MRI-A6. */
3064
3088
  readonly meetingEnd: "/api/v1/meet/end";
3065
3089
  /**
package/dist/core.js CHANGED
@@ -323,7 +323,8 @@ function createWebResumeStorage() {
323
323
  }
324
324
  };
325
325
  }
326
- var CLEARS_RESUME = (phase) => phase === "left" || phase === "removed" || phase === "superseded" || phase === "inactive" || phase === "ended" || phase === "record" || phase === "prejoin" || phase.startsWith("refused:") || phase.startsWith("waiting:");
326
+ 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:");
327
+ var WAITING_RESUMES = (phase) => phase.startsWith("waiting:");
327
328
  function autoRejoinDelayMs(attempt, random = Math.random) {
328
329
  const base = Math.min(15e3, 1e3 * 2 ** Math.max(0, attempt));
329
330
  return Math.round(base * (0.5 + random()));
@@ -455,6 +456,10 @@ function createConnectionSupervisor(options) {
455
456
  rejoinAttempts = 0;
456
457
  stopRejoin();
457
458
  saveMarker(true);
459
+ } else if (WAITING_RESUMES(phase)) {
460
+ stopRejoin();
461
+ driverRegion = null;
462
+ saveMarker(true);
458
463
  } else if (phase === "disconnected") {
459
464
  driverRegion = null;
460
465
  saveMarker(true);
@@ -630,10 +635,10 @@ var MEET_ROUTES = {
630
635
  recordingStop: "/api/v1/meet/recording/stop",
631
636
  noteTakerStart: "/api/v1/meet/agent/start",
632
637
  noteTakerStop: "/api/v1/meet/agent/stop",
633
- /** In-meeting Q&A. Streams NDJSON; body is `{meeting_id, question}` only. */
634
- intelligenceAsk: "/api/v1/meet/intelligence/ask",
635
638
  /** Anyone in the meeting (guests with the room pass included) asks for captions for themselves. */
636
639
  noteTakerCaptions: "/api/v1/meet/agent/captions",
640
+ /** In-meeting Q&A. Streams NDJSON; body is `{meeting_id, question}` only. */
641
+ intelligenceAsk: "/api/v1/meet/intelligence/ask",
637
642
  /** A host ends the meeting for everyone. Served by MRI-A6. */
638
643
  meetingEnd: "/api/v1/meet/end",
639
644
  /**
@@ -758,6 +763,7 @@ function parseRoomToken(body, roomName) {
758
763
  connectionIdentity: readString(payload, "connection_identity") ?? personKey,
759
764
  connectionKind: readString(payload, "connection_kind") === "companion" ? "companion" : "main",
760
765
  secondDeviceChoice,
766
+ secondDeviceRule: readString(payload, "second_device_rule"),
761
767
  displayName: readString(payload, "display_name") ?? readString(payload, "displayName") ?? identity,
762
768
  expiresAt,
763
769
  canPublish: readBoolean(payload, "can_publish", true),
@@ -1302,6 +1308,7 @@ var STATES = [
1302
1308
  "ended"
1303
1309
  ];
1304
1310
  function readState(value) {
1311
+ if (value === "dispatching") return "joining";
1305
1312
  return typeof value === "string" && STATES.includes(value) ? value : null;
1306
1313
  }
1307
1314
  function isNoteTaker(participant) {
@@ -1496,6 +1503,12 @@ var JOINABLE_FROM = /* @__PURE__ */ new Set([
1496
1503
  // allows the press; the server's gate decides whether it knocks or is refused again.
1497
1504
  "refused:lobby_rejects"
1498
1505
  ]);
1506
+ var RETRYABLE_REFUSALS = /* @__PURE__ */ new Set([
1507
+ "refused:locked",
1508
+ "refused:too_early",
1509
+ "refused:meeting_full",
1510
+ "refused:platform_capacity"
1511
+ ]);
1499
1512
  var NOT_ENDABLE = /* @__PURE__ */ new Set([
1500
1513
  "ended",
1501
1514
  "record",
@@ -1561,7 +1574,7 @@ function nextPhase(from, event) {
1561
1574
  case "link_state":
1562
1575
  return from === "resolving" && event.reason !== null && isJoinRefusalReason(event.reason) ? refusalPhase(event.reason) : null;
1563
1576
  case "join":
1564
- return JOINABLE_FROM.has(from) ? "joining" : null;
1577
+ return JOINABLE_FROM.has(from) || RETRYABLE_REFUSALS.has(from) ? "joining" : null;
1565
1578
  case "auto_rejoin":
1566
1579
  return from === "disconnected" ? "joining" : null;
1567
1580
  case "resumed":
@@ -1986,6 +1999,10 @@ var RPCS = {
1986
1999
  admitAll: "meet_admit_all",
1987
2000
  setLock: "meet_set_lock",
1988
2001
  recordConsent: "meet_record_consent",
2002
+ /** One meeting rule as the gate obeys it (the knob ladder, this meeting's rung included). */
2003
+ meetingRule: "meet_policy",
2004
+ /** A host sets one rule for THIS meeting (the `meet_meeting` rung); refusals come back as `{ok:false}`. */
2005
+ setMeetingRule: "meet_policy_set",
1989
2006
  /*
1990
2007
  * ── MEET WAVE 1 — management (0.8). Every write is a SECURITY DEFINER door
1991
2008
  * authorized by the meeting's host or a real iam grant (editor to change,
@@ -2032,7 +2049,7 @@ var INVITEE_COLUMNS = "id,meeting_id,invitee_user_id,email,display_name,role,rsv
2032
2049
  var RECORDING_COLUMNS = "id,meeting_id,state,started_at,ended_at,started_by,file_id,failure_reason";
2033
2050
  var SEGMENT_COLUMNS = "id,meeting_id,identity,speaker,text,started_at,is_final,metadata";
2034
2051
  var NOTE_COLUMNS = "id,meeting_id,text,kind,assignee_user_id,created_at,metadata";
2035
- 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";
2052
+ 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";
2036
2053
  function projectStays(value) {
2037
2054
  if (!Array.isArray(value)) return [];
2038
2055
  const stays = [];
@@ -2432,6 +2449,8 @@ function createMeetRepository(options) {
2432
2449
  admissionState: states.includes(admission) ? admission : "admitted",
2433
2450
  knockedAt: text(row, "knocked_at"),
2434
2451
  knockExpiresAt: text(row, "knock_expires_at"),
2452
+ // The list read selects `metadata->>knock_flag`; a Postgres Changes row carries `metadata`.
2453
+ knockFlag: text(row, "knock_flag") ?? (typeof row["metadata"] === "object" && row["metadata"] !== null ? text(row["metadata"], "knock_flag") : null),
2435
2454
  isAgent: bool(row, "is_agent", false),
2436
2455
  joinedAt: text(row, "joined_at"),
2437
2456
  leftAt: text(row, "left_at"),
@@ -2755,6 +2774,25 @@ function createMeetRepository(options) {
2755
2774
  );
2756
2775
  return projectMeeting(row);
2757
2776
  },
2777
+ async meetingRule(meetingId, key) {
2778
+ const response = await db.rpc(RPCS.meetingRule, { p_meeting_id: meetingId, p_key: key });
2779
+ if (response.error !== null) throw normalizeMeetError(response.error, "meet.meetingRule");
2780
+ return response.data;
2781
+ },
2782
+ async setMeetingRule(meetingId, key, value) {
2783
+ const response = await db.rpc(RPCS.setMeetingRule, { p_meeting_id: meetingId, p_key: key, p_value: value });
2784
+ if (response.error !== null) throw normalizeMeetError(response.error, "meet.setMeetingRule");
2785
+ const answer = response.data ?? {};
2786
+ if (answer["ok"] !== true) {
2787
+ throw new MeetError(
2788
+ "forbidden",
2789
+ typeof answer["detail"] === "string" ? answer["detail"] : "This meeting's rule was not changed.",
2790
+ "Only the meeting's host or a co-host sets its rules; an organization can lock a rule for everyone.",
2791
+ answer
2792
+ );
2793
+ }
2794
+ return answer["effective_value"];
2795
+ },
2758
2796
  async transcript(meetingId, limit = 1e3) {
2759
2797
  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);
2760
2798
  if (response.error !== null) throw normalizeMeetError(response.error, "meet.transcript");
@@ -4920,7 +4958,8 @@ function lobbyEntryFrom(attendee, now = Date.now()) {
4920
4958
  knockedAt: attendee.knockedAt ?? attendee.joinedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
4921
4959
  knockExpiresAt: attendee.knockExpiresAt ?? null,
4922
4960
  decidedAt: null,
4923
- decidedBy: null
4961
+ decidedBy: null,
4962
+ flag: attendee.knockFlag ?? null
4924
4963
  };
4925
4964
  }
4926
4965
  function deniedEntryFrom(attendee) {
@@ -5092,11 +5131,15 @@ function createMeetingSession(options) {
5092
5131
  }
5093
5132
  let policyTimer = null;
5094
5133
  let policyReading = false;
5134
+ let policyInFlight = null;
5095
5135
  async function readLivePolicy() {
5096
5136
  const meeting = store.snapshot().meeting;
5097
5137
  const pass = options.resolvePass?.() ?? null;
5098
- if (meeting === null || pass === null || policyReading) return;
5138
+ if (meeting === null || pass === null) return;
5139
+ if (policyReading) return policyInFlight ?? void 0;
5099
5140
  policyReading = true;
5141
+ let done = () => void 0;
5142
+ policyInFlight = new Promise((resolve) => done = resolve);
5100
5143
  try {
5101
5144
  const response = await options.api.request({
5102
5145
  path: `${MEET_ROUTES.state}?meeting_id=${encodeURIComponent(meeting.id)}`,
@@ -5117,6 +5160,8 @@ function createMeetingSession(options) {
5117
5160
  } catch {
5118
5161
  } finally {
5119
5162
  policyReading = false;
5163
+ policyInFlight = null;
5164
+ done();
5120
5165
  }
5121
5166
  }
5122
5167
  function syncLivePolicyTimer() {
@@ -5415,6 +5460,7 @@ function createMeetingSession(options) {
5415
5460
  },
5416
5461
  stopWaiting,
5417
5462
  readState: readState2,
5463
+ readLivePolicy,
5418
5464
  async readExit(connection, held) {
5419
5465
  const meeting = store.snapshot().meeting;
5420
5466
  const pass = held ?? options.resolvePass?.() ?? null;
@@ -5452,6 +5498,17 @@ function createMeetingSession(options) {
5452
5498
  async askAgain() {
5453
5499
  await options.rejoin?.();
5454
5500
  },
5501
+ async meetingRule(key) {
5502
+ const meeting = requireMeeting("meet.meetingRule");
5503
+ return repository.meetingRule(meeting.id, key);
5504
+ },
5505
+ async setMeetingRule(key, value) {
5506
+ requireHostUser("meet.setMeetingRule");
5507
+ const meeting = requireMeeting("meet.setMeetingRule");
5508
+ const effective = await repository.setMeetingRule(meeting.id, key, value);
5509
+ hint();
5510
+ return effective;
5511
+ },
5455
5512
  async setLock(locked) {
5456
5513
  const by = requireHostUser("meet.setLock");
5457
5514
  const meeting = requireMeeting("meet.setLock");
@@ -6843,7 +6900,7 @@ function createRoomEngine(options) {
6843
6900
  const { secondDevice: _answered, ...rest } = lastRequest;
6844
6901
  lastRequest = rest;
6845
6902
  }
6846
- options.tabClaim?.inRoom(String(request.roomName), String(token.identity));
6903
+ options.tabClaim?.inRoom(String(request.roomName), String(token.identity), token.secondDeviceRule ?? null);
6847
6904
  current = token;
6848
6905
  lastServerUrl = token.serverUrl;
6849
6906
  connectionPolicy = token.connectionPolicy ?? DEFAULT_CONNECTION_POLICY;
@@ -7155,10 +7212,12 @@ function createRoomEngine(options) {
7155
7212
  if (claim === void 0 || userId === null) return false;
7156
7213
  const before = store.snapshot();
7157
7214
  if (before.phase !== "prejoin" || before.secondDevice !== null) return false;
7158
- if (!await claim.presentElsewhere(String(roomName), `user:${String(userId)}`)) return false;
7215
+ const person = `user:${String(userId)}`;
7216
+ const found = claim.presenceElsewhere !== void 0 ? await claim.presenceElsewhere(String(roomName), person) : await claim.presentElsewhere(String(roomName), person) ? { rule: null } : null;
7217
+ if (found === null || found.rule === "allow_both") return false;
7159
7218
  const now2 = store.snapshot();
7160
7219
  if (now2.phase !== "prejoin" || now2.secondDevice !== null) return false;
7161
- store.patch({ secondDevice: { rule: "ask_switch_or_join" } });
7220
+ store.patch({ secondDevice: { rule: found.rule ?? "ask_switch_or_join" } });
7162
7221
  report("info", "meet: this browser already has you in this meeting \u2014 offering the choice before Join");
7163
7222
  return true;
7164
7223
  },
@@ -7414,6 +7473,7 @@ function createInRoomClient(options) {
7414
7473
  action: request.action,
7415
7474
  ...request.identity != null ? { identity: request.identity } : {},
7416
7475
  ...request.name !== void 0 ? { name: request.name } : {},
7476
+ ...request.value !== void 0 ? { value: request.value } : {},
7417
7477
  ...request.reason !== void 0 ? { reason: request.reason } : {}
7418
7478
  },
7419
7479
  ...hdrs !== void 0 ? { headers: hdrs } : {}