agent-comms 3.2.0 → 3.4.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 (39) 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/connection-approval.d.ts +1 -1
  5. package/dist/core/connection-approval.d.ts.map +1 -1
  6. package/dist/core/connection-approval.js +1 -1
  7. package/dist/core/connection-approval.js.map +1 -1
  8. package/dist/core/hub-session.d.ts +40 -0
  9. package/dist/core/hub-session.d.ts.map +1 -0
  10. package/dist/core/hub-session.js +106 -0
  11. package/dist/core/hub-session.js.map +1 -0
  12. package/dist/core/tool.d.ts.map +1 -1
  13. package/dist/core/tool.js +4 -1
  14. package/dist/core/tool.js.map +1 -1
  15. package/dist/core/wire-mesh-transport.d.ts +2 -0
  16. package/dist/core/wire-mesh-transport.d.ts.map +1 -1
  17. package/dist/core/wire-mesh-transport.js +38 -5
  18. package/dist/core/wire-mesh-transport.js.map +1 -1
  19. package/dist/core/ws-dial.d.ts +3 -0
  20. package/dist/core/ws-dial.d.ts.map +1 -0
  21. package/dist/core/ws-dial.js +122 -0
  22. package/dist/core/ws-dial.js.map +1 -0
  23. package/dist/test/hub-helpers.d.ts +3 -0
  24. package/dist/test/hub-helpers.d.ts.map +1 -0
  25. package/dist/test/hub-helpers.js +6 -0
  26. package/dist/test/hub-helpers.js.map +1 -0
  27. package/dist/test/hub-mode-session.integration.test.d.ts +2 -0
  28. package/dist/test/hub-mode-session.integration.test.d.ts.map +1 -0
  29. package/dist/test/hub-mode-session.integration.test.js +188 -0
  30. package/dist/test/hub-mode-session.integration.test.js.map +1 -0
  31. package/dist/test/ws-dial.test.d.ts +2 -0
  32. package/dist/test/ws-dial.test.d.ts.map +1 -0
  33. package/dist/test/ws-dial.test.js +84 -0
  34. package/dist/test/ws-dial.test.js.map +1 -0
  35. package/dist/test/wss-remote-connect.integration.test.d.ts +2 -0
  36. package/dist/test/wss-remote-connect.integration.test.d.ts.map +1 -0
  37. package/dist/test/wss-remote-connect.integration.test.js +106 -0
  38. package/dist/test/wss-remote-connect.integration.test.js.map +1 -0
  39. package/package.json +1 -1
