agent-comms 2.21.17 → 2.21.18

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.
@@ -0,0 +1,740 @@
1
+ /**
2
+ * Direct, DI-based unit tests for DeliveryEngine's delivery/broadcast/notification half -- applyPatch's "delivery" case, broadcastPatch, deliverLocallyAndBroadcast, fireLocalDelivery, deliverToRoom, notifyRoomsOfStatus/NameChange, emitDeliveryStatus, markRead, deliver, and drainDelivery. Split from delivery-engine.test.ts to satisfy the repo's max-lines cap: that file covers the presence/queueing/membership-merge/state-sync/patch-application half. Both files share an identical preamble (helpers, fakes, makeHarness) by necessity of the split -- see delivery-engine.test.ts's own header for the full rationale.
3
+ */
4
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
5
+ import { loadRoomTokens } from "../core/identity-store.js";
6
+ import { randomId } from "../core/random-id.js";
7
+ import { DeliveryEngine, } from "../core/delivery-engine.js";
8
+ import { bytesToHex } from "wire-mesh-core/domain/device-id";
9
+ vi.mock("../core/identity-store.js", () => ({
10
+ loadRoomTokens: vi.fn(),
11
+ }));
12
+ // Opaque placeholder: markRead never inspects a token's own COSE_Sign1 structure, only forwards whatever loadRoomTokens returns to sendRoomRequestToMember.
13
+ const FAKE_TOKEN = "fake-token";
14
+ /** A device-id is a 64-character lowercase hex SHA-256 digest; room-path.ts's assertDeviceIdHex rejects anything shorter. */
15
+ const DEVICE_ID_HEX_LENGTH = 64;
16
+ const PEER_ID = "a".repeat(DEVICE_ID_HEX_LENGTH);
17
+ const OTHER_ID = "b".repeat(DEVICE_ID_HEX_LENGTH);
18
+ const THIRD_ID = "c".repeat(DEVICE_ID_HEX_LENGTH);
19
+ const NOW_MS = 1_700_000_000_000;
20
+ /** Mirrors delivery-engine.ts's own private MAX_LOCAL_DELIVERY_DEDUP_KEYS -- not exported, so re-derived here as the literal the source comment documents rather than imported. */
21
+ const MAX_LOCAL_DELIVERY_DEDUP_KEYS = 50;
22
+ /** A fresh, distinct, real device-id-shaped hex id -- avoids the no-magic-numbers problem a per-test literal byte value would run into (matching room-protocol.test.ts's own precedent), using the same randomId() utility production code already uses for the identical purpose. */
23
+ function messageId() {
24
+ return bytesToHex(randomId());
25
+ }
26
+ function room(overrides = {}) {
27
+ return {
28
+ id: "room-1",
29
+ version: 1,
30
+ name: "room-name",
31
+ type: "public",
32
+ owner: PEER_ID,
33
+ createdAt: "2026-01-01T00:00:00.000Z",
34
+ description: "",
35
+ members: [PEER_ID],
36
+ invited: [],
37
+ memberJoins: {},
38
+ memberLeaves: {},
39
+ invitedJoins: {},
40
+ invitedLeaves: {},
41
+ ...overrides,
42
+ };
43
+ }
44
+ function agent(overrides = {}) {
45
+ return {
46
+ id: OTHER_ID,
47
+ version: 1,
48
+ name: "recipient",
49
+ harness: "pi",
50
+ cwd: "/tmp",
51
+ pid: 111,
52
+ startedAt: "2026-01-01T00:00:00.000Z",
53
+ visibility: "visible",
54
+ status: "active",
55
+ tags: [],
56
+ subscribedRooms: [],
57
+ ...overrides,
58
+ };
59
+ }
60
+ function roomMessage(overrides = {}) {
61
+ return {
62
+ id: messageId(),
63
+ from: PEER_ID,
64
+ room: "room-1",
65
+ content: "hi",
66
+ timestamp: "2026-01-01T00:00:00.000Z",
67
+ readBy: [],
68
+ ...overrides,
69
+ };
70
+ }
71
+ function dmMessage(overrides = {}) {
72
+ return {
73
+ id: messageId(),
74
+ from: PEER_ID,
75
+ to: OTHER_ID,
76
+ content: "hi",
77
+ timestamp: "2026-01-01T00:00:00.000Z",
78
+ readBy: [],
79
+ ...overrides,
80
+ };
81
+ }
82
+ function fakeTransport() {
83
+ return {
84
+ dataPort: 4000,
85
+ isCoordinator: false,
86
+ hasCoordinatorConnection: false,
87
+ startDataServer: vi.fn().mockResolvedValue(undefined),
88
+ connectToCoordinator: vi.fn().mockResolvedValue(undefined),
89
+ becomeCoordinator: vi.fn().mockResolvedValue(undefined),
90
+ connectToPeer: vi.fn().mockResolvedValue(undefined),
91
+ send: vi.fn().mockResolvedValue(undefined),
92
+ acceptConnection: vi.fn().mockResolvedValue(undefined),
93
+ rejectConnection: vi.fn().mockResolvedValue(undefined),
94
+ connectToRemote: vi.fn().mockResolvedValue(undefined),
95
+ broadcast: vi.fn().mockResolvedValue(undefined),
96
+ broadcastRevocation: vi.fn().mockResolvedValue(undefined),
97
+ sendRoomRequest: vi
98
+ .fn()
99
+ .mockResolvedValue({ result: "error", code: "not_connected" }),
100
+ addListener: vi.fn().mockResolvedValue("listener-1"),
101
+ removeListener: vi.fn().mockResolvedValue(undefined),
102
+ listListeners: vi.fn().mockReturnValue([]),
103
+ shutdown: vi.fn().mockResolvedValue(undefined),
104
+ unref: vi.fn(),
105
+ };
106
+ }
107
+ function makeHarness() {
108
+ let onDelivery;
109
+ let onPatch;
110
+ let shutDown = false;
111
+ const transport = fakeTransport();
112
+ const sendRoomRequestToMember = vi.fn().mockResolvedValue(undefined);
113
+ const revocationRecord = vi.fn().mockResolvedValue(undefined);
114
+ const deps = {
115
+ agents: new Map(),
116
+ rooms: new Map(),
117
+ messages: new Map(),
118
+ dms: new Map(),
119
+ deliveryQueues: new Map(),
120
+ localDeliveryKeys: new Set(),
121
+ pendingMarkReadTimers: [],
122
+ getPeerId: () => PEER_ID,
123
+ requireIdentity: () => ({
124
+ slot: { harness: "pi", cwd: "/tmp" },
125
+ clock: { now: () => NOW_MS },
126
+ identity: {},
127
+ revocation: { record: revocationRecord },
128
+ }),
129
+ requireTransport: () => transport,
130
+ getOnDelivery: () => onDelivery,
131
+ getOnPatch: () => onPatch,
132
+ isShutDown: () => shutDown,
133
+ sendRoomRequestToMember,
134
+ };
135
+ return {
136
+ deps,
137
+ engine: new DeliveryEngine(deps),
138
+ transport,
139
+ sendRoomRequestToMember,
140
+ revocationRecord,
141
+ setOnDelivery(fn) {
142
+ onDelivery = fn;
143
+ },
144
+ setOnPatch(fn) {
145
+ onPatch = fn;
146
+ },
147
+ setShutDown(v) {
148
+ shutDown = v;
149
+ },
150
+ };
151
+ }
152
+ beforeEach(() => {
153
+ vi.mocked(loadRoomTokens).mockReset();
154
+ vi.mocked(loadRoomTokens).mockReturnValue({ "room-1": FAKE_TOKEN });
155
+ });
156
+ describe("DeliveryEngine — applyPatch(delivery)", () => {
157
+ it("queues the event for the target agent regardless of who it targets", async () => {
158
+ const h = makeHarness();
159
+ await h.engine.applyPatch({
160
+ type: "delivery",
161
+ agentId: OTHER_ID,
162
+ event: { type: "member_left", room: "room-1", agent: OTHER_ID },
163
+ });
164
+ expect(h.deps.deliveryQueues.get(OTHER_ID)).toHaveLength(1);
165
+ });
166
+ it("does not fire onDelivery for a patch targeting a different agent than this peer", async () => {
167
+ const h = makeHarness();
168
+ const delivered = vi.fn();
169
+ h.setOnDelivery(delivered);
170
+ await h.engine.applyPatch({
171
+ type: "delivery",
172
+ agentId: OTHER_ID,
173
+ event: { type: "member_left", room: "room-1", agent: OTHER_ID },
174
+ });
175
+ expect(delivered).not.toHaveBeenCalled();
176
+ });
177
+ it("fires onDelivery for a patch targeting this peer's own agent", async () => {
178
+ const h = makeHarness();
179
+ const delivered = vi.fn();
180
+ h.setOnDelivery(delivered);
181
+ const event = {
182
+ type: "room_message",
183
+ message: roomMessage(),
184
+ };
185
+ await h.engine.applyPatch({ type: "delivery", agentId: PEER_ID, event });
186
+ expect(delivered).toHaveBeenCalledWith(PEER_ID, event);
187
+ });
188
+ it("dedupes against a delivery already fired in this process, never calling onDelivery twice for it", async () => {
189
+ const h = makeHarness();
190
+ const delivered = vi.fn();
191
+ h.setOnDelivery(delivered);
192
+ const event = {
193
+ type: "room_message",
194
+ message: roomMessage(),
195
+ };
196
+ await h.engine.applyPatch({ type: "delivery", agentId: PEER_ID, event });
197
+ await h.engine.applyPatch({ type: "delivery", agentId: PEER_ID, event });
198
+ expect(delivered).toHaveBeenCalledTimes(1);
199
+ });
200
+ it("evicts the oldest local-delivery dedup key once the cap is exceeded", async () => {
201
+ const h = makeHarness();
202
+ h.setOnDelivery(vi.fn());
203
+ for (let i = 0; i < MAX_LOCAL_DELIVERY_DEDUP_KEYS + 1; i++) {
204
+ await h.engine.applyPatch({
205
+ type: "delivery",
206
+ agentId: PEER_ID,
207
+ event: {
208
+ type: "room_message",
209
+ message: roomMessage({ content: `m${i}` }),
210
+ },
211
+ });
212
+ }
213
+ expect(h.deps.localDeliveryKeys.size).toBe(MAX_LOCAL_DELIVERY_DEDUP_KEYS);
214
+ });
215
+ it("schedules a mark-read timer for a delivery targeting this peer, tracked in pendingMarkReadTimers", async () => {
216
+ const h = makeHarness();
217
+ h.setOnDelivery(vi.fn());
218
+ await h.engine.applyPatch({
219
+ type: "delivery",
220
+ agentId: PEER_ID,
221
+ event: { type: "room_message", message: roomMessage() },
222
+ });
223
+ expect(h.deps.pendingMarkReadTimers).toHaveLength(1);
224
+ });
225
+ it("does not schedule a mark-read timer once the store is already shut down", async () => {
226
+ const h = makeHarness();
227
+ h.setOnDelivery(vi.fn());
228
+ h.setShutDown(true);
229
+ await h.engine.applyPatch({
230
+ type: "delivery",
231
+ agentId: PEER_ID,
232
+ event: { type: "room_message", message: roomMessage() },
233
+ });
234
+ expect(h.deps.pendingMarkReadTimers).toHaveLength(0);
235
+ });
236
+ it("skips the scheduled mark-read work if the store is shut down by the time the timer fires", async () => {
237
+ vi.useFakeTimers();
238
+ try {
239
+ const h = makeHarness();
240
+ h.setOnDelivery(vi.fn());
241
+ vi.mocked(loadRoomTokens).mockReturnValue({ "room-1": FAKE_TOKEN });
242
+ const msg = roomMessage({ from: OTHER_ID });
243
+ h.deps.messages.set("room-1", [msg]);
244
+ await h.engine.applyPatch({
245
+ type: "delivery",
246
+ agentId: PEER_ID,
247
+ event: { type: "room_message", message: msg },
248
+ });
249
+ h.setShutDown(true);
250
+ await vi.advanceTimersByTimeAsync(0);
251
+ expect(h.sendRoomRequestToMember).not.toHaveBeenCalled();
252
+ }
253
+ finally {
254
+ vi.useRealTimers();
255
+ }
256
+ });
257
+ it("runs the scheduled mark-read work for a room_message when not shut down", async () => {
258
+ vi.useFakeTimers();
259
+ try {
260
+ const h = makeHarness();
261
+ h.setOnDelivery(vi.fn());
262
+ const msg = roomMessage({ from: OTHER_ID, id: messageId() });
263
+ h.deps.messages.set("room-1", [msg]);
264
+ await h.engine.applyPatch({
265
+ type: "delivery",
266
+ agentId: PEER_ID,
267
+ event: { type: "room_message", message: msg },
268
+ });
269
+ await vi.advanceTimersByTimeAsync(0);
270
+ expect(h.sendRoomRequestToMember).toHaveBeenCalledWith(OTHER_ID, "room-1", FAKE_TOKEN, expect.objectContaining({ verb: "room.read" }));
271
+ }
272
+ finally {
273
+ vi.useRealTimers();
274
+ }
275
+ });
276
+ it("runs the scheduled mark-read work for a dm when not shut down", async () => {
277
+ vi.useFakeTimers();
278
+ try {
279
+ const h = makeHarness();
280
+ h.setOnDelivery(vi.fn());
281
+ const key = "self:x";
282
+ const msg = dmMessage({ from: OTHER_ID, id: messageId() });
283
+ h.deps.dms.set(key, [msg]);
284
+ vi.mocked(loadRoomTokens).mockReturnValue({ [key]: FAKE_TOKEN });
285
+ await h.engine.applyPatch({
286
+ type: "delivery",
287
+ agentId: PEER_ID,
288
+ event: { type: "dm", message: msg },
289
+ });
290
+ await vi.advanceTimersByTimeAsync(0);
291
+ expect(h.sendRoomRequestToMember).toHaveBeenCalledWith(OTHER_ID, key, FAKE_TOKEN, expect.objectContaining({ verb: "room.read" }));
292
+ }
293
+ finally {
294
+ vi.useRealTimers();
295
+ }
296
+ });
297
+ });
298
+ // ---------------------------------------------------------------------------
299
+ // broadcastPatch
300
+ // ---------------------------------------------------------------------------
301
+ describe("DeliveryEngine — broadcastPatch", () => {
302
+ it("broadcasts a state_update message over the transport and invokes onPatch", async () => {
303
+ const h = makeHarness();
304
+ const onPatch = vi.fn();
305
+ h.setOnPatch(onPatch);
306
+ const patch = { type: "room_delete", roomId: "room-1" };
307
+ await h.engine.broadcastPatch(patch);
308
+ expect(h.transport.broadcast).toHaveBeenCalledWith({
309
+ method: "state_update",
310
+ patch,
311
+ });
312
+ expect(onPatch).toHaveBeenCalledWith(patch);
313
+ });
314
+ });
315
+ // ---------------------------------------------------------------------------
316
+ // deliverLocallyAndBroadcast / fireLocalDelivery
317
+ // ---------------------------------------------------------------------------
318
+ describe("DeliveryEngine — deliverLocallyAndBroadcast", () => {
319
+ it("emits a delivery_status(delivered) event back to the room message's own sender", async () => {
320
+ const h = makeHarness();
321
+ const sent = roomMessage({ from: PEER_ID, id: messageId() });
322
+ h.deps.messages.set("room-1", [sent]);
323
+ await h.engine.deliver(OTHER_ID, { type: "room_message", message: sent });
324
+ const senderQueue = h.deps.deliveryQueues.get(PEER_ID);
325
+ expect(senderQueue).toContainEqual(expect.objectContaining({
326
+ type: "delivery_status",
327
+ messageId: sent.id,
328
+ agent: OTHER_ID,
329
+ status: "delivered",
330
+ }));
331
+ });
332
+ it("emits a delivery_status(delivered) event back to a dm's own sender", async () => {
333
+ const h = makeHarness();
334
+ const sent = dmMessage({ from: PEER_ID, id: messageId() });
335
+ h.deps.dms.set("self:x", [sent]);
336
+ await h.engine.deliver(OTHER_ID, { type: "dm", message: sent });
337
+ const senderQueue = h.deps.deliveryQueues.get(PEER_ID);
338
+ expect(senderQueue).toContainEqual(expect.objectContaining({
339
+ type: "delivery_status",
340
+ messageId: sent.id,
341
+ agent: OTHER_ID,
342
+ status: "delivered",
343
+ }));
344
+ });
345
+ it("broadcasts the delivery over the transport", async () => {
346
+ const h = makeHarness();
347
+ await h.engine.deliver(OTHER_ID, {
348
+ type: "member_left",
349
+ room: "room-1",
350
+ agent: OTHER_ID,
351
+ });
352
+ expect(h.transport.broadcast).toHaveBeenCalledWith({
353
+ method: "state_update",
354
+ patch: {
355
+ type: "delivery",
356
+ agentId: OTHER_ID,
357
+ event: { type: "member_left", room: "room-1", agent: OTHER_ID },
358
+ },
359
+ });
360
+ });
361
+ });
362
+ describe("DeliveryEngine — fireLocalDelivery", () => {
363
+ it("does nothing when the event does not target this peer's own agent", () => {
364
+ const h = makeHarness();
365
+ const delivered = vi.fn();
366
+ h.setOnDelivery(delivered);
367
+ h.engine.fireLocalDelivery(OTHER_ID, {
368
+ type: "member_left",
369
+ room: "room-1",
370
+ agent: OTHER_ID,
371
+ });
372
+ expect(delivered).not.toHaveBeenCalled();
373
+ });
374
+ it("does nothing when no onDelivery callback is set", () => {
375
+ const h = makeHarness();
376
+ h.engine.fireLocalDelivery(PEER_ID, {
377
+ type: "member_left",
378
+ room: "room-1",
379
+ agent: PEER_ID,
380
+ });
381
+ // No throw is the assertion: there is no onDelivery to have been called.
382
+ });
383
+ it("skips a room_message this agent has already read", () => {
384
+ const h = makeHarness();
385
+ const delivered = vi.fn();
386
+ h.setOnDelivery(delivered);
387
+ const msg = roomMessage({ readBy: [PEER_ID] });
388
+ h.engine.fireLocalDelivery(PEER_ID, {
389
+ type: "room_message",
390
+ message: msg,
391
+ });
392
+ expect(delivered).not.toHaveBeenCalled();
393
+ });
394
+ it("skips a dm this agent has already read", () => {
395
+ const h = makeHarness();
396
+ const delivered = vi.fn();
397
+ h.setOnDelivery(delivered);
398
+ const msg = dmMessage({ readBy: [PEER_ID] });
399
+ h.engine.fireLocalDelivery(PEER_ID, { type: "dm", message: msg });
400
+ expect(delivered).not.toHaveBeenCalled();
401
+ });
402
+ it("fires for a room_message this agent has not yet read", () => {
403
+ const h = makeHarness();
404
+ const delivered = vi.fn();
405
+ h.setOnDelivery(delivered);
406
+ const msg = roomMessage({ readBy: [] });
407
+ h.engine.fireLocalDelivery(PEER_ID, {
408
+ type: "room_message",
409
+ message: msg,
410
+ });
411
+ expect(delivered).toHaveBeenCalledTimes(1);
412
+ });
413
+ it("dedupes against the identical event already fired once in this process", () => {
414
+ const h = makeHarness();
415
+ const delivered = vi.fn();
416
+ h.setOnDelivery(delivered);
417
+ const event = {
418
+ type: "member_left",
419
+ room: "room-1",
420
+ agent: PEER_ID,
421
+ };
422
+ h.engine.fireLocalDelivery(PEER_ID, event);
423
+ h.engine.fireLocalDelivery(PEER_ID, event);
424
+ expect(delivered).toHaveBeenCalledTimes(1);
425
+ });
426
+ it("evicts the oldest dedup key once the cap is exceeded", () => {
427
+ const h = makeHarness();
428
+ h.setOnDelivery(vi.fn());
429
+ for (let i = 0; i < MAX_LOCAL_DELIVERY_DEDUP_KEYS + 1; i++) {
430
+ h.engine.fireLocalDelivery(PEER_ID, {
431
+ type: "member_left",
432
+ room: `r${i}`,
433
+ agent: PEER_ID,
434
+ });
435
+ }
436
+ expect(h.deps.localDeliveryKeys.size).toBe(MAX_LOCAL_DELIVERY_DEDUP_KEYS);
437
+ });
438
+ it("removes exactly the delivered event from the pending queue, leaving other entries untouched", () => {
439
+ const h = makeHarness();
440
+ h.setOnDelivery(vi.fn());
441
+ const eventA = {
442
+ type: "member_left",
443
+ room: "room-a",
444
+ agent: PEER_ID,
445
+ };
446
+ const eventB = {
447
+ type: "member_left",
448
+ room: "room-b",
449
+ agent: PEER_ID,
450
+ };
451
+ h.deps.deliveryQueues.set(PEER_ID, [eventA, eventB]);
452
+ h.engine.fireLocalDelivery(PEER_ID, eventB);
453
+ expect(h.deps.deliveryQueues.get(PEER_ID)).toEqual([eventA]);
454
+ });
455
+ it("leaves the queue untouched when the fired event isn't present in it", () => {
456
+ const h = makeHarness();
457
+ h.setOnDelivery(vi.fn());
458
+ const eventA = {
459
+ type: "member_left",
460
+ room: "room-a",
461
+ agent: PEER_ID,
462
+ };
463
+ h.deps.deliveryQueues.set(PEER_ID, [eventA]);
464
+ h.engine.fireLocalDelivery(PEER_ID, {
465
+ type: "member_left",
466
+ room: "not-queued",
467
+ agent: PEER_ID,
468
+ });
469
+ expect(h.deps.deliveryQueues.get(PEER_ID)).toEqual([eventA]);
470
+ });
471
+ it("schedules a mark-read timer, tracked in pendingMarkReadTimers, when not shut down", () => {
472
+ const h = makeHarness();
473
+ h.setOnDelivery(vi.fn());
474
+ h.engine.fireLocalDelivery(PEER_ID, {
475
+ type: "room_message",
476
+ message: roomMessage(),
477
+ });
478
+ expect(h.deps.pendingMarkReadTimers).toHaveLength(1);
479
+ });
480
+ it("does not schedule a mark-read timer once already shut down", () => {
481
+ const h = makeHarness();
482
+ h.setOnDelivery(vi.fn());
483
+ h.setShutDown(true);
484
+ h.engine.fireLocalDelivery(PEER_ID, {
485
+ type: "room_message",
486
+ message: roomMessage(),
487
+ });
488
+ expect(h.deps.pendingMarkReadTimers).toHaveLength(0);
489
+ });
490
+ it("runs the scheduled mark-read work for a dm via fireLocalDelivery when not shut down", async () => {
491
+ vi.useFakeTimers();
492
+ try {
493
+ const h = makeHarness();
494
+ h.setOnDelivery(vi.fn());
495
+ const key = "self:y";
496
+ const msg = dmMessage({ from: OTHER_ID, id: messageId() });
497
+ h.deps.dms.set(key, [msg]);
498
+ vi.mocked(loadRoomTokens).mockReturnValue({ [key]: FAKE_TOKEN });
499
+ h.engine.fireLocalDelivery(PEER_ID, { type: "dm", message: msg });
500
+ await vi.advanceTimersByTimeAsync(0);
501
+ expect(h.sendRoomRequestToMember).toHaveBeenCalledWith(OTHER_ID, key, FAKE_TOKEN, expect.objectContaining({ verb: "room.read" }));
502
+ }
503
+ finally {
504
+ vi.useRealTimers();
505
+ }
506
+ });
507
+ it("skips the scheduled mark-read work via fireLocalDelivery if the store is shut down by the time the timer fires", async () => {
508
+ vi.useFakeTimers();
509
+ try {
510
+ const h = makeHarness();
511
+ h.setOnDelivery(vi.fn());
512
+ const msg = roomMessage({ from: OTHER_ID, id: messageId() });
513
+ h.deps.messages.set("room-1", [msg]);
514
+ h.engine.fireLocalDelivery(PEER_ID, {
515
+ type: "room_message",
516
+ message: msg,
517
+ });
518
+ h.setShutDown(true);
519
+ await vi.advanceTimersByTimeAsync(0);
520
+ expect(h.sendRoomRequestToMember).not.toHaveBeenCalled();
521
+ }
522
+ finally {
523
+ vi.useRealTimers();
524
+ }
525
+ });
526
+ });
527
+ // ---------------------------------------------------------------------------
528
+ // deliverToRoom / notifyRoomsOfStatus / notifyRoomsOfNameChange
529
+ // ---------------------------------------------------------------------------
530
+ describe("DeliveryEngine — deliverToRoom", () => {
531
+ it("does nothing for an unknown room", async () => {
532
+ const h = makeHarness();
533
+ await expect(h.engine.deliverToRoom("no-such-room", {
534
+ type: "member_left",
535
+ room: "no-such-room",
536
+ agent: OTHER_ID,
537
+ })).resolves.toBeUndefined();
538
+ });
539
+ it("delivers to every member except the excluded one", async () => {
540
+ const h = makeHarness();
541
+ h.deps.rooms.set("room-1", room({ members: [PEER_ID, OTHER_ID, THIRD_ID] }));
542
+ await h.engine.deliverToRoom("room-1", {
543
+ type: "member_status",
544
+ room: "room-1",
545
+ agent: PEER_ID,
546
+ status: "idle",
547
+ }, OTHER_ID);
548
+ expect(h.deps.deliveryQueues.get(PEER_ID)).toHaveLength(1);
549
+ expect(h.deps.deliveryQueues.get(THIRD_ID)).toHaveLength(1);
550
+ expect(h.deps.deliveryQueues.get(OTHER_ID)).toBeUndefined();
551
+ });
552
+ });
553
+ describe("DeliveryEngine — notifyRoomsOfStatus", () => {
554
+ it("does nothing for an agent with no known record", async () => {
555
+ const h = makeHarness();
556
+ await expect(h.engine.notifyRoomsOfStatus(OTHER_ID, "idle")).resolves.toBeUndefined();
557
+ });
558
+ it("delivers a member_status event to every one of the agent's subscribed rooms", async () => {
559
+ const h = makeHarness();
560
+ h.deps.agents.set(OTHER_ID, agent({ subscribedRooms: ["room-a", "room-b"] }));
561
+ h.deps.rooms.set("room-a", room({ id: "room-a", members: [PEER_ID] }));
562
+ h.deps.rooms.set("room-b", room({ id: "room-b", members: [THIRD_ID] }));
563
+ await h.engine.notifyRoomsOfStatus(OTHER_ID, "busy");
564
+ expect(h.deps.deliveryQueues.get(PEER_ID)).toContainEqual(expect.objectContaining({
565
+ type: "member_status",
566
+ room: "room-a",
567
+ agent: OTHER_ID,
568
+ status: "busy",
569
+ }));
570
+ expect(h.deps.deliveryQueues.get(THIRD_ID)).toContainEqual(expect.objectContaining({
571
+ type: "member_status",
572
+ room: "room-b",
573
+ agent: OTHER_ID,
574
+ status: "busy",
575
+ }));
576
+ });
577
+ });
578
+ describe("DeliveryEngine — notifyRoomsOfNameChange", () => {
579
+ it("does nothing for an agent with no known record", async () => {
580
+ const h = makeHarness();
581
+ await expect(h.engine.notifyRoomsOfNameChange(OTHER_ID, "old", "new")).resolves.toBeUndefined();
582
+ });
583
+ it("notifies other room members and the agent itself exactly once each", async () => {
584
+ const h = makeHarness();
585
+ h.deps.agents.set(OTHER_ID, agent({ subscribedRooms: ["room-a"] }));
586
+ h.deps.rooms.set("room-a", room({ id: "room-a", members: [PEER_ID, OTHER_ID] }));
587
+ await h.engine.notifyRoomsOfNameChange(OTHER_ID, "old-name", "new-name");
588
+ const peerQueue = h.deps.deliveryQueues.get(PEER_ID) ?? [];
589
+ const selfQueue = h.deps.deliveryQueues.get(OTHER_ID) ?? [];
590
+ expect(peerQueue.filter((e) => e.type === "name_changed")).toHaveLength(1);
591
+ expect(selfQueue.filter((e) => e.type === "name_changed")).toHaveLength(1);
592
+ });
593
+ });
594
+ // ---------------------------------------------------------------------------
595
+ // emitDeliveryStatus / findMessageSender / findMessageLocation (private, reached via public callers already exercised above; direct edge cases below)
596
+ // ---------------------------------------------------------------------------
597
+ describe("DeliveryEngine — emitDeliveryStatus via deliverLocallyAndBroadcast", () => {
598
+ it("emits nothing when the message's sender cannot be found anywhere", async () => {
599
+ const h = makeHarness();
600
+ const orphanMessage = roomMessage({ id: messageId() });
601
+ // Deliberately not stored in h.deps.messages, so findMessageSender returns undefined.
602
+ await expect(h.engine.deliver(OTHER_ID, {
603
+ type: "room_message",
604
+ message: orphanMessage,
605
+ })).resolves.toBeUndefined();
606
+ expect(h.deps.deliveryQueues.size).toBe(1);
607
+ expect(h.deps.deliveryQueues.get(OTHER_ID)).toHaveLength(1);
608
+ });
609
+ it("finds the room message's sender by exact id match among several messages in the same room", async () => {
610
+ const h = makeHarness();
611
+ const target = roomMessage({ id: messageId(), from: PEER_ID });
612
+ h.deps.messages.set("room-1", [
613
+ roomMessage({ id: messageId(), from: THIRD_ID }),
614
+ target,
615
+ ]);
616
+ await h.engine.deliver(OTHER_ID, {
617
+ type: "room_message",
618
+ message: target,
619
+ });
620
+ expect(h.deps.deliveryQueues.get(PEER_ID)).toContainEqual(expect.objectContaining({
621
+ type: "delivery_status",
622
+ messageId: target.id,
623
+ }));
624
+ });
625
+ it("finds a dm's sender by searching across every dm history when no room is given", async () => {
626
+ const h = makeHarness();
627
+ const target = dmMessage({ id: messageId(), from: PEER_ID });
628
+ h.deps.dms.set("self:other", [
629
+ dmMessage({ id: messageId(), from: THIRD_ID }),
630
+ ]);
631
+ h.deps.dms.set("self:x", [target]);
632
+ await h.engine.deliver(OTHER_ID, { type: "dm", message: target });
633
+ expect(h.deps.deliveryQueues.get(PEER_ID)).toContainEqual(expect.objectContaining({
634
+ type: "delivery_status",
635
+ messageId: target.id,
636
+ }));
637
+ });
638
+ });
639
+ // ---------------------------------------------------------------------------
640
+ // markRead (private, reached only via drainDelivery/fireLocalDelivery/applyPatch's timer -- direct edge cases below via drainDelivery, which awaits it synchronously with no timer indirection)
641
+ // ---------------------------------------------------------------------------
642
+ describe("DeliveryEngine — markRead via drainDelivery", () => {
643
+ it("adds the reader to readBy without duplicating an already-present entry", async () => {
644
+ const h = makeHarness();
645
+ const msg = roomMessage({
646
+ id: messageId(),
647
+ from: OTHER_ID,
648
+ readBy: [PEER_ID],
649
+ });
650
+ h.deps.messages.set("room-1", [msg]);
651
+ h.deps.deliveryQueues.set(PEER_ID, [
652
+ { type: "room_message", message: msg },
653
+ ]);
654
+ await h.engine.drainDelivery(PEER_ID);
655
+ expect(msg.readBy).toEqual([PEER_ID]);
656
+ });
657
+ it("pushes the reader onto readBy when not already present", async () => {
658
+ const h = makeHarness();
659
+ const msg = roomMessage({ id: messageId(), from: OTHER_ID, readBy: [] });
660
+ h.deps.messages.set("room-1", [msg]);
661
+ h.deps.deliveryQueues.set(PEER_ID, [
662
+ { type: "room_message", message: msg },
663
+ ]);
664
+ await h.engine.drainDelivery(PEER_ID);
665
+ expect(msg.readBy).toEqual([PEER_ID]);
666
+ });
667
+ it("finds the exact target room message by id among several others in the same room, not merely the first", async () => {
668
+ const h = makeHarness();
669
+ const target = roomMessage({ id: messageId(), from: OTHER_ID, readBy: [] });
670
+ h.deps.messages.set("room-1", [
671
+ roomMessage({ id: messageId(), from: THIRD_ID }),
672
+ target,
673
+ ]);
674
+ h.deps.deliveryQueues.set(PEER_ID, [
675
+ { type: "room_message", message: target },
676
+ ]);
677
+ await h.engine.drainDelivery(PEER_ID);
678
+ expect(target.readBy).toEqual([PEER_ID]);
679
+ expect(h.sendRoomRequestToMember).toHaveBeenCalledWith(OTHER_ID, "room-1", FAKE_TOKEN, expect.objectContaining({ verb: "room.read" }));
680
+ });
681
+ it("finds the exact target dm by id among several others in the same dm history, not merely the first", async () => {
682
+ const h = makeHarness();
683
+ const dmKey = "self:multi";
684
+ const target = dmMessage({ id: messageId(), from: OTHER_ID, readBy: [] });
685
+ h.deps.dms.set(dmKey, [
686
+ dmMessage({ id: messageId(), from: THIRD_ID }),
687
+ target,
688
+ ]);
689
+ vi.mocked(loadRoomTokens).mockReturnValue({ [dmKey]: FAKE_TOKEN });
690
+ h.deps.deliveryQueues.set(PEER_ID, [{ type: "dm", message: target }]);
691
+ await h.engine.drainDelivery(PEER_ID);
692
+ expect(target.readBy).toEqual([PEER_ID]);
693
+ expect(h.sendRoomRequestToMember).toHaveBeenCalledWith(OTHER_ID, dmKey, FAKE_TOKEN, expect.objectContaining({ verb: "room.read" }));
694
+ });
695
+ it("does not notify the author when the reader marking read is the author themselves", async () => {
696
+ const h = makeHarness();
697
+ const msg = roomMessage({ id: messageId(), from: PEER_ID, readBy: [] });
698
+ h.deps.messages.set("room-1", [msg]);
699
+ h.deps.deliveryQueues.set(PEER_ID, [
700
+ { type: "room_message", message: msg },
701
+ ]);
702
+ await h.engine.drainDelivery(PEER_ID);
703
+ expect(h.sendRoomRequestToMember).not.toHaveBeenCalled();
704
+ });
705
+ it("sends a directed room.read request to the message's own author with the message id and current time", async () => {
706
+ const h = makeHarness();
707
+ const msg = roomMessage({ id: messageId(), from: OTHER_ID, readBy: [] });
708
+ h.deps.messages.set("room-1", [msg]);
709
+ h.deps.deliveryQueues.set(PEER_ID, [
710
+ { type: "room_message", message: msg },
711
+ ]);
712
+ await h.engine.drainDelivery(PEER_ID);
713
+ expect(h.sendRoomRequestToMember).toHaveBeenCalledWith(OTHER_ID, "room-1", FAKE_TOKEN, expect.objectContaining({ verb: "room.read", at: NOW_MS }));
714
+ });
715
+ it("does nothing when no room:member token is persisted for the message's room", async () => {
716
+ const h = makeHarness();
717
+ vi.mocked(loadRoomTokens).mockReturnValue({});
718
+ const msg = roomMessage({ id: messageId(), from: OTHER_ID, readBy: [] });
719
+ h.deps.messages.set("room-1", [msg]);
720
+ h.deps.deliveryQueues.set(PEER_ID, [
721
+ { type: "room_message", message: msg },
722
+ ]);
723
+ await h.engine.drainDelivery(PEER_ID);
724
+ expect(h.sendRoomRequestToMember).not.toHaveBeenCalled();
725
+ // The local readBy update still happened -- read receipts are best-effort at the wire-notification step only.
726
+ expect(msg.readBy).toEqual([PEER_ID]);
727
+ });
728
+ it("does nothing when the message cannot be located at all", async () => {
729
+ const h = makeHarness();
730
+ h.deps.deliveryQueues.set(PEER_ID, [
731
+ { type: "room_message", message: roomMessage({ id: messageId() }) },
732
+ ]);
733
+ await expect(h.engine.drainDelivery(PEER_ID)).resolves.toBeDefined();
734
+ expect(h.sendRoomRequestToMember).not.toHaveBeenCalled();
735
+ });
736
+ });
737
+ afterEach(() => {
738
+ vi.useRealTimers();
739
+ });
740
+ //# sourceMappingURL=delivery-engine-delivery.test.js.map