@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,139 @@
|
|
|
1
|
+
import { type Envelope, type TransportErrorReason } from "./envelope.js";
|
|
2
|
+
import { Broker } from "./broker.js";
|
|
3
|
+
/**
|
|
4
|
+
* Symmetric peer-in-session API. Hides whether you are leader or follower;
|
|
5
|
+
* `send`, `request`, `onMessage`, `rename`, `leave` all work the same.
|
|
6
|
+
*
|
|
7
|
+
* Pending map demuxes parallel `request()` calls by message `id` → `re`.
|
|
8
|
+
*
|
|
9
|
+
* Failover: when the leader dies, follower socket emits `close`. Remaining
|
|
10
|
+
* peers re-run `joinOrLead`. One becomes the new leader; others reconnect.
|
|
11
|
+
*/
|
|
12
|
+
export type MessageHandler = (env: Envelope) => void;
|
|
13
|
+
export type ReconnectHandler = () => void;
|
|
14
|
+
export interface SessionPeerOptions {
|
|
15
|
+
sockPath: string;
|
|
16
|
+
name: string;
|
|
17
|
+
/**
|
|
18
|
+
* Working directory of this agent. Sent in the `register` so the broker can
|
|
19
|
+
* key peers by the (cwd, name) pair: two agents in the SAME folder with the
|
|
20
|
+
* same name are the SAME logical agent reincarnating (switch_session /
|
|
21
|
+
* restart), so the broker take-over the name instead of suffixing `#N`.
|
|
22
|
+
* Optional for backward-compat with peers that predate this field.
|
|
23
|
+
*/
|
|
24
|
+
cwd?: string;
|
|
25
|
+
/** Replace an existing same-(cwd,name) registration instead of accepting a
|
|
26
|
+
* broker-assigned `#N`. Use only for stable logical identities; ordinary
|
|
27
|
+
* multi-agent sessions should leave this false. */
|
|
28
|
+
takeoverExisting?: boolean;
|
|
29
|
+
auditPath?: string;
|
|
30
|
+
/** Per-request default timeout (ms). Override per call if needed. */
|
|
31
|
+
defaultTimeoutMs?: number;
|
|
32
|
+
}
|
|
33
|
+
export type AckStatus = "received" | "busy" | "denied" | "timeout";
|
|
34
|
+
export interface AckResult {
|
|
35
|
+
status: AckStatus;
|
|
36
|
+
/** The original envelope id that was awaiting ACK. */
|
|
37
|
+
id: string;
|
|
38
|
+
/** Target name reported by broker (when ACK arrived). Undefined on timeout. */
|
|
39
|
+
target?: string;
|
|
40
|
+
error?: `transport_error: ${TransportErrorReason}`;
|
|
41
|
+
reason?: TransportErrorReason;
|
|
42
|
+
}
|
|
43
|
+
export declare class MeshTransportError extends Error {
|
|
44
|
+
readonly reason: TransportErrorReason;
|
|
45
|
+
readonly correlationId: string;
|
|
46
|
+
constructor(reason: TransportErrorReason, correlationId: string);
|
|
47
|
+
}
|
|
48
|
+
export declare class SessionPeer {
|
|
49
|
+
private readonly opts;
|
|
50
|
+
/** Clean leaf name actually assigned by the broker (may carry a `#N`
|
|
51
|
+
* collision suffix). Used for display + self-filtering. */
|
|
52
|
+
private assignedName;
|
|
53
|
+
/** Canonical address assigned by the broker (`[<pc>:]<cwd>@<nome>`, or just
|
|
54
|
+
* the name for a legacy broker). This is the routing/identity key the mesh
|
|
55
|
+
* uses; callers ECHO it, never compose it. */
|
|
56
|
+
private assignedAddress;
|
|
57
|
+
private role;
|
|
58
|
+
private broker;
|
|
59
|
+
private socket;
|
|
60
|
+
private buf;
|
|
61
|
+
/** Map of in-flight request ids → resolver. Used by `request()`. */
|
|
62
|
+
private readonly pending;
|
|
63
|
+
/** Map of in-flight send ids → ACK resolver. Used by `sendWithAck()`. */
|
|
64
|
+
private readonly ackPending;
|
|
65
|
+
private readonly handlers;
|
|
66
|
+
private readonly reconnectHandlers;
|
|
67
|
+
private leftFlag;
|
|
68
|
+
constructor(opts: SessionPeerOptions);
|
|
69
|
+
/** Joins or leads the session at `sockPath`. Resolves with the assigned name. */
|
|
70
|
+
start(): Promise<string>;
|
|
71
|
+
/** Returns the clean leaf name as assigned by the broker (after any `#N`). */
|
|
72
|
+
name(): string;
|
|
73
|
+
/** Returns the canonical address (`[<pc>:]<cwd>@<nome>`) assigned by the
|
|
74
|
+
* broker — the key the mesh routes on. Equals `name()` against a legacy
|
|
75
|
+
* broker that returns no address. */
|
|
76
|
+
address(): string;
|
|
77
|
+
/** Returns "leader" or "follower" — current role. */
|
|
78
|
+
currentRole(): "leader" | "follower";
|
|
79
|
+
/** Returns the locally-hosted Broker when this peer is the leader, or
|
|
80
|
+
* null when it's a follower. Wave 25C uses this to attach the
|
|
81
|
+
* cross-PC router. */
|
|
82
|
+
localBroker(): Broker | null;
|
|
83
|
+
/**
|
|
84
|
+
* Fire-and-forget send. Doesn't await a reply.
|
|
85
|
+
*
|
|
86
|
+
* `re` (optional) lets the caller correlate this message as a reply to a
|
|
87
|
+
* previous request — when an LLM peer is *answering* a question from
|
|
88
|
+
* another agent, it must echo the original `id` here so the requester's
|
|
89
|
+
* pending map can resolve. Without `re`, the requester treats this as a
|
|
90
|
+
* new unsolicited message and its `request()` call times out.
|
|
91
|
+
*/
|
|
92
|
+
send(to: string | string[], body: unknown, re?: string | null): Promise<void>;
|
|
93
|
+
/**
|
|
94
|
+
* Unicast send + await broker ACK. Returns the ACK status:
|
|
95
|
+
* - `received` — peer was idle, envelope delivered, will be processed soon
|
|
96
|
+
* - `busy` — peer mid-turn, envelope dropped; sender is owner of retry
|
|
97
|
+
* - `denied` — broker/Relay refused delivery (including authorization or envelope failure)
|
|
98
|
+
* - `timeout` — no ACK within `timeoutMs`, or trusted Relay says offline
|
|
99
|
+
*
|
|
100
|
+
* Only meaningful for unicast non-broadcast addresses. The peer's body-level
|
|
101
|
+
* reply (if any) is asynchronous and arrives as a normal inbound envelope
|
|
102
|
+
* carrying `re=<this-send-id>` in a future turn — handled by `onMessage`.
|
|
103
|
+
*/
|
|
104
|
+
sendWithAck(to: string, body: unknown, re?: string | null, timeoutMs?: number): Promise<AckResult>;
|
|
105
|
+
/**
|
|
106
|
+
* Send + await reply. Resolves with the first inbound envelope whose `re`
|
|
107
|
+
* matches the outbound `id`. Rejects on timeout, teardown/write failure, or
|
|
108
|
+
* a trusted Relay transport error.
|
|
109
|
+
*/
|
|
110
|
+
request(to: string, body: unknown, timeoutMs?: number): Promise<Envelope>;
|
|
111
|
+
onMessage(handler: MessageHandler): () => void;
|
|
112
|
+
/**
|
|
113
|
+
* Fires after the peer successfully (re)joins following a failover —
|
|
114
|
+
* leader died and we re-elected. NOT called for the initial `start()`,
|
|
115
|
+
* only for post-drop reconnects. Consumers use this to re-query state
|
|
116
|
+
* the broker may have lost in the transition (e.g., peer list).
|
|
117
|
+
*/
|
|
118
|
+
onReconnect(handler: ReconnectHandler): () => void;
|
|
119
|
+
/**
|
|
120
|
+
* Requests a different display name from the broker. Returns the name
|
|
121
|
+
* actually assigned (may carry a #N suffix on collision). Implemented as
|
|
122
|
+
* a soft rejoin: leaves & rejoins with the new name.
|
|
123
|
+
*/
|
|
124
|
+
rename(newName: string): Promise<string>;
|
|
125
|
+
leave(): Promise<void>;
|
|
126
|
+
private _joinOrLead;
|
|
127
|
+
private _registerAsClient;
|
|
128
|
+
private _wireSocket;
|
|
129
|
+
private _registerOver;
|
|
130
|
+
private _preAckListener;
|
|
131
|
+
private _onData;
|
|
132
|
+
private _handleLine;
|
|
133
|
+
private _consumeAckTransportError;
|
|
134
|
+
private _rejectRequestTransportError;
|
|
135
|
+
private _dispatchToHandlers;
|
|
136
|
+
private _writeEnvelope;
|
|
137
|
+
private _onSocketClose;
|
|
138
|
+
private _teardownConn;
|
|
139
|
+
}
|
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
2
|
+
import { asTransportErrorBody, envelope, hasTransportErrorType, parse, serialize, EnvelopeError, } from "./envelope.js";
|
|
3
|
+
import { joinOrLead } from "./leader_election.js";
|
|
4
|
+
import { Broker } from "./broker.js";
|
|
5
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
6
|
+
const ACK_TIMEOUT_MS = 5_000;
|
|
7
|
+
const FAILOVER_RETRY_MS = 100;
|
|
8
|
+
export class MeshTransportError extends Error {
|
|
9
|
+
reason;
|
|
10
|
+
correlationId;
|
|
11
|
+
constructor(reason, correlationId) {
|
|
12
|
+
super(`transport_error: ${reason}`);
|
|
13
|
+
this.reason = reason;
|
|
14
|
+
this.correlationId = correlationId;
|
|
15
|
+
this.name = "MeshTransportError";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function hasExactAckType(body) {
|
|
19
|
+
return (typeof body === "object" &&
|
|
20
|
+
body !== null &&
|
|
21
|
+
Object.hasOwn(body, "type") &&
|
|
22
|
+
body.type === "ack");
|
|
23
|
+
}
|
|
24
|
+
function expectedAckSender(destination) {
|
|
25
|
+
// Local absolute paths may contain colons; only non-path aliases are remote.
|
|
26
|
+
if (destination === "" ||
|
|
27
|
+
!destination.includes(":") ||
|
|
28
|
+
destination.startsWith("/") ||
|
|
29
|
+
/^[A-Za-z]:[\\/]/.test(destination) ||
|
|
30
|
+
destination.startsWith("\\\\")) {
|
|
31
|
+
return "broker";
|
|
32
|
+
}
|
|
33
|
+
const remote = /^([^:]+):.+$/.exec(destination);
|
|
34
|
+
return remote ? `${remote[1]}:broker` : "broker";
|
|
35
|
+
}
|
|
36
|
+
function asAckBody(body) {
|
|
37
|
+
if (!hasExactAckType(body) ||
|
|
38
|
+
!Object.hasOwn(body, "status") ||
|
|
39
|
+
!Object.hasOwn(body, "target")) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
const { status, target } = body;
|
|
43
|
+
if ((status !== "received" && status !== "busy" && status !== "denied") ||
|
|
44
|
+
typeof target !== "string") {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
return { type: "ack", status, target };
|
|
48
|
+
}
|
|
49
|
+
export class SessionPeer {
|
|
50
|
+
opts;
|
|
51
|
+
/** Clean leaf name actually assigned by the broker (may carry a `#N`
|
|
52
|
+
* collision suffix). Used for display + self-filtering. */
|
|
53
|
+
assignedName;
|
|
54
|
+
/** Canonical address assigned by the broker (`[<pc>:]<cwd>@<nome>`, or just
|
|
55
|
+
* the name for a legacy broker). This is the routing/identity key the mesh
|
|
56
|
+
* uses; callers ECHO it, never compose it. */
|
|
57
|
+
assignedAddress;
|
|
58
|
+
role = "follower";
|
|
59
|
+
broker = null;
|
|
60
|
+
socket = null;
|
|
61
|
+
buf = "";
|
|
62
|
+
/** Map of in-flight request ids → resolver. Used by `request()`. */
|
|
63
|
+
pending = new Map();
|
|
64
|
+
/** Map of in-flight send ids → ACK resolver. Used by `sendWithAck()`. */
|
|
65
|
+
ackPending = new Map();
|
|
66
|
+
handlers = new Set();
|
|
67
|
+
reconnectHandlers = new Set();
|
|
68
|
+
leftFlag = false;
|
|
69
|
+
constructor(opts) {
|
|
70
|
+
this.opts = opts;
|
|
71
|
+
this.assignedName = opts.name;
|
|
72
|
+
this.assignedAddress = opts.name;
|
|
73
|
+
}
|
|
74
|
+
// ── public API ────────────────────────────────────────────────────────────
|
|
75
|
+
/** Joins or leads the session at `sockPath`. Resolves with the assigned name. */
|
|
76
|
+
async start() {
|
|
77
|
+
return this._joinOrLead();
|
|
78
|
+
}
|
|
79
|
+
/** Returns the clean leaf name as assigned by the broker (after any `#N`). */
|
|
80
|
+
name() {
|
|
81
|
+
return this.assignedName;
|
|
82
|
+
}
|
|
83
|
+
/** Returns the canonical address (`[<pc>:]<cwd>@<nome>`) assigned by the
|
|
84
|
+
* broker — the key the mesh routes on. Equals `name()` against a legacy
|
|
85
|
+
* broker that returns no address. */
|
|
86
|
+
address() {
|
|
87
|
+
return this.assignedAddress;
|
|
88
|
+
}
|
|
89
|
+
/** Returns "leader" or "follower" — current role. */
|
|
90
|
+
currentRole() {
|
|
91
|
+
return this.role;
|
|
92
|
+
}
|
|
93
|
+
/** Returns the locally-hosted Broker when this peer is the leader, or
|
|
94
|
+
* null when it's a follower. Wave 25C uses this to attach the
|
|
95
|
+
* cross-PC router. */
|
|
96
|
+
localBroker() {
|
|
97
|
+
return this.broker;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Fire-and-forget send. Doesn't await a reply.
|
|
101
|
+
*
|
|
102
|
+
* `re` (optional) lets the caller correlate this message as a reply to a
|
|
103
|
+
* previous request — when an LLM peer is *answering* a question from
|
|
104
|
+
* another agent, it must echo the original `id` here so the requester's
|
|
105
|
+
* pending map can resolve. Without `re`, the requester treats this as a
|
|
106
|
+
* new unsolicited message and its `request()` call times out.
|
|
107
|
+
*/
|
|
108
|
+
async send(to, body, re = null) {
|
|
109
|
+
const env = envelope(this.assignedName, to, body, re);
|
|
110
|
+
await this._writeEnvelope(env);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Unicast send + await broker ACK. Returns the ACK status:
|
|
114
|
+
* - `received` — peer was idle, envelope delivered, will be processed soon
|
|
115
|
+
* - `busy` — peer mid-turn, envelope dropped; sender is owner of retry
|
|
116
|
+
* - `denied` — broker/Relay refused delivery (including authorization or envelope failure)
|
|
117
|
+
* - `timeout` — no ACK within `timeoutMs`, or trusted Relay says offline
|
|
118
|
+
*
|
|
119
|
+
* Only meaningful for unicast non-broadcast addresses. The peer's body-level
|
|
120
|
+
* reply (if any) is asynchronous and arrives as a normal inbound envelope
|
|
121
|
+
* carrying `re=<this-send-id>` in a future turn — handled by `onMessage`.
|
|
122
|
+
*/
|
|
123
|
+
async sendWithAck(to, body, re = null, timeoutMs = ACK_TIMEOUT_MS) {
|
|
124
|
+
const env = envelope(this.assignedName, to, body, re);
|
|
125
|
+
return new Promise((resolve) => {
|
|
126
|
+
const timer = setTimeout(() => {
|
|
127
|
+
this.ackPending.delete(env.id);
|
|
128
|
+
resolve({ status: "timeout", id: env.id });
|
|
129
|
+
}, timeoutMs);
|
|
130
|
+
this.ackPending.set(env.id, {
|
|
131
|
+
expectedFrom: expectedAckSender(to),
|
|
132
|
+
resolve,
|
|
133
|
+
timer,
|
|
134
|
+
});
|
|
135
|
+
this._writeEnvelope(env).catch(() => {
|
|
136
|
+
const slot = this.ackPending.get(env.id);
|
|
137
|
+
if (!slot)
|
|
138
|
+
return;
|
|
139
|
+
clearTimeout(slot.timer);
|
|
140
|
+
this.ackPending.delete(env.id);
|
|
141
|
+
resolve({ status: "timeout", id: env.id });
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Send + await reply. Resolves with the first inbound envelope whose `re`
|
|
147
|
+
* matches the outbound `id`. Rejects on timeout, teardown/write failure, or
|
|
148
|
+
* a trusted Relay transport error.
|
|
149
|
+
*/
|
|
150
|
+
async request(to, body, timeoutMs = this.opts.defaultTimeoutMs ?? DEFAULT_TIMEOUT_MS) {
|
|
151
|
+
const env = envelope(this.assignedName, to, body, null);
|
|
152
|
+
return new Promise((resolve, reject) => {
|
|
153
|
+
const timer = setTimeout(() => {
|
|
154
|
+
this.pending.delete(env.id);
|
|
155
|
+
reject(new Error(`request to ${to} timed out after ${timeoutMs}ms`));
|
|
156
|
+
}, timeoutMs);
|
|
157
|
+
this.pending.set(env.id, { resolve, reject, timer });
|
|
158
|
+
this._writeEnvelope(env).catch((err) => {
|
|
159
|
+
const slot = this.pending.get(env.id);
|
|
160
|
+
if (!slot)
|
|
161
|
+
return;
|
|
162
|
+
clearTimeout(slot.timer);
|
|
163
|
+
this.pending.delete(env.id);
|
|
164
|
+
reject(err);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
onMessage(handler) {
|
|
169
|
+
this.handlers.add(handler);
|
|
170
|
+
return () => this.handlers.delete(handler);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Fires after the peer successfully (re)joins following a failover —
|
|
174
|
+
* leader died and we re-elected. NOT called for the initial `start()`,
|
|
175
|
+
* only for post-drop reconnects. Consumers use this to re-query state
|
|
176
|
+
* the broker may have lost in the transition (e.g., peer list).
|
|
177
|
+
*/
|
|
178
|
+
onReconnect(handler) {
|
|
179
|
+
this.reconnectHandlers.add(handler);
|
|
180
|
+
return () => this.reconnectHandlers.delete(handler);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Requests a different display name from the broker. Returns the name
|
|
184
|
+
* actually assigned (may carry a #N suffix on collision). Implemented as
|
|
185
|
+
* a soft rejoin: leaves & rejoins with the new name.
|
|
186
|
+
*/
|
|
187
|
+
async rename(newName) {
|
|
188
|
+
await this._teardownConn();
|
|
189
|
+
this.opts.name = newName;
|
|
190
|
+
this.assignedName = newName;
|
|
191
|
+
return this._joinOrLead();
|
|
192
|
+
}
|
|
193
|
+
async leave() {
|
|
194
|
+
this.leftFlag = true;
|
|
195
|
+
await this._teardownConn();
|
|
196
|
+
}
|
|
197
|
+
// ── join / failover loop ──────────────────────────────────────────────────
|
|
198
|
+
async _joinOrLead() {
|
|
199
|
+
const result = await joinOrLead(this.opts.sockPath);
|
|
200
|
+
if (result.role === "leader") {
|
|
201
|
+
this.role = "leader";
|
|
202
|
+
this.broker = new Broker({
|
|
203
|
+
server: result.server,
|
|
204
|
+
auditPath: this.opts.auditPath,
|
|
205
|
+
});
|
|
206
|
+
// Leader also registers itself as a peer so other followers see it +
|
|
207
|
+
// can address it. We create a self-loopback socket via the broker's
|
|
208
|
+
// internal API: easiest is to open a real client connection back to
|
|
209
|
+
// our own server.
|
|
210
|
+
return this._registerAsClient();
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
this.role = "follower";
|
|
214
|
+
this._wireSocket(result.socket);
|
|
215
|
+
return this._registerOver(result.socket);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
async _registerAsClient() {
|
|
219
|
+
const { createConnection } = await import("node:net");
|
|
220
|
+
const sock = createConnection(this.opts.sockPath);
|
|
221
|
+
await new Promise((resolve, reject) => {
|
|
222
|
+
sock.once("connect", () => resolve());
|
|
223
|
+
sock.once("error", reject);
|
|
224
|
+
});
|
|
225
|
+
this._wireSocket(sock);
|
|
226
|
+
return this._registerOver(sock);
|
|
227
|
+
}
|
|
228
|
+
_wireSocket(sock) {
|
|
229
|
+
this.socket = sock;
|
|
230
|
+
this.buf = "";
|
|
231
|
+
sock.setEncoding("utf8");
|
|
232
|
+
sock.on("data", (chunk) => this._onData(chunk));
|
|
233
|
+
sock.on("close", () => this._onSocketClose(sock));
|
|
234
|
+
sock.on("error", () => {
|
|
235
|
+
/* close will follow */
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
_registerOver(sock) {
|
|
239
|
+
return new Promise((resolve, reject) => {
|
|
240
|
+
// The first inbound line MUST be the register_ack. Buffer-aware.
|
|
241
|
+
const wait = setTimeout(() => reject(new Error("register_ack timeout")), 5_000);
|
|
242
|
+
const onceListener = (raw) => {
|
|
243
|
+
clearTimeout(wait);
|
|
244
|
+
// plan/38: a new broker returns `address_assigned` (canonical key) +
|
|
245
|
+
// `name_assigned` (clean leaf). Read both with cross-fallback so we work
|
|
246
|
+
// against either a new broker OR a legacy one (only `name_assigned`,
|
|
247
|
+
// where address == name).
|
|
248
|
+
const ack = raw;
|
|
249
|
+
const name = typeof ack?.name_assigned === "string"
|
|
250
|
+
? ack.name_assigned
|
|
251
|
+
: ack?.address_assigned;
|
|
252
|
+
const address = typeof ack?.address_assigned === "string"
|
|
253
|
+
? ack.address_assigned
|
|
254
|
+
: ack?.name_assigned;
|
|
255
|
+
if (ack &&
|
|
256
|
+
ack.type === "register_ack" &&
|
|
257
|
+
typeof name === "string" &&
|
|
258
|
+
typeof address === "string") {
|
|
259
|
+
this.assignedName = name;
|
|
260
|
+
this.assignedAddress = address;
|
|
261
|
+
this._preAckListener = null;
|
|
262
|
+
resolve(name);
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
reject(new Error(`expected register_ack, got: ${JSON.stringify(raw)}`));
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
this._preAckListener = onceListener;
|
|
269
|
+
const req = JSON.stringify({
|
|
270
|
+
type: "register",
|
|
271
|
+
name: this.opts.name,
|
|
272
|
+
// Only include cwd when set — keeps the wire identical to the legacy
|
|
273
|
+
// payload for callers that don't supply it (broker treats absent cwd
|
|
274
|
+
// as "no take-over", i.e. the old #N behavior).
|
|
275
|
+
...(this.opts.cwd === undefined ? {} : { cwd: this.opts.cwd }),
|
|
276
|
+
...(this.opts.takeoverExisting === true ? { takeover: true } : {}),
|
|
277
|
+
}) + "\n";
|
|
278
|
+
try {
|
|
279
|
+
sock.write(req);
|
|
280
|
+
}
|
|
281
|
+
catch (e) {
|
|
282
|
+
clearTimeout(wait);
|
|
283
|
+
reject(e);
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
_preAckListener = null;
|
|
288
|
+
_onData(chunk) {
|
|
289
|
+
this.buf += chunk;
|
|
290
|
+
let nl;
|
|
291
|
+
while ((nl = this.buf.indexOf("\n")) >= 0) {
|
|
292
|
+
const line = this.buf.slice(0, nl);
|
|
293
|
+
this.buf = this.buf.slice(nl + 1);
|
|
294
|
+
if (!line)
|
|
295
|
+
continue;
|
|
296
|
+
this._handleLine(line);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
_handleLine(line) {
|
|
300
|
+
// Before register_ack: parse loosely as an ack control message.
|
|
301
|
+
if (this._preAckListener) {
|
|
302
|
+
try {
|
|
303
|
+
const parsed = JSON.parse(line);
|
|
304
|
+
this._preAckListener(parsed);
|
|
305
|
+
}
|
|
306
|
+
catch {
|
|
307
|
+
// Garbage during register window — ignore.
|
|
308
|
+
}
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
// Regular envelope.
|
|
312
|
+
let env;
|
|
313
|
+
try {
|
|
314
|
+
env = parse(line);
|
|
315
|
+
}
|
|
316
|
+
catch (e) {
|
|
317
|
+
if (e instanceof EnvelopeError)
|
|
318
|
+
return;
|
|
319
|
+
throw e;
|
|
320
|
+
}
|
|
321
|
+
// Reserve every raw transport_error body before either pending map can
|
|
322
|
+
// correlate it. Only exact broker provenance plus a valid body may settle;
|
|
323
|
+
// forged or invalid reserved frames remain ordinary handler messages.
|
|
324
|
+
if (hasTransportErrorType(env.body)) {
|
|
325
|
+
const trusted = env.from === "broker" && env.re !== null
|
|
326
|
+
? asTransportErrorBody(env.body)
|
|
327
|
+
: null;
|
|
328
|
+
if (trusted && env.re !== null) {
|
|
329
|
+
this._consumeAckTransportError(env.re, trusted.reason);
|
|
330
|
+
this._rejectRequestTransportError(env.re, trusted.reason);
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
this._dispatchToHandlers(env);
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
// Reserve exact broker ACKs before generic correlation or handler dispatch.
|
|
337
|
+
// The sender is bound when the send begins: local sends accept only
|
|
338
|
+
// `broker`, while remote alias sends accept only `<alias>:broker`.
|
|
339
|
+
const fromBroker = env.from === "broker" || env.from.endsWith(":broker");
|
|
340
|
+
if (fromBroker && hasExactAckType(env.body)) {
|
|
341
|
+
const ackBody = asAckBody(env.body);
|
|
342
|
+
if (env.re !== null && ackBody) {
|
|
343
|
+
const slot = this.ackPending.get(env.re);
|
|
344
|
+
if (slot && slot.expectedFrom === env.from) {
|
|
345
|
+
clearTimeout(slot.timer);
|
|
346
|
+
this.ackPending.delete(env.re);
|
|
347
|
+
slot.resolve({
|
|
348
|
+
status: ackBody.status,
|
|
349
|
+
id: env.re,
|
|
350
|
+
target: ackBody.target,
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
// Correlate replies for `request()`.
|
|
357
|
+
if (env.re) {
|
|
358
|
+
const slot = this.pending.get(env.re);
|
|
359
|
+
if (slot) {
|
|
360
|
+
clearTimeout(slot.timer);
|
|
361
|
+
this.pending.delete(env.re);
|
|
362
|
+
slot.resolve(env);
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
// Otherwise dispatch to subscribers.
|
|
367
|
+
this._dispatchToHandlers(env);
|
|
368
|
+
}
|
|
369
|
+
_consumeAckTransportError(correlationId, reason) {
|
|
370
|
+
const pendingId = correlationId.toLowerCase();
|
|
371
|
+
const slot = this.ackPending.get(pendingId);
|
|
372
|
+
if (!slot)
|
|
373
|
+
return;
|
|
374
|
+
clearTimeout(slot.timer);
|
|
375
|
+
this.ackPending.delete(pendingId);
|
|
376
|
+
slot.resolve({
|
|
377
|
+
status: reason === "offline" ? "timeout" : "denied",
|
|
378
|
+
id: pendingId,
|
|
379
|
+
error: `transport_error: ${reason}`,
|
|
380
|
+
reason,
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
_rejectRequestTransportError(correlationId, reason) {
|
|
384
|
+
const pendingId = correlationId.toLowerCase();
|
|
385
|
+
const slot = this.pending.get(pendingId);
|
|
386
|
+
if (!slot)
|
|
387
|
+
return;
|
|
388
|
+
clearTimeout(slot.timer);
|
|
389
|
+
this.pending.delete(pendingId);
|
|
390
|
+
slot.reject(new MeshTransportError(reason, pendingId));
|
|
391
|
+
}
|
|
392
|
+
_dispatchToHandlers(env) {
|
|
393
|
+
for (const h of this.handlers) {
|
|
394
|
+
try {
|
|
395
|
+
h(env);
|
|
396
|
+
}
|
|
397
|
+
catch {
|
|
398
|
+
/* handler errors don't break peer */
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
async _writeEnvelope(env) {
|
|
403
|
+
if (!this.socket || this.socket.destroyed) {
|
|
404
|
+
throw new Error("session peer not connected");
|
|
405
|
+
}
|
|
406
|
+
this.socket.write(serialize(env));
|
|
407
|
+
}
|
|
408
|
+
async _onSocketClose(closedSock) {
|
|
409
|
+
if (this.leftFlag)
|
|
410
|
+
return; // intentional leave
|
|
411
|
+
// Only the CURRENT socket dying is a real failover. A close from a socket
|
|
412
|
+
// we've already replaced — `rename()` (teardown + rejoin) or a prior
|
|
413
|
+
// reconnect — must NOT trigger another `_joinOrLead`, or we'd double-
|
|
414
|
+
// register (the broker suffixes the second as `#N`) and leave an orphaned
|
|
415
|
+
// still-open socket as a ghost peer. `this.socket` is null mid-rename
|
|
416
|
+
// (teardown done, rejoin in flight) or already the new socket — either way
|
|
417
|
+
// `!== closedSock`, so we skip. Genuine leader death: `this.socket` is still
|
|
418
|
+
// the (now-closed) follower socket → identity matches → we re-elect.
|
|
419
|
+
if (this.socket !== closedSock)
|
|
420
|
+
return;
|
|
421
|
+
// Attempt to re-elect once. New leader will bind sockPath; we either
|
|
422
|
+
// become leader ourselves or rejoin as follower.
|
|
423
|
+
await delay(FAILOVER_RETRY_MS);
|
|
424
|
+
if (this.leftFlag || this.socket !== closedSock)
|
|
425
|
+
return;
|
|
426
|
+
try {
|
|
427
|
+
await this._joinOrLead();
|
|
428
|
+
// The new broker's peers map starts fresh — consumers must re-query
|
|
429
|
+
// any cached state (peer count, etc.) that depended on the old broker.
|
|
430
|
+
for (const h of this.reconnectHandlers) {
|
|
431
|
+
try {
|
|
432
|
+
h();
|
|
433
|
+
}
|
|
434
|
+
catch {
|
|
435
|
+
/* handler errors don't break peer */
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
catch {
|
|
440
|
+
/* election failed; peer stuck in disconnected state */
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
async _teardownConn() {
|
|
444
|
+
for (const [id, slot] of this.pending) {
|
|
445
|
+
clearTimeout(slot.timer);
|
|
446
|
+
this.pending.delete(id);
|
|
447
|
+
slot.reject(new Error("peer leaving"));
|
|
448
|
+
}
|
|
449
|
+
for (const [id, slot] of this.ackPending) {
|
|
450
|
+
clearTimeout(slot.timer);
|
|
451
|
+
this.ackPending.delete(id);
|
|
452
|
+
slot.resolve({ status: "timeout", id });
|
|
453
|
+
}
|
|
454
|
+
if (this.socket) {
|
|
455
|
+
try {
|
|
456
|
+
this.socket.destroy();
|
|
457
|
+
}
|
|
458
|
+
catch {
|
|
459
|
+
/* ignored */
|
|
460
|
+
}
|
|
461
|
+
this.socket = null;
|
|
462
|
+
}
|
|
463
|
+
if (this.broker) {
|
|
464
|
+
try {
|
|
465
|
+
await this.broker.close();
|
|
466
|
+
}
|
|
467
|
+
catch {
|
|
468
|
+
/* ignored */
|
|
469
|
+
}
|
|
470
|
+
this.broker = null;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
//# sourceMappingURL=peer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"peer.js","sourceRoot":"","sources":["../../src/session/peer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan/25 Wave D — pure formatter for the `/unbien peers` output.
|
|
3
|
+
*
|
|
4
|
+
* Lives in its own module so it can be unit-tested without booting the full
|
|
5
|
+
* extension (no keychain access, no relay client, no mocks needed). The
|
|
6
|
+
* extension imports the function and wraps it with the `_sessionPeer`
|
|
7
|
+
* `list_peers` request.
|
|
8
|
+
*
|
|
9
|
+
* Input shape: the broker's `list_peers_reply` body returns peer names as
|
|
10
|
+
* plain strings — local peers without a prefix (`sess-1`, `agent-2`),
|
|
11
|
+
* cross-PC peers with a `<pc_label>:<peer>` prefix (`casa:sess-3`).
|
|
12
|
+
*/
|
|
13
|
+
export declare function formatPeerInventory(peers: string[], selfName?: string): string;
|