claudemesh-cli 1.0.3 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/entrypoints/cli.js +904 -136
- package/dist/entrypoints/cli.js.map +11 -7
- package/dist/entrypoints/mcp.js +280 -38
- package/dist/entrypoints/mcp.js.map +6 -4
- package/package.json +1 -1
package/dist/entrypoints/cli.js
CHANGED
|
@@ -88,7 +88,7 @@ __export(exports_urls, {
|
|
|
88
88
|
VERSION: () => VERSION,
|
|
89
89
|
URLS: () => URLS
|
|
90
90
|
});
|
|
91
|
-
var URLS, VERSION = "1.0
|
|
91
|
+
var URLS, VERSION = "1.2.0", env;
|
|
92
92
|
var init_urls = __esm(() => {
|
|
93
93
|
URLS = {
|
|
94
94
|
BROKER: process.env.CLAUDEMESH_BROKER_URL ?? "wss://ic.claudemesh.com/ws",
|
|
@@ -6392,11 +6392,136 @@ var init_ban = __esm(() => {
|
|
|
6392
6392
|
init_exit_codes();
|
|
6393
6393
|
});
|
|
6394
6394
|
|
|
6395
|
+
// src/services/bridge/protocol.ts
|
|
6396
|
+
import { homedir as homedir4 } from "node:os";
|
|
6397
|
+
import { join as join4 } from "node:path";
|
|
6398
|
+
function socketPath(meshSlug) {
|
|
6399
|
+
return join4(homedir4(), ".claudemesh", "sockets", `${meshSlug}.sock`);
|
|
6400
|
+
}
|
|
6401
|
+
function socketDir() {
|
|
6402
|
+
return join4(homedir4(), ".claudemesh", "sockets");
|
|
6403
|
+
}
|
|
6404
|
+
function frame(obj) {
|
|
6405
|
+
return JSON.stringify(obj) + `
|
|
6406
|
+
`;
|
|
6407
|
+
}
|
|
6408
|
+
|
|
6409
|
+
class LineParser {
|
|
6410
|
+
buf = "";
|
|
6411
|
+
feed(chunk) {
|
|
6412
|
+
this.buf += typeof chunk === "string" ? chunk : chunk.toString("utf-8");
|
|
6413
|
+
const lines = [];
|
|
6414
|
+
let nl = this.buf.indexOf(`
|
|
6415
|
+
`);
|
|
6416
|
+
while (nl !== -1) {
|
|
6417
|
+
lines.push(this.buf.slice(0, nl));
|
|
6418
|
+
this.buf = this.buf.slice(nl + 1);
|
|
6419
|
+
nl = this.buf.indexOf(`
|
|
6420
|
+
`);
|
|
6421
|
+
}
|
|
6422
|
+
return lines;
|
|
6423
|
+
}
|
|
6424
|
+
}
|
|
6425
|
+
var init_protocol = () => {};
|
|
6426
|
+
|
|
6427
|
+
// src/services/bridge/client.ts
|
|
6428
|
+
import { createConnection } from "node:net";
|
|
6429
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
6430
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
6431
|
+
async function tryBridge(meshSlug, verb, args = {}, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
6432
|
+
const path = socketPath(meshSlug);
|
|
6433
|
+
if (!existsSync5(path))
|
|
6434
|
+
return null;
|
|
6435
|
+
return new Promise((resolve) => {
|
|
6436
|
+
const id = randomUUID2();
|
|
6437
|
+
const req = { id, verb, args };
|
|
6438
|
+
const parser = new LineParser;
|
|
6439
|
+
let settled = false;
|
|
6440
|
+
const finish = (value) => {
|
|
6441
|
+
if (settled)
|
|
6442
|
+
return;
|
|
6443
|
+
settled = true;
|
|
6444
|
+
try {
|
|
6445
|
+
socket.destroy();
|
|
6446
|
+
} catch {}
|
|
6447
|
+
clearTimeout(timer);
|
|
6448
|
+
resolve(value);
|
|
6449
|
+
};
|
|
6450
|
+
const socket = createConnection({ path });
|
|
6451
|
+
const timer = setTimeout(() => {
|
|
6452
|
+
finish(null);
|
|
6453
|
+
}, timeoutMs);
|
|
6454
|
+
socket.on("connect", () => {
|
|
6455
|
+
try {
|
|
6456
|
+
socket.write(frame(req));
|
|
6457
|
+
} catch {
|
|
6458
|
+
finish(null);
|
|
6459
|
+
}
|
|
6460
|
+
});
|
|
6461
|
+
socket.on("data", (chunk) => {
|
|
6462
|
+
const lines = parser.feed(chunk);
|
|
6463
|
+
for (const line of lines) {
|
|
6464
|
+
if (!line.trim())
|
|
6465
|
+
continue;
|
|
6466
|
+
let res;
|
|
6467
|
+
try {
|
|
6468
|
+
res = JSON.parse(line);
|
|
6469
|
+
} catch {
|
|
6470
|
+
continue;
|
|
6471
|
+
}
|
|
6472
|
+
if (res.id !== id)
|
|
6473
|
+
continue;
|
|
6474
|
+
if (res.ok)
|
|
6475
|
+
finish({ ok: true, result: res.result });
|
|
6476
|
+
else
|
|
6477
|
+
finish({ ok: false, error: res.error });
|
|
6478
|
+
return;
|
|
6479
|
+
}
|
|
6480
|
+
});
|
|
6481
|
+
socket.on("error", (err) => {
|
|
6482
|
+
const code = err.code;
|
|
6483
|
+
if (code === "ECONNREFUSED" || code === "ENOENT" || code === "EPERM") {
|
|
6484
|
+
finish(null);
|
|
6485
|
+
} else {
|
|
6486
|
+
finish(null);
|
|
6487
|
+
}
|
|
6488
|
+
});
|
|
6489
|
+
socket.on("close", () => {
|
|
6490
|
+
finish(null);
|
|
6491
|
+
});
|
|
6492
|
+
});
|
|
6493
|
+
}
|
|
6494
|
+
var DEFAULT_TIMEOUT_MS = 5000;
|
|
6495
|
+
var init_client3 = __esm(() => {
|
|
6496
|
+
init_protocol();
|
|
6497
|
+
});
|
|
6498
|
+
|
|
6395
6499
|
// src/commands/peers.ts
|
|
6396
6500
|
var exports_peers = {};
|
|
6397
6501
|
__export(exports_peers, {
|
|
6398
6502
|
runPeers: () => runPeers
|
|
6399
6503
|
});
|
|
6504
|
+
function projectFields(record, fields) {
|
|
6505
|
+
const out = {};
|
|
6506
|
+
for (const f of fields) {
|
|
6507
|
+
const sourceKey = FIELD_ALIAS[f] ?? f;
|
|
6508
|
+
out[f] = record[sourceKey];
|
|
6509
|
+
}
|
|
6510
|
+
return out;
|
|
6511
|
+
}
|
|
6512
|
+
async function listPeersForMesh(slug) {
|
|
6513
|
+
const bridged = await tryBridge(slug, "peers");
|
|
6514
|
+
if (bridged && bridged.ok) {
|
|
6515
|
+
return bridged.result;
|
|
6516
|
+
}
|
|
6517
|
+
let result = [];
|
|
6518
|
+
await withMesh({ meshSlug: slug }, async (client) => {
|
|
6519
|
+
const all = await client.listPeers();
|
|
6520
|
+
const selfPubkey = client.getSessionPubkey();
|
|
6521
|
+
result = selfPubkey ? all.filter((p) => p.pubkey !== selfPubkey) : all;
|
|
6522
|
+
});
|
|
6523
|
+
return result;
|
|
6524
|
+
}
|
|
6400
6525
|
async function runPeers(flags) {
|
|
6401
6526
|
const config = readConfig();
|
|
6402
6527
|
const slugs = flags.mesh ? [flags.mesh] : config.meshes.map((m) => m.slug);
|
|
@@ -6405,55 +6530,59 @@ async function runPeers(flags) {
|
|
|
6405
6530
|
render.hint("claudemesh <invite-url> # join + launch");
|
|
6406
6531
|
process.exit(1);
|
|
6407
6532
|
}
|
|
6533
|
+
const fieldList = typeof flags.json === "string" && flags.json.length > 0 ? flags.json.split(",").map((s) => s.trim()).filter(Boolean) : null;
|
|
6534
|
+
const wantsJson = flags.json !== undefined && flags.json !== false;
|
|
6408
6535
|
const allJson = [];
|
|
6409
6536
|
for (const slug of slugs) {
|
|
6410
6537
|
try {
|
|
6411
|
-
|
|
6412
|
-
|
|
6413
|
-
const
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
render.
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
}
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
render.info(
|
|
6439
|
-
|
|
6440
|
-
render.info(dim(` cwd: ${p.cwd}`));
|
|
6441
|
-
}
|
|
6442
|
-
});
|
|
6538
|
+
const peers = await listPeersForMesh(slug);
|
|
6539
|
+
if (wantsJson) {
|
|
6540
|
+
const projected = fieldList ? peers.map((p) => projectFields(p, fieldList)) : peers;
|
|
6541
|
+
allJson.push({ mesh: slug, peers: projected });
|
|
6542
|
+
continue;
|
|
6543
|
+
}
|
|
6544
|
+
render.section(`peers on ${slug} (${peers.length})`);
|
|
6545
|
+
if (peers.length === 0) {
|
|
6546
|
+
render.info(dim(" (no peers connected)"));
|
|
6547
|
+
continue;
|
|
6548
|
+
}
|
|
6549
|
+
for (const p of peers) {
|
|
6550
|
+
const groups = p.groups.length ? " [" + p.groups.map((g) => `@${g.name}${g.role ? `:${g.role}` : ""}`).join(", ") + "]" : "";
|
|
6551
|
+
const statusDot = p.status === "working" ? yellow("●") : green("●");
|
|
6552
|
+
const name = bold(p.displayName);
|
|
6553
|
+
const meta = [];
|
|
6554
|
+
if (p.peerType)
|
|
6555
|
+
meta.push(p.peerType);
|
|
6556
|
+
if (p.channel)
|
|
6557
|
+
meta.push(p.channel);
|
|
6558
|
+
if (p.model)
|
|
6559
|
+
meta.push(p.model);
|
|
6560
|
+
const metaStr = meta.length ? dim(` (${meta.join(", ")})`) : "";
|
|
6561
|
+
const summary = p.summary ? dim(` — ${p.summary}`) : "";
|
|
6562
|
+
const pubkeyTag = dim(` · ${p.pubkey.slice(0, 16)}…`);
|
|
6563
|
+
render.info(`${statusDot} ${name}${groups}${metaStr}${pubkeyTag}${summary}`);
|
|
6564
|
+
if (p.cwd)
|
|
6565
|
+
render.info(dim(` cwd: ${p.cwd}`));
|
|
6566
|
+
}
|
|
6443
6567
|
} catch (e) {
|
|
6444
6568
|
render.err(`${slug}: ${e instanceof Error ? e.message : String(e)}`);
|
|
6445
6569
|
}
|
|
6446
6570
|
}
|
|
6447
|
-
if (
|
|
6571
|
+
if (wantsJson) {
|
|
6448
6572
|
process.stdout.write(JSON.stringify(slugs.length === 1 ? allJson[0]?.peers : allJson, null, 2) + `
|
|
6449
6573
|
`);
|
|
6450
6574
|
}
|
|
6451
6575
|
}
|
|
6576
|
+
var FIELD_ALIAS;
|
|
6452
6577
|
var init_peers = __esm(() => {
|
|
6453
6578
|
init_connect();
|
|
6454
6579
|
init_facade();
|
|
6580
|
+
init_client3();
|
|
6455
6581
|
init_render();
|
|
6456
6582
|
init_styles();
|
|
6583
|
+
FIELD_ALIAS = {
|
|
6584
|
+
name: "displayName"
|
|
6585
|
+
};
|
|
6457
6586
|
});
|
|
6458
6587
|
|
|
6459
6588
|
// src/commands/send.ts
|
|
@@ -6462,7 +6591,33 @@ __export(exports_send, {
|
|
|
6462
6591
|
runSend: () => runSend
|
|
6463
6592
|
});
|
|
6464
6593
|
async function runSend(flags, to, message) {
|
|
6594
|
+
if (!to || !message) {
|
|
6595
|
+
render.err("Usage: claudemesh send <to> <message>");
|
|
6596
|
+
process.exit(1);
|
|
6597
|
+
}
|
|
6465
6598
|
const priority = flags.priority === "now" ? "now" : flags.priority === "low" ? "low" : "next";
|
|
6599
|
+
const config = readConfig();
|
|
6600
|
+
const meshSlug = flags.mesh ?? (config.meshes.length === 1 ? config.meshes[0].slug : null);
|
|
6601
|
+
if (meshSlug) {
|
|
6602
|
+
const bridged = await tryBridge(meshSlug, "send", { to, message, priority });
|
|
6603
|
+
if (bridged !== null) {
|
|
6604
|
+
if (bridged.ok) {
|
|
6605
|
+
const r = bridged.result;
|
|
6606
|
+
if (flags.json) {
|
|
6607
|
+
console.log(JSON.stringify({ ok: true, messageId: r.messageId, target: to }));
|
|
6608
|
+
} else {
|
|
6609
|
+
render.ok(`sent to ${to}`, r.messageId ? dim(r.messageId.slice(0, 8)) : undefined);
|
|
6610
|
+
}
|
|
6611
|
+
return;
|
|
6612
|
+
}
|
|
6613
|
+
if (flags.json) {
|
|
6614
|
+
console.log(JSON.stringify({ ok: false, error: bridged.error }));
|
|
6615
|
+
} else {
|
|
6616
|
+
render.err(`send failed: ${bridged.error}`);
|
|
6617
|
+
}
|
|
6618
|
+
process.exit(1);
|
|
6619
|
+
}
|
|
6620
|
+
}
|
|
6466
6621
|
await withMesh({ meshSlug: flags.mesh ?? null }, async (client) => {
|
|
6467
6622
|
let targetSpec = to;
|
|
6468
6623
|
if (!to.startsWith("@") && to !== "*" && !/^[0-9a-f]{64}$/i.test(to)) {
|
|
@@ -6470,22 +6625,34 @@ async function runSend(flags, to, message) {
|
|
|
6470
6625
|
const match = peers.find((p) => p.displayName.toLowerCase() === to.toLowerCase());
|
|
6471
6626
|
if (!match) {
|
|
6472
6627
|
const names = peers.map((p) => p.displayName).join(", ");
|
|
6473
|
-
|
|
6628
|
+
render.err(`Peer "${to}" not found.`, `online: ${names || "(none)"}`);
|
|
6474
6629
|
process.exit(1);
|
|
6475
6630
|
}
|
|
6476
6631
|
targetSpec = match.pubkey;
|
|
6477
6632
|
}
|
|
6478
6633
|
const result = await client.send(targetSpec, message, priority);
|
|
6479
6634
|
if (result.ok) {
|
|
6480
|
-
|
|
6635
|
+
if (flags.json) {
|
|
6636
|
+
console.log(JSON.stringify({ ok: true, messageId: result.messageId, target: to }));
|
|
6637
|
+
} else {
|
|
6638
|
+
render.ok(`sent to ${to}`, result.messageId ? dim(result.messageId.slice(0, 8)) : undefined);
|
|
6639
|
+
}
|
|
6481
6640
|
} else {
|
|
6482
|
-
|
|
6641
|
+
if (flags.json) {
|
|
6642
|
+
console.log(JSON.stringify({ ok: false, error: result.error ?? "unknown" }));
|
|
6643
|
+
} else {
|
|
6644
|
+
render.err(`send failed: ${result.error ?? "unknown error"}`);
|
|
6645
|
+
}
|
|
6483
6646
|
process.exit(1);
|
|
6484
6647
|
}
|
|
6485
6648
|
});
|
|
6486
6649
|
}
|
|
6487
6650
|
var init_send = __esm(() => {
|
|
6488
6651
|
init_connect();
|
|
6652
|
+
init_facade();
|
|
6653
|
+
init_client3();
|
|
6654
|
+
init_render();
|
|
6655
|
+
init_styles();
|
|
6489
6656
|
});
|
|
6490
6657
|
|
|
6491
6658
|
// src/commands/inbox.ts
|
|
@@ -6715,6 +6882,313 @@ var init_recall = __esm(() => {
|
|
|
6715
6882
|
init_exit_codes();
|
|
6716
6883
|
});
|
|
6717
6884
|
|
|
6885
|
+
// src/commands/broker-actions.ts
|
|
6886
|
+
var exports_broker_actions = {};
|
|
6887
|
+
__export(exports_broker_actions, {
|
|
6888
|
+
runVisible: () => runVisible,
|
|
6889
|
+
runTaskComplete: () => runTaskComplete,
|
|
6890
|
+
runTaskClaim: () => runTaskClaim,
|
|
6891
|
+
runSummary: () => runSummary,
|
|
6892
|
+
runStatusSet: () => runStatusSet,
|
|
6893
|
+
runStats: () => runStats,
|
|
6894
|
+
runPing: () => runPing,
|
|
6895
|
+
runMsgStatus: () => runMsgStatus,
|
|
6896
|
+
runGroupLeave: () => runGroupLeave,
|
|
6897
|
+
runGroupJoin: () => runGroupJoin,
|
|
6898
|
+
runForget: () => runForget,
|
|
6899
|
+
runClock: () => runClock
|
|
6900
|
+
});
|
|
6901
|
+
function unambiguousMesh(opts) {
|
|
6902
|
+
if (opts.mesh)
|
|
6903
|
+
return opts.mesh;
|
|
6904
|
+
const config = readConfig();
|
|
6905
|
+
return config.meshes.length === 1 ? config.meshes[0].slug : null;
|
|
6906
|
+
}
|
|
6907
|
+
async function runStatusSet(state, opts) {
|
|
6908
|
+
const valid = ["idle", "working", "dnd"];
|
|
6909
|
+
if (!valid.includes(state)) {
|
|
6910
|
+
render.err(`Invalid status: ${state}`, `must be one of: ${valid.join(", ")}`);
|
|
6911
|
+
return EXIT.INVALID_ARGS;
|
|
6912
|
+
}
|
|
6913
|
+
const meshSlug = unambiguousMesh(opts);
|
|
6914
|
+
if (meshSlug) {
|
|
6915
|
+
const bridged = await tryBridge(meshSlug, "status_set", { status: state });
|
|
6916
|
+
if (bridged !== null) {
|
|
6917
|
+
if (bridged.ok) {
|
|
6918
|
+
if (opts.json)
|
|
6919
|
+
console.log(JSON.stringify({ status: state }));
|
|
6920
|
+
else
|
|
6921
|
+
render.ok(`status set to ${bold(state)}`);
|
|
6922
|
+
return EXIT.SUCCESS;
|
|
6923
|
+
}
|
|
6924
|
+
render.err(bridged.error);
|
|
6925
|
+
return EXIT.INTERNAL_ERROR;
|
|
6926
|
+
}
|
|
6927
|
+
}
|
|
6928
|
+
await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
|
|
6929
|
+
await client.setStatus(state);
|
|
6930
|
+
});
|
|
6931
|
+
if (opts.json)
|
|
6932
|
+
console.log(JSON.stringify({ status: state }));
|
|
6933
|
+
else
|
|
6934
|
+
render.ok(`status set to ${bold(state)}`);
|
|
6935
|
+
return EXIT.SUCCESS;
|
|
6936
|
+
}
|
|
6937
|
+
async function runSummary(text, opts) {
|
|
6938
|
+
if (!text) {
|
|
6939
|
+
render.err("Usage: claudemesh summary <text>");
|
|
6940
|
+
return EXIT.INVALID_ARGS;
|
|
6941
|
+
}
|
|
6942
|
+
const meshSlug = unambiguousMesh(opts);
|
|
6943
|
+
if (meshSlug) {
|
|
6944
|
+
const bridged = await tryBridge(meshSlug, "summary", { summary: text });
|
|
6945
|
+
if (bridged !== null) {
|
|
6946
|
+
if (bridged.ok) {
|
|
6947
|
+
if (opts.json)
|
|
6948
|
+
console.log(JSON.stringify({ summary: text }));
|
|
6949
|
+
else
|
|
6950
|
+
render.ok("summary set", dim(text));
|
|
6951
|
+
return EXIT.SUCCESS;
|
|
6952
|
+
}
|
|
6953
|
+
render.err(bridged.error);
|
|
6954
|
+
return EXIT.INTERNAL_ERROR;
|
|
6955
|
+
}
|
|
6956
|
+
}
|
|
6957
|
+
await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
|
|
6958
|
+
await client.setSummary(text);
|
|
6959
|
+
});
|
|
6960
|
+
if (opts.json)
|
|
6961
|
+
console.log(JSON.stringify({ summary: text }));
|
|
6962
|
+
else
|
|
6963
|
+
render.ok("summary set", dim(text));
|
|
6964
|
+
return EXIT.SUCCESS;
|
|
6965
|
+
}
|
|
6966
|
+
async function runVisible(value, opts) {
|
|
6967
|
+
let visible;
|
|
6968
|
+
if (value === "true" || value === "1" || value === "yes")
|
|
6969
|
+
visible = true;
|
|
6970
|
+
else if (value === "false" || value === "0" || value === "no")
|
|
6971
|
+
visible = false;
|
|
6972
|
+
else {
|
|
6973
|
+
render.err("Usage: claudemesh visible <true|false>");
|
|
6974
|
+
return EXIT.INVALID_ARGS;
|
|
6975
|
+
}
|
|
6976
|
+
const meshSlug = unambiguousMesh(opts);
|
|
6977
|
+
if (meshSlug) {
|
|
6978
|
+
const bridged = await tryBridge(meshSlug, "visible", { visible });
|
|
6979
|
+
if (bridged !== null) {
|
|
6980
|
+
if (bridged.ok) {
|
|
6981
|
+
if (opts.json)
|
|
6982
|
+
console.log(JSON.stringify({ visible }));
|
|
6983
|
+
else
|
|
6984
|
+
render.ok(visible ? "you are now visible to peers" : "you are now hidden", visible ? undefined : "direct messages still reach you");
|
|
6985
|
+
return EXIT.SUCCESS;
|
|
6986
|
+
}
|
|
6987
|
+
render.err(bridged.error);
|
|
6988
|
+
return EXIT.INTERNAL_ERROR;
|
|
6989
|
+
}
|
|
6990
|
+
}
|
|
6991
|
+
await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
|
|
6992
|
+
await client.setVisible(visible);
|
|
6993
|
+
});
|
|
6994
|
+
if (opts.json)
|
|
6995
|
+
console.log(JSON.stringify({ visible }));
|
|
6996
|
+
else
|
|
6997
|
+
render.ok(visible ? "you are now visible to peers" : "you are now hidden", visible ? undefined : "direct messages still reach you");
|
|
6998
|
+
return EXIT.SUCCESS;
|
|
6999
|
+
}
|
|
7000
|
+
async function runGroupJoin(name, opts) {
|
|
7001
|
+
if (!name) {
|
|
7002
|
+
render.err("Usage: claudemesh group join @<name> [--role X]");
|
|
7003
|
+
return EXIT.INVALID_ARGS;
|
|
7004
|
+
}
|
|
7005
|
+
const cleanName = name.startsWith("@") ? name.slice(1) : name;
|
|
7006
|
+
await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
|
|
7007
|
+
await client.joinGroup(cleanName, opts.role);
|
|
7008
|
+
});
|
|
7009
|
+
if (opts.json) {
|
|
7010
|
+
console.log(JSON.stringify({ group: cleanName, role: opts.role ?? null }));
|
|
7011
|
+
return EXIT.SUCCESS;
|
|
7012
|
+
}
|
|
7013
|
+
render.ok(`joined ${clay("@" + cleanName)}`, opts.role ? `as ${opts.role}` : undefined);
|
|
7014
|
+
return EXIT.SUCCESS;
|
|
7015
|
+
}
|
|
7016
|
+
async function runGroupLeave(name, opts) {
|
|
7017
|
+
if (!name) {
|
|
7018
|
+
render.err("Usage: claudemesh group leave @<name>");
|
|
7019
|
+
return EXIT.INVALID_ARGS;
|
|
7020
|
+
}
|
|
7021
|
+
const cleanName = name.startsWith("@") ? name.slice(1) : name;
|
|
7022
|
+
await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
|
|
7023
|
+
await client.leaveGroup(cleanName);
|
|
7024
|
+
});
|
|
7025
|
+
if (opts.json) {
|
|
7026
|
+
console.log(JSON.stringify({ group: cleanName, left: true }));
|
|
7027
|
+
return EXIT.SUCCESS;
|
|
7028
|
+
}
|
|
7029
|
+
render.ok(`left ${clay("@" + cleanName)}`);
|
|
7030
|
+
return EXIT.SUCCESS;
|
|
7031
|
+
}
|
|
7032
|
+
async function runForget(id, opts) {
|
|
7033
|
+
if (!id) {
|
|
7034
|
+
render.err("Usage: claudemesh forget <memory-id>");
|
|
7035
|
+
return EXIT.INVALID_ARGS;
|
|
7036
|
+
}
|
|
7037
|
+
await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
|
|
7038
|
+
await client.forget(id);
|
|
7039
|
+
});
|
|
7040
|
+
if (opts.json) {
|
|
7041
|
+
console.log(JSON.stringify({ id, forgotten: true }));
|
|
7042
|
+
return EXIT.SUCCESS;
|
|
7043
|
+
}
|
|
7044
|
+
render.ok(`forgot ${dim(id.slice(0, 8))}`);
|
|
7045
|
+
return EXIT.SUCCESS;
|
|
7046
|
+
}
|
|
7047
|
+
async function runMsgStatus(id, opts) {
|
|
7048
|
+
if (!id) {
|
|
7049
|
+
render.err("Usage: claudemesh msg-status <message-id>");
|
|
7050
|
+
return EXIT.INVALID_ARGS;
|
|
7051
|
+
}
|
|
7052
|
+
return await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
|
|
7053
|
+
const result = await client.messageStatus(id);
|
|
7054
|
+
if (!result) {
|
|
7055
|
+
if (opts.json)
|
|
7056
|
+
console.log(JSON.stringify({ id, found: false }));
|
|
7057
|
+
else
|
|
7058
|
+
render.err(`Message ${id} not found or timed out.`);
|
|
7059
|
+
return EXIT.NOT_FOUND;
|
|
7060
|
+
}
|
|
7061
|
+
if (opts.json) {
|
|
7062
|
+
console.log(JSON.stringify(result, null, 2));
|
|
7063
|
+
return EXIT.SUCCESS;
|
|
7064
|
+
}
|
|
7065
|
+
render.section(`message ${id.slice(0, 12)}…`);
|
|
7066
|
+
render.kv([
|
|
7067
|
+
["target", result.targetSpec],
|
|
7068
|
+
["delivered", result.delivered ? "yes" : "no"],
|
|
7069
|
+
["delivered_at", result.deliveredAt ?? dim("—")]
|
|
7070
|
+
]);
|
|
7071
|
+
if (result.recipients.length > 0) {
|
|
7072
|
+
render.blank();
|
|
7073
|
+
render.heading("recipients");
|
|
7074
|
+
for (const r of result.recipients) {
|
|
7075
|
+
process.stdout.write(` ${bold(r.name)} ${dim(r.pubkey.slice(0, 12) + "…")} ${dim("·")} ${r.status}
|
|
7076
|
+
`);
|
|
7077
|
+
}
|
|
7078
|
+
}
|
|
7079
|
+
return EXIT.SUCCESS;
|
|
7080
|
+
});
|
|
7081
|
+
}
|
|
7082
|
+
async function runClock(opts) {
|
|
7083
|
+
return await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
|
|
7084
|
+
const result = await client.getClock();
|
|
7085
|
+
if (!result) {
|
|
7086
|
+
if (opts.json)
|
|
7087
|
+
console.log(JSON.stringify({ error: "timed out" }));
|
|
7088
|
+
else
|
|
7089
|
+
render.err("Clock query timed out");
|
|
7090
|
+
return EXIT.INTERNAL_ERROR;
|
|
7091
|
+
}
|
|
7092
|
+
if (opts.json) {
|
|
7093
|
+
console.log(JSON.stringify(result, null, 2));
|
|
7094
|
+
return EXIT.SUCCESS;
|
|
7095
|
+
}
|
|
7096
|
+
const statusLabel = result.speed === 0 ? "not started" : result.paused ? "paused" : "running";
|
|
7097
|
+
render.section(`mesh clock — ${statusLabel}`);
|
|
7098
|
+
render.kv([
|
|
7099
|
+
["speed", `x${result.speed}`],
|
|
7100
|
+
["tick", String(result.tick)],
|
|
7101
|
+
["sim_time", result.simTime],
|
|
7102
|
+
["started_at", result.startedAt]
|
|
7103
|
+
]);
|
|
7104
|
+
return EXIT.SUCCESS;
|
|
7105
|
+
});
|
|
7106
|
+
}
|
|
7107
|
+
async function runStats(opts) {
|
|
7108
|
+
return await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
|
|
7109
|
+
const peers = await client.listPeers();
|
|
7110
|
+
if (opts.json) {
|
|
7111
|
+
console.log(JSON.stringify({
|
|
7112
|
+
mesh: client.meshSlug,
|
|
7113
|
+
peers: peers.map((p) => ({ name: p.displayName, pubkey: p.pubkey, stats: p.stats ?? null }))
|
|
7114
|
+
}, null, 2));
|
|
7115
|
+
return EXIT.SUCCESS;
|
|
7116
|
+
}
|
|
7117
|
+
render.section(client.meshSlug);
|
|
7118
|
+
for (const p of peers) {
|
|
7119
|
+
const s = p.stats;
|
|
7120
|
+
if (!s) {
|
|
7121
|
+
process.stdout.write(` ${bold(p.displayName)} ${dim("(no stats)")}
|
|
7122
|
+
`);
|
|
7123
|
+
continue;
|
|
7124
|
+
}
|
|
7125
|
+
const up = s.uptime != null ? `${Math.floor(s.uptime / 60)}m` : "—";
|
|
7126
|
+
process.stdout.write(` ${bold(p.displayName)} ${dim(`in:${s.messagesIn ?? 0} out:${s.messagesOut ?? 0} tools:${s.toolCalls ?? 0} up:${up} err:${s.errors ?? 0}`)}
|
|
7127
|
+
`);
|
|
7128
|
+
}
|
|
7129
|
+
return EXIT.SUCCESS;
|
|
7130
|
+
});
|
|
7131
|
+
}
|
|
7132
|
+
async function runPing(opts) {
|
|
7133
|
+
return await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
|
|
7134
|
+
const peers = await client.listPeers();
|
|
7135
|
+
if (opts.json) {
|
|
7136
|
+
console.log(JSON.stringify({
|
|
7137
|
+
mesh: client.meshSlug,
|
|
7138
|
+
ws_status: client.status,
|
|
7139
|
+
peers_online: peers.length,
|
|
7140
|
+
push_buffer: client.pushHistory.length
|
|
7141
|
+
}, null, 2));
|
|
7142
|
+
return EXIT.SUCCESS;
|
|
7143
|
+
}
|
|
7144
|
+
render.section(`ping ${client.meshSlug}`);
|
|
7145
|
+
render.kv([
|
|
7146
|
+
["ws_status", client.status],
|
|
7147
|
+
["peers_online", String(peers.length)],
|
|
7148
|
+
["push_buffer", String(client.pushHistory.length)]
|
|
7149
|
+
]);
|
|
7150
|
+
return EXIT.SUCCESS;
|
|
7151
|
+
});
|
|
7152
|
+
}
|
|
7153
|
+
async function runTaskClaim(id, opts) {
|
|
7154
|
+
if (!id) {
|
|
7155
|
+
render.err("Usage: claudemesh task claim <id>");
|
|
7156
|
+
return EXIT.INVALID_ARGS;
|
|
7157
|
+
}
|
|
7158
|
+
await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
|
|
7159
|
+
await client.claimTask(id);
|
|
7160
|
+
});
|
|
7161
|
+
if (opts.json) {
|
|
7162
|
+
console.log(JSON.stringify({ id, claimed: true }));
|
|
7163
|
+
return EXIT.SUCCESS;
|
|
7164
|
+
}
|
|
7165
|
+
render.ok(`claimed ${dim(id.slice(0, 8))}`);
|
|
7166
|
+
return EXIT.SUCCESS;
|
|
7167
|
+
}
|
|
7168
|
+
async function runTaskComplete(id, result, opts) {
|
|
7169
|
+
if (!id) {
|
|
7170
|
+
render.err("Usage: claudemesh task complete <id> [result]");
|
|
7171
|
+
return EXIT.INVALID_ARGS;
|
|
7172
|
+
}
|
|
7173
|
+
await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
|
|
7174
|
+
await client.completeTask(id, result);
|
|
7175
|
+
});
|
|
7176
|
+
if (opts.json) {
|
|
7177
|
+
console.log(JSON.stringify({ id, completed: true, result: result ?? null }));
|
|
7178
|
+
return EXIT.SUCCESS;
|
|
7179
|
+
}
|
|
7180
|
+
render.ok(`completed ${dim(id.slice(0, 8))}`, result);
|
|
7181
|
+
return EXIT.SUCCESS;
|
|
7182
|
+
}
|
|
7183
|
+
var init_broker_actions = __esm(() => {
|
|
7184
|
+
init_connect();
|
|
7185
|
+
init_facade();
|
|
7186
|
+
init_client3();
|
|
7187
|
+
init_render();
|
|
7188
|
+
init_styles();
|
|
7189
|
+
init_exit_codes();
|
|
7190
|
+
});
|
|
7191
|
+
|
|
6718
7192
|
// src/commands/remind.ts
|
|
6719
7193
|
var exports_remind = {};
|
|
6720
7194
|
__export(exports_remind, {
|
|
@@ -7021,17 +7495,17 @@ __export(exports_install, {
|
|
|
7021
7495
|
import {
|
|
7022
7496
|
chmodSync as chmodSync3,
|
|
7023
7497
|
copyFileSync,
|
|
7024
|
-
existsSync as
|
|
7498
|
+
existsSync as existsSync6,
|
|
7025
7499
|
mkdirSync as mkdirSync3,
|
|
7026
7500
|
readFileSync as readFileSync4,
|
|
7027
7501
|
writeFileSync as writeFileSync5
|
|
7028
7502
|
} from "node:fs";
|
|
7029
|
-
import { homedir as
|
|
7030
|
-
import { dirname as dirname2, join as
|
|
7503
|
+
import { homedir as homedir5, platform as platform5 } from "node:os";
|
|
7504
|
+
import { dirname as dirname2, join as join5, resolve } from "node:path";
|
|
7031
7505
|
import { fileURLToPath } from "node:url";
|
|
7032
7506
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
7033
7507
|
function readClaudeConfig() {
|
|
7034
|
-
if (!
|
|
7508
|
+
if (!existsSync6(CLAUDE_CONFIG))
|
|
7035
7509
|
return {};
|
|
7036
7510
|
const text = readFileSync4(CLAUDE_CONFIG, "utf-8").trim();
|
|
7037
7511
|
if (!text)
|
|
@@ -7043,12 +7517,12 @@ function readClaudeConfig() {
|
|
|
7043
7517
|
}
|
|
7044
7518
|
}
|
|
7045
7519
|
function backupClaudeConfig() {
|
|
7046
|
-
if (!
|
|
7520
|
+
if (!existsSync6(CLAUDE_CONFIG))
|
|
7047
7521
|
return;
|
|
7048
|
-
const backupDir =
|
|
7522
|
+
const backupDir = join5(dirname2(CLAUDE_CONFIG), ".claude", "backups");
|
|
7049
7523
|
mkdirSync3(backupDir, { recursive: true });
|
|
7050
7524
|
const ts = Date.now();
|
|
7051
|
-
const dest =
|
|
7525
|
+
const dest = join5(backupDir, `.claude.json.pre-claudemesh.${ts}`);
|
|
7052
7526
|
copyFileSync(CLAUDE_CONFIG, dest);
|
|
7053
7527
|
}
|
|
7054
7528
|
function patchMcpServer(entry) {
|
|
@@ -7072,7 +7546,7 @@ function patchMcpServer(entry) {
|
|
|
7072
7546
|
return action;
|
|
7073
7547
|
}
|
|
7074
7548
|
function removeMcpServer() {
|
|
7075
|
-
if (!
|
|
7549
|
+
if (!existsSync6(CLAUDE_CONFIG))
|
|
7076
7550
|
return false;
|
|
7077
7551
|
backupClaudeConfig();
|
|
7078
7552
|
const cfg = readClaudeConfig();
|
|
@@ -7120,7 +7594,7 @@ function entriesEqual(a, b) {
|
|
|
7120
7594
|
return a.command === b.command && JSON.stringify(a.args ?? []) === JSON.stringify(b.args ?? []);
|
|
7121
7595
|
}
|
|
7122
7596
|
function readClaudeSettings() {
|
|
7123
|
-
if (!
|
|
7597
|
+
if (!existsSync6(CLAUDE_SETTINGS))
|
|
7124
7598
|
return {};
|
|
7125
7599
|
const text = readFileSync4(CLAUDE_SETTINGS, "utf-8").trim();
|
|
7126
7600
|
if (!text)
|
|
@@ -7147,7 +7621,7 @@ function installAllowedTools() {
|
|
|
7147
7621
|
return { added: toAdd, unchanged: CLAUDEMESH_TOOLS.length - toAdd.length };
|
|
7148
7622
|
}
|
|
7149
7623
|
function uninstallAllowedTools() {
|
|
7150
|
-
if (!
|
|
7624
|
+
if (!existsSync6(CLAUDE_SETTINGS))
|
|
7151
7625
|
return 0;
|
|
7152
7626
|
const settings = readClaudeSettings();
|
|
7153
7627
|
const existing = settings.allowedTools ?? [];
|
|
@@ -7182,7 +7656,7 @@ function installHooks() {
|
|
|
7182
7656
|
return { added, unchanged };
|
|
7183
7657
|
}
|
|
7184
7658
|
function uninstallHooks() {
|
|
7185
|
-
if (!
|
|
7659
|
+
if (!existsSync6(CLAUDE_SETTINGS))
|
|
7186
7660
|
return 0;
|
|
7187
7661
|
const settings = readClaudeSettings();
|
|
7188
7662
|
const hooks = settings.hooks;
|
|
@@ -7230,7 +7704,7 @@ function runInstall(args = []) {
|
|
|
7230
7704
|
render.err("`bun` is not on PATH.", "Install Bun first: https://bun.com");
|
|
7231
7705
|
process.exit(1);
|
|
7232
7706
|
}
|
|
7233
|
-
if (!
|
|
7707
|
+
if (!existsSync6(entry)) {
|
|
7234
7708
|
render.err(`MCP entry not found at ${entry}`);
|
|
7235
7709
|
process.exit(1);
|
|
7236
7710
|
}
|
|
@@ -7346,8 +7820,8 @@ var init_install = __esm(() => {
|
|
|
7346
7820
|
init_facade();
|
|
7347
7821
|
init_render();
|
|
7348
7822
|
init_styles();
|
|
7349
|
-
CLAUDE_CONFIG =
|
|
7350
|
-
CLAUDE_SETTINGS =
|
|
7823
|
+
CLAUDE_CONFIG = join5(homedir5(), ".claude.json");
|
|
7824
|
+
CLAUDE_SETTINGS = join5(homedir5(), ".claude", "settings.json");
|
|
7351
7825
|
CLAUDEMESH_TOOLS = [
|
|
7352
7826
|
"mcp__claudemesh__cancel_scheduled",
|
|
7353
7827
|
"mcp__claudemesh__check_messages",
|
|
@@ -7402,10 +7876,10 @@ var exports_uninstall = {};
|
|
|
7402
7876
|
__export(exports_uninstall, {
|
|
7403
7877
|
uninstall: () => uninstall
|
|
7404
7878
|
});
|
|
7405
|
-
import { readFileSync as readFileSync5, writeFileSync as writeFileSync6, existsSync as
|
|
7879
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync6, existsSync as existsSync7 } from "node:fs";
|
|
7406
7880
|
async function uninstall() {
|
|
7407
7881
|
let removed = 0;
|
|
7408
|
-
if (
|
|
7882
|
+
if (existsSync7(PATHS.CLAUDE_JSON)) {
|
|
7409
7883
|
try {
|
|
7410
7884
|
const raw = readFileSync5(PATHS.CLAUDE_JSON, "utf-8");
|
|
7411
7885
|
const config = JSON.parse(raw);
|
|
@@ -7419,7 +7893,7 @@ async function uninstall() {
|
|
|
7419
7893
|
}
|
|
7420
7894
|
} catch {}
|
|
7421
7895
|
}
|
|
7422
|
-
if (
|
|
7896
|
+
if (existsSync7(PATHS.CLAUDE_SETTINGS)) {
|
|
7423
7897
|
try {
|
|
7424
7898
|
const raw = readFileSync5(PATHS.CLAUDE_SETTINGS, "utf-8");
|
|
7425
7899
|
const config = JSON.parse(raw);
|
|
@@ -7467,9 +7941,9 @@ var exports_doctor = {};
|
|
|
7467
7941
|
__export(exports_doctor, {
|
|
7468
7942
|
runDoctor: () => runDoctor
|
|
7469
7943
|
});
|
|
7470
|
-
import { existsSync as
|
|
7471
|
-
import { homedir as
|
|
7472
|
-
import { join as
|
|
7944
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6, statSync as statSync2 } from "node:fs";
|
|
7945
|
+
import { homedir as homedir6, platform as platform6 } from "node:os";
|
|
7946
|
+
import { join as join6 } from "node:path";
|
|
7473
7947
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
7474
7948
|
function checkNode() {
|
|
7475
7949
|
const major = Number(process.versions.node.split(".")[0]);
|
|
@@ -7493,8 +7967,8 @@ function checkClaudeOnPath() {
|
|
|
7493
7967
|
};
|
|
7494
7968
|
}
|
|
7495
7969
|
function checkMcpRegistered() {
|
|
7496
|
-
const claudeConfig =
|
|
7497
|
-
if (!
|
|
7970
|
+
const claudeConfig = join6(homedir6(), ".claude.json");
|
|
7971
|
+
if (!existsSync8(claudeConfig)) {
|
|
7498
7972
|
return {
|
|
7499
7973
|
name: "claudemesh MCP registered in ~/.claude.json",
|
|
7500
7974
|
pass: false,
|
|
@@ -7519,8 +7993,8 @@ function checkMcpRegistered() {
|
|
|
7519
7993
|
}
|
|
7520
7994
|
}
|
|
7521
7995
|
function checkHooksRegistered() {
|
|
7522
|
-
const settings =
|
|
7523
|
-
if (!
|
|
7996
|
+
const settings = join6(homedir6(), ".claude", "settings.json");
|
|
7997
|
+
if (!existsSync8(settings)) {
|
|
7524
7998
|
return {
|
|
7525
7999
|
name: "Status hooks registered in ~/.claude/settings.json",
|
|
7526
8000
|
pass: false,
|
|
@@ -7545,7 +8019,7 @@ function checkHooksRegistered() {
|
|
|
7545
8019
|
}
|
|
7546
8020
|
function checkConfigFile() {
|
|
7547
8021
|
const path = getConfigPath();
|
|
7548
|
-
if (!
|
|
8022
|
+
if (!existsSync8(path)) {
|
|
7549
8023
|
return {
|
|
7550
8024
|
name: "~/.claudemesh/config.json exists and parses",
|
|
7551
8025
|
pass: true,
|
|
@@ -7728,7 +8202,7 @@ var exports_status = {};
|
|
|
7728
8202
|
__export(exports_status, {
|
|
7729
8203
|
runStatus: () => runStatus
|
|
7730
8204
|
});
|
|
7731
|
-
import { statSync as statSync3, existsSync as
|
|
8205
|
+
import { statSync as statSync3, existsSync as existsSync9 } from "node:fs";
|
|
7732
8206
|
import WebSocket2 from "ws";
|
|
7733
8207
|
async function probeBroker(url, timeoutMs = 4000) {
|
|
7734
8208
|
return new Promise((resolve2) => {
|
|
@@ -7758,7 +8232,7 @@ async function runStatus() {
|
|
|
7758
8232
|
render.section(`status (v${VERSION})`);
|
|
7759
8233
|
const configPath = getConfigPath();
|
|
7760
8234
|
let configPermsNote = "missing";
|
|
7761
|
-
if (
|
|
8235
|
+
if (existsSync9(configPath)) {
|
|
7762
8236
|
const mode = (statSync3(configPath).mode & 511).toString(8).padStart(4, "0");
|
|
7763
8237
|
configPermsNote = mode === "0600" ? `${mode}` : `${mode} — expected 0600`;
|
|
7764
8238
|
}
|
|
@@ -7904,10 +8378,10 @@ var init_check_claude_binary = __esm(() => {
|
|
|
7904
8378
|
});
|
|
7905
8379
|
|
|
7906
8380
|
// src/services/health/check-mcp-registered.ts
|
|
7907
|
-
import { existsSync as
|
|
8381
|
+
import { existsSync as existsSync10, readFileSync as readFileSync7 } from "node:fs";
|
|
7908
8382
|
function checkMcpRegistered2() {
|
|
7909
8383
|
try {
|
|
7910
|
-
if (!
|
|
8384
|
+
if (!existsSync10(PATHS.CLAUDE_JSON)) {
|
|
7911
8385
|
return { name: "mcp-registered", ok: false, message: "~/.claude.json not found" };
|
|
7912
8386
|
}
|
|
7913
8387
|
const raw = readFileSync7(PATHS.CLAUDE_JSON, "utf-8");
|
|
@@ -7925,10 +8399,10 @@ var init_check_mcp_registered = __esm(() => {
|
|
|
7925
8399
|
});
|
|
7926
8400
|
|
|
7927
8401
|
// src/services/health/check-hooks-registered.ts
|
|
7928
|
-
import { existsSync as
|
|
8402
|
+
import { existsSync as existsSync11, readFileSync as readFileSync8 } from "node:fs";
|
|
7929
8403
|
function checkHooksRegistered2() {
|
|
7930
8404
|
try {
|
|
7931
|
-
if (!
|
|
8405
|
+
if (!existsSync11(PATHS.CLAUDE_SETTINGS)) {
|
|
7932
8406
|
return { name: "hooks-registered", ok: false, message: "~/.claude/settings.json not found" };
|
|
7933
8407
|
}
|
|
7934
8408
|
const raw = readFileSync8(PATHS.CLAUDE_SETTINGS, "utf-8");
|
|
@@ -7946,10 +8420,10 @@ var init_check_hooks_registered = __esm(() => {
|
|
|
7946
8420
|
});
|
|
7947
8421
|
|
|
7948
8422
|
// src/services/health/check-config-perms.ts
|
|
7949
|
-
import { existsSync as
|
|
8423
|
+
import { existsSync as existsSync12, statSync as statSync4 } from "node:fs";
|
|
7950
8424
|
function checkConfigPerms() {
|
|
7951
8425
|
const configFile = PATHS.CONFIG_FILE;
|
|
7952
|
-
if (!
|
|
8426
|
+
if (!existsSync12(configFile)) {
|
|
7953
8427
|
return { name: "config-perms", ok: true, message: "No config file yet (first run)" };
|
|
7954
8428
|
}
|
|
7955
8429
|
try {
|
|
@@ -7967,9 +8441,9 @@ var init_check_config_perms = __esm(() => {
|
|
|
7967
8441
|
});
|
|
7968
8442
|
|
|
7969
8443
|
// src/services/health/check-keypairs-valid.ts
|
|
7970
|
-
import { existsSync as
|
|
8444
|
+
import { existsSync as existsSync13, readFileSync as readFileSync9 } from "node:fs";
|
|
7971
8445
|
function checkKeypairsValid() {
|
|
7972
|
-
if (!
|
|
8446
|
+
if (!existsSync13(PATHS.CONFIG_FILE)) {
|
|
7973
8447
|
return { name: "keypairs-valid", ok: true, message: "No config (first run)" };
|
|
7974
8448
|
}
|
|
7975
8449
|
try {
|
|
@@ -8453,18 +8927,18 @@ var exports_url_handler = {};
|
|
|
8453
8927
|
__export(exports_url_handler, {
|
|
8454
8928
|
runUrlHandler: () => runUrlHandler
|
|
8455
8929
|
});
|
|
8456
|
-
import { platform as platform7, homedir as
|
|
8457
|
-
import { existsSync as
|
|
8458
|
-
import { join as
|
|
8930
|
+
import { platform as platform7, homedir as homedir7 } from "node:os";
|
|
8931
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync4, writeFileSync as writeFileSync7, rmSync as rmSync2, chmodSync as chmodSync4 } from "node:fs";
|
|
8932
|
+
import { join as join7 } from "node:path";
|
|
8459
8933
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
8460
8934
|
function resolveClaudemeshBin() {
|
|
8461
8935
|
return process.argv[1] ?? "claudemesh";
|
|
8462
8936
|
}
|
|
8463
8937
|
function installDarwin() {
|
|
8464
8938
|
const binPath = resolveClaudemeshBin();
|
|
8465
|
-
const appDir =
|
|
8466
|
-
const contents =
|
|
8467
|
-
const macOS =
|
|
8939
|
+
const appDir = join7(homedir7(), "Library", "Application Support", "claudemesh", "ClaudemeshHandler.app");
|
|
8940
|
+
const contents = join7(appDir, "Contents");
|
|
8941
|
+
const macOS = join7(contents, "MacOS");
|
|
8468
8942
|
mkdirSync4(macOS, { recursive: true });
|
|
8469
8943
|
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
8470
8944
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
@@ -8488,7 +8962,7 @@ function installDarwin() {
|
|
|
8488
8962
|
</array>
|
|
8489
8963
|
</dict>
|
|
8490
8964
|
</plist>`;
|
|
8491
|
-
writeFileSync7(
|
|
8965
|
+
writeFileSync7(join7(contents, "Info.plist"), plist);
|
|
8492
8966
|
const shim = `#!/bin/sh
|
|
8493
8967
|
URL="$1"
|
|
8494
8968
|
CODE=\${URL#claudemesh://}
|
|
@@ -8502,7 +8976,7 @@ tell application "Terminal"
|
|
|
8502
8976
|
end tell
|
|
8503
8977
|
EOF
|
|
8504
8978
|
`;
|
|
8505
|
-
const shimPath =
|
|
8979
|
+
const shimPath = join7(macOS, "open-url");
|
|
8506
8980
|
writeFileSync7(shimPath, shim);
|
|
8507
8981
|
chmodSync4(shimPath, 493);
|
|
8508
8982
|
const lsreg = spawnSync5("/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister", ["-f", appDir], { encoding: "utf-8" });
|
|
@@ -8514,7 +8988,7 @@ EOF
|
|
|
8514
8988
|
}
|
|
8515
8989
|
function installLinux() {
|
|
8516
8990
|
const binPath = resolveClaudemeshBin();
|
|
8517
|
-
const appsDir =
|
|
8991
|
+
const appsDir = join7(homedir7(), ".local", "share", "applications");
|
|
8518
8992
|
mkdirSync4(appsDir, { recursive: true });
|
|
8519
8993
|
const desktop = `[Desktop Entry]
|
|
8520
8994
|
Type=Application
|
|
@@ -8526,7 +9000,7 @@ Terminal=true
|
|
|
8526
9000
|
MimeType=x-scheme-handler/claudemesh;
|
|
8527
9001
|
NoDisplay=true
|
|
8528
9002
|
`;
|
|
8529
|
-
const desktopPath =
|
|
9003
|
+
const desktopPath = join7(appsDir, "claudemesh.desktop");
|
|
8530
9004
|
writeFileSync7(desktopPath, desktop);
|
|
8531
9005
|
const xdg1 = spawnSync5("xdg-mime", ["default", "claudemesh.desktop", "x-scheme-handler/claudemesh"], { encoding: "utf-8" });
|
|
8532
9006
|
if (xdg1.status !== 0) {
|
|
@@ -8549,7 +9023,7 @@ function installWindows() {
|
|
|
8549
9023
|
`[HKEY_CURRENT_USER\\Software\\Classes\\claudemesh\\shell\\open\\command]`,
|
|
8550
9024
|
`@="\\"${binPath.replace(/\\/g, "\\\\")}\\" \\"%1\\""`
|
|
8551
9025
|
];
|
|
8552
|
-
const regPath =
|
|
9026
|
+
const regPath = join7(homedir7(), "claudemesh-handler.reg");
|
|
8553
9027
|
writeFileSync7(regPath, lines.join(`\r
|
|
8554
9028
|
`));
|
|
8555
9029
|
const res = spawnSync5("reg.exe", ["import", regPath], { encoding: "utf-8" });
|
|
@@ -8561,15 +9035,15 @@ function installWindows() {
|
|
|
8561
9035
|
return EXIT.SUCCESS;
|
|
8562
9036
|
}
|
|
8563
9037
|
function uninstallDarwin() {
|
|
8564
|
-
const appDir =
|
|
8565
|
-
if (
|
|
9038
|
+
const appDir = join7(homedir7(), "Library", "Application Support", "claudemesh", "ClaudemeshHandler.app");
|
|
9039
|
+
if (existsSync14(appDir))
|
|
8566
9040
|
rmSync2(appDir, { recursive: true, force: true });
|
|
8567
9041
|
render.ok("removed claudemesh:// handler on macOS");
|
|
8568
9042
|
return EXIT.SUCCESS;
|
|
8569
9043
|
}
|
|
8570
9044
|
function uninstallLinux() {
|
|
8571
|
-
const desktopPath =
|
|
8572
|
-
if (
|
|
9045
|
+
const desktopPath = join7(homedir7(), ".local", "share", "applications", "claudemesh.desktop");
|
|
9046
|
+
if (existsSync14(desktopPath))
|
|
8573
9047
|
rmSync2(desktopPath, { force: true });
|
|
8574
9048
|
render.ok("removed claudemesh:// handler on Linux");
|
|
8575
9049
|
return EXIT.SUCCESS;
|
|
@@ -8614,9 +9088,9 @@ var exports_status_line = {};
|
|
|
8614
9088
|
__export(exports_status_line, {
|
|
8615
9089
|
runStatusLine: () => runStatusLine
|
|
8616
9090
|
});
|
|
8617
|
-
import { existsSync as
|
|
8618
|
-
import { join as
|
|
8619
|
-
import { homedir as
|
|
9091
|
+
import { existsSync as existsSync15, readFileSync as readFileSync10 } from "node:fs";
|
|
9092
|
+
import { join as join8 } from "node:path";
|
|
9093
|
+
import { homedir as homedir8 } from "node:os";
|
|
8620
9094
|
async function runStatusLine() {
|
|
8621
9095
|
try {
|
|
8622
9096
|
const config = readConfig();
|
|
@@ -8624,9 +9098,9 @@ async function runStatusLine() {
|
|
|
8624
9098
|
process.stdout.write("◇ claudemesh (not joined)");
|
|
8625
9099
|
return EXIT.SUCCESS;
|
|
8626
9100
|
}
|
|
8627
|
-
const cachePath =
|
|
9101
|
+
const cachePath = join8(homedir8(), ".claudemesh", "peer-cache.json");
|
|
8628
9102
|
let cache = {};
|
|
8629
|
-
if (
|
|
9103
|
+
if (existsSync15(cachePath)) {
|
|
8630
9104
|
try {
|
|
8631
9105
|
cache = JSON.parse(readFileSync10(cachePath, "utf-8"));
|
|
8632
9106
|
} catch {}
|
|
@@ -8659,7 +9133,7 @@ __export(exports_backup, {
|
|
|
8659
9133
|
runRestore: () => runRestore,
|
|
8660
9134
|
runBackup: () => runBackup
|
|
8661
9135
|
});
|
|
8662
|
-
import { readFileSync as readFileSync11, writeFileSync as writeFileSync8, existsSync as
|
|
9136
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync8, existsSync as existsSync16 } from "node:fs";
|
|
8663
9137
|
import { createInterface as createInterface10 } from "node:readline";
|
|
8664
9138
|
function readHidden(prompt5) {
|
|
8665
9139
|
return new Promise((resolve2) => {
|
|
@@ -8701,7 +9175,7 @@ async function deriveKey(pass, salt, s) {
|
|
|
8701
9175
|
}
|
|
8702
9176
|
async function runBackup(outPath) {
|
|
8703
9177
|
const configPath = getConfigPath();
|
|
8704
|
-
if (!
|
|
9178
|
+
if (!existsSync16(configPath)) {
|
|
8705
9179
|
console.error(" No config found — nothing to back up. Join a mesh first.");
|
|
8706
9180
|
return EXIT.NOT_FOUND;
|
|
8707
9181
|
}
|
|
@@ -8735,7 +9209,7 @@ async function runRestore(inPath) {
|
|
|
8735
9209
|
console.error(" Usage: claudemesh restore <backup-file>");
|
|
8736
9210
|
return EXIT.INVALID_ARGS;
|
|
8737
9211
|
}
|
|
8738
|
-
if (!
|
|
9212
|
+
if (!existsSync16(inPath)) {
|
|
8739
9213
|
console.error(` ✗ File not found: ${inPath}`);
|
|
8740
9214
|
return EXIT.NOT_FOUND;
|
|
8741
9215
|
}
|
|
@@ -8758,7 +9232,7 @@ async function runRestore(inPath) {
|
|
|
8758
9232
|
return EXIT.INTERNAL_ERROR;
|
|
8759
9233
|
}
|
|
8760
9234
|
const configPath = getConfigPath();
|
|
8761
|
-
if (
|
|
9235
|
+
if (existsSync16(configPath)) {
|
|
8762
9236
|
const backupOld = `${configPath}.before-restore.${Date.now()}`;
|
|
8763
9237
|
writeFileSync8(backupOld, readFileSync11(configPath), { mode: 384 });
|
|
8764
9238
|
console.log(` ↻ Existing config saved to ${backupOld}`);
|
|
@@ -8783,8 +9257,8 @@ __export(exports_upgrade, {
|
|
|
8783
9257
|
runUpgrade: () => runUpgrade
|
|
8784
9258
|
});
|
|
8785
9259
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
8786
|
-
import { existsSync as
|
|
8787
|
-
import { dirname as dirname3, join as
|
|
9260
|
+
import { existsSync as existsSync17 } from "node:fs";
|
|
9261
|
+
import { dirname as dirname3, join as join9, resolve as resolve2 } from "node:path";
|
|
8788
9262
|
async function latestVersion() {
|
|
8789
9263
|
try {
|
|
8790
9264
|
const res = await fetch(URLS.NPM_REGISTRY, { signal: AbortSignal.timeout(8000) });
|
|
@@ -8797,15 +9271,15 @@ async function latestVersion() {
|
|
|
8797
9271
|
}
|
|
8798
9272
|
}
|
|
8799
9273
|
function findNpm() {
|
|
8800
|
-
const portable =
|
|
8801
|
-
if (
|
|
8802
|
-
return { npm: portable, prefix:
|
|
9274
|
+
const portable = join9(process.env.HOME ?? "", ".claudemesh", "node", "bin", "npm");
|
|
9275
|
+
if (existsSync17(portable)) {
|
|
9276
|
+
return { npm: portable, prefix: join9(process.env.HOME ?? "", ".claudemesh") };
|
|
8803
9277
|
}
|
|
8804
9278
|
let cur = resolve2(process.argv[1] ?? ".");
|
|
8805
9279
|
for (let i = 0;i < 6; i++) {
|
|
8806
9280
|
cur = dirname3(cur);
|
|
8807
|
-
const candidate =
|
|
8808
|
-
if (
|
|
9281
|
+
const candidate = join9(cur, "bin", "npm");
|
|
9282
|
+
if (existsSync17(candidate))
|
|
8809
9283
|
return { npm: candidate };
|
|
8810
9284
|
}
|
|
8811
9285
|
return { npm: "npm" };
|
|
@@ -8867,9 +9341,9 @@ __export(exports_grants, {
|
|
|
8867
9341
|
runBlock: () => runBlock,
|
|
8868
9342
|
isAllowed: () => isAllowed
|
|
8869
9343
|
});
|
|
8870
|
-
import { existsSync as
|
|
8871
|
-
import { homedir as
|
|
8872
|
-
import { join as
|
|
9344
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync5, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "node:fs";
|
|
9345
|
+
import { homedir as homedir9 } from "node:os";
|
|
9346
|
+
import { join as join10 } from "node:path";
|
|
8873
9347
|
async function syncToBroker(meshSlug, grants) {
|
|
8874
9348
|
const auth = getStoredToken();
|
|
8875
9349
|
if (!auth)
|
|
@@ -8887,7 +9361,7 @@ async function syncToBroker(meshSlug, grants) {
|
|
|
8887
9361
|
}
|
|
8888
9362
|
}
|
|
8889
9363
|
function readGrants() {
|
|
8890
|
-
if (!
|
|
9364
|
+
if (!existsSync18(GRANT_FILE))
|
|
8891
9365
|
return {};
|
|
8892
9366
|
try {
|
|
8893
9367
|
return JSON.parse(readFileSync12(GRANT_FILE, "utf-8"));
|
|
@@ -8896,8 +9370,8 @@ function readGrants() {
|
|
|
8896
9370
|
}
|
|
8897
9371
|
}
|
|
8898
9372
|
function writeGrants(g) {
|
|
8899
|
-
const dir =
|
|
8900
|
-
if (!
|
|
9373
|
+
const dir = join10(homedir9(), ".claudemesh");
|
|
9374
|
+
if (!existsSync18(dir))
|
|
8901
9375
|
mkdirSync5(dir, { recursive: true });
|
|
8902
9376
|
writeFileSync9(GRANT_FILE, JSON.stringify(g, null, 2), { mode: 384 });
|
|
8903
9377
|
}
|
|
@@ -9055,7 +9529,7 @@ var init_grants = __esm(() => {
|
|
|
9055
9529
|
BROKER_HTTP7 = URLS.BROKER.replace("wss://", "https://").replace("ws://", "http://").replace("/ws", "");
|
|
9056
9530
|
ALL_CAPS = ["read", "dm", "broadcast", "state-read", "state-write", "file-read"];
|
|
9057
9531
|
DEFAULT_CAPS = ["read", "dm", "broadcast", "state-read"];
|
|
9058
|
-
GRANT_FILE =
|
|
9532
|
+
GRANT_FILE = join10(homedir9(), ".claudemesh", "grants.json");
|
|
9059
9533
|
});
|
|
9060
9534
|
|
|
9061
9535
|
// src/mcp/tools/definitions.ts
|
|
@@ -9981,6 +10455,165 @@ var init_definitions = __esm(() => {
|
|
|
9981
10455
|
];
|
|
9982
10456
|
});
|
|
9983
10457
|
|
|
10458
|
+
// src/services/bridge/server.ts
|
|
10459
|
+
import { createServer as createServer2 } from "node:net";
|
|
10460
|
+
import { mkdirSync as mkdirSync6, unlinkSync as unlinkSync2, existsSync as existsSync19, chmodSync as chmodSync5 } from "node:fs";
|
|
10461
|
+
async function resolveTarget2(client, to) {
|
|
10462
|
+
if (to.startsWith("@") || to === "*" || /^[0-9a-f]{64}$/i.test(to)) {
|
|
10463
|
+
return { ok: true, spec: to };
|
|
10464
|
+
}
|
|
10465
|
+
const peers = await client.listPeers();
|
|
10466
|
+
const match = peers.find((p) => p.displayName.toLowerCase() === to.toLowerCase());
|
|
10467
|
+
if (!match) {
|
|
10468
|
+
return {
|
|
10469
|
+
ok: false,
|
|
10470
|
+
error: `peer "${to}" not found. online: ${peers.map((p) => p.displayName).join(", ") || "(none)"}`
|
|
10471
|
+
};
|
|
10472
|
+
}
|
|
10473
|
+
return { ok: true, spec: match.pubkey };
|
|
10474
|
+
}
|
|
10475
|
+
async function dispatch(client, req) {
|
|
10476
|
+
const args = req.args ?? {};
|
|
10477
|
+
try {
|
|
10478
|
+
switch (req.verb) {
|
|
10479
|
+
case "ping": {
|
|
10480
|
+
const peers = await client.listPeers();
|
|
10481
|
+
return {
|
|
10482
|
+
id: req.id,
|
|
10483
|
+
ok: true,
|
|
10484
|
+
result: {
|
|
10485
|
+
mesh: client.meshSlug,
|
|
10486
|
+
ws_status: client.status,
|
|
10487
|
+
peers_online: peers.length,
|
|
10488
|
+
push_buffer: client.pushHistory.length
|
|
10489
|
+
}
|
|
10490
|
+
};
|
|
10491
|
+
}
|
|
10492
|
+
case "peers": {
|
|
10493
|
+
const peers = await client.listPeers();
|
|
10494
|
+
return { id: req.id, ok: true, result: peers };
|
|
10495
|
+
}
|
|
10496
|
+
case "send": {
|
|
10497
|
+
const to = String(args.to ?? "");
|
|
10498
|
+
const message = String(args.message ?? "");
|
|
10499
|
+
const priority = args.priority ?? "next";
|
|
10500
|
+
if (!to || !message) {
|
|
10501
|
+
return { id: req.id, ok: false, error: "send: `to` and `message` required" };
|
|
10502
|
+
}
|
|
10503
|
+
const resolved = await resolveTarget2(client, to);
|
|
10504
|
+
if (!resolved.ok)
|
|
10505
|
+
return { id: req.id, ok: false, error: resolved.error };
|
|
10506
|
+
const result = await client.send(resolved.spec, message, priority);
|
|
10507
|
+
if (!result.ok) {
|
|
10508
|
+
return { id: req.id, ok: false, error: result.error ?? "send failed" };
|
|
10509
|
+
}
|
|
10510
|
+
return {
|
|
10511
|
+
id: req.id,
|
|
10512
|
+
ok: true,
|
|
10513
|
+
result: { messageId: result.messageId, target: resolved.spec }
|
|
10514
|
+
};
|
|
10515
|
+
}
|
|
10516
|
+
case "summary": {
|
|
10517
|
+
const text = String(args.summary ?? "");
|
|
10518
|
+
if (!text)
|
|
10519
|
+
return { id: req.id, ok: false, error: "summary: `summary` required" };
|
|
10520
|
+
await client.setSummary(text);
|
|
10521
|
+
return { id: req.id, ok: true, result: { summary: text } };
|
|
10522
|
+
}
|
|
10523
|
+
case "status_set": {
|
|
10524
|
+
const state = String(args.status ?? "");
|
|
10525
|
+
if (!["idle", "working", "dnd"].includes(state)) {
|
|
10526
|
+
return { id: req.id, ok: false, error: "status_set: must be idle | working | dnd" };
|
|
10527
|
+
}
|
|
10528
|
+
await client.setStatus(state);
|
|
10529
|
+
return { id: req.id, ok: true, result: { status: state } };
|
|
10530
|
+
}
|
|
10531
|
+
case "visible": {
|
|
10532
|
+
const visible = Boolean(args.visible);
|
|
10533
|
+
await client.setVisible(visible);
|
|
10534
|
+
return { id: req.id, ok: true, result: { visible } };
|
|
10535
|
+
}
|
|
10536
|
+
default:
|
|
10537
|
+
return { id: req.id, ok: false, error: `unknown verb: ${req.verb}` };
|
|
10538
|
+
}
|
|
10539
|
+
} catch (err) {
|
|
10540
|
+
return {
|
|
10541
|
+
id: req.id,
|
|
10542
|
+
ok: false,
|
|
10543
|
+
error: err instanceof Error ? err.message : String(err)
|
|
10544
|
+
};
|
|
10545
|
+
}
|
|
10546
|
+
}
|
|
10547
|
+
function handleConnection(socket, client) {
|
|
10548
|
+
const parser = new LineParser;
|
|
10549
|
+
socket.on("data", (chunk) => {
|
|
10550
|
+
const lines = parser.feed(chunk);
|
|
10551
|
+
for (const line of lines) {
|
|
10552
|
+
if (!line.trim())
|
|
10553
|
+
continue;
|
|
10554
|
+
let req;
|
|
10555
|
+
try {
|
|
10556
|
+
req = JSON.parse(line);
|
|
10557
|
+
} catch {
|
|
10558
|
+
continue;
|
|
10559
|
+
}
|
|
10560
|
+
if (!req || typeof req !== "object" || !req.id || !req.verb)
|
|
10561
|
+
continue;
|
|
10562
|
+
dispatch(client, req).then((res) => {
|
|
10563
|
+
try {
|
|
10564
|
+
socket.write(frame(res));
|
|
10565
|
+
} catch {}
|
|
10566
|
+
});
|
|
10567
|
+
}
|
|
10568
|
+
});
|
|
10569
|
+
socket.on("error", () => {});
|
|
10570
|
+
}
|
|
10571
|
+
function startBridgeServer(client) {
|
|
10572
|
+
const path = socketPath(client.meshSlug);
|
|
10573
|
+
const dir = socketDir();
|
|
10574
|
+
if (!existsSync19(dir)) {
|
|
10575
|
+
mkdirSync6(dir, { recursive: true, mode: 448 });
|
|
10576
|
+
}
|
|
10577
|
+
if (existsSync19(path)) {
|
|
10578
|
+
try {
|
|
10579
|
+
unlinkSync2(path);
|
|
10580
|
+
} catch {}
|
|
10581
|
+
}
|
|
10582
|
+
const server = createServer2((socket) => handleConnection(socket, client));
|
|
10583
|
+
try {
|
|
10584
|
+
server.listen(path);
|
|
10585
|
+
} catch (err) {
|
|
10586
|
+
process.stderr.write(`[claudemesh] bridge: failed to bind ${path}: ${String(err)}
|
|
10587
|
+
`);
|
|
10588
|
+
return null;
|
|
10589
|
+
}
|
|
10590
|
+
server.on("error", (err) => {
|
|
10591
|
+
process.stderr.write(`[claudemesh] bridge: ${String(err)}
|
|
10592
|
+
`);
|
|
10593
|
+
});
|
|
10594
|
+
try {
|
|
10595
|
+
chmodSync5(path, 384);
|
|
10596
|
+
} catch {}
|
|
10597
|
+
let stopped = false;
|
|
10598
|
+
return {
|
|
10599
|
+
path,
|
|
10600
|
+
stop() {
|
|
10601
|
+
if (stopped)
|
|
10602
|
+
return;
|
|
10603
|
+
stopped = true;
|
|
10604
|
+
try {
|
|
10605
|
+
server.close();
|
|
10606
|
+
} catch {}
|
|
10607
|
+
try {
|
|
10608
|
+
unlinkSync2(path);
|
|
10609
|
+
} catch {}
|
|
10610
|
+
}
|
|
10611
|
+
};
|
|
10612
|
+
}
|
|
10613
|
+
var init_server = __esm(() => {
|
|
10614
|
+
init_protocol();
|
|
10615
|
+
});
|
|
10616
|
+
|
|
9984
10617
|
// src/mcp/server.ts
|
|
9985
10618
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
9986
10619
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -10163,6 +10796,16 @@ function formatPush(p, meshSlug) {
|
|
|
10163
10796
|
return `[${meshSlug}]${tag} from ${p.senderPubkey.slice(0, 12)}… (${p.priority}, ${p.createdAt}):
|
|
10164
10797
|
${body}`;
|
|
10165
10798
|
}
|
|
10799
|
+
function maybeWarnDeprecated(toolName) {
|
|
10800
|
+
const hint = DEPRECATED_TOOL_HINTS[toolName];
|
|
10801
|
+
if (!hint)
|
|
10802
|
+
return;
|
|
10803
|
+
if (warnedTools.has(toolName))
|
|
10804
|
+
return;
|
|
10805
|
+
warnedTools.add(toolName);
|
|
10806
|
+
process.stderr.write(`[claudemesh] mcp tool "${toolName}" is soft-deprecated in 1.1.0 ` + `and will be removed in 2.0.0. Use \`${hint}\` instead.
|
|
10807
|
+
`);
|
|
10808
|
+
}
|
|
10166
10809
|
async function startMcpServer() {
|
|
10167
10810
|
const serviceIdx = process.argv.indexOf("--service");
|
|
10168
10811
|
if (serviceIdx !== -1 && process.argv[serviceIdx + 1]) {
|
|
@@ -10458,6 +11101,7 @@ ${manifest.allowed_tools.map((t) => ` - ${t}`).join(`
|
|
|
10458
11101
|
if (config.meshes.length === 0) {
|
|
10459
11102
|
return text("No meshes joined. Run `claudemesh join https://claudemesh.com/join/<token>` first.", true);
|
|
10460
11103
|
}
|
|
11104
|
+
maybeWarnDeprecated(name);
|
|
10461
11105
|
switch (name) {
|
|
10462
11106
|
case "send_message": {
|
|
10463
11107
|
const { to, message, priority } = args ?? {};
|
|
@@ -10535,12 +11179,12 @@ ${peerLines.join(`
|
|
|
10535
11179
|
}
|
|
10536
11180
|
}
|
|
10537
11181
|
try {
|
|
10538
|
-
const { writeFileSync: writeFileSync10, mkdirSync:
|
|
11182
|
+
const { writeFileSync: writeFileSync10, mkdirSync: mkdirSync7, existsSync: existsSync20 } = await import("node:fs");
|
|
10539
11183
|
const { join: joinPath } = await import("node:path");
|
|
10540
|
-
const { homedir:
|
|
10541
|
-
const dir = joinPath(
|
|
10542
|
-
if (!
|
|
10543
|
-
|
|
11184
|
+
const { homedir: homedir10 } = await import("node:os");
|
|
11185
|
+
const dir = joinPath(homedir10(), ".claudemesh");
|
|
11186
|
+
if (!existsSync20(dir))
|
|
11187
|
+
mkdirSync7(dir, { recursive: true });
|
|
10544
11188
|
writeFileSync10(joinPath(dir, "peer-cache.json"), JSON.stringify(statusCache));
|
|
10545
11189
|
} catch {}
|
|
10546
11190
|
return text(sections.join(`
|
|
@@ -10783,17 +11427,17 @@ ${lines.join(`
|
|
|
10783
11427
|
const { path: filePath, name: fileName, tags, to: fileTo } = args ?? {};
|
|
10784
11428
|
if (!filePath)
|
|
10785
11429
|
return text("share_file: `path` required", true);
|
|
10786
|
-
const { existsSync:
|
|
10787
|
-
if (!
|
|
11430
|
+
const { existsSync: existsSync20 } = await import("node:fs");
|
|
11431
|
+
if (!existsSync20(filePath))
|
|
10788
11432
|
return text(`share_file: file not found: ${filePath}`, true);
|
|
10789
11433
|
const client = allClients()[0];
|
|
10790
11434
|
if (!client)
|
|
10791
11435
|
return text("share_file: not connected", true);
|
|
10792
11436
|
if (fileTo) {
|
|
10793
11437
|
const { encryptFile: encryptFile2, sealKeyForPeer: sealKeyForPeer2 } = await Promise.resolve().then(() => (init_file_crypto(), exports_file_crypto));
|
|
10794
|
-
const { readFileSync: readFileSync13, writeFileSync: writeFileSync10, mkdtempSync: mkdtempSync2, unlinkSync:
|
|
11438
|
+
const { readFileSync: readFileSync13, writeFileSync: writeFileSync10, mkdtempSync: mkdtempSync2, unlinkSync: unlinkSync3, rmdirSync } = await import("node:fs");
|
|
10795
11439
|
const { tmpdir: tmpdir2 } = await import("node:os");
|
|
10796
|
-
const { join:
|
|
11440
|
+
const { join: join11, basename } = await import("node:path");
|
|
10797
11441
|
const peers = await client.listPeers();
|
|
10798
11442
|
const targetPeer = peers.find((p) => p.pubkey === fileTo || p.displayName === fileTo);
|
|
10799
11443
|
if (!targetPeer) {
|
|
@@ -10816,8 +11460,8 @@ ${lines.join(`
|
|
|
10816
11460
|
combined.set(ciphertext, nonceBytes.length);
|
|
10817
11461
|
const rawName = fileName ?? basename(filePath);
|
|
10818
11462
|
const baseName = basename(rawName).replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 255);
|
|
10819
|
-
const tmpDir = mkdtempSync2(
|
|
10820
|
-
const tmpPath =
|
|
11463
|
+
const tmpDir = mkdtempSync2(join11(tmpdir2(), "cm-"));
|
|
11464
|
+
const tmpPath = join11(tmpDir, baseName);
|
|
10821
11465
|
writeFileSync10(tmpPath, combined);
|
|
10822
11466
|
try {
|
|
10823
11467
|
const fileId = await client.uploadFile(tmpPath, client.meshId, client.meshSlug, {
|
|
@@ -10833,7 +11477,7 @@ ${lines.join(`
|
|
|
10833
11477
|
return text(`share_file: upload failed — ${e instanceof Error ? e.message : String(e)}`, true);
|
|
10834
11478
|
} finally {
|
|
10835
11479
|
try {
|
|
10836
|
-
|
|
11480
|
+
unlinkSync3(tmpPath);
|
|
10837
11481
|
} catch {}
|
|
10838
11482
|
try {
|
|
10839
11483
|
rmdirSync(tmpDir);
|
|
@@ -10893,9 +11537,9 @@ ${lines.join(`
|
|
|
10893
11537
|
const plaintext = await decryptFile2(ciphertext, nonce, kf);
|
|
10894
11538
|
if (!plaintext)
|
|
10895
11539
|
return text(genericErr, true);
|
|
10896
|
-
const { writeFileSync: writeFileSync11, mkdirSync:
|
|
11540
|
+
const { writeFileSync: writeFileSync11, mkdirSync: mkdirSync8 } = await import("node:fs");
|
|
10897
11541
|
const { dirname: dirname5 } = await import("node:path");
|
|
10898
|
-
|
|
11542
|
+
mkdirSync8(dirname5(save_to), { recursive: true });
|
|
10899
11543
|
writeFileSync11(save_to, plaintext);
|
|
10900
11544
|
return text(`Downloaded and decrypted: ${result.name} → ${save_to}`);
|
|
10901
11545
|
}
|
|
@@ -10906,9 +11550,9 @@ ${lines.join(`
|
|
|
10906
11550
|
}
|
|
10907
11551
|
if (!res.ok)
|
|
10908
11552
|
return text(`get_file: download failed (${res.status})`, true);
|
|
10909
|
-
const { writeFileSync: writeFileSync10, mkdirSync:
|
|
11553
|
+
const { writeFileSync: writeFileSync10, mkdirSync: mkdirSync7 } = await import("node:fs");
|
|
10910
11554
|
const { dirname: dirname4 } = await import("node:path");
|
|
10911
|
-
|
|
11555
|
+
mkdirSync7(dirname4(save_to), { recursive: true });
|
|
10912
11556
|
writeFileSync10(save_to, Buffer.from(await res.arrayBuffer()));
|
|
10913
11557
|
return text(`Downloaded: ${result.name} → ${save_to}`);
|
|
10914
11558
|
}
|
|
@@ -11667,8 +12311,8 @@ ${lines.join(`
|
|
|
11667
12311
|
const entryType = vType ?? "env";
|
|
11668
12312
|
let plaintextBytes;
|
|
11669
12313
|
if (entryType === "file") {
|
|
11670
|
-
const { existsSync:
|
|
11671
|
-
if (!
|
|
12314
|
+
const { existsSync: existsSync20, readFileSync: readFileSync13 } = await import("node:fs");
|
|
12315
|
+
if (!existsSync20(value))
|
|
11672
12316
|
return text(`vault_set: file not found: ${value}`, true);
|
|
11673
12317
|
plaintextBytes = new Uint8Array(readFileSync13(value));
|
|
11674
12318
|
} else {
|
|
@@ -11927,8 +12571,14 @@ ${lines.join(`
|
|
|
11927
12571
|
});
|
|
11928
12572
|
const transport = new StdioServerTransport;
|
|
11929
12573
|
await server.connect(transport);
|
|
12574
|
+
const bridges = [];
|
|
11930
12575
|
startClients(config).then(() => {
|
|
11931
12576
|
wirePushHandlers().catch(() => {});
|
|
12577
|
+
for (const client of allClients()) {
|
|
12578
|
+
const bridge = startBridgeServer(client);
|
|
12579
|
+
if (bridge)
|
|
12580
|
+
bridges.push(bridge);
|
|
12581
|
+
}
|
|
11932
12582
|
}).catch(() => {
|
|
11933
12583
|
wirePushHandlers().catch(() => {});
|
|
11934
12584
|
});
|
|
@@ -12101,6 +12751,11 @@ ${lines.join(`
|
|
|
12101
12751
|
const keepalive = setInterval(() => {}, 1000);
|
|
12102
12752
|
const shutdown = () => {
|
|
12103
12753
|
clearInterval(keepalive);
|
|
12754
|
+
for (const b of bridges) {
|
|
12755
|
+
try {
|
|
12756
|
+
b.stop();
|
|
12757
|
+
} catch {}
|
|
12758
|
+
}
|
|
12104
12759
|
stopAll();
|
|
12105
12760
|
process.exit(0);
|
|
12106
12761
|
};
|
|
@@ -12221,12 +12876,41 @@ async function startServiceProxy(serviceName) {
|
|
|
12221
12876
|
process.on("SIGTERM", shutdown);
|
|
12222
12877
|
process.on("SIGINT", shutdown);
|
|
12223
12878
|
}
|
|
12224
|
-
var peerNameCache, peerNameCacheAge = 0, CACHE_TTL_MS = 30000;
|
|
12225
|
-
var
|
|
12879
|
+
var peerNameCache, peerNameCacheAge = 0, CACHE_TTL_MS = 30000, DEPRECATED_TOOL_HINTS, warnedTools;
|
|
12880
|
+
var init_server2 = __esm(() => {
|
|
12226
12881
|
init_definitions();
|
|
12227
12882
|
init_facade();
|
|
12228
12883
|
init_facade8();
|
|
12884
|
+
init_server();
|
|
12229
12885
|
peerNameCache = new Map;
|
|
12886
|
+
DEPRECATED_TOOL_HINTS = {
|
|
12887
|
+
send_message: "claudemesh send <to> <msg> [--mesh X] [--priority Y]",
|
|
12888
|
+
list_peers: "claudemesh peers --json",
|
|
12889
|
+
check_messages: "claudemesh inbox --json",
|
|
12890
|
+
message_status: "claudemesh msg-status <id>",
|
|
12891
|
+
set_profile: "claudemesh profile --avatar X --bio Y",
|
|
12892
|
+
set_status: "claudemesh status set <state>",
|
|
12893
|
+
set_summary: "claudemesh summary <text>",
|
|
12894
|
+
set_visible: "claudemesh visible <true|false>",
|
|
12895
|
+
join_group: "claudemesh group join @<name> [--role X]",
|
|
12896
|
+
leave_group: "claudemesh group leave @<name>",
|
|
12897
|
+
get_state: "claudemesh state get <key> --json",
|
|
12898
|
+
set_state: "claudemesh state set <key> <value>",
|
|
12899
|
+
list_state: "claudemesh state list --json",
|
|
12900
|
+
remember: "claudemesh remember <text>",
|
|
12901
|
+
recall: "claudemesh recall <query> --json",
|
|
12902
|
+
forget: "claudemesh forget <id>",
|
|
12903
|
+
schedule_reminder: "claudemesh remind <msg> --in/--at/--cron",
|
|
12904
|
+
list_scheduled: "claudemesh remind list --json",
|
|
12905
|
+
cancel_scheduled: "claudemesh remind cancel <id>",
|
|
12906
|
+
mesh_info: "claudemesh info --json",
|
|
12907
|
+
mesh_stats: "claudemesh stats --json",
|
|
12908
|
+
mesh_clock: "claudemesh clock --json",
|
|
12909
|
+
ping_mesh: "claudemesh ping",
|
|
12910
|
+
claim_task: "claudemesh task claim <id>",
|
|
12911
|
+
complete_task: "claudemesh task complete <id>"
|
|
12912
|
+
};
|
|
12913
|
+
warnedTools = new Set;
|
|
12230
12914
|
});
|
|
12231
12915
|
|
|
12232
12916
|
// src/commands/mcp.ts
|
|
@@ -12241,7 +12925,7 @@ async function runMcp() {
|
|
|
12241
12925
|
process.exit(0);
|
|
12242
12926
|
}
|
|
12243
12927
|
var init_mcp = __esm(() => {
|
|
12244
|
-
|
|
12928
|
+
init_server2();
|
|
12245
12929
|
});
|
|
12246
12930
|
|
|
12247
12931
|
// src/commands/hook.ts
|
|
@@ -12521,12 +13205,28 @@ Messaging
|
|
|
12521
13205
|
claudemesh peers see who's online
|
|
12522
13206
|
claudemesh send <to> <msg> send a message
|
|
12523
13207
|
claudemesh inbox drain pending messages
|
|
13208
|
+
claudemesh msg-status <id> check delivery status
|
|
12524
13209
|
claudemesh state get|set|list shared state
|
|
12525
13210
|
claudemesh remember <text> store a memory
|
|
12526
13211
|
claudemesh recall <query> search memories
|
|
13212
|
+
claudemesh forget <id> remove a memory
|
|
12527
13213
|
claudemesh remind ... schedule a reminder
|
|
12528
13214
|
claudemesh profile view or edit your profile
|
|
12529
13215
|
claudemesh info mesh overview
|
|
13216
|
+
claudemesh stats per-peer activity counters
|
|
13217
|
+
claudemesh clock mesh logical clock state
|
|
13218
|
+
claudemesh ping diagnostic round-trip
|
|
13219
|
+
|
|
13220
|
+
Identity / presence
|
|
13221
|
+
claudemesh status set <state> set peer status (idle | working | dnd)
|
|
13222
|
+
claudemesh summary <text> broadcast 1-2 sentence work summary
|
|
13223
|
+
claudemesh visible <true|false> toggle peer visibility
|
|
13224
|
+
claudemesh group join @<name> join a group (--role X optional)
|
|
13225
|
+
claudemesh group leave @<name> leave a group
|
|
13226
|
+
|
|
13227
|
+
Tasks
|
|
13228
|
+
claudemesh task claim <id> claim an unclaimed task
|
|
13229
|
+
claudemesh task complete <id> mark task done [result]
|
|
12530
13230
|
|
|
12531
13231
|
Auth
|
|
12532
13232
|
claudemesh login sign in (browser or paste token)
|
|
@@ -12681,12 +13381,12 @@ async function main() {
|
|
|
12681
13381
|
}
|
|
12682
13382
|
case "peers": {
|
|
12683
13383
|
const { runPeers: runPeers2 } = await Promise.resolve().then(() => (init_peers(), exports_peers));
|
|
12684
|
-
await runPeers2({ mesh: flags.mesh, json:
|
|
13384
|
+
await runPeers2({ mesh: flags.mesh, json: flags.json });
|
|
12685
13385
|
break;
|
|
12686
13386
|
}
|
|
12687
13387
|
case "send": {
|
|
12688
13388
|
const { runSend: runSend2 } = await Promise.resolve().then(() => (init_send(), exports_send));
|
|
12689
|
-
await runSend2({}, positionals[0] ?? "", positionals.slice(1).join(" "));
|
|
13389
|
+
await runSend2({ mesh: flags.mesh, priority: flags.priority, json: !!flags.json }, positionals[0] ?? "", positionals.slice(1).join(" "));
|
|
12690
13390
|
break;
|
|
12691
13391
|
}
|
|
12692
13392
|
case "inbox": {
|
|
@@ -12723,6 +13423,11 @@ async function main() {
|
|
|
12723
13423
|
process.exit(await recall2(positionals.join(" "), { json: !!flags.json }));
|
|
12724
13424
|
break;
|
|
12725
13425
|
}
|
|
13426
|
+
case "forget": {
|
|
13427
|
+
const { runForget: runForget2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
|
|
13428
|
+
process.exit(await runForget2(positionals[0], { mesh: flags.mesh, json: !!flags.json }));
|
|
13429
|
+
break;
|
|
13430
|
+
}
|
|
12726
13431
|
case "remind": {
|
|
12727
13432
|
const { runRemind: runRemind2 } = await Promise.resolve().then(() => (init_remind(), exports_remind));
|
|
12728
13433
|
await runRemind2({ mesh: flags.mesh }, positionals);
|
|
@@ -12733,6 +13438,64 @@ async function main() {
|
|
|
12733
13438
|
await runProfile2(flags);
|
|
12734
13439
|
break;
|
|
12735
13440
|
}
|
|
13441
|
+
case "summary": {
|
|
13442
|
+
const { runSummary: runSummary2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
|
|
13443
|
+
process.exit(await runSummary2(positionals.join(" "), { mesh: flags.mesh, json: !!flags.json }));
|
|
13444
|
+
break;
|
|
13445
|
+
}
|
|
13446
|
+
case "visible": {
|
|
13447
|
+
const { runVisible: runVisible2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
|
|
13448
|
+
process.exit(await runVisible2(positionals[0], { mesh: flags.mesh, json: !!flags.json }));
|
|
13449
|
+
break;
|
|
13450
|
+
}
|
|
13451
|
+
case "group": {
|
|
13452
|
+
const sub = positionals[0];
|
|
13453
|
+
if (sub === "join") {
|
|
13454
|
+
const { runGroupJoin: runGroupJoin2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
|
|
13455
|
+
process.exit(await runGroupJoin2(positionals[1], { mesh: flags.mesh, role: flags.role, json: !!flags.json }));
|
|
13456
|
+
} else if (sub === "leave") {
|
|
13457
|
+
const { runGroupLeave: runGroupLeave2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
|
|
13458
|
+
process.exit(await runGroupLeave2(positionals[1], { mesh: flags.mesh, json: !!flags.json }));
|
|
13459
|
+
} else {
|
|
13460
|
+
console.error("Usage: claudemesh group <join|leave> @<name> [--role X]");
|
|
13461
|
+
process.exit(EXIT.INVALID_ARGS);
|
|
13462
|
+
}
|
|
13463
|
+
break;
|
|
13464
|
+
}
|
|
13465
|
+
case "msg-status": {
|
|
13466
|
+
const { runMsgStatus: runMsgStatus2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
|
|
13467
|
+
process.exit(await runMsgStatus2(positionals[0], { mesh: flags.mesh, json: !!flags.json }));
|
|
13468
|
+
break;
|
|
13469
|
+
}
|
|
13470
|
+
case "clock": {
|
|
13471
|
+
const { runClock: runClock2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
|
|
13472
|
+
process.exit(await runClock2({ mesh: flags.mesh, json: !!flags.json }));
|
|
13473
|
+
break;
|
|
13474
|
+
}
|
|
13475
|
+
case "stats": {
|
|
13476
|
+
const { runStats: runStats2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
|
|
13477
|
+
process.exit(await runStats2({ mesh: flags.mesh, json: !!flags.json }));
|
|
13478
|
+
break;
|
|
13479
|
+
}
|
|
13480
|
+
case "ping": {
|
|
13481
|
+
const { runPing: runPing2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
|
|
13482
|
+
process.exit(await runPing2({ mesh: flags.mesh, json: !!flags.json }));
|
|
13483
|
+
break;
|
|
13484
|
+
}
|
|
13485
|
+
case "task": {
|
|
13486
|
+
const sub = positionals[0];
|
|
13487
|
+
if (sub === "claim") {
|
|
13488
|
+
const { runTaskClaim: runTaskClaim2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
|
|
13489
|
+
process.exit(await runTaskClaim2(positionals[1], { mesh: flags.mesh, json: !!flags.json }));
|
|
13490
|
+
} else if (sub === "complete") {
|
|
13491
|
+
const { runTaskComplete: runTaskComplete2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
|
|
13492
|
+
process.exit(await runTaskComplete2(positionals[1], positionals.slice(2).join(" ") || undefined, { mesh: flags.mesh, json: !!flags.json }));
|
|
13493
|
+
} else {
|
|
13494
|
+
console.error("Usage: claudemesh task <claim|complete> <id> [result]");
|
|
13495
|
+
process.exit(EXIT.INVALID_ARGS);
|
|
13496
|
+
}
|
|
13497
|
+
break;
|
|
13498
|
+
}
|
|
12736
13499
|
case "login": {
|
|
12737
13500
|
const { login: login2 } = await Promise.resolve().then(() => (init_login(), exports_login));
|
|
12738
13501
|
process.exit(await login2());
|
|
@@ -12769,8 +13532,13 @@ async function main() {
|
|
|
12769
13532
|
break;
|
|
12770
13533
|
}
|
|
12771
13534
|
case "status": {
|
|
12772
|
-
|
|
12773
|
-
|
|
13535
|
+
if (positionals[0] === "set") {
|
|
13536
|
+
const { runStatusSet: runStatusSet2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
|
|
13537
|
+
process.exit(await runStatusSet2(positionals[1] ?? "", { mesh: flags.mesh, json: !!flags.json }));
|
|
13538
|
+
} else {
|
|
13539
|
+
const { runStatus: runStatus2 } = await Promise.resolve().then(() => (init_status(), exports_status));
|
|
13540
|
+
await runStatus2();
|
|
13541
|
+
}
|
|
12774
13542
|
break;
|
|
12775
13543
|
}
|
|
12776
13544
|
case "sync": {
|
|
@@ -12866,4 +13634,4 @@ main().catch((err) => {
|
|
|
12866
13634
|
process.exit(EXIT.INTERNAL_ERROR);
|
|
12867
13635
|
});
|
|
12868
13636
|
|
|
12869
|
-
//# debugId=
|
|
13637
|
+
//# debugId=25926A42D1A4B83764756E2164756E21
|