remote-pi 0.1.2 → 0.2.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 (99) hide show
  1. package/README.md +195 -36
  2. package/dist/bin/supervisord.d.ts +2 -0
  3. package/dist/bin/supervisord.js +44 -0
  4. package/dist/bin/supervisord.js.map +1 -0
  5. package/dist/config.d.ts +49 -5
  6. package/dist/config.js +73 -9
  7. package/dist/config.js.map +1 -1
  8. package/dist/daemon/client.d.ts +20 -0
  9. package/dist/daemon/client.js +128 -0
  10. package/dist/daemon/client.js.map +1 -0
  11. package/dist/daemon/control_protocol.d.ts +100 -0
  12. package/dist/daemon/control_protocol.js +63 -0
  13. package/dist/daemon/control_protocol.js.map +1 -0
  14. package/dist/daemon/id.d.ts +18 -0
  15. package/dist/daemon/id.js +30 -0
  16. package/dist/daemon/id.js.map +1 -0
  17. package/dist/daemon/install.d.ts +132 -0
  18. package/dist/daemon/install.js +312 -0
  19. package/dist/daemon/install.js.map +1 -0
  20. package/dist/daemon/registry.d.ts +47 -0
  21. package/dist/daemon/registry.js +123 -0
  22. package/dist/daemon/registry.js.map +1 -0
  23. package/dist/daemon/rpc_child.d.ts +76 -0
  24. package/dist/daemon/rpc_child.js +130 -0
  25. package/dist/daemon/rpc_child.js.map +1 -0
  26. package/dist/daemon/supervisor.d.ts +38 -0
  27. package/dist/daemon/supervisor.js +301 -0
  28. package/dist/daemon/supervisor.js.map +1 -0
  29. package/dist/index.d.ts +62 -8
  30. package/dist/index.js +1232 -304
  31. package/dist/index.js.map +1 -1
  32. package/dist/mesh/canonical.d.ts +30 -0
  33. package/dist/mesh/canonical.js +61 -0
  34. package/dist/mesh/canonical.js.map +1 -0
  35. package/dist/mesh/client.d.ts +31 -0
  36. package/dist/mesh/client.js +56 -0
  37. package/dist/mesh/client.js.map +1 -0
  38. package/dist/mesh/encoding.d.ts +36 -0
  39. package/dist/mesh/encoding.js +53 -0
  40. package/dist/mesh/encoding.js.map +1 -0
  41. package/dist/mesh/self_revoke.d.ts +111 -0
  42. package/dist/mesh/self_revoke.js +182 -0
  43. package/dist/mesh/self_revoke.js.map +1 -0
  44. package/dist/mesh/siblings.d.ts +62 -0
  45. package/dist/mesh/siblings.js +95 -0
  46. package/dist/mesh/siblings.js.map +1 -0
  47. package/dist/mesh/types.d.ts +34 -0
  48. package/dist/mesh/types.js +11 -0
  49. package/dist/mesh/types.js.map +1 -0
  50. package/dist/mesh/verify.d.ts +17 -0
  51. package/dist/mesh/verify.js +77 -0
  52. package/dist/mesh/verify.js.map +1 -0
  53. package/dist/pairing/qr.d.ts +16 -5
  54. package/dist/pairing/qr.js +27 -8
  55. package/dist/pairing/qr.js.map +1 -1
  56. package/dist/pairing/storage.d.ts +41 -0
  57. package/dist/pairing/storage.js +158 -21
  58. package/dist/pairing/storage.js.map +1 -1
  59. package/dist/protocol/types.d.ts +23 -0
  60. package/dist/session/broker.d.ts +74 -0
  61. package/dist/session/broker.js +142 -4
  62. package/dist/session/broker.js.map +1 -1
  63. package/dist/session/broker_remote.d.ts +110 -0
  64. package/dist/session/broker_remote.js +397 -0
  65. package/dist/session/broker_remote.js.map +1 -0
  66. package/dist/session/cwd_lock.d.ts +28 -0
  67. package/dist/session/cwd_lock.js +89 -0
  68. package/dist/session/cwd_lock.js.map +1 -0
  69. package/dist/session/global_config.d.ts +9 -0
  70. package/dist/session/global_config.js +9 -0
  71. package/dist/session/global_config.js.map +1 -1
  72. package/dist/session/leader_election.d.ts +16 -0
  73. package/dist/session/leader_election.js +22 -0
  74. package/dist/session/leader_election.js.map +1 -1
  75. package/dist/session/local_config.d.ts +12 -5
  76. package/dist/session/local_config.js +24 -3
  77. package/dist/session/local_config.js.map +1 -1
  78. package/dist/session/peer.d.ts +28 -1
  79. package/dist/session/peer.js +69 -2
  80. package/dist/session/peer.js.map +1 -1
  81. package/dist/session/peer_inventory.d.ts +13 -0
  82. package/dist/session/peer_inventory.js +48 -0
  83. package/dist/session/peer_inventory.js.map +1 -0
  84. package/dist/session/setup_wizard.d.ts +32 -8
  85. package/dist/session/setup_wizard.js +45 -33
  86. package/dist/session/setup_wizard.js.map +1 -1
  87. package/dist/session/tools.d.ts +15 -7
  88. package/dist/session/tools.js +145 -31
  89. package/dist/session/tools.js.map +1 -1
  90. package/dist/transport/pi_forward_client.d.ts +29 -0
  91. package/dist/transport/pi_forward_client.js +62 -0
  92. package/dist/transport/pi_forward_client.js.map +1 -0
  93. package/dist/ui/footer.js +8 -6
  94. package/dist/ui/footer.js.map +1 -1
  95. package/docs/daemon.md +289 -0
  96. package/package.json +10 -3
  97. package/service-templates/launchd.plist.template +35 -0
  98. package/service-templates/systemd.service.template +19 -0
  99. package/skills/agent-network/SKILL.md +273 -294
