agent-comms 3.21.0 → 3.22.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 (78) 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/bridges/user/web/actions.d.ts +59 -0
  5. package/dist/bridges/user/web/actions.d.ts.map +1 -0
  6. package/dist/bridges/user/web/actions.js +109 -0
  7. package/dist/bridges/user/web/actions.js.map +1 -0
  8. package/dist/bridges/user/web/event-publisher.d.ts +30 -0
  9. package/dist/bridges/user/web/event-publisher.d.ts.map +1 -0
  10. package/dist/bridges/user/web/event-publisher.js +84 -0
  11. package/dist/bridges/user/web/event-publisher.js.map +1 -0
  12. package/dist/bridges/user/web/router.d.ts +696 -0
  13. package/dist/bridges/user/web/router.d.ts.map +1 -0
  14. package/dist/bridges/user/web/router.js +50 -0
  15. package/dist/bridges/user/web/router.js.map +1 -0
  16. package/dist/bridges/user/web/server.d.ts +2 -0
  17. package/dist/bridges/user/web/server.d.ts.map +1 -1
  18. package/dist/bridges/user/web/server.js +94 -114
  19. package/dist/bridges/user/web/server.js.map +1 -1
  20. package/dist/bridges/user/web/test/orpc-router.integration.test.d.ts +7 -0
  21. package/dist/bridges/user/web/test/orpc-router.integration.test.d.ts.map +1 -0
  22. package/dist/bridges/user/web/test/orpc-router.integration.test.js +214 -0
  23. package/dist/bridges/user/web/test/orpc-router.integration.test.js.map +1 -0
  24. package/dist/core/bridge.d.ts +3 -0
  25. package/dist/core/bridge.d.ts.map +1 -1
  26. package/dist/core/bridge.js +14 -0
  27. package/dist/core/bridge.js.map +1 -1
  28. package/dist/core/data-frame-routing.d.ts +14 -0
  29. package/dist/core/data-frame-routing.d.ts.map +1 -0
  30. package/dist/core/data-frame-routing.js +37 -0
  31. package/dist/core/data-frame-routing.js.map +1 -0
  32. package/dist/core/gossip-directory.d.ts +5 -0
  33. package/dist/core/gossip-directory.d.ts.map +1 -1
  34. package/dist/core/gossip-directory.js +7 -0
  35. package/dist/core/gossip-directory.js.map +1 -1
  36. package/dist/core/hub-session.d.ts +5 -1
  37. package/dist/core/hub-session.d.ts.map +1 -1
  38. package/dist/core/hub-session.js +24 -0
  39. package/dist/core/hub-session.js.map +1 -1
  40. package/dist/core/mesh-graph-trace-tool.d.ts +12 -0
  41. package/dist/core/mesh-graph-trace-tool.d.ts.map +1 -0
  42. package/dist/core/mesh-graph-trace-tool.js +60 -0
  43. package/dist/core/mesh-graph-trace-tool.js.map +1 -0
  44. package/dist/core/mesh-graph.d.ts +14 -0
  45. package/dist/core/mesh-graph.d.ts.map +1 -0
  46. package/dist/core/mesh-graph.js +46 -0
  47. package/dist/core/mesh-graph.js.map +1 -0
  48. package/dist/core/mesh-network-actions.d.ts +28 -0
  49. package/dist/core/mesh-network-actions.d.ts.map +1 -0
  50. package/dist/core/mesh-network-actions.js +143 -0
  51. package/dist/core/mesh-network-actions.js.map +1 -0
  52. package/dist/core/mesh-store.d.ts +5 -1
  53. package/dist/core/mesh-store.d.ts.map +1 -1
  54. package/dist/core/mesh-store.js +16 -0
  55. package/dist/core/mesh-store.js.map +1 -1
  56. package/dist/core/tool.d.ts +3 -10
  57. package/dist/core/tool.d.ts.map +1 -1
  58. package/dist/core/tool.js +15 -147
  59. package/dist/core/tool.js.map +1 -1
  60. package/dist/core/transport.d.ts +35 -0
  61. package/dist/core/transport.d.ts.map +1 -1
  62. package/dist/core/types.d.ts +12 -0
  63. package/dist/core/types.d.ts.map +1 -1
  64. package/dist/core/types.js +6 -0
  65. package/dist/core/types.js.map +1 -1
  66. package/dist/core/wire-mesh-transport.d.ts +7 -2
  67. package/dist/core/wire-mesh-transport.d.ts.map +1 -1
  68. package/dist/core/wire-mesh-transport.js +22 -38
  69. package/dist/core/wire-mesh-transport.js.map +1 -1
  70. package/dist/test/mesh-graph-trace-tool.test.d.ts +2 -0
  71. package/dist/test/mesh-graph-trace-tool.test.d.ts.map +1 -0
  72. package/dist/test/mesh-graph-trace-tool.test.js +104 -0
  73. package/dist/test/mesh-graph-trace-tool.test.js.map +1 -0
  74. package/dist/test/mesh-graph-trace.integration.test.d.ts +5 -0
  75. package/dist/test/mesh-graph-trace.integration.test.d.ts.map +1 -0
  76. package/dist/test/mesh-graph-trace.integration.test.js +146 -0
  77. package/dist/test/mesh-graph-trace.integration.test.js.map +1 -0
  78. package/package.json +2 -2
