claudemesh-cli 1.0.0-alpha.28 → 1.0.0-alpha.29
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 +464 -80
- package/dist/entrypoints/cli.js.map +12 -9
- package/dist/entrypoints/mcp.js +388 -24
- package/dist/entrypoints/mcp.js.map +9 -4
- package/package.json +1 -1
package/dist/entrypoints/mcp.js
CHANGED
|
@@ -3286,6 +3286,359 @@ var init_facade3 = __esm(() => {
|
|
|
3286
3286
|
init_errors();
|
|
3287
3287
|
});
|
|
3288
3288
|
|
|
3289
|
+
// src/commands/connect.ts
|
|
3290
|
+
import { hostname } from "node:os";
|
|
3291
|
+
import { createInterface } from "node:readline";
|
|
3292
|
+
async function pickMesh(meshes) {
|
|
3293
|
+
console.log(`
|
|
3294
|
+
Select mesh:`);
|
|
3295
|
+
meshes.forEach((m, i) => {
|
|
3296
|
+
console.log(` ${i + 1}) ${m.slug}`);
|
|
3297
|
+
});
|
|
3298
|
+
console.log("");
|
|
3299
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
3300
|
+
return new Promise((resolve) => {
|
|
3301
|
+
rl.question(" Choice [1]: ", (answer) => {
|
|
3302
|
+
rl.close();
|
|
3303
|
+
const idx = parseInt(answer || "1", 10) - 1;
|
|
3304
|
+
if (idx >= 0 && idx < meshes.length) {
|
|
3305
|
+
resolve(meshes[idx]);
|
|
3306
|
+
} else {
|
|
3307
|
+
console.error(" Invalid choice, using first mesh.");
|
|
3308
|
+
resolve(meshes[0]);
|
|
3309
|
+
}
|
|
3310
|
+
});
|
|
3311
|
+
});
|
|
3312
|
+
}
|
|
3313
|
+
async function withMesh(opts, fn) {
|
|
3314
|
+
const config = readConfig();
|
|
3315
|
+
if (config.meshes.length === 0) {
|
|
3316
|
+
console.error("No meshes joined. Run `claudemesh join <url>` first.");
|
|
3317
|
+
process.exit(1);
|
|
3318
|
+
}
|
|
3319
|
+
let mesh;
|
|
3320
|
+
if (opts.meshSlug) {
|
|
3321
|
+
const found = config.meshes.find((m) => m.slug === opts.meshSlug);
|
|
3322
|
+
if (!found) {
|
|
3323
|
+
console.error(`Mesh "${opts.meshSlug}" not found. Joined: ${config.meshes.map((m) => m.slug).join(", ")}`);
|
|
3324
|
+
process.exit(1);
|
|
3325
|
+
}
|
|
3326
|
+
mesh = found;
|
|
3327
|
+
} else if (config.meshes.length === 1) {
|
|
3328
|
+
mesh = config.meshes[0];
|
|
3329
|
+
} else {
|
|
3330
|
+
mesh = await pickMesh(config.meshes);
|
|
3331
|
+
}
|
|
3332
|
+
const displayName = opts.displayName ?? config.displayName ?? `${hostname()}-${process.pid}`;
|
|
3333
|
+
const client = new BrokerClient(mesh, { displayName });
|
|
3334
|
+
try {
|
|
3335
|
+
await client.connect();
|
|
3336
|
+
const result = await fn(client, mesh);
|
|
3337
|
+
return result;
|
|
3338
|
+
} finally {
|
|
3339
|
+
client.close();
|
|
3340
|
+
}
|
|
3341
|
+
}
|
|
3342
|
+
var init_connect = __esm(() => {
|
|
3343
|
+
init_facade3();
|
|
3344
|
+
init_facade();
|
|
3345
|
+
});
|
|
3346
|
+
|
|
3347
|
+
// src/ui/styles.ts
|
|
3348
|
+
function moveTo(row, col) {
|
|
3349
|
+
return isTTY ? `\x1B[${row};${col}H` : "";
|
|
3350
|
+
}
|
|
3351
|
+
function visibleLength(s) {
|
|
3352
|
+
return s.replace(/\x1b\[[^m]*m/g, "").length;
|
|
3353
|
+
}
|
|
3354
|
+
var isTTY, esc = (code) => (s) => isTTY ? `${code}${s}\x1B[0m` : s, orange, clay, amber, bold, dim, green, yellow, red, cyan, boldOrange, HIDE_CURSOR, SHOW_CURSOR, CLEAR_SCREEN, CLEAR_LINE, icons;
|
|
3355
|
+
var init_styles = __esm(() => {
|
|
3356
|
+
isTTY = process.stdout.isTTY && !process.env.NO_COLOR && process.env.TERM !== "dumb";
|
|
3357
|
+
orange = esc("\x1B[38;5;208m");
|
|
3358
|
+
clay = esc("\x1B[38;5;173m");
|
|
3359
|
+
amber = esc("\x1B[38;5;214m");
|
|
3360
|
+
bold = esc("\x1B[1m");
|
|
3361
|
+
dim = esc("\x1B[2m");
|
|
3362
|
+
green = esc("\x1B[32m");
|
|
3363
|
+
yellow = esc("\x1B[33m");
|
|
3364
|
+
red = esc("\x1B[31m");
|
|
3365
|
+
cyan = esc("\x1B[36m");
|
|
3366
|
+
boldOrange = esc("\x1B[1m\x1B[38;5;208m");
|
|
3367
|
+
HIDE_CURSOR = isTTY ? "\x1B[?25l" : "";
|
|
3368
|
+
SHOW_CURSOR = isTTY ? "\x1B[?25h" : "";
|
|
3369
|
+
CLEAR_SCREEN = isTTY ? "\x1B[2J\x1B[H" : "";
|
|
3370
|
+
CLEAR_LINE = isTTY ? "\x1B[K" : "";
|
|
3371
|
+
icons = {
|
|
3372
|
+
check: "✔",
|
|
3373
|
+
cross: "✘",
|
|
3374
|
+
warn: "⚠",
|
|
3375
|
+
arrow: "→",
|
|
3376
|
+
bullet: "●",
|
|
3377
|
+
dash: "—",
|
|
3378
|
+
ellipsis: "…"
|
|
3379
|
+
};
|
|
3380
|
+
});
|
|
3381
|
+
|
|
3382
|
+
// src/ui/render.ts
|
|
3383
|
+
var OUT, ERR, INDENT = " ", render;
|
|
3384
|
+
var init_render = __esm(() => {
|
|
3385
|
+
init_styles();
|
|
3386
|
+
OUT = process.stdout;
|
|
3387
|
+
ERR = process.stderr;
|
|
3388
|
+
render = {
|
|
3389
|
+
blank() {
|
|
3390
|
+
OUT.write(`
|
|
3391
|
+
`);
|
|
3392
|
+
},
|
|
3393
|
+
ok(msg, detail) {
|
|
3394
|
+
const d = detail ? ` ${dim("(" + detail + ")")}` : "";
|
|
3395
|
+
OUT.write(`${INDENT}${green(icons.check)} ${msg}${d}
|
|
3396
|
+
`);
|
|
3397
|
+
},
|
|
3398
|
+
warn(msg, hint) {
|
|
3399
|
+
OUT.write(`${INDENT}${yellow(icons.warn)} ${msg}
|
|
3400
|
+
`);
|
|
3401
|
+
if (hint)
|
|
3402
|
+
OUT.write(`${INDENT} ${dim(hint)}
|
|
3403
|
+
`);
|
|
3404
|
+
},
|
|
3405
|
+
err(msg, hint) {
|
|
3406
|
+
ERR.write(`${INDENT}${red(icons.cross)} ${msg}
|
|
3407
|
+
`);
|
|
3408
|
+
if (hint)
|
|
3409
|
+
ERR.write(`${INDENT} ${dim(hint)}
|
|
3410
|
+
`);
|
|
3411
|
+
},
|
|
3412
|
+
info(msg) {
|
|
3413
|
+
OUT.write(`${INDENT}${msg}
|
|
3414
|
+
`);
|
|
3415
|
+
},
|
|
3416
|
+
section(title) {
|
|
3417
|
+
OUT.write(`
|
|
3418
|
+
${INDENT}${dim("—")} ${clay(title)}
|
|
3419
|
+
|
|
3420
|
+
`);
|
|
3421
|
+
},
|
|
3422
|
+
heading(title) {
|
|
3423
|
+
OUT.write(`${INDENT}${bold(title)}
|
|
3424
|
+
`);
|
|
3425
|
+
},
|
|
3426
|
+
kv(pairs, opts) {
|
|
3427
|
+
const pad = opts?.padTo ?? Math.max(...pairs.map(([k]) => k.length)) + 2;
|
|
3428
|
+
for (const [k, v] of pairs) {
|
|
3429
|
+
OUT.write(`${INDENT}${dim(k.padEnd(pad, " "))}${v}
|
|
3430
|
+
`);
|
|
3431
|
+
}
|
|
3432
|
+
},
|
|
3433
|
+
code(snippet) {
|
|
3434
|
+
for (const line of snippet.split(`
|
|
3435
|
+
`)) {
|
|
3436
|
+
OUT.write(`${INDENT} ${cyan(line)}
|
|
3437
|
+
`);
|
|
3438
|
+
}
|
|
3439
|
+
},
|
|
3440
|
+
link(url) {
|
|
3441
|
+
OUT.write(`${INDENT}${clay(url)}
|
|
3442
|
+
`);
|
|
3443
|
+
},
|
|
3444
|
+
hint(msg) {
|
|
3445
|
+
OUT.write(`${INDENT}${dim(icons.arrow + " " + msg)}
|
|
3446
|
+
`);
|
|
3447
|
+
}
|
|
3448
|
+
};
|
|
3449
|
+
});
|
|
3450
|
+
|
|
3451
|
+
// src/constants/exit-codes.ts
|
|
3452
|
+
var EXIT;
|
|
3453
|
+
var init_exit_codes = __esm(() => {
|
|
3454
|
+
EXIT = {
|
|
3455
|
+
SUCCESS: 0,
|
|
3456
|
+
USER_CANCELLED: 1,
|
|
3457
|
+
AUTH_FAILED: 2,
|
|
3458
|
+
INVALID_ARGS: 3,
|
|
3459
|
+
NETWORK_ERROR: 4,
|
|
3460
|
+
NOT_FOUND: 5,
|
|
3461
|
+
ALREADY_EXISTS: 6,
|
|
3462
|
+
PERMISSION_DENIED: 7,
|
|
3463
|
+
INTERNAL_ERROR: 8,
|
|
3464
|
+
CLAUDE_MISSING: 9
|
|
3465
|
+
};
|
|
3466
|
+
});
|
|
3467
|
+
|
|
3468
|
+
// src/commands/grants.ts
|
|
3469
|
+
var exports_grants = {};
|
|
3470
|
+
__export(exports_grants, {
|
|
3471
|
+
runRevoke: () => runRevoke,
|
|
3472
|
+
runGrants: () => runGrants,
|
|
3473
|
+
runGrant: () => runGrant,
|
|
3474
|
+
runBlock: () => runBlock,
|
|
3475
|
+
isAllowed: () => isAllowed
|
|
3476
|
+
});
|
|
3477
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
3478
|
+
import { homedir as homedir2 } from "node:os";
|
|
3479
|
+
import { join as join2 } from "node:path";
|
|
3480
|
+
function readGrants() {
|
|
3481
|
+
if (!existsSync2(GRANT_FILE))
|
|
3482
|
+
return {};
|
|
3483
|
+
try {
|
|
3484
|
+
return JSON.parse(readFileSync2(GRANT_FILE, "utf-8"));
|
|
3485
|
+
} catch {
|
|
3486
|
+
return {};
|
|
3487
|
+
}
|
|
3488
|
+
}
|
|
3489
|
+
function writeGrants(g) {
|
|
3490
|
+
const dir = join2(homedir2(), ".claudemesh");
|
|
3491
|
+
if (!existsSync2(dir))
|
|
3492
|
+
mkdirSync2(dir, { recursive: true });
|
|
3493
|
+
writeFileSync2(GRANT_FILE, JSON.stringify(g, null, 2), { mode: 384 });
|
|
3494
|
+
}
|
|
3495
|
+
function resolveCaps(input) {
|
|
3496
|
+
if (input.includes("all"))
|
|
3497
|
+
return [...ALL_CAPS];
|
|
3498
|
+
return input.filter((c) => ALL_CAPS.includes(c));
|
|
3499
|
+
}
|
|
3500
|
+
async function resolvePeer(meshSlug, name) {
|
|
3501
|
+
return await withMesh({ meshSlug }, async (client) => {
|
|
3502
|
+
const peers = await client.listPeers();
|
|
3503
|
+
const match = peers.find((p) => p.displayName === name || p.pubkey === name || p.pubkey.startsWith(name));
|
|
3504
|
+
return match ? { displayName: match.displayName, pubkey: match.pubkey } : null;
|
|
3505
|
+
});
|
|
3506
|
+
}
|
|
3507
|
+
function pickMesh2(slug) {
|
|
3508
|
+
const cfg = readConfig();
|
|
3509
|
+
if (slug)
|
|
3510
|
+
return cfg.meshes.find((m) => m.slug === slug) ? slug : null;
|
|
3511
|
+
return cfg.meshes[0]?.slug ?? null;
|
|
3512
|
+
}
|
|
3513
|
+
async function runGrant(peer, caps, opts = {}) {
|
|
3514
|
+
if (!peer || caps.length === 0) {
|
|
3515
|
+
render.err("Usage: claudemesh grant <peer> <capability...>");
|
|
3516
|
+
render.hint(`Capabilities: ${ALL_CAPS.join(", ")}, all`);
|
|
3517
|
+
return EXIT.INVALID_ARGS;
|
|
3518
|
+
}
|
|
3519
|
+
const mesh = pickMesh2(opts.mesh);
|
|
3520
|
+
if (!mesh) {
|
|
3521
|
+
render.err("No matching mesh — join one first.");
|
|
3522
|
+
return EXIT.NOT_FOUND;
|
|
3523
|
+
}
|
|
3524
|
+
const resolved = await resolvePeer(mesh, peer);
|
|
3525
|
+
if (!resolved) {
|
|
3526
|
+
render.err(`Peer "${peer}" not found on ${mesh}.`);
|
|
3527
|
+
return EXIT.NOT_FOUND;
|
|
3528
|
+
}
|
|
3529
|
+
const wanted = resolveCaps(caps);
|
|
3530
|
+
if (wanted.length === 0) {
|
|
3531
|
+
render.err(`Unknown capabilities: ${caps.join(", ")}`);
|
|
3532
|
+
return EXIT.INVALID_ARGS;
|
|
3533
|
+
}
|
|
3534
|
+
const store = readGrants();
|
|
3535
|
+
const meshGrants = store[mesh] ?? {};
|
|
3536
|
+
const existing = meshGrants[resolved.pubkey] ?? DEFAULT_CAPS.slice();
|
|
3537
|
+
const merged = Array.from(new Set([...existing, ...wanted]));
|
|
3538
|
+
meshGrants[resolved.pubkey] = merged;
|
|
3539
|
+
store[mesh] = meshGrants;
|
|
3540
|
+
writeGrants(store);
|
|
3541
|
+
render.ok(`Granted ${wanted.join(", ")} to ${resolved.displayName} on ${mesh}.`);
|
|
3542
|
+
render.kv([["now", merged.join(", ")]]);
|
|
3543
|
+
return EXIT.SUCCESS;
|
|
3544
|
+
}
|
|
3545
|
+
async function runRevoke(peer, caps, opts = {}) {
|
|
3546
|
+
if (!peer || caps.length === 0) {
|
|
3547
|
+
render.err("Usage: claudemesh revoke <peer> <capability...>");
|
|
3548
|
+
return EXIT.INVALID_ARGS;
|
|
3549
|
+
}
|
|
3550
|
+
const mesh = pickMesh2(opts.mesh);
|
|
3551
|
+
if (!mesh) {
|
|
3552
|
+
render.err("No matching mesh.");
|
|
3553
|
+
return EXIT.NOT_FOUND;
|
|
3554
|
+
}
|
|
3555
|
+
const resolved = await resolvePeer(mesh, peer);
|
|
3556
|
+
if (!resolved) {
|
|
3557
|
+
render.err(`Peer "${peer}" not found on ${mesh}.`);
|
|
3558
|
+
return EXIT.NOT_FOUND;
|
|
3559
|
+
}
|
|
3560
|
+
const wanted = caps.includes("all") ? ALL_CAPS.slice() : resolveCaps(caps);
|
|
3561
|
+
const store = readGrants();
|
|
3562
|
+
const meshGrants = store[mesh] ?? {};
|
|
3563
|
+
const existing = meshGrants[resolved.pubkey] ?? DEFAULT_CAPS.slice();
|
|
3564
|
+
const after = existing.filter((c) => !wanted.includes(c));
|
|
3565
|
+
meshGrants[resolved.pubkey] = after;
|
|
3566
|
+
store[mesh] = meshGrants;
|
|
3567
|
+
writeGrants(store);
|
|
3568
|
+
render.ok(`Revoked ${wanted.join(", ")} from ${resolved.displayName} on ${mesh}.`);
|
|
3569
|
+
render.kv([["now", after.length ? after.join(", ") : "(none)"]]);
|
|
3570
|
+
return EXIT.SUCCESS;
|
|
3571
|
+
}
|
|
3572
|
+
async function runBlock(peer, opts = {}) {
|
|
3573
|
+
if (!peer) {
|
|
3574
|
+
render.err("Usage: claudemesh block <peer>");
|
|
3575
|
+
return EXIT.INVALID_ARGS;
|
|
3576
|
+
}
|
|
3577
|
+
const mesh = pickMesh2(opts.mesh);
|
|
3578
|
+
if (!mesh) {
|
|
3579
|
+
render.err("No matching mesh.");
|
|
3580
|
+
return EXIT.NOT_FOUND;
|
|
3581
|
+
}
|
|
3582
|
+
const resolved = await resolvePeer(mesh, peer);
|
|
3583
|
+
if (!resolved) {
|
|
3584
|
+
render.err(`Peer "${peer}" not found on ${mesh}.`);
|
|
3585
|
+
return EXIT.NOT_FOUND;
|
|
3586
|
+
}
|
|
3587
|
+
const store = readGrants();
|
|
3588
|
+
const meshGrants = store[mesh] ?? {};
|
|
3589
|
+
meshGrants[resolved.pubkey] = [];
|
|
3590
|
+
store[mesh] = meshGrants;
|
|
3591
|
+
writeGrants(store);
|
|
3592
|
+
render.ok(`Blocked ${resolved.displayName} on ${mesh} (all capabilities revoked).`);
|
|
3593
|
+
render.hint(`Undo with: claudemesh grant ${resolved.displayName} all --mesh ${mesh}`);
|
|
3594
|
+
return EXIT.SUCCESS;
|
|
3595
|
+
}
|
|
3596
|
+
async function runGrants(opts = {}) {
|
|
3597
|
+
const mesh = pickMesh2(opts.mesh);
|
|
3598
|
+
if (!mesh) {
|
|
3599
|
+
render.err("No matching mesh.");
|
|
3600
|
+
return EXIT.NOT_FOUND;
|
|
3601
|
+
}
|
|
3602
|
+
const store = readGrants();
|
|
3603
|
+
const meshGrants = store[mesh] ?? {};
|
|
3604
|
+
if (opts.json) {
|
|
3605
|
+
console.log(JSON.stringify({ schema_version: "1.0", mesh, grants: meshGrants }, null, 2));
|
|
3606
|
+
return EXIT.SUCCESS;
|
|
3607
|
+
}
|
|
3608
|
+
render.section(`grants on ${mesh}`);
|
|
3609
|
+
const peerPubkeys = Object.keys(meshGrants);
|
|
3610
|
+
if (peerPubkeys.length === 0) {
|
|
3611
|
+
render.info("(no overrides — all peers use default caps: " + DEFAULT_CAPS.join(", ") + ")");
|
|
3612
|
+
return EXIT.SUCCESS;
|
|
3613
|
+
}
|
|
3614
|
+
await withMesh({ meshSlug: mesh }, async (client) => {
|
|
3615
|
+
const peers = await client.listPeers();
|
|
3616
|
+
const byPk = new Map(peers.map((p) => [p.pubkey, p.displayName]));
|
|
3617
|
+
for (const [pk, caps] of Object.entries(meshGrants)) {
|
|
3618
|
+
const name = byPk.get(pk) ?? `${pk.slice(0, 10)}…`;
|
|
3619
|
+
render.kv([[name, caps.length ? caps.join(", ") : "(blocked)"]]);
|
|
3620
|
+
}
|
|
3621
|
+
});
|
|
3622
|
+
return EXIT.SUCCESS;
|
|
3623
|
+
}
|
|
3624
|
+
function isAllowed(meshSlug, peerPubkey, cap) {
|
|
3625
|
+
const store = readGrants();
|
|
3626
|
+
const entry = store[meshSlug]?.[peerPubkey];
|
|
3627
|
+
if (entry === undefined)
|
|
3628
|
+
return DEFAULT_CAPS.includes(cap);
|
|
3629
|
+
return entry.includes(cap);
|
|
3630
|
+
}
|
|
3631
|
+
var ALL_CAPS, DEFAULT_CAPS, GRANT_FILE;
|
|
3632
|
+
var init_grants = __esm(() => {
|
|
3633
|
+
init_facade();
|
|
3634
|
+
init_connect();
|
|
3635
|
+
init_render();
|
|
3636
|
+
init_exit_codes();
|
|
3637
|
+
ALL_CAPS = ["read", "dm", "broadcast", "state-read", "state-write", "file-read"];
|
|
3638
|
+
DEFAULT_CAPS = ["read", "dm", "broadcast", "state-read"];
|
|
3639
|
+
GRANT_FILE = join2(homedir2(), ".claudemesh", "grants.json");
|
|
3640
|
+
});
|
|
3641
|
+
|
|
3289
3642
|
// src/mcp/server.ts
|
|
3290
3643
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3291
3644
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -3749,13 +4102,13 @@ ${peerLines.join(`
|
|
|
3749
4102
|
}
|
|
3750
4103
|
}
|
|
3751
4104
|
try {
|
|
3752
|
-
const { writeFileSync:
|
|
4105
|
+
const { writeFileSync: writeFileSync3, mkdirSync: mkdirSync3, existsSync: existsSync3 } = await import("node:fs");
|
|
3753
4106
|
const { join: joinPath } = await import("node:path");
|
|
3754
|
-
const { homedir:
|
|
3755
|
-
const dir = joinPath(
|
|
3756
|
-
if (!
|
|
3757
|
-
|
|
3758
|
-
|
|
4107
|
+
const { homedir: homedir3 } = await import("node:os");
|
|
4108
|
+
const dir = joinPath(homedir3(), ".claudemesh");
|
|
4109
|
+
if (!existsSync3(dir))
|
|
4110
|
+
mkdirSync3(dir, { recursive: true });
|
|
4111
|
+
writeFileSync3(joinPath(dir, "peer-cache.json"), JSON.stringify(statusCache));
|
|
3759
4112
|
} catch {}
|
|
3760
4113
|
return text(sections.join(`
|
|
3761
4114
|
|
|
@@ -3997,23 +4350,23 @@ ${lines.join(`
|
|
|
3997
4350
|
const { path: filePath, name: fileName, tags, to: fileTo } = args ?? {};
|
|
3998
4351
|
if (!filePath)
|
|
3999
4352
|
return text("share_file: `path` required", true);
|
|
4000
|
-
const { existsSync:
|
|
4001
|
-
if (!
|
|
4353
|
+
const { existsSync: existsSync3 } = await import("node:fs");
|
|
4354
|
+
if (!existsSync3(filePath))
|
|
4002
4355
|
return text(`share_file: file not found: ${filePath}`, true);
|
|
4003
4356
|
const client = allClients()[0];
|
|
4004
4357
|
if (!client)
|
|
4005
4358
|
return text("share_file: not connected", true);
|
|
4006
4359
|
if (fileTo) {
|
|
4007
4360
|
const { encryptFile: encryptFile2, sealKeyForPeer: sealKeyForPeer2 } = await Promise.resolve().then(() => (init_file_crypto(), exports_file_crypto));
|
|
4008
|
-
const { readFileSync:
|
|
4361
|
+
const { readFileSync: readFileSync3, writeFileSync: writeFileSync3, mkdtempSync, unlinkSync, rmdirSync } = await import("node:fs");
|
|
4009
4362
|
const { tmpdir } = await import("node:os");
|
|
4010
|
-
const { join:
|
|
4363
|
+
const { join: join3, basename } = await import("node:path");
|
|
4011
4364
|
const peers = await client.listPeers();
|
|
4012
4365
|
const targetPeer = peers.find((p) => p.pubkey === fileTo || p.displayName === fileTo);
|
|
4013
4366
|
if (!targetPeer) {
|
|
4014
4367
|
return text(`share_file: peer not found: ${fileTo}`, true);
|
|
4015
4368
|
}
|
|
4016
|
-
const plaintext =
|
|
4369
|
+
const plaintext = readFileSync3(filePath);
|
|
4017
4370
|
const { ciphertext, nonce, key } = await encryptFile2(new Uint8Array(plaintext));
|
|
4018
4371
|
const sealedForTarget = await sealKeyForPeer2(key, targetPeer.pubkey);
|
|
4019
4372
|
const myPubkey = client.getSessionPubkey();
|
|
@@ -4030,9 +4383,9 @@ ${lines.join(`
|
|
|
4030
4383
|
combined.set(ciphertext, nonceBytes.length);
|
|
4031
4384
|
const rawName = fileName ?? basename(filePath);
|
|
4032
4385
|
const baseName = basename(rawName).replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 255);
|
|
4033
|
-
const tmpDir = mkdtempSync(
|
|
4034
|
-
const tmpPath =
|
|
4035
|
-
|
|
4386
|
+
const tmpDir = mkdtempSync(join3(tmpdir(), "cm-"));
|
|
4387
|
+
const tmpPath = join3(tmpDir, baseName);
|
|
4388
|
+
writeFileSync3(tmpPath, combined);
|
|
4036
4389
|
try {
|
|
4037
4390
|
const fileId = await client.uploadFile(tmpPath, client.meshId, client.meshSlug, {
|
|
4038
4391
|
name: baseName,
|
|
@@ -4107,10 +4460,10 @@ ${lines.join(`
|
|
|
4107
4460
|
const plaintext = await decryptFile2(ciphertext, nonce, kf);
|
|
4108
4461
|
if (!plaintext)
|
|
4109
4462
|
return text(genericErr, true);
|
|
4110
|
-
const { writeFileSync:
|
|
4463
|
+
const { writeFileSync: writeFileSync4, mkdirSync: mkdirSync4 } = await import("node:fs");
|
|
4111
4464
|
const { dirname: dirname2 } = await import("node:path");
|
|
4112
|
-
|
|
4113
|
-
|
|
4465
|
+
mkdirSync4(dirname2(save_to), { recursive: true });
|
|
4466
|
+
writeFileSync4(save_to, plaintext);
|
|
4114
4467
|
return text(`Downloaded and decrypted: ${result.name} → ${save_to}`);
|
|
4115
4468
|
}
|
|
4116
4469
|
let res = await fetch(result.url, { signal: AbortSignal.timeout(1e4) }).catch(() => null);
|
|
@@ -4120,10 +4473,10 @@ ${lines.join(`
|
|
|
4120
4473
|
}
|
|
4121
4474
|
if (!res.ok)
|
|
4122
4475
|
return text(`get_file: download failed (${res.status})`, true);
|
|
4123
|
-
const { writeFileSync:
|
|
4476
|
+
const { writeFileSync: writeFileSync3, mkdirSync: mkdirSync3 } = await import("node:fs");
|
|
4124
4477
|
const { dirname } = await import("node:path");
|
|
4125
|
-
|
|
4126
|
-
|
|
4478
|
+
mkdirSync3(dirname(save_to), { recursive: true });
|
|
4479
|
+
writeFileSync3(save_to, Buffer.from(await res.arrayBuffer()));
|
|
4127
4480
|
return text(`Downloaded: ${result.name} → ${save_to}`);
|
|
4128
4481
|
}
|
|
4129
4482
|
case "list_files": {
|
|
@@ -4881,10 +5234,10 @@ ${lines.join(`
|
|
|
4881
5234
|
const entryType = vType ?? "env";
|
|
4882
5235
|
let plaintextBytes;
|
|
4883
5236
|
if (entryType === "file") {
|
|
4884
|
-
const { existsSync:
|
|
4885
|
-
if (!
|
|
5237
|
+
const { existsSync: existsSync3, readFileSync: readFileSync3 } = await import("node:fs");
|
|
5238
|
+
if (!existsSync3(value))
|
|
4886
5239
|
return text(`vault_set: file not found: ${value}`, true);
|
|
4887
|
-
plaintextBytes = new Uint8Array(
|
|
5240
|
+
plaintextBytes = new Uint8Array(readFileSync3(value));
|
|
4888
5241
|
} else {
|
|
4889
5242
|
plaintextBytes = new TextEncoder().encode(value);
|
|
4890
5243
|
}
|
|
@@ -5212,6 +5565,17 @@ ${lines.join(`
|
|
|
5212
5565
|
}
|
|
5213
5566
|
const fromPubkey = msg.senderPubkey || "";
|
|
5214
5567
|
const fromName = fromPubkey ? await resolvePeerName(client, fromPubkey) : "unknown";
|
|
5568
|
+
if (fromPubkey) {
|
|
5569
|
+
try {
|
|
5570
|
+
const { isAllowed: isAllowed2 } = await Promise.resolve().then(() => (init_grants(), exports_grants));
|
|
5571
|
+
const kindCap = msg.kind === "broadcast" ? "broadcast" : "dm";
|
|
5572
|
+
if (!isAllowed2(client.meshSlug, fromPubkey, kindCap)) {
|
|
5573
|
+
process.stderr.write(`[claudemesh] dropped ${kindCap} from ${fromName} (not granted)
|
|
5574
|
+
`);
|
|
5575
|
+
return;
|
|
5576
|
+
}
|
|
5577
|
+
} catch {}
|
|
5578
|
+
}
|
|
5215
5579
|
if (messageMode === "inbox") {
|
|
5216
5580
|
try {
|
|
5217
5581
|
await server.notification({
|
|
@@ -5437,4 +5801,4 @@ startMcpServer().catch((err) => {
|
|
|
5437
5801
|
process.exit(1);
|
|
5438
5802
|
});
|
|
5439
5803
|
|
|
5440
|
-
//# debugId=
|
|
5804
|
+
//# debugId=342A89449EA1CD7764756E2164756E21
|