claudemesh-cli 1.34.2 → 1.34.4
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 +135 -61
- package/dist/entrypoints/cli.js.map +4 -4
- package/dist/entrypoints/mcp.js +156 -57
- package/dist/entrypoints/mcp.js.map +5 -4
- package/package.json +1 -1
- package/skills/claudemesh/SKILL.md +18 -7
package/dist/entrypoints/mcp.js
CHANGED
|
@@ -81,7 +81,7 @@ __export(exports_urls, {
|
|
|
81
81
|
VERSION: () => VERSION,
|
|
82
82
|
URLS: () => URLS
|
|
83
83
|
});
|
|
84
|
-
var URLS, VERSION = "1.34.
|
|
84
|
+
var URLS, VERSION = "1.34.4", env;
|
|
85
85
|
var init_urls = __esm(() => {
|
|
86
86
|
URLS = {
|
|
87
87
|
BROKER: process.env.CLAUDEMESH_BROKER_URL ?? "wss://ic.claudemesh.com/ws",
|
|
@@ -2632,6 +2632,44 @@ var init_facade3 = __esm(() => {
|
|
|
2632
2632
|
init_errors();
|
|
2633
2633
|
});
|
|
2634
2634
|
|
|
2635
|
+
// src/services/session/token.ts
|
|
2636
|
+
var exports_token = {};
|
|
2637
|
+
__export(exports_token, {
|
|
2638
|
+
readSessionTokenFromEnv: () => readSessionTokenFromEnv,
|
|
2639
|
+
mintSessionToken: () => mintSessionToken,
|
|
2640
|
+
TOKEN_FILE_ENV: () => TOKEN_FILE_ENV
|
|
2641
|
+
});
|
|
2642
|
+
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
2643
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
2644
|
+
function mintSessionToken(dir, fileName = "session-token") {
|
|
2645
|
+
const token = randomBytes3(32).toString("hex");
|
|
2646
|
+
const filePath = `${dir}/${fileName}`;
|
|
2647
|
+
writeFileSync2(filePath, token, { mode: 384 });
|
|
2648
|
+
return { token, filePath };
|
|
2649
|
+
}
|
|
2650
|
+
function readSessionTokenFromEnv(env2 = process.env) {
|
|
2651
|
+
const direct = env2.CLAUDEMESH_IPC_TOKEN;
|
|
2652
|
+
if (direct && /^[0-9a-f]{64}$/i.test(direct))
|
|
2653
|
+
return direct.toLowerCase();
|
|
2654
|
+
const path = env2[ENV_TOKEN_FILE];
|
|
2655
|
+
if (!path)
|
|
2656
|
+
return null;
|
|
2657
|
+
try {
|
|
2658
|
+
if (!existsSync2(path))
|
|
2659
|
+
return null;
|
|
2660
|
+
const raw = readFileSync2(path, "utf8").trim();
|
|
2661
|
+
if (/^[0-9a-f]{64}$/i.test(raw))
|
|
2662
|
+
return raw.toLowerCase();
|
|
2663
|
+
return null;
|
|
2664
|
+
} catch {
|
|
2665
|
+
return null;
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
var ENV_TOKEN_FILE = "CLAUDEMESH_IPC_TOKEN_FILE", TOKEN_FILE_ENV;
|
|
2669
|
+
var init_token = __esm(() => {
|
|
2670
|
+
TOKEN_FILE_ENV = ENV_TOKEN_FILE;
|
|
2671
|
+
});
|
|
2672
|
+
|
|
2635
2673
|
// src/mcp/server.ts
|
|
2636
2674
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
2637
2675
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -2643,12 +2681,12 @@ import {
|
|
|
2643
2681
|
ListResourcesRequestSchema,
|
|
2644
2682
|
ReadResourceRequestSchema
|
|
2645
2683
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
2646
|
-
import { existsSync as
|
|
2684
|
+
import { existsSync as existsSync3, appendFileSync } from "node:fs";
|
|
2647
2685
|
import { request as httpRequest } from "node:http";
|
|
2648
2686
|
import { join as join3 } from "node:path";
|
|
2649
2687
|
async function daemonReady() {
|
|
2650
2688
|
for (let i = 0;i < DAEMON_BOOT_RETRIES; i++) {
|
|
2651
|
-
if (
|
|
2689
|
+
if (existsSync3(DAEMON_PATHS.SOCK_FILE))
|
|
2652
2690
|
return true;
|
|
2653
2691
|
await new Promise((r) => setTimeout(r, DAEMON_BOOT_RETRY_MS));
|
|
2654
2692
|
}
|
|
@@ -2666,9 +2704,12 @@ function bailNoDaemon() {
|
|
|
2666
2704
|
`);
|
|
2667
2705
|
process.exit(1);
|
|
2668
2706
|
}
|
|
2669
|
-
function daemonGet(path) {
|
|
2707
|
+
function daemonGet(path, opts = {}) {
|
|
2670
2708
|
return new Promise((resolve, reject) => {
|
|
2671
|
-
const
|
|
2709
|
+
const headers = {};
|
|
2710
|
+
if (opts.sessionToken)
|
|
2711
|
+
headers.Authorization = `ClaudeMesh-Session ${opts.sessionToken}`;
|
|
2712
|
+
const req = httpRequest({ socketPath: DAEMON_PATHS.SOCK_FILE, path, method: "GET", timeout: 5000, headers }, (res) => {
|
|
2672
2713
|
const chunks = [];
|
|
2673
2714
|
res.on("data", (c) => chunks.push(c));
|
|
2674
2715
|
res.on("end", () => {
|
|
@@ -2962,13 +3003,19 @@ ${mf.allowed_tools.map((t) => ` - ${t}`).join(`
|
|
|
2962
3003
|
} catch {}
|
|
2963
3004
|
}
|
|
2964
3005
|
});
|
|
3006
|
+
let welcomeSent = false;
|
|
3007
|
+
const WELCOME_GRACE_MS = 2000;
|
|
3008
|
+
server.oninitialized = () => {
|
|
3009
|
+
mcpLog("server_initialized");
|
|
3010
|
+
if (welcomeSent)
|
|
3011
|
+
return;
|
|
3012
|
+
welcomeSent = true;
|
|
3013
|
+
setTimeout(() => {
|
|
3014
|
+
emitMeshWelcome(server, mcpLog);
|
|
3015
|
+
}, WELCOME_GRACE_MS);
|
|
3016
|
+
};
|
|
2965
3017
|
const transport = new StdioServerTransport;
|
|
2966
3018
|
await server.connect(transport);
|
|
2967
|
-
const WELCOME_DELAY_MS = 5000;
|
|
2968
|
-
const WELCOME_LOOKBACK_MS = 24 * 60 * 60 * 1000;
|
|
2969
|
-
setTimeout(() => {
|
|
2970
|
-
emitInboxWelcome(server, mcpLog, WELCOME_LOOKBACK_MS);
|
|
2971
|
-
}, WELCOME_DELAY_MS);
|
|
2972
3019
|
const keepalive = setInterval(() => {}, 1000);
|
|
2973
3020
|
const shutdown = () => {
|
|
2974
3021
|
clearInterval(keepalive);
|
|
@@ -2978,52 +3025,95 @@ ${mf.allowed_tools.map((t) => ` - ${t}`).join(`
|
|
|
2978
3025
|
process.on("SIGTERM", shutdown);
|
|
2979
3026
|
process.on("SIGINT", shutdown);
|
|
2980
3027
|
}
|
|
2981
|
-
async function
|
|
2982
|
-
const
|
|
2983
|
-
const
|
|
2984
|
-
let
|
|
3028
|
+
async function emitMeshWelcome(server, mcpLog) {
|
|
3029
|
+
const { readSessionTokenFromEnv: readSessionTokenFromEnv2 } = await Promise.resolve().then(() => (init_token(), exports_token));
|
|
3030
|
+
const sessionToken = readSessionTokenFromEnv2();
|
|
3031
|
+
let selfDisplayName;
|
|
3032
|
+
let selfSessionPubkey;
|
|
3033
|
+
let selfMeshSlug;
|
|
3034
|
+
let selfRole;
|
|
3035
|
+
if (sessionToken) {
|
|
3036
|
+
try {
|
|
3037
|
+
const { status, body } = await daemonGet("/v1/sessions/me", { sessionToken });
|
|
3038
|
+
if (status === 200 && body?.session) {
|
|
3039
|
+
selfDisplayName = body.session.displayName;
|
|
3040
|
+
selfMeshSlug = body.session.mesh;
|
|
3041
|
+
selfRole = body.session.role;
|
|
3042
|
+
selfSessionPubkey = body.session.presence?.sessionPubkey;
|
|
3043
|
+
}
|
|
3044
|
+
} catch (e) {
|
|
3045
|
+
mcpLog("welcome_self_lookup_failed", { err: String(e) });
|
|
3046
|
+
}
|
|
3047
|
+
}
|
|
3048
|
+
let peerCount = -1;
|
|
3049
|
+
let peerNames = [];
|
|
2985
3050
|
try {
|
|
2986
|
-
const
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
3051
|
+
const path = selfMeshSlug ? `/v1/peers?mesh=${encodeURIComponent(selfMeshSlug)}` : "/v1/peers";
|
|
3052
|
+
const { status, body } = await daemonGet(path, { sessionToken });
|
|
3053
|
+
if (status === 200 && Array.isArray(body?.peers)) {
|
|
3054
|
+
const peers = body.peers;
|
|
3055
|
+
const real = peers.filter((p) => {
|
|
3056
|
+
const channel = String(p.channel ?? "");
|
|
3057
|
+
const peerRole = String(p.peerRole ?? "");
|
|
3058
|
+
const isInfra = channel === "claudemesh-daemon" || peerRole === "control-plane";
|
|
3059
|
+
if (isInfra)
|
|
3060
|
+
return false;
|
|
3061
|
+
if (selfSessionPubkey && p.pubkey === selfSessionPubkey)
|
|
3062
|
+
return false;
|
|
3063
|
+
return true;
|
|
3064
|
+
});
|
|
3065
|
+
peerCount = real.length;
|
|
3066
|
+
peerNames = real.map((p) => String(p.displayName ?? "unknown")).filter((n, i, arr) => arr.indexOf(n) === i).slice(0, 5);
|
|
3067
|
+
mcpLog("welcome_peers_resolved", { total: peers.length, real: real.length });
|
|
3068
|
+
} else {
|
|
3069
|
+
mcpLog("welcome_peers_status", { status });
|
|
3070
|
+
}
|
|
3071
|
+
} catch (e) {
|
|
3072
|
+
mcpLog("welcome_peers_lookup_failed", { err: String(e) });
|
|
3073
|
+
}
|
|
3074
|
+
const sinceIso = new Date(Date.now() - 86400000).toISOString();
|
|
3075
|
+
const inboxPath = selfMeshSlug ? `/v1/inbox?mesh=${encodeURIComponent(selfMeshSlug)}&since=${encodeURIComponent(sinceIso)}&limit=20` : `/v1/inbox?since=${encodeURIComponent(sinceIso)}&limit=20`;
|
|
3076
|
+
let inboxItems = [];
|
|
3077
|
+
try {
|
|
3078
|
+
const { status, body } = await daemonGet(inboxPath, { sessionToken });
|
|
3079
|
+
if (status === 200 && Array.isArray(body?.items)) {
|
|
3080
|
+
inboxItems = body.items;
|
|
2990
3081
|
}
|
|
2991
|
-
body = res.body;
|
|
2992
3082
|
} catch (e) {
|
|
2993
|
-
mcpLog("
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
const
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
const
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
}
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3083
|
+
mcpLog("welcome_inbox_lookup_failed", { err: String(e) });
|
|
3084
|
+
}
|
|
3085
|
+
const lines = [];
|
|
3086
|
+
const idTag = selfDisplayName ? `${selfDisplayName}${selfSessionPubkey ? ` (${selfSessionPubkey.slice(0, 8)})` : ""}${selfRole ? ` [${selfRole}]` : ""}` : "session";
|
|
3087
|
+
const meshTag = selfMeshSlug ? ` on mesh \`${selfMeshSlug}\`` : "";
|
|
3088
|
+
lines.push(`\uD83C\uDF10 [welcome] claudemesh connected — you are **${idTag}**${meshTag}.`);
|
|
3089
|
+
if (peerCount === 0) {
|
|
3090
|
+
lines.push(`\uD83D\uDC65 No other peers online right now.`);
|
|
3091
|
+
} else if (peerCount > 0) {
|
|
3092
|
+
const namesPreview = peerNames.join(", ");
|
|
3093
|
+
const more = peerCount > peerNames.length ? ` …and ${peerCount - peerNames.length} more` : "";
|
|
3094
|
+
lines.push(`\uD83D\uDC65 ${peerCount} peer${peerCount === 1 ? "" : "s"} online: ${namesPreview}${more}`);
|
|
3095
|
+
} else {
|
|
3096
|
+
lines.push(`\uD83D\uDC65 Peer list unavailable (daemon query failed).`);
|
|
3097
|
+
}
|
|
3098
|
+
if (inboxItems.length === 0) {
|
|
3099
|
+
lines.push(`\uD83D\uDCE5 Inbox is empty (last 24h).`);
|
|
3100
|
+
} else {
|
|
3101
|
+
lines.push(`\uD83D\uDCE5 ${inboxItems.length} message${inboxItems.length === 1 ? "" : "s"} in inbox (last 24h):`);
|
|
3102
|
+
for (const it of inboxItems.slice(0, 3)) {
|
|
3103
|
+
const sender = String(it.sender_name ?? "unknown");
|
|
3104
|
+
const senderPub = String(it.sender_pubkey ?? "").slice(0, 8);
|
|
3105
|
+
const tag = sender !== senderPub ? `${sender} (${senderPub})` : senderPub;
|
|
3106
|
+
const bodyText = (typeof it.body === "string" ? it.body : "(encrypted)").slice(0, 60);
|
|
3107
|
+
const time = it.received_at ? new Date(String(it.received_at)).toLocaleTimeString() : "";
|
|
3108
|
+
lines.push(` ${tag} ${time}: ${bodyText}`);
|
|
3109
|
+
}
|
|
3110
|
+
if (inboxItems.length > 3)
|
|
3111
|
+
lines.push(` …and ${inboxItems.length - 3} more`);
|
|
3112
|
+
}
|
|
3113
|
+
lines.push(`\uD83D\uDCA1 Use: \`claudemesh peer list\` · \`claudemesh send <peer> <msg>\` · \`claudemesh inbox\``);
|
|
3114
|
+
lines.push(`\uD83D\uDCDA Read the \`claudemesh\` skill (SKILL.md) for full CLI / channel / inbox reference if not yet in context.`);
|
|
3115
|
+
const content = lines.join(`
|
|
3018
3116
|
`);
|
|
3019
|
-
const remainder = items.length > 3 ? `
|
|
3020
|
-
…and ${items.length - 3} more` : "";
|
|
3021
|
-
const meshList = [...byMesh.keys()].filter(Boolean).join(", ");
|
|
3022
|
-
const header = `\uD83D\uDCE5 [welcome] ${items.length} message${items.length === 1 ? "" : "s"} in inbox from the last 24h${meshList ? ` (${meshList})` : ""}`;
|
|
3023
|
-
const footer = `
|
|
3024
|
-
Run \`claudemesh inbox\` for full content.`;
|
|
3025
|
-
const content = `${header}
|
|
3026
|
-
${preview}${remainder}${footer}`;
|
|
3027
3117
|
try {
|
|
3028
3118
|
await server.notification({
|
|
3029
3119
|
method: "notifications/claude/channel",
|
|
@@ -3031,13 +3121,22 @@ ${preview}${remainder}${footer}`;
|
|
|
3031
3121
|
content,
|
|
3032
3122
|
meta: {
|
|
3033
3123
|
kind: "welcome",
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3124
|
+
self_display_name: selfDisplayName ?? "",
|
|
3125
|
+
self_session_pubkey: selfSessionPubkey ?? "",
|
|
3126
|
+
self_role: selfRole ?? "",
|
|
3127
|
+
mesh_slug: selfMeshSlug ?? "",
|
|
3128
|
+
peer_count: peerCount >= 0 ? peerCount : null,
|
|
3129
|
+
peer_names: peerNames,
|
|
3130
|
+
unread_count: inboxItems.length,
|
|
3131
|
+
latest_message_ids: inboxItems.slice(0, 10).map((it) => String(it.id ?? ""))
|
|
3037
3132
|
}
|
|
3038
3133
|
}
|
|
3039
3134
|
});
|
|
3040
|
-
mcpLog("welcome_emitted", {
|
|
3135
|
+
mcpLog("welcome_emitted", {
|
|
3136
|
+
mesh: selfMeshSlug ?? "",
|
|
3137
|
+
peer_count: peerCount,
|
|
3138
|
+
unread_count: inboxItems.length
|
|
3139
|
+
});
|
|
3041
3140
|
} catch (err) {
|
|
3042
3141
|
mcpLog("welcome_emit_failed", { err: String(err) });
|
|
3043
3142
|
}
|
|
@@ -3154,4 +3253,4 @@ startMcpServer().catch((err) => {
|
|
|
3154
3253
|
process.exit(1);
|
|
3155
3254
|
});
|
|
3156
3255
|
|
|
3157
|
-
//# debugId=
|
|
3256
|
+
//# debugId=37722A693A6DEC1564756E2164756E21
|