@palbase/web 1.6.1 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -825,6 +825,49 @@ interface ChatMessage {
825
825
  * Mirrors iOS `ChatMessage.effectiveExpiry` (which it derives from).
826
826
  */
827
827
  readonly expiresAt: Date | null;
828
+ /**
829
+ * Server-metadata cluster — the double-tick DELIVERED watermark on THIS user's OWN
830
+ * (`direction === 'outgoing'`) messages, FOLDED TO USER-LEVEL. The wire carries the
831
+ * acking device_id; the SDK folds across a peer's devices and across peers to ONE
832
+ * user-level server_seq (MONOTONIC max — a stale lower incoming tick NEVER lowers it).
833
+ * A per-message tick is "is `message.serverSeq <= deliveredUpTo`?". Absent (`undefined`)
834
+ * until a `delivered` conv event covers this message; never set on an incoming message.
835
+ * Mirrors iOS `Chat.deliveredUpTo` (a chat-level scalar there; per-message here).
836
+ */
837
+ readonly deliveredUpTo?: number;
838
+ /**
839
+ * Server-metadata cluster — the double-tick READ watermark on THIS user's OWN
840
+ * (`direction === 'outgoing'`) messages, FOLDED TO USER-LEVEL + MONOTONIC max (same
841
+ * fold as `deliveredUpTo`). Set by a `read` conv event. Read STAYS gated by the peer's
842
+ * `share_receipts` server-side (the broadcast simply never arrives when muted); the
843
+ * client fold is identical to delivered. Mirrors iOS `Chat.readUpTo`.
844
+ */
845
+ readonly readUpTo?: number;
846
+ }
847
+ /**
848
+ * The per-(user, group) notify scope (the server-metadata MUTE toggle). `'all'`
849
+ * (default, absent row) fires the push wake; `'none'` (muted) suppresses it. The raw
850
+ * wire value is the snake-free `"all"`/`"none"` string. An unknown/garbage server value
851
+ * maps to `'all'` at the surface — fail-OPEN, never silently mutes (mirrors iOS
852
+ * `NotifyScope`). The server stores this opaque enum and stays MLS-blind (no content).
853
+ */
854
+ type NotifyScope = 'all' | 'none';
855
+ /**
856
+ * The caller's OWN unread view (the `GET /v1/messaging/groups/{gid}/unread` response).
857
+ * Every field is an OPAQUE server-metadata integer (no message content): the group's max
858
+ * server_seq, this caller's read + delivered cursors, and the server-derived unread
859
+ * count. The camelCase mirror of the snake_case wire (`group_max_seq` → `groupMaxSeq`,
860
+ * etc). Mirrors iOS `UnreadView`.
861
+ */
862
+ interface UnreadView {
863
+ /** The highest server_seq the group has reached (the newest message's seq). */
864
+ readonly groupMaxSeq: number;
865
+ /** The furthest server_seq THIS caller has marked read. */
866
+ readonly lastReadSeq: number;
867
+ /** The furthest server_seq THIS caller's devices have acked delivered. */
868
+ readonly deliveredSeq: number;
869
+ /** The server-derived unread count for this caller (clamped `>= 0` at the surface). */
870
+ readonly unreadCount: number;
828
871
  }
829
872
  /** The receipt from a send — the server's monotonic sequence + accepted epoch. */
