agent-comms 2.20.2 → 2.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +1 -1
  4. package/dist/core/agent-registry.d.ts +38 -0
  5. package/dist/core/agent-registry.d.ts.map +1 -0
  6. package/dist/core/agent-registry.js +117 -0
  7. package/dist/core/agent-registry.js.map +1 -0
  8. package/dist/core/connection-approval.d.ts +48 -0
  9. package/dist/core/connection-approval.d.ts.map +1 -0
  10. package/dist/core/connection-approval.js +89 -0
  11. package/dist/core/connection-approval.js.map +1 -0
  12. package/dist/core/delivery-engine.d.ts +82 -0
  13. package/dist/core/delivery-engine.d.ts.map +1 -0
  14. package/dist/core/delivery-engine.js +464 -0
  15. package/dist/core/delivery-engine.js.map +1 -0
  16. package/dist/core/federation-bridge.d.ts +32 -0
  17. package/dist/core/federation-bridge.d.ts.map +1 -0
  18. package/dist/core/federation-bridge.js +113 -0
  19. package/dist/core/federation-bridge.js.map +1 -0
  20. package/dist/core/mesh-store-shared.d.ts +39 -0
  21. package/dist/core/mesh-store-shared.d.ts.map +1 -0
  22. package/dist/core/mesh-store-shared.js +32 -0
  23. package/dist/core/mesh-store-shared.js.map +1 -0
  24. package/dist/core/mesh-store.d.ts +65 -256
  25. package/dist/core/mesh-store.d.ts.map +1 -1
  26. package/dist/core/mesh-store.js +211 -1917
  27. package/dist/core/mesh-store.js.map +1 -1
  28. package/dist/core/peer-lifecycle.d.ts +36 -0
  29. package/dist/core/peer-lifecycle.d.ts.map +1 -0
  30. package/dist/core/peer-lifecycle.js +85 -0
  31. package/dist/core/peer-lifecycle.js.map +1 -0
  32. package/dist/core/room-lifecycle.d.ts +82 -0
  33. package/dist/core/room-lifecycle.d.ts.map +1 -0
  34. package/dist/core/room-lifecycle.js +459 -0
  35. package/dist/core/room-lifecycle.js.map +1 -0
  36. package/dist/core/room-messaging.d.ts +31 -0
  37. package/dist/core/room-messaging.d.ts.map +1 -0
  38. package/dist/core/room-messaging.js +120 -0
  39. package/dist/core/room-messaging.js.map +1 -0
  40. package/dist/core/room-protocol.d.ts +85 -0
  41. package/dist/core/room-protocol.d.ts.map +1 -0
  42. package/dist/core/room-protocol.js +479 -0
  43. package/dist/core/room-protocol.js.map +1 -0
  44. package/dist/core/room-wire-extensions.d.ts +36 -0
  45. package/dist/core/room-wire-extensions.d.ts.map +1 -0
  46. package/dist/core/room-wire-extensions.js +52 -0
  47. package/dist/core/room-wire-extensions.js.map +1 -0
  48. package/dist/core/stale-agent-checker.d.ts +28 -0
  49. package/dist/core/stale-agent-checker.d.ts.map +1 -0
  50. package/dist/core/stale-agent-checker.js +77 -0
  51. package/dist/core/stale-agent-checker.js.map +1 -0
  52. package/package.json +1 -1
