@geohar/un-bien 0.7.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/LICENSE +21 -0
- package/README.md +726 -0
- package/dist/actions/handlers.d.ts +77 -0
- package/dist/actions/handlers.js +26 -0
- package/dist/actions/handlers.js.map +1 -0
- package/dist/actions/registry.d.ts +39 -0
- package/dist/actions/registry.js +62 -0
- package/dist/actions/registry.js.map +1 -0
- package/dist/bin/supervisord.d.ts +2 -0
- package/dist/bin/supervisord.js +86 -0
- package/dist/bin/supervisord.js.map +1 -0
- package/dist/config.d.ts +84 -0
- package/dist/config.js +115 -0
- package/dist/config.js.map +1 -0
- package/dist/daemon/client.d.ts +20 -0
- package/dist/daemon/client.js +131 -0
- package/dist/daemon/client.js.map +1 -0
- package/dist/daemon/control_protocol.d.ts +176 -0
- package/dist/daemon/control_protocol.js +63 -0
- package/dist/daemon/control_protocol.js.map +1 -0
- package/dist/daemon/cron_log.d.ts +45 -0
- package/dist/daemon/cron_log.js +71 -0
- package/dist/daemon/cron_log.js.map +1 -0
- package/dist/daemon/cron_registry.d.ts +80 -0
- package/dist/daemon/cron_registry.js +198 -0
- package/dist/daemon/cron_registry.js.map +1 -0
- package/dist/daemon/id.d.ts +24 -0
- package/dist/daemon/id.js +36 -0
- package/dist/daemon/id.js.map +1 -0
- package/dist/daemon/install.d.ts +170 -0
- package/dist/daemon/install.js +603 -0
- package/dist/daemon/install.js.map +1 -0
- package/dist/daemon/registry.d.ts +63 -0
- package/dist/daemon/registry.js +153 -0
- package/dist/daemon/registry.js.map +1 -0
- package/dist/daemon/rpc_child.d.ts +194 -0
- package/dist/daemon/rpc_child.js +419 -0
- package/dist/daemon/rpc_child.js.map +1 -0
- package/dist/daemon/supervisor.d.ts +93 -0
- package/dist/daemon/supervisor.js +666 -0
- package/dist/daemon/supervisor.js.map +1 -0
- package/dist/extension_ui_bridge.d.ts +26 -0
- package/dist/extension_ui_bridge.js +341 -0
- package/dist/extension_ui_bridge.js.map +1 -0
- package/dist/index.d.ts +197 -0
- package/dist/index.js +5750 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/mesh_result.d.ts +10 -0
- package/dist/mcp/mesh_result.js +42 -0
- package/dist/mcp/mesh_result.js.map +1 -0
- package/dist/mcp/mesh_server.d.ts +16 -0
- package/dist/mcp/mesh_server.js +373 -0
- package/dist/mcp/mesh_server.js.map +1 -0
- package/dist/mesh/canonical.d.ts +30 -0
- package/dist/mesh/canonical.js +63 -0
- package/dist/mesh/canonical.js.map +1 -0
- package/dist/mesh/client.d.ts +18 -0
- package/dist/mesh/client.js +127 -0
- package/dist/mesh/client.js.map +1 -0
- package/dist/mesh/encoding.d.ts +38 -0
- package/dist/mesh/encoding.js +217 -0
- package/dist/mesh/encoding.js.map +1 -0
- package/dist/mesh/self_revoke.d.ts +73 -0
- package/dist/mesh/self_revoke.js +407 -0
- package/dist/mesh/self_revoke.js.map +1 -0
- package/dist/mesh/siblings.d.ts +49 -0
- package/dist/mesh/siblings.js +159 -0
- package/dist/mesh/siblings.js.map +1 -0
- package/dist/mesh/types.d.ts +34 -0
- package/dist/mesh/types.js +11 -0
- package/dist/mesh/types.js.map +1 -0
- package/dist/mesh/verify.d.ts +17 -0
- package/dist/mesh/verify.js +86 -0
- package/dist/mesh/verify.js.map +1 -0
- package/dist/pairing/crypto.d.ts +8 -0
- package/dist/pairing/crypto.js +22 -0
- package/dist/pairing/crypto.js.map +1 -0
- package/dist/pairing/qr.d.ts +59 -0
- package/dist/pairing/qr.js +127 -0
- package/dist/pairing/qr.js.map +1 -0
- package/dist/pairing/storage.d.ts +120 -0
- package/dist/pairing/storage.js +614 -0
- package/dist/pairing/storage.js.map +1 -0
- package/dist/panel_bridge.d.ts +15 -0
- package/dist/panel_bridge.js +409 -0
- package/dist/panel_bridge.js.map +1 -0
- package/dist/paths.d.ts +39 -0
- package/dist/paths.js +51 -0
- package/dist/paths.js.map +1 -0
- package/dist/protocol/codec.d.ts +7 -0
- package/dist/protocol/codec.js +48 -0
- package/dist/protocol/codec.js.map +1 -0
- package/dist/protocol/types.d.ts +404 -0
- package/dist/protocol/types.js +2 -0
- package/dist/protocol/types.js.map +1 -0
- package/dist/rooms.d.ts +42 -0
- package/dist/rooms.js +78 -0
- package/dist/rooms.js.map +1 -0
- package/dist/session/bridge.d.ts +37 -0
- package/dist/session/bridge.js +134 -0
- package/dist/session/bridge.js.map +1 -0
- package/dist/session/broker.d.ts +189 -0
- package/dist/session/broker.js +527 -0
- package/dist/session/broker.js.map +1 -0
- package/dist/session/broker_remote.d.ts +74 -0
- package/dist/session/broker_remote.js +581 -0
- package/dist/session/broker_remote.js.map +1 -0
- package/dist/session/cwd_lock.d.ts +33 -0
- package/dist/session/cwd_lock.js +127 -0
- package/dist/session/cwd_lock.js.map +1 -0
- package/dist/session/debug_log.d.ts +3 -0
- package/dist/session/debug_log.js +32 -0
- package/dist/session/debug_log.js.map +1 -0
- package/dist/session/envelope.d.ts +33 -0
- package/dist/session/envelope.js +117 -0
- package/dist/session/envelope.js.map +1 -0
- package/dist/session/global_config.d.ts +33 -0
- package/dist/session/global_config.js +73 -0
- package/dist/session/global_config.js.map +1 -0
- package/dist/session/ipc.d.ts +27 -0
- package/dist/session/ipc.js +22 -0
- package/dist/session/ipc.js.map +1 -0
- package/dist/session/leader_election.d.ts +32 -0
- package/dist/session/leader_election.js +108 -0
- package/dist/session/leader_election.js.map +1 -0
- package/dist/session/local_config.d.ts +67 -0
- package/dist/session/local_config.js +193 -0
- package/dist/session/local_config.js.map +1 -0
- package/dist/session/mesh_node.d.ts +116 -0
- package/dist/session/mesh_node.js +596 -0
- package/dist/session/mesh_node.js.map +1 -0
- package/dist/session/peer.d.ts +139 -0
- package/dist/session/peer.js +474 -0
- package/dist/session/peer.js.map +1 -0
- package/dist/session/peer_inventory.d.ts +13 -0
- package/dist/session/peer_inventory.js +48 -0
- package/dist/session/peer_inventory.js.map +1 -0
- package/dist/session/peer_limits.d.ts +9 -0
- package/dist/session/peer_limits.js +24 -0
- package/dist/session/peer_limits.js.map +1 -0
- package/dist/session/rpc_envelope.d.ts +108 -0
- package/dist/session/rpc_envelope.js +221 -0
- package/dist/session/rpc_envelope.js.map +1 -0
- package/dist/session/rpc_inbound.d.ts +55 -0
- package/dist/session/rpc_inbound.js +136 -0
- package/dist/session/rpc_inbound.js.map +1 -0
- package/dist/session/setup_wizard.d.ts +39 -0
- package/dist/session/setup_wizard.js +63 -0
- package/dist/session/setup_wizard.js.map +1 -0
- package/dist/session/tools.d.ts +24 -0
- package/dist/session/tools.js +272 -0
- package/dist/session/tools.js.map +1 -0
- package/dist/session/wizard.d.ts +13 -0
- package/dist/session/wizard.js +20 -0
- package/dist/session/wizard.js.map +1 -0
- package/dist/transport/peer_channel.d.ts +52 -0
- package/dist/transport/peer_channel.js +145 -0
- package/dist/transport/peer_channel.js.map +1 -0
- package/dist/transport/pi_forward_client.d.ts +29 -0
- package/dist/transport/pi_forward_client.js +68 -0
- package/dist/transport/pi_forward_client.js.map +1 -0
- package/dist/transport/relay_client.d.ts +96 -0
- package/dist/transport/relay_client.js +210 -0
- package/dist/transport/relay_client.js.map +1 -0
- package/dist/ui/footer.d.ts +32 -0
- package/dist/ui/footer.js +34 -0
- package/dist/ui/footer.js.map +1 -0
- package/docs/daemon.md +289 -0
- package/package.json +92 -0
- package/service-templates/launchd.plist.template +35 -0
- package/service-templates/systemd.service.template +19 -0
- package/service-templates/task-launcher.vbs.template +10 -0
- package/service-templates/task-scheduler.xml.template +38 -0
- package/skills/agent-network/SKILL.md +310 -0
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
import { appendFile, mkdir } from "node:fs/promises";
|
|
2
|
+
import { dirname, posix, win32 } from "node:path";
|
|
3
|
+
import { parse, serialize, uuidv7, EnvelopeError, } from "./envelope.js";
|
|
4
|
+
import { sanitizeSegment } from "./local_config.js";
|
|
5
|
+
import { isBoundedPeerInfo, MAX_CWD_LENGTH, MAX_PEERS_UPDATE_ENTRIES, } from "./peer_limits.js";
|
|
6
|
+
/**
|
|
7
|
+
* THE sole encoder of a peer address (plan/38): `[<pc>:]<cwd>@<nome>`.
|
|
8
|
+
*
|
|
9
|
+
* - `cwd` present → `<cwd>@<nome>` (the `@` separates name from path so a `/`
|
|
10
|
+
* in the path never confuses lookup, which is exact-match anyway).
|
|
11
|
+
* - `cwd` empty (legacy peer that sent no cwd) → `address == name`, preserving
|
|
12
|
+
* pre-plan/38 behavior so a mixed mesh keeps routing.
|
|
13
|
+
* - `pc` present (cross-PC, Fase 2) → prefixed `<pc>:`.
|
|
14
|
+
*
|
|
15
|
+
* Does NOT sanitize — callers sanitize the `name` once (see `sanitizeMeshName`)
|
|
16
|
+
* before composing, so an already-appended `#N` collision suffix survives.
|
|
17
|
+
* Everyone else ECHOES `peer.address` verbatim; only the broker composes.
|
|
18
|
+
*/
|
|
19
|
+
export function composeAddress(parts) {
|
|
20
|
+
const base = parts.cwd ? `${parts.cwd}@${parts.name}` : parts.name;
|
|
21
|
+
return parts.pc ? `${parts.pc}:${base}` : base;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Sanitize a requested mesh name to a safe leaf while PRESERVING a trailing
|
|
25
|
+
* `#N` collision suffix (which the cwd-lock or a prior assignment may have
|
|
26
|
+
* added — `sanitizeSegment` alone would mangle `#`→`-`). The base is run through
|
|
27
|
+
* `sanitizeSegment` (af66d04); an unusable base (empty / reserved keyword) falls
|
|
28
|
+
* back to `"agent"`.
|
|
29
|
+
*/
|
|
30
|
+
export function sanitizeMeshName(raw) {
|
|
31
|
+
const m = /^(.*?)(#\d+)?$/.exec(raw);
|
|
32
|
+
const base = sanitizeSegment(m?.[1] ?? raw) ?? "agent";
|
|
33
|
+
return m?.[2] ? base + m[2] : base;
|
|
34
|
+
}
|
|
35
|
+
const BROKER_NAME = "broker";
|
|
36
|
+
/** Host-independent Windows drive absolute-path check. */
|
|
37
|
+
function isWindowsDriveAbsolutePath(value) {
|
|
38
|
+
return /^[A-Za-z]:[\\/]/.test(value);
|
|
39
|
+
}
|
|
40
|
+
/** Accept legacy empty cwd plus bounded syntactically absolute paths only. */
|
|
41
|
+
function isValidRegisteredCwd(value) {
|
|
42
|
+
if (value === "")
|
|
43
|
+
return true;
|
|
44
|
+
if (value.length > MAX_CWD_LENGTH || /[\0\r\n]/.test(value)) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
return (posix.isAbsolute(value) ||
|
|
48
|
+
isWindowsDriveAbsolutePath(value) ||
|
|
49
|
+
(win32.isAbsolute(value) && /^[/\\]{2}/.test(value)));
|
|
50
|
+
}
|
|
51
|
+
export class Broker {
|
|
52
|
+
peers = new Map();
|
|
53
|
+
auditPath;
|
|
54
|
+
onRouted;
|
|
55
|
+
server;
|
|
56
|
+
/** Plan/25 Wave C: optional handoff for cross-PC routing. Null = local only. */
|
|
57
|
+
remoteRouter = null;
|
|
58
|
+
constructor(opts) {
|
|
59
|
+
this.server = opts.server;
|
|
60
|
+
this.auditPath = opts.auditPath;
|
|
61
|
+
this.onRouted = opts.onRouted;
|
|
62
|
+
this.server.on("connection", (socket) => this._handleConnection(socket));
|
|
63
|
+
}
|
|
64
|
+
/** Attach (or detach with null) a cross-PC router. Idempotent. */
|
|
65
|
+
setRemoteRouter(router) {
|
|
66
|
+
this.remoteRouter = router;
|
|
67
|
+
}
|
|
68
|
+
/** Clear only when the caller still owns the active router slot. */
|
|
69
|
+
clearRemoteRouter(expected) {
|
|
70
|
+
if (this.remoteRouter === expected)
|
|
71
|
+
this.remoteRouter = null;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Plan/25 Wave C entry point: deliver an envelope that arrived from a
|
|
75
|
+
* remote PC (via relay forward) into the local UDS mesh. Skips the
|
|
76
|
+
* `force from = conn.name` rule (that defense is anti-spoof for local
|
|
77
|
+
* peers; cross-PC has its own defense via the relay's verified `from_pc`).
|
|
78
|
+
*
|
|
79
|
+
* Returns the ACK status so the caller (broker_remote) can pack and
|
|
80
|
+
* forward an ACK envelope back across the relay:
|
|
81
|
+
* - `received` — target exists, envelope delivered (plan/34: always
|
|
82
|
+
* delivered when the peer is online — the Pi harness enqueues mid-turn
|
|
83
|
+
* messages, so there is no busy-drop)
|
|
84
|
+
* - `denied` — no such local peer (or write failed) — caller maps to
|
|
85
|
+
* transport_error or denied ACK as it sees fit
|
|
86
|
+
*/
|
|
87
|
+
injectFromRemote(env) {
|
|
88
|
+
// Remote callers do not cross the normal UDS parser, so validate the exact
|
|
89
|
+
// serialized payload before claiming receipt or writing it to a peer.
|
|
90
|
+
let validated;
|
|
91
|
+
try {
|
|
92
|
+
validated = parse(serialize(env));
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return "denied";
|
|
96
|
+
}
|
|
97
|
+
if (typeof validated.to !== "string" ||
|
|
98
|
+
validated.to === "broadcast" ||
|
|
99
|
+
validated.to === BROKER_NAME) {
|
|
100
|
+
// Cross-PC is unicast-only at this protocol layer.
|
|
101
|
+
return "denied";
|
|
102
|
+
}
|
|
103
|
+
const targetName = validated.to;
|
|
104
|
+
const peer = this.peers.get(targetName);
|
|
105
|
+
if (!peer)
|
|
106
|
+
return "denied";
|
|
107
|
+
const line = serialize(validated);
|
|
108
|
+
try {
|
|
109
|
+
peer.socket.write(line);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return "denied";
|
|
113
|
+
}
|
|
114
|
+
void this._appendAudit(validated, [targetName], "received", "relay");
|
|
115
|
+
this.onRouted?.(validated, [targetName]);
|
|
116
|
+
return "received";
|
|
117
|
+
}
|
|
118
|
+
/** Peers currently registered. Snapshot, safe to read. */
|
|
119
|
+
peerNames() {
|
|
120
|
+
return [...this.peers.keys()];
|
|
121
|
+
}
|
|
122
|
+
async close() {
|
|
123
|
+
for (const p of this.peers.values())
|
|
124
|
+
p.socket.destroy();
|
|
125
|
+
this.peers.clear();
|
|
126
|
+
await new Promise((resolve) => this.server.close(() => resolve()));
|
|
127
|
+
}
|
|
128
|
+
// ── connection lifecycle ──────────────────────────────────────────────────
|
|
129
|
+
_handleConnection(socket) {
|
|
130
|
+
const conn = { name: "", cwd: "", address: "", socket, buf: "" };
|
|
131
|
+
socket.setEncoding("utf8");
|
|
132
|
+
socket.on("data", (chunk) => this._onData(conn, chunk));
|
|
133
|
+
socket.on("close", () => this._onClose(conn));
|
|
134
|
+
socket.on("error", () => {
|
|
135
|
+
/* ignored — close will follow */
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
_onData(conn, chunk) {
|
|
139
|
+
conn.buf += chunk;
|
|
140
|
+
let nl;
|
|
141
|
+
while ((nl = conn.buf.indexOf("\n")) >= 0) {
|
|
142
|
+
const line = conn.buf.slice(0, nl);
|
|
143
|
+
conn.buf = conn.buf.slice(nl + 1);
|
|
144
|
+
if (!line)
|
|
145
|
+
continue;
|
|
146
|
+
void this._handleLine(conn, line);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
async _handleLine(conn, line) {
|
|
150
|
+
// Unregistered conn: a read-only `list_peers` probe (the `unbien peers`
|
|
151
|
+
// CLI — answered without registering, so it leaves no trace on the mesh) or
|
|
152
|
+
// the mandatory `register` handshake. Anything else `_handleRegister` drops.
|
|
153
|
+
if (!conn.name) {
|
|
154
|
+
if (this._tryObserverProbe(conn, line))
|
|
155
|
+
return;
|
|
156
|
+
this._handleRegister(conn, line);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
// Already registered — must be a regular envelope.
|
|
160
|
+
let env;
|
|
161
|
+
try {
|
|
162
|
+
env = parse(line);
|
|
163
|
+
}
|
|
164
|
+
catch (e) {
|
|
165
|
+
if (e instanceof EnvelopeError)
|
|
166
|
+
return; // malformed; drop silently
|
|
167
|
+
throw e;
|
|
168
|
+
}
|
|
169
|
+
// Force `from` to the registered ADDRESS (security: peer can't spoof; and
|
|
170
|
+
// replies/ACKs address back by the same canonical key the Map is keyed on).
|
|
171
|
+
env.from = conn.address;
|
|
172
|
+
await this._route(env);
|
|
173
|
+
}
|
|
174
|
+
_handleRegister(conn, line) {
|
|
175
|
+
let req;
|
|
176
|
+
try {
|
|
177
|
+
const parsed = JSON.parse(line);
|
|
178
|
+
if (!parsed ||
|
|
179
|
+
typeof parsed !== "object" ||
|
|
180
|
+
parsed.type !== "register" ||
|
|
181
|
+
typeof parsed.name !== "string") {
|
|
182
|
+
conn.socket.destroy();
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
req = parsed;
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
conn.socket.destroy();
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
// (cwd, name) identity (plan/38). The cwd is the first-class axis: the
|
|
192
|
+
// address embeds it, so two same-named agents in DIFFERENT folders get
|
|
193
|
+
// distinct addresses and never collide. Legacy peers (no cwd) keep the old
|
|
194
|
+
// global-name behavior. New peers can opt into exact-address takeover for
|
|
195
|
+
// same-folder reincarnations such as daemon restarts.
|
|
196
|
+
const requestedCwd = req.cwd === undefined ? "" : req.cwd;
|
|
197
|
+
if (typeof requestedCwd !== "string" ||
|
|
198
|
+
!isValidRegisteredCwd(requestedCwd)) {
|
|
199
|
+
conn.socket.destroy();
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const identity = this._identityForRegister(requestedCwd, req.name, req.takeover === true);
|
|
203
|
+
if (!identity) {
|
|
204
|
+
conn.socket.destroy();
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
conn.cwd = requestedCwd;
|
|
208
|
+
conn.name = identity.name;
|
|
209
|
+
conn.address = identity.address;
|
|
210
|
+
// Candidate validity is established before a takeover evicts its prior
|
|
211
|
+
// connection, so a rejected replacement cannot drop a healthy peer.
|
|
212
|
+
if (identity.replaceAddress)
|
|
213
|
+
this._dropPeerAt(identity.replaceAddress);
|
|
214
|
+
this.peers.set(identity.address, conn);
|
|
215
|
+
// `name_assigned` doubles as the compat alias: for a legacy peer it equals
|
|
216
|
+
// `address_assigned` (cwd empty → address == name), so old clients that read
|
|
217
|
+
// `name_assigned` still get a routable identity.
|
|
218
|
+
const ack = {
|
|
219
|
+
type: "register_ack",
|
|
220
|
+
address_assigned: conn.address,
|
|
221
|
+
name_assigned: conn.name,
|
|
222
|
+
};
|
|
223
|
+
try {
|
|
224
|
+
conn.socket.write(JSON.stringify(ack) + "\n");
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
/* peer hung up */
|
|
228
|
+
}
|
|
229
|
+
// Notify others (peer_joined broadcast). The field carries the ADDRESS.
|
|
230
|
+
this._broadcastSystem({ type: "peer_joined", name: conn.address, address: conn.address }, conn.address);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Answer a read-only `list_peers` request from an UNREGISTERED connection
|
|
234
|
+
* (the `unbien peers` CLI probe). Returns true when the line was such a
|
|
235
|
+
* probe — the reply is written and the connection stays unregistered: no
|
|
236
|
+
* name assigned, no `peer_joined`/`peer_left` broadcast, no sibling push, so
|
|
237
|
+
* querying the roster from the shell never perturbs the mesh. Returns false
|
|
238
|
+
* (not a probe) so the caller falls through to the register handshake.
|
|
239
|
+
*/
|
|
240
|
+
_tryObserverProbe(conn, line) {
|
|
241
|
+
let parsed;
|
|
242
|
+
try {
|
|
243
|
+
parsed = JSON.parse(line);
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
return false; // not JSON → let _handleRegister destroy it
|
|
247
|
+
}
|
|
248
|
+
if (!parsed || typeof parsed !== "object" || parsed.type !== "list_peers") {
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
const reply = {
|
|
252
|
+
from: BROKER_NAME,
|
|
253
|
+
to: "observer", // synthetic: the conn has no registered name
|
|
254
|
+
id: uuidv7(),
|
|
255
|
+
re: null,
|
|
256
|
+
body: {
|
|
257
|
+
type: "list_peers_reply",
|
|
258
|
+
peers: this._allPeerNames(),
|
|
259
|
+
peers_detailed: this._allPeerInfos(),
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
try {
|
|
263
|
+
conn.socket.write(serialize(reply));
|
|
264
|
+
}
|
|
265
|
+
catch {
|
|
266
|
+
/* probe hung up */
|
|
267
|
+
}
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
/** Local UDS peer names plus cross-PC `<pc>:<peer>` entries from the remote
|
|
271
|
+
* router (empty when no bridge). Shared by the registered `list_peers`
|
|
272
|
+
* handler and the unregistered observer probe. */
|
|
273
|
+
_allPeerNames() {
|
|
274
|
+
const remote = this.remoteRouter ? this.remoteRouter.listRemotePeers() : [];
|
|
275
|
+
return [...this.peerNames(), ...remote];
|
|
276
|
+
}
|
|
277
|
+
/** Structured roster of LOCAL UDS peers (plan/38): one `PeerInfo` each, no
|
|
278
|
+
* `pc` (they're on this machine). Public so the cross-PC router
|
|
279
|
+
* (`broker_remote`) can read the authoritative local inventory directly to
|
|
280
|
+
* push to siblings — no `list_peers` round-trip, no stale cache. */
|
|
281
|
+
localPeerInfos() {
|
|
282
|
+
return [...this.peers.values()].map((p) => ({
|
|
283
|
+
cwd: p.cwd,
|
|
284
|
+
name: p.name,
|
|
285
|
+
address: p.address,
|
|
286
|
+
}));
|
|
287
|
+
}
|
|
288
|
+
/** Structured roster (plan/38): local peers (no `pc`) + cross-PC peers with
|
|
289
|
+
* `pc`/`cwd`/`name` filled by the remote router (Fase 2). */
|
|
290
|
+
_allPeerInfos() {
|
|
291
|
+
const remote = this.remoteRouter?.listRemotePeerInfos() ?? [];
|
|
292
|
+
return [...this.localPeerInfos(), ...remote];
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Resolve a free `(name, address)` for a register, keyed by **(cwd, name)**
|
|
296
|
+
* (plan/38): the collision check is on the composed ADDRESS, so a name only
|
|
297
|
+
* collides with another peer in the SAME cwd. `#N` is appended to the name
|
|
298
|
+
* (matching the cwd-lock's suffix scheme) until the address is free; for a
|
|
299
|
+
* legacy peer (cwd "") the address is the name, preserving global-name `#N`.
|
|
300
|
+
*/
|
|
301
|
+
_identityForRegister(cwd, requested, takeover) {
|
|
302
|
+
const sanitized = sanitizeMeshName(requested);
|
|
303
|
+
const candidateFor = (name) => {
|
|
304
|
+
const address = composeAddress({ cwd, name });
|
|
305
|
+
return isBoundedPeerInfo({ cwd, name, address })
|
|
306
|
+
? { name, address }
|
|
307
|
+
: null;
|
|
308
|
+
};
|
|
309
|
+
const direct = candidateFor(sanitized);
|
|
310
|
+
if (!direct)
|
|
311
|
+
return null;
|
|
312
|
+
if (takeover && cwd && this.peers.has(direct.address)) {
|
|
313
|
+
return { ...direct, replaceAddress: direct.address };
|
|
314
|
+
}
|
|
315
|
+
if (this.peers.size >= MAX_PEERS_UPDATE_ENTRIES)
|
|
316
|
+
return null;
|
|
317
|
+
if (!this.peers.has(direct.address))
|
|
318
|
+
return direct;
|
|
319
|
+
// Collision: strip any client-provided `#N`, then re-suffix from #2.
|
|
320
|
+
const base = sanitized.replace(/#\d+$/, "");
|
|
321
|
+
for (let n = 2; n < 1000; n++) {
|
|
322
|
+
const candidate = candidateFor(`${base}#${n}`);
|
|
323
|
+
if (!candidate)
|
|
324
|
+
return null;
|
|
325
|
+
if (!this.peers.has(candidate.address))
|
|
326
|
+
return candidate;
|
|
327
|
+
}
|
|
328
|
+
return null;
|
|
329
|
+
}
|
|
330
|
+
_dropPeerAt(address) {
|
|
331
|
+
const existing = this.peers.get(address);
|
|
332
|
+
if (!existing)
|
|
333
|
+
return;
|
|
334
|
+
this.peers.delete(address);
|
|
335
|
+
// The old socket's close event may arrive after the replacement has been
|
|
336
|
+
// inserted. Clear its address so it cannot delete the replacement.
|
|
337
|
+
existing.address = "";
|
|
338
|
+
try {
|
|
339
|
+
existing.socket.destroy();
|
|
340
|
+
}
|
|
341
|
+
catch {
|
|
342
|
+
/* ignored */
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
_onClose(conn) {
|
|
346
|
+
if (!conn.address)
|
|
347
|
+
return;
|
|
348
|
+
if (this.peers.get(conn.address) !== conn)
|
|
349
|
+
return;
|
|
350
|
+
this.peers.delete(conn.address);
|
|
351
|
+
this._broadcastSystem({ type: "peer_left", name: conn.address, address: conn.address }, conn.address);
|
|
352
|
+
}
|
|
353
|
+
// ── routing ───────────────────────────────────────────────────────────────
|
|
354
|
+
async _route(env) {
|
|
355
|
+
// Special handling for messages addressed to the broker itself.
|
|
356
|
+
if (env.to === BROKER_NAME) {
|
|
357
|
+
this._handleBrokerMessage(env);
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
// Give known cross-PC aliases first chance to route. A syntactically
|
|
361
|
+
// absolute Windows drive address contains a colon but is always exact
|
|
362
|
+
// local; all other local registrations may not shadow a known alias.
|
|
363
|
+
const exactLocal = typeof env.to === "string" ? this.peers.get(env.to) : undefined;
|
|
364
|
+
const exactWindowsDriveLocal = !!exactLocal && isWindowsDriveAbsolutePath(exactLocal.cwd);
|
|
365
|
+
if (!exactWindowsDriveLocal &&
|
|
366
|
+
this.remoteRouter &&
|
|
367
|
+
typeof env.to === "string") {
|
|
368
|
+
if (this.remoteRouter.tryRouteOutbound(env))
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
const targets = this._resolveTargets(env);
|
|
372
|
+
const delivered = [];
|
|
373
|
+
const line = serialize(env);
|
|
374
|
+
const isUnicast = typeof env.to === "string" && env.to !== "broadcast";
|
|
375
|
+
// plan/34: reliable delivery — always write to the target's socket. The
|
|
376
|
+
// Pi harness enqueues messages that arrive mid-turn, so there is no
|
|
377
|
+
// busy-drop and `busy` is no longer a possible ACK status. Unicast sends
|
|
378
|
+
// to an online peer always ACK `received`.
|
|
379
|
+
let ackStatus = "none";
|
|
380
|
+
for (const targetName of targets) {
|
|
381
|
+
const peer = this.peers.get(targetName);
|
|
382
|
+
if (!peer)
|
|
383
|
+
continue; // unknown peer: silent drop (sender times out)
|
|
384
|
+
try {
|
|
385
|
+
peer.socket.write(line);
|
|
386
|
+
delivered.push(targetName);
|
|
387
|
+
if (isUnicast) {
|
|
388
|
+
ackStatus = "received";
|
|
389
|
+
this._sendAckToSender(env, "received", targetName);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
catch {
|
|
393
|
+
// peer dropped mid-write — close handler will fire; treat as silent
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
if (this.auditPath)
|
|
397
|
+
await this._appendAudit(env, delivered, ackStatus);
|
|
398
|
+
this.onRouted?.(env, delivered);
|
|
399
|
+
}
|
|
400
|
+
_resolveTargets(env) {
|
|
401
|
+
if (env.to === "broadcast") {
|
|
402
|
+
// plan/38 decision C: broadcast is scoped to the sender's cwd (folder
|
|
403
|
+
// colleagues), local-only. A peer in /a/b never hears /a/c. The sender is
|
|
404
|
+
// keyed by its address (= env.from); legacy peers (cwd "") broadcast among
|
|
405
|
+
// other cwd-less peers, matching pre-plan/38 behavior.
|
|
406
|
+
const sender = this.peers.get(env.from);
|
|
407
|
+
const scope = sender?.cwd ?? "";
|
|
408
|
+
return [...this.peers.values()]
|
|
409
|
+
.filter((p) => p.address !== env.from && p.cwd === scope)
|
|
410
|
+
.map((p) => p.address);
|
|
411
|
+
}
|
|
412
|
+
if (Array.isArray(env.to)) {
|
|
413
|
+
return env.to.filter((n) => n !== env.from);
|
|
414
|
+
}
|
|
415
|
+
// Unicast: drop self-loops too. The skill warns "useless" but the LLM
|
|
416
|
+
// might still try (especially with deceiving `re` reply chains). A
|
|
417
|
+
// self-loop has no upside and risks unbounded message ↔ inject ↔ message
|
|
418
|
+
// cycles when the inbound injector tells the LLM "reply with re=…".
|
|
419
|
+
if (env.to === env.from)
|
|
420
|
+
return [];
|
|
421
|
+
return [env.to];
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Writes an ACK envelope to the original sender's socket. Synchronous —
|
|
425
|
+
* the caller is inside `_route` and must keep busy-check/busy-set atomic.
|
|
426
|
+
* Broker → sender: `from="broker"`, `to=env.from`, `re=env.id`,
|
|
427
|
+
* `body={type:"ack", status, target}`.
|
|
428
|
+
*/
|
|
429
|
+
_sendAckToSender(env, status, target) {
|
|
430
|
+
const sender = this.peers.get(env.from);
|
|
431
|
+
if (!sender)
|
|
432
|
+
return; // sender vanished mid-write
|
|
433
|
+
const body = { type: "ack", status, target };
|
|
434
|
+
const ackEnv = {
|
|
435
|
+
from: BROKER_NAME,
|
|
436
|
+
to: env.from,
|
|
437
|
+
id: uuidv7(),
|
|
438
|
+
re: env.id,
|
|
439
|
+
body,
|
|
440
|
+
};
|
|
441
|
+
try {
|
|
442
|
+
sender.socket.write(serialize(ackEnv));
|
|
443
|
+
}
|
|
444
|
+
catch {
|
|
445
|
+
/* sender dropped; close handler will fire */
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
_handleBrokerMessage(env) {
|
|
449
|
+
const body = env.body;
|
|
450
|
+
if (!body || typeof body !== "object")
|
|
451
|
+
return;
|
|
452
|
+
if (body.type === "list_peers") {
|
|
453
|
+
const reply = {
|
|
454
|
+
from: BROKER_NAME,
|
|
455
|
+
to: env.from,
|
|
456
|
+
id: uuidv7(),
|
|
457
|
+
re: env.id,
|
|
458
|
+
body: {
|
|
459
|
+
type: "list_peers_reply",
|
|
460
|
+
peers: this._allPeerNames(), // addresses — legacy clients route by these
|
|
461
|
+
peers_detailed: this._allPeerInfos(), // plan/38 — clients group without parsing
|
|
462
|
+
},
|
|
463
|
+
};
|
|
464
|
+
const peer = this.peers.get(env.from);
|
|
465
|
+
if (peer) {
|
|
466
|
+
try {
|
|
467
|
+
peer.socket.write(serialize(reply));
|
|
468
|
+
}
|
|
469
|
+
catch {
|
|
470
|
+
/* ignored */
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
// plan/34: `turn_state` is no longer consumed — the broker doesn't gate
|
|
476
|
+
// delivery on busy state. The Pi extension still publishes working state
|
|
477
|
+
// as room_meta over the relay (index.ts), independent of the broker.
|
|
478
|
+
}
|
|
479
|
+
_broadcastSystem(body, excludeAddress) {
|
|
480
|
+
for (const [address, peer] of this.peers) {
|
|
481
|
+
if (address === excludeAddress)
|
|
482
|
+
continue;
|
|
483
|
+
const env = {
|
|
484
|
+
from: BROKER_NAME,
|
|
485
|
+
to: address,
|
|
486
|
+
id: uuidv7(),
|
|
487
|
+
re: null,
|
|
488
|
+
body,
|
|
489
|
+
};
|
|
490
|
+
try {
|
|
491
|
+
peer.socket.write(serialize(env));
|
|
492
|
+
}
|
|
493
|
+
catch {
|
|
494
|
+
/* ignored */
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
async _appendAudit(env, delivered, ackStatus,
|
|
499
|
+
/**
|
|
500
|
+
* Plan/25 Wave D: provenance hint for the audit reader. `"relay"` marks
|
|
501
|
+
* envelopes injected via `injectFromRemote` (cross-PC). Local UDS
|
|
502
|
+
* delivery keeps the default `"uds"` so existing audit consumers see
|
|
503
|
+
* a uniform field rather than an undefined hole.
|
|
504
|
+
*/
|
|
505
|
+
via = "uds") {
|
|
506
|
+
if (!this.auditPath)
|
|
507
|
+
return;
|
|
508
|
+
const line = JSON.stringify({
|
|
509
|
+
ts: Date.now(),
|
|
510
|
+
from: env.from,
|
|
511
|
+
to: env.to,
|
|
512
|
+
id: env.id,
|
|
513
|
+
re: env.re,
|
|
514
|
+
delivered,
|
|
515
|
+
ack_status: ackStatus,
|
|
516
|
+
via,
|
|
517
|
+
}) + "\n";
|
|
518
|
+
try {
|
|
519
|
+
await mkdir(dirname(this.auditPath), { recursive: true });
|
|
520
|
+
await appendFile(this.auditPath, line, "utf8");
|
|
521
|
+
}
|
|
522
|
+
catch {
|
|
523
|
+
/* audit best-effort */
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
//# sourceMappingURL=broker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broker.js","sourceRoot":"","sources":["../../src/session/broker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { Broker, PeerInfo, RemoteRouter } from "./broker.js";
|
|
2
|
+
import { type Envelope } from "./envelope.js";
|
|
3
|
+
import type { PiForwardClient } from "../transport/pi_forward_client.js";
|
|
4
|
+
import type { MeshTopologySnapshot } from "../mesh/siblings.js";
|
|
5
|
+
export interface WirePeerInfo {
|
|
6
|
+
cwd: string;
|
|
7
|
+
name: string;
|
|
8
|
+
address: string;
|
|
9
|
+
}
|
|
10
|
+
export interface RemotePeerEntry {
|
|
11
|
+
infos: WirePeerInfo[];
|
|
12
|
+
pcPubkey: string;
|
|
13
|
+
ts: number;
|
|
14
|
+
}
|
|
15
|
+
export interface BrokerRemoteOptions {
|
|
16
|
+
broker: Broker;
|
|
17
|
+
pi: PiForwardClient;
|
|
18
|
+
topology: MeshTopologySnapshot;
|
|
19
|
+
cacheTtlMs?: number;
|
|
20
|
+
reannounceIntervalMs?: number;
|
|
21
|
+
log?: (msg: string) => void;
|
|
22
|
+
/** Defaults true for compatibility; Task 6 bridge construction passes false. */
|
|
23
|
+
activateOnConstruct?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface BrokerRemoteLifecycle {
|
|
26
|
+
activate(): void;
|
|
27
|
+
setTopology(next: MeshTopologySnapshot): void;
|
|
28
|
+
}
|
|
29
|
+
export declare class BrokerRemote implements RemoteRouter, BrokerRemoteLifecycle {
|
|
30
|
+
private readonly broker;
|
|
31
|
+
private readonly pi;
|
|
32
|
+
private readonly technicalSelfPubkey;
|
|
33
|
+
private readonly cacheTtlMs;
|
|
34
|
+
private readonly reannounceIntervalMs;
|
|
35
|
+
private readonly log;
|
|
36
|
+
private routing;
|
|
37
|
+
/** Canonical sibling pubkey → cached local roster. */
|
|
38
|
+
private readonly remotePeers;
|
|
39
|
+
/** Canonical sibling pubkeys whose active topology refresh must be retried. */
|
|
40
|
+
private readonly topologyRefreshNeeded;
|
|
41
|
+
/** Canonical sibling pubkey → in-flight roster fills. */
|
|
42
|
+
private readonly pendingFills;
|
|
43
|
+
private readonly onIncoming;
|
|
44
|
+
private reannounceTimer;
|
|
45
|
+
private lifecycle;
|
|
46
|
+
constructor(opts: BrokerRemoteOptions);
|
|
47
|
+
activate(): void;
|
|
48
|
+
detach(): void;
|
|
49
|
+
setTopology(next: MeshTopologySnapshot): void;
|
|
50
|
+
private _bootstrapWithSiblings;
|
|
51
|
+
private _localPeersBody;
|
|
52
|
+
private _remoteInfosByPubkey;
|
|
53
|
+
getRemotePeers(pcLabel: string): string[];
|
|
54
|
+
getAllRemote(): Record<string, string[]>;
|
|
55
|
+
listRemotePeers(): string[];
|
|
56
|
+
listRemotePeerInfos(): PeerInfo[];
|
|
57
|
+
onLocalPeersChanged(_peers: string[]): void;
|
|
58
|
+
tryRouteOutbound(env: Envelope): boolean;
|
|
59
|
+
private _routeToCanonicalSibling;
|
|
60
|
+
handleIncoming(env: Envelope, fromPc: string): void;
|
|
61
|
+
private _setRemoteCache;
|
|
62
|
+
private _awaitPeersFill;
|
|
63
|
+
private _clearPendingFills;
|
|
64
|
+
private _clearAllPendingFills;
|
|
65
|
+
private _propagateTransportError;
|
|
66
|
+
private _sendControlEnvelope;
|
|
67
|
+
private _legacyLabelForPubkey;
|
|
68
|
+
private _dropMetadataOnly;
|
|
69
|
+
private _logMetadataOnly;
|
|
70
|
+
}
|
|
71
|
+
export declare function parseAddress(to: string): {
|
|
72
|
+
pcLabel: string;
|
|
73
|
+
peerName: string;
|
|
74
|
+
} | null;
|