@openmarket/rooms-client 0.1.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.
Files changed (87) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +25 -0
  3. package/dist/agent/armed-mode.d.ts +187 -0
  4. package/dist/agent/armed-mode.js +306 -0
  5. package/dist/agent/clients/common.d.ts +70 -0
  6. package/dist/agent/clients/common.js +46 -0
  7. package/dist/agent/lane-draft.d.ts +15 -0
  8. package/dist/agent/lane-draft.js +43 -0
  9. package/dist/agent/lane-prompts.d.ts +102 -0
  10. package/dist/agent/lane-prompts.js +120 -0
  11. package/dist/agent/library-context.d.ts +38 -0
  12. package/dist/agent/library-context.js +57 -0
  13. package/dist/agent/library-model.d.ts +41 -0
  14. package/dist/agent/library-model.js +173 -0
  15. package/dist/agent/room-context.d.ts +151 -0
  16. package/dist/agent/room-context.js +251 -0
  17. package/dist/agent/sidebar-model.d.ts +86 -0
  18. package/dist/agent/sidebar-model.js +162 -0
  19. package/dist/agent/topic-inbox.d.ts +119 -0
  20. package/dist/agent/topic-inbox.js +266 -0
  21. package/dist/agent/topic-view-batcher.d.ts +54 -0
  22. package/dist/agent/topic-view-batcher.js +115 -0
  23. package/dist/client.d.ts +421 -0
  24. package/dist/client.js +1428 -0
  25. package/dist/doc-reconcile.d.ts +100 -0
  26. package/dist/doc-reconcile.js +110 -0
  27. package/dist/doc-uri.d.ts +29 -0
  28. package/dist/doc-uri.js +55 -0
  29. package/dist/endpoints.d.ts +9 -0
  30. package/dist/endpoints.js +13 -0
  31. package/dist/jwt.d.ts +10 -0
  32. package/dist/jwt.js +51 -0
  33. package/dist/library-publisher.d.ts +52 -0
  34. package/dist/library-publisher.js +49 -0
  35. package/dist/merge3.d.ts +50 -0
  36. package/dist/merge3.js +280 -0
  37. package/dist/names.d.ts +6 -0
  38. package/dist/names.js +35 -0
  39. package/dist/shared/emoji-data.d.ts +22 -0
  40. package/dist/shared/emoji-data.js +8834 -0
  41. package/dist/shared/mentions.d.ts +6 -0
  42. package/dist/shared/mentions.js +32 -0
  43. package/dist/shared/rooms-protocol.d.ts +1183 -0
  44. package/dist/shared/rooms-protocol.js +160 -0
  45. package/dist/social-client.d.ts +361 -0
  46. package/dist/social-client.js +686 -0
  47. package/dist/social-types.d.ts +338 -0
  48. package/dist/social-types.js +1 -0
  49. package/dist/suggestion-attribution.d.ts +10 -0
  50. package/dist/suggestion-attribution.js +56 -0
  51. package/dist/topic-uri.d.ts +26 -0
  52. package/dist/topic-uri.js +40 -0
  53. package/dist/types.d.ts +2 -0
  54. package/dist/types.js +1 -0
  55. package/dist/version.d.ts +2 -0
  56. package/dist/version.js +2 -0
  57. package/dist/ws-client.d.ts +115 -0
  58. package/dist/ws-client.js +491 -0
  59. package/package.json +180 -0
  60. package/src/agent/armed-mode.ts +368 -0
  61. package/src/agent/clients/common.ts +91 -0
  62. package/src/agent/lane-draft.ts +47 -0
  63. package/src/agent/lane-prompts.ts +267 -0
  64. package/src/agent/library-context.ts +97 -0
  65. package/src/agent/library-model.ts +210 -0
  66. package/src/agent/room-context.ts +351 -0
  67. package/src/agent/sidebar-model.ts +235 -0
  68. package/src/agent/topic-inbox.ts +297 -0
  69. package/src/agent/topic-view-batcher.ts +134 -0
  70. package/src/client.ts +2331 -0
  71. package/src/doc-reconcile.ts +160 -0
  72. package/src/doc-uri.ts +83 -0
  73. package/src/endpoints.ts +14 -0
  74. package/src/jwt.ts +59 -0
  75. package/src/library-publisher.ts +93 -0
  76. package/src/merge3.ts +326 -0
  77. package/src/names.ts +44 -0
  78. package/src/shared/emoji-data.ts +8868 -0
  79. package/src/shared/mentions.ts +32 -0
  80. package/src/shared/rooms-protocol.ts +1339 -0
  81. package/src/social-client.ts +1287 -0
  82. package/src/social-types.ts +376 -0
  83. package/src/suggestion-attribution.ts +83 -0
  84. package/src/topic-uri.ts +64 -0
  85. package/src/types.ts +83 -0
  86. package/src/version.ts +2 -0
  87. package/src/ws-client.ts +611 -0
