@ai-matrx/meet 0.7.7 → 0.7.9

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.d.cts CHANGED
@@ -605,6 +605,55 @@ declare function createMeetApi(options: MeetApiOptions): MeetApi;
605
605
  /** `GET /files/{id}/download?inline=1` — the platform files route (R3). */
606
606
  declare function fileDownloadPath(fileId: string): string;
607
607
 
608
+ /**
609
+ * ONE error classification for the whole package (C22).
610
+ *
611
+ * The banned alternative is a host catching a LiveKit or PostgREST error and
612
+ * deciding for itself whether the camera is busy, the token expired, or the
613
+ * meeting is locked — which is how the same five-branch `if` gets copy-pasted
614
+ * into every consumer and drifts. Everything this package throws is a
615
+ * `MeetError` with a stable `code` and a `remedy` SENTENCE. Nothing fails
616
+ * silently, and nothing fails without saying what to do about it.
617
+ *
618
+ * The device codes exist because "it doesn't work" in a video product is almost
619
+ * always one of four specific, differently-remediable things: permission
620
+ * denied, no such device, device already in use by another app, or insecure
621
+ * context (http, where `getUserMedia` does not exist at all). A single
622
+ * "media-error" would make the UI say the wrong sentence three times out of
623
+ * four.
624
+ */
625
+ type MeetErrorCode = "session-unavailable" | "forbidden" | "not-found" | "conflict" | "token" | "transport" | "invalid-response" | "misconfigured" | "permission-denied" | "device-not-found" | "device-in-use" | "insecure-context" | "media-unsupported" | "room-locked" | "lobby-denied" | "capacity"
626
+ /** Meet wave 1: the meeting was cancelled — its link resolves, its room never opens. */
627
+ | "cancelled" | "unknown";
628
+ declare class MeetError extends Error {
629
+ readonly code: MeetErrorCode;
630
+ /** What to DO. Rendered to the user for the device codes. */
631
+ readonly remedy: string;
632
+ readonly cause?: unknown;
633
+ constructor(code: MeetErrorCode, message: string, remedy: string, cause?: unknown);
634
+ /** True when retrying after the host re-establishes a session is the fix. */
635
+ get isRetryable(): boolean;
636
+ /** True when the user, not the code, must act — the UI shows `remedy`. */
637
+ get isUserActionable(): boolean;
638
+ }
639
+ /**
640
+ * THE ONE PLACE a raw database/transport error becomes a typed one. Called at
641
+ * every repository boundary; nothing else in the package inspects a raw error,
642
+ * and no consumer should ever have to.
643
+ */
644
+ declare function normalizeMeetError(error: unknown, operation: string): MeetError;
645
+ /**
646
+ * THE DEVICE ERROR TRANSLATOR — the second-most-copied block in every video app.
647
+ *
648
+ * `getUserMedia` rejects with DOMException names, and every one of them means
649
+ * something a user could fix if we told them. This is the whole reason the
650
+ * device layer lives in the package (C22 test 3: less-than-perfect unless done
651
+ * perfectly).
652
+ */
653
+ declare function normalizeDeviceError(error: unknown, operation: string): MeetError;
654
+ /** A response whose SHAPE is wrong — the ingress boundary, not the wire. */
655
+ declare function invalidResponse(operation: string, detail: string): MeetError;
656
+
608
657
  /**
609
658
  * WHO SAID THAT — one answer, every surface, both lanes (MRI-A16).
610
659
  *
@@ -666,55 +715,6 @@ declare function learnNames(book: NameBook, entries: readonly {
666
715
  */
667
716
  declare function displayNameFor(book: NameBook, identity: ParticipantIdentity | string, preferred?: string | null | undefined): string;
668
717
 
669
- /**
670
- * ONE error classification for the whole package (C22).
671
- *
672
- * The banned alternative is a host catching a LiveKit or PostgREST error and
673
- * deciding for itself whether the camera is busy, the token expired, or the
674
- * meeting is locked — which is how the same five-branch `if` gets copy-pasted
675
- * into every consumer and drifts. Everything this package throws is a
676
- * `MeetError` with a stable `code` and a `remedy` SENTENCE. Nothing fails
677
- * silently, and nothing fails without saying what to do about it.
678
- *
679
- * The device codes exist because "it doesn't work" in a video product is almost
680
- * always one of four specific, differently-remediable things: permission
681
- * denied, no such device, device already in use by another app, or insecure
682
- * context (http, where `getUserMedia` does not exist at all). A single
683
- * "media-error" would make the UI say the wrong sentence three times out of
684
- * four.
685
- */
686
- type MeetErrorCode = "session-unavailable" | "forbidden" | "not-found" | "conflict" | "token" | "transport" | "invalid-response" | "misconfigured" | "permission-denied" | "device-not-found" | "device-in-use" | "insecure-context" | "media-unsupported" | "room-locked" | "lobby-denied" | "capacity"
687
- /** Meet wave 1: the meeting was cancelled — its link resolves, its room never opens. */
688
- | "cancelled" | "unknown";
689
- declare class MeetError extends Error {
690
- readonly code: MeetErrorCode;
691
- /** What to DO. Rendered to the user for the device codes. */
692
- readonly remedy: string;
693
- readonly cause?: unknown;
694
- constructor(code: MeetErrorCode, message: string, remedy: string, cause?: unknown);
695
- /** True when retrying after the host re-establishes a session is the fix. */
696
- get isRetryable(): boolean;
697
- /** True when the user, not the code, must act — the UI shows `remedy`. */
698
- get isUserActionable(): boolean;
699
- }
700
- /**
701
- * THE ONE PLACE a raw database/transport error becomes a typed one. Called at
702
- * every repository boundary; nothing else in the package inspects a raw error,
703
- * and no consumer should ever have to.
704
- */
705
- declare function normalizeMeetError(error: unknown, operation: string): MeetError;
706
- /**
707
- * THE DEVICE ERROR TRANSLATOR — the second-most-copied block in every video app.
708
- *
709
- * `getUserMedia` rejects with DOMException names, and every one of them means
710
- * something a user could fix if we told them. This is the whole reason the
711
- * device layer lives in the package (C22 test 3: less-than-perfect unless done
712
- * perfectly).
713
- */
714
- declare function normalizeDeviceError(error: unknown, operation: string): MeetError;
715
- /** A response whose SHAPE is wrong — the ingress boundary, not the wire. */
716
- declare function invalidResponse(operation: string, detail: string): MeetError;
717
-
718
718
  /**
719
719
  * LISTEN-ONLY ATTENDANCE — being IN the room is never contingent on a device.
720
720
  *
@@ -995,6 +995,17 @@ interface MeetSnapshot {
995
995
  readonly failed: boolean;
996
996
  readonly at: number;
997
997
  } | null;
998
+ /**
999
+ * "Message privately" asked for from ANY per-person menu — a tile's, the
1000
+ * People panel's — and answered by the one `ControlBar` that owns the chat
1001
+ * panel (0.7.8). Through 0.7.7 only the People panel could open a private
1002
+ * chat, so the Board's tile menu (and the Room's) had no such item while the
1003
+ * People panel did: two menus for one person that disagreed.
1004
+ */
1005
+ readonly privateChatRequest: {
1006
+ readonly to: ParticipantIdentity;
1007
+ readonly at: number;
1008
+ } | null;
998
1009
  readonly effects: MediaEffects;
