claudemesh-cli 1.29.0 → 1.30.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/dist/entrypoints/cli.js +364 -43
- package/dist/entrypoints/cli.js.map +13 -11
- 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.0", 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();
|
|
@@ -11831,11 +12152,11 @@ function uninstallAllowedTools() {
|
|
|
11831
12152
|
}
|
|
11832
12153
|
function installHooks() {
|
|
11833
12154
|
const settings = readClaudeSettings();
|
|
11834
|
-
const
|
|
12155
|
+
const hooks2 = (settings.hooks ??= {}) ?? {};
|
|
11835
12156
|
let added = 0;
|
|
11836
12157
|
let unchanged = 0;
|
|
11837
12158
|
const ensure = (event, command) => {
|
|
11838
|
-
const list =
|
|
12159
|
+
const list = hooks2[event] ??= [];
|
|
11839
12160
|
const alreadyPresent = list.some((entry) => (entry.hooks ?? []).some((h) => h.command === command));
|
|
11840
12161
|
if (alreadyPresent) {
|
|
11841
12162
|
unchanged += 1;
|
|
@@ -11846,7 +12167,7 @@ function installHooks() {
|
|
|
11846
12167
|
};
|
|
11847
12168
|
ensure("Stop", HOOK_COMMAND_STOP);
|
|
11848
12169
|
ensure("UserPromptSubmit", HOOK_COMMAND_USER_PROMPT);
|
|
11849
|
-
settings.hooks =
|
|
12170
|
+
settings.hooks = hooks2;
|
|
11850
12171
|
writeClaudeSettings(settings);
|
|
11851
12172
|
return { added, unchanged };
|
|
11852
12173
|
}
|
|
@@ -11854,24 +12175,24 @@ function uninstallHooks() {
|
|
|
11854
12175
|
if (!existsSync13(CLAUDE_SETTINGS))
|
|
11855
12176
|
return 0;
|
|
11856
12177
|
const settings = readClaudeSettings();
|
|
11857
|
-
const
|
|
11858
|
-
if (!
|
|
12178
|
+
const hooks2 = settings.hooks;
|
|
12179
|
+
if (!hooks2)
|
|
11859
12180
|
return 0;
|
|
11860
12181
|
let removed = 0;
|
|
11861
|
-
for (const event of Object.keys(
|
|
12182
|
+
for (const event of Object.keys(hooks2)) {
|
|
11862
12183
|
const kept = [];
|
|
11863
|
-
for (const entry of
|
|
12184
|
+
for (const entry of hooks2[event] ?? []) {
|
|
11864
12185
|
const filtered = (entry.hooks ?? []).filter((h) => !(h.command ?? "").includes(HOOK_MARKER));
|
|
11865
12186
|
removed += (entry.hooks ?? []).length - filtered.length;
|
|
11866
12187
|
if (filtered.length > 0)
|
|
11867
12188
|
kept.push({ ...entry, hooks: filtered });
|
|
11868
12189
|
}
|
|
11869
12190
|
if (kept.length === 0)
|
|
11870
|
-
delete
|
|
12191
|
+
delete hooks2[event];
|
|
11871
12192
|
else
|
|
11872
|
-
|
|
12193
|
+
hooks2[event] = kept;
|
|
11873
12194
|
}
|
|
11874
|
-
settings.hooks =
|
|
12195
|
+
settings.hooks = hooks2;
|
|
11875
12196
|
writeClaudeSettings(settings);
|
|
11876
12197
|
return removed;
|
|
11877
12198
|
}
|
|
@@ -12176,10 +12497,10 @@ async function uninstall() {
|
|
|
12176
12497
|
try {
|
|
12177
12498
|
const raw = readFileSync13(PATHS.CLAUDE_SETTINGS, "utf-8");
|
|
12178
12499
|
const config = JSON.parse(raw);
|
|
12179
|
-
const
|
|
12180
|
-
if (
|
|
12500
|
+
const hooks2 = config.hooks;
|
|
12501
|
+
if (hooks2) {
|
|
12181
12502
|
let removedHooks = 0;
|
|
12182
|
-
for (const [event, entries] of Object.entries(
|
|
12503
|
+
for (const [event, entries] of Object.entries(hooks2)) {
|
|
12183
12504
|
if (!Array.isArray(entries))
|
|
12184
12505
|
continue;
|
|
12185
12506
|
const filtered = entries.filter((h) => {
|
|
@@ -12189,9 +12510,9 @@ async function uninstall() {
|
|
|
12189
12510
|
if (filtered.length < entries.length) {
|
|
12190
12511
|
removedHooks += entries.length - filtered.length;
|
|
12191
12512
|
if (filtered.length === 0)
|
|
12192
|
-
delete
|
|
12513
|
+
delete hooks2[event];
|
|
12193
12514
|
else
|
|
12194
|
-
|
|
12515
|
+
hooks2[event] = filtered;
|
|
12195
12516
|
}
|
|
12196
12517
|
}
|
|
12197
12518
|
if (removedHooks > 0) {
|
|
@@ -12393,8 +12714,8 @@ async function checkBrokerWs() {
|
|
|
12393
12714
|
const wsUrl = URLS.BROKER;
|
|
12394
12715
|
const start = Date.now();
|
|
12395
12716
|
try {
|
|
12396
|
-
const
|
|
12397
|
-
const ws = new
|
|
12717
|
+
const WebSocket4 = (await import("ws")).default;
|
|
12718
|
+
const ws = new WebSocket4(wsUrl);
|
|
12398
12719
|
const result = await new Promise((resolve2) => {
|
|
12399
12720
|
const timer = setTimeout(() => {
|
|
12400
12721
|
try {
|
|
@@ -12505,11 +12826,11 @@ __export(exports_status, {
|
|
|
12505
12826
|
runStatus: () => runStatus2
|
|
12506
12827
|
});
|
|
12507
12828
|
import { statSync as statSync4, existsSync as existsSync16 } from "node:fs";
|
|
12508
|
-
import
|
|
12829
|
+
import WebSocket4 from "ws";
|
|
12509
12830
|
async function probeBroker(url, timeoutMs = 4000) {
|
|
12510
12831
|
return new Promise((resolve2) => {
|
|
12511
12832
|
const started = Date.now();
|
|
12512
|
-
const ws = new
|
|
12833
|
+
const ws = new WebSocket4(url);
|
|
12513
12834
|
const timer = setTimeout(() => {
|
|
12514
12835
|
try {
|
|
12515
12836
|
ws.terminate();
|
|
@@ -14530,17 +14851,17 @@ async function runUnwatch(id, opts) {
|
|
|
14530
14851
|
}
|
|
14531
14852
|
async function runWebhookList(opts) {
|
|
14532
14853
|
return await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
|
|
14533
|
-
const
|
|
14854
|
+
const hooks2 = await client.listWebhooks();
|
|
14534
14855
|
if (opts.json) {
|
|
14535
|
-
emitJson(
|
|
14856
|
+
emitJson(hooks2);
|
|
14536
14857
|
return EXIT.SUCCESS;
|
|
14537
14858
|
}
|
|
14538
|
-
if (
|
|
14859
|
+
if (hooks2.length === 0) {
|
|
14539
14860
|
render.info(dim("(no webhooks)"));
|
|
14540
14861
|
return EXIT.SUCCESS;
|
|
14541
14862
|
}
|
|
14542
|
-
render.section(`webhooks (${
|
|
14543
|
-
for (const h of
|
|
14863
|
+
render.section(`webhooks (${hooks2.length})`);
|
|
14864
|
+
for (const h of hooks2) {
|
|
14544
14865
|
const dot = h.active ? "●" : dim("○");
|
|
14545
14866
|
process.stdout.write(` ${dot} ${bold(h.name)} ${dim("· " + h.url)}
|
|
14546
14867
|
`);
|
|
@@ -15511,7 +15832,7 @@ __export(exports_file, {
|
|
|
15511
15832
|
runFileShare: () => runFileShare,
|
|
15512
15833
|
runFileGet: () => runFileGet
|
|
15513
15834
|
});
|
|
15514
|
-
import { hostname as
|
|
15835
|
+
import { hostname as osHostname2 } from "node:os";
|
|
15515
15836
|
import { resolve as resolvePath, basename, dirname as dirname9 } from "node:path";
|
|
15516
15837
|
import { statSync as statSync7, existsSync as existsSync26, writeFileSync as writeFileSync17, mkdirSync as mkdirSync11 } from "node:fs";
|
|
15517
15838
|
function emitJson2(data) {
|
|
@@ -15543,7 +15864,7 @@ async function runFileShare(filePath, opts) {
|
|
|
15543
15864
|
return await withMesh({ meshSlug: opts.mesh ?? null }, async (client, mesh) => {
|
|
15544
15865
|
if (opts.to && !opts.upload) {
|
|
15545
15866
|
const peers = await client.listPeers();
|
|
15546
|
-
const myHost =
|
|
15867
|
+
const myHost = osHostname2();
|
|
15547
15868
|
const target = peers.find((p) => {
|
|
15548
15869
|
if (!p.hostname || p.hostname !== myHost)
|
|
15549
15870
|
return false;
|
|
@@ -15705,7 +16026,7 @@ var require_client = __commonJS((exports) => {
|
|
|
15705
16026
|
var ws_1 = __importDefault(__require("ws"));
|
|
15706
16027
|
var crypto_js_1 = require_crypto();
|
|
15707
16028
|
var MAX_QUEUED2 = 100;
|
|
15708
|
-
var
|
|
16029
|
+
var HELLO_ACK_TIMEOUT_MS4 = 5000;
|
|
15709
16030
|
var BACKOFF_CAPS2 = [1000, 2000, 4000, 8000, 16000, 30000];
|
|
15710
16031
|
|
|
15711
16032
|
class MeshClient extends node_events_1.EventEmitter {
|
|
@@ -15770,7 +16091,7 @@ var require_client = __commonJS((exports) => {
|
|
|
15770
16091
|
this.debug("hello_ack timeout");
|
|
15771
16092
|
ws.close();
|
|
15772
16093
|
reject(new Error("hello_ack timeout"));
|
|
15773
|
-
},
|
|
16094
|
+
}, HELLO_ACK_TIMEOUT_MS4);
|
|
15774
16095
|
};
|
|
15775
16096
|
const onMessage = (raw) => {
|
|
15776
16097
|
let msg;
|
|
@@ -19550,4 +19871,4 @@ main().catch((err) => {
|
|
|
19550
19871
|
process.exit(EXIT.INTERNAL_ERROR);
|
|
19551
19872
|
});
|
|
19552
19873
|
|
|
19553
|
-
//# debugId=
|
|
19874
|
+
//# debugId=A7687DD2912DA01C64756E2164756E21
|