claudemesh-cli 1.29.0 → 1.30.1
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/dist/entrypoints/cli.js +397 -45
- package/dist/entrypoints/cli.js.map +14 -12
- package/dist/entrypoints/mcp.js +2 -2
- package/dist/entrypoints/mcp.js.map +2 -2
- package/package.json +1 -1
package/dist/entrypoints/cli.js
CHANGED
|
@@ -92,7 +92,8 @@ var init_exit_codes = __esm(() => {
|
|
|
92
92
|
ALREADY_EXISTS: 6,
|
|
93
93
|
PERMISSION_DENIED: 7,
|
|
94
94
|
INTERNAL_ERROR: 8,
|
|
95
|
-
CLAUDE_MISSING: 9
|
|
95
|
+
CLAUDE_MISSING: 9,
|
|
96
|
+
IO_ERROR: 10
|
|
96
97
|
};
|
|
97
98
|
});
|
|
98
99
|
|
|
@@ -103,7 +104,7 @@ __export(exports_urls, {
|
|
|
103
104
|
VERSION: () => VERSION,
|
|
104
105
|
URLS: () => URLS
|
|
105
106
|
});
|
|
106
|
-
var URLS, VERSION = "1.
|
|
107
|
+
var URLS, VERSION = "1.30.1", env;
|
|
107
108
|
var init_urls = __esm(() => {
|
|
108
109
|
URLS = {
|
|
109
110
|
BROKER: process.env.CLAUDEMESH_BROKER_URL ?? "wss://ic.claudemesh.com/ws",
|
|
@@ -3941,6 +3942,38 @@ var init_lifecycle = __esm(() => {
|
|
|
3941
3942
|
init_paths2();
|
|
3942
3943
|
});
|
|
3943
3944
|
|
|
3945
|
+
// src/services/broker/session-hello-sig.ts
|
|
3946
|
+
var exports_session_hello_sig = {};
|
|
3947
|
+
__export(exports_session_hello_sig, {
|
|
3948
|
+
signSessionHello: () => signSessionHello,
|
|
3949
|
+
signParentAttestation: () => signParentAttestation,
|
|
3950
|
+
DEFAULT_ATTESTATION_TTL_MS: () => DEFAULT_ATTESTATION_TTL_MS
|
|
3951
|
+
});
|
|
3952
|
+
async function signParentAttestation(args) {
|
|
3953
|
+
const s = await ensureSodium();
|
|
3954
|
+
const expiresAt = (args.now ?? Date.now()) + (args.ttlMs ?? DEFAULT_ATTESTATION_TTL_MS);
|
|
3955
|
+
const canonical = `claudemesh-session-attest|${args.parentMemberPubkey}|${args.sessionPubkey}|${expiresAt}`;
|
|
3956
|
+
const sig = s.crypto_sign_detached(s.from_string(canonical), s.from_hex(args.parentSecretKey));
|
|
3957
|
+
return {
|
|
3958
|
+
sessionPubkey: args.sessionPubkey,
|
|
3959
|
+
parentMemberPubkey: args.parentMemberPubkey,
|
|
3960
|
+
expiresAt,
|
|
3961
|
+
signature: s.to_hex(sig)
|
|
3962
|
+
};
|
|
3963
|
+
}
|
|
3964
|
+
async function signSessionHello(args) {
|
|
3965
|
+
const s = await ensureSodium();
|
|
3966
|
+
const timestamp2 = args.now ?? Date.now();
|
|
3967
|
+
const canonical = `claudemesh-session-hello|${args.meshId}|${args.parentMemberPubkey}|${args.sessionPubkey}|${timestamp2}`;
|
|
3968
|
+
const sig = s.crypto_sign_detached(s.from_string(canonical), s.from_hex(args.sessionSecretKey));
|
|
3969
|
+
return { timestamp: timestamp2, signature: s.to_hex(sig) };
|
|
3970
|
+
}
|
|
3971
|
+
var DEFAULT_ATTESTATION_TTL_MS;
|
|
3972
|
+
var init_session_hello_sig = __esm(() => {
|
|
3973
|
+
init_keypair();
|
|
3974
|
+
DEFAULT_ATTESTATION_TTL_MS = 12 * 60 * 60 * 1000;
|
|
3975
|
+
});
|
|
3976
|
+
|
|
3944
3977
|
// src/commands/launch.ts
|
|
3945
3978
|
var exports_launch = {};
|
|
3946
3979
|
__export(exports_launch, {
|
|
@@ -4344,6 +4377,8 @@ async function runLaunch(flags, rawArgs) {
|
|
|
4344
4377
|
};
|
|
4345
4378
|
writeFileSync7(join5(tmpDir, "config.json"), JSON.stringify(sessionConfig, null, 2) + `
|
|
4346
4379
|
`, "utf-8");
|
|
4380
|
+
const isResume = args.resume !== null || args.continueSession;
|
|
4381
|
+
const claudeSessionId = isResume ? undefined : randomUUID();
|
|
4347
4382
|
let sessionTokenFilePath = null;
|
|
4348
4383
|
let sessionTokenForCleanup = null;
|
|
4349
4384
|
try {
|
|
@@ -4351,6 +4386,27 @@ async function runLaunch(flags, rawArgs) {
|
|
|
4351
4386
|
const minted = mintSessionToken2(tmpDir);
|
|
4352
4387
|
sessionTokenFilePath = minted.filePath;
|
|
4353
4388
|
sessionTokenForCleanup = minted.token;
|
|
4389
|
+
let presencePayload;
|
|
4390
|
+
try {
|
|
4391
|
+
const { generateKeypair: generateKeypair4 } = await Promise.resolve().then(() => (init_facade7(), exports_facade4));
|
|
4392
|
+
const { signParentAttestation: signParentAttestation2 } = await Promise.resolve().then(() => (init_session_hello_sig(), exports_session_hello_sig));
|
|
4393
|
+
const sessionKp = await generateKeypair4();
|
|
4394
|
+
const att = await signParentAttestation2({
|
|
4395
|
+
parentMemberPubkey: mesh.pubkey,
|
|
4396
|
+
parentSecretKey: mesh.secretKey,
|
|
4397
|
+
sessionPubkey: sessionKp.publicKey
|
|
4398
|
+
});
|
|
4399
|
+
presencePayload = {
|
|
4400
|
+
session_pubkey: sessionKp.publicKey,
|
|
4401
|
+
session_secret_key: sessionKp.secretKey,
|
|
4402
|
+
parent_attestation: {
|
|
4403
|
+
session_pubkey: att.sessionPubkey,
|
|
4404
|
+
parent_member_pubkey: att.parentMemberPubkey,
|
|
4405
|
+
expires_at: att.expiresAt,
|
|
4406
|
+
signature: att.signature
|
|
4407
|
+
}
|
|
4408
|
+
};
|
|
4409
|
+
} catch {}
|
|
4354
4410
|
const { ipc: ipc2 } = await Promise.resolve().then(() => (init_client3(), exports_client));
|
|
4355
4411
|
const sessionIdForRegister = claudeSessionId ?? randomUUID();
|
|
4356
4412
|
await ipc2({
|
|
@@ -4365,7 +4421,8 @@ async function runLaunch(flags, rawArgs) {
|
|
|
4365
4421
|
pid: process.pid,
|
|
4366
4422
|
cwd: process.cwd(),
|
|
4367
4423
|
...role ? { role } : {},
|
|
4368
|
-
...parsedGroups.length > 0 ? { groups: parsedGroups.map((g) => `@${g.name}${g.role ? `:${g.role}` : ""}`) } : {}
|
|
4424
|
+
...parsedGroups.length > 0 ? { groups: parsedGroups.map((g) => `@${g.name}${g.role ? `:${g.role}` : ""}`) } : {},
|
|
4425
|
+
...presencePayload ? { presence: presencePayload } : {}
|
|
4369
4426
|
}
|
|
4370
4427
|
}).catch(() => null);
|
|
4371
4428
|
process._claudemeshTokenEnv = {
|
|
@@ -4429,8 +4486,6 @@ async function runLaunch(flags, rawArgs) {
|
|
|
4429
4486
|
}
|
|
4430
4487
|
filtered.push(args.claudeArgs[i]);
|
|
4431
4488
|
}
|
|
4432
|
-
const isResume = args.resume !== null || args.continueSession;
|
|
4433
|
-
const claudeSessionId = isResume ? undefined : randomUUID();
|
|
4434
4489
|
const claudeArgs = [
|
|
4435
4490
|
"--dangerously-load-development-channels",
|
|
4436
4491
|
"server:claudemesh",
|
|
@@ -8440,7 +8495,7 @@ async function runMsgStatus(id, opts) {
|
|
|
8440
8495
|
console.log(JSON.stringify(result, null, 2));
|
|
8441
8496
|
return EXIT.SUCCESS;
|
|
8442
8497
|
}
|
|
8443
|
-
render.section(`message ${
|
|
8498
|
+
render.section(`message ${lookupId.slice(0, 12)}…`);
|
|
8444
8499
|
render.kv([
|
|
8445
8500
|
["target", result.targetSpec],
|
|
8446
8501
|
["delivered", result.delivered ? "yes" : "no"],
|
|
@@ -9258,13 +9313,27 @@ function startReaper() {
|
|
|
9258
9313
|
return;
|
|
9259
9314
|
reaperHandle = setInterval(reapDead, REAPER_INTERVAL_MS).unref?.() ?? reaperHandle;
|
|
9260
9315
|
}
|
|
9316
|
+
function setRegistryHooks(next) {
|
|
9317
|
+
hooks.onRegister = next.onRegister;
|
|
9318
|
+
hooks.onDeregister = next.onDeregister;
|
|
9319
|
+
}
|
|
9261
9320
|
function registerSession(info) {
|
|
9262
9321
|
const priorToken = bySessionId.get(info.sessionId);
|
|
9263
|
-
if (priorToken && priorToken !== info.token)
|
|
9264
|
-
byToken.
|
|
9322
|
+
if (priorToken && priorToken !== info.token) {
|
|
9323
|
+
const prior = byToken.get(priorToken);
|
|
9324
|
+
if (prior) {
|
|
9325
|
+
byToken.delete(priorToken);
|
|
9326
|
+
try {
|
|
9327
|
+
hooks.onDeregister?.(prior);
|
|
9328
|
+
} catch {}
|
|
9329
|
+
}
|
|
9330
|
+
}
|
|
9265
9331
|
const stored = { ...info, registeredAt: Date.now() };
|
|
9266
9332
|
byToken.set(info.token, stored);
|
|
9267
9333
|
bySessionId.set(info.sessionId, info.token);
|
|
9334
|
+
try {
|
|
9335
|
+
hooks.onRegister?.(stored);
|
|
9336
|
+
} catch {}
|
|
9268
9337
|
return stored;
|
|
9269
9338
|
}
|
|
9270
9339
|
function deregisterByToken(token) {
|
|
@@ -9274,6 +9343,9 @@ function deregisterByToken(token) {
|
|
|
9274
9343
|
byToken.delete(token);
|
|
9275
9344
|
if (bySessionId.get(entry.sessionId) === token)
|
|
9276
9345
|
bySessionId.delete(entry.sessionId);
|
|
9346
|
+
try {
|
|
9347
|
+
hooks.onDeregister?.(entry);
|
|
9348
|
+
} catch {}
|
|
9277
9349
|
return true;
|
|
9278
9350
|
}
|
|
9279
9351
|
function resolveToken(token) {
|
|
@@ -9305,12 +9377,13 @@ function reapDead() {
|
|
|
9305
9377
|
for (const t of dead)
|
|
9306
9378
|
deregisterByToken(t);
|
|
9307
9379
|
}
|
|
9308
|
-
var TTL_MS, REAPER_INTERVAL_MS, byToken, bySessionId, reaperHandle = null;
|
|
9380
|
+
var TTL_MS, REAPER_INTERVAL_MS, byToken, bySessionId, hooks, reaperHandle = null;
|
|
9309
9381
|
var init_session_registry = __esm(() => {
|
|
9310
9382
|
TTL_MS = 24 * 60 * 60 * 1000;
|
|
9311
9383
|
REAPER_INTERVAL_MS = 30 * 1000;
|
|
9312
9384
|
byToken = new Map;
|
|
9313
9385
|
bySessionId = new Map;
|
|
9386
|
+
hooks = {};
|
|
9314
9387
|
});
|
|
9315
9388
|
|
|
9316
9389
|
// src/daemon/ipc/server.ts
|
|
@@ -9461,6 +9534,28 @@ function makeHandler(opts) {
|
|
|
9461
9534
|
const cwd = typeof body.cwd === "string" ? body.cwd : undefined;
|
|
9462
9535
|
const role = typeof body.role === "string" ? body.role : undefined;
|
|
9463
9536
|
const groups = Array.isArray(body.groups) ? body.groups.filter((g) => typeof g === "string") : undefined;
|
|
9537
|
+
let presence;
|
|
9538
|
+
const rawPresence = body.presence;
|
|
9539
|
+
if (rawPresence && typeof rawPresence === "object") {
|
|
9540
|
+
const p = rawPresence;
|
|
9541
|
+
const sessionPubkey = typeof p.session_pubkey === "string" ? p.session_pubkey.toLowerCase() : "";
|
|
9542
|
+
const sessionSecretKey = typeof p.session_secret_key === "string" ? p.session_secret_key.toLowerCase() : "";
|
|
9543
|
+
const att = p.parent_attestation;
|
|
9544
|
+
if (/^[0-9a-f]{64}$/.test(sessionPubkey) && /^[0-9a-f]{128}$/.test(sessionSecretKey) && att && typeof att === "object" && typeof att.session_pubkey === "string" && typeof att.parent_member_pubkey === "string" && typeof att.expires_at === "number" && typeof att.signature === "string") {
|
|
9545
|
+
presence = {
|
|
9546
|
+
sessionPubkey,
|
|
9547
|
+
sessionSecretKey,
|
|
9548
|
+
parentAttestation: {
|
|
9549
|
+
sessionPubkey: att.session_pubkey.toLowerCase(),
|
|
9550
|
+
parentMemberPubkey: att.parent_member_pubkey.toLowerCase(),
|
|
9551
|
+
expiresAt: att.expires_at,
|
|
9552
|
+
signature: att.signature.toLowerCase()
|
|
9553
|
+
}
|
|
9554
|
+
};
|
|
9555
|
+
} else {
|
|
9556
|
+
opts.log("warn", "session_register_presence_malformed", { mesh });
|
|
9557
|
+
}
|
|
9558
|
+
}
|
|
9464
9559
|
const stored = registerSession({
|
|
9465
9560
|
token: token.toLowerCase(),
|
|
9466
9561
|
sessionId,
|
|
@@ -9469,10 +9564,20 @@ function makeHandler(opts) {
|
|
|
9469
9564
|
pid,
|
|
9470
9565
|
cwd,
|
|
9471
9566
|
role,
|
|
9472
|
-
groups
|
|
9567
|
+
groups,
|
|
9568
|
+
...presence ? { presence } : {}
|
|
9569
|
+
});
|
|
9570
|
+
opts.log("info", "session_registered", {
|
|
9571
|
+
sessionId,
|
|
9572
|
+
mesh,
|
|
9573
|
+
pid,
|
|
9574
|
+
presence: presence ? "yes" : "no"
|
|
9575
|
+
});
|
|
9576
|
+
respond(res, 200, {
|
|
9577
|
+
ok: true,
|
|
9578
|
+
registered_at: stored.registeredAt,
|
|
9579
|
+
presence_accepted: !!presence
|
|
9473
9580
|
});
|
|
9474
|
-
opts.log("info", "session_registered", { sessionId, mesh, pid });
|
|
9475
|
-
respond(res, 200, { ok: true, registered_at: stored.registeredAt });
|
|
9476
9581
|
} catch (e) {
|
|
9477
9582
|
respond(res, 400, { error: String(e) });
|
|
9478
9583
|
}
|
|
@@ -10573,9 +10678,168 @@ var init_broker = __esm(() => {
|
|
|
10573
10678
|
BACKOFF_CAPS_MS = [1000, 2000, 4000, 8000, 16000, 30000];
|
|
10574
10679
|
});
|
|
10575
10680
|
|
|
10681
|
+
// src/daemon/session-broker.ts
|
|
10682
|
+
import { hostname as osHostname } from "node:os";
|
|
10683
|
+
import WebSocket3 from "ws";
|
|
10684
|
+
|
|
10685
|
+
class SessionBrokerClient {
|
|
10686
|
+
opts;
|
|
10687
|
+
ws = null;
|
|
10688
|
+
_status = "closed";
|
|
10689
|
+
closed = false;
|
|
10690
|
+
reconnectAttempt = 0;
|
|
10691
|
+
reconnectTimer = null;
|
|
10692
|
+
helloTimer = null;
|
|
10693
|
+
constructor(opts) {
|
|
10694
|
+
this.opts = opts;
|
|
10695
|
+
}
|
|
10696
|
+
get status() {
|
|
10697
|
+
return this._status;
|
|
10698
|
+
}
|
|
10699
|
+
get meshSlug() {
|
|
10700
|
+
return this.opts.mesh.slug;
|
|
10701
|
+
}
|
|
10702
|
+
get sessionPubkey() {
|
|
10703
|
+
return this.opts.sessionPubkey;
|
|
10704
|
+
}
|
|
10705
|
+
log = (level, msg, meta) => {
|
|
10706
|
+
(this.opts.log ?? defaultLog2)(level, msg, {
|
|
10707
|
+
mesh: this.opts.mesh.slug,
|
|
10708
|
+
session_pubkey: this.opts.sessionPubkey.slice(0, 12),
|
|
10709
|
+
...meta
|
|
10710
|
+
});
|
|
10711
|
+
};
|
|
10712
|
+
setStatus(s) {
|
|
10713
|
+
if (this._status === s)
|
|
10714
|
+
return;
|
|
10715
|
+
this._status = s;
|
|
10716
|
+
this.opts.onStatusChange?.(s);
|
|
10717
|
+
}
|
|
10718
|
+
async connect() {
|
|
10719
|
+
if (this.closed)
|
|
10720
|
+
throw new Error("client_closed");
|
|
10721
|
+
if (this._status === "connecting" || this._status === "open")
|
|
10722
|
+
return;
|
|
10723
|
+
this.setStatus("connecting");
|
|
10724
|
+
const ws = new WebSocket3(this.opts.mesh.brokerUrl);
|
|
10725
|
+
this.ws = ws;
|
|
10726
|
+
return new Promise((resolve, reject) => {
|
|
10727
|
+
ws.on("open", async () => {
|
|
10728
|
+
try {
|
|
10729
|
+
const { timestamp: timestamp2, signature } = await signSessionHello({
|
|
10730
|
+
meshId: this.opts.mesh.meshId,
|
|
10731
|
+
parentMemberPubkey: this.opts.mesh.pubkey,
|
|
10732
|
+
sessionPubkey: this.opts.sessionPubkey,
|
|
10733
|
+
sessionSecretKey: this.opts.sessionSecretKey
|
|
10734
|
+
});
|
|
10735
|
+
ws.send(JSON.stringify({
|
|
10736
|
+
type: "session_hello",
|
|
10737
|
+
meshId: this.opts.mesh.meshId,
|
|
10738
|
+
parentMemberId: this.opts.mesh.memberId,
|
|
10739
|
+
parentMemberPubkey: this.opts.mesh.pubkey,
|
|
10740
|
+
sessionPubkey: this.opts.sessionPubkey,
|
|
10741
|
+
parentAttestation: this.opts.parentAttestation,
|
|
10742
|
+
displayName: this.opts.displayName,
|
|
10743
|
+
sessionId: this.opts.sessionId,
|
|
10744
|
+
pid: this.opts.pid,
|
|
10745
|
+
cwd: this.opts.cwd ?? process.cwd(),
|
|
10746
|
+
hostname: osHostname(),
|
|
10747
|
+
peerType: "ai",
|
|
10748
|
+
channel: "claudemesh-session",
|
|
10749
|
+
...this.opts.groups && this.opts.groups.length > 0 ? { groups: this.opts.groups } : {},
|
|
10750
|
+
...this.opts.role ? { role: this.opts.role } : {},
|
|
10751
|
+
timestamp: timestamp2,
|
|
10752
|
+
signature
|
|
10753
|
+
}));
|
|
10754
|
+
this.helloTimer = setTimeout(() => {
|
|
10755
|
+
this.log("warn", "session_hello_ack_timeout");
|
|
10756
|
+
try {
|
|
10757
|
+
ws.close();
|
|
10758
|
+
} catch {}
|
|
10759
|
+
reject(new Error("session_hello_ack_timeout"));
|
|
10760
|
+
}, HELLO_ACK_TIMEOUT_MS3);
|
|
10761
|
+
} catch (e) {
|
|
10762
|
+
reject(e instanceof Error ? e : new Error(String(e)));
|
|
10763
|
+
}
|
|
10764
|
+
});
|
|
10765
|
+
ws.on("message", (raw) => {
|
|
10766
|
+
let msg;
|
|
10767
|
+
try {
|
|
10768
|
+
msg = JSON.parse(raw.toString());
|
|
10769
|
+
} catch {
|
|
10770
|
+
return;
|
|
10771
|
+
}
|
|
10772
|
+
if (msg.type === "hello_ack") {
|
|
10773
|
+
if (this.helloTimer)
|
|
10774
|
+
clearTimeout(this.helloTimer);
|
|
10775
|
+
this.helloTimer = null;
|
|
10776
|
+
this.setStatus("open");
|
|
10777
|
+
this.reconnectAttempt = 0;
|
|
10778
|
+
resolve();
|
|
10779
|
+
return;
|
|
10780
|
+
}
|
|
10781
|
+
if (msg.type === "error") {
|
|
10782
|
+
this.log("warn", "broker_error", { code: msg.code, message: msg.message });
|
|
10783
|
+
if (msg.code === "unknown_message_type") {
|
|
10784
|
+
this.closed = true;
|
|
10785
|
+
}
|
|
10786
|
+
return;
|
|
10787
|
+
}
|
|
10788
|
+
});
|
|
10789
|
+
ws.on("close", (code, reason) => {
|
|
10790
|
+
if (this.helloTimer) {
|
|
10791
|
+
clearTimeout(this.helloTimer);
|
|
10792
|
+
this.helloTimer = null;
|
|
10793
|
+
}
|
|
10794
|
+
if (this.closed) {
|
|
10795
|
+
this.setStatus("closed");
|
|
10796
|
+
return;
|
|
10797
|
+
}
|
|
10798
|
+
this.setStatus("reconnecting");
|
|
10799
|
+
const wait = BACKOFF_CAPS_MS2[Math.min(this.reconnectAttempt, BACKOFF_CAPS_MS2.length - 1)] ?? 30000;
|
|
10800
|
+
this.reconnectAttempt++;
|
|
10801
|
+
this.log("info", "session_broker_reconnect_scheduled", { wait_ms: wait, code, reason: reason.toString("utf8") });
|
|
10802
|
+
this.reconnectTimer = setTimeout(() => this.connect().catch((err) => this.log("warn", "session_broker_reconnect_failed", { err: String(err) })), wait);
|
|
10803
|
+
if (this._status === "connecting")
|
|
10804
|
+
reject(new Error(`closed_before_hello_${code}`));
|
|
10805
|
+
});
|
|
10806
|
+
ws.on("error", (err) => this.log("warn", "session_broker_ws_error", { err: err.message }));
|
|
10807
|
+
});
|
|
10808
|
+
}
|
|
10809
|
+
async close() {
|
|
10810
|
+
this.closed = true;
|
|
10811
|
+
if (this.reconnectTimer) {
|
|
10812
|
+
clearTimeout(this.reconnectTimer);
|
|
10813
|
+
this.reconnectTimer = null;
|
|
10814
|
+
}
|
|
10815
|
+
if (this.helloTimer) {
|
|
10816
|
+
clearTimeout(this.helloTimer);
|
|
10817
|
+
this.helloTimer = null;
|
|
10818
|
+
}
|
|
10819
|
+
try {
|
|
10820
|
+
this.ws?.close();
|
|
10821
|
+
} catch {}
|
|
10822
|
+
this.setStatus("closed");
|
|
10823
|
+
}
|
|
10824
|
+
}
|
|
10825
|
+
function defaultLog2(level, msg, meta) {
|
|
10826
|
+
const line = JSON.stringify({ level, msg, ...meta, ts: new Date().toISOString() });
|
|
10827
|
+
if (level === "info")
|
|
10828
|
+
process.stdout.write(line + `
|
|
10829
|
+
`);
|
|
10830
|
+
else
|
|
10831
|
+
process.stderr.write(line + `
|
|
10832
|
+
`);
|
|
10833
|
+
}
|
|
10834
|
+
var HELLO_ACK_TIMEOUT_MS3 = 5000, BACKOFF_CAPS_MS2;
|
|
10835
|
+
var init_session_broker = __esm(() => {
|
|
10836
|
+
init_session_hello_sig();
|
|
10837
|
+
BACKOFF_CAPS_MS2 = [1000, 2000, 4000, 8000, 16000, 30000];
|
|
10838
|
+
});
|
|
10839
|
+
|
|
10576
10840
|
// src/daemon/drain.ts
|
|
10577
10841
|
function startDrainWorker(opts) {
|
|
10578
|
-
const log2 = opts.log ??
|
|
10842
|
+
const log2 = opts.log ?? defaultLog3;
|
|
10579
10843
|
let stopped = false;
|
|
10580
10844
|
let wakeResolve = null;
|
|
10581
10845
|
let wakePromise = new Promise((r) => {
|
|
@@ -10719,7 +10983,7 @@ async function randomNonce2() {
|
|
|
10719
10983
|
const { randomBytes: randomBytes6 } = await import("node:crypto");
|
|
10720
10984
|
return randomBytes6(24).toString("base64");
|
|
10721
10985
|
}
|
|
10722
|
-
function
|
|
10986
|
+
function defaultLog3(level, msg, meta) {
|
|
10723
10987
|
const line = JSON.stringify({ level, msg, ...meta, ts: new Date().toISOString() });
|
|
10724
10988
|
if (level === "info")
|
|
10725
10989
|
process.stdout.write(line + `
|
|
@@ -11062,6 +11326,56 @@ async function runDaemon(opts = {}) {
|
|
|
11062
11326
|
}
|
|
11063
11327
|
let drain = null;
|
|
11064
11328
|
drain = startDrainWorker({ db: outboxDb, brokers });
|
|
11329
|
+
const sessionBrokers = new Map;
|
|
11330
|
+
setRegistryHooks({
|
|
11331
|
+
onRegister: (info) => {
|
|
11332
|
+
if (!info.presence)
|
|
11333
|
+
return;
|
|
11334
|
+
const meshConfig = meshConfigs.get(info.mesh);
|
|
11335
|
+
if (!meshConfig) {
|
|
11336
|
+
process.stderr.write(JSON.stringify({
|
|
11337
|
+
level: "warn",
|
|
11338
|
+
msg: "session_broker_no_mesh_config",
|
|
11339
|
+
mesh: info.mesh,
|
|
11340
|
+
ts: new Date().toISOString()
|
|
11341
|
+
}) + `
|
|
11342
|
+
`);
|
|
11343
|
+
return;
|
|
11344
|
+
}
|
|
11345
|
+
const prior = sessionBrokers.get(info.token);
|
|
11346
|
+
if (prior) {
|
|
11347
|
+
sessionBrokers.delete(info.token);
|
|
11348
|
+
prior.close().catch(() => {});
|
|
11349
|
+
}
|
|
11350
|
+
const client = new SessionBrokerClient({
|
|
11351
|
+
mesh: meshConfig,
|
|
11352
|
+
sessionPubkey: info.presence.sessionPubkey,
|
|
11353
|
+
sessionSecretKey: info.presence.sessionSecretKey,
|
|
11354
|
+
parentAttestation: info.presence.parentAttestation,
|
|
11355
|
+
sessionId: info.sessionId,
|
|
11356
|
+
displayName: info.displayName,
|
|
11357
|
+
...info.role ? { role: info.role } : {},
|
|
11358
|
+
...info.cwd ? { cwd: info.cwd } : {},
|
|
11359
|
+
pid: info.pid
|
|
11360
|
+
});
|
|
11361
|
+
sessionBrokers.set(info.token, client);
|
|
11362
|
+
client.connect().catch((err) => process.stderr.write(JSON.stringify({
|
|
11363
|
+
level: "warn",
|
|
11364
|
+
msg: "session_broker_connect_failed",
|
|
11365
|
+
mesh: info.mesh,
|
|
11366
|
+
err: String(err),
|
|
11367
|
+
ts: new Date().toISOString()
|
|
11368
|
+
}) + `
|
|
11369
|
+
`));
|
|
11370
|
+
},
|
|
11371
|
+
onDeregister: (info) => {
|
|
11372
|
+
const client = sessionBrokers.get(info.token);
|
|
11373
|
+
if (!client)
|
|
11374
|
+
return;
|
|
11375
|
+
sessionBrokers.delete(info.token);
|
|
11376
|
+
client.close().catch(() => {});
|
|
11377
|
+
}
|
|
11378
|
+
});
|
|
11065
11379
|
startReaper();
|
|
11066
11380
|
const ipc2 = startIpcServer({
|
|
11067
11381
|
localToken,
|
|
@@ -11105,6 +11419,12 @@ async function runDaemon(opts = {}) {
|
|
|
11105
11419
|
await b.close();
|
|
11106
11420
|
} catch {}
|
|
11107
11421
|
}
|
|
11422
|
+
for (const b of sessionBrokers.values()) {
|
|
11423
|
+
try {
|
|
11424
|
+
await b.close();
|
|
11425
|
+
} catch {}
|
|
11426
|
+
}
|
|
11427
|
+
sessionBrokers.clear();
|
|
11108
11428
|
await ipc2.close();
|
|
11109
11429
|
try {
|
|
11110
11430
|
outboxDb.close();
|
|
@@ -11126,6 +11446,7 @@ var init_run = __esm(() => {
|
|
|
11126
11446
|
init_server();
|
|
11127
11447
|
init_session_registry();
|
|
11128
11448
|
init_broker();
|
|
11449
|
+
init_session_broker();
|
|
11129
11450
|
init_drain();
|
|
11130
11451
|
init_inbound();
|
|
11131
11452
|
init_identity();
|
|
@@ -11200,7 +11521,9 @@ function installDarwin(args) {
|
|
|
11200
11521
|
const plist = darwinPlistPath();
|
|
11201
11522
|
mkdirSync7(dirname5(plist), { recursive: true });
|
|
11202
11523
|
const log2 = DAEMON_PATHS.LOG_FILE;
|
|
11524
|
+
const nodeBin = process.execPath;
|
|
11203
11525
|
const meshArgs = [
|
|
11526
|
+
`<string>${escapeXml(args.binaryPath)}</string>`,
|
|
11204
11527
|
"<string>daemon</string>",
|
|
11205
11528
|
"<string>up</string>",
|
|
11206
11529
|
"<string>--mesh</string>",
|
|
@@ -11216,7 +11539,7 @@ function installDarwin(args) {
|
|
|
11216
11539
|
<string>${SERVICE_LABEL}</string>
|
|
11217
11540
|
<key>ProgramArguments</key>
|
|
11218
11541
|
<array>
|
|
11219
|
-
<string>${escapeXml(
|
|
11542
|
+
<string>${escapeXml(nodeBin)}</string>
|
|
11220
11543
|
${meshArgs}
|
|
11221
11544
|
</array>
|
|
11222
11545
|
<key>RunAtLoad</key>
|
|
@@ -11240,6 +11563,20 @@ function installDarwin(args) {
|
|
|
11240
11563
|
</plist>
|
|
11241
11564
|
`;
|
|
11242
11565
|
writeFileSync11(plist, xml, { mode: 420 });
|
|
11566
|
+
try {
|
|
11567
|
+
execSync2(`launchctl bootout gui/$(id -u)/${SERVICE_LABEL}`, { stdio: "ignore" });
|
|
11568
|
+
} catch {}
|
|
11569
|
+
try {
|
|
11570
|
+
const pidPath = DAEMON_PATHS.PID_FILE;
|
|
11571
|
+
if (existsSync12(pidPath)) {
|
|
11572
|
+
const pid = parseInt(readFileSync11(pidPath, "utf8").trim(), 10);
|
|
11573
|
+
if (Number.isFinite(pid) && pid > 0) {
|
|
11574
|
+
try {
|
|
11575
|
+
process.kill(pid, "SIGTERM");
|
|
11576
|
+
} catch {}
|
|
11577
|
+
}
|
|
11578
|
+
}
|
|
11579
|
+
} catch {}
|
|
11243
11580
|
return {
|
|
11244
11581
|
platform: "darwin",
|
|
11245
11582
|
unitPath: plist,
|
|
@@ -11252,6 +11589,7 @@ function linuxUnitPath() {
|
|
|
11252
11589
|
function installLinux(args) {
|
|
11253
11590
|
const unit = linuxUnitPath();
|
|
11254
11591
|
mkdirSync7(dirname5(unit), { recursive: true });
|
|
11592
|
+
const nodeBin = process.execPath;
|
|
11255
11593
|
const execArgs = [
|
|
11256
11594
|
"daemon",
|
|
11257
11595
|
"up",
|
|
@@ -11266,7 +11604,7 @@ Wants=network-online.target
|
|
|
11266
11604
|
|
|
11267
11605
|
[Service]
|
|
11268
11606
|
Type=simple
|
|
11269
|
-
ExecStart=${shellQuote(args.binaryPath)} ${execArgs}
|
|
11607
|
+
ExecStart=${shellQuote(nodeBin)} ${shellQuote(args.binaryPath)} ${execArgs}
|
|
11270
11608
|
Restart=always
|
|
11271
11609
|
RestartSec=3
|
|
11272
11610
|
StandardOutput=append:${DAEMON_PATHS.LOG_FILE}
|
|
@@ -11277,6 +11615,20 @@ Environment=PATH=/usr/local/bin:/usr/bin:/bin
|
|
|
11277
11615
|
WantedBy=default.target
|
|
11278
11616
|
`;
|
|
11279
11617
|
writeFileSync11(unit, content, { mode: 420 });
|
|
11618
|
+
try {
|
|
11619
|
+
execSync2(`systemctl --user stop ${SYSTEMD_UNIT}`, { stdio: "ignore" });
|
|
11620
|
+
} catch {}
|
|
11621
|
+
try {
|
|
11622
|
+
const pidPath = DAEMON_PATHS.PID_FILE;
|
|
11623
|
+
if (existsSync12(pidPath)) {
|
|
11624
|
+
const pid = parseInt(readFileSync11(pidPath, "utf8").trim(), 10);
|
|
11625
|
+
if (Number.isFinite(pid) && pid > 0) {
|
|
11626
|
+
try {
|
|
11627
|
+
process.kill(pid, "SIGTERM");
|
|
11628
|
+
} catch {}
|
|
11629
|
+
}
|
|
11630
|
+
}
|
|
11631
|
+
} catch {}
|
|
11280
11632
|
return {
|
|
11281
11633
|
platform: "linux",
|
|
11282
11634
|
unitPath: unit,
|
|
@@ -11831,11 +12183,11 @@ function uninstallAllowedTools() {
|
|
|
11831
12183
|
}
|
|
11832
12184
|
function installHooks() {
|
|
11833
12185
|
const settings = readClaudeSettings();
|
|
11834
|
-
const
|
|
12186
|
+
const hooks2 = (settings.hooks ??= {}) ?? {};
|
|
11835
12187
|
let added = 0;
|
|
11836
12188
|
let unchanged = 0;
|
|
11837
12189
|
const ensure = (event, command) => {
|
|
11838
|
-
const list =
|
|
12190
|
+
const list = hooks2[event] ??= [];
|
|
11839
12191
|
const alreadyPresent = list.some((entry) => (entry.hooks ?? []).some((h) => h.command === command));
|
|
11840
12192
|
if (alreadyPresent) {
|
|
11841
12193
|
unchanged += 1;
|
|
@@ -11846,7 +12198,7 @@ function installHooks() {
|
|
|
11846
12198
|
};
|
|
11847
12199
|
ensure("Stop", HOOK_COMMAND_STOP);
|
|
11848
12200
|
ensure("UserPromptSubmit", HOOK_COMMAND_USER_PROMPT);
|
|
11849
|
-
settings.hooks =
|
|
12201
|
+
settings.hooks = hooks2;
|
|
11850
12202
|
writeClaudeSettings(settings);
|
|
11851
12203
|
return { added, unchanged };
|
|
11852
12204
|
}
|
|
@@ -11854,24 +12206,24 @@ function uninstallHooks() {
|
|
|
11854
12206
|
if (!existsSync13(CLAUDE_SETTINGS))
|
|
11855
12207
|
return 0;
|
|
11856
12208
|
const settings = readClaudeSettings();
|
|
11857
|
-
const
|
|
11858
|
-
if (!
|
|
12209
|
+
const hooks2 = settings.hooks;
|
|
12210
|
+
if (!hooks2)
|
|
11859
12211
|
return 0;
|
|
11860
12212
|
let removed = 0;
|
|
11861
|
-
for (const event of Object.keys(
|
|
12213
|
+
for (const event of Object.keys(hooks2)) {
|
|
11862
12214
|
const kept = [];
|
|
11863
|
-
for (const entry of
|
|
12215
|
+
for (const entry of hooks2[event] ?? []) {
|
|
11864
12216
|
const filtered = (entry.hooks ?? []).filter((h) => !(h.command ?? "").includes(HOOK_MARKER));
|
|
11865
12217
|
removed += (entry.hooks ?? []).length - filtered.length;
|
|
11866
12218
|
if (filtered.length > 0)
|
|
11867
12219
|
kept.push({ ...entry, hooks: filtered });
|
|
11868
12220
|
}
|
|
11869
12221
|
if (kept.length === 0)
|
|
11870
|
-
delete
|
|
12222
|
+
delete hooks2[event];
|
|
11871
12223
|
else
|
|
11872
|
-
|
|
12224
|
+
hooks2[event] = kept;
|
|
11873
12225
|
}
|
|
11874
|
-
settings.hooks =
|
|
12226
|
+
settings.hooks = hooks2;
|
|
11875
12227
|
writeClaudeSettings(settings);
|
|
11876
12228
|
return removed;
|
|
11877
12229
|
}
|
|
@@ -12176,10 +12528,10 @@ async function uninstall() {
|
|
|
12176
12528
|
try {
|
|
12177
12529
|
const raw = readFileSync13(PATHS.CLAUDE_SETTINGS, "utf-8");
|
|
12178
12530
|
const config = JSON.parse(raw);
|
|
12179
|
-
const
|
|
12180
|
-
if (
|
|
12531
|
+
const hooks2 = config.hooks;
|
|
12532
|
+
if (hooks2) {
|
|
12181
12533
|
let removedHooks = 0;
|
|
12182
|
-
for (const [event, entries] of Object.entries(
|
|
12534
|
+
for (const [event, entries] of Object.entries(hooks2)) {
|
|
12183
12535
|
if (!Array.isArray(entries))
|
|
12184
12536
|
continue;
|
|
12185
12537
|
const filtered = entries.filter((h) => {
|
|
@@ -12189,9 +12541,9 @@ async function uninstall() {
|
|
|
12189
12541
|
if (filtered.length < entries.length) {
|
|
12190
12542
|
removedHooks += entries.length - filtered.length;
|
|
12191
12543
|
if (filtered.length === 0)
|
|
12192
|
-
delete
|
|
12544
|
+
delete hooks2[event];
|
|
12193
12545
|
else
|
|
12194
|
-
|
|
12546
|
+
hooks2[event] = filtered;
|
|
12195
12547
|
}
|
|
12196
12548
|
}
|
|
12197
12549
|
if (removedHooks > 0) {
|
|
@@ -12393,8 +12745,8 @@ async function checkBrokerWs() {
|
|
|
12393
12745
|
const wsUrl = URLS.BROKER;
|
|
12394
12746
|
const start = Date.now();
|
|
12395
12747
|
try {
|
|
12396
|
-
const
|
|
12397
|
-
const ws = new
|
|
12748
|
+
const WebSocket4 = (await import("ws")).default;
|
|
12749
|
+
const ws = new WebSocket4(wsUrl);
|
|
12398
12750
|
const result = await new Promise((resolve2) => {
|
|
12399
12751
|
const timer = setTimeout(() => {
|
|
12400
12752
|
try {
|
|
@@ -12505,11 +12857,11 @@ __export(exports_status, {
|
|
|
12505
12857
|
runStatus: () => runStatus2
|
|
12506
12858
|
});
|
|
12507
12859
|
import { statSync as statSync4, existsSync as existsSync16 } from "node:fs";
|
|
12508
|
-
import
|
|
12860
|
+
import WebSocket4 from "ws";
|
|
12509
12861
|
async function probeBroker(url, timeoutMs = 4000) {
|
|
12510
12862
|
return new Promise((resolve2) => {
|
|
12511
12863
|
const started = Date.now();
|
|
12512
|
-
const ws = new
|
|
12864
|
+
const ws = new WebSocket4(url);
|
|
12513
12865
|
const timer = setTimeout(() => {
|
|
12514
12866
|
try {
|
|
12515
12867
|
ws.terminate();
|
|
@@ -14530,17 +14882,17 @@ async function runUnwatch(id, opts) {
|
|
|
14530
14882
|
}
|
|
14531
14883
|
async function runWebhookList(opts) {
|
|
14532
14884
|
return await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
|
|
14533
|
-
const
|
|
14885
|
+
const hooks2 = await client.listWebhooks();
|
|
14534
14886
|
if (opts.json) {
|
|
14535
|
-
emitJson(
|
|
14887
|
+
emitJson(hooks2);
|
|
14536
14888
|
return EXIT.SUCCESS;
|
|
14537
14889
|
}
|
|
14538
|
-
if (
|
|
14890
|
+
if (hooks2.length === 0) {
|
|
14539
14891
|
render.info(dim("(no webhooks)"));
|
|
14540
14892
|
return EXIT.SUCCESS;
|
|
14541
14893
|
}
|
|
14542
|
-
render.section(`webhooks (${
|
|
14543
|
-
for (const h of
|
|
14894
|
+
render.section(`webhooks (${hooks2.length})`);
|
|
14895
|
+
for (const h of hooks2) {
|
|
14544
14896
|
const dot = h.active ? "●" : dim("○");
|
|
14545
14897
|
process.stdout.write(` ${dot} ${bold(h.name)} ${dim("· " + h.url)}
|
|
14546
14898
|
`);
|
|
@@ -15511,7 +15863,7 @@ __export(exports_file, {
|
|
|
15511
15863
|
runFileShare: () => runFileShare,
|
|
15512
15864
|
runFileGet: () => runFileGet
|
|
15513
15865
|
});
|
|
15514
|
-
import { hostname as
|
|
15866
|
+
import { hostname as osHostname2 } from "node:os";
|
|
15515
15867
|
import { resolve as resolvePath, basename, dirname as dirname9 } from "node:path";
|
|
15516
15868
|
import { statSync as statSync7, existsSync as existsSync26, writeFileSync as writeFileSync17, mkdirSync as mkdirSync11 } from "node:fs";
|
|
15517
15869
|
function emitJson2(data) {
|
|
@@ -15543,7 +15895,7 @@ async function runFileShare(filePath, opts) {
|
|
|
15543
15895
|
return await withMesh({ meshSlug: opts.mesh ?? null }, async (client, mesh) => {
|
|
15544
15896
|
if (opts.to && !opts.upload) {
|
|
15545
15897
|
const peers = await client.listPeers();
|
|
15546
|
-
const myHost =
|
|
15898
|
+
const myHost = osHostname2();
|
|
15547
15899
|
const target = peers.find((p) => {
|
|
15548
15900
|
if (!p.hostname || p.hostname !== myHost)
|
|
15549
15901
|
return false;
|
|
@@ -15705,7 +16057,7 @@ var require_client = __commonJS((exports) => {
|
|
|
15705
16057
|
var ws_1 = __importDefault(__require("ws"));
|
|
15706
16058
|
var crypto_js_1 = require_crypto();
|
|
15707
16059
|
var MAX_QUEUED2 = 100;
|
|
15708
|
-
var
|
|
16060
|
+
var HELLO_ACK_TIMEOUT_MS4 = 5000;
|
|
15709
16061
|
var BACKOFF_CAPS2 = [1000, 2000, 4000, 8000, 16000, 30000];
|
|
15710
16062
|
|
|
15711
16063
|
class MeshClient extends node_events_1.EventEmitter {
|
|
@@ -15770,7 +16122,7 @@ var require_client = __commonJS((exports) => {
|
|
|
15770
16122
|
this.debug("hello_ack timeout");
|
|
15771
16123
|
ws.close();
|
|
15772
16124
|
reject(new Error("hello_ack timeout"));
|
|
15773
|
-
},
|
|
16125
|
+
}, HELLO_ACK_TIMEOUT_MS4);
|
|
15774
16126
|
};
|
|
15775
16127
|
const onMessage = (raw) => {
|
|
15776
16128
|
let msg;
|
|
@@ -19550,4 +19902,4 @@ main().catch((err) => {
|
|
|
19550
19902
|
process.exit(EXIT.INTERNAL_ERROR);
|
|
19551
19903
|
});
|
|
19552
19904
|
|
|
19553
|
-
//# debugId=
|
|
19905
|
+
//# debugId=6DFC8CA65CBA4E0364756E2164756E21
|