@@ -0,0 +1,120 @@
1
+ /**
2
+ * RoomMessaging — the sending side of room messages and DMs: sendRoomMessage/sendDm fan out one directed, wire-authenticated room.send per member via RoomProtocol's own retry-queueing sendRoomRequestToMember (P3.5), and readRoomMessages reads back a room's local history. Split out of mesh-store.ts to reduce it under the repo's max-lines cap.
3
+ */
4
+ import { bytesFromHex, bytesToHex } from "wire-mesh-core/domain/device-id";
5
+ import { dmRoomPath } from "./room-path.js";
6
+ import { loadRoomTokens } from "./identity-store.js";
7
+ import { randomId } from "./random-id.js";
8
+ import { CommsError } from "./store.js";
9
+ export class RoomMessaging {
10
+ deps;
11
+ constructor(deps) {
12
+ this.deps = deps;
13
+ }
14
+ /**
15
+ * Sends a room message via a real, wire-authenticated room.send fan-out (P3.5): one directed request per member, each carrying this sender's own persisted room:member token, rather than the legacy broadcastPatch's full-state replication. A member unreachable right now is queued for retry (see sendRoomRequestToMember/flushPendingRoomRequests) instead of blocking or failing the whole send -- delivery to any one recipient is independent of every other.
16
+ */
17
+ async sendRoomMessage(roomId, from, content, replyTo, streamingBehavior) {
18
+ const room = this.deps.rooms.get(roomId);
19
+ if (!room)
20
+ throw new CommsError(`Room ${roomId} not found`, "ROOM_NOT_FOUND");
21
+ if (!room.members.includes(from))
22
+ throw new CommsError(`Not a member of ${roomId}`, "NOT_MEMBER");
23
+ const { slot, clock } = this.deps.requireIdentity();
24
+ const token = loadRoomTokens(slot)[roomId];
25
+ if (token === undefined) {
26
+ throw new CommsError(`No room:member token for ${roomId}`, "NOT_MEMBER");
27
+ }
28
+ const messageId = randomId();
29
+ const id = bytesToHex(messageId);
30
+ const message = {
31
+ id,
32
+ from,
33
+ room: roomId,
34
+ content,
35
+ timestamp: new Date().toISOString(),
36
+ readBy: [from],
37
+ ...(replyTo !== undefined && { replyTo }),
38
+ ...(streamingBehavior !== undefined && { streamingBehavior }),
39
+ };
40
+ const arr = this.deps.messages.get(roomId) ?? [];
41
+ arr.push(message);
42
+ this.deps.messages.set(roomId, arr);
43
+ // Forward to federated links if the room is federated
44
+ if (room.federated) {
45
+ await this.deps.federation.forwardRoomMessage(roomId, message);
46
+ }
47
+ const params = {
48
+ verb: "room.send",
49
+ "message-id": messageId,
50
+ "sent-at": clock.now(),
51
+ text: content,
52
+ ...(replyTo !== undefined && {
53
+ refs: [{ id: bytesFromHex(replyTo), relation: "reply" }],
54
+ }),
55
+ ...(streamingBehavior !== undefined && {
56
+ "streaming-behavior": streamingBehavior,
57
+ }),
58
+ };
59
+ for (const memberId of room.members) {
60
+ if (memberId !== from) {
61
+ await this.deps.roomProtocol.sendRoomRequestToMember(memberId, roomId, token, params);
62
+ }
63
+ }
64
+ return message;
65
+ }
66
+ async readRoomMessages(roomId, since) {
67
+ await Promise.resolve();
68
+ const arr = this.deps.messages.get(roomId) ?? [];
69
+ if (!since)
70
+ return [...arr];
71
+ return arr.filter((m) => m.timestamp > since);
72
+ }
73
+ /**
74
+ * Sends a DM via the same wire-authenticated room.send fan-out sendRoomMessage uses (P3.5): a DM is just a dm-shaped room path with exactly one other member, so it rides the identical mechanism rather than a separate one. Self-DM is the one exception -- a purely local scratchpad note that never leaves the process, so it needs no token and no wire round trip at all.
75
+ */
76
+ async sendDm(from, to, content, streamingBehavior) {
77
+ if (to !== from) {
78
+ const recipient = this.deps.agents.get(to);
79
+ if (!recipient)
80
+ throw new CommsError(`Agent ${to} not found`, "AGENT_NOT_FOUND");
81
+ if (recipient.visibility === "ghost")
82
+ throw new CommsError(`Cannot DM agent ${to}`, "AGENT_NOT_FOUND");
83
+ }
84
+ const messageId = randomId();
85
+ const id = bytesToHex(messageId);
86
+ const message = {
87
+ id,
88
+ from,
89
+ to,
90
+ content,
91
+ timestamp: new Date().toISOString(),
92
+ readBy: [from],
93
+ ...(streamingBehavior !== undefined && { streamingBehavior }),
94
+ };
95
+ // Self-DM is a purely local scratchpad note -- it never leaves the process, so it needs no room-path and dmRoomPath's own a===b refusal (a path naming the same device twice is not a valid DM path at all) correctly does not apply here.
96
+ const key = to === from ? `self:${from}` : dmRoomPath(from, to);
97
+ const arr = this.deps.dms.get(key) ?? [];
98
+ arr.push(message);
99
+ this.deps.dms.set(key, arr);
100
+ if (to !== from) {
101
+ const { slot, clock } = this.deps.requireIdentity();
102
+ const token = loadRoomTokens(slot)[key];
103
+ if (token === undefined) {
104
+ throw new CommsError(`No room:member token for ${key}`, "NOT_MEMBER");
105
+ }
106
+ const params = {
107
+ verb: "room.send",
108
+ "message-id": messageId,
109
+ "sent-at": clock.now(),
110
+ text: content,
111
+ ...(streamingBehavior !== undefined && {
112
+ "streaming-behavior": streamingBehavior,
113
+ }),
114
+ };
115
+ await this.deps.roomProtocol.sendRoomRequestToMember(to, key, token, params);
116
+ }
117
+ return message;
118
+ }
119
+ }
120
+ //# sourceMappingURL=room-messaging.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"room-messaging.js","sourceRoot":"","sources":["../../src/core/room-messaging.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * RoomProtocol — the receiving/responding half of the room wire protocol: the room-verb handlers a WireMeshTransport dispatches into (room.send, room.read, room.members, room.join, room.invite, room.leave), the directed room-domain request fan-out primitives (sendRoomMessageDirected, sendRoomRequestToMember, its retry queue and flush), and the human accept/reject decision points for a pending room.join. Split out of mesh-store.ts to reduce it under the repo's max-lines cap. Owns pendingRoomRequests and pendingRoomJoins exclusively -- nothing outside this class ever reads or writes them.
3
+ */
4
+ import type { CapabilityToken } from "wire-mesh-core/generated/protocol";
5
+ import type { MeshStoreIdentity } from "./mesh-store-shared.js";
6
+ import type { DeliveryEngine } from "./delivery-engine.js";
7
+ import type { RoomVerbHandler } from "./room-router.js";
8
+ import type { MeshTransport } from "./transport.js";
9
+ import type { AgentIdentity, DmMessage, Room, RoomMessage } from "./types.js";
10
+ /** The state and collaborators RoomProtocol needs from MeshStore. rooms/messages/dms/agents/dmRequestsInitiatedByMe are direct references into MeshStore's own fields; deliveryEngine is the already-constructed instance, narrowed to what a room-verb handler ever needs; revokeMemberGrant is deferred (RoomLifecycle, which owns it, doesn't exist yet when RoomProtocol is constructed -- construction order: ... -> roomProtocol -> roomMessaging -> roomLifecycle -> ...), wired the same lazy-`this`-capture way DeliveryEngine's own sendRoomRequestToMember closure is. */
11
+ export interface RoomProtocolDeps {
12
+ rooms: Map<string, Room>;
13
+ messages: Map<string, RoomMessage[]>;
14
+ dms: Map<string, DmMessage[]>;
15
+ agents: Map<string, AgentIdentity>;
16
+ dmRequestsInitiatedByMe: Set<string>;
17
+ getPeerId: () => string;
18
+ requireIdentity: () => MeshStoreIdentity;
19
+ requireTransport: () => MeshTransport;
20
+ deliveryEngine: Pick<DeliveryEngine, "queueDelivery" | "fireLocalDelivery" | "bump" | "recordMemberOp" | "refreshMembership" | "broadcastPatch" | "deliverToRoom">;
21
+ /** RoomLifecycle's own method, deferred -- see the interface doc comment above. */
22
+ revokeMemberGrant: (roomId: string, memberId: string) => Promise<void>;
23
+ }
24
+ export declare class RoomProtocol {
25
+ private readonly deps;
26
+ /** Directed room-domain requests (room.send, room.read) that failed because their target member wasn't reachable at send time, held for retry when that member's own connection is (re)established -- the wire-authenticated fan-out's substitute for the legacy full-state-sync's own automatic eventual consistency, since a direct request to a disconnected peer fails immediately with no protocol-level retry of its own. Keyed by member device-id hex, bounded oldest-first per member with the same cap ordinary delivery queues use. */
27
+ private readonly pendingRoomRequests;
28
+ /** Pending room.join requests awaiting owner approval, keyed by `${roomPath}::${requesterId}` -- the held-open manage-request's own resolve() function is stored here so acceptRoomJoin/rejectRoomJoin can settle it in place. */
29
+ private readonly pendingRoomJoins;
30
+ constructor(deps: RoomProtocolDeps);
31
+ /** Room verb handlers this store registers with its own WireMeshTransport, keyed by params.verb per room-router.ts's own dispatch discipline. */
32
+ get roomVerbHandlers(): Partial<Record<string, RoomVerbHandler>>;
33
+ /** Reads the "reply" message-ref out of a room.send's own params (if any) and returns the hex id it names -- room.send's replyTo carries a single parent message, so the first reply-relation ref is the one that matters; any further refs are a future relation this handler doesn't yet act on. */
34
+ private static replyToFromRefs;
35
+ /** Reads room.send's own "streaming-behavior" extension field (open params tail, not a named schema field) and validates it against the same StreamingBehavior contract every other delivery path already enforces -- an unrecognised or malformed value is dropped rather than rejecting the whole send, matching core/room's own obligation to ignore what it doesn't understand instead of failing closed on an extension field. */
36
+ private static streamingBehaviorFromParams;
37
+ /**
38
+ * Receiving side of a directed room.send (P3.5): verifies the presented token against all six of core/room's own obligations, then delivers the message locally exactly once -- the manage-response this returns IS the delivery receipt, so there is no separate "delivered" event to emit the way the legacy broadcastPatch path needed one. Branches on the room-path's own shape: an owner-named path stores a RoomMessage in this room's own history and fires a room_message event; a DM path stores a DmMessage keyed by the same dm-path sendDm already uses and fires a dm event -- both ride the identical room:member-gated verb, since a DM is just a room-path variant, not a separate verb.
39
+ */
40
+ private handleRoomSend;
41
+ /**
42
+ * Receiving side of a directed room.read (P3.5): verifies the presented token the same way handleRoomSend does, then for each read message-id in the batch, updates this store's own local copy of that message's readBy (this store holds one because it's the message's own author -- the reason it's the one being notified) and fires a delivery_status event locally, replacing what markRead used to broadcast via the legacy message_read patch. Read receipts stay voluntary and best-effort by design: a message-id this store doesn't recognise (already expired from history, or simply never this store's own) is silently skipped rather than treated as an error.
43
+ */
44
+ private handleRoomRead;
45
+ /**
46
+ * Receiving side of room.members (P3.6): a plain membership + room-state refresh for an already-admitted member, verified the same way handleRoomSend/handleRoomRead are -- room.members grants nothing new, it just answers "who's here, and what's this room called" on demand, the same information room.join's own response already carries at admission time. A DM path has no Room record (this.rooms never holds one for a dm-shaped path) and no name/description/type to report, so its own members list is derived directly from the path's own two participants instead.
47
+ */
48
+ private handleRoomMembers;
49
+ /**
50
+ * Sends one directed room.send to a single member's own session, attaching this store's own persisted room:member token for the given room path -- the primitive P3.5's own directed fan-out (deliverToRoom) will loop over per member once it replaces the legacy broadcastPatch path this store still uses for message delivery today. Throws if this store holds no token for the room: never a member, or a token that expired or was revoked with nothing fresh persisted in its place.
51
+ */
52
+ sendRoomMessageDirected(roomPath: string, memberId: string, text: string): Promise<void>;
53
+ /** Records a room-domain request that couldn't reach memberId right now, for a later flushPendingRoomRequests to retry once that member reconnects. Bounded oldest-first with the same cap ordinary delivery queues use, so an indefinitely-offline member cannot grow this without limit. */
54
+ private queuePendingRoomRequest;
55
+ /**
56
+ * Sends one directed room-domain request (room.send, room.read, or any future room:member-gated verb) to a single member, queuing it for retry instead of throwing when the member isn't currently reachable -- the fan-out's own per-recipient primitive, distinct from sendRoomMessageDirected's deliberate throw-on-failure contract for a caller sending to one specific, known recipient. Silently drops a request this store no longer holds a token for (no longer a member of the room) rather than queuing something that will only fail again on retry.
57
+ */
58
+ sendRoomRequestToMember(memberId: string, roomPath: string, token: CapabilityToken, params: Record<string, unknown>): Promise<void>;
59
+ /** Retries every room.send queued for memberId since it was last reachable, dropping (not re-queuing) any whose room this store no longer holds a token for. Called once a connection to memberId is (re)established -- handlePeerConnected fires for both a fresh introduction and a reconnection after downtime, exactly the two cases a queued send needs to be retried on. */
60
+ flushPendingRoomRequests(memberId: string): Promise<void>;
61
+ /**
62
+ * Owner-side admission for an incoming room.join request, against either a named room this store owns or a DM path this store is a participant of. Named-room admission always needs a human decision; DM admission needs one only for the party being contacted first -- the reply half of the two-round consent flow (section 6) auto-approves, since a reply on a path this node itself opened is not unsolicited contact.
63
+ */
64
+ private handleRoomJoin;
65
+ /** Shared admission continuation for both room.join branches above: waits for a human decision (unless auto-approved), then mints and returns the requester's own independent, parent-less room:member grant. */
66
+ private admitRoomJoin;
67
+ /**
68
+ * Receiving side of a real, wire-level room.invite (P3.8): unlike every other room verb, the request itself is deliberately ungated (the sender already IS the room's own owner, with no need to prove capability to invite) -- the security instead lives entirely in the embedded params.token, which must genuinely name this store's own identity as bearer and root at the room path's own claimed owner. Persists the verified token via saveRoomToken (mirroring joinRemoteRoom's own persistence) and fires a local room_invite delivery event carrying the room's real name/description (room-state) and the inviter's real name/cwd (inviter-agent) when the sender includes them, falling back to the bare device-id and room path otherwise.
69
+ */
70
+ private handleRoomInvite;
71
+ /**
72
+ * Receiving side of a real, wire-level room.leave (P3.8), covering both an actual member leaving and a decline of a never-joined invite -- the same wire request either way, since both are "give up a room:member grant I hold," per leaveRemoteRoom's own reasoning. Distinguishes the two purely from this store's own membership/invited lists (never from anything the sender claims), revokes the sender's grant for real via revokeMemberGrant, and notifies accordingly: member_left broadcast to the room's other members for a real leave, a local invite_declined event (carrying the sender's own optional reason extension) for a decline -- there is no third party to notify for a decline, since nobody else ever knew about an invite that was never accepted.
73
+ */
74
+ private handleRoomLeave;
75
+ /** Every room.join request currently held open awaiting this store's own accept/reject decision. */
76
+ listPendingRoomJoins(): {
77
+ roomPath: string;
78
+ requesterId: string;
79
+ }[];
80
+ /** Approves a pending room.join request, resuming handleRoomJoin's own suspended mint-and-respond continuation. */
81
+ acceptRoomJoin(roomPath: string, requesterId: string): void;
82
+ /** Denies a pending room.join request, optionally with a reason surfaced to the requester in the resulting manage-error's own message field. */
83
+ rejectRoomJoin(roomPath: string, requesterId: string, reason?: string): void;
84
+ }
85
+ //# sourceMappingURL=room-protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"room-protocol.d.ts","sourceRoot":"","sources":["../../src/core/room-protocol.ts"],"names":[],"mappings":"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"}