830
873
  interface SentReceipt {
@@ -1001,7 +1044,12 @@ interface ChatBackend {
1001
1044
  registerActive(group: MessagingGroup): void;
1002
1045
  setTyping(group: MessagingGroup, isTyping: boolean): void;
1003
1046
  markRead(group: MessagingGroup, upToServerSeq: number): Promise<void>;
1004
- /** Subscribe live message + conv (presence/typing/read) for an active group. */
1047
+ /** Server-metadata cluster: set/get the per-(user,group) notify scope (mute) and
1048
+ * fetch the caller's own unread view. The server stays MLS-blind (opaque metadata). */
1049
+ setNotifyScope(group: MessagingGroup, scope: NotifyScope): Promise<NotifyScope>;
1050
+ getNotifyScope(group: MessagingGroup): Promise<NotifyScope>;
1051
+ unread(group: MessagingGroup): Promise<UnreadView>;
1052
+ /** Subscribe live message + conv (presence/typing/read/delivered) for an active group. */
1005
1053
  subscribeLive(group: MessagingGroup, chat: Chat): Unsubscribe$1;
1006
1054
  /** Resolve a sender device id → its owning user id (for senderUserId). */
1007
1055
  userIdForDevice(group: MessagingGroup, deviceId: string): Promise<string | null>;
@@ -1306,6 +1354,20 @@ declare class Chat {
1306
1354
  leave(): Promise<void>;
1307
1355
  setTyping(isTyping: boolean): void;
1308
1356
  markRead(message: ChatMessage): Promise<void>;
1357
+ /** Set this chat's notify scope (the mute toggle). `'none'` mutes the push wake;
1358
+ * `'all'` unmutes (the default). Materializes a draft first (the scope is a
1359
+ * per-(user,group) server row), PUTs `/notify`, and returns the server-echoed scope.
1360
+ * Mirrors iOS `Chat.setNotifyScope`. */
1361
+ setNotifyScope(scope: NotifyScope): Promise<NotifyScope>;
1362
+ /** Refresh + return this chat's notify scope from the server (fail-OPEN to `'all'`).
1363
+ * Returns `'all'` for a draft chat (no server row yet). */
1364
+ getNotifyScope(): Promise<NotifyScope>;
1365
+ /** Fetch the caller's authoritative SERVER unread count (opaque server metadata).
1366
+ * Returns the clamped count (`max(0, …)`); `0` for a draft chat. The local computed
1367
+ * `unreadCount` getter stays the instant, offline best-effort badge — this is the
1368
+ * canonical count on demand. Named distinctly so it does not shadow the observable
1369
+ * `unreadCount` snapshot getter. Mirrors iOS `Chat.refreshUnread`. */
1370
+ unreadCountFromServer(): Promise<number>;
1309
1371
  /** Add an emoji reaction to a message. No-op if the message isn't reactable
1310
1372
  * (empty clientMsgId — a legacy/system row). The reaction folds locally with
1311
1373
  * the server receipt's `(epoch, serverSeq)` so the target's tally updates
@@ -1731,4 +1793,4 @@ declare class PalbeAnalytics {
1731
1793
  private post;
1732
1794
  }
1733
1795
 
1734
- export { type AnalyticsProperties as A, type PresenceState as B, Call as C, type RealtimeConnectionState as D, type RealtimeHandler as E, type FlagsView as F, type RealtimePayload as G, type RealtimeStatus as H, type RealtimeStatusSnapshot as I, type RealtimeSubscription as J, type ResolvedMention as K, type ResolvedReply as L, type MagicLinkResult as M, type PalbeRuntime as N, type OAuthExchangeResult as O, PalbeAnalytics as P, buildRuntime as Q, RealtimeChannel as R, type SentReceipt as S, type Unsubscribe as U, type AuthChangeEvent as a, type AuthState as b, type AuthSuccess as c, type AuthUser as d, type CallChangeCallback as e, type CallParticipant as f, type CallState as g, Chat as h, type ChatBackend as i, type ChatDraft as j, type ChatKind as k, type ChatMember as l, type ChatMessage as m, type ChatMessageKind as n, type ChatRole as o, type ChatState as p, type CommsPrefs as q, type MentionRange as r, type MessageDirection as s, PalbeAuth as t, PalbeCalls as u, type PalbeConfig as v, PalbeFlags as w, PalbeMessaging as x, type PalbeOAuthConfig as y, PalbeRealtime as z };
1796
+ export { type AnalyticsProperties as A, type PresenceState as B, Call as C, type RealtimeConnectionState as D, type RealtimeHandler as E, type FlagsView as F, type RealtimePayload as G, type RealtimeStatus as H, type RealtimeStatusSnapshot as I, type RealtimeSubscription as J, type ResolvedMention as K, type ResolvedReply as L, type MagicLinkResult as M, type NotifyScope as N, type OAuthExchangeResult as O, PalbeAnalytics as P, type Unsubscribe as Q, RealtimeChannel as R, type SentReceipt as S, type PalbeRuntime as T, type UnreadView as U, buildRuntime as V, type AuthChangeEvent as a, type AuthState as b, type AuthSuccess as c, type AuthUser as d, type CallChangeCallback as e, type CallParticipant as f, type CallState as g, Chat as h, type ChatBackend as i, type ChatDraft as j, type ChatKind as k, type ChatMember as l, type ChatMessage as m, type ChatMessageKind as n, type ChatRole as o, type ChatState as p, type CommsPrefs as q, type MentionRange as r, type MessageDirection as s, PalbeAuth as t, PalbeCalls as u, type PalbeConfig as v, PalbeFlags as w, PalbeMessaging as x, type PalbeOAuthConfig as y, PalbeRealtime as z };
@@ -825,6 +825,49 @@ interface ChatMessage {
825
825
  * Mirrors iOS `ChatMessage.effectiveExpiry` (which it derives from).
826
826
  */
827
827
  readonly expiresAt: Date | null;
828
+ /**
829
+ * Server-metadata cluster — the double-tick DELIVERED watermark on THIS user's OWN
830
+ * (`direction === 'outgoing'`) messages, FOLDED TO USER-LEVEL. The wire carries the
831
+ * acking device_id; the SDK folds across a peer's devices and across peers to ONE
832
+ * user-level server_seq (MONOTONIC max — a stale lower incoming tick NEVER lowers it).
833
+ * A per-message tick is "is `message.serverSeq <= deliveredUpTo`?". Absent (`undefined`)
834
+ * until a `delivered` conv event covers this message; never set on an incoming message.
835
+ * Mirrors iOS `Chat.deliveredUpTo` (a chat-level scalar there; per-message here).
836
+ */
837
+ readonly deliveredUpTo?: number;
838
+ /**
839
+ * Server-metadata cluster — the double-tick READ watermark on THIS user's OWN
840
+ * (`direction === 'outgoing'`) messages, FOLDED TO USER-LEVEL + MONOTONIC max (same
841
+ * fold as `deliveredUpTo`). Set by a `read` conv event. Read STAYS gated by the peer's
842
+ * `share_receipts` server-side (the broadcast simply never arrives when muted); the
843
+ * client fold is identical to delivered. Mirrors iOS `Chat.readUpTo`.
844
+ */
845
+ readonly readUpTo?: number;
846
+ }
847
+ /**
848
+ * The per-(user, group) notify scope (the server-metadata MUTE toggle). `'all'`
849
+ * (default, absent row) fires the push wake; `'none'` (muted) suppresses it. The raw
850
+ * wire value is the snake-free `"all"`/`"none"` string. An unknown/garbage server value
851
+ * maps to `'all'` at the surface — fail-OPEN, never silently mutes (mirrors iOS
852
+ * `NotifyScope`). The server stores this opaque enum and stays MLS-blind (no content).
853
+ */
854
+ type NotifyScope = 'all' | 'none';
855
+ /**
856
+ * The caller's OWN unread view (the `GET /v1/messaging/groups/{gid}/unread` response).
857
+ * Every field is an OPAQUE server-metadata integer (no message content): the group's max
858
+ * server_seq, this caller's read + delivered cursors, and the server-derived unread
859
+ * count. The camelCase mirror of the snake_case wire (`group_max_seq` → `groupMaxSeq`,
860
+ * etc). Mirrors iOS `UnreadView`.
861
+ */
862
+ interface UnreadView {
863
+ /** The highest server_seq the group has reached (the newest message's seq). */
864
+ readonly groupMaxSeq: number;
865
+ /** The furthest server_seq THIS caller has marked read. */
866
+ readonly lastReadSeq: number;
867
+ /** The furthest server_seq THIS caller's devices have acked delivered. */
868
+ readonly deliveredSeq: number;
869
+ /** The server-derived unread count for this caller (clamped `>= 0` at the surface). */
870
+ readonly unreadCount: number;
828
871
  }
829
872
  /** The receipt from a send — the server's monotonic sequence + accepted epoch. */
830
873
  interface SentReceipt {
@@ -1001,7 +1044,12 @@ interface ChatBackend {
1001
1044
  registerActive(group: MessagingGroup): void;
1002
1045
  setTyping(group: MessagingGroup, isTyping: boolean): void;
1003
1046
  markRead(group: MessagingGroup, upToServerSeq: number): Promise<void>;
1004
- /** Subscribe live message + conv (presence/typing/read) for an active group. */
1047
+ /** Server-metadata cluster: set/get the per-(user,group) notify scope (mute) and
1048
+ * fetch the caller's own unread view. The server stays MLS-blind (opaque metadata). */
1049
+ setNotifyScope(group: MessagingGroup, scope: NotifyScope): Promise<NotifyScope>;
1050
+ getNotifyScope(group: MessagingGroup): Promise<NotifyScope>;
1051
+ unread(group: MessagingGroup): Promise<UnreadView>;
1052
+ /** Subscribe live message + conv (presence/typing/read/delivered) for an active group. */
1005
1053
  subscribeLive(group: MessagingGroup, chat: Chat): Unsubscribe$1;
1006
1054
  /** Resolve a sender device id → its owning user id (for senderUserId). */
1007
1055
  userIdForDevice(group: MessagingGroup, deviceId: string): Promise<string | null>;
@@ -1306,6 +1354,20 @@ declare class Chat {
1306
1354
  leave(): Promise<void>;
1307
1355
  setTyping(isTyping: boolean): void;
1308
1356
  markRead(message: ChatMessage): Promise<void>;
1357
+ /** Set this chat's notify scope (the mute toggle). `'none'` mutes the push wake;
1358
+ * `'all'` unmutes (the default). Materializes a draft first (the scope is a
1359
+ * per-(user,group) server row), PUTs `/notify`, and returns the server-echoed scope.
1360
+ * Mirrors iOS `Chat.setNotifyScope`. */
1361
+ setNotifyScope(scope: NotifyScope): Promise<NotifyScope>;
1362
+ /** Refresh + return this chat's notify scope from the server (fail-OPEN to `'all'`).
1363
+ * Returns `'all'` for a draft chat (no server row yet). */
1364
+ getNotifyScope(): Promise<NotifyScope>;
1365
+ /** Fetch the caller's authoritative SERVER unread count (opaque server metadata).
1366
+ * Returns the clamped count (`max(0, …)`); `0` for a draft chat. The local computed
1367
+ * `unreadCount` getter stays the instant, offline best-effort badge — this is the
1368
+ * canonical count on demand. Named distinctly so it does not shadow the observable
1369
+ * `unreadCount` snapshot getter. Mirrors iOS `Chat.refreshUnread`. */
1370
+ unreadCountFromServer(): Promise<number>;
1309
1371
  /** Add an emoji reaction to a message. No-op if the message isn't reactable
1310
1372
  * (empty clientMsgId — a legacy/system row). The reaction folds locally with
1311
1373
  * the server receipt's `(epoch, serverSeq)` so the target's tally updates
@@ -1731,4 +1793,4 @@ declare class PalbeAnalytics {
1731
1793
  private post;
1732
1794
  }
1733
1795
 
1734
- export { type AnalyticsProperties as A, type PresenceState as B, Call as C, type RealtimeConnectionState as D, type RealtimeHandler as E, type FlagsView as F, type RealtimePayload as G, type RealtimeStatus as H, type RealtimeStatusSnapshot as I, type RealtimeSubscription as J, type ResolvedMention as K, type ResolvedReply as L, type MagicLinkResult as M, type PalbeRuntime as N, type OAuthExchangeResult as O, PalbeAnalytics as P, buildRuntime as Q, RealtimeChannel as R, type SentReceipt as S, type Unsubscribe as U, type AuthChangeEvent as a, type AuthState as b, type AuthSuccess as c, type AuthUser as d, type CallChangeCallback as e, type CallParticipant as f, type CallState as g, Chat as h, type ChatBackend as i, type ChatDraft as j, type ChatKind as k, type ChatMember as l, type ChatMessage as m, type ChatMessageKind as n, type ChatRole as o, type ChatState as p, type CommsPrefs as q, type MentionRange as r, type MessageDirection as s, PalbeAuth as t, PalbeCalls as u, type PalbeConfig as v, PalbeFlags as w, PalbeMessaging as x, type PalbeOAuthConfig as y, PalbeRealtime as z };
1796
+ export { type AnalyticsProperties as A, type PresenceState as B, Call as C, type RealtimeConnectionState as D, type RealtimeHandler as E, type FlagsView as F, type RealtimePayload as G, type RealtimeStatus as H, type RealtimeStatusSnapshot as I, type RealtimeSubscription as J, type ResolvedMention as K, type ResolvedReply as L, type MagicLinkResult as M, type NotifyScope as N, type OAuthExchangeResult as O, PalbeAnalytics as P, type Unsubscribe as Q, RealtimeChannel as R, type SentReceipt as S, type PalbeRuntime as T, type UnreadView as U, buildRuntime as V, type AuthChangeEvent as a, type AuthState as b, type AuthSuccess as c, type AuthUser as d, type CallChangeCallback as e, type CallParticipant as f, type CallState as g, Chat as h, type ChatBackend as i, type ChatDraft as j, type ChatKind as k, type ChatMember as l, type ChatMessage as m, type ChatMessageKind as n, type ChatRole as o, type ChatState as p, type CommsPrefs as q, type MentionRange as r, type MessageDirection as s, PalbeAuth as t, PalbeCalls as u, type PalbeConfig as v, PalbeFlags as w, PalbeMessaging as x, type PalbeOAuthConfig as y, PalbeRealtime as z };
@@ -2884,6 +2884,10 @@ var MessagingPaths = {
2884
2884
  groupMessages: (displayId) => `${GROUPS}/${seg(displayId)}/messages`,
2885
2885
  groupCommits: (displayId) => `${GROUPS}/${seg(displayId)}/commits`,
2886
2886
  groupRead: (displayId) => `${GROUPS}/${seg(displayId)}/read`,
2887
+ // Server-metadata cluster: the per-(user,group) notify scope (mute toggle, GET/PUT)
2888
+ // + the caller's own unread view (GET). {gid} is the grp_ display_id (M3 #7).
2889
+ groupNotify: (displayId) => `${GROUPS}/${seg(displayId)}/notify`,
2890
+ groupUnread: (displayId) => `${GROUPS}/${seg(displayId)}/unread`,
2887
2891
  deviceWelcomes: (deviceId) => `${DEVICES}/${seg(deviceId)}/welcomes`,
2888
2892
  deviceQueue: (deviceId) => `${DEVICES}/${seg(deviceId)}/queue`,
2889
2893
  deviceQueueAck: (deviceId) => `${DEVICES}/${seg(deviceId)}/queue/ack`,
@@ -4462,6 +4466,18 @@ var Chat = class {
4462
4466
  lastSeenAt: ts ? new Date(ts * 1e3) : null
4463
4467
  });
4464
4468
  this.emit();
4469
+ } else if (event === "delivered" || event === "read") {
4470
+ const seq = typeof payload.up_to_server_seq === "number" ? payload.up_to_server_seq : null;
4471
+ if (seq === null) return;
4472
+ let changed = false;
4473
+ this.messageList = this.messageList.map((m) => {
4474
+ if (m.direction !== "outgoing" || m.serverSeq > seq) return m;
4475
+ const cur = event === "delivered" ? m.deliveredUpTo ?? -1 : m.readUpTo ?? -1;
4476
+ if (seq <= cur) return m;
4477
+ changed = true;
4478
+ return event === "delivered" ? { ...m, deliveredUpTo: seq } : { ...m, readUpTo: seq };
4479
+ });
4480
+ if (changed) this.emit();
4465
4481
  }
4466
4482
  }
4467
4483
  kindOf(incoming) {
@@ -4710,6 +4726,31 @@ var Chat = class {
4710
4726
  this.readWatermark = Math.max(this.readWatermark, message.serverSeq);
4711
4727
  this.emit();
4712
4728
  }
4729
+ // ── Server-metadata cluster: notify scope (mute) + server unread ──
4730
+ /** Set this chat's notify scope (the mute toggle). `'none'` mutes the push wake;
4731
+ * `'all'` unmutes (the default). Materializes a draft first (the scope is a
4732
+ * per-(user,group) server row), PUTs `/notify`, and returns the server-echoed scope.
4733
+ * Mirrors iOS `Chat.setNotifyScope`. */
4734
+ async setNotifyScope(scope) {
4735
+ const group = await this.materializeIfNeeded();
4736
+ return this.backend.setNotifyScope(group, scope);
4737
+ }
4738
+ /** Refresh + return this chat's notify scope from the server (fail-OPEN to `'all'`).
4739
+ * Returns `'all'` for a draft chat (no server row yet). */
4740
+ async getNotifyScope() {
4741
+ if (!this._group) return "all";
4742
+ return this.backend.getNotifyScope(this._group);
4743
+ }
4744
+ /** Fetch the caller's authoritative SERVER unread count (opaque server metadata).
4745
+ * Returns the clamped count (`max(0, …)`); `0` for a draft chat. The local computed
4746
+ * `unreadCount` getter stays the instant, offline best-effort badge — this is the
4747
+ * canonical count on demand. Named distinctly so it does not shadow the observable
4748
+ * `unreadCount` snapshot getter. Mirrors iOS `Chat.refreshUnread`. */
4749
+ async unreadCountFromServer() {
4750
+ if (!this._group) return 0;
4751
+ const v = await this.backend.unread(this._group);
4752
+ return Math.max(0, v.unreadCount);
4753
+ }
4713
4754
  // ── Reactions ──
4714
4755
  /** Add an emoji reaction to a message. No-op if the message isn't reactable
4715
4756
  * (empty clientMsgId — a legacy/system row). The reaction folds locally with
@@ -5148,7 +5189,7 @@ var MessageDeliverySource = class {
5148
5189
  if (this.observed.has(group.displayId)) return;
5149
5190
  try {
5150
5191
  const channel = this.rt.realtime.channel(`messaging:conv:${group.rfcGroupId}`);
5151
- const subs = ["presence", "typing", "read"].map(
5192
+ const subs = ["presence", "typing", "read", "delivered"].map(
5152
5193
  (ev) => channel.on(ev, (payload) => {
5153
5194
  this.hub.emitConv(group.displayId, { event: ev, payload });
5154
5195
  })
@@ -5188,6 +5229,40 @@ var MessageDeliverySource = class {
5188
5229
  body: { read_seq: upToServerSeq, read_epoch: group.currentEpoch, is_private: false }
5189
5230
  });
5190
5231
  }
5232
+ // ── Server-metadata cluster: notify scope (mute) + unread (HTTP) ──
5233
+ /** PUT `/v1/messaging/groups/{gid}/notify` — set the caller's per-(user,group) notify
5234
+ * scope (`'all'`|`'none'`). The server stores the opaque enum verbatim and stays blind.
5235
+ * Returns the server-echoed scope (fail-OPEN to `'all'` on an unknown value). */
5236
+ async setNotifyScope(group, scope) {
5237
+ const res = await palbeRequest(
5238
+ this.rt,
5239
+ "PUT",
5240
+ MessagingPaths.groupNotify(group.displayId),
5241
+ { body: { notify_scope: scope } }
5242
+ );
5243
+ return res.notify_scope === "none" ? "none" : "all";
5244
+ }
5245
+ /** GET `/v1/messaging/groups/{gid}/notify` — the caller's notify scope. An absent
5246
+ * server row / unknown value reads as `'all'` (fail-OPEN — never silently mutes). */
5247
+ async getNotifyScope(group) {
5248
+ const res = await palbeRequest(
5249
+ this.rt,
5250
+ "GET",
5251
+ MessagingPaths.groupNotify(group.displayId)
5252
+ );
5253
+ return res.notify_scope === "none" ? "none" : "all";
5254
+ }
5255
+ /** GET `/v1/messaging/groups/{gid}/unread` — the caller's OWN unread view (opaque
5256
+ * server metadata). Maps the snake_case wire → the camelCase `UnreadView`. */
5257
+ async unread(group) {
5258
+ const res = await palbeRequest(this.rt, "GET", MessagingPaths.groupUnread(group.displayId));
5259
+ return {
5260
+ groupMaxSeq: res.group_max_seq,
5261
+ lastReadSeq: res.last_read_seq,
5262
+ deliveredSeq: res.delivered_seq,
5263
+ unreadCount: res.unread_count
5264
+ };
5265
+ }
5191
5266
  };
5192
5267
  function isOwnEchoOrConsumed(e) {
5193
5268
  const msg = e instanceof Error ? e.message : String(e);
@@ -7241,9 +7316,9 @@ var MessagingCoordinator = class {
7241
7316
  });
7242
7317
  return group;
7243
7318
  }
7244
- async sendText(group, text, replyTo, bodyRanges) {
7319
+ async sendText(group, text, replyTo, bodyRanges, expiry) {
7245
7320
  const r = await this.resolve();
7246
- return r.groups.sendText(group, text, replyTo, bodyRanges);
7321
+ return r.groups.sendText(group, text, replyTo, bodyRanges, expiry);
7247
7322
  }
7248
7323
  async sendReaction(group, args) {
7249
7324
  const r = await this.resolve();
@@ -7344,6 +7419,19 @@ var MessagingCoordinator = class {
7344
7419
  const r = await this.resolve();
7345
7420
  await r.source.markRead(group, upToServerSeq);
7346
7421
  }
7422
+ // ── Server-metadata cluster: notify scope (mute) + unread ──
7423
+ async setNotifyScope(group, scope) {
7424
+ const r = await this.resolve();
7425
+ return r.source.setNotifyScope(group, scope);
7426
+ }
7427
+ async getNotifyScope(group) {
7428
+ const r = await this.resolve();
7429
+ return r.source.getNotifyScope(group);
7430
+ }
7431
+ async unread(group) {
7432
+ const r = await this.resolve();
7433
+ return r.source.unread(group);
7434
+ }
7347
7435
  subscribeLive(group, chat) {
7348
7436
  let offMsg = null;
7349
7437
  let offConv = null;
@@ -8283,7 +8371,7 @@ function defaultSessionStorage(key) {
8283
8371
  }
8284
8372
 
8285
8373
  // src/version.ts
8286
- var VERSION = "1.6.1";
8374
+ var VERSION = "1.7.0";
8287
8375
 
8288
8376
  // src/runtime.ts
8289
8377
  function buildRuntime(config) {
@@ -8643,4 +8731,4 @@ export {
8643
8731
  pb,
8644
8732
  createBoundClient
8645
8733
  };
8646
- //# sourceMappingURL=chunk-EQAHM3ZJ.js.map
8734
+ //# sourceMappingURL=chunk-QRO632M7.js.map