@@ -0,0 +1,397 @@
1
+ import { envelope, uuidv7 } from "./envelope.js";
2
+ /**
3
+ * Plan/25 Wave B/C — cross-PC broker.
4
+ *
5
+ * Maintains a cache of `<pc_label> → { peers, pc_pubkey, ts }` populated
6
+ * by `peers_update` envelopes pushed from sibling Pis and refreshed lazily
7
+ * via `peers_request` on cache miss.
8
+ *
9
+ * Owns two halves of the protocol:
10
+ *
11
+ * - **Outbound** (`tryRouteOutbound`): broker hands off envelopes with a
12
+ * known `<pc>:` prefix. We rewrite `env.from` with our own pc_label,
13
+ * pack onto the relay via `pi_forward_client.sendEnvelopeToPi`.
14
+ *
15
+ * - **Inbound** (`handleIncoming`): `pi_forward_client` emits envelopes
16
+ * received from a verified `from_pc`. We:
17
+ * 1. Anti-spoof the `envelope.from` prefix against the sibling cache
18
+ * keyed by `from_pc` (defends against a Pi lying about its own
19
+ * `pc_label`).
20
+ * 2. Intercept control envelopes (`peers_update`, `peers_request`,
21
+ * `transport_error`) before any local UDS delivery.
22
+ * 3. Strip the `<pc>:` prefix from `env.to` and call
23
+ * `broker.injectFromRemote`. Build a one-way ACK envelope back via
24
+ * the relay so the cross-PC sender's `sendWithAck` resolves.
25
+ *
26
+ * The replies-bypass-busy rule from Wave 0 is honoured at injection time
27
+ * by the broker itself; `broker_remote` does not duplicate the check.
28
+ *
29
+ * Siblings (`Map<pc_label, pc_pubkey>`) are seeded externally by the
30
+ * extension at bootstrap (typically from `mesh_versions` of every paired
31
+ * Owner). Membership is the only thing we trust to ground anti-spoof —
32
+ * the cache of peers is just for routing UX.
33
+ */
34
+ const CACHE_TTL_MS = 5 * 60_000;
35
+ const PEERS_REQUEST_TIMEOUT_MS = 2_000;
36
+ const BROKER_NAME = "broker";
37
+ export class BrokerRemote {
38
+ broker;
39
+ pi;
40
+ selfPcLabel;
41
+ selfPcPubkey;
42
+ cacheTtlMs;
43
+ log;
44
+ /** Siblings: pc_label → pc_pubkey. Authoritative for anti-spoof. */
45
+ siblingByLabel = new Map();
46
+ /** Reverse index built from siblings: pc_pubkey → pc_label. */
47
+ siblingByPubkey = new Map();
48
+ /** Cache of peers per remote pc_label. */
49
+ remotePeers = new Map();
50
+ /** In-flight `peers_request` calls, keyed by pc_label. */
51
+ pendingFills = new Map();
52
+ /** Local peers (UDS) at the moment of last `onLocalPeersChanged` call. */
53
+ lastLocalPeers = [];
54
+ onIncoming;
55
+ detached = false;
56
+ constructor(opts) {
57
+ this.broker = opts.broker;
58
+ this.pi = opts.pi;
59
+ this.selfPcLabel = opts.selfPcLabel;
60
+ this.selfPcPubkey = opts.selfPcPubkey;
61
+ this.cacheTtlMs = opts.cacheTtlMs ?? CACHE_TTL_MS;
62
+ this.log = opts.log ?? ((msg) => console.error(msg));
63
+ for (const s of opts.siblings ?? [])
64
+ this._addSibling(s);
65
+ this.onIncoming = (env, fromPc) => this.handleIncoming(env, fromPc);
66
+ this.pi.on("envelope", this.onIncoming);
67
+ this.broker.setRemoteRouter(this);
68
+ // Seed `lastLocalPeers` from the live broker so the first
69
+ // `onLocalPeersChanged`-triggered push (or the bootstrap pushes below)
70
+ // already carry real state. Without seeding, the same single-peer
71
+ // mesh bug applies to OUTGOING `peers_update`s too: we'd announce
72
+ // ourselves to siblings as having zero peers.
73
+ this.lastLocalPeers = this.broker.peerNames();
74
+ // Plan/25 Wave B bootstrap: kick a `peers_request` at every known
75
+ // sibling so the cache is warm before anyone calls `list_peers` or
76
+ // `agent_send` cross-PC. Also push our current peer list proactively
77
+ // so siblings don't have to wait for their own request roundtrip.
78
+ // Best-effort; siblings offline at boot will reply when they come
79
+ // online and push their own `peers_update`.
80
+ this._bootstrapWithSiblings();
81
+ }
82
+ /** Bootstrap: announce ourselves AND ask every sibling for their peers.
83
+ * Single helper so `_addSibling` can reuse half of it when a new
84
+ * sibling appears via `setSiblings`. */
85
+ _bootstrapWithSiblings() {
86
+ for (const [, pcPubkey] of this.siblingByLabel) {
87
+ this._sendControlEnvelope(pcPubkey, { type: "peers_request" });
88
+ this._sendControlEnvelope(pcPubkey, {
89
+ type: "peers_update",
90
+ peers: this.lastLocalPeers,
91
+ });
92
+ }
93
+ }
94
+ detach() {
95
+ if (this.detached)
96
+ return;
97
+ this.detached = true;
98
+ this.pi.off("envelope", this.onIncoming);
99
+ this.broker.setRemoteRouter(null);
100
+ }
101
+ // ── Sibling management ────────────────────────────────────────────────────
102
+ /** Replace or extend the sibling set. Idempotent on identical input.
103
+ * Removes any sibling missing from `next`. Plan/25 Wave B bootstrap:
104
+ * fires `peers_request` at any sibling that wasn't in the previous
105
+ * set so the cache warms up without waiting for their next push. */
106
+ setSiblings(next) {
107
+ const prevPubkeys = new Set(this.siblingByPubkey.keys());
108
+ this.siblingByLabel.clear();
109
+ this.siblingByPubkey.clear();
110
+ for (const s of next)
111
+ this._addSibling(s);
112
+ // Drop cache entries for siblings that disappeared.
113
+ for (const label of [...this.remotePeers.keys()]) {
114
+ if (!this.siblingByLabel.has(label))
115
+ this.remotePeers.delete(label);
116
+ }
117
+ // For newly-added pubkeys: do the same announce+request pair the
118
+ // constructor does. Re-pinging siblings we already knew about would
119
+ // be wasteful (and triggers redundant audit lines on their side).
120
+ for (const [, pcPubkey] of this.siblingByLabel) {
121
+ if (prevPubkeys.has(pcPubkey))
122
+ continue;
123
+ this._sendControlEnvelope(pcPubkey, { type: "peers_request" });
124
+ this._sendControlEnvelope(pcPubkey, {
125
+ type: "peers_update",
126
+ peers: this.lastLocalPeers,
127
+ });
128
+ }
129
+ }
130
+ _addSibling(s) {
131
+ if (!s.pcLabel || !s.pcPubkey)
132
+ return;
133
+ if (s.pcLabel === this.selfPcLabel)
134
+ return; // never list self as sibling
135
+ if (s.pcPubkey === this.selfPcPubkey)
136
+ return;
137
+ this.siblingByLabel.set(s.pcLabel, s.pcPubkey);
138
+ this.siblingByPubkey.set(s.pcPubkey, s.pcLabel);
139
+ }
140
+ // ── Public cache API ──────────────────────────────────────────────────────
141
+ /** Returns the cached peer list for a remote pc_label, or [] when
142
+ * unknown / expired. */
143
+ getRemotePeers(pcLabel) {
144
+ const entry = this.remotePeers.get(pcLabel);
145
+ if (!entry)
146
+ return [];
147
+ if (Date.now() - entry.ts > this.cacheTtlMs)
148
+ return [];
149
+ return [...entry.peers];
150
+ }
151
+ /** Returns the full cross-PC inventory: pc_label → peers (TTL-respected). */
152
+ getAllRemote() {
153
+ const out = {};
154
+ for (const [label] of this.remotePeers) {
155
+ const peers = this.getRemotePeers(label);
156
+ if (peers.length > 0)
157
+ out[label] = peers;
158
+ }
159
+ return out;
160
+ }
161
+ /** Returns aggregated remote peer names (`<pc>:<peer>`) for the broker's
162
+ * `list_peers` reply. Skips siblings with no cache entry. */
163
+ listRemotePeers() {
164
+ const out = [];
165
+ for (const [label] of this.remotePeers) {
166
+ for (const peer of this.getRemotePeers(label)) {
167
+ out.push(`${label}:${peer}`);
168
+ }
169
+ }
170
+ return out;
171
+ }
172
+ // ── Push proativo ─────────────────────────────────────────────────────────
173
+ /**
174
+ * Called whenever the local UDS broker's peer set changes
175
+ * (peer_joined/peer_left). We push a `peers_update` envelope to every
176
+ * sibling so their caches stay fresh without polling.
177
+ */
178
+ onLocalPeersChanged(peers) {
179
+ this.lastLocalPeers = [...peers];
180
+ if (this.siblingByLabel.size === 0)
181
+ return;
182
+ const body = { type: "peers_update", peers: this.lastLocalPeers };
183
+ for (const [, pcPubkey] of this.siblingByLabel) {
184
+ this._sendControlEnvelope(pcPubkey, body);
185
+ }
186
+ }
187
+ // ── RemoteRouter ──────────────────────────────────────────────────────────
188
+ /**
189
+ * Broker hook (plan/25 Wave C). Inspect `env.to` for a `<pc>:` prefix:
190
+ *
191
+ * - no prefix or prefix == selfPcLabel → return false (broker delivers
192
+ * locally; if same-self prefix is present we DON'T strip it here —
193
+ * the local resolver will treat it as a literal name, which works
194
+ * because local names don't carry colons in practice)
195
+ * - prefix === known sibling label → rewrite `env.from`, pack onto the
196
+ * relay, return true. May trigger a lazy `peers_request` when the
197
+ * cache is empty (returns false on hard cache miss so the broker
198
+ * surfaces a transport_error path; we always optimistically send,
199
+ * and ACK timeout in the sender ends up reporting the failure).
200
+ * - prefix is not a known sibling label → return false (backward-compat
201
+ * for hypothetical local names containing `:`)
202
+ */
203
+ tryRouteOutbound(env) {
204
+ if (this.detached)
205
+ return false;
206
+ if (typeof env.to !== "string")
207
+ return false;
208
+ const parsed = parseAddress(env.to);
209
+ if (!parsed)
210
+ return false;
211
+ const { pcLabel } = parsed;
212
+ if (pcLabel === this.selfPcLabel)
213
+ return false; // same-PC: local handles
214
+ const siblingPk = this.siblingByLabel.get(pcLabel);
215
+ if (!siblingPk)
216
+ return false; // unknown prefix → fall through
217
+ // We have a destination PC. Rewrite `from` with our own pc_label.
218
+ const rewritten = {
219
+ ...env,
220
+ from: `${this.selfPcLabel}:${env.from}`,
221
+ };
222
+ // Optimistic send. If the recipient's cache doesn't list our target
223
+ // yet, the recipient's wrapper still injects (the broker just decides
224
+ // received/busy/denied on actual local UDS state). A simultaneous
225
+ // `peers_request` warms the cache for next time.
226
+ this.pi.sendEnvelopeToPi(siblingPk, rewritten);
227
+ if (this.remotePeers.get(pcLabel) === undefined) {
228
+ this._sendControlEnvelope(siblingPk, { type: "peers_request" });
229
+ void this._awaitPeersFill(pcLabel, PEERS_REQUEST_TIMEOUT_MS);
230
+ }
231
+ return true;
232
+ }
233
+ // ── Inbound ───────────────────────────────────────────────────────────────
234
+ /**
235
+ * Entry point for envelopes the relay forwards to us. Receives the
236
+ * envelope verbatim plus the verified `from_pc` (Pi-pubkey of the
237
+ * sender, authoritative — relay-checked).
238
+ */
239
+ handleIncoming(env, fromPc) {
240
+ // ── transport_error from relay ─────────────────────────────────────────
241
+ // The relay synthesises these with `from_pc = "_relay"` and
242
+ // `envelope.from = "_relay"`. Inject locally as a system envelope
243
+ // addressed to the original sender (env.to is the original sender's
244
+ // prefixed address; strip the prefix and deliver via UDS).
245
+ if (fromPc === "_relay") {
246
+ this._propagateTransportError(env);
247
+ return;
248
+ }
249
+ // ── anti-spoof ─────────────────────────────────────────────────────────
250
+ const claimedLabel = this.siblingByPubkey.get(fromPc);
251
+ if (!claimedLabel) {
252
+ this.log(`[broker_remote] drop: from_pc ${fromPc.slice(0, 12)}… not in sibling cache`);
253
+ return;
254
+ }
255
+ if (typeof env.from === "string") {
256
+ const fromPrefix = env.from.split(":", 1)[0];
257
+ if (fromPrefix !== claimedLabel) {
258
+ this.log(`[broker_remote] drop: envelope.from "${env.from}" prefix ` +
259
+ `mismatches sibling label "${claimedLabel}"`);
260
+ return;
261
+ }
262
+ }
263
+ const body = env.body;
264
+ const bodyType = body && typeof body === "object" ? body.type : undefined;
265
+ // ── control: peers_update ──────────────────────────────────────────────
266
+ if (bodyType === "peers_update") {
267
+ const peers = Array.isArray(body.peers)
268
+ ? body.peers.filter((p) => typeof p === "string")
269
+ : [];
270
+ this._setRemoteCache(claimedLabel, fromPc, peers);
271
+ return;
272
+ }
273
+ // ── control: peers_request ─────────────────────────────────────────────
274
+ if (bodyType === "peers_request") {
275
+ // Always query the broker directly for the current peer list. We
276
+ // can't rely on `lastLocalPeers` because that cache is fed by the
277
+ // `peer_joined`/`peer_left` broadcast in index.ts — and the broker
278
+ // never delivers a `peer_joined` to the peer that just joined (see
279
+ // `_broadcastSystem(..., excludeName=assigned)`). In a single-peer
280
+ // mesh, no event ever fires → `lastLocalPeers` stays `[]` →
281
+ // siblings see us as "no peers" → cache populates empty → cross-PC
282
+ // `list_peers` misses us. Querying broker.peerNames() resolves
283
+ // sync (Map keys), so this is essentially free.
284
+ const currentLocal = this.broker.peerNames();
285
+ this._sendControlEnvelope(fromPc, {
286
+ type: "peers_update",
287
+ peers: currentLocal,
288
+ });
289
+ return;
290
+ }
291
+ // ── control: ack ───────────────────────────────────────────────────────
292
+ // ACK envelopes from a remote wrapper are addressed to our local
293
+ // sender. Strip prefix from `to` and inject so the sender's
294
+ // `sendWithAck` pending resolves. ACK envelopes carry `re` (always)
295
+ // and bypass busy via the `isReply` rule in `injectFromRemote`.
296
+ // (No special-casing needed — generic injection below covers them.)
297
+ // ── regular envelope: strip `to` prefix and inject ─────────────────────
298
+ if (typeof env.to !== "string") {
299
+ this.log("[broker_remote] drop: cross-PC envelope must be unicast string");
300
+ return;
301
+ }
302
+ const toParsed = parseAddress(env.to);
303
+ let injectedEnv = env;
304
+ if (toParsed && toParsed.pcLabel === this.selfPcLabel) {
305
+ injectedEnv = { ...env, to: toParsed.peerName };
306
+ }
307
+ else if (toParsed) {
308
+ // `to` carries a third-party prefix — not for us. Drop.
309
+ this.log(`[broker_remote] drop: envelope.to "${env.to}" not addressed to ` +
310
+ `selfPcLabel "${this.selfPcLabel}"`);
311
+ return;
312
+ }
313
+ const status = this.broker.injectFromRemote(injectedEnv);
314
+ // Only generate an ACK for non-ACK envelopes — otherwise we'd loop
315
+ // ACKing the ACK. Detect by body shape.
316
+ if (bodyType === "ack")
317
+ return;
318
+ // Forward an ACK envelope back to fromPc. The cross-PC sender's
319
+ // `sendWithAck` correlates by `re = env.id`.
320
+ const ackBody = { type: "ack", status, target: injectedEnv.to };
321
+ const ackEnv = {
322
+ from: `${this.selfPcLabel}:${BROKER_NAME}`,
323
+ to: env.from,
324
+ id: uuidv7(),
325
+ re: env.id,
326
+ body: ackBody,
327
+ };
328
+ this.pi.sendEnvelopeToPi(fromPc, ackEnv);
329
+ }
330
+ // ── Internals ─────────────────────────────────────────────────────────────
331
+ _setRemoteCache(pcLabel, pcPubkey, peers) {
332
+ this.remotePeers.set(pcLabel, { peers, pcPubkey, ts: Date.now() });
333
+ // Resolve any pending `peers_request` waiters for this label.
334
+ const pending = this.pendingFills.get(pcLabel);
335
+ if (pending) {
336
+ for (const slot of pending) {
337
+ clearTimeout(slot.timer);
338
+ slot.resolve();
339
+ }
340
+ this.pendingFills.delete(pcLabel);
341
+ }
342
+ }
343
+ _awaitPeersFill(pcLabel, timeoutMs) {
344
+ return new Promise((resolve) => {
345
+ const slot = {
346
+ resolve,
347
+ timer: setTimeout(() => {
348
+ const set = this.pendingFills.get(pcLabel);
349
+ set?.delete(slot);
350
+ resolve();
351
+ }, timeoutMs),
352
+ };
353
+ const set = this.pendingFills.get(pcLabel) ?? new Set();
354
+ set.add(slot);
355
+ this.pendingFills.set(pcLabel, set);
356
+ });
357
+ }
358
+ _propagateTransportError(env) {
359
+ // Strip prefix from to (if any) and deliver to the local sender by
360
+ // injecting the envelope into the broker. Per plan/25 spec the
361
+ // wrapper's `sendWithAck` will see this as a body with
362
+ // `type:"transport_error"` correlated by `re`. The ackPending matcher
363
+ // only resolves for body.type === "ack", so transport_error envelopes
364
+ // fall through to handlers — which is what we want (sender's pending
365
+ // map times out, then handler dispatches inbox notification).
366
+ if (typeof env.to !== "string")
367
+ return;
368
+ const parsed = parseAddress(env.to);
369
+ const injected = parsed && parsed.pcLabel === this.selfPcLabel
370
+ ? { ...env, to: parsed.peerName }
371
+ : env;
372
+ this.broker.injectFromRemote(injected);
373
+ }
374
+ _sendControlEnvelope(toPc, body) {
375
+ const env = envelope(`${this.selfPcLabel}:_broker_remote`, `${this._labelForPubkey(toPc) ?? "?"}:_broker_remote`, body, null);
376
+ this.pi.sendEnvelopeToPi(toPc, env);
377
+ }
378
+ _labelForPubkey(pcPubkey) {
379
+ return this.siblingByPubkey.get(pcPubkey);
380
+ }
381
+ }
382
+ // ── Helpers ──────────────────────────────────────────────────────────────────
383
+ /**
384
+ * Parse a `<pc>:<peer>` address. Returns null when the input doesn't
385
+ * carry a `:`. Note: callers are responsible for deciding whether the
386
+ * parsed `pcLabel` is meaningful (i.e., matches selfPcLabel or a known
387
+ * sibling); a non-null return here does NOT imply the address is remote.
388
+ * The broker's prefix routing uses this — local names containing literal
389
+ * `:` continue working as long as no sibling carries the same prefix.
390
+ */
391
+ export function parseAddress(to) {
392
+ const idx = to.indexOf(":");
393
+ if (idx <= 0 || idx === to.length - 1)
394
+ return null;
395
+ return { pcLabel: to.slice(0, idx), peerName: to.slice(idx + 1) };
396
+ }
397
+ //# sourceMappingURL=broker_remote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"broker_remote.js","sourceRoot":"","sources":["../../src/session/broker_remote.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ export interface AcquiredLock {
2
+ ok: true;
3
+ /** Manual release. Optional — process exit cleans up too. */
4
+ release(): void;
5
+ }
6
+ export interface RefusedLock {
7
+ ok: false;
8
+ /** Where the live lock socket lives, in case the caller wants to log it. */
9
+ lockPath: string;
10
+ }
11
+ export type CwdLockResult = AcquiredLock | RefusedLock;
12
+ /** Path of the lock socket for a given cwd. Pure helper (no IO). */
13
+ export declare function lockPathForCwd(cwd: string): string;
14
+ /**
15
+ * Attempts to acquire the cwd lock. Resolves with either:
16
+ * - `{ ok: true, release }` when we own it (server bound + retained).
17
+ * - `{ ok: false, lockPath }` when a live Pi already holds the lock.
18
+ *
19
+ * Self-healing path: if the prior holder crashed, the leftover socket file
20
+ * fails `tryConnect` (ECONNREFUSED). We unlink it and retry the bind — the
21
+ * second attempt then succeeds.
22
+ *
23
+ * The server holds no actual listener logic; its only job is to keep the
24
+ * UDS endpoint pinned by the OS. No incoming connection ever does anything
25
+ * useful — the next-Pi-attempt's `tryConnect` succeeding is the entire
26
+ * signal we care about.
27
+ */
28
+ export declare function acquireCwdLock(cwd: string): Promise<CwdLockResult>;
@@ -0,0 +1,89 @@
1
+ import { mkdirSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { dirname, join } from "node:path";
4
+ import { roomIdForCwd } from "../rooms.js";
5
+ import { removeStaleSock, tryBind, tryConnect } from "./leader_election.js";
6
+ /**
7
+ * Per-cwd singleton lock for `/remote-pi`. At most one Pi process per
8
+ * working directory may hold the lock; the second attempt is refused.
9
+ *
10
+ * Why a UDS bind instead of a PID lock file:
11
+ * - The OS releases the socket handle the instant the process dies, even
12
+ * on `kill -9` or hard crash. No stale-lock cleanup needed.
13
+ * - The next Pi to try in the same cwd detects the dead socket via
14
+ * `ECONNREFUSED` on `tryConnect`, unlinks the leftover file, and
15
+ * binds successfully. Fully self-healing.
16
+ * - Kernel-enforced — there is no race window between "check if held"
17
+ * and "claim", which an explicit PID file would have.
18
+ *
19
+ * Lock files live in `~/.pi/remote/locks/<roomId>.sock` (where `roomId` is
20
+ * `sha256(realpath(cwd))[:12]`), NOT inside the cwd itself, to dodge:
21
+ * - The 104/108-char path-length limit on UDS sockets on macOS/Linux.
22
+ * - Symlinked cwds (realpath canonicalization happens in `roomIdForCwd`).
23
+ * - Read-only cwds (the home directory is always writable).
24
+ *
25
+ * Caller workflow:
26
+ * const lock = await acquireCwdLock(cwd);
27
+ * if (!lock.ok) { ui.notify("Já tem um agente rodando nessa pasta."); return; }
28
+ * // …run /remote-pi normally; lock auto-releases on process exit
29
+ */
30
+ const LOCKS_DIR = join(homedir(), ".pi", "remote", "locks");
31
+ /** Path of the lock socket for a given cwd. Pure helper (no IO). */
32
+ export function lockPathForCwd(cwd) {
33
+ return join(LOCKS_DIR, `${roomIdForCwd(cwd)}.sock`);
34
+ }
35
+ /**
36
+ * Attempts to acquire the cwd lock. Resolves with either:
37
+ * - `{ ok: true, release }` when we own it (server bound + retained).
38
+ * - `{ ok: false, lockPath }` when a live Pi already holds the lock.
39
+ *
40
+ * Self-healing path: if the prior holder crashed, the leftover socket file
41
+ * fails `tryConnect` (ECONNREFUSED). We unlink it and retry the bind — the
42
+ * second attempt then succeeds.
43
+ *
44
+ * The server holds no actual listener logic; its only job is to keep the
45
+ * UDS endpoint pinned by the OS. No incoming connection ever does anything
46
+ * useful — the next-Pi-attempt's `tryConnect` succeeding is the entire
47
+ * signal we care about.
48
+ */
49
+ export async function acquireCwdLock(cwd) {
50
+ const lockPath = lockPathForCwd(cwd);
51
+ mkdirSync(dirname(lockPath), { recursive: true });
52
+ // First attempt: bind directly.
53
+ let server = await tryBind(lockPath);
54
+ if (server)
55
+ return _acquired(server, lockPath);
56
+ // Bind failed — check whether the existing socket has a live listener.
57
+ const probe = await tryConnect(lockPath);
58
+ if (probe) {
59
+ probe.destroy();
60
+ return { ok: false, lockPath };
61
+ }
62
+ // Socket is stale (no listener answered). Clean up + retry bind once.
63
+ removeStaleSock(lockPath);
64
+ server = await tryBind(lockPath);
65
+ if (server)
66
+ return _acquired(server, lockPath);
67
+ // Race: someone else bound between our unlink and retry. Treat as held.
68
+ return { ok: false, lockPath };
69
+ }
70
+ function _acquired(server, _lockPath) {
71
+ let released = false;
72
+ // Don't keep the event loop alive just to hold the socket — the Pi
73
+ // process has its own reasons to stay up (relay WS, broker, etc.).
74
+ // When those are gone, the OS will tear the socket down with us.
75
+ server.unref();
76
+ return {
77
+ ok: true,
78
+ release: () => {
79
+ if (released)
80
+ return;
81
+ released = true;
82
+ try {
83
+ server.close();
84
+ }
85
+ catch { /* ignored */ }
86
+ },
87
+ };
88
+ }
89
+ //# sourceMappingURL=cwd_lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cwd_lock.js","sourceRoot":"","sources":["../../src/session/cwd_lock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAE5E;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;AAgB5D,oEAAoE;AACpE,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,OAAO,IAAI,CAAC,SAAS,EAAE,GAAG,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACtD,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,GAAW;IAC9C,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACrC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAElD,gCAAgC;IAChC,IAAI,MAAM,GAAkB,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpD,IAAI,MAAM;QAAE,OAAO,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAE/C,uEAAuE;IACvE,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,KAAK,EAAE,CAAC;QACV,KAAK,CAAC,OAAO,EAAE,CAAC;QAChB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;IACjC,CAAC;IAED,sEAAsE;IACtE,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC1B,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjC,IAAI,MAAM;QAAE,OAAO,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAE/C,wEAAwE;IACxE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AACjC,CAAC;AAED,SAAS,SAAS,CAAC,MAAc,EAAE,SAAiB;IAClD,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,mEAAmE;IACnE,mEAAmE;IACnE,iEAAiE;IACjE,MAAM,CAAC,KAAK,EAAE,CAAC;IACf,OAAO;QACL,EAAE,EAAE,IAAI;QACR,OAAO,EAAE,GAAG,EAAE;YACZ,IAAI,QAAQ;gBAAE,OAAO;YACrB,QAAQ,GAAG,IAAI,CAAC;YAChB,IAAI,CAAC;gBAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,aAAa,CAAC,CAAC;QACjD,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -1,3 +1,12 @@
1
+ /**
2
+ * Fixed UDS session name. The local mesh is single per machine — every Pi
3
+ * process on the host shares this broker. Previous versions exposed
4
+ * multi-session support (named sessions, leave/rename/sessions commands);
5
+ * those were removed in the 2026-05-23 simplification because in practice
6
+ * every install converged on one session anyway and multi-session UX added
7
+ * friction without value.
8
+ */
9
+ export declare const LOCAL_SESSION_NAME = "local";
1
10
  /** Ensures the new subdirs exist inside the existing ~/.pi/remote/. */
2
11
  export declare function ensureGlobalDirs(): void;
3
12
  /** Path to the UDS socket for a named session. */
@@ -4,6 +4,15 @@ import { join } from "node:path";
4
4
  const HOME_PI_REMOTE = join(homedir(), ".pi", "remote");
5
5
  const SESSIONS_DIR = join(HOME_PI_REMOTE, "sessions");
6
6
  const SKILLS_DIR = join(HOME_PI_REMOTE, "skills");
7
+ /**
8
+ * Fixed UDS session name. The local mesh is single per machine — every Pi
9
+ * process on the host shares this broker. Previous versions exposed
10
+ * multi-session support (named sessions, leave/rename/sessions commands);
11
+ * those were removed in the 2026-05-23 simplification because in practice
12
+ * every install converged on one session anyway and multi-session UX added
13
+ * friction without value.
14
+ */
15
+ export const LOCAL_SESSION_NAME = "local";
7
16
  /** Ensures the new subdirs exist inside the existing ~/.pi/remote/. */
8
17
  export function ensureGlobalDirs() {
9
18
  mkdirSync(SESSIONS_DIR, { recursive: true });
@@ -1 +1 @@
1
- {"version":3,"file":"global_config.js","sourceRoot":"","sources":["../../src/session/global_config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACvE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;AACxD,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;AACtD,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;AAElD,uEAAuE;AACvE,MAAM,UAAU,gBAAgB;IAC9B,SAAS,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC7C,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;AACjD,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;AACjD,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,YAAY;IAC1B,gBAAgB,EAAE,CAAC;IACnB,IAAI,CAAC;QACH,OAAO,WAAW,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YAChD,IAAI,CAAC;gBACH,OAAO,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;YAC3D,CAAC;YAAC,MAAM,CAAC;gBAAC,OAAO,KAAK,CAAC;YAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,UAAU,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3C,CAAC"}
1
+ {"version":3,"file":"global_config.js","sourceRoot":"","sources":["../../src/session/global_config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACvE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;AACxD,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;AACtD,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;AAElD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAO,CAAC;AAE1C,uEAAuE;AACvE,MAAM,UAAU,gBAAgB;IAC9B,SAAS,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC7C,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;AACjD,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;AACjD,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,YAAY;IAC1B,gBAAgB,EAAE,CAAC;IACnB,IAAI,CAAC;QACH,OAAO,WAAW,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YAChD,IAAI,CAAC;gBACH,OAAO,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;YAC3D,CAAC;YAAC,MAAM,CAAC;gBAAC,OAAO,KAAK,CAAC;YAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,UAAU,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3C,CAAC"}
@@ -14,3 +14,19 @@ export type ElectionResult = {
14
14
  * Returns the role + the live handle (server for leader, socket for follower).
15
15
  */
16
16
  export declare function joinOrLead(sockPath: string): Promise<ElectionResult>;
17
+ /**
18
+ * Probes a UDS path: if a live listener responds, returns the connected
19
+ * socket; otherwise returns null (timeout or ECONNREFUSED). Exported so
20
+ * the cwd-lock primitive can reuse it without duplicating the OS dance.
21
+ */
22
+ export declare function tryConnect(sockPath: string): Promise<Socket | null>;
23
+ /**
24
+ * Attempts to bind a UDS server on `sockPath`. Returns the live server on
25
+ * success, null when the path is already held (EADDRINUSE) or any other
26
+ * bind error. Caller is responsible for `unlink`ing a stale sock file
27
+ * before retrying.
28
+ */
29
+ export declare function tryBind(sockPath: string): Promise<Server | null>;
30
+ /** Unlinks the sock file if it exists and is actually a socket. No-op
31
+ * otherwise. Used to clear stale sockets left behind by a crashed peer. */
32
+ export declare function removeStaleSock(sockPath: string): void;
@@ -27,6 +27,28 @@ export async function joinOrLead(sockPath) {
27
27
  }
28
28
  throw new Error(`leader election failed after ${MAX_ATTEMPTS} attempts: ${sockPath}`);
29
29
  }
30
+ /**
31
+ * Probes a UDS path: if a live listener responds, returns the connected
32
+ * socket; otherwise returns null (timeout or ECONNREFUSED). Exported so
33
+ * the cwd-lock primitive can reuse it without duplicating the OS dance.
34
+ */
35
+ export function tryConnect(sockPath) {
36
+ return _tryConnect(sockPath);
37
+ }
38
+ /**
39
+ * Attempts to bind a UDS server on `sockPath`. Returns the live server on
40
+ * success, null when the path is already held (EADDRINUSE) or any other
41
+ * bind error. Caller is responsible for `unlink`ing a stale sock file
42
+ * before retrying.
43
+ */
44
+ export function tryBind(sockPath) {
45
+ return _tryBind(sockPath);
46
+ }
47
+ /** Unlinks the sock file if it exists and is actually a socket. No-op
48
+ * otherwise. Used to clear stale sockets left behind by a crashed peer. */
49
+ export function removeStaleSock(sockPath) {
50
+ _removeStaleSock(sockPath);
51
+ }
30
52
  function _tryConnect(sockPath) {
31
53
  return new Promise((resolve) => {
32
54
  const sock = createConnection({ path: sockPath });
@@ -1 +1 @@
1
- {"version":3,"file":"leader_election.js","sourceRoot":"","sources":["../../src/session/leader_election.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"leader_election.js","sourceRoot":"","sources":["../../src/session/leader_election.ts"],"names":[],"mappings":"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"}