@@ -0,0 +1,1339 @@
1
+ export const RoomClientMessageType = {
2
+ AUTHENTICATE: "AUTHENTICATE",
3
+ CREATE_ROOM: "CREATE_ROOM",
4
+ INVITE: "INVITE",
5
+ REMOVE_MEMBER: "REMOVE_MEMBER",
6
+ SEARCH: "SEARCH",
7
+ JOIN: "JOIN",
8
+ HISTORY: "HISTORY",
9
+ PEEK: "PEEK",
10
+ LEAVE: "LEAVE",
11
+ POST: "POST",
12
+ REACT: "REACT",
13
+ EDIT: "EDIT",
14
+ DELETE: "DELETE",
15
+ THREAD: "THREAD",
16
+ PIN: "PIN",
17
+ UNPIN: "UNPIN",
18
+ PINS: "PINS",
19
+ REACTORS: "REACTORS",
20
+ REPORT: "REPORT",
21
+ MUTE: "MUTE",
22
+ KICK: "KICK",
23
+ BAN: "BAN",
24
+ ROLE_CHANGE: "ROLE_CHANGE",
25
+ SET_READ_ONLY: "SET_READ_ONLY",
26
+ AUDIT_LOG: "AUDIT_LOG",
27
+ SPACES: "SPACES",
28
+ JOIN_SPACE: "JOIN_SPACE",
29
+ READ_STATE: "READ_STATE",
30
+ SEARCH_ENTRIES: "SEARCH_ENTRIES",
31
+ WHO: "WHO",
32
+ TYPING: "TYPING",
33
+ STATUS: "STATUS",
34
+ ACK: "ACK",
35
+ PING: "PING",
36
+ FRIENDS: "FRIENDS",
37
+ DM_OPEN: "DM_OPEN",
38
+ DM_HISTORY: "DM_HISTORY",
39
+ DM_SEND: "DM_SEND",
40
+ DM_READ: "DM_READ",
41
+ TOPIC_CREATE: "TOPIC_CREATE",
42
+ TOPIC_RENAME: "TOPIC_RENAME",
43
+ TOPIC_MOVE: "TOPIC_MOVE",
44
+ TOPIC_MERGE: "TOPIC_MERGE",
45
+ TOPIC_RESOLVE: "TOPIC_RESOLVE",
46
+ TOPIC_SET_ATTENTION: "TOPIC_SET_ATTENTION",
47
+ TOPIC_LIST: "TOPIC_LIST",
48
+ } as const;
49
+
50
+ export type RoomClientMessageType =
51
+ (typeof RoomClientMessageType)[keyof typeof RoomClientMessageType];
52
+
53
+ export const RoomServerMessageType = {
54
+ AUTH_SUCCESS: "AUTH_SUCCESS",
55
+ ROOM_CREATED: "ROOM_CREATED",
56
+ ROOM_INVITED: "ROOM_INVITED",
57
+ ROOM_MEMBER_REMOVED: "ROOM_MEMBER_REMOVED",
58
+ ROOMS: "ROOMS",
59
+ BACKFILL: "BACKFILL",
60
+ HISTORY: "HISTORY",
61
+ PEEK_RESULT: "PEEK_RESULT",
62
+ MESSAGE: "MESSAGE",
63
+ ENTRY_UPDATED: "ENTRY_UPDATED",
64
+ THREAD: "THREAD",
65
+ PINS: "PINS",
66
+ REACTORS: "REACTORS",
67
+ ROOM_REPORTED: "ROOM_REPORTED",
68
+ ROOM_MUTED: "ROOM_MUTED",
69
+ ROOM_BANNED: "ROOM_BANNED",
70
+ ROOM_MEMBER_ROLE_CHANGED: "ROOM_MEMBER_ROLE_CHANGED",
71
+ ROOM_READ_ONLY_SET: "ROOM_READ_ONLY_SET",
72
+ ROOM_AUDIT_LOG: "ROOM_AUDIT_LOG",
73
+ SPACES: "SPACES",
74
+ SPACE_JOINED: "SPACE_JOINED",
75
+ SPACE_MEMBER_ADDED: "SPACE_MEMBER_ADDED",
76
+ SPACE_INVITE: "SPACE_INVITE",
77
+ ROOM_UPDATED: "ROOM_UPDATED",
78
+ SPACE_UPDATED: "SPACE_UPDATED",
79
+ READ_STATE: "READ_STATE",
80
+ SEARCH_RESULTS: "SEARCH_RESULTS",
81
+ PRESENCE: "PRESENCE",
82
+ RESYNC: "RESYNC",
83
+ PRESENCE_DELTA: "PRESENCE_DELTA",
84
+ WHO: "WHO",
85
+ TYPING: "TYPING",
86
+ ERROR: "ERROR",
87
+ PONG: "PONG",
88
+ FRIENDS: "FRIENDS",
89
+ DM_OPENED: "DM_OPENED",
90
+ DM_HISTORY: "DM_HISTORY",
91
+ DM_MESSAGE: "DM_MESSAGE",
92
+ DM_INBOX_UPDATED: "DM_INBOX_UPDATED",
93
+ TOPIC: "TOPIC",
94
+ TOPICS: "TOPICS",
95
+ TOPIC_UPDATED: "TOPIC_UPDATED",
96
+ } as const;
97
+
98
+ export function addBounded<T>(set: Set<T>, value: T, max: number): void {
99
+ set.add(value);
100
+ while (set.size > max) {
101
+ const oldest = set.values().next().value as T | undefined;
102
+ if (oldest === undefined) return;
103
+ set.delete(oldest);
104
+ }
105
+ }
106
+
107
+ export type RoomServerMessageType =
108
+ (typeof RoomServerMessageType)[keyof typeof RoomServerMessageType];
109
+
110
+ export const SUPPORTED_ROOM_PROTOCOL_VERSION = 2;
111
+
112
+ export const RoomLedgerEntryType = {
113
+ POST: "post",
114
+ SYSTEM: "system",
115
+ SYSTEM_MARKET: "system_market",
116
+ MODERATION: "moderation",
117
+ SECRET: "secret",
118
+ } as const;
119
+
120
+ export type RoomLedgerEntryType = (typeof RoomLedgerEntryType)[keyof typeof RoomLedgerEntryType];
121
+
122
+ /** Sealed-secrets envelope on a `secret` entry. Opaque everywhere except the
123
+ * recipients' daemons: armored age ciphertext plus recipient userIds. The
124
+ * `kind` reveals only whether a text value or a file reference is inside. */
125
+ export interface RoomLedgerSecretPayload {
126
+ armored: string;
127
+ recipients: string[];
128
+ kind: "text" | "file";
129
+ }
130
+
131
+ export function isSystemRoomLedgerEntryType(type: RoomLedgerEntryType): boolean {
132
+ return (
133
+ type === RoomLedgerEntryType.SYSTEM ||
134
+ type === RoomLedgerEntryType.SYSTEM_MARKET ||
135
+ type === RoomLedgerEntryType.MODERATION
136
+ );
137
+ }
138
+
139
+ export type RoomMemberTier = "free" | "paid";
140
+ export type RoomUserStatus = "online" | "idle" | "dnd";
141
+ export type RoomAccessMode = "public" | "invite_only" | "code" | "space";
142
+ export type RoomSearchScope = "canonical" | "community" | "all";
143
+ export type RoomRole = "owner" | "admin" | "mod" | "member";
144
+ /** Per-channel topics dial, owner-set data. Defaults to "allowed" since the
145
+ * 2026-07-12 dial-default flip (see RoomMeta.topicsPolicy for the wire
146
+ * semantics of an absent value). */
147
+ export type RoomTopicsPolicy = "off" | "allowed" | "required";
148
+ export type RoomTopicAttention = "follow" | "default" | "mute";
149
+
150
+ export interface RoomMember {
151
+ userId: string;
152
+ username: string;
153
+ handle: string;
154
+ isAgent: boolean;
155
+ roomRole?: RoomRole | null | undefined;
156
+ chatRole?: string | null | undefined;
157
+ status?: RoomUserStatus | undefined;
158
+ tier?: RoomMemberTier | null | undefined;
159
+ since?: string | number | null | undefined;
160
+ joinedAt: number;
161
+ avatarUrl?: string | null;
162
+ statusText?: string | null;
163
+ }
164
+
165
+ export interface RoomMeta {
166
+ name: string;
167
+ title: string;
168
+ description: string;
169
+ kind: string;
170
+ symbols: string[];
171
+ community?: boolean | undefined;
172
+ access?: RoomAccessMode | undefined;
173
+ maxMembers?: number | undefined;
174
+ createdByUserId?: string | undefined;
175
+ createdByHandle?: string | undefined;
176
+ category?: string | null | undefined;
177
+ sortOrder?: number | undefined;
178
+ spaceId?: string | null | undefined;
179
+ postingRoles?: RoomRole[] | undefined;
180
+ postingRolesRestricted?: boolean | undefined;
181
+ viewerRole?: RoomRole | null | undefined;
182
+ /** Head event sequence; diff against the read cursor for unread badges. */
183
+ headSeq?: number | undefined;
184
+ /** Topics dial for this channel. Absent reads as "allowed" since the
185
+ * 2026-07-12 dial-default flip (post-flip relays always advertise the
186
+ * stored value, "off" included); explicit "off" means topics are inert. */
187
+ topicsPolicy?: RoomTopicsPolicy | undefined;
188
+ tags?: string[] | undefined;
189
+ entities?: string[] | undefined;
190
+ sourceRefs?: Array<Record<string, unknown>> | undefined;
191
+ readOnly?: boolean | undefined;
192
+ heat?:
193
+ | {
194
+ score?: number | undefined;
195
+ roomHeat?: number | undefined;
196
+ marketHeat?: number | undefined;
197
+ heatKind?: "room" | "market" | "mixed" | undefined;
198
+ messageRate?: number | undefined;
199
+ freshMessageRate?: number | undefined;
200
+ recentMessageCount?: number | undefined;
201
+ baselineMessageRate?: number | undefined;
202
+ surge?: number | undefined;
203
+ onlineCount?: number | undefined;
204
+ activeSenders?: number | undefined;
205
+ updatedAt?: string | number | undefined;
206
+ }
207
+ | null
208
+ | undefined;
209
+ onlineCount?: number | undefined;
210
+ }
211
+
212
+ export interface RoomLedgerEntry {
213
+ seq: number;
214
+ ts: number;
215
+ room: string;
216
+ handle: string;
217
+ userId: string;
218
+ isAgent: boolean;
219
+ type: RoomLedgerEntryType;
220
+ text?: string | undefined;
221
+ secret?: RoomLedgerSecretPayload | undefined;
222
+ clientMsgId?: string | undefined;
223
+ receiptId?: string | undefined;
224
+ inReplyTo?: number | undefined;
225
+ /** Registry-backed topic this entry was posted into; absent = untopicked. */
226
+ topicId?: string | undefined;
227
+ tier?: RoomMemberTier | null | undefined;
228
+ since?: string | number | null | undefined;
229
+ reactions?: Array<{ emoji: string; count: number }> | undefined;
230
+ editedAt?: string | number | Date | undefined;
231
+ deletedAt?: string | number | Date | undefined;
232
+ deletedBy?: string | undefined;
233
+ replyCount?: number | undefined;
234
+ lastReplyAt?: string | number | Date | undefined;
235
+ pinned?: boolean | undefined;
236
+ pinnedBy?: string | null | undefined;
237
+ pinnedAt?: string | number | Date | null | undefined;
238
+ attachments?: RoomAttachment[] | undefined;
239
+ roomRole?: RoomRole | null | undefined;
240
+ }
241
+
242
+ export interface RoomAttachment {
243
+ /** Object key under room-attachments/; clients sign it at render time. */
244
+ key: string;
245
+ name: string;
246
+ size: number;
247
+ mime: string;
248
+ scanStatus?: "pending" | "clean" | "held" | undefined;
249
+ }
250
+
251
+ /**
252
+ * A registry-backed topic inside a channel. The id is permanent: rename
253
+ * changes `name` only, and links (`om://topic/<topicId>`) keep resolving.
254
+ * A merged topic stays resolvable via `mergedInto` (its own id never changes
255
+ * either; readers follow the alias to the surviving topic).
256
+ */
257
+ export interface RoomTopic {
258
+ topicId: string;
259
+ room: string;
260
+ name: string;
261
+ resolved: boolean;
262
+ createdByUserId?: string | undefined;
263
+ mergedInto?: string | null | undefined;
264
+ }
265
+
266
+ export interface RoomAuthSuccessPayload {
267
+ userId: string;
268
+ username: string;
269
+ handle: string;
270
+ isAgent?: boolean;
271
+ isGuest?: boolean;
272
+ connectionId: string;
273
+ protocolVersion: number;
274
+ minClientBuild?: string | undefined;
275
+ }
276
+
277
+ export interface RoomBackfillPayload {
278
+ room: string;
279
+ entries: RoomLedgerEntry[];
280
+ upToSeq: number;
281
+ hasMore: boolean;
282
+ readOnly?: boolean | undefined;
283
+ beforeSeq?: number;
284
+ sinceSeq?: number;
285
+ atMs?: number;
286
+ requestId?: string;
287
+ }
288
+
289
+ export interface RoomMessagePayload {
290
+ room: string;
291
+ seq: number;
292
+ entry: RoomLedgerEntry;
293
+ requestId?: string;
294
+ }
295
+
296
+ export type RoomEntryUpdatedPayload = RoomMessagePayload;
297
+
298
+ export interface RoomThreadPayload {
299
+ room: string;
300
+ rootSeq: number;
301
+ entries: RoomLedgerEntry[];
302
+ upToSeq: number;
303
+ hasMore: boolean;
304
+ requestId?: string | undefined;
305
+ }
306
+
307
+ export interface RoomPinsPayload {
308
+ room: string;
309
+ pins: RoomLedgerEntry[];
310
+ hasMore: boolean;
311
+ requestId?: string | undefined;
312
+ }
313
+
314
+ export interface RoomReadStatePayload {
315
+ readState: Record<string, number>;
316
+ requestId?: string | undefined;
317
+ }
318
+
319
+ export interface RoomSearchResultsPayload {
320
+ room: string;
321
+ query: string;
322
+ entries: RoomLedgerEntry[];
323
+ hasMore: boolean;
324
+ requestId?: string | undefined;
325
+ }
326
+
327
+ export interface RoomPresencePayload {
328
+ room: string;
329
+ humans: number;
330
+ agents: number;
331
+ total: number;
332
+ guestCount?: number | undefined;
333
+ sample: RoomMember[];
334
+ members?: RoomMember[] | undefined;
335
+ requestId?: string | undefined;
336
+ }
337
+
338
+ export interface RoomPresenceDeltaPayload {
339
+ room: string;
340
+ joined?: RoomMember | undefined;
341
+ left?: string | undefined;
342
+ /** In-place identity refresh (status/statusText/avatar changes). */
343
+ updated?: RoomMember | undefined;
344
+ humans: number;
345
+ agents: number;
346
+ guestCount?: number | undefined;
347
+ }
348
+
349
+ export const ROOM_PRESENCE_SAMPLE_LIMIT = 50;
350
+
351
+ /**
352
+ * Relay typing contract (kiyotaka `room.constants.ts`). Two facts every
353
+ * client-side typing feature must design against:
354
+ *
355
+ * - A typer's roster entry expires ROOM_TYPING_RELAY_ENTRY_TTL_MS after
356
+ * their last start frame, and the expiry is pruned lazily on the next
357
+ * roster read; it is NEVER broadcast. A client that wants the entry to
358
+ * survive a long message must re-send start inside this window, and a
359
+ * client rendering the roster must self-expire it locally.
360
+ * - Roster broadcasts are throttled to one per room per
361
+ * ROOM_TYPING_RELAY_BROADCAST_THROTTLE_MS (a trailing broadcast covers
362
+ * frames coalesced inside the window), so any roster a client displays
363
+ * can be that stale before the next one arrives.
364
+ */
365
+ export const ROOM_TYPING_RELAY_ENTRY_TTL_MS = 5_000;
366
+ export const ROOM_TYPING_RELAY_BROADCAST_THROTTLE_MS = 2_000;
367
+
368
+ export function applyRoomPresenceDelta(
369
+ current: RoomPresencePayload | null | undefined,
370
+ delta: RoomPresenceDeltaPayload,
371
+ ): RoomPresencePayload {
372
+ let sample = [...(current?.sample ?? current?.members ?? [])];
373
+ if (delta.left) {
374
+ const left = delta.left.toLowerCase();
375
+ sample = sample.filter((member) => member.userId.toLowerCase() !== left);
376
+ }
377
+ if (delta.joined) {
378
+ const joined = delta.joined.userId.toLowerCase();
379
+ sample = sample.filter((member) => member.userId.toLowerCase() !== joined);
380
+ if (sample.length < ROOM_PRESENCE_SAMPLE_LIMIT) sample.push(delta.joined);
381
+ }
382
+ if (delta.updated) {
383
+ const updated = delta.updated.userId.toLowerCase();
384
+ // In-place identity refresh: replace only if already sampled (an update
385
+ // must not grow the sample past what joins admitted).
386
+ sample = sample.map((member) =>
387
+ member.userId.toLowerCase() === updated ? { ...member, ...delta.updated } : member,
388
+ );
389
+ }
390
+ return {
391
+ ...(current ?? {}),
392
+ room: delta.room,
393
+ humans: delta.humans,
394
+ agents: delta.agents,
395
+ total: delta.humans + delta.agents,
396
+ ...(delta.guestCount !== undefined ? { guestCount: delta.guestCount } : {}),
397
+ sample,
398
+ members: sample,
399
+ };
400
+ }
401
+
402
+ export interface RoomWhoPayload {
403
+ room: string;
404
+ members: RoomMember[];
405
+ offset: number;
406
+ limit: number;
407
+ total: number;
408
+ humans?: number | undefined;
409
+ agents?: number | undefined;
410
+ guestCount?: number | undefined;
411
+ requestId?: string | undefined;
412
+ }
413
+
414
+ export interface RoomTypingPayload {
415
+ room: string;
416
+ users: string[];
417
+ count: number;
418
+ }
419
+
420
+ export interface RoomResyncPayload {
421
+ room: string;
422
+ reason: "stream_gap" | "stream_poison" | "stale_cursor";
423
+ sinceSeq?: number | undefined;
424
+ missing?: number | undefined;
425
+ attempts?: number | undefined;
426
+ }
427
+
428
+ export interface RoomErrorPayload {
429
+ code: string;
430
+ message: string;
431
+ details?: unknown;
432
+ requestId?: string;
433
+ }
434
+
435
+ export interface RoomFriendPresence {
436
+ friendshipId?: string | undefined;
437
+ userId: string;
438
+ username: string;
439
+ acceptedAt?: number | undefined;
440
+ lastMessageAt?: number | undefined;
441
+ }
442
+
443
+ export interface RoomSearchPayload {
444
+ requestId?: string;
445
+ query?: string;
446
+ scope?: RoomSearchScope;
447
+ category?: string | string[];
448
+ tag?: string | string[];
449
+ kind?: string | string[];
450
+ entity?: string | string[];
451
+ symbol?: string | string[];
452
+ spaceId?: string | string[];
453
+ hot?: boolean;
454
+ createdByMe?: boolean;
455
+ includeArchived?: boolean;
456
+ limit?: number;
457
+ }
458
+
459
+ export interface RoomCreatePayload {
460
+ requestId?: string;
461
+ name: string;
462
+ title?: string;
463
+ description?: string;
464
+ access?: RoomAccessMode;
465
+ maxMembers?: number;
466
+ category?: string;
467
+ sortOrder?: number;
468
+ spaceId?: string;
469
+ postingRoles?: RoomRole[];
470
+ tags?: string[];
471
+ }
472
+
473
+ export interface RoomCreatedPayload {
474
+ requestId?: string;
475
+ room: RoomMeta;
476
+ joinCode?: string;
477
+ }
478
+
479
+ export interface RoomInvitePayload {
480
+ requestId?: string;
481
+ room: string;
482
+ username?: string;
483
+ userId?: string;
484
+ }
485
+
486
+ export interface RoomInvitedPayload {
487
+ requestId?: string;
488
+ room: string;
489
+ invitedUserId: string;
490
+ invitedHandle: string;
491
+ }
492
+
493
+ export interface RoomRemoveMemberPayload {
494
+ requestId?: string;
495
+ room: string;
496
+ username?: string;
497
+ userId?: string;
498
+ reason?: string;
499
+ }
500
+
501
+ export interface RoomMemberRemovedPayload {
502
+ requestId?: string;
503
+ room: string;
504
+ removedUserId: string;
505
+ removedHandle: string;
506
+ }
507
+
508
+ export interface RoomDmParticipant {
509
+ userId: string;
510
+ username: string;
511
+ }
512
+
513
+ export interface RoomDmMessage {
514
+ id?: string | undefined;
515
+ _id?: string | undefined;
516
+ messageId?: string | undefined;
517
+ conversationId?: string | undefined;
518
+ senderId?: string | undefined;
519
+ userId?: string | undefined;
520
+ senderUsername?: string | undefined;
521
+ username?: string | undefined;
522
+ content: string;
523
+ clientMsgId?: string | undefined;
524
+ type?: string | undefined;
525
+ timestamp?: string | number | undefined;
526
+ createdAt?: string | number | undefined;
527
+ /** Sealed DM: content is '' and the opaque envelope rides here. */
528
+ secret?: RoomLedgerSecretPayload | null | undefined;
529
+ metadata?: Record<string, unknown> | undefined;
530
+ }
531
+
532
+ export interface RoomDmOpenPayload {
533
+ requestId?: string;
534
+ username: string;
535
+ limit?: number;
536
+ markRead?: boolean;
537
+ }
538
+
539
+ export interface RoomDmHistoryPayload {
540
+ requestId?: string;
541
+ username?: string;
542
+ conversationId?: string;
543
+ before?: number;
544
+ limit?: number;
545
+ markRead?: boolean;
546
+ }
547
+
548
+ export interface RoomDmSendPayload {
549
+ requestId?: string;
550
+ username?: string;
551
+ conversationId?: string;
552
+ content: string;
553
+ clientMsgId?: string;
554
+ }
555
+
556
+ export interface RoomDmReadPayload {
557
+ requestId?: string;
558
+ username?: string;
559
+ conversationId?: string;
560
+ before?: number;
561
+ }
562
+
563
+ export interface RoomDmOpenedPayload {
564
+ requestId?: string;
565
+ conversationId: string;
566
+ participant: RoomDmParticipant;
567
+ messages: RoomDmMessage[];
568
+ hasMore?: boolean;
569
+ cursor?: number;
570
+ }
571
+
572
+ export type RoomDmHistoryResultPayload = RoomDmOpenedPayload;
573
+
574
+ export interface RoomDmMessagePayload {
575
+ requestId?: string;
576
+ conversationId: string;
577
+ participant: RoomDmParticipant;
578
+ message: RoomDmMessage;
579
+ clientMsgId?: string;
580
+ }
581
+
582
+ export interface RoomDmInboxUpdatedPayload {
583
+ conversationId: string;
584
+ participant: RoomDmParticipant;
585
+ unreadCount: number;
586
+ lastMessage?: RoomDmMessage;
587
+ updatedAt?: string | number;
588
+ }
589
+
590
+ export interface RoomReportPayload {
591
+ requestId?: string;
592
+ room: string;
593
+ seq?: number;
594
+ targetUserId?: string;
595
+ reason: string;
596
+ }
597
+
598
+ export interface RoomReportedPayload {
599
+ requestId?: string;
600
+ room: string;
601
+ target: { kind: "event"; seq: number } | { kind: "membership"; userId: string };
602
+ }
603
+
604
+ export interface RoomModerateMemberPayload {
605
+ requestId?: string;
606
+ room: string;
607
+ username?: string;
608
+ userId?: string;
609
+ reason?: string;
610
+ }
611
+
612
+ export interface RoomMutePayload extends RoomModerateMemberPayload {
613
+ until: string | number | Date;
614
+ }
615
+
616
+ export interface RoomMutedPayload {
617
+ requestId?: string;
618
+ room: string;
619
+ mutedUserId: string;
620
+ mutedHandle: string;
621
+ until: string | number | Date;
622
+ }
623
+
624
+ export interface RoomBannedPayload {
625
+ requestId?: string;
626
+ room: string;
627
+ bannedUserId: string;
628
+ bannedHandle: string;
629
+ }
630
+
631
+ export interface RoomRoleChangePayload {
632
+ requestId?: string;
633
+ room: string;
634
+ username?: string;
635
+ userId?: string;
636
+ role: RoomRole;
637
+ reason?: string;
638
+ }
639
+
640
+ export interface RoomMemberRoleChangedPayload {
641
+ requestId?: string;
642
+ room: string;
643
+ targetUserId: string;
644
+ targetHandle: string;
645
+ role: RoomRole;
646
+ actorUserId?: string;
647
+ }
648
+
649
+ export interface RoomSetReadOnlyPayload {
650
+ requestId?: string;
651
+ room: string;
652
+ postingRoles: RoomRole[];
653
+ reason?: string;
654
+ }
655
+
656
+ export interface RoomReadOnlySetPayload {
657
+ requestId?: string;
658
+ room: string;
659
+ postingRoles: RoomRole[];
660
+ }
661
+
662
+ export interface RoomAuditLogRequestPayload {
663
+ requestId?: string;
664
+ room: string;
665
+ limit?: number;
666
+ }
667
+
668
+ export interface RoomAuditEntry {
669
+ roomId: string;
670
+ actor: string;
671
+ action: string;
672
+ target?: Record<string, unknown> | undefined;
673
+ reason?: string | undefined;
674
+ at: string | number | Date;
675
+ }
676
+
677
+ export interface RoomAuditLogPayload {
678
+ requestId?: string;
679
+ room: string;
680
+ entries: RoomAuditEntry[];
681
+ }
682
+
683
+ export interface RoomSpace {
684
+ spaceId: string;
685
+ name: string;
686
+ ownerUserId: string;
687
+ createdAt: string | number | Date;
688
+ joined?: boolean | undefined;
689
+ iconUrl?: string | null | undefined;
690
+ }
691
+
692
+ export interface RoomSpacesPayload {
693
+ requestId?: string;
694
+ spaces: RoomSpace[];
695
+ }
696
+
697
+ export interface RoomJoinSpacePayload {
698
+ requestId?: string;
699
+ spaceId: string;
700
+ }
701
+
702
+ export interface SpaceMemberAddedPayload {
703
+ spaceId: string;
704
+ spaceName?: string;
705
+ role: string;
706
+ addedBy?: string;
707
+ }
708
+
709
+ export interface RoomReactorsPayload {
710
+ room: string;
711
+ seq: number;
712
+ reactors: Array<{
713
+ emoji: string;
714
+ users: Array<{ userId: string; handle: string }>;
715
+ count: number;
716
+ }>;
717
+ requestId?: string;
718
+ }
719
+
720
+ export interface SpaceInvitePayload {
721
+ inviteId: string;
722
+ spaceId: string;
723
+ spaceName?: string;
724
+ role: string;
725
+ invitedBy?: string;
726
+ }
727
+
728
+ /** Channel settings changed: full meta replace, or an archive tombstone. */
729
+ export interface RoomUpdatedPayload {
730
+ room: string;
731
+ meta?: RoomMeta | undefined;
732
+ archived?: boolean | undefined;
733
+ }
734
+
735
+ /** Server settings changed (rename / icon / archive). */
736
+ export interface SpaceUpdatedPayload {
737
+ spaceId: string;
738
+ name?: string | undefined;
739
+ iconUrl?: string | null | undefined;
740
+ archived?: boolean | undefined;
741
+ }
742
+
743
+ export interface RoomSpaceJoinedPayload {
744
+ requestId?: string;
745
+ space: RoomSpace;
746
+ }
747
+
748
+ export interface RoomTopicCreatePayload {
749
+ requestId?: string;
750
+ room: string;
751
+ name: string;
752
+ }
753
+
754
+ export interface RoomTopicRenamePayload {
755
+ requestId?: string;
756
+ topicId: string;
757
+ name: string;
758
+ }
759
+
760
+ export interface RoomTopicMovePayload {
761
+ requestId?: string;
762
+ topicId: string;
763
+ seqs: number[];
764
+ toTopicId: string;
765
+ }
766
+
767
+ export interface RoomTopicMergePayload {
768
+ requestId?: string;
769
+ topicId: string;
770
+ intoTopicId: string;
771
+ }
772
+
773
+ export interface RoomTopicResolvePayload {
774
+ requestId?: string;
775
+ topicId: string;
776
+ /** Defaults to true (mark resolved) when omitted; false reopens it. */
777
+ resolved?: boolean;
778
+ }
779
+
780
+ export interface RoomTopicSetAttentionPayload {
781
+ requestId?: string;
782
+ topicId: string;
783
+ attention: RoomTopicAttention;
784
+ }
785
+
786
+ export interface RoomTopicListPayload {
787
+ requestId?: string;
788
+ room: string;
789
+ includeResolved?: boolean;
790
+ /** Also return the caller's per-bucket view state and the room head. */
791
+ withState?: boolean;
792
+ }
793
+
794
+ /**
795
+ * Per-bucket view state for the requesting user: one entry per topicId plus
796
+ * the reserved '' key for the room's untopicked (linear) messages. lastSeq
797
+ * and unreadCount cover visible user messages only; unreadCount also
798
+ * excludes the caller's own posts and saturates at a server-side cap. The
799
+ * per-topic cursors and the room-wide cursor are independent per the phase
800
+ * 2 contract: a linear read never implies a topic was seen, and vice versa.
801
+ */
802
+ export interface RoomTopicBucketState {
803
+ lastSeq: number;
804
+ unreadCount: number;
805
+ cursor: number;
806
+ attention: RoomTopicAttention;
807
+ }
808
+
809
+ export interface RoomTopicResultPayload {
810
+ room: string;
811
+ topic: RoomTopic;
812
+ requestId?: string | undefined;
813
+ }
814
+
815
+ export interface RoomTopicsResultPayload {
816
+ room: string;
817
+ topics: RoomTopic[];
818
+ /** Present when the request asked withState: keyed by topicId plus ''. */
819
+ state?: Record<string, RoomTopicBucketState> | undefined;
820
+ /** Present when the request asked withState: the room head seq. */
821
+ headSeq?: number | undefined;
822
+ requestId?: string | undefined;
823
+ }
824
+
825
+ /** Broadcast to the room on any topic mutation (create/rename/move/merge/resolve). */
826
+ export interface RoomTopicUpdatedPayload {
827
+ room: string;
828
+ topic: RoomTopic;
829
+ }
830
+
831
+ export type RoomClientMessage =
832
+ | {
833
+ type: typeof RoomClientMessageType.AUTHENTICATE;
834
+ payload: {
835
+ token?: string;
836
+ username?: string;
837
+ handle?: string;
838
+ isAgent?: boolean;
839
+ protocolVersion?: number;
840
+ };
841
+ timestamp?: number;
842
+ }
843
+ | {
844
+ type: typeof RoomClientMessageType.CREATE_ROOM;
845
+ payload: RoomCreatePayload;
846
+ timestamp?: number;
847
+ }
848
+ | {
849
+ type: typeof RoomClientMessageType.INVITE;
850
+ payload: RoomInvitePayload;
851
+ timestamp?: number;
852
+ }
853
+ | {
854
+ type: typeof RoomClientMessageType.REMOVE_MEMBER;
855
+ payload: RoomRemoveMemberPayload;
856
+ timestamp?: number;
857
+ }
858
+ | { type: typeof RoomClientMessageType.SEARCH; payload: RoomSearchPayload; timestamp?: number }
859
+ | {
860
+ type: typeof RoomClientMessageType.JOIN;
861
+ payload: {
862
+ room: string;
863
+ workspaceId?: string;
864
+ requestId?: string;
865
+ code?: string;
866
+ sinceSeq?: number;
867
+ limit?: number;
868
+ reason?: string;
869
+ source?: string;
870
+ hook?: string;
871
+ suggestionId?: string;
872
+ };
873
+ timestamp?: number;
874
+ }
875
+ | {
876
+ type: typeof RoomClientMessageType.HISTORY;
877
+ payload: {
878
+ room: string;
879
+ requestId?: string;
880
+ sinceSeq?: number;
881
+ beforeSeq?: number;
882
+ atMs?: number;
883
+ limit?: number;
884
+ };
885
+ timestamp?: number;
886
+ }
887
+ | {
888
+ type: typeof RoomClientMessageType.PEEK;
889
+ payload: {
890
+ room: string;
891
+ requestId?: string;
892
+ sinceSeq?: number;
893
+ beforeSeq?: number;
894
+ atMs?: number;
895
+ limit?: number;
896
+ };
897
+ timestamp?: number;
898
+ }
899
+ | { type: typeof RoomClientMessageType.LEAVE; payload: { room: string }; timestamp?: number }
900
+ | {
901
+ type: typeof RoomClientMessageType.POST;
902
+ payload: {
903
+ room: string;
904
+ text?: string;
905
+ attachments?: RoomAttachment[];
906
+ inReplyTo?: number;
907
+ /** Post directly into a topic; the room's linear stream is unaffected. */
908
+ topicId?: string;
909
+ clientMsgId?: string;
910
+ reason?: string;
911
+ requestId?: string;
912
+ };
913
+ timestamp?: number;
914
+ }
915
+ | {
916
+ type: typeof RoomClientMessageType.REACT;
917
+ payload: {
918
+ requestId?: string;
919
+ room: string;
920
+ seq: number;
921
+ emoji: string;
922
+ op: "add" | "remove";
923
+ };
924
+ timestamp?: number;
925
+ }
926
+ | {
927
+ type: typeof RoomClientMessageType.EDIT;
928
+ payload: {
929
+ requestId?: string;
930
+ room: string;
931
+ seq: number;
932
+ text: string;
933
+ };
934
+ timestamp?: number;
935
+ }
936
+ | {
937
+ type: typeof RoomClientMessageType.DELETE;
938
+ payload: {
939
+ requestId?: string;
940
+ room: string;
941
+ seq: number;
942
+ };
943
+ timestamp?: number;
944
+ }
945
+ | {
946
+ type: typeof RoomClientMessageType.THREAD;
947
+ payload: {
948
+ requestId?: string;
949
+ room: string;
950
+ rootSeq: number;
951
+ beforeSeq?: number;
952
+ sinceSeq?: number;
953
+ limit?: number;
954
+ };
955
+ timestamp?: number;
956
+ }
957
+ | {
958
+ type: typeof RoomClientMessageType.PIN;
959
+ payload: { requestId?: string; room: string; seq: number };
960
+ timestamp?: number;
961
+ }
962
+ | {
963
+ type: typeof RoomClientMessageType.UNPIN;
964
+ payload: { requestId?: string; room: string; seq: number };
965
+ timestamp?: number;
966
+ }
967
+ | {
968
+ type: typeof RoomClientMessageType.PINS;
969
+ payload: { requestId?: string; room: string; limit?: number };
970
+ timestamp?: number;
971
+ }
972
+ | {
973
+ type: typeof RoomClientMessageType.REACTORS;
974
+ payload: { requestId?: string; room: string; seq: number; emoji?: string; limit?: number };
975
+ timestamp?: number;
976
+ }
977
+ | {
978
+ type: typeof RoomClientMessageType.REPORT;
979
+ payload: RoomReportPayload;
980
+ timestamp?: number;
981
+ }
982
+ | {
983
+ type: typeof RoomClientMessageType.MUTE;
984
+ payload: RoomMutePayload;
985
+ timestamp?: number;
986
+ }
987
+ | {
988
+ type: typeof RoomClientMessageType.KICK;
989
+ payload: RoomModerateMemberPayload;
990
+ timestamp?: number;
991
+ }
992
+ | {
993
+ type: typeof RoomClientMessageType.BAN;
994
+ payload: RoomModerateMemberPayload;
995
+ timestamp?: number;
996
+ }
997
+ | {
998
+ type: typeof RoomClientMessageType.ROLE_CHANGE;
999
+ payload: RoomRoleChangePayload;
1000
+ timestamp?: number;
1001
+ }
1002
+ | {
1003
+ type: typeof RoomClientMessageType.SET_READ_ONLY;
1004
+ payload: RoomSetReadOnlyPayload;
1005
+ timestamp?: number;
1006
+ }
1007
+ | {
1008
+ type: typeof RoomClientMessageType.AUDIT_LOG;
1009
+ payload: RoomAuditLogRequestPayload;
1010
+ timestamp?: number;
1011
+ }
1012
+ | {
1013
+ type: typeof RoomClientMessageType.SPACES;
1014
+ payload?: { requestId?: string };
1015
+ timestamp?: number;
1016
+ }
1017
+ | {
1018
+ type: typeof RoomClientMessageType.JOIN_SPACE;
1019
+ payload: RoomJoinSpacePayload;
1020
+ timestamp?: number;
1021
+ }
1022
+ | {
1023
+ type: typeof RoomClientMessageType.READ_STATE;
1024
+ payload: { requestId?: string; rooms?: string[] };
1025
+ timestamp?: number;
1026
+ }
1027
+ | {
1028
+ type: typeof RoomClientMessageType.SEARCH_ENTRIES;
1029
+ payload: {
1030
+ requestId?: string;
1031
+ room: string;
1032
+ query: string;
1033
+ beforeSeq?: number;
1034
+ sinceSeq?: number;
1035
+ fromMs?: number;
1036
+ toMs?: number;
1037
+ limit?: number;
1038
+ };
1039
+ timestamp?: number;
1040
+ }
1041
+ | {
1042
+ type: typeof RoomClientMessageType.WHO;
1043
+ payload: { room: string; requestId?: string; offset?: number; limit?: number };
1044
+ timestamp?: number;
1045
+ }
1046
+ | {
1047
+ type: typeof RoomClientMessageType.TYPING;
1048
+ payload: { room: string; state: "start" | "stop" };
1049
+ timestamp?: number;
1050
+ }
1051
+ | {
1052
+ type: typeof RoomClientMessageType.STATUS;
1053
+ payload: { status: RoomUserStatus; statusText?: string | null };
1054
+ timestamp?: number;
1055
+ }
1056
+ | {
1057
+ type: typeof RoomClientMessageType.ACK;
1058
+ /** `topicId` acks a per-topic cursor; the room-wide cursor is separate. */
1059
+ payload: { room: string; seq: number; topicId?: string };
1060
+ timestamp?: number;
1061
+ }
1062
+ | { type: typeof RoomClientMessageType.PING; payload?: Record<string, never>; timestamp?: number }
1063
+ | {
1064
+ type: typeof RoomClientMessageType.FRIENDS;
1065
+ payload?: Record<string, never>;
1066
+ timestamp?: number;
1067
+ }
1068
+ | {
1069
+ type: typeof RoomClientMessageType.DM_OPEN;
1070
+ payload: RoomDmOpenPayload;
1071
+ timestamp?: number;
1072
+ }
1073
+ | {
1074
+ type: typeof RoomClientMessageType.DM_HISTORY;
1075
+ payload: RoomDmHistoryPayload;
1076
+ timestamp?: number;
1077
+ }
1078
+ | {
1079
+ type: typeof RoomClientMessageType.DM_SEND;
1080
+ payload: RoomDmSendPayload;
1081
+ timestamp?: number;
1082
+ }
1083
+ | {
1084
+ type: typeof RoomClientMessageType.DM_READ;
1085
+ payload: RoomDmReadPayload;
1086
+ timestamp?: number;
1087
+ }
1088
+ | {
1089
+ type: typeof RoomClientMessageType.TOPIC_CREATE;
1090
+ payload: RoomTopicCreatePayload;
1091
+ timestamp?: number;
1092
+ }
1093
+ | {
1094
+ type: typeof RoomClientMessageType.TOPIC_RENAME;
1095
+ payload: RoomTopicRenamePayload;
1096
+ timestamp?: number;
1097
+ }
1098
+ | {
1099
+ type: typeof RoomClientMessageType.TOPIC_MOVE;
1100
+ payload: RoomTopicMovePayload;
1101
+ timestamp?: number;
1102
+ }
1103
+ | {
1104
+ type: typeof RoomClientMessageType.TOPIC_MERGE;
1105
+ payload: RoomTopicMergePayload;
1106
+ timestamp?: number;
1107
+ }
1108
+ | {
1109
+ type: typeof RoomClientMessageType.TOPIC_RESOLVE;
1110
+ payload: RoomTopicResolvePayload;
1111
+ timestamp?: number;
1112
+ }
1113
+ | {
1114
+ type: typeof RoomClientMessageType.TOPIC_SET_ATTENTION;
1115
+ payload: RoomTopicSetAttentionPayload;
1116
+ timestamp?: number;
1117
+ }
1118
+ | {
1119
+ type: typeof RoomClientMessageType.TOPIC_LIST;
1120
+ payload: RoomTopicListPayload;
1121
+ timestamp?: number;
1122
+ };
1123
+
1124
+ export type RoomServerMessage =
1125
+ | {
1126
+ type: typeof RoomServerMessageType.AUTH_SUCCESS;
1127
+ payload: RoomAuthSuccessPayload;
1128
+ timestamp: number;
1129
+ }
1130
+ | {
1131
+ type: typeof RoomServerMessageType.ROOM_CREATED;
1132
+ payload: RoomCreatedPayload;
1133
+ timestamp: number;
1134
+ }
1135
+ | {
1136
+ type: typeof RoomServerMessageType.ROOM_INVITED;
1137
+ payload: RoomInvitedPayload;
1138
+ timestamp: number;
1139
+ }
1140
+ | {
1141
+ type: typeof RoomServerMessageType.ROOM_MEMBER_REMOVED;
1142
+ payload: RoomMemberRemovedPayload;
1143
+ timestamp: number;
1144
+ }
1145
+ | {
1146
+ type: typeof RoomServerMessageType.ROOMS;
1147
+ payload: { rooms: RoomMeta[]; requestId?: string };
1148
+ timestamp: number;
1149
+ }
1150
+ | {
1151
+ type: typeof RoomServerMessageType.BACKFILL;
1152
+ payload: RoomBackfillPayload;
1153
+ timestamp: number;
1154
+ }
1155
+ | {
1156
+ type: typeof RoomServerMessageType.HISTORY;
1157
+ payload: RoomBackfillPayload;
1158
+ timestamp: number;
1159
+ }
1160
+ | {
1161
+ type: typeof RoomServerMessageType.PEEK_RESULT;
1162
+ payload: RoomBackfillPayload;
1163
+ timestamp: number;
1164
+ }
1165
+ | {
1166
+ type: typeof RoomServerMessageType.MESSAGE;
1167
+ payload: RoomMessagePayload;
1168
+ timestamp: number;
1169
+ }
1170
+ | {
1171
+ type: typeof RoomServerMessageType.ENTRY_UPDATED;
1172
+ payload: RoomEntryUpdatedPayload;
1173
+ timestamp: number;
1174
+ }
1175
+ | {
1176
+ type: typeof RoomServerMessageType.THREAD;
1177
+ payload: RoomThreadPayload;
1178
+ timestamp: number;
1179
+ }
1180
+ | {
1181
+ type: typeof RoomServerMessageType.PINS;
1182
+ payload: RoomPinsPayload;
1183
+ timestamp: number;
1184
+ }
1185
+ | {
1186
+ type: typeof RoomServerMessageType.ROOM_REPORTED;
1187
+ payload: RoomReportedPayload;
1188
+ timestamp: number;
1189
+ }
1190
+ | {
1191
+ type: typeof RoomServerMessageType.ROOM_MUTED;
1192
+ payload: RoomMutedPayload;
1193
+ timestamp: number;
1194
+ }
1195
+ | {
1196
+ type: typeof RoomServerMessageType.ROOM_BANNED;
1197
+ payload: RoomBannedPayload;
1198
+ timestamp: number;
1199
+ }
1200
+ | {
1201
+ type: typeof RoomServerMessageType.ROOM_MEMBER_ROLE_CHANGED;
1202
+ payload: RoomMemberRoleChangedPayload;
1203
+ timestamp: number;
1204
+ }
1205
+ | {
1206
+ type: typeof RoomServerMessageType.ROOM_READ_ONLY_SET;
1207
+ payload: RoomReadOnlySetPayload;
1208
+ timestamp: number;
1209
+ }
1210
+ | {
1211
+ type: typeof RoomServerMessageType.ROOM_AUDIT_LOG;
1212
+ payload: RoomAuditLogPayload;
1213
+ timestamp: number;
1214
+ }
1215
+ | {
1216
+ type: typeof RoomServerMessageType.SPACES;
1217
+ payload: RoomSpacesPayload;
1218
+ timestamp: number;
1219
+ }
1220
+ | {
1221
+ type: typeof RoomServerMessageType.SPACE_JOINED;
1222
+ payload: RoomSpaceJoinedPayload;
1223
+ timestamp: number;
1224
+ }
1225
+ | {
1226
+ type: typeof RoomServerMessageType.SPACE_MEMBER_ADDED;
1227
+ payload: SpaceMemberAddedPayload;
1228
+ timestamp: number;
1229
+ }
1230
+ | {
1231
+ type: typeof RoomServerMessageType.ROOM_UPDATED;
1232
+ payload: RoomUpdatedPayload;
1233
+ timestamp?: number;
1234
+ }
1235
+ | {
1236
+ type: typeof RoomServerMessageType.SPACE_UPDATED;
1237
+ payload: SpaceUpdatedPayload;
1238
+ timestamp?: number;
1239
+ }
1240
+ | {
1241
+ type: typeof RoomServerMessageType.SPACE_INVITE;
1242
+ payload: SpaceInvitePayload;
1243
+ timestamp: number;
1244
+ }
1245
+ | {
1246
+ type: typeof RoomServerMessageType.REACTORS;
1247
+ payload: RoomReactorsPayload;
1248
+ timestamp: number;
1249
+ }
1250
+ | {
1251
+ type: typeof RoomServerMessageType.READ_STATE;
1252
+ payload: RoomReadStatePayload;
1253
+ timestamp: number;
1254
+ }
1255
+ | {
1256
+ type: typeof RoomServerMessageType.SEARCH_RESULTS;
1257
+ payload: RoomSearchResultsPayload;
1258
+ timestamp: number;
1259
+ }
1260
+ | {
1261
+ type: typeof RoomServerMessageType.PRESENCE;
1262
+ payload: RoomPresencePayload;
1263
+ timestamp: number;
1264
+ }
1265
+ | {
1266
+ type: typeof RoomServerMessageType.RESYNC;
1267
+ payload: RoomResyncPayload;
1268
+ timestamp: number;
1269
+ }
1270
+ | {
1271
+ type: typeof RoomServerMessageType.PRESENCE_DELTA;
1272
+ payload: RoomPresenceDeltaPayload;
1273
+ timestamp: number;
1274
+ }
1275
+ | {
1276
+ type: typeof RoomServerMessageType.WHO;
1277
+ payload: RoomWhoPayload;
1278
+ timestamp: number;
1279
+ }
1280
+ | {
1281
+ type: typeof RoomServerMessageType.TYPING;
1282
+ payload: RoomTypingPayload;
1283
+ timestamp: number;
1284
+ }
1285
+ | {
1286
+ type: typeof RoomServerMessageType.ERROR;
1287
+ payload: RoomErrorPayload;
1288
+ timestamp: number;
1289
+ }
1290
+ | {
1291
+ type: typeof RoomServerMessageType.PONG;
1292
+ payload: Record<string, never>;
1293
+ timestamp: number;
1294
+ }
1295
+ | {
1296
+ type: typeof RoomServerMessageType.FRIENDS;
1297
+ payload: { friends: RoomFriendPresence[] };
1298
+ timestamp: number;
1299
+ }
1300
+ | {
1301
+ type: typeof RoomServerMessageType.DM_OPENED;
1302
+ payload: RoomDmOpenedPayload;
1303
+ timestamp: number;
1304
+ }
1305
+ | {
1306
+ type: typeof RoomServerMessageType.DM_HISTORY;
1307
+ payload: RoomDmHistoryResultPayload;
1308
+ timestamp: number;
1309
+ }
1310
+ | {
1311
+ type: typeof RoomServerMessageType.DM_MESSAGE;
1312
+ payload: RoomDmMessagePayload;
1313
+ timestamp: number;
1314
+ }
1315
+ | {
1316
+ type: typeof RoomServerMessageType.DM_INBOX_UPDATED;
1317
+ payload: RoomDmInboxUpdatedPayload;
1318
+ timestamp: number;
1319
+ }
1320
+ | {
1321
+ type: typeof RoomServerMessageType.TOPIC;
1322
+ payload: RoomTopicResultPayload;
1323
+ timestamp: number;
1324
+ }
1325
+ | {
1326
+ type: typeof RoomServerMessageType.TOPICS;
1327
+ payload: RoomTopicsResultPayload;
1328
+ timestamp: number;
1329
+ }
1330
+ | {
1331
+ type: typeof RoomServerMessageType.TOPIC_UPDATED;
1332
+ payload: RoomTopicUpdatedPayload;
1333
+ timestamp: number;
1334
+ };
1335
+
1336
+ export type RoomServerMessageOf<T extends RoomServerMessageType> = Extract<
1337
+ RoomServerMessage,
1338
+ { type: T }
1339
+ >;