@@ -15,7 +15,7 @@
15
15
  "url": "https://github.com/ExaDev/agent-comms.git"
16
16
  },
17
17
  "description": "Cross-harness LLM agent communication mesh — rooms, DMs, and presence",
18
- "version": "3.21.0"
18
+ "version": "3.22.0"
19
19
  }
20
20
  ]
21
21
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agent-comms",
3
3
  "description": "Cross-harness LLM agent communication mesh — rooms, DMs, and presence",
4
- "version": "3.21.0",
4
+ "version": "3.22.0",
5
5
  "author": {
6
6
  "name": "ExaDev"
7
7
  },
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![GitHub](https://img.shields.io/badge/GitHub-181717?logo=github&logoColor=white)](https://github.com/ExaDev/agent-comms)
4
4
  [![npm](https://img.shields.io/badge/npm-CB3837?logo=npm&logoColor=white)](https://www.npmjs.com/package/agent-comms)
5
- [![version](https://img.shields.io/badge/version-3.21.0-blue)](https://github.com/ExaDev/agent-comms/releases/tag/v3.21.0)
5
+ [![version](https://img.shields.io/badge/version-3.22.0-blue)](https://github.com/ExaDev/agent-comms/releases/tag/v3.22.0)
6
6
  [![CI](https://img.shields.io/github/actions/workflow/status/ExaDev/agent-comms/ci.yml?branch=main)](https://github.com/ExaDev/agent-comms/actions)
7
7
 
8
8
  Cross-harness communication mesh for LLM agents: rooms, DMs, presence, and visibility over TCP with zero filesystem dependencies.
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Plain action functions -- one per browser-facing action, extracted from server.ts's executeAction switch so both the legacy /api/action REST dispatcher and the new oRPC router call the same implementation instead of two copies drifting apart.
3
+ *
4
+ * Each function preserves executeAction's exact prior validation behaviour (empty string treated the same as missing) even though the oRPC contract's own Zod schemas already enforce presence and type -- the contract validates shape, these functions still validate the same business rules the REST path has always enforced.
5
+ */
6
+ import type { PushManager } from "../../../core/push-manager.js";
7
+ import type { ChatController } from "../controller.js";
8
+ import type { ActionResult } from "./contract.js";
9
+ export declare function sendAction(controller: ChatController, input: Readonly<{
10
+ target: string;
11
+ content: string;
12
+ }>): Promise<ActionResult>;
13
+ export declare function dmAction(controller: ChatController, input: Readonly<{
14
+ target: string;
15
+ content: string;
16
+ }>): Promise<ActionResult>;
17
+ export declare function joinRoomAction(controller: ChatController, input: Readonly<{
18
+ room: string;
19
+ }>): Promise<ActionResult>;
20
+ export declare function leaveRoomAction(controller: ChatController, input: Readonly<{
21
+ room?: string | undefined;
22
+ }>): Promise<ActionResult>;
23
+ export declare function createRoomAction(controller: ChatController, input: Readonly<{
24
+ name: string;
25
+ type: "public" | "private" | "secret";
26
+ description?: string | undefined;
27
+ }>): Promise<ActionResult>;
28
+ export declare function listRoomsAction(controller: ChatController): Promise<ActionResult>;
29
+ export declare function listAgentsAction(controller: ChatController): Promise<ActionResult>;
30
+ export declare function readRoomAction(controller: ChatController, input: Readonly<{
31
+ room?: string | undefined;
32
+ }>): Promise<ActionResult>;
33
+ export declare function destroyRoomAction(controller: ChatController, input: Readonly<{
34
+ room: string;
35
+ }>): Promise<ActionResult>;
36
+ export declare function inviteAction(controller: ChatController, input: Readonly<{
37
+ room: string;
38
+ agent: string;
39
+ }>): Promise<ActionResult>;
40
+ export declare function declineInviteAction(controller: ChatController, input: Readonly<{
41
+ room: string;
42
+ reason: string;
43
+ }>): Promise<ActionResult>;
44
+ export declare function kickAction(controller: ChatController, input: Readonly<{
45
+ room: string;
46
+ agent: string;
47
+ }>): Promise<ActionResult>;
48
+ export declare function renameAgentAction(controller: ChatController, input: Readonly<{
49
+ agent: string;
50
+ name: string;
51
+ }>): Promise<ActionResult>;
52
+ export declare function pushSubscribeAction(controller: ChatController, pushManager: PushManager | undefined, input: Readonly<{
53
+ subscription: unknown;
54
+ agentId?: string | undefined;
55
+ }>): ActionResult;
56
+ export declare function pushUnsubscribeAction(controller: ChatController, pushManager: PushManager | undefined, input: Readonly<{
57
+ agentId?: string | undefined;
58
+ }>): ActionResult;
59
+ //# sourceMappingURL=actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../../../src/bridges/user/web/actions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Plain action functions -- one per browser-facing action, extracted from server.ts's executeAction switch so both the legacy /api/action REST dispatcher and the new oRPC router call the same implementation instead of two copies drifting apart.
3
+ *
4
+ * Each function preserves executeAction's exact prior validation behaviour (empty string treated the same as missing) even though the oRPC contract's own Zod schemas already enforce presence and type -- the contract validates shape, these functions still validate the same business rules the REST path has always enforced.
5
+ */
6
+ export async function sendAction(controller, input) {
7
+ if (input.target === "" || input.content === "") {
8
+ return { content: "Missing target or content", isError: true };
9
+ }
10
+ return controller.send(input.target, input.content);
11
+ }
12
+ export async function dmAction(controller, input) {
13
+ if (input.target === "" || input.content === "") {
14
+ return { content: "Missing target or content", isError: true };
15
+ }
16
+ return controller.dm(input.target, input.content);
17
+ }
18
+ export async function joinRoomAction(controller, input) {
19
+ if (input.room === "")
20
+ return { content: "Missing room", isError: true };
21
+ const result = await controller.switchRoom(input.room);
22
+ if (!result.isError) {
23
+ const msgs = await controller.readRoom();
24
+ return { content: `${result.content}\n${msgs.content}`, isError: false };
25
+ }
26
+ return result;
27
+ }
28
+ export async function leaveRoomAction(controller, input) {
29
+ return controller.leaveRoom(input.room);
30
+ }
31
+ export async function createRoomAction(controller, input) {
32
+ if (input.name === "")
33
+ return { content: "Missing name", isError: true };
34
+ return controller.createRoom(input.name, input.type, input.description ?? "");
35
+ }
36
+ export async function listRoomsAction(controller) {
37
+ return controller.listRooms();
38
+ }
39
+ export async function listAgentsAction(controller) {
40
+ return controller.listAgents();
41
+ }
42
+ export async function readRoomAction(controller, input) {
43
+ return controller.readRoom(input.room);
44
+ }
45
+ export async function destroyRoomAction(controller, input) {
46
+ if (input.room === "")
47
+ return { content: "Missing room", isError: true };
48
+ return controller.destroyRoom(input.room);
49
+ }
50
+ export async function inviteAction(controller, input) {
51
+ if (input.room === "" || input.agent === "") {
52
+ return { content: "Missing room or agent", isError: true };
53
+ }
54
+ return controller.invite(input.room, input.agent);
55
+ }
56
+ export async function declineInviteAction(controller, input) {
57
+ if (input.room === "" || input.reason === "") {
58
+ return { content: "Missing room or reason", isError: true };
59
+ }
60
+ return controller.declineInvite(input.room, input.reason);
61
+ }
62
+ export async function kickAction(controller, input) {
63
+ if (input.room === "" || input.agent === "") {
64
+ return { content: "Missing room or agent", isError: true };
65
+ }
66
+ return controller.kick(input.room, input.agent);
67
+ }
68
+ export async function renameAgentAction(controller, input) {
69
+ if (input.agent === "" || input.name === "") {
70
+ return { content: "Missing agent or name", isError: true };
71
+ }
72
+ return controller.renameAgent(input.agent, input.name);
73
+ }
74
+ function isPushSubscription(value) {
75
+ if (typeof value !== "object" || value === null)
76
+ return false;
77
+ if (!("endpoint" in value) || typeof value.endpoint !== "string")
78
+ return false;
79
+ if (!("keys" in value))
80
+ return false;
81
+ const keys = value.keys;
82
+ if (typeof keys !== "object" || keys === null)
83
+ return false;
84
+ if (!("p256dh" in keys) || typeof keys.p256dh !== "string")
85
+ return false;
86
+ if (!("auth" in keys) || typeof keys.auth !== "string")
87
+ return false;
88
+ return true;
89
+ }
90
+ export function pushSubscribeAction(controller, pushManager, input) {
91
+ if (!pushManager) {
92
+ return { content: "Push notifications unavailable", isError: true };
93
+ }
94
+ if (!isPushSubscription(input.subscription)) {
95
+ return { content: "Invalid push subscription", isError: true };
96
+ }
97
+ const agentId = input.agentId ?? controller.agentId;
98
+ pushManager.addSubscription(agentId, input.subscription);
99
+ return { content: "Push subscription registered", isError: false };
100
+ }
101
+ export function pushUnsubscribeAction(controller, pushManager, input) {
102
+ if (!pushManager) {
103
+ return { content: "Push notifications unavailable", isError: true };
104
+ }
105
+ const agentId = input.agentId ?? controller.agentId;
106
+ pushManager.removeSubscription(agentId);
107
+ return { content: "Push subscription removed", isError: false };
108
+ }
109
+ //# sourceMappingURL=actions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.js","sourceRoot":"","sources":["../../../../src/bridges/user/web/actions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * In-memory, resumable event publisher for the web UI's subscribeEvents stream.
3
+ *
4
+ * oRPC v2 beta (`\@orpc/server`, `\@orpc/client`, `\@orpc/contract` at 2.0.0-beta.35 -- confirmed against the actual published tarballs, not just docs) ships no MemoryPublisher/EventPublisher class. This is a hand-written equivalent built on the primitives that do exist: a plain async generator (satisfies AsyncIteratorObject on its own) and withEventMeta (from `\@standard-server/core`, re-exported by `\@orpc/server`) to tag each published event with a monotonic id oRPC's own RetryLinkPlugin already knows how to read back as lastEventId on reconnect.
5
+ *
6
+ * One instance per WebServerHandle -- not a module-level singleton -- so multiple concurrent web server instances (multiple bridges each starting their own web UI) never share replay buffers.
7
+ */
8
+ import type { MeshEvent } from "./contract.js";
9
+ export interface MeshEventPublisherOptions {
10
+ /** How long a published event stays available for replay by a resuming subscriber. */
11
+ retentionMs?: number;
12
+ }
13
+ export interface MeshEventSubscribeOptions {
14
+ signal?: AbortSignal;
15
+ lastEventId?: string;
16
+ }
17
+ export declare class MeshEventPublisher {
18
+ private seq;
19
+ private readonly buffer;
20
+ private readonly listeners;
21
+ private readonly retentionMs;
22
+ constructor(options?: Readonly<MeshEventPublisherOptions>);
23
+ publish(event: MeshEvent): void;
24
+ private prune;
25
+ /**
26
+ * Replays buffered events after `lastEventId` (or every buffered event, if a resuming subscriber's `lastEventId` has already aged out of the retention window), then yields new events as they're published until `signal` aborts.
27
+ */
28
+ subscribe(options?: Readonly<MeshEventSubscribeOptions>): AsyncGenerator<MeshEvent, void, void>;
29
+ }
30
+ //# sourceMappingURL=event-publisher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-publisher.d.ts","sourceRoot":"","sources":["../../../../src/bridges/user/web/event-publisher.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAO/C,MAAM,WAAW,yBAAyB;IACxC,sFAAsF;IACtF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAUD,MAAM,WAAW,yBAAyB;IACxC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyC;IACnE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;gBAEzB,OAAO,GAAE,QAAQ,CAAC,yBAAyB,CAAM;IAI7D,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAQ/B,OAAO,CAAC,KAAK;IAUb;;OAEG;IACI,SAAS,CACd,OAAO,GAAE,QAAQ,CAAC,yBAAyB,CAAM,GAChD,cAAc,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC;CA8CzC"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * In-memory, resumable event publisher for the web UI's subscribeEvents stream.
3
+ *
4
+ * oRPC v2 beta (`\@orpc/server`, `\@orpc/client`, `\@orpc/contract` at 2.0.0-beta.35 -- confirmed against the actual published tarballs, not just docs) ships no MemoryPublisher/EventPublisher class. This is a hand-written equivalent built on the primitives that do exist: a plain async generator (satisfies AsyncIteratorObject on its own) and withEventMeta (from `\@standard-server/core`, re-exported by `\@orpc/server`) to tag each published event with a monotonic id oRPC's own RetryLinkPlugin already knows how to read back as lastEventId on reconnect.
5
+ *
6
+ * One instance per WebServerHandle -- not a module-level singleton -- so multiple concurrent web server instances (multiple bridges each starting their own web UI) never share replay buffers.
7
+ */
8
+ import { withEventMeta } from "@orpc/server";
9
+ /** A plain function call is opaque to TS's control-flow narrowing, unlike a direct `signal?.aborted` comparison -- narrowing that across an `await` (the abort can genuinely flip mid-wait) produces a false "these types have no overlap" error at the re-check below the await. */
10
+ function isAborted(signal) {
11
+ return signal?.aborted === true;
12
+ }
13
+ const DEFAULT_RETENTION_MS = 60_000;
14
+ export class MeshEventPublisher {
15
+ seq = 0;
16
+ buffer = [];
17
+ listeners = new Set();
18
+ retentionMs;
19
+ constructor(options = {}) {
20
+ this.retentionMs = options.retentionMs ?? DEFAULT_RETENTION_MS;
21
+ }
22
+ publish(event) {
23
+ this.prune();
24
+ const id = String(++this.seq);
25
+ const tagged = withEventMeta(event, { id });
26
+ this.buffer.push({ id, event: tagged, publishedAt: Date.now() });
27
+ for (const listener of this.listeners)
28
+ listener(tagged);
29
+ }
30
+ prune() {
31
+ const cutoff = Date.now() - this.retentionMs;
32
+ while (this.buffer.length > 0 &&
33
+ (this.buffer[0]?.publishedAt ?? Infinity) < cutoff) {
34
+ this.buffer.shift();
35
+ }
36
+ }
37
+ /**
38
+ * Replays buffered events after `lastEventId` (or every buffered event, if a resuming subscriber's `lastEventId` has already aged out of the retention window), then yields new events as they're published until `signal` aborts.
39
+ */
40
+ async *subscribe(options = {}) {
41
+ const { signal, lastEventId } = options;
42
+ this.prune();
43
+ if (lastEventId !== undefined) {
44
+ const startIndex = this.buffer.findIndex((b) => b.id === lastEventId);
45
+ const replay = startIndex === -1 ? this.buffer : this.buffer.slice(startIndex + 1);
46
+ for (const buffered of replay) {
47
+ if (isAborted(signal))
48
+ return;
49
+ yield buffered.event;
50
+ }
51
+ }
52
+ const queue = [];
53
+ let wake;
54
+ const listener = (event) => {
55
+ queue.push(event);
56
+ wake?.();
57
+ };
58
+ this.listeners.add(listener);
59
+ try {
60
+ for (;;) {
61
+ if (isAborted(signal))
62
+ return;
63
+ if (queue.length === 0) {
64
+ await new Promise((resolve) => {
65
+ wake = resolve;
66
+ signal?.addEventListener("abort", () => {
67
+ resolve();
68
+ }, { once: true });
69
+ });
70
+ wake = undefined;
71
+ if (isAborted(signal))
72
+ return;
73
+ }
74
+ const next = queue.shift();
75
+ if (next !== undefined)
76
+ yield next;
77
+ }
78
+ }
79
+ finally {
80
+ this.listeners.delete(listener);
81
+ }
82
+ }
83
+ }
84
+ //# sourceMappingURL=event-publisher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-publisher.js","sourceRoot":"","sources":["../../../../src/bridges/user/web/event-publisher.ts"],"names":[],"mappings":"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"}