999
1010
  /**
1000
1011
  * Captions AND durable rows, reconciled into one list (D16). A record
@@ -1177,6 +1188,7 @@ declare const MEET_ANSWER_EVENTS: {
1177
1188
  };
1178
1189
  /** The `info` event carrying what the answer was built from. */
1179
1190
  declare const MEET_ANSWER_CONTEXT_EVENT = "meet_intelligence_context";
1191
+
1180
1192
  interface ServerRefusal {
1181
1193
  readonly reason: string;
1182
1194
  readonly remedy: string;
@@ -2898,12 +2910,30 @@ interface AttendanceRow {
2898
2910
  /** True when `durationMs` was measured to the meeting's end, not a recorded leave. */
2899
2911
  readonly durationToEnd: boolean;
2900
2912
  readonly admission: MeetingAttendee["admissionState"];
2913
+ /** How many times this person came in (a rejoin or a second device). */
2914
+ readonly joins: number;
2901
2915
  }
2902
2916
  /**
2903
2917
  * The attendance report of ONE meeting, host first then by arrival. People who
2904
2918
  * knocked and were never let in are kept (with no join time) — "who asked to
2905
2919
  * come in" is part of the record — but a denied knock has no duration.
2906
2920
  */
2921
+ /**
2922
+ * WHO a participant row is, as a PERSON (verifier, 2026-09-27: an export listed
2923
+ * the same attendee twice under "attended"). A signed-in person is their
2924
+ * account — every device and every rejoin is one person. A guest without an
2925
+ * account gets a fresh `guest:<random>` identity on every join, so the name
2926
+ * they typed is the only thread between their joins (Zoom's attendee report
2927
+ * merges link guests the same way); two different accountless guests who
2928
+ * typed the identical name read as one, which is the lesser error.
2929
+ */
2930
+ declare function attendeeKey(person: MeetingAttendee, names?: NameBook): string;
2931
+ /**
2932
+ * One row per PERSON, in first-seen order: the row that actually joined (the
2933
+ * earliest) represents them. For a list of names or a head-count; the
2934
+ * attendance REPORT merges times as well (`attendanceReport`).
2935
+ */
2936
+ declare function uniqueAttendees(attendees: readonly MeetingAttendee[], names?: NameBook): readonly MeetingAttendee[];
2907
2937
  declare function attendanceReport(meeting: MeetingRecord, attendees: readonly MeetingAttendee[], names?: NameBook): readonly AttendanceRow[];
2908
2938
  /** Headline numbers for the top of a report. The assistant is never a person. */
2909
2939
  declare function attendanceTotals(rows: readonly AttendanceRow[]): {
@@ -3255,4 +3285,4 @@ interface InRoomClientOptions {
3255
3285
  }
3256
3286
  declare function createInRoomClient(options: InRoomClientOptions): InRoomClient;
3257
3287
 
3258
- export { ATTENDANCE_CSV_HEADER, type AccessTokenSource, type AdmissionState, type AnnounceResult, type ApplyRoomEventArgs, type AskArgs, type AttendanceKind, type AttendanceRow, type AudioProcessing, CALL_INVITE_KIND, CALL_INVITE_VERSION, CONSENT_NOTICE_ATTRIBUTE, type CallCenter, type CallCenterOptions, type CallId, type CallInvite, type CallInviteHandlerOptions, type CallInvitePayload, type CallMode, type CallState, type CallablePerson, type ConnectionQuality, type CreateCallInviteInput, type CreateMeetingInput, DATA_TOPICS, DEFAULT_EFFECTS, DEFAULT_PAGE_SIZE, type DataTopic, type DeviceKind, type DeviceManager, type DeviceManagerOptions, type DeviceSnapshot, type DeviceStorage, type DriverConnectionState, type DriverParticipant, type DriverTrackKind, type DriverTranscription, END_MEETING_NOT_SERVED, type EffectsStorage, type EndMeetingResult, FILE_SESSION_PATH, type FollowUpDraft, type FollowUpRecipient, type FollowUpSendResult, GUEST_RECORD_ACCESS_CHOICES, GUEST_RECORD_ACCESS_LEVELS, GUEST_RECORD_ACCESS_METADATA_KEY, GUEST_RECORD_NOT_SHARED, type GuestRecordAccess, type GuestRecordAccessResolution, type GuestRecordAccessSetting, IDLE_MEDIA, IDLE_TRACK, type InRoomClient, type InRoomClientOptions, type InviteeInput, type InviteeRole, type JoinRequest, type JsonObject, type JsonValue, LISTEN_ONLY_NOTICE, type LibraryRecording, type LiveKitDriverOptions, type LobbyEntry, type LocalMediaState, type LocalTrackState, MEETING_INVITE_KIND, MEETING_INVITE_VERSION, MEET_ANSWER_CONTEXT_EVENT, MEET_ANSWER_EVENTS, MEET_EVENTS, MEET_ROUTES, MEET_SCHEMA, MODERATION_ACTIONS, type MediaDevicesLike, type MediaEffects, type MediaUnavailable, type MeetAi, type MeetAiAnswer, type MeetAiOptions, type MeetAnswerCoverage, type MeetApi, type MeetApiOptions, type MeetApiRequest, type MeetDevice, MeetError, type MeetErrorCode, type MeetEvent, type MeetFileMedia, type MeetGrants, type MeetIdentity, type MeetParticipant, type MeetRepository, type MeetRoomDriver, type MeetSnapshot, type MeetStore, type MeetingAttendee, type MeetingChanges, type MeetingChatHistory, type MeetingId, type MeetingInviteHandlerOptions, type MeetingInvitePayload, type MeetingInvitee, type MeetingKind, type MeetingNote, type MeetingNoteKind, type MeetingOccurrence, type MeetingRecord, type MeetingRecordBundle, type MeetingRecordRestriction, type MeetingRecordRestrictionNotice, type MeetingSearchHit, type MeetingSearchSource, type MeetingSession, type MeetingSessionOptions, type MeetingSettings, type ModerationAction, type ModerationNotice, type ModerationRequest, type ModerationResult, NOTE_TAKER_IDENTITY_PREFIX, NOTE_TAKER_METADATA_KEY, NO_GRANTS, type NameBook, type NoteTakerDispatch, type NoteTakerRefusal, type NoteTakerState, type NoteTakerStatus, ORGANIZATION_HEADER, type OccurrenceOverride, type OccurrenceState, type OrganizationId, PARTICIPANT_CAN_RECORD_ATTRIBUTE, PARTICIPANT_ROLE_ATTRIBUTE, type ParticipantIdentity, type ParticipantRole, REACTION_TTL_MS, REFUSED_ABSENCE, ROLE_RANK, ROOM_EVENTS, ROOM_EVENT_PREFIX, ROOM_TOKEN_HEADER, RPCS, type RecordingController, type RecordingControllerOptions, type RecordingPolicy, type RecordingRecord, type RecordingState, type RepositoryOptions, type RoomChatMessage, type RoomDriverFactory, type RoomDriverHandlers, type RoomEngine, type RoomEngineOptions, type RoomEventOutcome, type RoomEventTopic, type RoomName, type RoomPhase, type RoomReaction, type RoomToken, type RoomTokenStorage, type RsvpAnswer, type RsvpInvitation, type RsvpState, type ScheduleMeetingInput, type Stage, type StageArgs, type StageLayout, TABLES, TRANSCRIPTION_ATTRIBUTES, TRANSCRIPTION_TOPIC, type TokenClient, type TokenClientOptions, type TokenRequest, type TranscriptBlock, type TranscriptFormat, type TranscriptMatch, type TranscriptSegment, type TranscriptSource, type UpcomingOccurrence, type UserId, type VideoEffect, type WrapUpAnnouncement, type WrapUpStatus, absenceSentence, activeWrapUpSummary, announceMeeting, applyRoomEvent, asCallId, asMeetingId, asOrganizationId, asParticipantIdentity, asRoomName, asUserId, attendanceCsv, attendanceReport, attendanceTotals, callInviteAction, callInviteText, callStateLabel, canModerate, canModerateParticipant, canTransition, captionSegment, changesPatch, clockPosition, computeStage, countLabel, createCallCenter, createCallInviteHandler, createDeviceManager, createInRoomClient, createLiveKitDriver, createMeetAi, createMeetApi, createMeetRepository, createMeetStore, createMeetingInviteHandler, createMeetingSession, createMemoryDeviceStorage, createRecordingController, createRoomEngine, createTokenClient, createWebDeviceStorage, createWebEffectsStorage, createWebRoomTokenStorage, displayNameFor, fileDownloadPath, gridColumns, groupTranscript, guestRecordAccessExplanation, guestRecordAccessLabel, guestRecordAccessSetting, hasEnded, hostUserIds, invalidResponse, isGuest, isGuestIdentity, isHostRole, isListenOnly, isNoteTaker, isRealName, isRoomEventTopic, learnName, learnNames, listenOnlyNotice, loadFollowUpDraft, loadGuestMeetingRecord, loadMeetingChat, loadMeetingRecord, mapConnectionState, mapQuality, meetingInviteAction, meetingLength, meetingLink, meetingPath, meetingSlug, meetingTopic, meetingWhen, mergeCaption, mergeRecord, normalizeDeviceError, normalizeMeetError, normalizeSpoken, noteTakerIdentity, noteTakerLabel, noteTakerParticipant, noteTakerStatus, notesDocument, orderParticipants, parseRoomToken, participantSummary, playableRecordingFileId, projectInvitee, projectLibraryRecording, projectNote, projectOccurrence, projectOverride, projectParticipant, projectRsvpInvitation, projectSearchHit, projectSegment, projectUpcoming, pushMeetingToGoogleCalendar, readServerRefusal, readableTranscript, recordingLabel, recordingNotice, recordingOffsetMs, roleOf, roomTopic, searchTranscript, sendFollowUp, setGuestRecordAccess, settingsPatch, snapshotParticipant, snippetRuns, summarizeMeetingRecordRestrictions, transcriptDocument, unavailableFrom, userTopic, wasRefused, wrapUpStatus };
3288
+ export { ATTENDANCE_CSV_HEADER, type AccessTokenSource, type AdmissionState, type AnnounceResult, type ApplyRoomEventArgs, type AskArgs, type AttendanceKind, type AttendanceRow, type AudioProcessing, CALL_INVITE_KIND, CALL_INVITE_VERSION, CONSENT_NOTICE_ATTRIBUTE, type CallCenter, type CallCenterOptions, type CallId, type CallInvite, type CallInviteHandlerOptions, type CallInvitePayload, type CallMode, type CallState, type CallablePerson, type ConnectionQuality, type CreateCallInviteInput, type CreateMeetingInput, DATA_TOPICS, DEFAULT_EFFECTS, DEFAULT_PAGE_SIZE, type DataTopic, type DeviceKind, type DeviceManager, type DeviceManagerOptions, type DeviceSnapshot, type DeviceStorage, type DriverConnectionState, type DriverParticipant, type DriverTrackKind, type DriverTranscription, END_MEETING_NOT_SERVED, type EffectsStorage, type EndMeetingResult, FILE_SESSION_PATH, type FollowUpDraft, type FollowUpRecipient, type FollowUpSendResult, GUEST_RECORD_ACCESS_CHOICES, GUEST_RECORD_ACCESS_LEVELS, GUEST_RECORD_ACCESS_METADATA_KEY, GUEST_RECORD_NOT_SHARED, type GuestRecordAccess, type GuestRecordAccessResolution, type GuestRecordAccessSetting, IDLE_MEDIA, IDLE_TRACK, type InRoomClient, type InRoomClientOptions, type InviteeInput, type InviteeRole, type JoinRequest, type JsonObject, type JsonValue, LISTEN_ONLY_NOTICE, type LibraryRecording, type LiveKitDriverOptions, type LobbyEntry, type LocalMediaState, type LocalTrackState, MEETING_INVITE_KIND, MEETING_INVITE_VERSION, MEET_ANSWER_CONTEXT_EVENT, MEET_ANSWER_EVENTS, MEET_EVENTS, MEET_ROUTES, MEET_SCHEMA, MODERATION_ACTIONS, type MediaDevicesLike, type MediaEffects, type MediaUnavailable, type MeetAi, type MeetAiAnswer, type MeetAiOptions, type MeetAnswerCoverage, type MeetApi, type MeetApiOptions, type MeetApiRequest, type MeetDevice, MeetError, type MeetErrorCode, type MeetEvent, type MeetFileMedia, type MeetGrants, type MeetIdentity, type MeetParticipant, type MeetRepository, type MeetRoomDriver, type MeetSnapshot, type MeetStore, type MeetingAttendee, type MeetingChanges, type MeetingChatHistory, type MeetingId, type MeetingInviteHandlerOptions, type MeetingInvitePayload, type MeetingInvitee, type MeetingKind, type MeetingNote, type MeetingNoteKind, type MeetingOccurrence, type MeetingRecord, type MeetingRecordBundle, type MeetingRecordRestriction, type MeetingRecordRestrictionNotice, type MeetingSearchHit, type MeetingSearchSource, type MeetingSession, type MeetingSessionOptions, type MeetingSettings, type ModerationAction, type ModerationNotice, type ModerationRequest, type ModerationResult, NOTE_TAKER_IDENTITY_PREFIX, NOTE_TAKER_METADATA_KEY, NO_GRANTS, type NameBook, type NoteTakerDispatch, type NoteTakerRefusal, type NoteTakerState, type NoteTakerStatus, ORGANIZATION_HEADER, type OccurrenceOverride, type OccurrenceState, type OrganizationId, PARTICIPANT_CAN_RECORD_ATTRIBUTE, PARTICIPANT_ROLE_ATTRIBUTE, type ParticipantIdentity, type ParticipantRole, REACTION_TTL_MS, REFUSED_ABSENCE, ROLE_RANK, ROOM_EVENTS, ROOM_EVENT_PREFIX, ROOM_TOKEN_HEADER, RPCS, type RecordingController, type RecordingControllerOptions, type RecordingPolicy, type RecordingRecord, type RecordingState, type RepositoryOptions, type RoomChatMessage, type RoomDriverFactory, type RoomDriverHandlers, type RoomEngine, type RoomEngineOptions, type RoomEventOutcome, type RoomEventTopic, type RoomName, type RoomPhase, type RoomReaction, type RoomToken, type RoomTokenStorage, type RsvpAnswer, type RsvpInvitation, type RsvpState, type ScheduleMeetingInput, type Stage, type StageArgs, type StageLayout, TABLES, TRANSCRIPTION_ATTRIBUTES, TRANSCRIPTION_TOPIC, type TokenClient, type TokenClientOptions, type TokenRequest, type TranscriptBlock, type TranscriptFormat, type TranscriptMatch, type TranscriptSegment, type TranscriptSource, type UpcomingOccurrence, type UserId, type VideoEffect, type WrapUpAnnouncement, type WrapUpStatus, absenceSentence, activeWrapUpSummary, announceMeeting, applyRoomEvent, asCallId, asMeetingId, asOrganizationId, asParticipantIdentity, asRoomName, asUserId, attendanceCsv, attendanceReport, attendanceTotals, attendeeKey, callInviteAction, callInviteText, callStateLabel, canModerate, canModerateParticipant, canTransition, captionSegment, changesPatch, clockPosition, computeStage, countLabel, createCallCenter, createCallInviteHandler, createDeviceManager, createInRoomClient, createLiveKitDriver, createMeetAi, createMeetApi, createMeetRepository, createMeetStore, createMeetingInviteHandler, createMeetingSession, createMemoryDeviceStorage, createRecordingController, createRoomEngine, createTokenClient, createWebDeviceStorage, createWebEffectsStorage, createWebRoomTokenStorage, displayNameFor, fileDownloadPath, gridColumns, groupTranscript, guestRecordAccessExplanation, guestRecordAccessLabel, guestRecordAccessSetting, hasEnded, hostUserIds, invalidResponse, isGuest, isGuestIdentity, isHostRole, isListenOnly, isNoteTaker, isRealName, isRoomEventTopic, learnName, learnNames, listenOnlyNotice, loadFollowUpDraft, loadGuestMeetingRecord, loadMeetingChat, loadMeetingRecord, mapConnectionState, mapQuality, meetingInviteAction, meetingLength, meetingLink, meetingPath, meetingSlug, meetingTopic, meetingWhen, mergeCaption, mergeRecord, normalizeDeviceError, normalizeMeetError, normalizeSpoken, noteTakerIdentity, noteTakerLabel, noteTakerParticipant, noteTakerStatus, notesDocument, orderParticipants, parseRoomToken, participantSummary, playableRecordingFileId, projectInvitee, projectLibraryRecording, projectNote, projectOccurrence, projectOverride, projectParticipant, projectRsvpInvitation, projectSearchHit, projectSegment, projectUpcoming, pushMeetingToGoogleCalendar, readServerRefusal, readableTranscript, recordingLabel, recordingNotice, recordingOffsetMs, roleOf, roomTopic, searchTranscript, sendFollowUp, setGuestRecordAccess, settingsPatch, snapshotParticipant, snippetRuns, summarizeMeetingRecordRestrictions, transcriptDocument, unavailableFrom, uniqueAttendees, userTopic, wasRefused, wrapUpStatus };
package/dist/index.d.ts CHANGED
@@ -605,6 +605,55 @@ declare function createMeetApi(options: MeetApiOptions): MeetApi;
605
605
  /** `GET /files/{id}/download?inline=1` — the platform files route (R3). */
606
606
  declare function fileDownloadPath(fileId: string): string;
607
607
 
608
+ /**
609
+ * ONE error classification for the whole package (C22).
610
+ *
611
+ * The banned alternative is a host catching a LiveKit or PostgREST error and
612
+ * deciding for itself whether the camera is busy, the token expired, or the
613
+ * meeting is locked — which is how the same five-branch `if` gets copy-pasted
614
+ * into every consumer and drifts. Everything this package throws is a
615
+ * `MeetError` with a stable `code` and a `remedy` SENTENCE. Nothing fails
616
+ * silently, and nothing fails without saying what to do about it.
617
+ *
618
+ * The device codes exist because "it doesn't work" in a video product is almost
619
+ * always one of four specific, differently-remediable things: permission
620
+ * denied, no such device, device already in use by another app, or insecure
621
+ * context (http, where `getUserMedia` does not exist at all). A single
622
+ * "media-error" would make the UI say the wrong sentence three times out of
623
+ * four.
624
+ */
625
+ type MeetErrorCode = "session-unavailable" | "forbidden" | "not-found" | "conflict" | "token" | "transport" | "invalid-response" | "misconfigured" | "permission-denied" | "device-not-found" | "device-in-use" | "insecure-context" | "media-unsupported" | "room-locked" | "lobby-denied" | "capacity"
626
+ /** Meet wave 1: the meeting was cancelled — its link resolves, its room never opens. */
627
+ | "cancelled" | "unknown";
628
+ declare class MeetError extends Error {
629
+ readonly code: MeetErrorCode;
630
+ /** What to DO. Rendered to the user for the device codes. */
631
+ readonly remedy: string;
632
+ readonly cause?: unknown;
633
+ constructor(code: MeetErrorCode, message: string, remedy: string, cause?: unknown);
634
+ /** True when retrying after the host re-establishes a session is the fix. */
635
+ get isRetryable(): boolean;
636
+ /** True when the user, not the code, must act — the UI shows `remedy`. */
637
+ get isUserActionable(): boolean;
638
+ }
639
+ /**
640
+ * THE ONE PLACE a raw database/transport error becomes a typed one. Called at
641
+ * every repository boundary; nothing else in the package inspects a raw error,
642
+ * and no consumer should ever have to.
643
+ */
644
+ declare function normalizeMeetError(error: unknown, operation: string): MeetError;
645
+ /**
646
+ * THE DEVICE ERROR TRANSLATOR — the second-most-copied block in every video app.
647
+ *
648
+ * `getUserMedia` rejects with DOMException names, and every one of them means
649
+ * something a user could fix if we told them. This is the whole reason the
650
+ * device layer lives in the package (C22 test 3: less-than-perfect unless done
651
+ * perfectly).
652
+ */
653
+ declare function normalizeDeviceError(error: unknown, operation: string): MeetError;
654
+ /** A response whose SHAPE is wrong — the ingress boundary, not the wire. */
655
+ declare function invalidResponse(operation: string, detail: string): MeetError;
656
+
608
657
  /**
609
658
  * WHO SAID THAT — one answer, every surface, both lanes (MRI-A16).
610
659
  *
@@ -666,55 +715,6 @@ declare function learnNames(book: NameBook, entries: readonly {
666
715
  */
667
716
  declare function displayNameFor(book: NameBook, identity: ParticipantIdentity | string, preferred?: string | null | undefined): string;
668
717
 
669
- /**
670
- * ONE error classification for the whole package (C22).
671
- *
672
- * The banned alternative is a host catching a LiveKit or PostgREST error and
673
- * deciding for itself whether the camera is busy, the token expired, or the
674
- * meeting is locked — which is how the same five-branch `if` gets copy-pasted
675
- * into every consumer and drifts. Everything this package throws is a
676
- * `MeetError` with a stable `code` and a `remedy` SENTENCE. Nothing fails
677
- * silently, and nothing fails without saying what to do about it.
678
- *
679
- * The device codes exist because "it doesn't work" in a video product is almost
680
- * always one of four specific, differently-remediable things: permission
681
- * denied, no such device, device already in use by another app, or insecure
682
- * context (http, where `getUserMedia` does not exist at all). A single
683
- * "media-error" would make the UI say the wrong sentence three times out of
684
- * four.
685
- */
686
- type MeetErrorCode = "session-unavailable" | "forbidden" | "not-found" | "conflict" | "token" | "transport" | "invalid-response" | "misconfigured" | "permission-denied" | "device-not-found" | "device-in-use" | "insecure-context" | "media-unsupported" | "room-locked" | "lobby-denied" | "capacity"
687
- /** Meet wave 1: the meeting was cancelled — its link resolves, its room never opens. */
688
- | "cancelled" | "unknown";
689
- declare class MeetError extends Error {
690
- readonly code: MeetErrorCode;
691
- /** What to DO. Rendered to the user for the device codes. */
692
- readonly remedy: string;
693
- readonly cause?: unknown;
694
- constructor(code: MeetErrorCode, message: string, remedy: string, cause?: unknown);
695
- /** True when retrying after the host re-establishes a session is the fix. */
696
- get isRetryable(): boolean;
697
- /** True when the user, not the code, must act — the UI shows `remedy`. */
698
- get isUserActionable(): boolean;
699
- }
700
- /**
701
- * THE ONE PLACE a raw database/transport error becomes a typed one. Called at
702
- * every repository boundary; nothing else in the package inspects a raw error,
703
- * and no consumer should ever have to.
704
- */
705
- declare function normalizeMeetError(error: unknown, operation: string): MeetError;
706
- /**
707
- * THE DEVICE ERROR TRANSLATOR — the second-most-copied block in every video app.
708
- *
709
- * `getUserMedia` rejects with DOMException names, and every one of them means
710
- * something a user could fix if we told them. This is the whole reason the
711
- * device layer lives in the package (C22 test 3: less-than-perfect unless done
712
- * perfectly).
713
- */
714
- declare function normalizeDeviceError(error: unknown, operation: string): MeetError;
715
- /** A response whose SHAPE is wrong — the ingress boundary, not the wire. */
716
- declare function invalidResponse(operation: string, detail: string): MeetError;
717
-
718
718
  /**
719
719
  * LISTEN-ONLY ATTENDANCE — being IN the room is never contingent on a device.
720
720
  *
@@ -995,6 +995,17 @@ interface MeetSnapshot {
995
995
  readonly failed: boolean;
996
996
  readonly at: number;
997
997
  } | null;
998
+ /**
999
+ * "Message privately" asked for from ANY per-person menu — a tile's, the
1000
+ * People panel's — and answered by the one `ControlBar` that owns the chat
1001
+ * panel (0.7.8). Through 0.7.7 only the People panel could open a private
1002
+ * chat, so the Board's tile menu (and the Room's) had no such item while the
1003
+ * People panel did: two menus for one person that disagreed.
1004
+ */
1005
+ readonly privateChatRequest: {
1006
+ readonly to: ParticipantIdentity;
1007
+ readonly at: number;
1008
+ } | null;
998
1009
  readonly effects: MediaEffects;
999
1010
  /**
1000
1011
  * Captions AND durable rows, reconciled into one list (D16). A record
@@ -1177,6 +1188,7 @@ declare const MEET_ANSWER_EVENTS: {
1177
1188
  };
1178
1189
  /** The `info` event carrying what the answer was built from. */
1179
1190
  declare const MEET_ANSWER_CONTEXT_EVENT = "meet_intelligence_context";
1191
+
1180
1192
  interface ServerRefusal {
1181
1193
  readonly reason: string;
1182
1194
  readonly remedy: string;
@@ -2898,12 +2910,30 @@ interface AttendanceRow {
2898
2910
  /** True when `durationMs` was measured to the meeting's end, not a recorded leave. */
2899
2911
  readonly durationToEnd: boolean;
2900
2912
  readonly admission: MeetingAttendee["admissionState"];
2913
+ /** How many times this person came in (a rejoin or a second device). */
2914
+ readonly joins: number;
2901
2915
  }
2902
2916
  /**
2903
2917
  * The attendance report of ONE meeting, host first then by arrival. People who
2904
2918
  * knocked and were never let in are kept (with no join time) — "who asked to
2905
2919
  * come in" is part of the record — but a denied knock has no duration.
2906
2920
  */
2921
+ /**
2922
+ * WHO a participant row is, as a PERSON (verifier, 2026-09-27: an export listed
2923
+ * the same attendee twice under "attended"). A signed-in person is their
2924
+ * account — every device and every rejoin is one person. A guest without an
2925
+ * account gets a fresh `guest:<random>` identity on every join, so the name
2926
+ * they typed is the only thread between their joins (Zoom's attendee report
2927
+ * merges link guests the same way); two different accountless guests who
2928
+ * typed the identical name read as one, which is the lesser error.
2929
+ */
2930
+ declare function attendeeKey(person: MeetingAttendee, names?: NameBook): string;
2931
+ /**
2932
+ * One row per PERSON, in first-seen order: the row that actually joined (the
2933
+ * earliest) represents them. For a list of names or a head-count; the
2934
+ * attendance REPORT merges times as well (`attendanceReport`).
2935
+ */
2936
+ declare function uniqueAttendees(attendees: readonly MeetingAttendee[], names?: NameBook): readonly MeetingAttendee[];
2907
2937
  declare function attendanceReport(meeting: MeetingRecord, attendees: readonly MeetingAttendee[], names?: NameBook): readonly AttendanceRow[];
2908
2938
  /** Headline numbers for the top of a report. The assistant is never a person. */
2909
2939
  declare function attendanceTotals(rows: readonly AttendanceRow[]): {
@@ -3255,4 +3285,4 @@ interface InRoomClientOptions {
3255
3285
  }
3256
3286
  declare function createInRoomClient(options: InRoomClientOptions): InRoomClient;
3257
3287
 
3258
- export { ATTENDANCE_CSV_HEADER, type AccessTokenSource, type AdmissionState, type AnnounceResult, type ApplyRoomEventArgs, type AskArgs, type AttendanceKind, type AttendanceRow, type AudioProcessing, CALL_INVITE_KIND, CALL_INVITE_VERSION, CONSENT_NOTICE_ATTRIBUTE, type CallCenter, type CallCenterOptions, type CallId, type CallInvite, type CallInviteHandlerOptions, type CallInvitePayload, type CallMode, type CallState, type CallablePerson, type ConnectionQuality, type CreateCallInviteInput, type CreateMeetingInput, DATA_TOPICS, DEFAULT_EFFECTS, DEFAULT_PAGE_SIZE, type DataTopic, type DeviceKind, type DeviceManager, type DeviceManagerOptions, type DeviceSnapshot, type DeviceStorage, type DriverConnectionState, type DriverParticipant, type DriverTrackKind, type DriverTranscription, END_MEETING_NOT_SERVED, type EffectsStorage, type EndMeetingResult, FILE_SESSION_PATH, type FollowUpDraft, type FollowUpRecipient, type FollowUpSendResult, GUEST_RECORD_ACCESS_CHOICES, GUEST_RECORD_ACCESS_LEVELS, GUEST_RECORD_ACCESS_METADATA_KEY, GUEST_RECORD_NOT_SHARED, type GuestRecordAccess, type GuestRecordAccessResolution, type GuestRecordAccessSetting, IDLE_MEDIA, IDLE_TRACK, type InRoomClient, type InRoomClientOptions, type InviteeInput, type InviteeRole, type JoinRequest, type JsonObject, type JsonValue, LISTEN_ONLY_NOTICE, type LibraryRecording, type LiveKitDriverOptions, type LobbyEntry, type LocalMediaState, type LocalTrackState, MEETING_INVITE_KIND, MEETING_INVITE_VERSION, MEET_ANSWER_CONTEXT_EVENT, MEET_ANSWER_EVENTS, MEET_EVENTS, MEET_ROUTES, MEET_SCHEMA, MODERATION_ACTIONS, type MediaDevicesLike, type MediaEffects, type MediaUnavailable, type MeetAi, type MeetAiAnswer, type MeetAiOptions, type MeetAnswerCoverage, type MeetApi, type MeetApiOptions, type MeetApiRequest, type MeetDevice, MeetError, type MeetErrorCode, type MeetEvent, type MeetFileMedia, type MeetGrants, type MeetIdentity, type MeetParticipant, type MeetRepository, type MeetRoomDriver, type MeetSnapshot, type MeetStore, type MeetingAttendee, type MeetingChanges, type MeetingChatHistory, type MeetingId, type MeetingInviteHandlerOptions, type MeetingInvitePayload, type MeetingInvitee, type MeetingKind, type MeetingNote, type MeetingNoteKind, type MeetingOccurrence, type MeetingRecord, type MeetingRecordBundle, type MeetingRecordRestriction, type MeetingRecordRestrictionNotice, type MeetingSearchHit, type MeetingSearchSource, type MeetingSession, type MeetingSessionOptions, type MeetingSettings, type ModerationAction, type ModerationNotice, type ModerationRequest, type ModerationResult, NOTE_TAKER_IDENTITY_PREFIX, NOTE_TAKER_METADATA_KEY, NO_GRANTS, type NameBook, type NoteTakerDispatch, type NoteTakerRefusal, type NoteTakerState, type NoteTakerStatus, ORGANIZATION_HEADER, type OccurrenceOverride, type OccurrenceState, type OrganizationId, PARTICIPANT_CAN_RECORD_ATTRIBUTE, PARTICIPANT_ROLE_ATTRIBUTE, type ParticipantIdentity, type ParticipantRole, REACTION_TTL_MS, REFUSED_ABSENCE, ROLE_RANK, ROOM_EVENTS, ROOM_EVENT_PREFIX, ROOM_TOKEN_HEADER, RPCS, type RecordingController, type RecordingControllerOptions, type RecordingPolicy, type RecordingRecord, type RecordingState, type RepositoryOptions, type RoomChatMessage, type RoomDriverFactory, type RoomDriverHandlers, type RoomEngine, type RoomEngineOptions, type RoomEventOutcome, type RoomEventTopic, type RoomName, type RoomPhase, type RoomReaction, type RoomToken, type RoomTokenStorage, type RsvpAnswer, type RsvpInvitation, type RsvpState, type ScheduleMeetingInput, type Stage, type StageArgs, type StageLayout, TABLES, TRANSCRIPTION_ATTRIBUTES, TRANSCRIPTION_TOPIC, type TokenClient, type TokenClientOptions, type TokenRequest, type TranscriptBlock, type TranscriptFormat, type TranscriptMatch, type TranscriptSegment, type TranscriptSource, type UpcomingOccurrence, type UserId, type VideoEffect, type WrapUpAnnouncement, type WrapUpStatus, absenceSentence, activeWrapUpSummary, announceMeeting, applyRoomEvent, asCallId, asMeetingId, asOrganizationId, asParticipantIdentity, asRoomName, asUserId, attendanceCsv, attendanceReport, attendanceTotals, callInviteAction, callInviteText, callStateLabel, canModerate, canModerateParticipant, canTransition, captionSegment, changesPatch, clockPosition, computeStage, countLabel, createCallCenter, createCallInviteHandler, createDeviceManager, createInRoomClient, createLiveKitDriver, createMeetAi, createMeetApi, createMeetRepository, createMeetStore, createMeetingInviteHandler, createMeetingSession, createMemoryDeviceStorage, createRecordingController, createRoomEngine, createTokenClient, createWebDeviceStorage, createWebEffectsStorage, createWebRoomTokenStorage, displayNameFor, fileDownloadPath, gridColumns, groupTranscript, guestRecordAccessExplanation, guestRecordAccessLabel, guestRecordAccessSetting, hasEnded, hostUserIds, invalidResponse, isGuest, isGuestIdentity, isHostRole, isListenOnly, isNoteTaker, isRealName, isRoomEventTopic, learnName, learnNames, listenOnlyNotice, loadFollowUpDraft, loadGuestMeetingRecord, loadMeetingChat, loadMeetingRecord, mapConnectionState, mapQuality, meetingInviteAction, meetingLength, meetingLink, meetingPath, meetingSlug, meetingTopic, meetingWhen, mergeCaption, mergeRecord, normalizeDeviceError, normalizeMeetError, normalizeSpoken, noteTakerIdentity, noteTakerLabel, noteTakerParticipant, noteTakerStatus, notesDocument, orderParticipants, parseRoomToken, participantSummary, playableRecordingFileId, projectInvitee, projectLibraryRecording, projectNote, projectOccurrence, projectOverride, projectParticipant, projectRsvpInvitation, projectSearchHit, projectSegment, projectUpcoming, pushMeetingToGoogleCalendar, readServerRefusal, readableTranscript, recordingLabel, recordingNotice, recordingOffsetMs, roleOf, roomTopic, searchTranscript, sendFollowUp, setGuestRecordAccess, settingsPatch, snapshotParticipant, snippetRuns, summarizeMeetingRecordRestrictions, transcriptDocument, unavailableFrom, userTopic, wasRefused, wrapUpStatus };
3288
+ export { ATTENDANCE_CSV_HEADER, type AccessTokenSource, type AdmissionState, type AnnounceResult, type ApplyRoomEventArgs, type AskArgs, type AttendanceKind, type AttendanceRow, type AudioProcessing, CALL_INVITE_KIND, CALL_INVITE_VERSION, CONSENT_NOTICE_ATTRIBUTE, type CallCenter, type CallCenterOptions, type CallId, type CallInvite, type CallInviteHandlerOptions, type CallInvitePayload, type CallMode, type CallState, type CallablePerson, type ConnectionQuality, type CreateCallInviteInput, type CreateMeetingInput, DATA_TOPICS, DEFAULT_EFFECTS, DEFAULT_PAGE_SIZE, type DataTopic, type DeviceKind, type DeviceManager, type DeviceManagerOptions, type DeviceSnapshot, type DeviceStorage, type DriverConnectionState, type DriverParticipant, type DriverTrackKind, type DriverTranscription, END_MEETING_NOT_SERVED, type EffectsStorage, type EndMeetingResult, FILE_SESSION_PATH, type FollowUpDraft, type FollowUpRecipient, type FollowUpSendResult, GUEST_RECORD_ACCESS_CHOICES, GUEST_RECORD_ACCESS_LEVELS, GUEST_RECORD_ACCESS_METADATA_KEY, GUEST_RECORD_NOT_SHARED, type GuestRecordAccess, type GuestRecordAccessResolution, type GuestRecordAccessSetting, IDLE_MEDIA, IDLE_TRACK, type InRoomClient, type InRoomClientOptions, type InviteeInput, type InviteeRole, type JoinRequest, type JsonObject, type JsonValue, LISTEN_ONLY_NOTICE, type LibraryRecording, type LiveKitDriverOptions, type LobbyEntry, type LocalMediaState, type LocalTrackState, MEETING_INVITE_KIND, MEETING_INVITE_VERSION, MEET_ANSWER_CONTEXT_EVENT, MEET_ANSWER_EVENTS, MEET_EVENTS, MEET_ROUTES, MEET_SCHEMA, MODERATION_ACTIONS, type MediaDevicesLike, type MediaEffects, type MediaUnavailable, type MeetAi, type MeetAiAnswer, type MeetAiOptions, type MeetAnswerCoverage, type MeetApi, type MeetApiOptions, type MeetApiRequest, type MeetDevice, MeetError, type MeetErrorCode, type MeetEvent, type MeetFileMedia, type MeetGrants, type MeetIdentity, type MeetParticipant, type MeetRepository, type MeetRoomDriver, type MeetSnapshot, type MeetStore, type MeetingAttendee, type MeetingChanges, type MeetingChatHistory, type MeetingId, type MeetingInviteHandlerOptions, type MeetingInvitePayload, type MeetingInvitee, type MeetingKind, type MeetingNote, type MeetingNoteKind, type MeetingOccurrence, type MeetingRecord, type MeetingRecordBundle, type MeetingRecordRestriction, type MeetingRecordRestrictionNotice, type MeetingSearchHit, type MeetingSearchSource, type MeetingSession, type MeetingSessionOptions, type MeetingSettings, type ModerationAction, type ModerationNotice, type ModerationRequest, type ModerationResult, NOTE_TAKER_IDENTITY_PREFIX, NOTE_TAKER_METADATA_KEY, NO_GRANTS, type NameBook, type NoteTakerDispatch, type NoteTakerRefusal, type NoteTakerState, type NoteTakerStatus, ORGANIZATION_HEADER, type OccurrenceOverride, type OccurrenceState, type OrganizationId, PARTICIPANT_CAN_RECORD_ATTRIBUTE, PARTICIPANT_ROLE_ATTRIBUTE, type ParticipantIdentity, type ParticipantRole, REACTION_TTL_MS, REFUSED_ABSENCE, ROLE_RANK, ROOM_EVENTS, ROOM_EVENT_PREFIX, ROOM_TOKEN_HEADER, RPCS, type RecordingController, type RecordingControllerOptions, type RecordingPolicy, type RecordingRecord, type RecordingState, type RepositoryOptions, type RoomChatMessage, type RoomDriverFactory, type RoomDriverHandlers, type RoomEngine, type RoomEngineOptions, type RoomEventOutcome, type RoomEventTopic, type RoomName, type RoomPhase, type RoomReaction, type RoomToken, type RoomTokenStorage, type RsvpAnswer, type RsvpInvitation, type RsvpState, type ScheduleMeetingInput, type Stage, type StageArgs, type StageLayout, TABLES, TRANSCRIPTION_ATTRIBUTES, TRANSCRIPTION_TOPIC, type TokenClient, type TokenClientOptions, type TokenRequest, type TranscriptBlock, type TranscriptFormat, type TranscriptMatch, type TranscriptSegment, type TranscriptSource, type UpcomingOccurrence, type UserId, type VideoEffect, type WrapUpAnnouncement, type WrapUpStatus, absenceSentence, activeWrapUpSummary, announceMeeting, applyRoomEvent, asCallId, asMeetingId, asOrganizationId, asParticipantIdentity, asRoomName, asUserId, attendanceCsv, attendanceReport, attendanceTotals, attendeeKey, callInviteAction, callInviteText, callStateLabel, canModerate, canModerateParticipant, canTransition, captionSegment, changesPatch, clockPosition, computeStage, countLabel, createCallCenter, createCallInviteHandler, createDeviceManager, createInRoomClient, createLiveKitDriver, createMeetAi, createMeetApi, createMeetRepository, createMeetStore, createMeetingInviteHandler, createMeetingSession, createMemoryDeviceStorage, createRecordingController, createRoomEngine, createTokenClient, createWebDeviceStorage, createWebEffectsStorage, createWebRoomTokenStorage, displayNameFor, fileDownloadPath, gridColumns, groupTranscript, guestRecordAccessExplanation, guestRecordAccessLabel, guestRecordAccessSetting, hasEnded, hostUserIds, invalidResponse, isGuest, isGuestIdentity, isHostRole, isListenOnly, isNoteTaker, isRealName, isRoomEventTopic, learnName, learnNames, listenOnlyNotice, loadFollowUpDraft, loadGuestMeetingRecord, loadMeetingChat, loadMeetingRecord, mapConnectionState, mapQuality, meetingInviteAction, meetingLength, meetingLink, meetingPath, meetingSlug, meetingTopic, meetingWhen, mergeCaption, mergeRecord, normalizeDeviceError, normalizeMeetError, normalizeSpoken, noteTakerIdentity, noteTakerLabel, noteTakerParticipant, noteTakerStatus, notesDocument, orderParticipants, parseRoomToken, participantSummary, playableRecordingFileId, projectInvitee, projectLibraryRecording, projectNote, projectOccurrence, projectOverride, projectParticipant, projectRsvpInvitation, projectSearchHit, projectSegment, projectUpcoming, pushMeetingToGoogleCalendar, readServerRefusal, readableTranscript, recordingLabel, recordingNotice, recordingOffsetMs, roleOf, roomTopic, searchTranscript, sendFollowUp, setGuestRecordAccess, settingsPatch, snapshotParticipant, snippetRuns, summarizeMeetingRecordRestrictions, transcriptDocument, unavailableFrom, uniqueAttendees, userTopic, wasRefused, wrapUpStatus };