@openmarket/rooms-client 0.4.1 → 0.4.2

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/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type RoomAccessMode, type RoomAttachmentInput, type RoomAuditLogPayload, type RoomAuthSuccessPayload, type RoomBackfillPayload, type RoomClientPlatform, type RoomDmHistoryResultPayload, type RoomDmInboxUpdatedPayload, type RoomDmMessagePayload, type RoomDmOpenedPayload, type RoomFriendPresence, type RoomInvitedPayload, type RoomLedgerEntry, type RoomMemberRemovedPayload, type RoomMemberRoleChangedPayload, type RoomMeta, type RoomPinsPayload, type RoomPresencePayload, type RoomReactorsPayload, type RoomReadStatePayload, type RoomReportedPayload, type RoomRole, type RoomSearchResultsPayload, type RoomSearchScope, type RoomSpace, type RoomThreadPayload, type RoomTopic, type RoomTopicAttention, type RoomTopicResultPayload, type RoomTopicsResultPayload, type RoomUserStatus, type RoomWhoPayload } from "./types.js";
1
+ import { type RoomAccessMode, type RoomAttachmentInput, type RoomAuditLogPayload, type RoomAuthSuccessPayload, type RoomBackfillPayload, type RoomClientPlatform, type RoomDmHistoryResultPayload, type RoomDmInboxUpdatedPayload, type RoomDmMessageDeletedPayload, type RoomDmMessageEditedPayload, type RoomDmMessagePayload, type RoomDmOpenedPayload, type RoomDmPinsResultPayload, type RoomDmReactionUpdatedPayload, type RoomForwardMetadata, type RoomFriendPresence, type RoomInvitedPayload, type RoomLedgerEntry, type RoomMemberRemovedPayload, type RoomMemberRoleChangedPayload, type RoomMeta, type RoomPinsPayload, type RoomPresencePayload, type RoomReactorsPayload, type RoomReadStatePayload, type RoomReportedPayload, type RoomRole, type RoomSearchResultsPayload, type RoomSearchScope, type RoomSpace, type RoomThreadPayload, type RoomTopic, type RoomTopicAttention, type RoomTopicResultPayload, type RoomTopicsResultPayload, type RoomUserStatus, type RoomWhoPayload } from "./types.js";
2
2
  import { type RoomWebSocketCtor, RoomWsClient } from "./ws-client.js";
3
3
  export interface RoomClientConfig {
4
4
  url: string;
@@ -212,6 +212,10 @@ export interface RoomDmSendRequest {
212
212
  * URL. Stored on the message's imageUrl; the client signs keys on render.
213
213
  * Additive — omitted for text-only sends. */
214
214
  imageUrl?: string;
215
+ metadata?: RoomForwardMetadata;
216
+ }
217
+ export interface RoomDmReplyRequest extends RoomDmSendRequest {
218
+ replyTo: string;
215
219
  }
216
220
  export interface RoomDmReadRequest {
217
221
  username?: string;
@@ -260,20 +264,20 @@ export declare function openRoomDmOnClient(client: RoomWsClient, request: RoomDm
260
264
  export declare function requestRoomDmHistoryOnClient(client: RoomWsClient, request: RoomDmHistoryRequest, timeoutMs?: number): Promise<RoomDmHistoryResultPayload>;
261
265
  export declare function markRoomDmReadOnClient(client: RoomWsClient, request: RoomDmReadRequest, timeoutMs?: number): Promise<RoomDmInboxUpdatedPayload>;
262
266
  export declare function sendRoomDmOnClient(client: RoomWsClient, request: RoomDmSendRequest, timeoutMs?: number): Promise<RoomDmMessagePayload>;
263
- /** Edit one of my DM messages. Fire-and-forget over the WS; the relay fans out
264
- * DM_MESSAGE_EDITED to both participants. */
267
+ export declare function replyRoomDmOnClient(client: RoomWsClient, request: RoomDmReplyRequest, timeoutMs?: number): Promise<RoomDmMessagePayload>;
268
+ /** Edit one of my DM messages and wait for the correlated relay update. */
265
269
  export declare function editRoomDmOnClient(client: RoomWsClient, request: {
266
270
  conversationId?: string;
267
271
  username?: string;
268
272
  messageId: string;
269
273
  content: string;
270
- }): void;
274
+ }, timeoutMs?: number): Promise<RoomDmMessageEditedPayload>;
271
275
  /** Soft-delete one of my DM messages. The relay fans out DM_MESSAGE_DELETED. */
272
276
  export declare function deleteRoomDmOnClient(client: RoomWsClient, request: {
273
277
  conversationId?: string;
274
278
  username?: string;
275
279
  messageId: string;
276
- }): void;
280
+ }, timeoutMs?: number): Promise<RoomDmMessageDeletedPayload>;
277
281
  /** Toggle a reaction on a DM message. The relay fans out DM_REACTION_UPDATED. */
