agent-comms 1.14.0 → 1.15.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.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +1 -1
- package/dist/bridges/claude-code/channel.d.ts.map +1 -1
- package/dist/bridges/claude-code/channel.js +6 -1
- package/dist/bridges/claude-code/channel.js.map +1 -1
- package/dist/bridges/codex/tool.d.ts.map +1 -1
- package/dist/bridges/codex/tool.js +6 -1
- package/dist/bridges/codex/tool.js.map +1 -1
- package/dist/bridges/mcp/index.d.ts.map +1 -1
- package/dist/bridges/mcp/index.js +6 -1
- package/dist/bridges/mcp/index.js.map +1 -1
- package/dist/bridges/opencode/plugin.d.ts.map +1 -1
- package/dist/bridges/opencode/plugin.js +5 -0
- package/dist/bridges/opencode/plugin.js.map +1 -1
- package/dist/bridges/pi/index.d.ts.map +1 -1
- package/dist/bridges/pi/index.js +39 -17
- package/dist/bridges/pi/index.js.map +1 -1
- package/dist/bridges/user/controller.d.ts +9 -1
- package/dist/bridges/user/controller.d.ts.map +1 -1
- package/dist/bridges/user/controller.js +25 -1
- package/dist/bridges/user/controller.js.map +1 -1
- package/dist/bridges/user/tui.js +2 -0
- package/dist/bridges/user/tui.js.map +1 -1
- package/dist/bridges/user/web/build.d.ts +2 -0
- package/dist/bridges/user/web/build.d.ts.map +1 -1
- package/dist/bridges/user/web/build.js +44 -0
- package/dist/bridges/user/web/build.js.map +1 -1
- package/dist/bridges/user/web/frontend/components/App.d.ts +5 -0
- package/dist/bridges/user/web/frontend/components/App.d.ts.map +1 -1
- package/dist/bridges/user/web/frontend/components/App.js +1 -1
- package/dist/bridges/user/web/frontend/components/App.js.map +1 -1
- package/dist/bridges/user/web/frontend/components/ProjectTree.js +6 -3
- package/dist/bridges/user/web/frontend/components/ProjectTree.js.map +1 -1
- package/dist/bridges/user/web/frontend/components/RelayPanel.d.ts +15 -0
- package/dist/bridges/user/web/frontend/components/RelayPanel.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/components/RelayPanel.js +46 -0
- package/dist/bridges/user/web/frontend/components/RelayPanel.js.map +1 -0
- package/dist/bridges/user/web/frontend/components/Sidebar.d.ts +7 -2
- package/dist/bridges/user/web/frontend/components/Sidebar.d.ts.map +1 -1
- package/dist/bridges/user/web/frontend/components/Sidebar.js +15 -9
- package/dist/bridges/user/web/frontend/components/Sidebar.js.map +1 -1
- package/dist/bridges/user/web/frontend/input.js +1 -1
- package/dist/bridges/user/web/frontend/input.js.map +1 -1
- package/dist/bridges/user/web/frontend/main.js +73 -5
- package/dist/bridges/user/web/frontend/main.js.map +1 -1
- package/dist/bridges/user/web/frontend/mesh-client.d.ts +43 -0
- package/dist/bridges/user/web/frontend/mesh-client.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/mesh-client.js +132 -0
- package/dist/bridges/user/web/frontend/mesh-client.js.map +1 -0
- package/dist/bridges/user/web/frontend/mesh-worker.d.ts +14 -0
- package/dist/bridges/user/web/frontend/mesh-worker.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/mesh-worker.js +274 -0
- package/dist/bridges/user/web/frontend/mesh-worker.js.map +1 -0
- package/dist/bridges/user/web/frontend/relay-client.d.ts +40 -0
- package/dist/bridges/user/web/frontend/relay-client.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/relay-client.js +97 -0
- package/dist/bridges/user/web/frontend/relay-client.js.map +1 -0
- package/dist/bridges/user/web/frontend/relay-worker.d.ts +15 -0
- package/dist/bridges/user/web/frontend/relay-worker.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/relay-worker.js +366 -0
- package/dist/bridges/user/web/frontend/relay-worker.js.map +1 -0
- package/dist/bridges/user/web/frontend/sw.d.ts +16 -0
- package/dist/bridges/user/web/frontend/sw.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/sw.js +145 -0
- package/dist/bridges/user/web/frontend/sw.js.map +1 -0
- package/dist/bridges/user/web/frontend/url-sync.d.ts +48 -0
- package/dist/bridges/user/web/frontend/url-sync.d.ts.map +1 -0
- package/dist/bridges/user/web/frontend/url-sync.js +74 -0
- package/dist/bridges/user/web/frontend/url-sync.js.map +1 -0
- package/dist/bridges/user/web/server.d.ts +10 -3
- package/dist/bridges/user/web/server.d.ts.map +1 -1
- package/dist/bridges/user/web/server.js +254 -12
- package/dist/bridges/user/web/server.js.map +1 -1
- package/dist/core/bridge.d.ts +28 -0
- package/dist/core/bridge.d.ts.map +1 -1
- package/dist/core/bridge.js +137 -0
- package/dist/core/bridge.js.map +1 -1
- package/dist/core/comms-store.d.ts +22 -1
- package/dist/core/comms-store.d.ts.map +1 -1
- package/dist/core/discovery-mdns.d.ts +33 -0
- package/dist/core/discovery-mdns.d.ts.map +1 -0
- package/dist/core/discovery-mdns.js +182 -0
- package/dist/core/discovery-mdns.js.map +1 -0
- package/dist/core/discovery-tailscale.d.ts +40 -0
- package/dist/core/discovery-tailscale.d.ts.map +1 -0
- package/dist/core/discovery-tailscale.js +158 -0
- package/dist/core/discovery-tailscale.js.map +1 -0
- package/dist/core/discovery.d.ts +82 -0
- package/dist/core/discovery.d.ts.map +1 -0
- package/dist/core/discovery.js +194 -0
- package/dist/core/discovery.js.map +1 -0
- package/dist/core/federation.d.ts +100 -0
- package/dist/core/federation.d.ts.map +1 -0
- package/dist/core/federation.js +411 -0
- package/dist/core/federation.js.map +1 -0
- package/dist/core/identity.d.ts +31 -0
- package/dist/core/identity.d.ts.map +1 -0
- package/dist/core/identity.js +251 -0
- package/dist/core/identity.js.map +1 -0
- package/dist/core/index.d.ts +11 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +6 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/mesh-store.d.ts +72 -26
- package/dist/core/mesh-store.d.ts.map +1 -1
- package/dist/core/mesh-store.js +467 -352
- package/dist/core/mesh-store.js.map +1 -1
- package/dist/core/push-manager.d.ts +41 -0
- package/dist/core/push-manager.d.ts.map +1 -0
- package/dist/core/push-manager.js +60 -0
- package/dist/core/push-manager.js.map +1 -0
- package/dist/core/store.d.ts +21 -1
- package/dist/core/store.d.ts.map +1 -1
- package/dist/core/store.js +44 -0
- package/dist/core/store.js.map +1 -1
- package/dist/core/tcp-transport.d.ts +77 -0
- package/dist/core/tcp-transport.d.ts.map +1 -0
- package/dist/core/tcp-transport.js +596 -0
- package/dist/core/tcp-transport.js.map +1 -0
- package/dist/core/test/identity.unit.test.d.ts +5 -0
- package/dist/core/test/identity.unit.test.d.ts.map +1 -0
- package/dist/core/test/identity.unit.test.js +70 -0
- package/dist/core/test/identity.unit.test.js.map +1 -0
- package/dist/core/tls-transport.d.ts +69 -0
- package/dist/core/tls-transport.d.ts.map +1 -0
- package/dist/core/tls-transport.js +602 -0
- package/dist/core/tls-transport.js.map +1 -0
- package/dist/core/tool.d.ts +23 -2
- package/dist/core/tool.d.ts.map +1 -1
- package/dist/core/tool.js +269 -1
- package/dist/core/tool.js.map +1 -1
- package/dist/core/transport.d.ts +166 -0
- package/dist/core/transport.d.ts.map +1 -0
- package/dist/core/transport.js +20 -0
- package/dist/core/transport.js.map +1 -0
- package/dist/core/types.d.ts +136 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +71 -0
- package/dist/core/types.js.map +1 -1
- package/dist/core/vapid.d.ts +22 -0
- package/dist/core/vapid.d.ts.map +1 -0
- package/dist/core/vapid.js +50 -0
- package/dist/core/vapid.js.map +1 -0
- package/dist/core/web-push.d.ts +37 -0
- package/dist/core/web-push.d.ts.map +1 -0
- package/dist/core/web-push.js +198 -0
- package/dist/core/web-push.js.map +1 -0
- package/dist/core/wire-protocol.d.ts +131 -0
- package/dist/core/wire-protocol.d.ts.map +1 -0
- package/dist/core/wire-protocol.js +54 -0
- package/dist/core/wire-protocol.js.map +1 -0
- package/dist/core/ws-transport.d.ts +71 -0
- package/dist/core/ws-transport.d.ts.map +1 -0
- package/dist/core/ws-transport.js +560 -0
- package/dist/core/ws-transport.js.map +1 -0
- package/dist/test/approval.integration.test.d.ts +9 -0
- package/dist/test/approval.integration.test.d.ts.map +1 -0
- package/dist/test/approval.integration.test.js +361 -0
- package/dist/test/approval.integration.test.js.map +1 -0
- package/dist/test/delivery-receipt.helper.d.ts +16 -0
- package/dist/test/delivery-receipt.helper.d.ts.map +1 -0
- package/dist/test/delivery-receipt.helper.js +409 -0
- package/dist/test/delivery-receipt.helper.js.map +1 -0
- package/dist/test/delivery-receipt.runner.d.ts +13 -0
- package/dist/test/delivery-receipt.runner.d.ts.map +1 -0
- package/dist/test/delivery-receipt.runner.js +51 -0
- package/dist/test/delivery-receipt.runner.js.map +1 -0
- package/dist/test/federation.integration.test.d.ts +15 -0
- package/dist/test/federation.integration.test.d.ts.map +1 -0
- package/dist/test/federation.integration.test.js +218 -0
- package/dist/test/federation.integration.test.js.map +1 -0
- package/dist/test/listener-policy.integration.test.d.ts +9 -0
- package/dist/test/listener-policy.integration.test.d.ts.map +1 -0
- package/dist/test/listener-policy.integration.test.js +239 -0
- package/dist/test/listener-policy.integration.test.js.map +1 -0
- package/dist/test/tls-transport.integration.test.d.ts +8 -0
- package/dist/test/tls-transport.integration.test.d.ts.map +1 -0
- package/dist/test/tls-transport.integration.test.js +158 -0
- package/dist/test/tls-transport.integration.test.js.map +1 -0
- package/dist/test/visibility.integration.test.d.ts +12 -0
- package/dist/test/visibility.integration.test.d.ts.map +1 -0
- package/dist/test/visibility.integration.test.js +181 -0
- package/dist/test/visibility.integration.test.js.map +1 -0
- package/package.json +4 -1
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tailscale discovery backend — probes tailnet peers for mesh coordinators.
|
|
3
|
+
*
|
|
4
|
+
* Queries the Tailscale local API to get tailnet peers, then probes each
|
|
5
|
+
* peer's port 19876 with a TCP connection attempt (timeout 500ms).
|
|
6
|
+
* If reachable, the peer is added as a discovered mesh.
|
|
7
|
+
*
|
|
8
|
+
* No broadcasting is needed — Tailscale already knows all peers.
|
|
9
|
+
* startAdvertising() is a no-op since the coordinator already listens
|
|
10
|
+
* on the Tailscale IP.
|
|
11
|
+
*/
|
|
12
|
+
import * as http from "node:http";
|
|
13
|
+
import * as net from "node:net";
|
|
14
|
+
import { execFile } from "node:child_process";
|
|
15
|
+
import { promisify } from "node:util";
|
|
16
|
+
const execFileAsync = promisify(execFile);
|
|
17
|
+
const TCP_PROBE_TIMEOUT_MS = 500;
|
|
18
|
+
const DEFAULT_DISCOVER_TIMEOUT_MS = 5_000;
|
|
19
|
+
const COORDINATOR_PORT = 19876;
|
|
20
|
+
const TAILSCALE_API_PORT = 49156;
|
|
21
|
+
function parseTailscaleStatus(raw) {
|
|
22
|
+
if (typeof raw !== "object" || raw === null) {
|
|
23
|
+
throw new Error("Invalid TailscaleStatus: expected object");
|
|
24
|
+
}
|
|
25
|
+
return raw;
|
|
26
|
+
}
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// Tailscale backend
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
export class TailscaleDiscoveryBackend {
|
|
31
|
+
name = "tailscale";
|
|
32
|
+
/** No-op — the coordinator already listens on the Tailscale IP. */
|
|
33
|
+
async startAdvertising(opts) {
|
|
34
|
+
return `tailscale-${String(opts.port)}`;
|
|
35
|
+
}
|
|
36
|
+
/** No-op — nothing to stop. */
|
|
37
|
+
async stopAdvertising(id) {
|
|
38
|
+
void id;
|
|
39
|
+
}
|
|
40
|
+
/** Stop discovery — no-op since Tailscale has no persistent state to clean up. */
|
|
41
|
+
async stop() {
|
|
42
|
+
// Tailscale discovery is stateless — each discover() call probes peers fresh.
|
|
43
|
+
// No persistent connections or timers to tear down.
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Discover meshes on the tailnet by probing peers.
|
|
47
|
+
* Returns peers that respond to a TCP connection on port 19876.
|
|
48
|
+
*/
|
|
49
|
+
async discover(timeout) {
|
|
50
|
+
void timeout;
|
|
51
|
+
const peers = await this.getPeers();
|
|
52
|
+
if (peers.length === 0)
|
|
53
|
+
return [];
|
|
54
|
+
const probes = peers.map((peer) => this.probePeer(peer));
|
|
55
|
+
const results = await Promise.allSettled(probes);
|
|
56
|
+
const discovered = [];
|
|
57
|
+
for (const result of results) {
|
|
58
|
+
if (result.status === "fulfilled" && result.value !== undefined) {
|
|
59
|
+
discovered.push(result.value);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return discovered;
|
|
63
|
+
}
|
|
64
|
+
// -----------------------------------------------------------------------
|
|
65
|
+
// Internals
|
|
66
|
+
// -----------------------------------------------------------------------
|
|
67
|
+
/**
|
|
68
|
+
* Get tailnet peers via `tailscale status --json`.
|
|
69
|
+
* Falls back to the local API at localhost:49156 if the CLI is unavailable.
|
|
70
|
+
*/
|
|
71
|
+
async getPeers() {
|
|
72
|
+
const status = await this.fetchTailscaleStatus();
|
|
73
|
+
if (!status?.Peer)
|
|
74
|
+
return [];
|
|
75
|
+
const peers = [];
|
|
76
|
+
for (const [, peer] of Object.entries(status.Peer)) {
|
|
77
|
+
if (!peer.Online)
|
|
78
|
+
continue;
|
|
79
|
+
const ips = peer.TailscaleIPs;
|
|
80
|
+
if (!ips || ips.length === 0)
|
|
81
|
+
continue;
|
|
82
|
+
// Use the first IPv4 address
|
|
83
|
+
const ip = ips.find((addr) => addr.includes(".")) ?? ips[0];
|
|
84
|
+
if (!ip)
|
|
85
|
+
continue;
|
|
86
|
+
const hostname = peer.HostName ?? peer.DNSName?.replace(/\.tailnet.*$/, "") ?? ip;
|
|
87
|
+
peers.push({ ip, hostname });
|
|
88
|
+
}
|
|
89
|
+
return peers;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Fetch Tailscale status. Tries the CLI first, falls back to the local API.
|
|
93
|
+
*/
|
|
94
|
+
async fetchTailscaleStatus() {
|
|
95
|
+
// Try CLI first
|
|
96
|
+
try {
|
|
97
|
+
const { stdout } = await execFileAsync("tailscale", ["status", "--json"]);
|
|
98
|
+
return parseTailscaleStatus(JSON.parse(stdout));
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
// CLI not available — try the local API
|
|
102
|
+
}
|
|
103
|
+
// Fall back to local API
|
|
104
|
+
try {
|
|
105
|
+
return await this.fetchLocalApi();
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/** Query the Tailscale local API at localhost:49156. */
|
|
112
|
+
fetchLocalApi() {
|
|
113
|
+
return new Promise((resolve, reject) => {
|
|
114
|
+
const req = http.get(`http://localhost:${String(TAILSCALE_API_PORT)}/localapi/v0/status`, { timeout: DEFAULT_DISCOVER_TIMEOUT_MS }, (res) => {
|
|
115
|
+
const chunks = [];
|
|
116
|
+
res.on("data", (chunk) => chunks.push(chunk));
|
|
117
|
+
res.on("end", () => {
|
|
118
|
+
try {
|
|
119
|
+
resolve(parseTailscaleStatus(JSON.parse(Buffer.concat(chunks).toString())));
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
req.on("error", reject);
|
|
127
|
+
req.on("timeout", () => {
|
|
128
|
+
req.destroy();
|
|
129
|
+
reject(new Error("Tailscale local API timeout"));
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
/** Probe a single Tailscale peer for a listening mesh coordinator. */
|
|
134
|
+
probePeer(peer) {
|
|
135
|
+
return new Promise((resolve) => {
|
|
136
|
+
const socket = new net.Socket();
|
|
137
|
+
const timer = setTimeout(() => {
|
|
138
|
+
socket.destroy();
|
|
139
|
+
resolve(undefined);
|
|
140
|
+
}, TCP_PROBE_TIMEOUT_MS);
|
|
141
|
+
socket.connect(COORDINATOR_PORT, peer.ip, () => {
|
|
142
|
+
clearTimeout(timer);
|
|
143
|
+
socket.destroy();
|
|
144
|
+
resolve({
|
|
145
|
+
host: peer.ip,
|
|
146
|
+
port: COORDINATOR_PORT,
|
|
147
|
+
name: peer.hostname,
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
socket.on("error", () => {
|
|
151
|
+
clearTimeout(timer);
|
|
152
|
+
socket.destroy();
|
|
153
|
+
resolve(undefined);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=discovery-tailscale.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery-tailscale.js","sourceRoot":"","sources":["../../src/core/discovery-tailscale.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discovery — mesh discovery interface and manager.
|
|
3
|
+
*
|
|
4
|
+
* Defines the contract for discovery backends (mDNS, Tailscale, etc.)
|
|
5
|
+
* and a manager that routes calls to the appropriate backend.
|
|
6
|
+
* Discovery is opt-in — no broadcasting unless the agent explicitly
|
|
7
|
+
* calls mesh_advertise.
|
|
8
|
+
*/
|
|
9
|
+
import type { MeshVisibility } from "./types.js";
|
|
10
|
+
export interface DiscoveredMesh {
|
|
11
|
+
/** Host address of the discovered mesh coordinator. */
|
|
12
|
+
host: string;
|
|
13
|
+
/** Port the coordinator is listening on. */
|
|
14
|
+
port: number;
|
|
15
|
+
/** Human-readable mesh name (from mDNS TXT record or Tailscale hostname). */
|
|
16
|
+
name: string;
|
|
17
|
+
/** Number of agents in the mesh (if available). */
|
|
18
|
+
agentCount?: number;
|
|
19
|
+
/** Connection policies available (if advertised). */
|
|
20
|
+
policies?: string[];
|
|
21
|
+
}
|
|
22
|
+
export interface AdvertiseOptions {
|
|
23
|
+
/** Service name for mDNS / identifier for the mesh. */
|
|
24
|
+
name: string;
|
|
25
|
+
/** Port to advertise. */
|
|
26
|
+
port: number;
|
|
27
|
+
/** Network adapter/address to broadcast on. */
|
|
28
|
+
adapter?: string;
|
|
29
|
+
/** What information to reveal in discovery responses. */
|
|
30
|
+
policy?: "full" | "name-only";
|
|
31
|
+
}
|
|
32
|
+
export interface DiscoveryBackend {
|
|
33
|
+
readonly name: string;
|
|
34
|
+
startAdvertising(opts: AdvertiseOptions): Promise<string>;
|
|
35
|
+
stopAdvertising(id: string): Promise<void>;
|
|
36
|
+
discover(timeout?: number): Promise<DiscoveredMesh[]>;
|
|
37
|
+
/** Stop all activity (timers, sockets) for this backend. */
|
|
38
|
+
stop(): Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
export declare class DiscoveryManager {
|
|
41
|
+
private backends;
|
|
42
|
+
private activeAdvertisements;
|
|
43
|
+
private meshVisibility;
|
|
44
|
+
private perAdapterVisibility;
|
|
45
|
+
/** Advertisements that were paused due to visibility changes. */
|
|
46
|
+
private pausedAdvertisements;
|
|
47
|
+
/** Register a discovery backend. */
|
|
48
|
+
registerBackend(backend: DiscoveryBackend): void;
|
|
49
|
+
/** Start advertising on a specific backend. Returns an advertisement ID. */
|
|
50
|
+
advertise(backendName: string, opts: AdvertiseOptions): Promise<string>;
|
|
51
|
+
/**
|
|
52
|
+
* Set mesh-wide visibility level.
|
|
53
|
+
*
|
|
54
|
+
* - `discoverable` — normal operation, all backends active.
|
|
55
|
+
* - `quiet` — stop advertising but backends remain available for discover().
|
|
56
|
+
* - `dark` — stop all discovery activity (advertising + backend sockets).
|
|
57
|
+
*
|
|
58
|
+
* If `adapter` is specified, the visibility applies only to that backend.
|
|
59
|
+
* Otherwise it applies to the global mesh visibility.
|
|
60
|
+
*/
|
|
61
|
+
setVisibility(level: MeshVisibility, adapter?: string): Promise<void>;
|
|
62
|
+
/** Get current mesh visibility level (global or per-adapter). */
|
|
63
|
+
getVisibility(adapter?: string): MeshVisibility;
|
|
64
|
+
private setAdapterVisibility;
|
|
65
|
+
private pauseAllAdvertisements;
|
|
66
|
+
private pauseAdvertisementsForBackend;
|
|
67
|
+
private stopAllBackends;
|
|
68
|
+
private resumeAllAdvertisements;
|
|
69
|
+
private resumeAdvertisementsForBackend;
|
|
70
|
+
/** Stop a previously started advertisement. */
|
|
71
|
+
stopAdvertising(id: string): Promise<void>;
|
|
72
|
+
/** Check whether an advertisement ID was paused (visibility change stopped it). */
|
|
73
|
+
isPaused(id: string): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Discover meshes using a specific backend (or all backends if no name given).
|
|
76
|
+
* Returns deduplicated results.
|
|
77
|
+
*
|
|
78
|
+
* Respects visibility: returns empty results for backends that are "dark".
|
|
79
|
+
*/
|
|
80
|
+
discover(backendName?: string, timeout?: number): Promise<DiscoveredMesh[]>;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/core/discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAMjD,MAAM,WAAW,cAAc;IAC7B,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAMD,MAAM,WAAW,gBAAgB;IAC/B,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;CAC/B;AAMD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1D,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IACtD,4DAA4D;IAC5D,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAMD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAuC;IACvD,OAAO,CAAC,oBAAoB,CAA6B;IACzD,OAAO,CAAC,cAAc,CAAkC;IACxD,OAAO,CAAC,oBAAoB,CAAqC;IACjE,iEAAiE;IACjE,OAAO,CAAC,oBAAoB,CAGxB;IAEJ,oCAAoC;IACpC,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAIhD,4EAA4E;IACtE,SAAS,CACb,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,MAAM,CAAC;IAYlB;;;;;;;;;OASG;IACG,aAAa,CAAC,KAAK,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB3E,iEAAiE;IACjE,aAAa,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,cAAc;YAOjC,oBAAoB;YAqBpB,sBAAsB;YAkBtB,6BAA6B;YAoB7B,eAAe;YAQf,uBAAuB;YAUvB,8BAA8B;IAU5C,+CAA+C;IACzC,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAShD,mFAAmF;IACnF,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAI7B;;;;;OAKG;IACG,QAAQ,CACZ,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,cAAc,EAAE,CAAC;CAgC7B"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discovery — mesh discovery interface and manager.
|
|
3
|
+
*
|
|
4
|
+
* Defines the contract for discovery backends (mDNS, Tailscale, etc.)
|
|
5
|
+
* and a manager that routes calls to the appropriate backend.
|
|
6
|
+
* Discovery is opt-in — no broadcasting unless the agent explicitly
|
|
7
|
+
* calls mesh_advertise.
|
|
8
|
+
*/
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Discovery manager
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
export class DiscoveryManager {
|
|
13
|
+
backends = new Map();
|
|
14
|
+
activeAdvertisements = new Map();
|
|
15
|
+
meshVisibility = "discoverable";
|
|
16
|
+
perAdapterVisibility = new Map();
|
|
17
|
+
/** Advertisements that were paused due to visibility changes. */
|
|
18
|
+
pausedAdvertisements = new Map();
|
|
19
|
+
/** Register a discovery backend. */
|
|
20
|
+
registerBackend(backend) {
|
|
21
|
+
this.backends.set(backend.name, backend);
|
|
22
|
+
}
|
|
23
|
+
/** Start advertising on a specific backend. Returns an advertisement ID. */
|
|
24
|
+
async advertise(backendName, opts) {
|
|
25
|
+
const backend = this.backends.get(backendName);
|
|
26
|
+
if (!backend) {
|
|
27
|
+
throw new Error(`Unknown discovery backend: "${backendName}". Available: ${[...this.backends.keys()].join(", ")}`);
|
|
28
|
+
}
|
|
29
|
+
const id = await backend.startAdvertising(opts);
|
|
30
|
+
this.activeAdvertisements.set(id, backendName);
|
|
31
|
+
return id;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Set mesh-wide visibility level.
|
|
35
|
+
*
|
|
36
|
+
* - `discoverable` — normal operation, all backends active.
|
|
37
|
+
* - `quiet` — stop advertising but backends remain available for discover().
|
|
38
|
+
* - `dark` — stop all discovery activity (advertising + backend sockets).
|
|
39
|
+
*
|
|
40
|
+
* If `adapter` is specified, the visibility applies only to that backend.
|
|
41
|
+
* Otherwise it applies to the global mesh visibility.
|
|
42
|
+
*/
|
|
43
|
+
async setVisibility(level, adapter) {
|
|
44
|
+
if (adapter !== undefined) {
|
|
45
|
+
await this.setAdapterVisibility(adapter, level);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const prev = this.meshVisibility;
|
|
49
|
+
this.meshVisibility = level;
|
|
50
|
+
if (prev === level)
|
|
51
|
+
return;
|
|
52
|
+
if (level === "quiet") {
|
|
53
|
+
// Pause all advertisements but keep backends running
|
|
54
|
+
await this.pauseAllAdvertisements();
|
|
55
|
+
}
|
|
56
|
+
else if (level === "dark") {
|
|
57
|
+
// Pause advertisements and stop backends entirely
|
|
58
|
+
await this.pauseAllAdvertisements();
|
|
59
|
+
await this.stopAllBackends();
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// discoverable — resume previously paused advertisements and restart backends
|
|
63
|
+
await this.resumeAllAdvertisements();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Get current mesh visibility level (global or per-adapter). */
|
|
67
|
+
getVisibility(adapter) {
|
|
68
|
+
if (adapter !== undefined) {
|
|
69
|
+
return this.perAdapterVisibility.get(adapter) ?? this.meshVisibility;
|
|
70
|
+
}
|
|
71
|
+
return this.meshVisibility;
|
|
72
|
+
}
|
|
73
|
+
async setAdapterVisibility(adapter, level) {
|
|
74
|
+
const prev = this.perAdapterVisibility.get(adapter) ?? this.meshVisibility;
|
|
75
|
+
this.perAdapterVisibility.set(adapter, level);
|
|
76
|
+
if (prev === level)
|
|
77
|
+
return;
|
|
78
|
+
if (level === "quiet" || level === "dark") {
|
|
79
|
+
// Pause advertisements for this specific backend
|
|
80
|
+
await this.pauseAdvertisementsForBackend(adapter);
|
|
81
|
+
if (level === "dark") {
|
|
82
|
+
const backend = this.backends.get(adapter);
|
|
83
|
+
if (backend)
|
|
84
|
+
await backend.stop();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
await this.resumeAdvertisementsForBackend(adapter);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async pauseAllAdvertisements() {
|
|
92
|
+
// Capture current ads before clearing
|
|
93
|
+
for (const [id, backendName] of this.activeAdvertisements) {
|
|
94
|
+
// We've lost the original opts — but we can just stop the ad
|
|
95
|
+
this.pausedAdvertisements.set(id, {
|
|
96
|
+
backendName,
|
|
97
|
+
opts: { name: "resumed", port: 0 },
|
|
98
|
+
});
|
|
99
|
+
const backend = this.backends.get(backendName);
|
|
100
|
+
if (backend) {
|
|
101
|
+
await backend.stopAdvertising(id).catch(() => {
|
|
102
|
+
/* intentionally empty — best-effort stop */
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
this.activeAdvertisements.clear();
|
|
107
|
+
}
|
|
108
|
+
async pauseAdvertisementsForBackend(backendName) {
|
|
109
|
+
for (const [id, bn] of this.activeAdvertisements) {
|
|
110
|
+
if (bn === backendName) {
|
|
111
|
+
this.pausedAdvertisements.set(id, {
|
|
112
|
+
backendName,
|
|
113
|
+
opts: { name: "resumed", port: 0 },
|
|
114
|
+
});
|
|
115
|
+
const backend = this.backends.get(backendName);
|
|
116
|
+
if (backend) {
|
|
117
|
+
await backend.stopAdvertising(id).catch(() => {
|
|
118
|
+
/* intentionally empty — best-effort stop */
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
this.activeAdvertisements.delete(id);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
async stopAllBackends() {
|
|
126
|
+
for (const backend of this.backends.values()) {
|
|
127
|
+
await backend.stop().catch(() => {
|
|
128
|
+
/* intentionally empty — best-effort stop */
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async resumeAllAdvertisements() {
|
|
133
|
+
// Restart backends first (they may have been stopped in "dark" mode)
|
|
134
|
+
// Note: backends reinitialise their sockets on next startAdvertising/discover call.
|
|
135
|
+
for (const [id] of this.pausedAdvertisements) {
|
|
136
|
+
this.pausedAdvertisements.delete(id);
|
|
137
|
+
// We can't fully resume without original opts — the caller must
|
|
138
|
+
// re-advertise. Mark as not paused so new advertise calls work.
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
async resumeAdvertisementsForBackend(backendName) {
|
|
142
|
+
for (const [id, entry] of this.pausedAdvertisements) {
|
|
143
|
+
if (entry.backendName === backendName) {
|
|
144
|
+
this.pausedAdvertisements.delete(id);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/** Stop a previously started advertisement. */
|
|
149
|
+
async stopAdvertising(id) {
|
|
150
|
+
const backendName = this.activeAdvertisements.get(id);
|
|
151
|
+
if (!backendName)
|
|
152
|
+
return;
|
|
153
|
+
const backend = this.backends.get(backendName);
|
|
154
|
+
if (!backend)
|
|
155
|
+
return;
|
|
156
|
+
await backend.stopAdvertising(id);
|
|
157
|
+
this.activeAdvertisements.delete(id);
|
|
158
|
+
}
|
|
159
|
+
/** Check whether an advertisement ID was paused (visibility change stopped it). */
|
|
160
|
+
isPaused(id) {
|
|
161
|
+
return this.pausedAdvertisements.has(id);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Discover meshes using a specific backend (or all backends if no name given).
|
|
165
|
+
* Returns deduplicated results.
|
|
166
|
+
*
|
|
167
|
+
* Respects visibility: returns empty results for backends that are "dark".
|
|
168
|
+
*/
|
|
169
|
+
async discover(backendName, timeout) {
|
|
170
|
+
const targets = backendName !== undefined
|
|
171
|
+
? [this.backends.get(backendName)].filter((b) => b !== undefined)
|
|
172
|
+
: [...this.backends.values()];
|
|
173
|
+
// Filter out backends that are dark (per-adapter or global)
|
|
174
|
+
const activeTargets = targets.filter((b) => {
|
|
175
|
+
const vis = this.getVisibility(b.name);
|
|
176
|
+
return vis !== "dark";
|
|
177
|
+
});
|
|
178
|
+
const results = await Promise.all(activeTargets.map((b) => b.discover(timeout)));
|
|
179
|
+
// Deduplicate by host+port
|
|
180
|
+
const seen = new Set();
|
|
181
|
+
const deduped = [];
|
|
182
|
+
for (const meshes of results) {
|
|
183
|
+
for (const mesh of meshes) {
|
|
184
|
+
const key = `${mesh.host}:${String(mesh.port)}`;
|
|
185
|
+
if (!seen.has(key)) {
|
|
186
|
+
seen.add(key);
|
|
187
|
+
deduped.push(mesh);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return deduped;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/core/discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAiDH,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E,MAAM,OAAO,gBAAgB;IACnB,QAAQ,GAAG,IAAI,GAAG,EAA4B,CAAC;IAC/C,oBAAoB,GAAG,IAAI,GAAG,EAAkB,CAAC;IACjD,cAAc,GAAmB,cAAc,CAAC;IAChD,oBAAoB,GAAG,IAAI,GAAG,EAA0B,CAAC;IACjE,iEAAiE;IACzD,oBAAoB,GAAG,IAAI,GAAG,EAGnC,CAAC;IAEJ,oCAAoC;IACpC,eAAe,CAAC,OAAyB;QACvC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED,4EAA4E;IAC5E,KAAK,CAAC,SAAS,CACb,WAAmB,EACnB,IAAsB;QAEtB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,+BAA+B,WAAW,iBAAiB,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAClG,CAAC;QACJ,CAAC;QACD,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAChD,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;QAC/C,OAAO,EAAE,CAAC;IACZ,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,aAAa,CAAC,KAAqB,EAAE,OAAgB;QACzD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,IAAI,CAAC,oBAAoB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAChD,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,CAAC;QACjC,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;QAE5B,IAAI,IAAI,KAAK,KAAK;YAAE,OAAO;QAE3B,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;YACtB,qDAAqD;YACrD,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;QACtC,CAAC;aAAM,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;YAC5B,kDAAkD;YAClD,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;YACpC,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC/B,CAAC;aAAM,CAAC;YACN,8EAA8E;YAC9E,MAAM,IAAI,CAAC,uBAAuB,EAAE,CAAC;QACvC,CAAC;IACH,CAAC;IAED,iEAAiE;IACjE,aAAa,CAAC,OAAgB;QAC5B,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,cAAc,CAAC;QACvE,CAAC;QACD,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAEO,KAAK,CAAC,oBAAoB,CAChC,OAAe,EACf,KAAqB;QAErB,MAAM,IAAI,GAAG,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,cAAc,CAAC;QAC3E,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAE9C,IAAI,IAAI,KAAK,KAAK;YAAE,OAAO;QAE3B,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;YAC1C,iDAAiD;YACjD,MAAM,IAAI,CAAC,6BAA6B,CAAC,OAAO,CAAC,CAAC;YAClD,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;gBACrB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAC3C,IAAI,OAAO;oBAAE,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;YACpC,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,CAAC,8BAA8B,CAAC,OAAO,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,sBAAsB;QAClC,sCAAsC;QACtC,KAAK,MAAM,CAAC,EAAE,EAAE,WAAW,CAAC,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC1D,6DAA6D;YAC7D,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,EAAE,EAAE;gBAChC,WAAW;gBACX,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE;aACnC,CAAC,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YAC/C,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;oBAC3C,4CAA4C;gBAC9C,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,CAAC;IACpC,CAAC;IAEO,KAAK,CAAC,6BAA6B,CACzC,WAAmB;QAEnB,KAAK,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;YACjD,IAAI,EAAE,KAAK,WAAW,EAAE,CAAC;gBACvB,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,EAAE,EAAE;oBAChC,WAAW;oBACX,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE;iBACnC,CAAC,CAAC;gBACH,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;gBAC/C,IAAI,OAAO,EAAE,CAAC;oBACZ,MAAM,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;wBAC3C,4CAA4C;oBAC9C,CAAC,CAAC,CAAC;gBACL,CAAC;gBACD,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,eAAe;QAC3B,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YAC7C,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;gBAC9B,4CAA4C;YAC9C,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,uBAAuB;QACnC,qEAAqE;QACrE,oFAAoF;QACpF,KAAK,MAAM,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC7C,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACrC,gEAAgE;YAChE,gEAAgE;QAClE,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,8BAA8B,CAC1C,WAAmB;QAEnB,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;YACpD,IAAI,KAAK,CAAC,WAAW,KAAK,WAAW,EAAE,CAAC;gBACtC,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;IACH,CAAC;IAED,+CAA+C;IAC/C,KAAK,CAAC,eAAe,CAAC,EAAU;QAC9B,MAAM,WAAW,GAAG,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtD,IAAI,CAAC,WAAW;YAAE,OAAO;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,MAAM,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,mFAAmF;IACnF,QAAQ,CAAC,EAAU;QACjB,OAAO,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,QAAQ,CACZ,WAAoB,EACpB,OAAgB;QAEhB,MAAM,OAAO,GACX,WAAW,KAAK,SAAS;YACvB,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CACrC,CAAC,CAAC,EAAyB,EAAE,CAAC,CAAC,KAAK,SAAS,CAC9C;YACH,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAElC,4DAA4D;QAC5D,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;YACzC,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACvC,OAAO,GAAG,KAAK,MAAM,CAAC;QACxB,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAC9C,CAAC;QAEF,2BAA2B;QAC3B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,MAAM,OAAO,GAAqB,EAAE,CAAC;QACrC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;gBAC1B,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBACnB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;oBACd,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FederationManager — manages TLS links between mesh coordinators.
|
|
3
|
+
*
|
|
4
|
+
* Federation links are persistent TLS connections between coordinators on
|
|
5
|
+
* different machines. They forward agent presence, room memberships, and
|
|
6
|
+
* messages for rooms marked as federated. Non-federated rooms never leave
|
|
7
|
+
* the local mesh.
|
|
8
|
+
*
|
|
9
|
+
* Each link uses certificate pinning (the same trust model as TlsTransport).
|
|
10
|
+
* The wire protocol runs over the same newline-delimited JSON framing as the
|
|
11
|
+
* local mesh, but with `fed_*` method types.
|
|
12
|
+
*/
|
|
13
|
+
import * as tls from "node:tls";
|
|
14
|
+
import type { AgentIdentity, RoomMessage } from "./types.js";
|
|
15
|
+
import type { PeerIdentity } from "./identity.js";
|
|
16
|
+
/** Represents an active federation link (outbound or inbound). */
|
|
17
|
+
export interface FedLink {
|
|
18
|
+
/** Unique ID for this link (assigned locally). */
|
|
19
|
+
id: string;
|
|
20
|
+
/** Remote mesh ID (received during handshake). */
|
|
21
|
+
remoteMeshId: string;
|
|
22
|
+
/** Human-readable name for the remote mesh. */
|
|
23
|
+
remoteName: string;
|
|
24
|
+
/** The TLS socket. */
|
|
25
|
+
socket: tls.TLSSocket;
|
|
26
|
+
/** Whether the handshake has completed successfully. */
|
|
27
|
+
ready: boolean;
|
|
28
|
+
/** Direction of the connection. */
|
|
29
|
+
direction: "outbound" | "inbound";
|
|
30
|
+
}
|
|
31
|
+
/** Callbacks the FederationManager uses to interact with local mesh state. */
|
|
32
|
+
export interface FedCallbacks {
|
|
33
|
+
/** Called when a remote agent becomes visible over a federation link. */
|
|
34
|
+
onAgentVisible(agent: AgentIdentity): Promise<void>;
|
|
35
|
+
/** Called when a remote agent goes offline/disappears. */
|
|
36
|
+
onAgentGone(agentId: string): Promise<void>;
|
|
37
|
+
/** Called when a message arrives for a federated room. */
|
|
38
|
+
onRoomMessage(roomId: string, message: RoomMessage): Promise<void>;
|
|
39
|
+
/** Called when a remote agent joins a federated room. */
|
|
40
|
+
onRoomJoin(roomId: string, agentId: string, agentName: string): Promise<void>;
|
|
41
|
+
/** Called when a remote agent leaves a federated room. */
|
|
42
|
+
onRoomLeave(roomId: string, agentId: string): Promise<void>;
|
|
43
|
+
/** Get all visible agents in the local mesh (for syncing to new links). */
|
|
44
|
+
getVisibleAgents(): AgentIdentity[];
|
|
45
|
+
/** Get all federated rooms and their member lists (for syncing to new links). */
|
|
46
|
+
getFederatedRoomMemberships(): Map<string, string[]>;
|
|
47
|
+
}
|
|
48
|
+
export declare class FederationManager {
|
|
49
|
+
private links;
|
|
50
|
+
private identity;
|
|
51
|
+
private meshId;
|
|
52
|
+
private meshName;
|
|
53
|
+
private callbacks;
|
|
54
|
+
private pingTimers;
|
|
55
|
+
private shutDown;
|
|
56
|
+
private pendingPongs;
|
|
57
|
+
constructor(meshId: string, meshName: string, callbacks: FedCallbacks);
|
|
58
|
+
/** The TLS identity used for federation connections. */
|
|
59
|
+
get tlsIdentity(): PeerIdentity;
|
|
60
|
+
/**
|
|
61
|
+
* Establish an outbound federation link to a remote coordinator.
|
|
62
|
+
* Returns the local link ID once the handshake completes.
|
|
63
|
+
*/
|
|
64
|
+
connect(host: string, port: number, name?: string): Promise<string>;
|
|
65
|
+
/**
|
|
66
|
+
* Handle an incoming TLS connection that sent a fed_handshake.
|
|
67
|
+
* Called by the transport layer when a federation connection arrives.
|
|
68
|
+
*/
|
|
69
|
+
handleInbound(socket: tls.TLSSocket): Promise<string>;
|
|
70
|
+
/** Disconnect a specific federation link. */
|
|
71
|
+
disconnect(linkId: string): Promise<void>;
|
|
72
|
+
/** List all active federation links. */
|
|
73
|
+
listLinks(): FedLink[];
|
|
74
|
+
/** Broadcast an agent visibility event to all ready links. */
|
|
75
|
+
broadcastAgentVisible(agent: AgentIdentity): Promise<void>;
|
|
76
|
+
/** Broadcast an agent gone event to all ready links. */
|
|
77
|
+
broadcastAgentGone(agentId: string): Promise<void>;
|
|
78
|
+
/** Forward a room message to all ready links (federated rooms only). */
|
|
79
|
+
forwardRoomMessage(roomId: string, message: RoomMessage): Promise<void>;
|
|
80
|
+
/** Broadcast a room join to all ready links. */
|
|
81
|
+
broadcastRoomJoin(roomId: string, agentId: string, agentName: string): Promise<void>;
|
|
82
|
+
/** Broadcast a room leave to all ready links. */
|
|
83
|
+
broadcastRoomLeave(roomId: string, agentId: string): Promise<void>;
|
|
84
|
+
shutdown(): Promise<void>;
|
|
85
|
+
private tlsConnect;
|
|
86
|
+
private wireSocket;
|
|
87
|
+
private handleMessage;
|
|
88
|
+
/**
|
|
89
|
+
* After handshake, push our visible agents and federated room memberships
|
|
90
|
+
* to the newly connected link.
|
|
91
|
+
*/
|
|
92
|
+
private syncStateToLink;
|
|
93
|
+
private waitForHandshake;
|
|
94
|
+
private startPing;
|
|
95
|
+
private sendPing;
|
|
96
|
+
private writeToSocket;
|
|
97
|
+
private broadcastToReady;
|
|
98
|
+
private clearLinkTimers;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=federation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"federation.d.ts","sourceRoot":"","sources":["../../src/core/federation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAGhC,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAMlD,kEAAkE;AAClE,MAAM,WAAW,OAAO;IACtB,kDAAkD;IAClD,EAAE,EAAE,MAAM,CAAC;IACX,kDAAkD;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,sBAAsB;IACtB,MAAM,EAAE,GAAG,CAAC,SAAS,CAAC;IACtB,wDAAwD;IACxD,KAAK,EAAE,OAAO,CAAC;IACf,mCAAmC;IACnC,SAAS,EAAE,UAAU,GAAG,SAAS,CAAC;CACnC;AAED,8EAA8E;AAC9E,MAAM,WAAW,YAAY;IAC3B,yEAAyE;IACzE,cAAc,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,0DAA0D;IAC1D,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,0DAA0D;IAC1D,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,yDAAyD;IACzD,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,0DAA0D;IAC1D,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,2EAA2E;IAC3E,gBAAgB,IAAI,aAAa,EAAE,CAAC;IACpC,iFAAiF;IACjF,2BAA2B,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACtD;AAcD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,KAAK,CAA8B;IAC3C,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAe;IAChC,OAAO,CAAC,UAAU,CAAqD;IACvE,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,YAAY,CAAoD;gBAE5D,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY;IAOrE,wDAAwD;IACxD,IAAI,WAAW,IAAI,YAAY,CAE9B;IAMD;;;OAGG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAsCzE;;;OAGG;IACG,aAAa,CAAC,MAAM,EAAE,GAAG,CAAC,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC;IA6B3D,6CAA6C;IACvC,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW/C,wCAAwC;IACxC,SAAS,IAAI,OAAO,EAAE;IAQtB,8DAA8D;IACxD,qBAAqB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAKhE,wDAAwD;IAClD,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKxD,wEAAwE;IAClE,kBAAkB,CACtB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC;IAKhB,gDAAgD;IAC1C,iBAAiB,CACrB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC;IAUhB,iDAAiD;IAC3C,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASlE,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAW/B,OAAO,CAAC,UAAU;IAkClB,OAAO,CAAC,UAAU;YAyBJ,aAAa;IA+E3B;;;OAGG;YACW,eAAe;IAkC7B,OAAO,CAAC,gBAAgB;IA0BxB,OAAO,CAAC,SAAS;YAUH,QAAQ;YAoBR,aAAa;YAcb,gBAAgB;IAmB9B,OAAO,CAAC,eAAe;CAYxB"}
|