claudemesh-cli 1.28.0 → 1.29.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 +415 -154
- package/dist/entrypoints/cli.js.map +11 -8
- package/dist/entrypoints/mcp.js +2 -2
- package/dist/entrypoints/mcp.js.map +1 -1
- package/package.json +1 -1
package/dist/entrypoints/cli.js
CHANGED
|
@@ -103,7 +103,7 @@ __export(exports_urls, {
|
|
|
103
103
|
VERSION: () => VERSION,
|
|
104
104
|
URLS: () => URLS
|
|
105
105
|
});
|
|
106
|
-
var URLS, VERSION = "1.
|
|
106
|
+
var URLS, VERSION = "1.29.0", env;
|
|
107
107
|
var init_urls = __esm(() => {
|
|
108
108
|
URLS = {
|
|
109
109
|
BROKER: process.env.CLAUDEMESH_BROKER_URL ?? "wss://ic.claudemesh.com/ws",
|
|
@@ -3668,7 +3668,50 @@ var init_local_token = __esm(() => {
|
|
|
3668
3668
|
init_paths2();
|
|
3669
3669
|
});
|
|
3670
3670
|
|
|
3671
|
+
// src/services/session/token.ts
|
|
3672
|
+
var exports_token = {};
|
|
3673
|
+
__export(exports_token, {
|
|
3674
|
+
readSessionTokenFromEnv: () => readSessionTokenFromEnv,
|
|
3675
|
+
mintSessionToken: () => mintSessionToken,
|
|
3676
|
+
TOKEN_FILE_ENV: () => TOKEN_FILE_ENV
|
|
3677
|
+
});
|
|
3678
|
+
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
3679
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "node:fs";
|
|
3680
|
+
function mintSessionToken(dir, fileName = "session-token") {
|
|
3681
|
+
const token = randomBytes5(32).toString("hex");
|
|
3682
|
+
const filePath = `${dir}/${fileName}`;
|
|
3683
|
+
writeFileSync5(filePath, token, { mode: 384 });
|
|
3684
|
+
return { token, filePath };
|
|
3685
|
+
}
|
|
3686
|
+
function readSessionTokenFromEnv(env2 = process.env) {
|
|
3687
|
+
const direct = env2.CLAUDEMESH_IPC_TOKEN;
|
|
3688
|
+
if (direct && /^[0-9a-f]{64}$/i.test(direct))
|
|
3689
|
+
return direct.toLowerCase();
|
|
3690
|
+
const path = env2[ENV_TOKEN_FILE];
|
|
3691
|
+
if (!path)
|
|
3692
|
+
return null;
|
|
3693
|
+
try {
|
|
3694
|
+
if (!existsSync5(path))
|
|
3695
|
+
return null;
|
|
3696
|
+
const raw = readFileSync5(path, "utf8").trim();
|
|
3697
|
+
if (/^[0-9a-f]{64}$/i.test(raw))
|
|
3698
|
+
return raw.toLowerCase();
|
|
3699
|
+
return null;
|
|
3700
|
+
} catch {
|
|
3701
|
+
return null;
|
|
3702
|
+
}
|
|
3703
|
+
}
|
|
3704
|
+
var ENV_TOKEN_FILE = "CLAUDEMESH_IPC_TOKEN_FILE", TOKEN_FILE_ENV;
|
|
3705
|
+
var init_token = __esm(() => {
|
|
3706
|
+
TOKEN_FILE_ENV = ENV_TOKEN_FILE;
|
|
3707
|
+
});
|
|
3708
|
+
|
|
3671
3709
|
// src/daemon/ipc/client.ts
|
|
3710
|
+
var exports_client = {};
|
|
3711
|
+
__export(exports_client, {
|
|
3712
|
+
ipc: () => ipc,
|
|
3713
|
+
IpcError: () => IpcError
|
|
3714
|
+
});
|
|
3672
3715
|
import { request as httpRequest } from "node:http";
|
|
3673
3716
|
async function ipc(opts) {
|
|
3674
3717
|
const useTcp = !!opts.preferTcp;
|
|
@@ -3688,6 +3731,11 @@ async function ipc(opts) {
|
|
|
3688
3731
|
throw new IpcError(0, null, "daemon local token not found; is the daemon running?");
|
|
3689
3732
|
headers.authorization = `Bearer ${tok}`;
|
|
3690
3733
|
}
|
|
3734
|
+
if (!useTcp) {
|
|
3735
|
+
const sessionTok = readSessionTokenFromEnv();
|
|
3736
|
+
if (sessionTok)
|
|
3737
|
+
headers.authorization = `ClaudeMesh-Session ${sessionTok}`;
|
|
3738
|
+
}
|
|
3691
3739
|
return new Promise((resolve, reject) => {
|
|
3692
3740
|
const req = httpRequest(useTcp ? { host: DAEMON_TCP_HOST, port: DAEMON_TCP_DEFAULT_PORT, path: opts.path, method: opts.method ?? "GET", headers } : { socketPath: DAEMON_PATHS.SOCK_FILE, path: opts.path, method: opts.method ?? "GET", headers }, (res) => {
|
|
3693
3741
|
const chunks = [];
|
|
@@ -3712,6 +3760,7 @@ var IpcError;
|
|
|
3712
3760
|
var init_client3 = __esm(() => {
|
|
3713
3761
|
init_paths2();
|
|
3714
3762
|
init_local_token();
|
|
3763
|
+
init_token();
|
|
3715
3764
|
IpcError = class IpcError extends Error {
|
|
3716
3765
|
status;
|
|
3717
3766
|
payload;
|
|
@@ -3729,7 +3778,7 @@ __export(exports_lifecycle, {
|
|
|
3729
3778
|
ensureDaemonReady: () => ensureDaemonReady,
|
|
3730
3779
|
_resetDaemonReadyCache: () => _resetDaemonReadyCache
|
|
3731
3780
|
});
|
|
3732
|
-
import { existsSync as
|
|
3781
|
+
import { existsSync as existsSync6, readFileSync as readFileSync6, statSync, unlinkSync as unlinkSync2, writeFileSync as writeFileSync6 } from "node:fs";
|
|
3733
3782
|
import { join as join4 } from "node:path";
|
|
3734
3783
|
async function ensureDaemonReady(opts = {}) {
|
|
3735
3784
|
if (lastResultThisProcess && (lastResultThisProcess.state === "up" || lastResultThisProcess.state === "started")) {
|
|
@@ -3770,7 +3819,7 @@ async function runEnsureDaemon(opts) {
|
|
|
3770
3819
|
return { state: "spawn-failed", durationMs: Date.now() - t0, reason: spawnRes.reason };
|
|
3771
3820
|
}
|
|
3772
3821
|
async function probeDaemon() {
|
|
3773
|
-
if (!
|
|
3822
|
+
if (!existsSync6(DAEMON_PATHS.SOCK_FILE))
|
|
3774
3823
|
return "absent";
|
|
3775
3824
|
try {
|
|
3776
3825
|
const res = await ipc({ path: "/v1/version", timeoutMs: PROBE_TIMEOUT_MS });
|
|
@@ -3803,7 +3852,7 @@ function recentSpawnFailureFresh() {
|
|
|
3803
3852
|
}
|
|
3804
3853
|
function markSpawnFailure() {
|
|
3805
3854
|
try {
|
|
3806
|
-
|
|
3855
|
+
writeFileSync6(SPAWN_FAIL_FILE(), String(Date.now()), { mode: 384 });
|
|
3807
3856
|
} catch {}
|
|
3808
3857
|
}
|
|
3809
3858
|
function clearSpawnFailure() {
|
|
@@ -3840,9 +3889,9 @@ async function spawnDaemon(opts) {
|
|
|
3840
3889
|
}
|
|
3841
3890
|
async function acquireOrShareLock(_opts) {
|
|
3842
3891
|
const lockPath = SPAWN_LOCK_FILE();
|
|
3843
|
-
if (
|
|
3892
|
+
if (existsSync6(lockPath)) {
|
|
3844
3893
|
try {
|
|
3845
|
-
const pidStr =
|
|
3894
|
+
const pidStr = readFileSync6(lockPath, "utf8").trim();
|
|
3846
3895
|
const pid = Number.parseInt(pidStr, 10);
|
|
3847
3896
|
if (Number.isFinite(pid) && pid > 0) {
|
|
3848
3897
|
try {
|
|
@@ -3853,7 +3902,7 @@ async function acquireOrShareLock(_opts) {
|
|
|
3853
3902
|
} catch {}
|
|
3854
3903
|
}
|
|
3855
3904
|
try {
|
|
3856
|
-
|
|
3905
|
+
writeFileSync6(lockPath, String(process.pid), { mode: 384 });
|
|
3857
3906
|
} catch {}
|
|
3858
3907
|
return "acquired";
|
|
3859
3908
|
}
|
|
@@ -3865,7 +3914,7 @@ function releaseLock() {
|
|
|
3865
3914
|
async function pollForSocket(budgetMs) {
|
|
3866
3915
|
const start = Date.now();
|
|
3867
3916
|
while (Date.now() - start < budgetMs) {
|
|
3868
|
-
if (
|
|
3917
|
+
if (existsSync6(DAEMON_PATHS.SOCK_FILE)) {
|
|
3869
3918
|
const probe = await probeDaemon();
|
|
3870
3919
|
if (probe === "up")
|
|
3871
3920
|
return { ok: true };
|
|
@@ -3899,7 +3948,7 @@ __export(exports_launch, {
|
|
|
3899
3948
|
});
|
|
3900
3949
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
3901
3950
|
import { randomUUID } from "node:crypto";
|
|
3902
|
-
import { mkdtempSync, writeFileSync as
|
|
3951
|
+
import { mkdtempSync, writeFileSync as writeFileSync7, rmSync, readdirSync, statSync as statSync2, existsSync as existsSync7, readFileSync as readFileSync7 } from "node:fs";
|
|
3903
3952
|
import { tmpdir, hostname as hostname2, homedir as homedir3 } from "node:os";
|
|
3904
3953
|
import { join as join5 } from "node:path";
|
|
3905
3954
|
import { createInterface as createInterface4 } from "node:readline";
|
|
@@ -4248,8 +4297,8 @@ async function runLaunch(flags, rawArgs) {
|
|
|
4248
4297
|
await ensureDaemonRunning(mesh.slug, args.quiet);
|
|
4249
4298
|
try {
|
|
4250
4299
|
const claudeConfigPath = join5(homedir3(), ".claude.json");
|
|
4251
|
-
if (
|
|
4252
|
-
const claudeConfig = JSON.parse(
|
|
4300
|
+
if (existsSync7(claudeConfigPath)) {
|
|
4301
|
+
const claudeConfig = JSON.parse(readFileSync7(claudeConfigPath, "utf-8"));
|
|
4253
4302
|
const mcpServers = claudeConfig.mcpServers ?? {};
|
|
4254
4303
|
let cleaned = 0;
|
|
4255
4304
|
for (const key of Object.keys(mcpServers)) {
|
|
@@ -4267,7 +4316,7 @@ async function runLaunch(flags, rawArgs) {
|
|
|
4267
4316
|
}
|
|
4268
4317
|
if (cleaned > 0) {
|
|
4269
4318
|
claudeConfig.mcpServers = mcpServers;
|
|
4270
|
-
|
|
4319
|
+
writeFileSync7(claudeConfigPath, JSON.stringify(claudeConfig, null, 2) + `
|
|
4271
4320
|
`, "utf-8");
|
|
4272
4321
|
}
|
|
4273
4322
|
}
|
|
@@ -4293,8 +4342,37 @@ async function runLaunch(flags, rawArgs) {
|
|
|
4293
4342
|
...parsedGroups.length > 0 ? { groups: parsedGroups } : {},
|
|
4294
4343
|
messageMode
|
|
4295
4344
|
};
|
|
4296
|
-
|
|
4345
|
+
writeFileSync7(join5(tmpDir, "config.json"), JSON.stringify(sessionConfig, null, 2) + `
|
|
4297
4346
|
`, "utf-8");
|
|
4347
|
+
let sessionTokenFilePath = null;
|
|
4348
|
+
let sessionTokenForCleanup = null;
|
|
4349
|
+
try {
|
|
4350
|
+
const { mintSessionToken: mintSessionToken2, TOKEN_FILE_ENV: TOKEN_FILE_ENV2 } = await Promise.resolve().then(() => (init_token(), exports_token));
|
|
4351
|
+
const minted = mintSessionToken2(tmpDir);
|
|
4352
|
+
sessionTokenFilePath = minted.filePath;
|
|
4353
|
+
sessionTokenForCleanup = minted.token;
|
|
4354
|
+
const { ipc: ipc2 } = await Promise.resolve().then(() => (init_client3(), exports_client));
|
|
4355
|
+
const sessionIdForRegister = claudeSessionId ?? randomUUID();
|
|
4356
|
+
await ipc2({
|
|
4357
|
+
method: "POST",
|
|
4358
|
+
path: "/v1/sessions/register",
|
|
4359
|
+
timeoutMs: 3000,
|
|
4360
|
+
body: {
|
|
4361
|
+
token: minted.token,
|
|
4362
|
+
session_id: sessionIdForRegister,
|
|
4363
|
+
mesh: mesh.slug,
|
|
4364
|
+
display_name: displayName,
|
|
4365
|
+
pid: process.pid,
|
|
4366
|
+
cwd: process.cwd(),
|
|
4367
|
+
...role ? { role } : {},
|
|
4368
|
+
...parsedGroups.length > 0 ? { groups: parsedGroups.map((g) => `@${g.name}${g.role ? `:${g.role}` : ""}`) } : {}
|
|
4369
|
+
}
|
|
4370
|
+
}).catch(() => null);
|
|
4371
|
+
process._claudemeshTokenEnv = {
|
|
4372
|
+
name: TOKEN_FILE_ENV2,
|
|
4373
|
+
value: minted.filePath
|
|
4374
|
+
};
|
|
4375
|
+
} catch {}
|
|
4298
4376
|
if (!args.quiet) {
|
|
4299
4377
|
printBanner(displayName, mesh.slug, role, parsedGroups, messageMode);
|
|
4300
4378
|
}
|
|
@@ -4303,7 +4381,7 @@ async function runLaunch(flags, rawArgs) {
|
|
|
4303
4381
|
const claudeConfigPath = join5(homedir3(), ".claude.json");
|
|
4304
4382
|
let claudeConfig = {};
|
|
4305
4383
|
try {
|
|
4306
|
-
claudeConfig = JSON.parse(
|
|
4384
|
+
claudeConfig = JSON.parse(readFileSync7(claudeConfigPath, "utf-8"));
|
|
4307
4385
|
} catch {
|
|
4308
4386
|
claudeConfig = {};
|
|
4309
4387
|
}
|
|
@@ -4330,7 +4408,7 @@ async function runLaunch(flags, rawArgs) {
|
|
|
4330
4408
|
meshMcpEntries.push({ key: entryKey, entry });
|
|
4331
4409
|
}
|
|
4332
4410
|
claudeConfig.mcpServers = mcpServers;
|
|
4333
|
-
|
|
4411
|
+
writeFileSync7(claudeConfigPath, JSON.stringify(claudeConfig, null, 2) + `
|
|
4334
4412
|
`, "utf-8");
|
|
4335
4413
|
if (!args.quiet && meshMcpEntries.length > 0) {
|
|
4336
4414
|
console.log(` ${meshMcpEntries.length} mesh service(s) registered as native MCPs:`);
|
|
@@ -4372,7 +4450,7 @@ async function runLaunch(flags, rawArgs) {
|
|
|
4372
4450
|
join5(homedir3(), ".claude", "bin", "claude")
|
|
4373
4451
|
];
|
|
4374
4452
|
for (const c of candidates) {
|
|
4375
|
-
if (
|
|
4453
|
+
if (existsSync7(c)) {
|
|
4376
4454
|
claudeBin = c;
|
|
4377
4455
|
break;
|
|
4378
4456
|
}
|
|
@@ -4382,13 +4460,13 @@ async function runLaunch(flags, rawArgs) {
|
|
|
4382
4460
|
if (meshMcpEntries.length > 0) {
|
|
4383
4461
|
try {
|
|
4384
4462
|
const claudeConfigPath = join5(homedir3(), ".claude.json");
|
|
4385
|
-
const claudeConfig = JSON.parse(
|
|
4463
|
+
const claudeConfig = JSON.parse(readFileSync7(claudeConfigPath, "utf-8"));
|
|
4386
4464
|
const mcpServers = claudeConfig.mcpServers ?? {};
|
|
4387
4465
|
for (const { key } of meshMcpEntries) {
|
|
4388
4466
|
delete mcpServers[key];
|
|
4389
4467
|
}
|
|
4390
4468
|
claudeConfig.mcpServers = mcpServers;
|
|
4391
|
-
|
|
4469
|
+
writeFileSync7(claudeConfigPath, JSON.stringify(claudeConfig, null, 2) + `
|
|
4392
4470
|
`, "utf-8");
|
|
4393
4471
|
} catch {}
|
|
4394
4472
|
}
|
|
@@ -4418,6 +4496,7 @@ async function runLaunch(flags, rawArgs) {
|
|
|
4418
4496
|
CLAUDEMESH_CONFIG_DIR: tmpDir,
|
|
4419
4497
|
CLAUDEMESH_DISPLAY_NAME: displayName,
|
|
4420
4498
|
...claudeSessionId ? { CLAUDEMESH_SESSION_ID: claudeSessionId } : {},
|
|
4499
|
+
...sessionTokenFilePath ? { CLAUDEMESH_IPC_TOKEN_FILE: sessionTokenFilePath } : {},
|
|
4421
4500
|
MCP_TIMEOUT: process.env.MCP_TIMEOUT ?? "30000",
|
|
4422
4501
|
MAX_MCP_OUTPUT_TOKENS: process.env.MAX_MCP_OUTPUT_TOKENS ?? "50000",
|
|
4423
4502
|
...role ? { CLAUDEMESH_ROLE: role } : {}
|
|
@@ -5085,7 +5164,7 @@ __export(exports_join, {
|
|
|
5085
5164
|
runJoin: () => runJoin
|
|
5086
5165
|
});
|
|
5087
5166
|
import sodium3 from "libsodium-wrappers";
|
|
5088
|
-
import { writeFileSync as
|
|
5167
|
+
import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync4 } from "node:fs";
|
|
5089
5168
|
import { join as join6, dirname as dirname3 } from "node:path";
|
|
5090
5169
|
import { homedir as homedir4, hostname as hostname3 } from "node:os";
|
|
5091
5170
|
function deriveAppBaseUrl() {
|
|
@@ -5210,7 +5289,7 @@ async function runJoin(args) {
|
|
|
5210
5289
|
const inviteFile = join6(configDir, `invite-${payload.mesh_slug}.txt`);
|
|
5211
5290
|
try {
|
|
5212
5291
|
mkdirSync4(dirname3(inviteFile), { recursive: true });
|
|
5213
|
-
|
|
5292
|
+
writeFileSync8(inviteFile, link, "utf-8");
|
|
5214
5293
|
} catch {}
|
|
5215
5294
|
console.log("");
|
|
5216
5295
|
console.log(`✓ Joined "${payload.mesh_slug}" as ${displayName}${enroll.alreadyMember ? " (already a member — re-enrolled with same pubkey)" : ""}`);
|
|
@@ -7660,6 +7739,45 @@ var init_daemon_route = __esm(() => {
|
|
|
7660
7739
|
init_warnings();
|
|
7661
7740
|
});
|
|
7662
7741
|
|
|
7742
|
+
// src/services/session/resolve.ts
|
|
7743
|
+
var exports_resolve = {};
|
|
7744
|
+
__export(exports_resolve, {
|
|
7745
|
+
getSessionInfo: () => getSessionInfo,
|
|
7746
|
+
_resetSessionCache: () => _resetSessionCache
|
|
7747
|
+
});
|
|
7748
|
+
async function getSessionInfo() {
|
|
7749
|
+
if (cached !== undefined)
|
|
7750
|
+
return cached;
|
|
7751
|
+
const tok = readSessionTokenFromEnv();
|
|
7752
|
+
if (!tok) {
|
|
7753
|
+
cached = null;
|
|
7754
|
+
return null;
|
|
7755
|
+
}
|
|
7756
|
+
try {
|
|
7757
|
+
const res = await ipc({
|
|
7758
|
+
path: "/v1/sessions/me",
|
|
7759
|
+
timeoutMs: 1500
|
|
7760
|
+
});
|
|
7761
|
+
if (res.status !== 200 || !res.body.session) {
|
|
7762
|
+
cached = null;
|
|
7763
|
+
return null;
|
|
7764
|
+
}
|
|
7765
|
+
cached = res.body.session;
|
|
7766
|
+
return cached;
|
|
7767
|
+
} catch {
|
|
7768
|
+
cached = null;
|
|
7769
|
+
return null;
|
|
7770
|
+
}
|
|
7771
|
+
}
|
|
7772
|
+
function _resetSessionCache() {
|
|
7773
|
+
cached = undefined;
|
|
7774
|
+
}
|
|
7775
|
+
var cached = undefined;
|
|
7776
|
+
var init_resolve = __esm(() => {
|
|
7777
|
+
init_client3();
|
|
7778
|
+
init_token();
|
|
7779
|
+
});
|
|
7780
|
+
|
|
7663
7781
|
// src/commands/peers.ts
|
|
7664
7782
|
var exports_peers = {};
|
|
7665
7783
|
__export(exports_peers, {
|
|
@@ -7699,7 +7817,14 @@ function annotateSelf(peer, selfMemberPubkey, selfSessionPubkey) {
|
|
|
7699
7817
|
}
|
|
7700
7818
|
async function runPeers(flags) {
|
|
7701
7819
|
const config = readConfig();
|
|
7702
|
-
|
|
7820
|
+
let slugs;
|
|
7821
|
+
if (flags.mesh) {
|
|
7822
|
+
slugs = [flags.mesh];
|
|
7823
|
+
} else {
|
|
7824
|
+
const { getSessionInfo: getSessionInfo2 } = await Promise.resolve().then(() => (init_resolve(), exports_resolve));
|
|
7825
|
+
const sess = await getSessionInfo2();
|
|
7826
|
+
slugs = sess ? [sess.mesh] : config.meshes.map((m) => m.slug);
|
|
7827
|
+
}
|
|
7703
7828
|
if (slugs.length === 0) {
|
|
7704
7829
|
render.err("No meshes joined.");
|
|
7705
7830
|
render.hint("claudemesh <invite-url> # join + launch");
|
|
@@ -8669,12 +8794,12 @@ var init_whoami = __esm(() => {
|
|
|
8669
8794
|
});
|
|
8670
8795
|
|
|
8671
8796
|
// src/daemon/lock.ts
|
|
8672
|
-
import { existsSync as
|
|
8797
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync8, unlinkSync as unlinkSync3, writeFileSync as writeFileSync9 } from "node:fs";
|
|
8673
8798
|
import { dirname as dirname4 } from "node:path";
|
|
8674
8799
|
function acquireSingletonLock() {
|
|
8675
8800
|
mkdirSync5(dirname4(DAEMON_PATHS.PID_FILE), { recursive: true, mode: 448 });
|
|
8676
|
-
if (
|
|
8677
|
-
const raw =
|
|
8801
|
+
if (existsSync8(DAEMON_PATHS.PID_FILE)) {
|
|
8802
|
+
const raw = readFileSync8(DAEMON_PATHS.PID_FILE, "utf8").trim();
|
|
8678
8803
|
const oldPid = Number.parseInt(raw, 10);
|
|
8679
8804
|
if (Number.isFinite(oldPid) && oldPid > 0 && isProcessAlive(oldPid)) {
|
|
8680
8805
|
return { result: "already-running", pid: oldPid };
|
|
@@ -8682,22 +8807,22 @@ function acquireSingletonLock() {
|
|
|
8682
8807
|
try {
|
|
8683
8808
|
unlinkSync3(DAEMON_PATHS.PID_FILE);
|
|
8684
8809
|
} catch {}
|
|
8685
|
-
|
|
8810
|
+
writeFileSync9(DAEMON_PATHS.PID_FILE, String(process.pid), { mode: 384 });
|
|
8686
8811
|
return { result: "stale", pid: process.pid };
|
|
8687
8812
|
}
|
|
8688
|
-
|
|
8813
|
+
writeFileSync9(DAEMON_PATHS.PID_FILE, String(process.pid), { mode: 384 });
|
|
8689
8814
|
return { result: "acquired", pid: process.pid };
|
|
8690
8815
|
}
|
|
8691
8816
|
function releaseSingletonLock() {
|
|
8692
8817
|
try {
|
|
8693
|
-
const raw =
|
|
8818
|
+
const raw = readFileSync8(DAEMON_PATHS.PID_FILE, "utf8").trim();
|
|
8694
8819
|
if (Number.parseInt(raw, 10) === process.pid)
|
|
8695
8820
|
unlinkSync3(DAEMON_PATHS.PID_FILE);
|
|
8696
8821
|
} catch {}
|
|
8697
8822
|
}
|
|
8698
8823
|
function readRunningPid() {
|
|
8699
8824
|
try {
|
|
8700
|
-
const raw =
|
|
8825
|
+
const raw = readFileSync8(DAEMON_PATHS.PID_FILE, "utf8").trim();
|
|
8701
8826
|
const pid = Number.parseInt(raw, 10);
|
|
8702
8827
|
if (Number.isFinite(pid) && pid > 0 && isProcessAlive(pid))
|
|
8703
8828
|
return pid;
|
|
@@ -8843,17 +8968,17 @@ function requeueDeadOrPending(db, args) {
|
|
|
8843
8968
|
|
|
8844
8969
|
// src/daemon/db/sqlite.ts
|
|
8845
8970
|
async function loadSqlite() {
|
|
8846
|
-
if (
|
|
8847
|
-
return
|
|
8971
|
+
if (cached2)
|
|
8972
|
+
return cached2;
|
|
8848
8973
|
try {
|
|
8849
8974
|
const mod = await import("node:sqlite");
|
|
8850
|
-
|
|
8851
|
-
return
|
|
8975
|
+
cached2 = mod.DatabaseSync;
|
|
8976
|
+
return cached2;
|
|
8852
8977
|
} catch (nodeErr) {
|
|
8853
8978
|
try {
|
|
8854
8979
|
const bunMod = await import("bun:sqlite");
|
|
8855
|
-
|
|
8856
|
-
return
|
|
8980
|
+
cached2 = bunMod.Database;
|
|
8981
|
+
return cached2;
|
|
8857
8982
|
} catch {
|
|
8858
8983
|
const msg = `claudemesh daemon requires Node.js 22.5+ for the embedded SQLite store (node:sqlite), or Bun (bun:sqlite) for dev. Current: ${process.version}. Original error: ${String(nodeErr)}`;
|
|
8859
8984
|
throw new Error(msg);
|
|
@@ -8884,7 +9009,7 @@ function inImmediateTx(db, fn) {
|
|
|
8884
9009
|
throw err;
|
|
8885
9010
|
}
|
|
8886
9011
|
}
|
|
8887
|
-
var
|
|
9012
|
+
var cached2 = null;
|
|
8888
9013
|
|
|
8889
9014
|
// src/daemon/fingerprint.ts
|
|
8890
9015
|
import { createHash } from "node:crypto";
|
|
@@ -9127,9 +9252,70 @@ function bindSseStream(res, bus) {
|
|
|
9127
9252
|
return cleanup;
|
|
9128
9253
|
}
|
|
9129
9254
|
|
|
9255
|
+
// src/daemon/session-registry.ts
|
|
9256
|
+
function startReaper() {
|
|
9257
|
+
if (reaperHandle)
|
|
9258
|
+
return;
|
|
9259
|
+
reaperHandle = setInterval(reapDead, REAPER_INTERVAL_MS).unref?.() ?? reaperHandle;
|
|
9260
|
+
}
|
|
9261
|
+
function registerSession(info) {
|
|
9262
|
+
const priorToken = bySessionId.get(info.sessionId);
|
|
9263
|
+
if (priorToken && priorToken !== info.token)
|
|
9264
|
+
byToken.delete(priorToken);
|
|
9265
|
+
const stored = { ...info, registeredAt: Date.now() };
|
|
9266
|
+
byToken.set(info.token, stored);
|
|
9267
|
+
bySessionId.set(info.sessionId, info.token);
|
|
9268
|
+
return stored;
|
|
9269
|
+
}
|
|
9270
|
+
function deregisterByToken(token) {
|
|
9271
|
+
const entry = byToken.get(token);
|
|
9272
|
+
if (!entry)
|
|
9273
|
+
return false;
|
|
9274
|
+
byToken.delete(token);
|
|
9275
|
+
if (bySessionId.get(entry.sessionId) === token)
|
|
9276
|
+
bySessionId.delete(entry.sessionId);
|
|
9277
|
+
return true;
|
|
9278
|
+
}
|
|
9279
|
+
function resolveToken(token) {
|
|
9280
|
+
const entry = byToken.get(token);
|
|
9281
|
+
if (!entry)
|
|
9282
|
+
return null;
|
|
9283
|
+
if (Date.now() - entry.registeredAt > TTL_MS) {
|
|
9284
|
+
deregisterByToken(token);
|
|
9285
|
+
return null;
|
|
9286
|
+
}
|
|
9287
|
+
return entry;
|
|
9288
|
+
}
|
|
9289
|
+
function listSessions() {
|
|
9290
|
+
return [...byToken.values()];
|
|
9291
|
+
}
|
|
9292
|
+
function reapDead() {
|
|
9293
|
+
const dead = [];
|
|
9294
|
+
for (const [token, info] of byToken.entries()) {
|
|
9295
|
+
if (Date.now() - info.registeredAt > TTL_MS) {
|
|
9296
|
+
dead.push(token);
|
|
9297
|
+
continue;
|
|
9298
|
+
}
|
|
9299
|
+
try {
|
|
9300
|
+
process.kill(info.pid, 0);
|
|
9301
|
+
} catch {
|
|
9302
|
+
dead.push(token);
|
|
9303
|
+
}
|
|
9304
|
+
}
|
|
9305
|
+
for (const t of dead)
|
|
9306
|
+
deregisterByToken(t);
|
|
9307
|
+
}
|
|
9308
|
+
var TTL_MS, REAPER_INTERVAL_MS, byToken, bySessionId, reaperHandle = null;
|
|
9309
|
+
var init_session_registry = __esm(() => {
|
|
9310
|
+
TTL_MS = 24 * 60 * 60 * 1000;
|
|
9311
|
+
REAPER_INTERVAL_MS = 30 * 1000;
|
|
9312
|
+
byToken = new Map;
|
|
9313
|
+
bySessionId = new Map;
|
|
9314
|
+
});
|
|
9315
|
+
|
|
9130
9316
|
// src/daemon/ipc/server.ts
|
|
9131
9317
|
import { createServer as createServer2 } from "node:http";
|
|
9132
|
-
import { chmodSync as chmodSync3, existsSync as
|
|
9318
|
+
import { chmodSync as chmodSync3, existsSync as existsSync9, unlinkSync as unlinkSync4 } from "node:fs";
|
|
9133
9319
|
import { timingSafeEqual } from "node:crypto";
|
|
9134
9320
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
9135
9321
|
function startIpcServer(opts) {
|
|
@@ -9145,7 +9331,7 @@ function startIpcServer(opts) {
|
|
|
9145
9331
|
meshConfigs: opts.meshConfigs,
|
|
9146
9332
|
onPendingInserted: opts.onPendingInserted
|
|
9147
9333
|
});
|
|
9148
|
-
if (
|
|
9334
|
+
if (existsSync9(DAEMON_PATHS.SOCK_FILE)) {
|
|
9149
9335
|
try {
|
|
9150
9336
|
unlinkSync4(DAEMON_PATHS.SOCK_FILE);
|
|
9151
9337
|
} catch {}
|
|
@@ -9231,11 +9417,19 @@ function makeHandler(opts) {
|
|
|
9231
9417
|
return;
|
|
9232
9418
|
}
|
|
9233
9419
|
}
|
|
9420
|
+
let session = null;
|
|
9421
|
+
{
|
|
9422
|
+
const authz = req.headers.authorization ?? "";
|
|
9423
|
+
const sm = /^ClaudeMesh-Session\s+([0-9a-f]{64})$/i.exec(authz.trim());
|
|
9424
|
+
if (sm && sm[1])
|
|
9425
|
+
session = resolveToken(sm[1].toLowerCase());
|
|
9426
|
+
}
|
|
9427
|
+
const meshFromCtx = (explicit) => explicit && explicit.trim() ? explicit : session?.mesh ?? null;
|
|
9234
9428
|
if (req.method === "GET" && url.pathname === "/v1/version") {
|
|
9235
9429
|
respond(res, 200, {
|
|
9236
9430
|
daemon_version: VERSION,
|
|
9237
9431
|
ipc_api: "v1",
|
|
9238
|
-
ipc_features: ["version", "health", "send", "inbox", "events", "peers", "profile", "skills", "state", "memory"],
|
|
9432
|
+
ipc_features: ["version", "health", "send", "inbox", "events", "peers", "profile", "skills", "state", "memory", "sessions"],
|
|
9239
9433
|
schema_version: 1
|
|
9240
9434
|
});
|
|
9241
9435
|
return;
|
|
@@ -9244,6 +9438,70 @@ function makeHandler(opts) {
|
|
|
9244
9438
|
respond(res, 200, { ok: true, pid: process.pid });
|
|
9245
9439
|
return;
|
|
9246
9440
|
}
|
|
9441
|
+
if (req.method === "POST" && url.pathname === "/v1/sessions/register") {
|
|
9442
|
+
try {
|
|
9443
|
+
const body = await readJsonBody(req, 64 * 1024);
|
|
9444
|
+
if (!body) {
|
|
9445
|
+
respond(res, 400, { error: "missing body" });
|
|
9446
|
+
return;
|
|
9447
|
+
}
|
|
9448
|
+
const token = typeof body.token === "string" ? body.token : "";
|
|
9449
|
+
if (!/^[0-9a-f]{64}$/i.test(token)) {
|
|
9450
|
+
respond(res, 400, { error: "token must be 64 hex chars" });
|
|
9451
|
+
return;
|
|
9452
|
+
}
|
|
9453
|
+
const sessionId = typeof body.session_id === "string" ? body.session_id : "";
|
|
9454
|
+
const mesh = typeof body.mesh === "string" ? body.mesh : "";
|
|
9455
|
+
const displayName = typeof body.display_name === "string" ? body.display_name : "";
|
|
9456
|
+
const pid = typeof body.pid === "number" ? body.pid : 0;
|
|
9457
|
+
if (!sessionId || !mesh || !displayName || !pid) {
|
|
9458
|
+
respond(res, 400, { error: "session_id, mesh, display_name, pid all required" });
|
|
9459
|
+
return;
|
|
9460
|
+
}
|
|
9461
|
+
const cwd = typeof body.cwd === "string" ? body.cwd : undefined;
|
|
9462
|
+
const role = typeof body.role === "string" ? body.role : undefined;
|
|
9463
|
+
const groups = Array.isArray(body.groups) ? body.groups.filter((g) => typeof g === "string") : undefined;
|
|
9464
|
+
const stored = registerSession({
|
|
9465
|
+
token: token.toLowerCase(),
|
|
9466
|
+
sessionId,
|
|
9467
|
+
mesh,
|
|
9468
|
+
displayName,
|
|
9469
|
+
pid,
|
|
9470
|
+
cwd,
|
|
9471
|
+
role,
|
|
9472
|
+
groups
|
|
9473
|
+
});
|
|
9474
|
+
opts.log("info", "session_registered", { sessionId, mesh, pid });
|
|
9475
|
+
respond(res, 200, { ok: true, registered_at: stored.registeredAt });
|
|
9476
|
+
} catch (e) {
|
|
9477
|
+
respond(res, 400, { error: String(e) });
|
|
9478
|
+
}
|
|
9479
|
+
return;
|
|
9480
|
+
}
|
|
9481
|
+
if (req.method === "DELETE" && url.pathname.startsWith("/v1/sessions/")) {
|
|
9482
|
+
const tail = url.pathname.slice("/v1/sessions/".length);
|
|
9483
|
+
if (!/^[0-9a-f]{64}$/i.test(tail)) {
|
|
9484
|
+
respond(res, 400, { error: "invalid token" });
|
|
9485
|
+
return;
|
|
9486
|
+
}
|
|
9487
|
+
const ok = deregisterByToken(tail.toLowerCase());
|
|
9488
|
+
respond(res, ok ? 200 : 404, { ok, token_prefix: tail.slice(0, 8) });
|
|
9489
|
+
return;
|
|
9490
|
+
}
|
|
9491
|
+
if (req.method === "GET" && url.pathname === "/v1/sessions/me") {
|
|
9492
|
+
if (!session) {
|
|
9493
|
+
respond(res, 401, { error: "no session token" });
|
|
9494
|
+
return;
|
|
9495
|
+
}
|
|
9496
|
+
const { token, ...redacted } = session;
|
|
9497
|
+
respond(res, 200, { session: { ...redacted, token_prefix: token.slice(0, 8) } });
|
|
9498
|
+
return;
|
|
9499
|
+
}
|
|
9500
|
+
if (req.method === "GET" && url.pathname === "/v1/sessions") {
|
|
9501
|
+
const all = listSessions().map(({ token, ...rest }) => ({ ...rest, token_prefix: token.slice(0, 8) }));
|
|
9502
|
+
respond(res, 200, { sessions: all });
|
|
9503
|
+
return;
|
|
9504
|
+
}
|
|
9247
9505
|
if (req.method === "GET" && url.pathname === "/v1/events") {
|
|
9248
9506
|
if (!opts.bus) {
|
|
9249
9507
|
respond(res, 503, { error: "event bus not initialised" });
|
|
@@ -9257,7 +9515,7 @@ function makeHandler(opts) {
|
|
|
9257
9515
|
respond(res, 503, { error: "broker not initialised" });
|
|
9258
9516
|
return;
|
|
9259
9517
|
}
|
|
9260
|
-
const filterMesh = url.searchParams.get("mesh") ?? undefined;
|
|
9518
|
+
const filterMesh = meshFromCtx(url.searchParams.get("mesh")) ?? undefined;
|
|
9261
9519
|
try {
|
|
9262
9520
|
const all = [];
|
|
9263
9521
|
for (const [slug, b] of opts.brokers.entries()) {
|
|
@@ -9282,7 +9540,7 @@ function makeHandler(opts) {
|
|
|
9282
9540
|
respond(res, 503, { error: "broker not initialised" });
|
|
9283
9541
|
return;
|
|
9284
9542
|
}
|
|
9285
|
-
const filterMesh = url.searchParams.get("mesh") ?? undefined;
|
|
9543
|
+
const filterMesh = meshFromCtx(url.searchParams.get("mesh")) ?? undefined;
|
|
9286
9544
|
const key = url.searchParams.get("key");
|
|
9287
9545
|
try {
|
|
9288
9546
|
if (key) {
|
|
@@ -9323,7 +9581,7 @@ function makeHandler(opts) {
|
|
|
9323
9581
|
respond(res, 400, { error: "missing 'key' (string)" });
|
|
9324
9582
|
return;
|
|
9325
9583
|
}
|
|
9326
|
-
const requested = (typeof body.mesh === "string" ? body.mesh : null)
|
|
9584
|
+
const requested = meshFromCtx(typeof body.mesh === "string" ? body.mesh : null);
|
|
9327
9585
|
let chosen = requested;
|
|
9328
9586
|
if (!chosen && opts.brokers.size === 1)
|
|
9329
9587
|
chosen = opts.brokers.keys().next().value;
|
|
@@ -9349,7 +9607,7 @@ function makeHandler(opts) {
|
|
|
9349
9607
|
return;
|
|
9350
9608
|
}
|
|
9351
9609
|
const query = url.searchParams.get("q") ?? "";
|
|
9352
|
-
const filterMesh = url.searchParams.get("mesh") ?? undefined;
|
|
9610
|
+
const filterMesh = meshFromCtx(url.searchParams.get("mesh")) ?? undefined;
|
|
9353
9611
|
try {
|
|
9354
9612
|
const all = [];
|
|
9355
9613
|
for (const [slug, b] of opts.brokers.entries()) {
|
|
@@ -9376,7 +9634,7 @@ function makeHandler(opts) {
|
|
|
9376
9634
|
respond(res, 400, { error: "missing 'content' (string)" });
|
|
9377
9635
|
return;
|
|
9378
9636
|
}
|
|
9379
|
-
const requested = (typeof body.mesh === "string" ? body.mesh : null)
|
|
9637
|
+
const requested = meshFromCtx(typeof body.mesh === "string" ? body.mesh : null);
|
|
9380
9638
|
let chosen = requested;
|
|
9381
9639
|
if (!chosen && opts.brokers.size === 1)
|
|
9382
9640
|
chosen = opts.brokers.keys().next().value;
|
|
@@ -9434,7 +9692,7 @@ function makeHandler(opts) {
|
|
|
9434
9692
|
return;
|
|
9435
9693
|
}
|
|
9436
9694
|
const query = url.searchParams.get("query") ?? undefined;
|
|
9437
|
-
const filterMesh = url.searchParams.get("mesh") ?? undefined;
|
|
9695
|
+
const filterMesh = meshFromCtx(url.searchParams.get("mesh")) ?? undefined;
|
|
9438
9696
|
try {
|
|
9439
9697
|
const all = [];
|
|
9440
9698
|
for (const [slug, b] of opts.brokers.entries()) {
|
|
@@ -9464,7 +9722,7 @@ function makeHandler(opts) {
|
|
|
9464
9722
|
respond(res, 400, { error: "missing skill name" });
|
|
9465
9723
|
return;
|
|
9466
9724
|
}
|
|
9467
|
-
const filterMesh = url.searchParams.get("mesh") ?? undefined;
|
|
9725
|
+
const filterMesh = meshFromCtx(url.searchParams.get("mesh")) ?? undefined;
|
|
9468
9726
|
try {
|
|
9469
9727
|
for (const [slug, b] of opts.brokers.entries()) {
|
|
9470
9728
|
if (filterMesh && filterMesh !== slug)
|
|
@@ -9492,7 +9750,7 @@ function makeHandler(opts) {
|
|
|
9492
9750
|
respond(res, 400, { error: "expected JSON object" });
|
|
9493
9751
|
return;
|
|
9494
9752
|
}
|
|
9495
|
-
const requested = (typeof body.mesh === "string" ? body.mesh : url.searchParams.get("mesh"))
|
|
9753
|
+
const requested = meshFromCtx(typeof body.mesh === "string" ? body.mesh : url.searchParams.get("mesh"));
|
|
9496
9754
|
const targets = requested ? [opts.brokers.get(requested)].filter(Boolean) : [...opts.brokers.values()];
|
|
9497
9755
|
if (targets.length === 0) {
|
|
9498
9756
|
respond(res, 404, { error: "mesh_not_attached", mesh: requested });
|
|
@@ -9776,16 +10034,16 @@ function parseSendRequest(body, idempotencyHeader) {
|
|
|
9776
10034
|
}
|
|
9777
10035
|
async function resolveAndEncrypt(req, broker, meshSecretKey, meshSlug) {
|
|
9778
10036
|
const { encryptDirect: encryptDirect2 } = await Promise.resolve().then(() => (init_box(), exports_box));
|
|
9779
|
-
const { randomBytes:
|
|
10037
|
+
const { randomBytes: randomBytes6 } = await import("node:crypto");
|
|
9780
10038
|
const to = req.to.trim();
|
|
9781
10039
|
if (to.startsWith("#") && /^#[0-9a-z_-]{20,}$/i.test(to)) {
|
|
9782
10040
|
const ciphertext = Buffer.from(req.message, "utf8").toString("base64");
|
|
9783
|
-
const nonce =
|
|
10041
|
+
const nonce = randomBytes6(24).toString("base64");
|
|
9784
10042
|
return { target_spec: to, ciphertext, nonce, mesh: meshSlug ?? "" };
|
|
9785
10043
|
}
|
|
9786
10044
|
if (to.startsWith("@") || to === "*") {
|
|
9787
10045
|
const ciphertext = Buffer.from(req.message, "utf8").toString("base64");
|
|
9788
|
-
const nonce =
|
|
10046
|
+
const nonce = randomBytes6(24).toString("base64");
|
|
9789
10047
|
return { target_spec: to, ciphertext, nonce, mesh: meshSlug ?? "" };
|
|
9790
10048
|
}
|
|
9791
10049
|
if (/^[0-9a-f]{64}$/i.test(to)) {
|
|
@@ -9826,6 +10084,7 @@ function respond(res, status, body) {
|
|
|
9826
10084
|
var init_server = __esm(() => {
|
|
9827
10085
|
init_paths2();
|
|
9828
10086
|
init_send2();
|
|
10087
|
+
init_session_registry();
|
|
9829
10088
|
init_urls();
|
|
9830
10089
|
});
|
|
9831
10090
|
|
|
@@ -10457,8 +10716,8 @@ function bufferToHex(b) {
|
|
|
10457
10716
|
return s;
|
|
10458
10717
|
}
|
|
10459
10718
|
async function randomNonce2() {
|
|
10460
|
-
const { randomBytes:
|
|
10461
|
-
return
|
|
10719
|
+
const { randomBytes: randomBytes6 } = await import("node:crypto");
|
|
10720
|
+
return randomBytes6(24).toString("base64");
|
|
10462
10721
|
}
|
|
10463
10722
|
function defaultLog2(level, msg, meta) {
|
|
10464
10723
|
const line = JSON.stringify({ level, msg, ...meta, ts: new Date().toISOString() });
|
|
@@ -10580,7 +10839,7 @@ __export(exports_identity, {
|
|
|
10580
10839
|
checkFingerprint: () => checkFingerprint,
|
|
10581
10840
|
acceptCurrentHost: () => acceptCurrentHost
|
|
10582
10841
|
});
|
|
10583
|
-
import { existsSync as
|
|
10842
|
+
import { existsSync as existsSync10, readFileSync as readFileSync9, writeFileSync as writeFileSync10 } from "node:fs";
|
|
10584
10843
|
import { join as join7 } from "node:path";
|
|
10585
10844
|
import { createHash as createHash2 } from "node:crypto";
|
|
10586
10845
|
import { networkInterfaces } from "node:os";
|
|
@@ -10601,13 +10860,13 @@ function computeCurrentFingerprint() {
|
|
|
10601
10860
|
}
|
|
10602
10861
|
function checkFingerprint() {
|
|
10603
10862
|
const current = computeCurrentFingerprint();
|
|
10604
|
-
if (!
|
|
10605
|
-
|
|
10863
|
+
if (!existsSync10(path())) {
|
|
10864
|
+
writeFileSync10(path(), JSON.stringify(current, null, 2), { mode: 384 });
|
|
10606
10865
|
return { result: "first_run", current };
|
|
10607
10866
|
}
|
|
10608
10867
|
let stored;
|
|
10609
10868
|
try {
|
|
10610
|
-
stored = JSON.parse(
|
|
10869
|
+
stored = JSON.parse(readFileSync9(path(), "utf8"));
|
|
10611
10870
|
} catch {
|
|
10612
10871
|
return { result: "unavailable", current };
|
|
10613
10872
|
}
|
|
@@ -10617,14 +10876,14 @@ function checkFingerprint() {
|
|
|
10617
10876
|
}
|
|
10618
10877
|
function acceptCurrentHost() {
|
|
10619
10878
|
const current = computeCurrentFingerprint();
|
|
10620
|
-
|
|
10879
|
+
writeFileSync10(path(), JSON.stringify(current, null, 2), { mode: 384 });
|
|
10621
10880
|
return current;
|
|
10622
10881
|
}
|
|
10623
10882
|
function readHostId() {
|
|
10624
10883
|
if (process.platform === "linux") {
|
|
10625
10884
|
for (const p of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
10626
10885
|
try {
|
|
10627
|
-
const raw =
|
|
10886
|
+
const raw = readFileSync9(p, "utf8").trim();
|
|
10628
10887
|
if (raw)
|
|
10629
10888
|
return `linux:${raw}`;
|
|
10630
10889
|
} catch {}
|
|
@@ -10669,16 +10928,16 @@ var init_identity = __esm(() => {
|
|
|
10669
10928
|
});
|
|
10670
10929
|
|
|
10671
10930
|
// src/daemon/run.ts
|
|
10672
|
-
import { existsSync as
|
|
10931
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync10 } from "node:fs";
|
|
10673
10932
|
function detectContainer() {
|
|
10674
10933
|
if (process.env.KUBERNETES_SERVICE_HOST)
|
|
10675
10934
|
return true;
|
|
10676
10935
|
if (process.env.CONTAINER === "1")
|
|
10677
10936
|
return true;
|
|
10678
10937
|
try {
|
|
10679
|
-
if (
|
|
10938
|
+
if (existsSync11("/.dockerenv"))
|
|
10680
10939
|
return true;
|
|
10681
|
-
const cg =
|
|
10940
|
+
const cg = readFileSync10("/proc/1/cgroup", "utf8");
|
|
10682
10941
|
if (/(docker|kubepods|containerd)/.test(cg))
|
|
10683
10942
|
return true;
|
|
10684
10943
|
} catch {}
|
|
@@ -10803,6 +11062,7 @@ async function runDaemon(opts = {}) {
|
|
|
10803
11062
|
}
|
|
10804
11063
|
let drain = null;
|
|
10805
11064
|
drain = startDrainWorker({ db: outboxDb, brokers });
|
|
11065
|
+
startReaper();
|
|
10806
11066
|
const ipc2 = startIpcServer({
|
|
10807
11067
|
localToken,
|
|
10808
11068
|
tcpEnabled,
|
|
@@ -10864,6 +11124,7 @@ var init_run = __esm(() => {
|
|
|
10864
11124
|
init_lock();
|
|
10865
11125
|
init_local_token();
|
|
10866
11126
|
init_server();
|
|
11127
|
+
init_session_registry();
|
|
10867
11128
|
init_broker();
|
|
10868
11129
|
init_drain();
|
|
10869
11130
|
init_inbound();
|
|
@@ -10879,7 +11140,7 @@ __export(exports_service_install, {
|
|
|
10879
11140
|
installService: () => installService,
|
|
10880
11141
|
detectPlatform: () => detectPlatform
|
|
10881
11142
|
});
|
|
10882
|
-
import { existsSync as
|
|
11143
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync7, writeFileSync as writeFileSync11, unlinkSync as unlinkSync5, readFileSync as readFileSync11 } from "node:fs";
|
|
10883
11144
|
import { execSync as execSync2 } from "node:child_process";
|
|
10884
11145
|
import { homedir as homedir5 } from "node:os";
|
|
10885
11146
|
import { join as join8, dirname as dirname5 } from "node:path";
|
|
@@ -10900,7 +11161,7 @@ function installService(args) {
|
|
|
10900
11161
|
if (isCi() && !args.allowCi) {
|
|
10901
11162
|
throw new Error("Refusing to install persistent service in CI; pass --allow-ci-persistent to override.");
|
|
10902
11163
|
}
|
|
10903
|
-
if (!
|
|
11164
|
+
if (!existsSync12(args.binaryPath)) {
|
|
10904
11165
|
throw new Error(`binary not found at ${args.binaryPath}`);
|
|
10905
11166
|
}
|
|
10906
11167
|
mkdirSync7(DAEMON_PATHS.DAEMON_DIR, { recursive: true, mode: 448 });
|
|
@@ -10916,7 +11177,7 @@ function uninstallService() {
|
|
|
10916
11177
|
try {
|
|
10917
11178
|
execSync2(`launchctl bootout gui/$(id -u)/${SERVICE_LABEL}`, { stdio: "ignore" });
|
|
10918
11179
|
} catch {}
|
|
10919
|
-
if (
|
|
11180
|
+
if (existsSync12(p)) {
|
|
10920
11181
|
unlinkSync5(p);
|
|
10921
11182
|
removed.push(p);
|
|
10922
11183
|
}
|
|
@@ -10925,7 +11186,7 @@ function uninstallService() {
|
|
|
10925
11186
|
try {
|
|
10926
11187
|
execSync2(`systemctl --user disable --now ${SYSTEMD_UNIT}`, { stdio: "ignore" });
|
|
10927
11188
|
} catch {}
|
|
10928
|
-
if (
|
|
11189
|
+
if (existsSync12(p)) {
|
|
10929
11190
|
unlinkSync5(p);
|
|
10930
11191
|
removed.push(p);
|
|
10931
11192
|
}
|
|
@@ -10978,7 +11239,7 @@ function installDarwin(args) {
|
|
|
10978
11239
|
</dict>
|
|
10979
11240
|
</plist>
|
|
10980
11241
|
`;
|
|
10981
|
-
|
|
11242
|
+
writeFileSync11(plist, xml, { mode: 420 });
|
|
10982
11243
|
return {
|
|
10983
11244
|
platform: "darwin",
|
|
10984
11245
|
unitPath: plist,
|
|
@@ -11015,7 +11276,7 @@ Environment=PATH=/usr/local/bin:/usr/bin:/bin
|
|
|
11015
11276
|
[Install]
|
|
11016
11277
|
WantedBy=default.target
|
|
11017
11278
|
`;
|
|
11018
|
-
|
|
11279
|
+
writeFileSync11(unit, content, { mode: 420 });
|
|
11019
11280
|
return {
|
|
11020
11281
|
platform: "linux",
|
|
11021
11282
|
unitPath: unit,
|
|
@@ -11035,10 +11296,10 @@ function readInstalledUnit() {
|
|
|
11035
11296
|
if (!platform5)
|
|
11036
11297
|
return { platform: null, path: null, content: null };
|
|
11037
11298
|
const path2 = platform5 === "darwin" ? darwinPlistPath() : linuxUnitPath();
|
|
11038
|
-
if (!
|
|
11299
|
+
if (!existsSync12(path2))
|
|
11039
11300
|
return { platform: platform5, path: null, content: null };
|
|
11040
11301
|
try {
|
|
11041
|
-
return { platform: platform5, path: path2, content:
|
|
11302
|
+
return { platform: platform5, path: path2, content: readFileSync11(path2, "utf8") };
|
|
11042
11303
|
} catch {
|
|
11043
11304
|
return { platform: platform5, path: path2, content: null };
|
|
11044
11305
|
}
|
|
@@ -11380,19 +11641,19 @@ __export(exports_install, {
|
|
|
11380
11641
|
import {
|
|
11381
11642
|
chmodSync as chmodSync4,
|
|
11382
11643
|
copyFileSync,
|
|
11383
|
-
existsSync as
|
|
11644
|
+
existsSync as existsSync13,
|
|
11384
11645
|
mkdirSync as mkdirSync8,
|
|
11385
|
-
readFileSync as
|
|
11386
|
-
writeFileSync as
|
|
11646
|
+
readFileSync as readFileSync12,
|
|
11647
|
+
writeFileSync as writeFileSync12
|
|
11387
11648
|
} from "node:fs";
|
|
11388
11649
|
import { homedir as homedir6, platform as platform5 } from "node:os";
|
|
11389
11650
|
import { dirname as dirname6, join as join9, resolve } from "node:path";
|
|
11390
11651
|
import { fileURLToPath } from "node:url";
|
|
11391
11652
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
11392
11653
|
function readClaudeConfig() {
|
|
11393
|
-
if (!
|
|
11654
|
+
if (!existsSync13(CLAUDE_CONFIG))
|
|
11394
11655
|
return {};
|
|
11395
|
-
const text =
|
|
11656
|
+
const text = readFileSync12(CLAUDE_CONFIG, "utf-8").trim();
|
|
11396
11657
|
if (!text)
|
|
11397
11658
|
return {};
|
|
11398
11659
|
try {
|
|
@@ -11402,7 +11663,7 @@ function readClaudeConfig() {
|
|
|
11402
11663
|
}
|
|
11403
11664
|
}
|
|
11404
11665
|
function backupClaudeConfig() {
|
|
11405
|
-
if (!
|
|
11666
|
+
if (!existsSync13(CLAUDE_CONFIG))
|
|
11406
11667
|
return;
|
|
11407
11668
|
const backupDir = join9(dirname6(CLAUDE_CONFIG), ".claude", "backups");
|
|
11408
11669
|
mkdirSync8(backupDir, { recursive: true });
|
|
@@ -11431,7 +11692,7 @@ function patchMcpServer(entry) {
|
|
|
11431
11692
|
return action;
|
|
11432
11693
|
}
|
|
11433
11694
|
function removeMcpServer() {
|
|
11434
|
-
if (!
|
|
11695
|
+
if (!existsSync13(CLAUDE_CONFIG))
|
|
11435
11696
|
return false;
|
|
11436
11697
|
backupClaudeConfig();
|
|
11437
11698
|
const cfg = readClaudeConfig();
|
|
@@ -11445,7 +11706,7 @@ function removeMcpServer() {
|
|
|
11445
11706
|
}
|
|
11446
11707
|
function flushClaudeConfig(obj) {
|
|
11447
11708
|
mkdirSync8(dirname6(CLAUDE_CONFIG), { recursive: true });
|
|
11448
|
-
|
|
11709
|
+
writeFileSync12(CLAUDE_CONFIG, JSON.stringify(obj, null, 2) + `
|
|
11449
11710
|
`, "utf-8");
|
|
11450
11711
|
try {
|
|
11451
11712
|
chmodSync4(CLAUDE_CONFIG, 384);
|
|
@@ -11468,7 +11729,7 @@ function resolveBundledSkillsDir() {
|
|
|
11468
11729
|
const here = fileURLToPath(import.meta.url);
|
|
11469
11730
|
const pkgRoot = resolve(dirname6(here), "..", "..");
|
|
11470
11731
|
const skillsDir = join9(pkgRoot, "skills");
|
|
11471
|
-
if (
|
|
11732
|
+
if (existsSync13(skillsDir))
|
|
11472
11733
|
return skillsDir;
|
|
11473
11734
|
return null;
|
|
11474
11735
|
}
|
|
@@ -11503,7 +11764,7 @@ function uninstallSkills() {
|
|
|
11503
11764
|
if (!entry.isDirectory())
|
|
11504
11765
|
continue;
|
|
11505
11766
|
const dstDir = join9(CLAUDE_SKILLS_ROOT, entry.name);
|
|
11506
|
-
if (
|
|
11767
|
+
if (existsSync13(dstDir)) {
|
|
11507
11768
|
try {
|
|
11508
11769
|
fs.rmSync(dstDir, { recursive: true, force: true });
|
|
11509
11770
|
removed.push(entry.name);
|
|
@@ -11528,9 +11789,9 @@ function entriesEqual(a, b) {
|
|
|
11528
11789
|
return a.command === b.command && JSON.stringify(a.args ?? []) === JSON.stringify(b.args ?? []);
|
|
11529
11790
|
}
|
|
11530
11791
|
function readClaudeSettings() {
|
|
11531
|
-
if (!
|
|
11792
|
+
if (!existsSync13(CLAUDE_SETTINGS))
|
|
11532
11793
|
return {};
|
|
11533
|
-
const text =
|
|
11794
|
+
const text = readFileSync12(CLAUDE_SETTINGS, "utf-8").trim();
|
|
11534
11795
|
if (!text)
|
|
11535
11796
|
return {};
|
|
11536
11797
|
try {
|
|
@@ -11541,7 +11802,7 @@ function readClaudeSettings() {
|
|
|
11541
11802
|
}
|
|
11542
11803
|
function writeClaudeSettings(obj) {
|
|
11543
11804
|
mkdirSync8(dirname6(CLAUDE_SETTINGS), { recursive: true });
|
|
11544
|
-
|
|
11805
|
+
writeFileSync12(CLAUDE_SETTINGS, JSON.stringify(obj, null, 2) + `
|
|
11545
11806
|
`, "utf-8");
|
|
11546
11807
|
}
|
|
11547
11808
|
function installAllowedTools() {
|
|
@@ -11555,7 +11816,7 @@ function installAllowedTools() {
|
|
|
11555
11816
|
return { added: toAdd, unchanged: CLAUDEMESH_TOOLS.length - toAdd.length };
|
|
11556
11817
|
}
|
|
11557
11818
|
function uninstallAllowedTools() {
|
|
11558
|
-
if (!
|
|
11819
|
+
if (!existsSync13(CLAUDE_SETTINGS))
|
|
11559
11820
|
return 0;
|
|
11560
11821
|
const settings = readClaudeSettings();
|
|
11561
11822
|
const existing = settings.allowedTools ?? [];
|
|
@@ -11590,7 +11851,7 @@ function installHooks() {
|
|
|
11590
11851
|
return { added, unchanged };
|
|
11591
11852
|
}
|
|
11592
11853
|
function uninstallHooks() {
|
|
11593
|
-
if (!
|
|
11854
|
+
if (!existsSync13(CLAUDE_SETTINGS))
|
|
11594
11855
|
return 0;
|
|
11595
11856
|
const settings = readClaudeSettings();
|
|
11596
11857
|
const hooks = settings.hooks;
|
|
@@ -11640,7 +11901,7 @@ function runInstall(args = []) {
|
|
|
11640
11901
|
render.err("`bun` is not on PATH.", "Install Bun first: https://bun.com");
|
|
11641
11902
|
process.exit(1);
|
|
11642
11903
|
}
|
|
11643
|
-
if (!
|
|
11904
|
+
if (!existsSync13(entry)) {
|
|
11644
11905
|
render.err(`MCP entry not found at ${entry}`);
|
|
11645
11906
|
process.exit(1);
|
|
11646
11907
|
}
|
|
@@ -11885,7 +12146,7 @@ var exports_uninstall = {};
|
|
|
11885
12146
|
__export(exports_uninstall, {
|
|
11886
12147
|
uninstall: () => uninstall
|
|
11887
12148
|
});
|
|
11888
|
-
import { readFileSync as
|
|
12149
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync13, existsSync as existsSync14, rmSync as rmSync2, readdirSync as readdirSync2 } from "node:fs";
|
|
11889
12150
|
import { join as join10, dirname as dirname7 } from "node:path";
|
|
11890
12151
|
import { homedir as homedir7 } from "node:os";
|
|
11891
12152
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
@@ -11893,27 +12154,27 @@ function bundledSkillsDir() {
|
|
|
11893
12154
|
const here = fileURLToPath2(import.meta.url);
|
|
11894
12155
|
const pkgRoot = join10(dirname7(here), "..", "..");
|
|
11895
12156
|
const skillsDir = join10(pkgRoot, "skills");
|
|
11896
|
-
return
|
|
12157
|
+
return existsSync14(skillsDir) ? skillsDir : null;
|
|
11897
12158
|
}
|
|
11898
12159
|
async function uninstall() {
|
|
11899
12160
|
let removed = 0;
|
|
11900
|
-
if (
|
|
12161
|
+
if (existsSync14(PATHS.CLAUDE_JSON)) {
|
|
11901
12162
|
try {
|
|
11902
|
-
const raw =
|
|
12163
|
+
const raw = readFileSync13(PATHS.CLAUDE_JSON, "utf-8");
|
|
11903
12164
|
const config = JSON.parse(raw);
|
|
11904
12165
|
const servers = config.mcpServers;
|
|
11905
12166
|
if (servers && "claudemesh" in servers) {
|
|
11906
12167
|
delete servers.claudemesh;
|
|
11907
|
-
|
|
12168
|
+
writeFileSync13(PATHS.CLAUDE_JSON, JSON.stringify(config, null, 2) + `
|
|
11908
12169
|
`, "utf-8");
|
|
11909
12170
|
render.ok("removed MCP server", dim("~/.claude.json"));
|
|
11910
12171
|
removed++;
|
|
11911
12172
|
}
|
|
11912
12173
|
} catch {}
|
|
11913
12174
|
}
|
|
11914
|
-
if (
|
|
12175
|
+
if (existsSync14(PATHS.CLAUDE_SETTINGS)) {
|
|
11915
12176
|
try {
|
|
11916
|
-
const raw =
|
|
12177
|
+
const raw = readFileSync13(PATHS.CLAUDE_SETTINGS, "utf-8");
|
|
11917
12178
|
const config = JSON.parse(raw);
|
|
11918
12179
|
const hooks = config.hooks;
|
|
11919
12180
|
if (hooks) {
|
|
@@ -11934,7 +12195,7 @@ async function uninstall() {
|
|
|
11934
12195
|
}
|
|
11935
12196
|
}
|
|
11936
12197
|
if (removedHooks > 0) {
|
|
11937
|
-
|
|
12198
|
+
writeFileSync13(PATHS.CLAUDE_SETTINGS, JSON.stringify(config, null, 2) + `
|
|
11938
12199
|
`, "utf-8");
|
|
11939
12200
|
render.ok(`removed ${removedHooks} claudemesh hook${removedHooks === 1 ? "" : "s"}`, dim("settings.json"));
|
|
11940
12201
|
removed++;
|
|
@@ -11950,7 +12211,7 @@ async function uninstall() {
|
|
|
11950
12211
|
if (!entry.isDirectory())
|
|
11951
12212
|
continue;
|
|
11952
12213
|
const dst = join10(CLAUDE_SKILLS_ROOT2, entry.name);
|
|
11953
|
-
if (
|
|
12214
|
+
if (existsSync14(dst)) {
|
|
11954
12215
|
try {
|
|
11955
12216
|
rmSync2(dst, { recursive: true, force: true });
|
|
11956
12217
|
removedSkills.push(entry.name);
|
|
@@ -11982,7 +12243,7 @@ var exports_doctor = {};
|
|
|
11982
12243
|
__export(exports_doctor, {
|
|
11983
12244
|
runDoctor: () => runDoctor
|
|
11984
12245
|
});
|
|
11985
|
-
import { existsSync as
|
|
12246
|
+
import { existsSync as existsSync15, readFileSync as readFileSync14, statSync as statSync3 } from "node:fs";
|
|
11986
12247
|
import { homedir as homedir8, platform as platform6 } from "node:os";
|
|
11987
12248
|
import { join as join11 } from "node:path";
|
|
11988
12249
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
@@ -12009,7 +12270,7 @@ function checkClaudeOnPath() {
|
|
|
12009
12270
|
}
|
|
12010
12271
|
function checkMcpRegistered() {
|
|
12011
12272
|
const claudeConfig = join11(homedir8(), ".claude.json");
|
|
12012
|
-
if (!
|
|
12273
|
+
if (!existsSync15(claudeConfig)) {
|
|
12013
12274
|
return {
|
|
12014
12275
|
name: "claudemesh MCP registered in ~/.claude.json",
|
|
12015
12276
|
pass: false,
|
|
@@ -12017,7 +12278,7 @@ function checkMcpRegistered() {
|
|
|
12017
12278
|
};
|
|
12018
12279
|
}
|
|
12019
12280
|
try {
|
|
12020
|
-
const cfg = JSON.parse(
|
|
12281
|
+
const cfg = JSON.parse(readFileSync14(claudeConfig, "utf-8"));
|
|
12021
12282
|
const registered = Boolean(cfg.mcpServers?.["claudemesh"]);
|
|
12022
12283
|
return {
|
|
12023
12284
|
name: "claudemesh MCP registered in ~/.claude.json",
|
|
@@ -12035,7 +12296,7 @@ function checkMcpRegistered() {
|
|
|
12035
12296
|
}
|
|
12036
12297
|
function checkHooksRegistered() {
|
|
12037
12298
|
const settings = join11(homedir8(), ".claude", "settings.json");
|
|
12038
|
-
if (!
|
|
12299
|
+
if (!existsSync15(settings)) {
|
|
12039
12300
|
return {
|
|
12040
12301
|
name: "Status hooks registered in ~/.claude/settings.json",
|
|
12041
12302
|
pass: false,
|
|
@@ -12043,7 +12304,7 @@ function checkHooksRegistered() {
|
|
|
12043
12304
|
};
|
|
12044
12305
|
}
|
|
12045
12306
|
try {
|
|
12046
|
-
const raw =
|
|
12307
|
+
const raw = readFileSync14(settings, "utf-8");
|
|
12047
12308
|
const has = raw.includes("claudemesh hook ");
|
|
12048
12309
|
return {
|
|
12049
12310
|
name: "Status hooks registered in ~/.claude/settings.json",
|
|
@@ -12060,7 +12321,7 @@ function checkHooksRegistered() {
|
|
|
12060
12321
|
}
|
|
12061
12322
|
function checkConfigFile() {
|
|
12062
12323
|
const path2 = getConfigPath();
|
|
12063
|
-
if (!
|
|
12324
|
+
if (!existsSync15(path2)) {
|
|
12064
12325
|
return {
|
|
12065
12326
|
name: "~/.claudemesh/config.json exists and parses",
|
|
12066
12327
|
pass: true,
|
|
@@ -12243,7 +12504,7 @@ var exports_status = {};
|
|
|
12243
12504
|
__export(exports_status, {
|
|
12244
12505
|
runStatus: () => runStatus2
|
|
12245
12506
|
});
|
|
12246
|
-
import { statSync as statSync4, existsSync as
|
|
12507
|
+
import { statSync as statSync4, existsSync as existsSync16 } from "node:fs";
|
|
12247
12508
|
import WebSocket3 from "ws";
|
|
12248
12509
|
async function probeBroker(url, timeoutMs = 4000) {
|
|
12249
12510
|
return new Promise((resolve2) => {
|
|
@@ -12273,7 +12534,7 @@ async function runStatus2() {
|
|
|
12273
12534
|
render.section(`status (v${VERSION})`);
|
|
12274
12535
|
const configPath = getConfigPath();
|
|
12275
12536
|
let configPermsNote = "missing";
|
|
12276
|
-
if (
|
|
12537
|
+
if (existsSync16(configPath)) {
|
|
12277
12538
|
const mode = (statSync4(configPath).mode & 511).toString(8).padStart(4, "0");
|
|
12278
12539
|
configPermsNote = mode === "0600" ? `${mode}` : `${mode} — expected 0600`;
|
|
12279
12540
|
}
|
|
@@ -12419,13 +12680,13 @@ var init_check_claude_binary = __esm(() => {
|
|
|
12419
12680
|
});
|
|
12420
12681
|
|
|
12421
12682
|
// src/services/health/check-mcp-registered.ts
|
|
12422
|
-
import { existsSync as
|
|
12683
|
+
import { existsSync as existsSync17, readFileSync as readFileSync15 } from "node:fs";
|
|
12423
12684
|
function checkMcpRegistered2() {
|
|
12424
12685
|
try {
|
|
12425
|
-
if (!
|
|
12686
|
+
if (!existsSync17(PATHS.CLAUDE_JSON)) {
|
|
12426
12687
|
return { name: "mcp-registered", ok: false, message: "~/.claude.json not found" };
|
|
12427
12688
|
}
|
|
12428
|
-
const raw =
|
|
12689
|
+
const raw = readFileSync15(PATHS.CLAUDE_JSON, "utf-8");
|
|
12429
12690
|
const config = JSON.parse(raw);
|
|
12430
12691
|
if (config.mcpServers && "claudemesh" in config.mcpServers) {
|
|
12431
12692
|
return { name: "mcp-registered", ok: true, message: "MCP server registered" };
|
|
@@ -12440,13 +12701,13 @@ var init_check_mcp_registered = __esm(() => {
|
|
|
12440
12701
|
});
|
|
12441
12702
|
|
|
12442
12703
|
// src/services/health/check-hooks-registered.ts
|
|
12443
|
-
import { existsSync as
|
|
12704
|
+
import { existsSync as existsSync18, readFileSync as readFileSync16 } from "node:fs";
|
|
12444
12705
|
function checkHooksRegistered2() {
|
|
12445
12706
|
try {
|
|
12446
|
-
if (!
|
|
12707
|
+
if (!existsSync18(PATHS.CLAUDE_SETTINGS)) {
|
|
12447
12708
|
return { name: "hooks-registered", ok: false, message: "~/.claude/settings.json not found" };
|
|
12448
12709
|
}
|
|
12449
|
-
const raw =
|
|
12710
|
+
const raw = readFileSync16(PATHS.CLAUDE_SETTINGS, "utf-8");
|
|
12450
12711
|
const config = JSON.parse(raw);
|
|
12451
12712
|
if (config.hooks) {
|
|
12452
12713
|
return { name: "hooks-registered", ok: true, message: "Hooks configured" };
|
|
@@ -12461,10 +12722,10 @@ var init_check_hooks_registered = __esm(() => {
|
|
|
12461
12722
|
});
|
|
12462
12723
|
|
|
12463
12724
|
// src/services/health/check-config-perms.ts
|
|
12464
|
-
import { existsSync as
|
|
12725
|
+
import { existsSync as existsSync19, statSync as statSync5 } from "node:fs";
|
|
12465
12726
|
function checkConfigPerms() {
|
|
12466
12727
|
const configFile = PATHS.CONFIG_FILE;
|
|
12467
|
-
if (!
|
|
12728
|
+
if (!existsSync19(configFile)) {
|
|
12468
12729
|
return { name: "config-perms", ok: true, message: "No config file yet (first run)" };
|
|
12469
12730
|
}
|
|
12470
12731
|
try {
|
|
@@ -12482,13 +12743,13 @@ var init_check_config_perms = __esm(() => {
|
|
|
12482
12743
|
});
|
|
12483
12744
|
|
|
12484
12745
|
// src/services/health/check-keypairs-valid.ts
|
|
12485
|
-
import { existsSync as
|
|
12746
|
+
import { existsSync as existsSync20, readFileSync as readFileSync17 } from "node:fs";
|
|
12486
12747
|
function checkKeypairsValid() {
|
|
12487
|
-
if (!
|
|
12748
|
+
if (!existsSync20(PATHS.CONFIG_FILE)) {
|
|
12488
12749
|
return { name: "keypairs-valid", ok: true, message: "No config (first run)" };
|
|
12489
12750
|
}
|
|
12490
12751
|
try {
|
|
12491
|
-
const raw =
|
|
12752
|
+
const raw = readFileSync17(PATHS.CONFIG_FILE, "utf-8");
|
|
12492
12753
|
const config = JSON.parse(raw);
|
|
12493
12754
|
const meshes = config.meshes ?? [];
|
|
12494
12755
|
if (meshes.length === 0) {
|
|
@@ -12969,7 +13230,7 @@ __export(exports_url_handler, {
|
|
|
12969
13230
|
runUrlHandler: () => runUrlHandler
|
|
12970
13231
|
});
|
|
12971
13232
|
import { platform as platform7, homedir as homedir9 } from "node:os";
|
|
12972
|
-
import { existsSync as
|
|
13233
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync9, writeFileSync as writeFileSync14, rmSync as rmSync3, chmodSync as chmodSync5 } from "node:fs";
|
|
12973
13234
|
import { join as join12 } from "node:path";
|
|
12974
13235
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
12975
13236
|
function resolveClaudemeshBin() {
|
|
@@ -13003,7 +13264,7 @@ function installDarwin2() {
|
|
|
13003
13264
|
</array>
|
|
13004
13265
|
</dict>
|
|
13005
13266
|
</plist>`;
|
|
13006
|
-
|
|
13267
|
+
writeFileSync14(join12(contents, "Info.plist"), plist);
|
|
13007
13268
|
const shim = `#!/bin/sh
|
|
13008
13269
|
URL="$1"
|
|
13009
13270
|
CODE=\${URL#claudemesh://}
|
|
@@ -13018,7 +13279,7 @@ end tell
|
|
|
13018
13279
|
EOF
|
|
13019
13280
|
`;
|
|
13020
13281
|
const shimPath = join12(macOS, "open-url");
|
|
13021
|
-
|
|
13282
|
+
writeFileSync14(shimPath, shim);
|
|
13022
13283
|
chmodSync5(shimPath, 493);
|
|
13023
13284
|
const lsreg = spawnSync5("/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister", ["-f", appDir], { encoding: "utf-8" });
|
|
13024
13285
|
if (lsreg.status !== 0) {
|
|
@@ -13042,7 +13303,7 @@ MimeType=x-scheme-handler/claudemesh;
|
|
|
13042
13303
|
NoDisplay=true
|
|
13043
13304
|
`;
|
|
13044
13305
|
const desktopPath = join12(appsDir, "claudemesh.desktop");
|
|
13045
|
-
|
|
13306
|
+
writeFileSync14(desktopPath, desktop);
|
|
13046
13307
|
const xdg1 = spawnSync5("xdg-mime", ["default", "claudemesh.desktop", "x-scheme-handler/claudemesh"], { encoding: "utf-8" });
|
|
13047
13308
|
if (xdg1.status !== 0) {
|
|
13048
13309
|
render.warn("xdg-mime not available — skipped mime default registration");
|
|
@@ -13065,7 +13326,7 @@ function installWindows() {
|
|
|
13065
13326
|
`@="\\"${binPath.replace(/\\/g, "\\\\")}\\" \\"%1\\""`
|
|
13066
13327
|
];
|
|
13067
13328
|
const regPath = join12(homedir9(), "claudemesh-handler.reg");
|
|
13068
|
-
|
|
13329
|
+
writeFileSync14(regPath, lines.join(`\r
|
|
13069
13330
|
`));
|
|
13070
13331
|
const res = spawnSync5("reg.exe", ["import", regPath], { encoding: "utf-8" });
|
|
13071
13332
|
if (res.status !== 0) {
|
|
@@ -13077,14 +13338,14 @@ function installWindows() {
|
|
|
13077
13338
|
}
|
|
13078
13339
|
function uninstallDarwin() {
|
|
13079
13340
|
const appDir = join12(homedir9(), "Library", "Application Support", "claudemesh", "ClaudemeshHandler.app");
|
|
13080
|
-
if (
|
|
13341
|
+
if (existsSync21(appDir))
|
|
13081
13342
|
rmSync3(appDir, { recursive: true, force: true });
|
|
13082
13343
|
render.ok("removed claudemesh:// handler on macOS");
|
|
13083
13344
|
return EXIT.SUCCESS;
|
|
13084
13345
|
}
|
|
13085
13346
|
function uninstallLinux() {
|
|
13086
13347
|
const desktopPath = join12(homedir9(), ".local", "share", "applications", "claudemesh.desktop");
|
|
13087
|
-
if (
|
|
13348
|
+
if (existsSync21(desktopPath))
|
|
13088
13349
|
rmSync3(desktopPath, { force: true });
|
|
13089
13350
|
render.ok("removed claudemesh:// handler on Linux");
|
|
13090
13351
|
return EXIT.SUCCESS;
|
|
@@ -13129,7 +13390,7 @@ var exports_status_line = {};
|
|
|
13129
13390
|
__export(exports_status_line, {
|
|
13130
13391
|
runStatusLine: () => runStatusLine
|
|
13131
13392
|
});
|
|
13132
|
-
import { existsSync as
|
|
13393
|
+
import { existsSync as existsSync22, readFileSync as readFileSync18 } from "node:fs";
|
|
13133
13394
|
import { join as join13 } from "node:path";
|
|
13134
13395
|
import { homedir as homedir10 } from "node:os";
|
|
13135
13396
|
async function runStatusLine() {
|
|
@@ -13141,9 +13402,9 @@ async function runStatusLine() {
|
|
|
13141
13402
|
}
|
|
13142
13403
|
const cachePath = join13(homedir10(), ".claudemesh", "peer-cache.json");
|
|
13143
13404
|
let cache = {};
|
|
13144
|
-
if (
|
|
13405
|
+
if (existsSync22(cachePath)) {
|
|
13145
13406
|
try {
|
|
13146
|
-
cache = JSON.parse(
|
|
13407
|
+
cache = JSON.parse(readFileSync18(cachePath, "utf-8"));
|
|
13147
13408
|
} catch {}
|
|
13148
13409
|
}
|
|
13149
13410
|
const pick = config.meshes[0];
|
|
@@ -13174,7 +13435,7 @@ __export(exports_backup, {
|
|
|
13174
13435
|
runRestore: () => runRestore,
|
|
13175
13436
|
runBackup: () => runBackup
|
|
13176
13437
|
});
|
|
13177
|
-
import { readFileSync as
|
|
13438
|
+
import { readFileSync as readFileSync19, writeFileSync as writeFileSync15, existsSync as existsSync23 } from "node:fs";
|
|
13178
13439
|
import { createInterface as createInterface11 } from "node:readline";
|
|
13179
13440
|
function readHidden(prompt5) {
|
|
13180
13441
|
return new Promise((resolve2) => {
|
|
@@ -13216,11 +13477,11 @@ async function deriveKey(pass, salt, s) {
|
|
|
13216
13477
|
}
|
|
13217
13478
|
async function runBackup(outPath) {
|
|
13218
13479
|
const configPath = getConfigPath();
|
|
13219
|
-
if (!
|
|
13480
|
+
if (!existsSync23(configPath)) {
|
|
13220
13481
|
console.error(" No config found — nothing to back up. Join a mesh first.");
|
|
13221
13482
|
return EXIT.NOT_FOUND;
|
|
13222
13483
|
}
|
|
13223
|
-
const plaintext =
|
|
13484
|
+
const plaintext = readFileSync19(configPath);
|
|
13224
13485
|
const pass = await readHidden(" Passphrase (min 12 chars): ");
|
|
13225
13486
|
if (pass.length < 12) {
|
|
13226
13487
|
console.error(" ✗ Passphrase too short.");
|
|
@@ -13238,7 +13499,7 @@ async function runBackup(outPath) {
|
|
|
13238
13499
|
const ciphertext = Buffer.from(s.crypto_aead_xchacha20poly1305_ietf_encrypt(plaintext, null, null, nonce, key));
|
|
13239
13500
|
const blob = Buffer.concat([MAGIC, salt, nonce, ciphertext]);
|
|
13240
13501
|
const file = outPath ?? `claudemesh-backup-${new Date().toISOString().replace(/[:.]/g, "-")}.cmb`;
|
|
13241
|
-
|
|
13502
|
+
writeFileSync15(file, blob, { mode: 384 });
|
|
13242
13503
|
console.log(`
|
|
13243
13504
|
✓ Backup saved: ${file}`);
|
|
13244
13505
|
console.log(` Size: ${blob.length} bytes. Guard the passphrase — there is no recovery.
|
|
@@ -13250,11 +13511,11 @@ async function runRestore(inPath) {
|
|
|
13250
13511
|
console.error(" Usage: claudemesh restore <backup-file>");
|
|
13251
13512
|
return EXIT.INVALID_ARGS;
|
|
13252
13513
|
}
|
|
13253
|
-
if (!
|
|
13514
|
+
if (!existsSync23(inPath)) {
|
|
13254
13515
|
console.error(` ✗ File not found: ${inPath}`);
|
|
13255
13516
|
return EXIT.NOT_FOUND;
|
|
13256
13517
|
}
|
|
13257
|
-
const blob =
|
|
13518
|
+
const blob = readFileSync19(inPath);
|
|
13258
13519
|
if (blob.length < 4 + 16 + 24 + 17 || !blob.subarray(0, 4).equals(MAGIC)) {
|
|
13259
13520
|
console.error(" ✗ Not a claudemesh backup file (bad magic).");
|
|
13260
13521
|
return EXIT.INVALID_ARGS;
|
|
@@ -13273,12 +13534,12 @@ async function runRestore(inPath) {
|
|
|
13273
13534
|
return EXIT.INTERNAL_ERROR;
|
|
13274
13535
|
}
|
|
13275
13536
|
const configPath = getConfigPath();
|
|
13276
|
-
if (
|
|
13537
|
+
if (existsSync23(configPath)) {
|
|
13277
13538
|
const backupOld = `${configPath}.before-restore.${Date.now()}`;
|
|
13278
|
-
|
|
13539
|
+
writeFileSync15(backupOld, readFileSync19(configPath), { mode: 384 });
|
|
13279
13540
|
console.log(` ↻ Existing config saved to ${backupOld}`);
|
|
13280
13541
|
}
|
|
13281
|
-
|
|
13542
|
+
writeFileSync15(configPath, Buffer.from(plaintext), { mode: 384 });
|
|
13282
13543
|
console.log(`
|
|
13283
13544
|
✓ Config restored to ${configPath}`);
|
|
13284
13545
|
console.log(" Run `claudemesh list` to verify your meshes.\n");
|
|
@@ -13298,7 +13559,7 @@ __export(exports_upgrade, {
|
|
|
13298
13559
|
runUpgrade: () => runUpgrade
|
|
13299
13560
|
});
|
|
13300
13561
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
13301
|
-
import { existsSync as
|
|
13562
|
+
import { existsSync as existsSync24 } from "node:fs";
|
|
13302
13563
|
import { dirname as dirname8, join as join14, resolve as resolve2 } from "node:path";
|
|
13303
13564
|
async function latestVersion() {
|
|
13304
13565
|
try {
|
|
@@ -13313,14 +13574,14 @@ async function latestVersion() {
|
|
|
13313
13574
|
}
|
|
13314
13575
|
function findNpm() {
|
|
13315
13576
|
const portable = join14(process.env.HOME ?? "", ".claudemesh", "node", "bin", "npm");
|
|
13316
|
-
if (
|
|
13577
|
+
if (existsSync24(portable)) {
|
|
13317
13578
|
return { npm: portable, prefix: join14(process.env.HOME ?? "", ".claudemesh") };
|
|
13318
13579
|
}
|
|
13319
13580
|
let cur = resolve2(process.argv[1] ?? ".");
|
|
13320
13581
|
for (let i = 0;i < 6; i++) {
|
|
13321
13582
|
cur = dirname8(cur);
|
|
13322
13583
|
const candidate = join14(cur, "bin", "npm");
|
|
13323
|
-
if (
|
|
13584
|
+
if (existsSync24(candidate))
|
|
13324
13585
|
return { npm: candidate };
|
|
13325
13586
|
}
|
|
13326
13587
|
return { npm: "npm" };
|
|
@@ -13382,7 +13643,7 @@ __export(exports_grants, {
|
|
|
13382
13643
|
runBlock: () => runBlock,
|
|
13383
13644
|
isAllowed: () => isAllowed
|
|
13384
13645
|
});
|
|
13385
|
-
import { existsSync as
|
|
13646
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync10, readFileSync as readFileSync20, writeFileSync as writeFileSync16 } from "node:fs";
|
|
13386
13647
|
import { homedir as homedir11 } from "node:os";
|
|
13387
13648
|
import { join as join15 } from "node:path";
|
|
13388
13649
|
async function syncToBroker(meshSlug, grants) {
|
|
@@ -13402,19 +13663,19 @@ async function syncToBroker(meshSlug, grants) {
|
|
|
13402
13663
|
}
|
|
13403
13664
|
}
|
|
13404
13665
|
function readGrants() {
|
|
13405
|
-
if (!
|
|
13666
|
+
if (!existsSync25(GRANT_FILE))
|
|
13406
13667
|
return {};
|
|
13407
13668
|
try {
|
|
13408
|
-
return JSON.parse(
|
|
13669
|
+
return JSON.parse(readFileSync20(GRANT_FILE, "utf-8"));
|
|
13409
13670
|
} catch {
|
|
13410
13671
|
return {};
|
|
13411
13672
|
}
|
|
13412
13673
|
}
|
|
13413
13674
|
function writeGrants(g) {
|
|
13414
13675
|
const dir = join15(homedir11(), ".claudemesh");
|
|
13415
|
-
if (!
|
|
13676
|
+
if (!existsSync25(dir))
|
|
13416
13677
|
mkdirSync10(dir, { recursive: true });
|
|
13417
|
-
|
|
13678
|
+
writeFileSync16(GRANT_FILE, JSON.stringify(g, null, 2), { mode: 384 });
|
|
13418
13679
|
}
|
|
13419
13680
|
function resolveCaps(input) {
|
|
13420
13681
|
if (input.includes("all"))
|
|
@@ -15252,7 +15513,7 @@ __export(exports_file, {
|
|
|
15252
15513
|
});
|
|
15253
15514
|
import { hostname as osHostname } from "node:os";
|
|
15254
15515
|
import { resolve as resolvePath, basename, dirname as dirname9 } from "node:path";
|
|
15255
|
-
import { statSync as statSync7, existsSync as
|
|
15516
|
+
import { statSync as statSync7, existsSync as existsSync26, writeFileSync as writeFileSync17, mkdirSync as mkdirSync11 } from "node:fs";
|
|
15256
15517
|
function emitJson2(data) {
|
|
15257
15518
|
console.log(JSON.stringify(data, null, 2));
|
|
15258
15519
|
}
|
|
@@ -15269,7 +15530,7 @@ async function runFileShare(filePath, opts) {
|
|
|
15269
15530
|
return EXIT.INVALID_ARGS;
|
|
15270
15531
|
}
|
|
15271
15532
|
const absPath = resolvePath(filePath);
|
|
15272
|
-
if (!
|
|
15533
|
+
if (!existsSync26(absPath)) {
|
|
15273
15534
|
render.err(`File not found: ${absPath}`);
|
|
15274
15535
|
return EXIT.INVALID_ARGS;
|
|
15275
15536
|
}
|
|
@@ -15349,7 +15610,7 @@ async function runFileGet(fileId, opts) {
|
|
|
15349
15610
|
const buf = Buffer.from(await res.arrayBuffer());
|
|
15350
15611
|
const outPath = opts.out ? resolvePath(opts.out) : resolvePath(process.cwd(), meta.name);
|
|
15351
15612
|
mkdirSync11(dirname9(outPath), { recursive: true });
|
|
15352
|
-
|
|
15613
|
+
writeFileSync17(outPath, buf);
|
|
15353
15614
|
if (opts.json) {
|
|
15354
15615
|
emitJson2({ fileId, name: meta.name, savedTo: outPath, sizeBytes: buf.length });
|
|
15355
15616
|
} else {
|
|
@@ -15959,7 +16220,7 @@ __export(exports_bridge, {
|
|
|
15959
16220
|
runBridge: () => runBridge,
|
|
15960
16221
|
bridgeConfigTemplate: () => bridgeConfigTemplate
|
|
15961
16222
|
});
|
|
15962
|
-
import { readFileSync as
|
|
16223
|
+
import { readFileSync as readFileSync21, existsSync as existsSync27 } from "node:fs";
|
|
15963
16224
|
function parseConfig(text) {
|
|
15964
16225
|
const trimmed = text.trim();
|
|
15965
16226
|
if (trimmed.startsWith("{"))
|
|
@@ -16003,13 +16264,13 @@ async function runBridge(configPath) {
|
|
|
16003
16264
|
render.err("Usage: claudemesh bridge run <config.yaml>");
|
|
16004
16265
|
return EXIT.INVALID_ARGS;
|
|
16005
16266
|
}
|
|
16006
|
-
if (!
|
|
16267
|
+
if (!existsSync27(configPath)) {
|
|
16007
16268
|
render.err(`config file not found: ${configPath}`);
|
|
16008
16269
|
return EXIT.NOT_FOUND;
|
|
16009
16270
|
}
|
|
16010
16271
|
let cfg;
|
|
16011
16272
|
try {
|
|
16012
|
-
cfg = parseConfig(
|
|
16273
|
+
cfg = parseConfig(readFileSync21(configPath, "utf-8"));
|
|
16013
16274
|
} catch (e) {
|
|
16014
16275
|
render.err(`failed to parse ${configPath}: ${e instanceof Error ? e.message : String(e)}`);
|
|
16015
16276
|
return EXIT.INVALID_ARGS;
|
|
@@ -16413,9 +16674,9 @@ function cacheKey(apiKeySecret, topicName) {
|
|
|
16413
16674
|
async function getTopicKey(args) {
|
|
16414
16675
|
const cacheId = cacheKey(args.apiKeySecret, args.topicName);
|
|
16415
16676
|
if (!args.fresh) {
|
|
16416
|
-
const
|
|
16417
|
-
if (
|
|
16418
|
-
return { ok: true, topicKey:
|
|
16677
|
+
const cached3 = cache.get(cacheId);
|
|
16678
|
+
if (cached3)
|
|
16679
|
+
return { ok: true, topicKey: cached3.topicKey };
|
|
16419
16680
|
}
|
|
16420
16681
|
let sealed;
|
|
16421
16682
|
try {
|
|
@@ -16983,11 +17244,11 @@ import {
|
|
|
16983
17244
|
ListResourcesRequestSchema,
|
|
16984
17245
|
ReadResourceRequestSchema
|
|
16985
17246
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
16986
|
-
import { existsSync as
|
|
17247
|
+
import { existsSync as existsSync28 } from "node:fs";
|
|
16987
17248
|
import { request as httpRequest2 } from "node:http";
|
|
16988
17249
|
async function daemonReady() {
|
|
16989
17250
|
for (let i = 0;i < DAEMON_BOOT_RETRIES; i++) {
|
|
16990
|
-
if (
|
|
17251
|
+
if (existsSync28(DAEMON_PATHS.SOCK_FILE))
|
|
16991
17252
|
return true;
|
|
16992
17253
|
await new Promise((r) => setTimeout(r, DAEMON_BOOT_RETRY_MS));
|
|
16993
17254
|
}
|
|
@@ -17317,9 +17578,9 @@ async function startServiceProxy(serviceName) {
|
|
|
17317
17578
|
const fetched = await client.getServiceTools(serviceName);
|
|
17318
17579
|
tools = fetched;
|
|
17319
17580
|
} catch {
|
|
17320
|
-
const
|
|
17321
|
-
if (
|
|
17322
|
-
tools =
|
|
17581
|
+
const cached3 = client.serviceCatalog.find((s) => s.name === serviceName);
|
|
17582
|
+
if (cached3)
|
|
17583
|
+
tools = cached3.tools;
|
|
17323
17584
|
}
|
|
17324
17585
|
if (tools.length === 0) {
|
|
17325
17586
|
process.stderr.write(`[mesh:${serviceName}] no tools found — service may not be running
|
|
@@ -19289,4 +19550,4 @@ main().catch((err) => {
|
|
|
19289
19550
|
process.exit(EXIT.INTERNAL_ERROR);
|
|
19290
19551
|
});
|
|
19291
19552
|
|
|
19292
|
-
//# debugId=
|
|
19553
|
+
//# debugId=FBD494B01BF81C7164756E2164756E21
|