@@ -0,0 +1,106 @@
1
+ // Integration: connectToRemote against a ws:// URL, through a minimal in-test fake hub speaking the real protocol (handshake reply, connect_request answered with manage-ok) -- proving the URL branch drives the identical session + connect_request flow the TLS branch uses, without standing up a TLS stack or a deployed hub.
2
+ import { createServer } from "node:http";
3
+ import { WebSocketServer } from "ws";
4
+ import { afterEach, describe, expect, it } from "vitest";
5
+ import { cdeDecodeOptions, cdeEncodeOptions, decode, encode } from "cbor2";
6
+ import { generateIdentity } from "../core/identity.js";
7
+ import { WireMeshTransport } from "../core/wire-mesh-transport.js";
8
+ const SHUTDOWN_GRACE_MS = 250;
9
+ const GARBAGE_PORT = 0; // meaningless in URL form -- exactly what the branch should tolerate
10
+ function inertEvents() {
11
+ return {
12
+ onMessage: () => undefined,
13
+ onPeerConnected: () => undefined,
14
+ onPeerDisconnected: () => undefined,
15
+ onIntroduction: () => undefined,
16
+ onConnectionRequest: () => undefined,
17
+ onPeerList: () => undefined,
18
+ onPeerJoined: () => undefined,
19
+ onBecomeCoordinator: () => undefined,
20
+ onRevocationAnnounce: () => undefined,
21
+ onPresenceAdvert: () => undefined,
22
+ };
23
+ }
24
+ /** The minimal fake hub: replies to a handshake with a compatible one, answers every manage-request with manage-ok. Records every frame for assertions. */
25
+ async function fakeHub() {
26
+ const received = [];
27
+ const http = createServer();
28
+ const wss = new WebSocketServer({ server: http });
29
+ wss.on("connection", (socket) => {
30
+ socket.on("message", (data) => {
31
+ const decodedFrame = decode(new Uint8Array(data), cdeDecodeOptions);
32
+ const frame = decodedFrame;
33
+ received.push(frame);
34
+ if (frame.type === "handshake") {
35
+ const answer = {
36
+ type: "handshake",
37
+ version: frame.version,
38
+ domains: frame.domains,
39
+ };
40
+ socket.send(new Uint8Array(encode(answer, cdeEncodeOptions)));
41
+ return;
42
+ }
43
+ if (frame.type === "manage-request") {
44
+ const response = {
45
+ type: "manage-response",
46
+ "request-id": frame["request-id"],
47
+ outcome: { result: "ok" },
48
+ };
49
+ socket.send(new Uint8Array(encode(response, cdeEncodeOptions)));
50
+ }
51
+ // Gossip and everything else: tolerated, unanswered -- the hub's own forwarding is not this test's subject.
52
+ });
53
+ });
54
+ await new Promise((resolve) => {
55
+ http.listen(0, "127.0.0.1", () => {
56
+ resolve();
57
+ });
58
+ });
59
+ const address = http.address();
60
+ if (address === null || typeof address === "string") {
61
+ throw new Error("expected a TCP listen address");
62
+ }
63
+ return {
64
+ url: `ws://127.0.0.1:${String(address.port)}/`,
65
+ received,
66
+ close: async () => new Promise((resolve) => {
67
+ // wss.close() alone waits for connected clients; terminate them first so shutdown cannot deadlock on the very connection under test.
68
+ for (const client of wss.clients) {
69
+ client.terminate();
70
+ }
71
+ wss.close();
72
+ http.close(() => {
73
+ resolve();
74
+ });
75
+ setTimeout(resolve, SHUTDOWN_GRACE_MS);
76
+ }),
77
+ };
78
+ }
79
+ const cleanups = [];
80
+ afterEach(async () => {
81
+ for (const close of cleanups.splice(0)) {
82
+ await close();
83
+ }
84
+ });
85
+ describe("connectToRemote with a ws:// URL", () => {
86
+ it("dials the hub, handshakes, and sends connect_request through the same flow as TLS", async () => {
87
+ const hub = await fakeHub();
88
+ cleanups.push(hub.close);
89
+ const identity = generateIdentity();
90
+ const transport = new WireMeshTransport(inertEvents(), identity);
91
+ await transport.connectToRemote(hub.url, GARBAGE_PORT, "peer-id", 0, "test-agent", "");
92
+ // The fake hub saw the full flow the TLS branch also drives: this side's handshake, then the connect_request manage-request.
93
+ const sawHandshake = hub.received.some((f) => f.type === "handshake");
94
+ const connectRequest = hub.received.find((f) => f.type === "manage-request");
95
+ expect(sawHandshake).toBe(true);
96
+ expect(connectRequest).toBeDefined();
97
+ await transport.shutdown();
98
+ });
99
+ it("rejects a non-ws/wss URL host outright rather than dialling garbage", async () => {
100
+ const identity = generateIdentity();
101
+ const transport = new WireMeshTransport(inertEvents(), identity);
102
+ await expect(transport.connectToRemote("ftp://example.com/", GARBAGE_PORT, "peer-id", 0, "test-agent", "")).rejects.toThrow(/hostname or a ws:\/\/ \/ wss:\/\//);
103
+ await transport.shutdown();
104
+ });
105
+ });
106
+ //# sourceMappingURL=wss-remote-connect.integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wss-remote-connect.integration.test.js","sourceRoot":"","sources":["../../src/test/wss-remote-connect.integration.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-comms",
3
- "version": "3.2.0",
3
+ "version": "3.4.0",
4
4
  "description": "Cross-harness communication mesh for LLM agents — rooms, DMs, presence, and real-time push delivery over TCP",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c",