278
282
  export declare function reactRoomDmOnClient(client: RoomWsClient, request: {
279
283
  conversationId?: string;
@@ -281,7 +285,23 @@ export declare function reactRoomDmOnClient(client: RoomWsClient, request: {
281
285
  messageId: string;
282
286
  emoji: string;
283
287
  op: "add" | "remove";
288
+ }, timeoutMs?: number): Promise<RoomDmReactionUpdatedPayload>;
289
+ /** Set shared pin state for a DM message. The relay fans out DM_PIN_UPDATED. */
290
+ export declare function pinRoomDmOnClient(client: RoomWsClient, request: {
291
+ conversationId?: string;
292
+ username?: string;
293
+ messageId: string;
284
294
  }): void;
295
+ export declare function unpinRoomDmOnClient(client: RoomWsClient, request: {
296
+ conversationId?: string;
297
+ username?: string;
298
+ messageId: string;
299
+ }): void;
300
+ export declare function requestRoomDmPinsOnClient(client: RoomWsClient, request: {
301
+ conversationId?: string;
302
+ username?: string;
303
+ limit?: number;
304
+ }, timeoutMs?: number): Promise<RoomDmPinsResultPayload>;
285
305
  export declare function peekRoom(config: RoomClientConfig, options: RoomPeekOptions): Promise<RoomBackfillPayload>;
286
306
  export declare function sayRoom(config: RoomClientConfig, options: RoomSayOptions): Promise<RoomSayResult>;
287
307
  export declare function joinRoom(config: RoomClientConfig, options: RoomJoinOptions): Promise<RoomJoinedSession>;
@@ -297,7 +317,7 @@ export declare function attachRejoinOnReconnect(client: RoomWsClient, options: R
297
317
  * (1..128 chars after trim); dedupe on (userId, clientMsgId) is server-side
298
318
  * work and NOT implied here.
299
319
  */
300
- export declare function postRoomMessage(client: RoomWsClient, room: string, text: string, inReplyTo?: number, attachments?: RoomAttachmentInput[], topicId?: string, clientMsgId?: string): string;
320
+ export declare function postRoomMessage(client: RoomWsClient, room: string, text: string, inReplyTo?: number, attachments?: RoomAttachmentInput[], topicId?: string, clientMsgId?: string, metadata?: RoomForwardMetadata): string;
301
321
  export declare function sendRoomTyping(client: RoomWsClient, room: string, state: "start" | "stop"): void;
302
322
  export declare function sendRoomStatus(client: RoomWsClient, status: RoomUserStatus, statusText?: string | null, platform?: RoomClientPlatform): void;
303
323
  /**
package/dist/client.js CHANGED
@@ -480,6 +480,7 @@ export async function sendRoomDmOnClient(client, request, timeoutMs) {
480
480
  ...(request.username ? { username: request.username } : {}),
481
481
  ...(request.conversationId ? { conversationId: request.conversationId } : {}),
482
482
  ...(request.imageUrl ? { imageUrl: request.imageUrl } : {}),
483
+ ...(request.metadata ? { metadata: request.metadata } : {}),
483
484
  },
484
485
  timestamp: Date.now(),
485
486
  });
@@ -488,12 +489,35 @@ export async function sendRoomDmOnClient(client, request, timeoutMs) {
488
489
  msg.payload.message.clientMsgId === clientMsgId, timeoutMs, requestId);
489
490
  return sent.payload;
490
491
  }
491
- /** Edit one of my DM messages. Fire-and-forget over the WS; the relay fans out
492
- * DM_MESSAGE_EDITED to both participants. */
493
- export function editRoomDmOnClient(client, request) {
492
+ export async function replyRoomDmOnClient(client, request, timeoutMs) {
493
+ const requestId = randomUUID();
494
+ const clientMsgId = request.clientMsgId ?? randomUUID();
495
+ client.send({
496
+ type: RoomClientMessageType.DM_REPLY,
497
+ payload: {
498
+ requestId,
499
+ content: request.content,
500
+ replyTo: request.replyTo,
501
+ clientMsgId,
502
+ ...(request.username ? { username: request.username } : {}),
503
+ ...(request.conversationId ? { conversationId: request.conversationId } : {}),
504
+ ...(request.imageUrl ? { imageUrl: request.imageUrl } : {}),
505
+ ...(request.metadata ? { metadata: request.metadata } : {}),
506
+ },
507
+ timestamp: Date.now(),
508
+ });
509
+ const sent = await client.waitFor(RoomServerMessageType.DM_MESSAGE, (msg) => msg.payload.requestId === requestId ||
510
+ msg.payload.clientMsgId === clientMsgId ||
511
+ msg.payload.message.clientMsgId === clientMsgId, timeoutMs, requestId);
512
+ return sent.payload;
513
+ }
514
+ /** Edit one of my DM messages and wait for the correlated relay update. */
515
+ export async function editRoomDmOnClient(client, request, timeoutMs) {
516
+ const requestId = randomUUID();
494
517
  client.send({
495
518
  type: RoomClientMessageType.DM_EDIT,
496
519
  payload: {
520
+ requestId,
497
521
  messageId: request.messageId,
498
522
  content: request.content,
499
523
  ...(request.conversationId ? { conversationId: request.conversationId } : {}),
@@ -501,24 +525,32 @@ export function editRoomDmOnClient(client, request) {
501
525
  },
502
526
  timestamp: Date.now(),
503
527
  });
528
+ const updated = await client.waitFor(RoomServerMessageType.DM_MESSAGE_EDITED, (msg) => msg.payload.requestId === requestId, timeoutMs, requestId);
529
+ return updated.payload;
504
530
  }
505
531
  /** Soft-delete one of my DM messages. The relay fans out DM_MESSAGE_DELETED. */
506
- export function deleteRoomDmOnClient(client, request) {
532
+ export async function deleteRoomDmOnClient(client, request, timeoutMs) {
533
+ const requestId = randomUUID();
507
534
  client.send({
508
535
  type: RoomClientMessageType.DM_DELETE,
509
536
  payload: {
537
+ requestId,
510
538
  messageId: request.messageId,
511
539
  ...(request.conversationId ? { conversationId: request.conversationId } : {}),
512
540
  ...(request.username ? { username: request.username } : {}),
513
541
  },
514
542
  timestamp: Date.now(),
515
543
  });
544
+ const updated = await client.waitFor(RoomServerMessageType.DM_MESSAGE_DELETED, (msg) => msg.payload.requestId === requestId, timeoutMs, requestId);
545
+ return updated.payload;
516
546
  }
517
547
  /** Toggle a reaction on a DM message. The relay fans out DM_REACTION_UPDATED. */
518
- export function reactRoomDmOnClient(client, request) {
548
+ export async function reactRoomDmOnClient(client, request, timeoutMs) {
549
+ const requestId = randomUUID();
519
550
  client.send({
520
551
  type: RoomClientMessageType.DM_REACT,
521
552
  payload: {
553
+ requestId,
522
554
  messageId: request.messageId,
523
555
  emoji: request.emoji,
524
556
  op: request.op,
@@ -527,6 +559,46 @@ export function reactRoomDmOnClient(client, request) {
527
559
  },
528
560
  timestamp: Date.now(),
529
561
  });
562
+ const updated = await client.waitFor(RoomServerMessageType.DM_REACTION_UPDATED, (msg) => msg.payload.requestId === requestId, timeoutMs, requestId);
563
+ return updated.payload;
564
+ }
565
+ /** Set shared pin state for a DM message. The relay fans out DM_PIN_UPDATED. */
566
+ export function pinRoomDmOnClient(client, request) {
567
+ client.send({
568
+ type: RoomClientMessageType.DM_PIN,
569
+ payload: {
570
+ messageId: request.messageId,
571
+ ...(request.conversationId ? { conversationId: request.conversationId } : {}),
572
+ ...(request.username ? { username: request.username } : {}),
573
+ },
574
+ timestamp: Date.now(),
575
+ });
576
+ }
577
+ export function unpinRoomDmOnClient(client, request) {
578
+ client.send({
579
+ type: RoomClientMessageType.DM_UNPIN,
580
+ payload: {
581
+ messageId: request.messageId,
582
+ ...(request.conversationId ? { conversationId: request.conversationId } : {}),
583
+ ...(request.username ? { username: request.username } : {}),
584
+ },
585
+ timestamp: Date.now(),
586
+ });
587
+ }
588
+ export async function requestRoomDmPinsOnClient(client, request, timeoutMs) {
589
+ const requestId = randomUUID();
590
+ client.send({
591
+ type: RoomClientMessageType.DM_PINS,
592
+ payload: {
593
+ requestId,
594
+ ...(request.conversationId ? { conversationId: request.conversationId } : {}),
595
+ ...(request.username ? { username: request.username } : {}),
596
+ ...(request.limit ? { limit: request.limit } : {}),
597
+ },
598
+ timestamp: Date.now(),
599
+ });
600
+ const result = await client.waitFor(RoomServerMessageType.DM_PINS, (message) => message.payload.requestId === requestId, timeoutMs, requestId);
601
+ return result.payload;
530
602
  }
531
603
  export async function peekRoom(config, options) {
532
604
  if (!config.webSocketCtor) {
@@ -641,7 +713,7 @@ export function attachRejoinOnReconnect(client, options, latestSeq, onRejoined,
641
713
  * (1..128 chars after trim); dedupe on (userId, clientMsgId) is server-side
642
714
  * work and NOT implied here.
643
715
  */
644
- export function postRoomMessage(client, room, text, inReplyTo, attachments, topicId, clientMsgId) {
716
+ export function postRoomMessage(client, room, text, inReplyTo, attachments, topicId, clientMsgId, metadata) {
645
717
  const msgId = clientMsgId ?? randomUUID();
646
718
  client.send({
647
719
  type: RoomClientMessageType.POST,
@@ -652,6 +724,7 @@ export function postRoomMessage(client, room, text, inReplyTo, attachments, topi
652
724
  clientMsgId: msgId,
653
725
  ...(inReplyTo !== undefined ? { inReplyTo } : {}),
654
726
  ...(topicId ? { topicId } : {}),
727
+ ...(metadata ? { metadata } : {}),
655
728
  },
656
729
  timestamp: Date.now(),
657
730
  });
@@ -37,10 +37,14 @@ export declare const RoomClientMessageType: {
37
37
  readonly DM_OPEN: "DM_OPEN";
38
38
  readonly DM_HISTORY: "DM_HISTORY";
39
39
  readonly DM_SEND: "DM_SEND";
40
+ readonly DM_REPLY: "DM_REPLY";
40
41
  readonly DM_READ: "DM_READ";
41
42
  readonly DM_EDIT: "DM_EDIT";
42
43
  readonly DM_DELETE: "DM_DELETE";
43
44
  readonly DM_REACT: "DM_REACT";
45
+ readonly DM_PIN: "DM_PIN";
46
+ readonly DM_UNPIN: "DM_UNPIN";
47
+ readonly DM_PINS: "DM_PINS";
44
48
  readonly TOPIC_CREATE: "TOPIC_CREATE";
45
49
  readonly TOPIC_RENAME: "TOPIC_RENAME";
46
50
  readonly TOPIC_MOVE: "TOPIC_MOVE";
@@ -94,6 +98,8 @@ export declare const RoomServerMessageType: {
94
98
  readonly DM_MESSAGE_EDITED: "DM_MESSAGE_EDITED";
95
99
  readonly DM_MESSAGE_DELETED: "DM_MESSAGE_DELETED";
96
100
  readonly DM_REACTION_UPDATED: "DM_REACTION_UPDATED";
101
+ readonly DM_PIN_UPDATED: "DM_PIN_UPDATED";
102
+ readonly DM_PINS: "DM_PINS";
97
103
  readonly TOPIC: "TOPIC";
98
104
  readonly TOPICS: "TOPICS";
99
105
  readonly TOPIC_UPDATED: "TOPIC_UPDATED";
@@ -225,6 +231,19 @@ export interface RoomLedgerEntry {
225
231
  pinnedAt?: string | number | Date | null | undefined;
226
232
  attachments?: RoomAttachment[] | undefined;
227
233
  roomRole?: RoomRole | null | undefined;
234
+ metadata?: (Record<string, unknown> & Partial<RoomForwardMetadata>) | undefined;
235
+ }
236
+ export type RoomForwardedFrom = {
237
+ kind: "room";
238
+ room: string;
239
+ seq: number;
240
+ handle: string;
241
+ } | {
242
+ kind: "dm";
243
+ handle: string;
244
+ };
245
+ export interface RoomForwardMetadata {
246
+ forwardedFrom: RoomForwardedFrom;
228
247
  }
229
248
  export interface RoomAttachment {
230
249
  /**
@@ -472,12 +491,14 @@ export interface RoomDmMessage {
472
491
  createdAt?: string | number | undefined;
473
492
  /** Sealed DM: content is '' and the opaque envelope rides here. */
474
493
  secret?: RoomLedgerSecretPayload | null | undefined;
475
- metadata?: Record<string, unknown> | undefined;
494
+ metadata?: (Record<string, unknown> & Partial<RoomForwardMetadata>) | undefined;
476
495
  /** Legacy public chat-image URL (renders as-is, no signing). */
477
496
  imageUrl?: string | null | undefined;
478
497
  /** Private, signed, scanned DM attachments (dm-attachments/ keyspace).
479
498
  * Additive: old messages carry none and render unchanged. */
480
499
  attachments?: RoomAttachment[] | undefined;
500
+ /** Shared pin state. Legacy messages omit it and read as unpinned. */
501
+ pinned?: boolean | undefined;
481
502
  }
482
503
  export interface RoomDmOpenPayload {
483
504
  requestId?: string;
@@ -502,6 +523,11 @@ export interface RoomDmSendPayload {
502
523
  /** DM-attachment key or legacy public image URL; stored on the message's
503
524
  * imageUrl. Additive — text-only sends omit it. */
504
525
  imageUrl?: string;
526
+ metadata?: RoomForwardMetadata | undefined;
527
+ }
528
+ /** Client → server: send a DM whose parent is another message in the same conversation. */
529
+ export interface RoomDmReplyPayload extends RoomDmSendPayload {
530
+ replyTo: string;
505
531
  }
506
532
  /** Client → server: edit one of my DM messages (sealed messages are rejected). */
507
533
  export interface RoomDmEditPayload {
@@ -520,6 +546,7 @@ export interface RoomDmDeletePayload {
520
546
  }
521
547
  /** Server → both participants: a DM message was edited. */
522
548
  export interface RoomDmMessageEditedPayload {
549
+ requestId?: string;
523
550
  conversationId: string;
524
551
  messageId: string;
525
552
  content: string;
@@ -528,6 +555,7 @@ export interface RoomDmMessageEditedPayload {
528
555
  }
529
556
  /** Server → both participants: a DM message was soft-deleted (tombstone). */
530
557
  export interface RoomDmMessageDeletedPayload {
558
+ requestId?: string;
531
559
  conversationId: string;
532
560
  messageId: string;
533
561
  deletedAt: string | number;
@@ -544,6 +572,7 @@ export interface RoomDmReactPayload {
544
572
  }
545
573
  /** Server → both participants: a DM message's aggregated reactions changed. */
546
574
  export interface RoomDmReactionUpdatedPayload {
575
+ requestId?: string;
547
576
  conversationId: string;
548
577
  messageId: string;
549
578
  reactions: Array<{
@@ -552,6 +581,31 @@ export interface RoomDmReactionUpdatedPayload {
552
581
  }>;
553
582
  participant: RoomDmParticipant;
554
583
  }
584
+ export interface RoomDmPinPayload {
585
+ requestId?: string;
586
+ conversationId?: string;
587
+ username?: string;
588
+ messageId: string;
589
+ }
590
+ export interface RoomDmPinsPayload {
591
+ requestId?: string;
592
+ conversationId?: string;
593
+ username?: string;
594
+ limit?: number;
595
+ }
596
+ export interface RoomDmPinUpdatedPayload {
597
+ requestId?: string;
598
+ conversationId: string;
599
+ participant: RoomDmParticipant;
600
+ messageId: string;
601
+ pinned: boolean;
602
+ }
603
+ export interface RoomDmPinsResultPayload {
604
+ requestId?: string;
605
+ conversationId: string;
606
+ participant: RoomDmParticipant;
607
+ pins: RoomDmMessage[];
608
+ }
555
609
  export interface RoomDmReadPayload {
556
610
  requestId?: string;
557
611
  username?: string;
@@ -889,6 +943,7 @@ export type RoomClientMessage = {
889
943
  clientMsgId?: string;
890
944
  reason?: string;
891
945
  requestId?: string;
946
+ metadata?: RoomForwardMetadata;
892
947
  };
893
948
  timestamp?: number;
894
949
  } | {
@@ -1074,6 +1129,10 @@ export type RoomClientMessage = {
1074
1129
  type: typeof RoomClientMessageType.DM_SEND;
1075
1130
  payload: RoomDmSendPayload;
1076
1131
  timestamp?: number;
1132
+ } | {
1133
+ type: typeof RoomClientMessageType.DM_REPLY;
1134
+ payload: RoomDmReplyPayload;
1135
+ timestamp?: number;
1077
1136
  } | {
1078
1137
  type: typeof RoomClientMessageType.DM_READ;
1079
1138
  payload: RoomDmReadPayload;
@@ -1090,6 +1149,18 @@ export type RoomClientMessage = {
1090
1149
  type: typeof RoomClientMessageType.DM_REACT;
1091
1150
  payload: RoomDmReactPayload;
1092
1151
  timestamp?: number;
1152
+ } | {
1153
+ type: typeof RoomClientMessageType.DM_PIN;
1154
+ payload: RoomDmPinPayload;
1155
+ timestamp?: number;
1156
+ } | {
1157
+ type: typeof RoomClientMessageType.DM_UNPIN;
1158
+ payload: RoomDmPinPayload;
1159
+ timestamp?: number;
1160
+ } | {
1161
+ type: typeof RoomClientMessageType.DM_PINS;
1162
+ payload: RoomDmPinsPayload;
1163
+ timestamp?: number;
1093
1164
  } | {
1094
1165
  type: typeof RoomClientMessageType.TOPIC_CREATE;
1095
1166
  payload: RoomTopicCreatePayload;
@@ -1296,6 +1367,14 @@ export type RoomServerMessage = {
1296
1367
  type: typeof RoomServerMessageType.DM_REACTION_UPDATED;
1297
1368
  payload: RoomDmReactionUpdatedPayload;
1298
1369
  timestamp: number;
1370
+ } | {
1371
+ type: typeof RoomServerMessageType.DM_PIN_UPDATED;
1372
+ payload: RoomDmPinUpdatedPayload;
1373
+ timestamp: number;
1374
+ } | {
1375
+ type: typeof RoomServerMessageType.DM_PINS;
1376
+ payload: RoomDmPinsResultPayload;
1377
+ timestamp: number;
1299
1378
  } | {
1300
1379
  type: typeof RoomServerMessageType.TOPIC;
1301
1380
  payload: RoomTopicResultPayload;
@@ -37,10 +37,14 @@ export const RoomClientMessageType = {
37
37
  DM_OPEN: "DM_OPEN",
38
38
  DM_HISTORY: "DM_HISTORY",
39
39
  DM_SEND: "DM_SEND",
40
+ DM_REPLY: "DM_REPLY",
40
41
  DM_READ: "DM_READ",
41
42
  DM_EDIT: "DM_EDIT",
42
43
  DM_DELETE: "DM_DELETE",
43
44
  DM_REACT: "DM_REACT",
45
+ DM_PIN: "DM_PIN",
46
+ DM_UNPIN: "DM_UNPIN",
47
+ DM_PINS: "DM_PINS",
44
48
  TOPIC_CREATE: "TOPIC_CREATE",
45
49
  TOPIC_RENAME: "TOPIC_RENAME",
46
50
  TOPIC_MOVE: "TOPIC_MOVE",
@@ -93,6 +97,8 @@ export const RoomServerMessageType = {
93
97
  DM_MESSAGE_EDITED: "DM_MESSAGE_EDITED",
94
98
  DM_MESSAGE_DELETED: "DM_MESSAGE_DELETED",
95
99
  DM_REACTION_UPDATED: "DM_REACTION_UPDATED",
100
+ DM_PIN_UPDATED: "DM_PIN_UPDATED",
101
+ DM_PINS: "DM_PINS",
96
102
  TOPIC: "TOPIC",
97
103
  TOPICS: "TOPICS",
98
104
  TOPIC_UPDATED: "TOPIC_UPDATED",
@@ -130,6 +130,8 @@ export interface RoomDmMessage {
130
130
  emoji: string;
131
131
  users: string[];
132
132
  }>;
133
+ /** Shared pin state. Additive; absent means unpinned. */
134
+ pinned?: boolean;
133
135
  /** Client-minted idempotency tag echoed back on DM sends, so a sender's
134
136
  * durable queue can settle its optimistic row. Additive (0.4.0). */
135
137
  clientMsgId?: string;
package/dist/types.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export type { RoomAccessMode, RoomAttachment, RoomAttachmentInput, RoomAuditEntry, RoomAuditLogPayload, RoomAuditLogRequestPayload, RoomAuthSuccessPayload, RoomBackfillPayload, RoomClientMessage, RoomClientPlatform, RoomCreatedPayload, RoomCreatePayload, RoomDmHistoryPayload, RoomDmHistoryResultPayload, RoomDmInboxUpdatedPayload, RoomDmMessage, RoomDmMessagePayload, RoomDmOpenedPayload, RoomDmOpenPayload, RoomDmParticipant, RoomDmReadPayload, RoomDmSendPayload, RoomEntryUpdatedPayload, RoomErrorPayload, RoomFriendPresence, RoomInvitedPayload, RoomInvitePayload, RoomLedgerEntry, RoomMember, RoomMemberRemovedPayload, RoomMemberRoleChangedPayload, RoomMemberTier, RoomMessagePayload, RoomMeta, RoomModerateMemberPayload, RoomMutedPayload, RoomPinsPayload, RoomPresenceDeltaPayload, RoomPresencePayload, RoomReactorsPayload, RoomReadStatePayload, RoomRemoveMemberPayload, RoomReportedPayload, RoomReportPayload, RoomResyncPayload, RoomRole, RoomRoleChangePayload, RoomSearchPayload, RoomSearchResultsPayload, RoomSearchScope, RoomServerMessage, RoomServerMessageOf, RoomSetAttentionPayload, RoomSetReadOnlyPayload, RoomSpace, RoomSpaceJoinedPayload, RoomSpacesPayload, RoomThreadPayload, RoomTopic, RoomTopicAttention, RoomTopicBucketState, RoomTopicCreatePayload, RoomTopicListPayload, RoomTopicMergePayload, RoomTopicMovePayload, RoomTopicRenamePayload, RoomTopicResolvePayload, RoomTopicResultPayload, RoomTopicSetAttentionPayload, RoomTopicsPolicy, RoomTopicsResultPayload, RoomTopicUpdatedPayload, RoomTypingPayload, RoomUserStatus, RoomWhoPayload, } from "./shared/rooms-protocol.js";
1
+ export type { RoomAccessMode, RoomAttachment, RoomAttachmentInput, RoomAuditEntry, RoomAuditLogPayload, RoomAuditLogRequestPayload, RoomAuthSuccessPayload, RoomBackfillPayload, RoomClientMessage, RoomClientPlatform, RoomCreatedPayload, RoomCreatePayload, RoomDmHistoryPayload, RoomDmHistoryResultPayload, RoomDmInboxUpdatedPayload, RoomDmMessage, RoomDmMessageDeletedPayload, RoomDmMessageEditedPayload, RoomDmMessagePayload, RoomDmOpenedPayload, RoomDmOpenPayload, RoomDmParticipant, RoomDmPinsResultPayload, RoomDmPinUpdatedPayload, RoomDmReactionUpdatedPayload, RoomDmReadPayload, RoomDmReplyPayload, RoomDmSendPayload, RoomEntryUpdatedPayload, RoomErrorPayload, RoomForwardedFrom, RoomForwardMetadata, RoomFriendPresence, RoomInvitedPayload, RoomInvitePayload, RoomLedgerEntry, RoomMember, RoomMemberRemovedPayload, RoomMemberRoleChangedPayload, RoomMemberTier, RoomMessagePayload, RoomMeta, RoomModerateMemberPayload, RoomMutedPayload, RoomPinsPayload, RoomPresenceDeltaPayload, RoomPresencePayload, RoomReactorsPayload, RoomReadStatePayload, RoomRemoveMemberPayload, RoomReportedPayload, RoomReportPayload, RoomResyncPayload, RoomRole, RoomRoleChangePayload, RoomSearchPayload, RoomSearchResultsPayload, RoomSearchScope, RoomServerMessage, RoomServerMessageOf, RoomSetAttentionPayload, RoomSetReadOnlyPayload, RoomSpace, RoomSpaceJoinedPayload, RoomSpacesPayload, RoomThreadPayload, RoomTopic, RoomTopicAttention, RoomTopicBucketState, RoomTopicCreatePayload, RoomTopicListPayload, RoomTopicMergePayload, RoomTopicMovePayload, RoomTopicRenamePayload, RoomTopicResolvePayload, RoomTopicResultPayload, RoomTopicSetAttentionPayload, RoomTopicsPolicy, RoomTopicsResultPayload, RoomTopicUpdatedPayload, RoomTypingPayload, RoomUserStatus, RoomWhoPayload, } from "./shared/rooms-protocol.js";
2
2
  export { applyRoomPresenceDelta, isSystemRoomLedgerEntryType, ROOM_PRESENCE_SAMPLE_LIMIT, RoomClientMessageType, RoomLedgerEntryType, RoomServerMessageType, SUPPORTED_ROOM_PROTOCOL_VERSION, } from "./shared/rooms-protocol.js";
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.6.0";
2
- export declare const RUNNER_VERSION = "0.6.0";
1
+ export declare const VERSION = "0.7.0";
2
+ export declare const RUNNER_VERSION = "0.7.0";
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
- export const VERSION = "0.6.0";
2
- export const RUNNER_VERSION = "0.6.0";
1
+ export const VERSION = "0.7.0";
2
+ export const RUNNER_VERSION = "0.7.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openmarket/rooms-client",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "OM Rooms protocol client: wire types, WebSocket + REST clients, and chat view-models. Browser-safe (no node:/bun: imports).",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -17,7 +17,12 @@
17
17
  "bun": ">=1.3.0",
18
18
  "node": ">=22"
19
19
  },
20
- "files": ["src", "dist", "README.md", "LICENSE"],
20
+ "files": [
21
+ "src",
22
+ "dist",
23
+ "README.md",
24
+ "LICENSE"
25
+ ],
21
26
  "publishConfig": {
22
27
  "access": "public"
23
28
  },
package/src/client.ts CHANGED
@@ -16,8 +16,13 @@ import {
16
16
  type RoomClientPlatform,
17
17
  type RoomDmHistoryResultPayload,
18
18
  type RoomDmInboxUpdatedPayload,
19
+ type RoomDmMessageDeletedPayload,
20
+ type RoomDmMessageEditedPayload,
19
21
  type RoomDmMessagePayload,
20
22
  type RoomDmOpenedPayload,
23
+ type RoomDmPinsResultPayload,
24
+ type RoomDmReactionUpdatedPayload,
25
+ type RoomForwardMetadata,
21
26
  type RoomFriendPresence,
22
27
  type RoomInvitedPayload,
23
28
  type RoomLedgerEntry,
@@ -292,6 +297,11 @@ export interface RoomDmSendRequest {
292
297
  * URL. Stored on the message's imageUrl; the client signs keys on render.
293
298
  * Additive — omitted for text-only sends. */
294
299
  imageUrl?: string;
300
+ metadata?: RoomForwardMetadata;
301
+ }
302
+
303
+ export interface RoomDmReplyRequest extends RoomDmSendRequest {
304
+ replyTo: string;
295
305
  }
296
306
 
297
307
  export interface RoomDmReadRequest {
@@ -969,6 +979,40 @@ export async function sendRoomDmOnClient(
969
979
  ...(request.username ? { username: request.username } : {}),
970
980
  ...(request.conversationId ? { conversationId: request.conversationId } : {}),
971
981
  ...(request.imageUrl ? { imageUrl: request.imageUrl } : {}),
982
+ ...(request.metadata ? { metadata: request.metadata } : {}),
983
+ },
984
+ timestamp: Date.now(),
985
+ });
986
+ const sent = await client.waitFor(
987
+ RoomServerMessageType.DM_MESSAGE,
988
+ (msg) =>
989
+ msg.payload.requestId === requestId ||
990
+ msg.payload.clientMsgId === clientMsgId ||
991
+ msg.payload.message.clientMsgId === clientMsgId,
992
+ timeoutMs,
993
+ requestId,
994
+ );
995
+ return sent.payload;
996
+ }
997
+
998
+ export async function replyRoomDmOnClient(
999
+ client: RoomWsClient,
1000
+ request: RoomDmReplyRequest,
1001
+ timeoutMs?: number,
1002
+ ): Promise<RoomDmMessagePayload> {
1003
+ const requestId = randomUUID();
1004
+ const clientMsgId = request.clientMsgId ?? randomUUID();
1005
+ client.send({
1006
+ type: RoomClientMessageType.DM_REPLY,
1007
+ payload: {
1008
+ requestId,
1009
+ content: request.content,
1010
+ replyTo: request.replyTo,
1011
+ clientMsgId,
1012
+ ...(request.username ? { username: request.username } : {}),
1013
+ ...(request.conversationId ? { conversationId: request.conversationId } : {}),
1014
+ ...(request.imageUrl ? { imageUrl: request.imageUrl } : {}),
1015
+ ...(request.metadata ? { metadata: request.metadata } : {}),
972
1016
  },
973
1017
  timestamp: Date.now(),
974
1018
  });
@@ -984,15 +1028,17 @@ export async function sendRoomDmOnClient(
984
1028
  return sent.payload;
985
1029
  }
986
1030
 
987
- /** Edit one of my DM messages. Fire-and-forget over the WS; the relay fans out
988
- * DM_MESSAGE_EDITED to both participants. */
989
- export function editRoomDmOnClient(
1031
+ /** Edit one of my DM messages and wait for the correlated relay update. */
1032
+ export async function editRoomDmOnClient(
990
1033
  client: RoomWsClient,
991
1034
  request: { conversationId?: string; username?: string; messageId: string; content: string },
992
- ): void {
1035
+ timeoutMs?: number,
1036
+ ): Promise<RoomDmMessageEditedPayload> {
1037
+ const requestId = randomUUID();
993
1038
  client.send({
994
1039
  type: RoomClientMessageType.DM_EDIT,
995
1040
  payload: {
1041
+ requestId,
996
1042
  messageId: request.messageId,
997
1043
  content: request.content,
998
1044
  ...(request.conversationId ? { conversationId: request.conversationId } : {}),
@@ -1000,26 +1046,43 @@ export function editRoomDmOnClient(
1000
1046
  },
1001
1047
  timestamp: Date.now(),
1002
1048
  });
1049
+ const updated = await client.waitFor(
1050
+ RoomServerMessageType.DM_MESSAGE_EDITED,
1051
+ (msg) => msg.payload.requestId === requestId,
1052
+ timeoutMs,
1053
+ requestId,
1054
+ );
1055
+ return updated.payload;
1003
1056
  }
1004
1057
 
1005
1058
  /** Soft-delete one of my DM messages. The relay fans out DM_MESSAGE_DELETED. */
1006
- export function deleteRoomDmOnClient(
1059
+ export async function deleteRoomDmOnClient(
1007
1060
  client: RoomWsClient,
1008
1061
  request: { conversationId?: string; username?: string; messageId: string },
1009
- ): void {
1062
+ timeoutMs?: number,
1063
+ ): Promise<RoomDmMessageDeletedPayload> {
1064
+ const requestId = randomUUID();
1010
1065
  client.send({
1011
1066
  type: RoomClientMessageType.DM_DELETE,
1012
1067
  payload: {
1068
+ requestId,
1013
1069
  messageId: request.messageId,
1014
1070
  ...(request.conversationId ? { conversationId: request.conversationId } : {}),
1015
1071
  ...(request.username ? { username: request.username } : {}),
1016
1072
  },
1017
1073
  timestamp: Date.now(),
1018
1074
  });
1075
+ const updated = await client.waitFor(
1076
+ RoomServerMessageType.DM_MESSAGE_DELETED,
1077
+ (msg) => msg.payload.requestId === requestId,
1078
+ timeoutMs,
1079
+ requestId,
1080
+ );
1081
+ return updated.payload;
1019
1082
  }
1020
1083
 
1021
1084
  /** Toggle a reaction on a DM message. The relay fans out DM_REACTION_UPDATED. */
1022
- export function reactRoomDmOnClient(
1085
+ export async function reactRoomDmOnClient(
1023
1086
  client: RoomWsClient,
1024
1087
  request: {
1025
1088
  conversationId?: string;
@@ -1028,10 +1091,13 @@ export function reactRoomDmOnClient(
1028
1091
  emoji: string;
1029
1092
  op: "add" | "remove";
1030
1093
  },
1031
- ): void {
1094
+ timeoutMs?: number,
1095
+ ): Promise<RoomDmReactionUpdatedPayload> {
1096
+ const requestId = randomUUID();
1032
1097
  client.send({
1033
1098
  type: RoomClientMessageType.DM_REACT,
1034
1099
  payload: {
1100
+ requestId,
1035
1101
  messageId: request.messageId,
1036
1102
  emoji: request.emoji,
1037
1103
  op: request.op,
@@ -1040,6 +1106,69 @@ export function reactRoomDmOnClient(
1040
1106
  },
1041
1107
  timestamp: Date.now(),
1042
1108
  });
1109
+ const updated = await client.waitFor(
1110
+ RoomServerMessageType.DM_REACTION_UPDATED,
1111
+ (msg) => msg.payload.requestId === requestId,
1112
+ timeoutMs,
1113
+ requestId,
1114
+ );
1115
+ return updated.payload;
1116
+ }
1117
+
1118
+ /** Set shared pin state for a DM message. The relay fans out DM_PIN_UPDATED. */
1119
+ export function pinRoomDmOnClient(
1120
+ client: RoomWsClient,
1121
+ request: { conversationId?: string; username?: string; messageId: string },
1122
+ ): void {
1123
+ client.send({
1124
+ type: RoomClientMessageType.DM_PIN,
1125
+ payload: {
1126
+ messageId: request.messageId,
1127
+ ...(request.conversationId ? { conversationId: request.conversationId } : {}),
1128
+ ...(request.username ? { username: request.username } : {}),
1129
+ },
1130
+ timestamp: Date.now(),
1131
+ });
1132
+ }
1133
+
1134
+ export function unpinRoomDmOnClient(
1135
+ client: RoomWsClient,
1136
+ request: { conversationId?: string; username?: string; messageId: string },
1137
+ ): void {
1138
+ client.send({
1139
+ type: RoomClientMessageType.DM_UNPIN,
1140
+ payload: {
1141
+ messageId: request.messageId,
1142
+ ...(request.conversationId ? { conversationId: request.conversationId } : {}),
1143
+ ...(request.username ? { username: request.username } : {}),
1144
+ },
1145
+ timestamp: Date.now(),
1146
+ });
1147
+ }
1148
+
1149
+ export async function requestRoomDmPinsOnClient(
1150
+ client: RoomWsClient,
1151
+ request: { conversationId?: string; username?: string; limit?: number },
1152
+ timeoutMs?: number,
1153
+ ): Promise<RoomDmPinsResultPayload> {
1154
+ const requestId = randomUUID();
1155
+ client.send({
1156
+ type: RoomClientMessageType.DM_PINS,
1157
+ payload: {
1158
+ requestId,
1159
+ ...(request.conversationId ? { conversationId: request.conversationId } : {}),
1160
+ ...(request.username ? { username: request.username } : {}),
1161
+ ...(request.limit ? { limit: request.limit } : {}),
1162
+ },
1163
+ timestamp: Date.now(),
1164
+ });
1165
+ const result = await client.waitFor(
1166
+ RoomServerMessageType.DM_PINS,
1167
+ (message) => message.payload.requestId === requestId,
1168
+ timeoutMs,
1169
+ requestId,
1170
+ );
1171
+ return result.payload;
1043
1172
  }
1044
1173
 
1045
1174
  export async function peekRoom(
@@ -1195,6 +1324,7 @@ export function postRoomMessage(
1195
1324
  attachments?: RoomAttachmentInput[],
1196
1325
  topicId?: string,
1197
1326
  clientMsgId?: string,
1327
+ metadata?: RoomForwardMetadata,
1198
1328
  ): string {
1199
1329
  const msgId = clientMsgId ?? randomUUID();
1200
1330
  client.send({
@@ -1206,6 +1336,7 @@ export function postRoomMessage(
1206
1336
  clientMsgId: msgId,
1207
1337
  ...(inReplyTo !== undefined ? { inReplyTo } : {}),
1208
1338
  ...(topicId ? { topicId } : {}),
1339
+ ...(metadata ? { metadata } : {}),
1209
1340
  },
1210
1341
  timestamp: Date.now(),
1211
1342
  });
@@ -37,10 +37,14 @@ export const RoomClientMessageType = {
37
37
  DM_OPEN: "DM_OPEN",
38
38
  DM_HISTORY: "DM_HISTORY",
39
39
  DM_SEND: "DM_SEND",
40
+ DM_REPLY: "DM_REPLY",
40
41
  DM_READ: "DM_READ",
41
42
  DM_EDIT: "DM_EDIT",
42
43
  DM_DELETE: "DM_DELETE",
43
44
  DM_REACT: "DM_REACT",
45
+ DM_PIN: "DM_PIN",
46
+ DM_UNPIN: "DM_UNPIN",
47
+ DM_PINS: "DM_PINS",
44
48
  TOPIC_CREATE: "TOPIC_CREATE",
45
49
  TOPIC_RENAME: "TOPIC_RENAME",
46
50
  TOPIC_MOVE: "TOPIC_MOVE",
@@ -97,6 +101,8 @@ export const RoomServerMessageType = {
97
101
  DM_MESSAGE_EDITED: "DM_MESSAGE_EDITED",
98
102
  DM_MESSAGE_DELETED: "DM_MESSAGE_DELETED",
99
103
  DM_REACTION_UPDATED: "DM_REACTION_UPDATED",
104
+ DM_PIN_UPDATED: "DM_PIN_UPDATED",
105
+ DM_PINS: "DM_PINS",
100
106
  TOPIC: "TOPIC",
101
107
  TOPICS: "TOPICS",
102
108
  TOPIC_UPDATED: "TOPIC_UPDATED",
@@ -253,6 +259,23 @@ export interface RoomLedgerEntry {
253
259
  pinnedAt?: string | number | Date | null | undefined;
254
260
  attachments?: RoomAttachment[] | undefined;
255
261
  roomRole?: RoomRole | null | undefined;
262
+ metadata?: (Record<string, unknown> & Partial<RoomForwardMetadata>) | undefined;
263
+ }
264
+
265
+ export type RoomForwardedFrom =
266
+ | {
267
+ kind: "room";
268
+ room: string;
269
+ seq: number;
270
+ handle: string;
271
+ }
272
+ | {
273
+ kind: "dm";
274
+ handle: string;
275
+ };
276
+
277
+ export interface RoomForwardMetadata {
278
+ forwardedFrom: RoomForwardedFrom;
256
279
  }
257
280
 
258
281
  export interface RoomAttachment {
@@ -560,12 +583,14 @@ export interface RoomDmMessage {
560
583
  createdAt?: string | number | undefined;
561
584
  /** Sealed DM: content is '' and the opaque envelope rides here. */
562
585
  secret?: RoomLedgerSecretPayload | null | undefined;
563
- metadata?: Record<string, unknown> | undefined;
586
+ metadata?: (Record<string, unknown> & Partial<RoomForwardMetadata>) | undefined;
564
587
  /** Legacy public chat-image URL (renders as-is, no signing). */
565
588
  imageUrl?: string | null | undefined;
566
589
  /** Private, signed, scanned DM attachments (dm-attachments/ keyspace).
567
590
  * Additive: old messages carry none and render unchanged. */
568
591
  attachments?: RoomAttachment[] | undefined;
592
+ /** Shared pin state. Legacy messages omit it and read as unpinned. */
593
+ pinned?: boolean | undefined;
569
594
  }
570
595
 
571
596
  export interface RoomDmOpenPayload {
@@ -593,6 +618,12 @@ export interface RoomDmSendPayload {
593
618
  /** DM-attachment key or legacy public image URL; stored on the message's
594
619
  * imageUrl. Additive — text-only sends omit it. */
595
620
  imageUrl?: string;
621
+ metadata?: RoomForwardMetadata | undefined;
622
+ }
623
+
624
+ /** Client → server: send a DM whose parent is another message in the same conversation. */
625
+ export interface RoomDmReplyPayload extends RoomDmSendPayload {
626
+ replyTo: string;
596
627
  }
597
628
 
598
629
  /** Client → server: edit one of my DM messages (sealed messages are rejected). */
@@ -614,6 +645,7 @@ export interface RoomDmDeletePayload {
614
645
 
615
646
  /** Server → both participants: a DM message was edited. */
616
647
  export interface RoomDmMessageEditedPayload {
648
+ requestId?: string;
617
649
  conversationId: string;
618
650
  messageId: string;
619
651
  content: string;
@@ -623,6 +655,7 @@ export interface RoomDmMessageEditedPayload {
623
655
 
624
656
  /** Server → both participants: a DM message was soft-deleted (tombstone). */
625
657
  export interface RoomDmMessageDeletedPayload {
658
+ requestId?: string;
626
659
  conversationId: string;
627
660
  messageId: string;
628
661
  deletedAt: string | number;
@@ -641,12 +674,42 @@ export interface RoomDmReactPayload {
641
674
 
642
675
  /** Server → both participants: a DM message's aggregated reactions changed. */
643
676
  export interface RoomDmReactionUpdatedPayload {
677
+ requestId?: string;
644
678
  conversationId: string;
645
679
  messageId: string;
646
680
  reactions: Array<{ emoji: string; users: string[] }>;
647
681
  participant: RoomDmParticipant;
648
682
  }
649
683
 
684
+ export interface RoomDmPinPayload {
685
+ requestId?: string;
686
+ conversationId?: string;
687
+ username?: string;
688
+ messageId: string;
689
+ }
690
+
691
+ export interface RoomDmPinsPayload {
692
+ requestId?: string;
693
+ conversationId?: string;
694
+ username?: string;
695
+ limit?: number;
696
+ }
697
+
698
+ export interface RoomDmPinUpdatedPayload {
699
+ requestId?: string;
700
+ conversationId: string;
701
+ participant: RoomDmParticipant;
702
+ messageId: string;
703
+ pinned: boolean;
704
+ }
705
+
706
+ export interface RoomDmPinsResultPayload {
707
+ requestId?: string;
708
+ conversationId: string;
709
+ participant: RoomDmParticipant;
710
+ pins: RoomDmMessage[];
711
+ }
712
+
650
713
  export interface RoomDmReadPayload {
651
714
  requestId?: string;
652
715
  username?: string;
@@ -1014,6 +1077,7 @@ export type RoomClientMessage =
1014
1077
  clientMsgId?: string;
1015
1078
  reason?: string;
1016
1079
  requestId?: string;
1080
+ metadata?: RoomForwardMetadata;
1017
1081
  };
1018
1082
  timestamp?: number;
1019
1083
  }
@@ -1189,6 +1253,11 @@ export type RoomClientMessage =
1189
1253
  payload: RoomDmSendPayload;
1190
1254
  timestamp?: number;
1191
1255
  }
1256
+ | {
1257
+ type: typeof RoomClientMessageType.DM_REPLY;
1258
+ payload: RoomDmReplyPayload;
1259
+ timestamp?: number;
1260
+ }
1192
1261
  | {
1193
1262
  type: typeof RoomClientMessageType.DM_READ;
1194
1263
  payload: RoomDmReadPayload;
@@ -1209,6 +1278,21 @@ export type RoomClientMessage =
1209
1278
  payload: RoomDmReactPayload;
1210
1279
  timestamp?: number;
1211
1280
  }
1281
+ | {
1282
+ type: typeof RoomClientMessageType.DM_PIN;
1283
+ payload: RoomDmPinPayload;
1284
+ timestamp?: number;
1285
+ }
1286
+ | {
1287
+ type: typeof RoomClientMessageType.DM_UNPIN;
1288
+ payload: RoomDmPinPayload;
1289
+ timestamp?: number;
1290
+ }
1291
+ | {
1292
+ type: typeof RoomClientMessageType.DM_PINS;
1293
+ payload: RoomDmPinsPayload;
1294
+ timestamp?: number;
1295
+ }
1212
1296
  | {
1213
1297
  type: typeof RoomClientMessageType.TOPIC_CREATE;
1214
1298
  payload: RoomTopicCreatePayload;
@@ -1461,6 +1545,16 @@ export type RoomServerMessage =
1461
1545
  payload: RoomDmReactionUpdatedPayload;
1462
1546
  timestamp: number;
1463
1547
  }
1548
+ | {
1549
+ type: typeof RoomServerMessageType.DM_PIN_UPDATED;
1550
+ payload: RoomDmPinUpdatedPayload;
1551
+ timestamp: number;
1552
+ }
1553
+ | {
1554
+ type: typeof RoomServerMessageType.DM_PINS;
1555
+ payload: RoomDmPinsResultPayload;
1556
+ timestamp: number;
1557
+ }
1464
1558
  | {
1465
1559
  type: typeof RoomServerMessageType.TOPIC;
1466
1560
  payload: RoomTopicResultPayload;
@@ -144,6 +144,8 @@ export interface RoomDmMessage {
144
144
  imageUrl?: string | null;
145
145
  /** Aggregated reactions (per-emoji userId lists). Additive. */
146
146
  reactions?: Array<{ emoji: string; users: string[] }>;
147
+ /** Shared pin state. Additive; absent means unpinned. */
148
+ pinned?: boolean;
147
149
  /** Client-minted idempotency tag echoed back on DM sends, so a sender's
148
150
  * durable queue can settle its optimistic row. Additive (0.4.0). */
149
151
  clientMsgId?: string;
package/src/types.ts CHANGED
@@ -15,14 +15,22 @@ export type {
15
15
  RoomDmHistoryResultPayload,
16
16
  RoomDmInboxUpdatedPayload,
17
17
  RoomDmMessage,
18
+ RoomDmMessageDeletedPayload,
19
+ RoomDmMessageEditedPayload,
18
20
  RoomDmMessagePayload,
19
21
  RoomDmOpenedPayload,
20
22
  RoomDmOpenPayload,
21
23
  RoomDmParticipant,
24
+ RoomDmPinsResultPayload,
25
+ RoomDmPinUpdatedPayload,
26
+ RoomDmReactionUpdatedPayload,
22
27
  RoomDmReadPayload,
28
+ RoomDmReplyPayload,
23
29
  RoomDmSendPayload,
24
30
  RoomEntryUpdatedPayload,
25
31
  RoomErrorPayload,
32
+ RoomForwardedFrom,
33
+ RoomForwardMetadata,
26
34
  RoomFriendPresence,
27
35
  RoomInvitedPayload,
28
36
  RoomInvitePayload,
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
- export const VERSION = "0.6.0";
2
- export const RUNNER_VERSION = "0.6.0";
1
+ export const VERSION = "0.7.0";
2
+ export const RUNNER_VERSION = "0.7.0";