@openmarket/rooms-client 0.4.0 → 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/agent/lane-prompts.js +1 -1
- package/dist/agent/room-context.d.ts +7 -0
- package/dist/agent/room-context.js +6 -2
- package/dist/client.d.ts +31 -6
- package/dist/client.js +93 -6
- package/dist/shared/rooms-protocol.d.ts +81 -1
- package/dist/shared/rooms-protocol.js +6 -0
- package/dist/social-client.d.ts +3 -2
- package/dist/social-types.d.ts +2 -0
- package/dist/types.d.ts +1 -1
- package/dist/version.d.ts +2 -2
- package/dist/version.js +2 -2
- package/package.json +7 -2
- package/src/agent/lane-prompts.ts +1 -1
- package/src/agent/room-context.ts +13 -2
- package/src/client.ts +169 -8
- package/src/shared/rooms-protocol.ts +96 -1
- package/src/social-client.ts +3 -2
- package/src/social-types.ts +2 -0
- package/src/types.ts +8 -0
- package/src/version.ts +2 -2
|
@@ -96,7 +96,7 @@ export function buildMergeProposalBootstrap(opts) {
|
|
|
96
96
|
/** The librarian bootstrap for `/brief refresh`: the agent rewrites the
|
|
97
97
|
* room's brief doc itself, in the canonical structure renderBrief pins. */
|
|
98
98
|
export function buildBriefRefreshBootstrap(opts) {
|
|
99
|
-
return lines(opts.personaLine, `You are the LIBRARIAN for ${opts.label}. Maintain its brief: a concise, current snapshot.`, "1. Read the recent conversation with room_history for this room.", `2. Read the existing brief if any: doc_read spaceId ${opts.spaceId}, path ${opts.path}.`, `3. List the docs in play with doc_list (spaceId ${opts.spaceId}).`, `4. Write the brief with doc_write (spaceId ${opts.spaceId}, path ${opts.path}, a note describing what changed), following EXACTLY this structure:`, "", `# Brief: ${opts.label}`, "", `> Auto-generated by the room agent, read-only. Updated ${opts.nowLabel}.`, "", "## Summary", "<one or two short paragraphs on what this room is about and where it stands>", "", "## Open
|
|
99
|
+
return lines(opts.personaLine, `You are the LIBRARIAN for ${opts.label}. Maintain its brief: a concise, current snapshot.`, "1. Read the recent conversation with room_history for this room.", `2. Read the existing brief if any: doc_read spaceId ${opts.spaceId}, path ${opts.path}.`, `3. List the docs in play with doc_list (spaceId ${opts.spaceId}).`, `4. Write the brief with doc_write (spaceId ${opts.spaceId}, path ${opts.path}, a note describing what changed), following EXACTLY this structure:`, "", `# Brief: ${opts.label}`, "", `> Auto-generated by the room agent, read-only. Updated ${opts.nowLabel}.`, "", "## Summary", "<one or two short paragraphs on what this room is about and where it stands>", "", "## Open questions", "- <unresolved questions, or `None.`>", "", "## Decisions", "- <decisions reached, or `None yet.`>", "", "## Docs in play", "- `path` (rN, when) for each referenced doc, or `None referenced.`", "", "Keep it tight and factual. Do NOT output a DRAFT line. After writing, reply with one line naming the revision you wrote.");
|
|
100
100
|
}
|
|
101
101
|
/** The scoped-summarize turn message. It runs on the DEFAULT lane bootstrap
|
|
102
102
|
* (context spine + citation teaching already present); the message carries
|
|
@@ -107,7 +107,14 @@ export interface BriefInput {
|
|
|
107
107
|
openThreads: string[];
|
|
108
108
|
decisions: string[];
|
|
109
109
|
docs: BriefDocRef[];
|
|
110
|
+
/** Highest message seq this brief has incorporated. Rendered into the
|
|
111
|
+
* banner as the librarian's shared cursor; co-librarians read it before
|
|
112
|
+
* spending anything. */
|
|
113
|
+
coveredSeq?: number;
|
|
110
114
|
}
|
|
115
|
+
/** The banner's machine-readable coverage claim. Parsers must only consult
|
|
116
|
+
* the banner blockquote line, never body prose. */
|
|
117
|
+
export declare const BRIEF_COVERED_RE: RegExp;
|
|
111
118
|
/** Render the canonical brief markdown. Deterministic shell; the LLM only
|
|
112
119
|
* supplies the summary/threads/decisions prose. */
|
|
113
120
|
export declare function renderBrief(input: BriefInput): string;
|
|
@@ -128,19 +128,23 @@ export function briefPath(roomName) {
|
|
|
128
128
|
.slice(0, 60) || "room";
|
|
129
129
|
return `briefs/${slug}.md`;
|
|
130
130
|
}
|
|
131
|
+
/** The banner's machine-readable coverage claim. Parsers must only consult
|
|
132
|
+
* the banner blockquote line, never body prose. */
|
|
133
|
+
export const BRIEF_COVERED_RE = /\bCovers through seq (\d+)\./;
|
|
131
134
|
/** Render the canonical brief markdown. Deterministic shell; the LLM only
|
|
132
135
|
* supplies the summary/threads/decisions prose. */
|
|
133
136
|
export function renderBrief(input) {
|
|
137
|
+
const covered = input.coveredSeq !== undefined ? ` Covers through seq ${input.coveredSeq}.` : "";
|
|
134
138
|
const lines = [];
|
|
135
139
|
lines.push(`# Brief: ${input.room}`);
|
|
136
140
|
lines.push("");
|
|
137
|
-
lines.push(`> Auto-generated by the room agent, read-only. Updated ${input.updatedAtLabel}
|
|
141
|
+
lines.push(`> Auto-generated by the room agent, read-only. Updated ${input.updatedAtLabel}.${covered}`);
|
|
138
142
|
lines.push("");
|
|
139
143
|
lines.push("## Summary");
|
|
140
144
|
lines.push("");
|
|
141
145
|
lines.push(input.summary.trim() || "_No summary yet._");
|
|
142
146
|
lines.push("");
|
|
143
|
-
lines.push("## Open
|
|
147
|
+
lines.push("## Open questions");
|
|
144
148
|
lines.push("");
|
|
145
149
|
if (input.openThreads.length === 0)
|
|
146
150
|
lines.push("_None._");
|
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 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,14 @@ 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;
|
|
219
|
+
}
|
|
220
|
+
export interface RoomDmReadRequest {
|
|
221
|
+
username?: string;
|
|
222
|
+
conversationId?: string;
|
|
215
223
|
}
|
|
216
224
|
export interface RoomThreadRequest {
|
|
217
225
|
room: string;
|
|
@@ -254,21 +262,22 @@ export declare function whoamiRoom(config: RoomClientConfig): Promise<RoomAuthSu
|
|
|
254
262
|
export declare function requestRoomFriends(client: RoomWsClient): Promise<RoomFriendPresence[]>;
|
|
255
263
|
export declare function openRoomDmOnClient(client: RoomWsClient, request: RoomDmOpenRequest, timeoutMs?: number): Promise<RoomDmOpenedPayload>;
|
|
256
264
|
export declare function requestRoomDmHistoryOnClient(client: RoomWsClient, request: RoomDmHistoryRequest, timeoutMs?: number): Promise<RoomDmHistoryResultPayload>;
|
|
265
|
+
export declare function markRoomDmReadOnClient(client: RoomWsClient, request: RoomDmReadRequest, timeoutMs?: number): Promise<RoomDmInboxUpdatedPayload>;
|
|
257
266
|
export declare function sendRoomDmOnClient(client: RoomWsClient, request: RoomDmSendRequest, timeoutMs?: number): Promise<RoomDmMessagePayload>;
|
|
258
|
-
|
|
259
|
-
|
|
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. */
|
|
260
269
|
export declare function editRoomDmOnClient(client: RoomWsClient, request: {
|
|
261
270
|
conversationId?: string;
|
|
262
271
|
username?: string;
|
|
263
272
|
messageId: string;
|
|
264
273
|
content: string;
|
|
265
|
-
}):
|
|
274
|
+
}, timeoutMs?: number): Promise<RoomDmMessageEditedPayload>;
|
|
266
275
|
/** Soft-delete one of my DM messages. The relay fans out DM_MESSAGE_DELETED. */
|
|
267
276
|
export declare function deleteRoomDmOnClient(client: RoomWsClient, request: {
|
|
268
277
|
conversationId?: string;
|
|
269
278
|
username?: string;
|
|
270
279
|
messageId: string;
|
|
271
|
-
}):
|
|
280
|
+
}, timeoutMs?: number): Promise<RoomDmMessageDeletedPayload>;
|
|
272
281
|
/** Toggle a reaction on a DM message. The relay fans out DM_REACTION_UPDATED. */
|
|
273
282
|
export declare function reactRoomDmOnClient(client: RoomWsClient, request: {
|
|
274
283
|
conversationId?: string;
|
|
@@ -276,7 +285,23 @@ export declare function reactRoomDmOnClient(client: RoomWsClient, request: {
|
|
|
276
285
|
messageId: string;
|
|
277
286
|
emoji: string;
|
|
278
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;
|
|
294
|
+
}): void;
|
|
295
|
+
export declare function unpinRoomDmOnClient(client: RoomWsClient, request: {
|
|
296
|
+
conversationId?: string;
|
|
297
|
+
username?: string;
|
|
298
|
+
messageId: string;
|
|
279
299
|
}): void;
|
|
300
|
+
export declare function requestRoomDmPinsOnClient(client: RoomWsClient, request: {
|
|
301
|
+
conversationId?: string;
|
|
302
|
+
username?: string;
|
|
303
|
+
limit?: number;
|
|
304
|
+
}, timeoutMs?: number): Promise<RoomDmPinsResultPayload>;
|
|
280
305
|
export declare function peekRoom(config: RoomClientConfig, options: RoomPeekOptions): Promise<RoomBackfillPayload>;
|
|
281
306
|
export declare function sayRoom(config: RoomClientConfig, options: RoomSayOptions): Promise<RoomSayResult>;
|
|
282
307
|
export declare function joinRoom(config: RoomClientConfig, options: RoomJoinOptions): Promise<RoomJoinedSession>;
|
|
@@ -292,7 +317,7 @@ export declare function attachRejoinOnReconnect(client: RoomWsClient, options: R
|
|
|
292
317
|
* (1..128 chars after trim); dedupe on (userId, clientMsgId) is server-side
|
|
293
318
|
* work and NOT implied here.
|
|
294
319
|
*/
|
|
295
|
-
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;
|
|
296
321
|
export declare function sendRoomTyping(client: RoomWsClient, room: string, state: "start" | "stop"): void;
|
|
297
322
|
export declare function sendRoomStatus(client: RoomWsClient, status: RoomUserStatus, statusText?: string | null, platform?: RoomClientPlatform): void;
|
|
298
323
|
/**
|
package/dist/client.js
CHANGED
|
@@ -454,6 +454,20 @@ export async function requestRoomDmHistoryOnClient(client, request, timeoutMs) {
|
|
|
454
454
|
const history = await client.waitFor(RoomServerMessageType.DM_HISTORY, (msg) => msg.payload.requestId === requestId, timeoutMs, requestId);
|
|
455
455
|
return history.payload;
|
|
456
456
|
}
|
|
457
|
+
export async function markRoomDmReadOnClient(client, request, timeoutMs) {
|
|
458
|
+
const requestId = randomUUID();
|
|
459
|
+
client.send({
|
|
460
|
+
type: RoomClientMessageType.DM_READ,
|
|
461
|
+
payload: {
|
|
462
|
+
requestId,
|
|
463
|
+
...(request.username ? { username: request.username } : {}),
|
|
464
|
+
...(request.conversationId ? { conversationId: request.conversationId } : {}),
|
|
465
|
+
},
|
|
466
|
+
timestamp: Date.now(),
|
|
467
|
+
});
|
|
468
|
+
const updated = await client.waitFor(RoomServerMessageType.DM_INBOX_UPDATED, (msg) => msg.payload.requestId === requestId, timeoutMs, requestId);
|
|
469
|
+
return updated.payload;
|
|
470
|
+
}
|
|
457
471
|
export async function sendRoomDmOnClient(client, request, timeoutMs) {
|
|
458
472
|
const requestId = randomUUID();
|
|
459
473
|
const clientMsgId = request.clientMsgId ?? randomUUID();
|
|
@@ -466,6 +480,29 @@ export async function sendRoomDmOnClient(client, request, timeoutMs) {
|
|
|
466
480
|
...(request.username ? { username: request.username } : {}),
|
|
467
481
|
...(request.conversationId ? { conversationId: request.conversationId } : {}),
|
|
468
482
|
...(request.imageUrl ? { imageUrl: request.imageUrl } : {}),
|
|
483
|
+
...(request.metadata ? { metadata: request.metadata } : {}),
|
|
484
|
+
},
|
|
485
|
+
timestamp: Date.now(),
|
|
486
|
+
});
|
|
487
|
+
const sent = await client.waitFor(RoomServerMessageType.DM_MESSAGE, (msg) => msg.payload.requestId === requestId ||
|
|
488
|
+
msg.payload.clientMsgId === clientMsgId ||
|
|
489
|
+
msg.payload.message.clientMsgId === clientMsgId, timeoutMs, requestId);
|
|
490
|
+
return sent.payload;
|
|
491
|
+
}
|
|
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 } : {}),
|
|
469
506
|
},
|
|
470
507
|
timestamp: Date.now(),
|
|
471
508
|
});
|
|
@@ -474,12 +511,13 @@ export async function sendRoomDmOnClient(client, request, timeoutMs) {
|
|
|
474
511
|
msg.payload.message.clientMsgId === clientMsgId, timeoutMs, requestId);
|
|
475
512
|
return sent.payload;
|
|
476
513
|
}
|
|
477
|
-
/** Edit one of my DM messages
|
|
478
|
-
|
|
479
|
-
|
|
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();
|
|
480
517
|
client.send({
|
|
481
518
|
type: RoomClientMessageType.DM_EDIT,
|
|
482
519
|
payload: {
|
|
520
|
+
requestId,
|
|
483
521
|
messageId: request.messageId,
|
|
484
522
|
content: request.content,
|
|
485
523
|
...(request.conversationId ? { conversationId: request.conversationId } : {}),
|
|
@@ -487,24 +525,32 @@ export function editRoomDmOnClient(client, request) {
|
|
|
487
525
|
},
|
|
488
526
|
timestamp: Date.now(),
|
|
489
527
|
});
|
|
528
|
+
const updated = await client.waitFor(RoomServerMessageType.DM_MESSAGE_EDITED, (msg) => msg.payload.requestId === requestId, timeoutMs, requestId);
|
|
529
|
+
return updated.payload;
|
|
490
530
|
}
|
|
491
531
|
/** Soft-delete one of my DM messages. The relay fans out DM_MESSAGE_DELETED. */
|
|
492
|
-
export function deleteRoomDmOnClient(client, request) {
|
|
532
|
+
export async function deleteRoomDmOnClient(client, request, timeoutMs) {
|
|
533
|
+
const requestId = randomUUID();
|
|
493
534
|
client.send({
|
|
494
535
|
type: RoomClientMessageType.DM_DELETE,
|
|
495
536
|
payload: {
|
|
537
|
+
requestId,
|
|
496
538
|
messageId: request.messageId,
|
|
497
539
|
...(request.conversationId ? { conversationId: request.conversationId } : {}),
|
|
498
540
|
...(request.username ? { username: request.username } : {}),
|
|
499
541
|
},
|
|
500
542
|
timestamp: Date.now(),
|
|
501
543
|
});
|
|
544
|
+
const updated = await client.waitFor(RoomServerMessageType.DM_MESSAGE_DELETED, (msg) => msg.payload.requestId === requestId, timeoutMs, requestId);
|
|
545
|
+
return updated.payload;
|
|
502
546
|
}
|
|
503
547
|
/** Toggle a reaction on a DM message. The relay fans out DM_REACTION_UPDATED. */
|
|
504
|
-
export function reactRoomDmOnClient(client, request) {
|
|
548
|
+
export async function reactRoomDmOnClient(client, request, timeoutMs) {
|
|
549
|
+
const requestId = randomUUID();
|
|
505
550
|
client.send({
|
|
506
551
|
type: RoomClientMessageType.DM_REACT,
|
|
507
552
|
payload: {
|
|
553
|
+
requestId,
|
|
508
554
|
messageId: request.messageId,
|
|
509
555
|
emoji: request.emoji,
|
|
510
556
|
op: request.op,
|
|
@@ -513,6 +559,46 @@ export function reactRoomDmOnClient(client, request) {
|
|
|
513
559
|
},
|
|
514
560
|
timestamp: Date.now(),
|
|
515
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;
|
|
516
602
|
}
|
|
517
603
|
export async function peekRoom(config, options) {
|
|
518
604
|
if (!config.webSocketCtor) {
|
|
@@ -627,7 +713,7 @@ export function attachRejoinOnReconnect(client, options, latestSeq, onRejoined,
|
|
|
627
713
|
* (1..128 chars after trim); dedupe on (userId, clientMsgId) is server-side
|
|
628
714
|
* work and NOT implied here.
|
|
629
715
|
*/
|
|
630
|
-
export function postRoomMessage(client, room, text, inReplyTo, attachments, topicId, clientMsgId) {
|
|
716
|
+
export function postRoomMessage(client, room, text, inReplyTo, attachments, topicId, clientMsgId, metadata) {
|
|
631
717
|
const msgId = clientMsgId ?? randomUUID();
|
|
632
718
|
client.send({
|
|
633
719
|
type: RoomClientMessageType.POST,
|
|
@@ -638,6 +724,7 @@ export function postRoomMessage(client, room, text, inReplyTo, attachments, topi
|
|
|
638
724
|
clientMsgId: msgId,
|
|
639
725
|
...(inReplyTo !== undefined ? { inReplyTo } : {}),
|
|
640
726
|
...(topicId ? { topicId } : {}),
|
|
727
|
+
...(metadata ? { metadata } : {}),
|
|
641
728
|
},
|
|
642
729
|
timestamp: Date.now(),
|
|
643
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;
|
|
@@ -575,6 +629,7 @@ export interface RoomDmMessagePayload {
|
|
|
575
629
|
clientMsgId?: string;
|
|
576
630
|
}
|
|
577
631
|
export interface RoomDmInboxUpdatedPayload {
|
|
632
|
+
requestId?: string;
|
|
578
633
|
conversationId: string;
|
|
579
634
|
participant: RoomDmParticipant;
|
|
580
635
|
unreadCount: number;
|
|
@@ -888,6 +943,7 @@ export type RoomClientMessage = {
|
|
|
888
943
|
clientMsgId?: string;
|
|
889
944
|
reason?: string;
|
|
890
945
|
requestId?: string;
|
|
946
|
+
metadata?: RoomForwardMetadata;
|
|
891
947
|
};
|
|
892
948
|
timestamp?: number;
|
|
893
949
|
} | {
|
|
@@ -1073,6 +1129,10 @@ export type RoomClientMessage = {
|
|
|
1073
1129
|
type: typeof RoomClientMessageType.DM_SEND;
|
|
1074
1130
|
payload: RoomDmSendPayload;
|
|
1075
1131
|
timestamp?: number;
|
|
1132
|
+
} | {
|
|
1133
|
+
type: typeof RoomClientMessageType.DM_REPLY;
|
|
1134
|
+
payload: RoomDmReplyPayload;
|
|
1135
|
+
timestamp?: number;
|
|
1076
1136
|
} | {
|
|
1077
1137
|
type: typeof RoomClientMessageType.DM_READ;
|
|
1078
1138
|
payload: RoomDmReadPayload;
|
|
@@ -1089,6 +1149,18 @@ export type RoomClientMessage = {
|
|
|
1089
1149
|
type: typeof RoomClientMessageType.DM_REACT;
|
|
1090
1150
|
payload: RoomDmReactPayload;
|
|
1091
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;
|
|
1092
1164
|
} | {
|
|
1093
1165
|
type: typeof RoomClientMessageType.TOPIC_CREATE;
|
|
1094
1166
|
payload: RoomTopicCreatePayload;
|
|
@@ -1295,6 +1367,14 @@ export type RoomServerMessage = {
|
|
|
1295
1367
|
type: typeof RoomServerMessageType.DM_REACTION_UPDATED;
|
|
1296
1368
|
payload: RoomDmReactionUpdatedPayload;
|
|
1297
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;
|
|
1298
1378
|
} | {
|
|
1299
1379
|
type: typeof RoomServerMessageType.TOPIC;
|
|
1300
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",
|
package/dist/social-client.d.ts
CHANGED
|
@@ -174,7 +174,8 @@ export interface RoomSpaceSummary {
|
|
|
174
174
|
export declare function listRoomSpacesViaChat(config: RoomSocialConfig): Promise<RoomSpaceSummary[]>;
|
|
175
175
|
export interface RoomSpaceMember {
|
|
176
176
|
userId: string;
|
|
177
|
-
role
|
|
177
|
+
/** The ladder role. 'librarian' maintains the generated briefs/ docs. */
|
|
178
|
+
role: "owner" | "admin" | "librarian" | "member";
|
|
178
179
|
/** Named identity roles (RoomSpaceRole.roleId). */
|
|
179
180
|
roleIds?: string[];
|
|
180
181
|
joinedAt?: string;
|
|
@@ -329,7 +330,7 @@ export declare function listRoomChannelMembers(config: RoomSocialConfig, roomId:
|
|
|
329
330
|
export declare function removeSpaceMember(config: RoomSocialConfig, spaceId: string, targetUserId: string): Promise<{
|
|
330
331
|
removed?: boolean;
|
|
331
332
|
}>;
|
|
332
|
-
export declare function changeSpaceMemberRole(config: RoomSocialConfig, spaceId: string, targetUserId: string, role: "admin" | "member"): Promise<RoomSpaceMember>;
|
|
333
|
+
export declare function changeSpaceMemberRole(config: RoomSocialConfig, spaceId: string, targetUserId: string, role: "admin" | "librarian" | "member"): Promise<RoomSpaceMember>;
|
|
333
334
|
/** Set (string) or clear (null) a member's per-space nickname; the store validates and enforces uniqueness. */
|
|
334
335
|
export declare function setSpaceMemberNickname(config: RoomSocialConfig, spaceId: string, targetUserId: string, nickname: string | null): Promise<RoomSpaceMember>;
|
|
335
336
|
export declare function createRoomSpace(config: RoomSocialConfig, input: {
|
package/dist/social-types.d.ts
CHANGED
|
@@ -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.
|
|
2
|
-
export declare const RUNNER_VERSION = "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.
|
|
2
|
-
export const RUNNER_VERSION = "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.
|
|
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": [
|
|
20
|
+
"files": [
|
|
21
|
+
"src",
|
|
22
|
+
"dist",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE"
|
|
25
|
+
],
|
|
21
26
|
"publishConfig": {
|
|
22
27
|
"access": "public"
|
|
23
28
|
},
|
|
@@ -202,7 +202,7 @@ export function buildBriefRefreshBootstrap(opts: {
|
|
|
202
202
|
"## Summary",
|
|
203
203
|
"<one or two short paragraphs on what this room is about and where it stands>",
|
|
204
204
|
"",
|
|
205
|
-
"## Open
|
|
205
|
+
"## Open questions",
|
|
206
206
|
"- <unresolved questions, or `None.`>",
|
|
207
207
|
"",
|
|
208
208
|
"## Decisions",
|
|
@@ -202,21 +202,32 @@ export interface BriefInput {
|
|
|
202
202
|
openThreads: string[];
|
|
203
203
|
decisions: string[];
|
|
204
204
|
docs: BriefDocRef[];
|
|
205
|
+
/** Highest message seq this brief has incorporated. Rendered into the
|
|
206
|
+
* banner as the librarian's shared cursor; co-librarians read it before
|
|
207
|
+
* spending anything. */
|
|
208
|
+
coveredSeq?: number;
|
|
205
209
|
}
|
|
206
210
|
|
|
211
|
+
/** The banner's machine-readable coverage claim. Parsers must only consult
|
|
212
|
+
* the banner blockquote line, never body prose. */
|
|
213
|
+
export const BRIEF_COVERED_RE = /\bCovers through seq (\d+)\./;
|
|
214
|
+
|
|
207
215
|
/** Render the canonical brief markdown. Deterministic shell; the LLM only
|
|
208
216
|
* supplies the summary/threads/decisions prose. */
|
|
209
217
|
export function renderBrief(input: BriefInput): string {
|
|
218
|
+
const covered = input.coveredSeq !== undefined ? ` Covers through seq ${input.coveredSeq}.` : "";
|
|
210
219
|
const lines: string[] = [];
|
|
211
220
|
lines.push(`# Brief: ${input.room}`);
|
|
212
221
|
lines.push("");
|
|
213
|
-
lines.push(
|
|
222
|
+
lines.push(
|
|
223
|
+
`> Auto-generated by the room agent, read-only. Updated ${input.updatedAtLabel}.${covered}`,
|
|
224
|
+
);
|
|
214
225
|
lines.push("");
|
|
215
226
|
lines.push("## Summary");
|
|
216
227
|
lines.push("");
|
|
217
228
|
lines.push(input.summary.trim() || "_No summary yet._");
|
|
218
229
|
lines.push("");
|
|
219
|
-
lines.push("## Open
|
|
230
|
+
lines.push("## Open questions");
|
|
220
231
|
lines.push("");
|
|
221
232
|
if (input.openThreads.length === 0) lines.push("_None._");
|
|
222
233
|
else for (const t of input.openThreads) lines.push(`- ${t}`);
|
package/src/client.ts
CHANGED
|
@@ -15,8 +15,14 @@ import {
|
|
|
15
15
|
RoomClientMessageType,
|
|
16
16
|
type RoomClientPlatform,
|
|
17
17
|
type RoomDmHistoryResultPayload,
|
|
18
|
+
type RoomDmInboxUpdatedPayload,
|
|
19
|
+
type RoomDmMessageDeletedPayload,
|
|
20
|
+
type RoomDmMessageEditedPayload,
|
|
18
21
|
type RoomDmMessagePayload,
|
|
19
22
|
type RoomDmOpenedPayload,
|
|
23
|
+
type RoomDmPinsResultPayload,
|
|
24
|
+
type RoomDmReactionUpdatedPayload,
|
|
25
|
+
type RoomForwardMetadata,
|
|
20
26
|
type RoomFriendPresence,
|
|
21
27
|
type RoomInvitedPayload,
|
|
22
28
|
type RoomLedgerEntry,
|
|
@@ -291,6 +297,16 @@ export interface RoomDmSendRequest {
|
|
|
291
297
|
* URL. Stored on the message's imageUrl; the client signs keys on render.
|
|
292
298
|
* Additive — omitted for text-only sends. */
|
|
293
299
|
imageUrl?: string;
|
|
300
|
+
metadata?: RoomForwardMetadata;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export interface RoomDmReplyRequest extends RoomDmSendRequest {
|
|
304
|
+
replyTo: string;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export interface RoomDmReadRequest {
|
|
308
|
+
username?: string;
|
|
309
|
+
conversationId?: string;
|
|
294
310
|
}
|
|
295
311
|
|
|
296
312
|
export interface RoomThreadRequest {
|
|
@@ -923,6 +939,30 @@ export async function requestRoomDmHistoryOnClient(
|
|
|
923
939
|
return history.payload;
|
|
924
940
|
}
|
|
925
941
|
|
|
942
|
+
export async function markRoomDmReadOnClient(
|
|
943
|
+
client: RoomWsClient,
|
|
944
|
+
request: RoomDmReadRequest,
|
|
945
|
+
timeoutMs?: number,
|
|
946
|
+
): Promise<RoomDmInboxUpdatedPayload> {
|
|
947
|
+
const requestId = randomUUID();
|
|
948
|
+
client.send({
|
|
949
|
+
type: RoomClientMessageType.DM_READ,
|
|
950
|
+
payload: {
|
|
951
|
+
requestId,
|
|
952
|
+
...(request.username ? { username: request.username } : {}),
|
|
953
|
+
...(request.conversationId ? { conversationId: request.conversationId } : {}),
|
|
954
|
+
},
|
|
955
|
+
timestamp: Date.now(),
|
|
956
|
+
});
|
|
957
|
+
const updated = await client.waitFor(
|
|
958
|
+
RoomServerMessageType.DM_INBOX_UPDATED,
|
|
959
|
+
(msg) => msg.payload.requestId === requestId,
|
|
960
|
+
timeoutMs,
|
|
961
|
+
requestId,
|
|
962
|
+
);
|
|
963
|
+
return updated.payload;
|
|
964
|
+
}
|
|
965
|
+
|
|
926
966
|
export async function sendRoomDmOnClient(
|
|
927
967
|
client: RoomWsClient,
|
|
928
968
|
request: RoomDmSendRequest,
|
|
@@ -939,6 +979,40 @@ export async function sendRoomDmOnClient(
|
|
|
939
979
|
...(request.username ? { username: request.username } : {}),
|
|
940
980
|
...(request.conversationId ? { conversationId: request.conversationId } : {}),
|
|
941
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 } : {}),
|
|
942
1016
|
},
|
|
943
1017
|
timestamp: Date.now(),
|
|
944
1018
|
});
|
|
@@ -954,15 +1028,17 @@ export async function sendRoomDmOnClient(
|
|
|
954
1028
|
return sent.payload;
|
|
955
1029
|
}
|
|
956
1030
|
|
|
957
|
-
/** Edit one of my DM messages
|
|
958
|
-
|
|
959
|
-
export function editRoomDmOnClient(
|
|
1031
|
+
/** Edit one of my DM messages and wait for the correlated relay update. */
|
|
1032
|
+
export async function editRoomDmOnClient(
|
|
960
1033
|
client: RoomWsClient,
|
|
961
1034
|
request: { conversationId?: string; username?: string; messageId: string; content: string },
|
|
962
|
-
|
|
1035
|
+
timeoutMs?: number,
|
|
1036
|
+
): Promise<RoomDmMessageEditedPayload> {
|
|
1037
|
+
const requestId = randomUUID();
|
|
963
1038
|
client.send({
|
|
964
1039
|
type: RoomClientMessageType.DM_EDIT,
|
|
965
1040
|
payload: {
|
|
1041
|
+
requestId,
|
|
966
1042
|
messageId: request.messageId,
|
|
967
1043
|
content: request.content,
|
|
968
1044
|
...(request.conversationId ? { conversationId: request.conversationId } : {}),
|
|
@@ -970,26 +1046,43 @@ export function editRoomDmOnClient(
|
|
|
970
1046
|
},
|
|
971
1047
|
timestamp: Date.now(),
|
|
972
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;
|
|
973
1056
|
}
|
|
974
1057
|
|
|
975
1058
|
/** Soft-delete one of my DM messages. The relay fans out DM_MESSAGE_DELETED. */
|
|
976
|
-
export function deleteRoomDmOnClient(
|
|
1059
|
+
export async function deleteRoomDmOnClient(
|
|
977
1060
|
client: RoomWsClient,
|
|
978
1061
|
request: { conversationId?: string; username?: string; messageId: string },
|
|
979
|
-
|
|
1062
|
+
timeoutMs?: number,
|
|
1063
|
+
): Promise<RoomDmMessageDeletedPayload> {
|
|
1064
|
+
const requestId = randomUUID();
|
|
980
1065
|
client.send({
|
|
981
1066
|
type: RoomClientMessageType.DM_DELETE,
|
|
982
1067
|
payload: {
|
|
1068
|
+
requestId,
|
|
983
1069
|
messageId: request.messageId,
|
|
984
1070
|
...(request.conversationId ? { conversationId: request.conversationId } : {}),
|
|
985
1071
|
...(request.username ? { username: request.username } : {}),
|
|
986
1072
|
},
|
|
987
1073
|
timestamp: Date.now(),
|
|
988
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;
|
|
989
1082
|
}
|
|
990
1083
|
|
|
991
1084
|
/** Toggle a reaction on a DM message. The relay fans out DM_REACTION_UPDATED. */
|
|
992
|
-
export function reactRoomDmOnClient(
|
|
1085
|
+
export async function reactRoomDmOnClient(
|
|
993
1086
|
client: RoomWsClient,
|
|
994
1087
|
request: {
|
|
995
1088
|
conversationId?: string;
|
|
@@ -998,10 +1091,13 @@ export function reactRoomDmOnClient(
|
|
|
998
1091
|
emoji: string;
|
|
999
1092
|
op: "add" | "remove";
|
|
1000
1093
|
},
|
|
1001
|
-
|
|
1094
|
+
timeoutMs?: number,
|
|
1095
|
+
): Promise<RoomDmReactionUpdatedPayload> {
|
|
1096
|
+
const requestId = randomUUID();
|
|
1002
1097
|
client.send({
|
|
1003
1098
|
type: RoomClientMessageType.DM_REACT,
|
|
1004
1099
|
payload: {
|
|
1100
|
+
requestId,
|
|
1005
1101
|
messageId: request.messageId,
|
|
1006
1102
|
emoji: request.emoji,
|
|
1007
1103
|
op: request.op,
|
|
@@ -1010,6 +1106,69 @@ export function reactRoomDmOnClient(
|
|
|
1010
1106
|
},
|
|
1011
1107
|
timestamp: Date.now(),
|
|
1012
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;
|
|
1013
1172
|
}
|
|
1014
1173
|
|
|
1015
1174
|
export async function peekRoom(
|
|
@@ -1165,6 +1324,7 @@ export function postRoomMessage(
|
|
|
1165
1324
|
attachments?: RoomAttachmentInput[],
|
|
1166
1325
|
topicId?: string,
|
|
1167
1326
|
clientMsgId?: string,
|
|
1327
|
+
metadata?: RoomForwardMetadata,
|
|
1168
1328
|
): string {
|
|
1169
1329
|
const msgId = clientMsgId ?? randomUUID();
|
|
1170
1330
|
client.send({
|
|
@@ -1176,6 +1336,7 @@ export function postRoomMessage(
|
|
|
1176
1336
|
clientMsgId: msgId,
|
|
1177
1337
|
...(inReplyTo !== undefined ? { inReplyTo } : {}),
|
|
1178
1338
|
...(topicId ? { topicId } : {}),
|
|
1339
|
+
...(metadata ? { metadata } : {}),
|
|
1179
1340
|
},
|
|
1180
1341
|
timestamp: Date.now(),
|
|
1181
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;
|
|
@@ -674,6 +737,7 @@ export interface RoomDmMessagePayload {
|
|
|
674
737
|
}
|
|
675
738
|
|
|
676
739
|
export interface RoomDmInboxUpdatedPayload {
|
|
740
|
+
requestId?: string;
|
|
677
741
|
conversationId: string;
|
|
678
742
|
participant: RoomDmParticipant;
|
|
679
743
|
unreadCount: number;
|
|
@@ -1013,6 +1077,7 @@ export type RoomClientMessage =
|
|
|
1013
1077
|
clientMsgId?: string;
|
|
1014
1078
|
reason?: string;
|
|
1015
1079
|
requestId?: string;
|
|
1080
|
+
metadata?: RoomForwardMetadata;
|
|
1016
1081
|
};
|
|
1017
1082
|
timestamp?: number;
|
|
1018
1083
|
}
|
|
@@ -1188,6 +1253,11 @@ export type RoomClientMessage =
|
|
|
1188
1253
|
payload: RoomDmSendPayload;
|
|
1189
1254
|
timestamp?: number;
|
|
1190
1255
|
}
|
|
1256
|
+
| {
|
|
1257
|
+
type: typeof RoomClientMessageType.DM_REPLY;
|
|
1258
|
+
payload: RoomDmReplyPayload;
|
|
1259
|
+
timestamp?: number;
|
|
1260
|
+
}
|
|
1191
1261
|
| {
|
|
1192
1262
|
type: typeof RoomClientMessageType.DM_READ;
|
|
1193
1263
|
payload: RoomDmReadPayload;
|
|
@@ -1208,6 +1278,21 @@ export type RoomClientMessage =
|
|
|
1208
1278
|
payload: RoomDmReactPayload;
|
|
1209
1279
|
timestamp?: number;
|
|
1210
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
|
+
}
|
|
1211
1296
|
| {
|
|
1212
1297
|
type: typeof RoomClientMessageType.TOPIC_CREATE;
|
|
1213
1298
|
payload: RoomTopicCreatePayload;
|
|
@@ -1460,6 +1545,16 @@ export type RoomServerMessage =
|
|
|
1460
1545
|
payload: RoomDmReactionUpdatedPayload;
|
|
1461
1546
|
timestamp: number;
|
|
1462
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
|
+
}
|
|
1463
1558
|
| {
|
|
1464
1559
|
type: typeof RoomServerMessageType.TOPIC;
|
|
1465
1560
|
payload: RoomTopicResultPayload;
|
package/src/social-client.ts
CHANGED
|
@@ -657,7 +657,8 @@ export async function listRoomSpacesViaChat(config: RoomSocialConfig): Promise<R
|
|
|
657
657
|
|
|
658
658
|
export interface RoomSpaceMember {
|
|
659
659
|
userId: string;
|
|
660
|
-
role
|
|
660
|
+
/** The ladder role. 'librarian' maintains the generated briefs/ docs. */
|
|
661
|
+
role: "owner" | "admin" | "librarian" | "member";
|
|
661
662
|
/** Named identity roles (RoomSpaceRole.roleId). */
|
|
662
663
|
roleIds?: string[];
|
|
663
664
|
joinedAt?: string;
|
|
@@ -1047,7 +1048,7 @@ export async function changeSpaceMemberRole(
|
|
|
1047
1048
|
config: RoomSocialConfig,
|
|
1048
1049
|
spaceId: string,
|
|
1049
1050
|
targetUserId: string,
|
|
1050
|
-
role: "admin" | "member",
|
|
1051
|
+
role: "admin" | "librarian" | "member",
|
|
1051
1052
|
): Promise<RoomSpaceMember> {
|
|
1052
1053
|
const result = await socialRequest<{ member: RoomSpaceMember }>(
|
|
1053
1054
|
config,
|
package/src/social-types.ts
CHANGED
|
@@ -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.
|
|
2
|
-
export const RUNNER_VERSION = "0.
|
|
1
|
+
export const VERSION = "0.7.0";
|
|
2
|
+
export const RUNNER_VERSION = "0.7.0";
|