claudemesh-cli 1.0.0 → 1.0.1
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
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.0.1", env;
|
|
92
92
|
var init_urls = __esm(() => {
|
|
93
93
|
URLS = {
|
|
94
94
|
BROKER: process.env.CLAUDEMESH_BROKER_URL ?? "wss://ic.claudemesh.com/ws",
|
|
@@ -1150,6 +1150,7 @@ class BrokerClient {
|
|
|
1150
1150
|
return this._serviceCatalog;
|
|
1151
1151
|
}
|
|
1152
1152
|
closed = false;
|
|
1153
|
+
terminalClose = null;
|
|
1153
1154
|
reconnectAttempt = 0;
|
|
1154
1155
|
helloTimer = null;
|
|
1155
1156
|
reconnectTimer = null;
|
|
@@ -1277,12 +1278,22 @@ class BrokerClient {
|
|
|
1277
1278
|
}
|
|
1278
1279
|
this.handleServerMessage(msg);
|
|
1279
1280
|
};
|
|
1280
|
-
const onClose = () => {
|
|
1281
|
+
const onClose = (code, reasonBuf) => {
|
|
1281
1282
|
if (this.helloTimer)
|
|
1282
1283
|
clearTimeout(this.helloTimer);
|
|
1283
1284
|
this.helloTimer = null;
|
|
1284
1285
|
if (this.ws === ws)
|
|
1285
1286
|
this.ws = null;
|
|
1287
|
+
const reason = reasonBuf?.toString("utf-8") ?? "";
|
|
1288
|
+
if (code === 4001 || code === 4002) {
|
|
1289
|
+
this.closed = true;
|
|
1290
|
+
this.setConnStatus("closed");
|
|
1291
|
+
this.terminalClose = { code, reason };
|
|
1292
|
+
if (this._status !== "open") {
|
|
1293
|
+
reject(new Error(`ws terminal close ${code}: ${reason || "session ended"}`));
|
|
1294
|
+
}
|
|
1295
|
+
return;
|
|
1296
|
+
}
|
|
1286
1297
|
if (this._status !== "open" && this._status !== "reconnecting") {
|
|
1287
1298
|
reject(new Error("ws closed before hello_ack"));
|
|
1288
1299
|
}
|
|
@@ -2965,6 +2976,9 @@ class BrokerClient {
|
|
|
2965
2976
|
}
|
|
2966
2977
|
if (msg.type === "error") {
|
|
2967
2978
|
this.debug(`broker error: ${msg.code} ${msg.message}`);
|
|
2979
|
+
if (msg.code === "revoked") {
|
|
2980
|
+
this.terminalClose = { code: 4002, reason: String(msg.message ?? "revoked") };
|
|
2981
|
+
}
|
|
2968
2982
|
const id = msg.id ? String(msg.id) : null;
|
|
2969
2983
|
let handledByPendingSend = false;
|
|
2970
2984
|
if (id) {
|
|
@@ -6164,6 +6178,25 @@ async function withMesh(opts, fn) {
|
|
|
6164
6178
|
await client.connect();
|
|
6165
6179
|
const result = await fn(client, mesh);
|
|
6166
6180
|
return result;
|
|
6181
|
+
} catch (e) {
|
|
6182
|
+
if (client.terminalClose) {
|
|
6183
|
+
const { code, reason } = client.terminalClose;
|
|
6184
|
+
if (code === 4002) {
|
|
6185
|
+
console.error(`
|
|
6186
|
+
✘ ${reason}
|
|
6187
|
+
`);
|
|
6188
|
+
} else if (code === 4001) {
|
|
6189
|
+
console.error(`
|
|
6190
|
+
✘ Kicked from this mesh. Run \`claudemesh\` to rejoin.
|
|
6191
|
+
`);
|
|
6192
|
+
} else {
|
|
6193
|
+
console.error(`
|
|
6194
|
+
✘ Broker closed connection: ${reason}
|
|
6195
|
+
`);
|
|
6196
|
+
}
|
|
6197
|
+
process.exit(1);
|
|
6198
|
+
}
|
|
6199
|
+
throw e;
|
|
6167
6200
|
} finally {
|
|
6168
6201
|
client.close();
|
|
6169
6202
|
}
|
|
@@ -6176,7 +6209,8 @@ var init_connect = __esm(() => {
|
|
|
6176
6209
|
// src/commands/kick.ts
|
|
6177
6210
|
var exports_kick = {};
|
|
6178
6211
|
__export(exports_kick, {
|
|
6179
|
-
runKick: () => runKick
|
|
6212
|
+
runKick: () => runKick,
|
|
6213
|
+
runDisconnect: () => runDisconnect
|
|
6180
6214
|
});
|
|
6181
6215
|
function parseStaleMs(input) {
|
|
6182
6216
|
const m = input.match(/^(\d+)(s|m|h)$/);
|
|
@@ -6192,36 +6226,63 @@ function parseStaleMs(input) {
|
|
|
6192
6226
|
return val * 3600000;
|
|
6193
6227
|
return null;
|
|
6194
6228
|
}
|
|
6195
|
-
|
|
6229
|
+
function buildPayload(kind, target, opts) {
|
|
6230
|
+
if (opts.all)
|
|
6231
|
+
return { type: kind, all: true };
|
|
6232
|
+
if (opts.stale) {
|
|
6233
|
+
const ms = parseStaleMs(opts.stale);
|
|
6234
|
+
if (!ms)
|
|
6235
|
+
return { error: `Invalid stale duration: "${opts.stale}". Use e.g. 30m, 1h, 300s.` };
|
|
6236
|
+
return { type: kind, stale: ms };
|
|
6237
|
+
}
|
|
6238
|
+
if (target)
|
|
6239
|
+
return { type: kind, target };
|
|
6240
|
+
return { error: `Usage: claudemesh ${kind} <peer> | --stale 30m | --all` };
|
|
6241
|
+
}
|
|
6242
|
+
async function runDisconnect(target, opts = {}) {
|
|
6196
6243
|
const config = readConfig();
|
|
6197
6244
|
const meshSlug = opts.mesh ?? config.meshes[0]?.slug;
|
|
6198
6245
|
if (!meshSlug) {
|
|
6199
6246
|
render.err("No mesh joined.");
|
|
6200
6247
|
return EXIT.NOT_FOUND;
|
|
6201
6248
|
}
|
|
6249
|
+
const built = buildPayload("disconnect", target, opts);
|
|
6250
|
+
if ("error" in built) {
|
|
6251
|
+
render.err(String(built.error));
|
|
6252
|
+
return EXIT.INVALID_ARGS;
|
|
6253
|
+
}
|
|
6202
6254
|
return await withMesh({ meshSlug }, async (client) => {
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
return EXIT.INVALID_ARGS;
|
|
6211
|
-
}
|
|
6212
|
-
payload = { type: "kick", stale: ms };
|
|
6213
|
-
} else if (target) {
|
|
6214
|
-
payload = { type: "kick", target };
|
|
6215
|
-
} else {
|
|
6216
|
-
render.err("Usage: claudemesh kick <peer> | --stale 30m | --all");
|
|
6217
|
-
return EXIT.INVALID_ARGS;
|
|
6255
|
+
const result = await client.sendAndWait(built);
|
|
6256
|
+
const peers = result?.affected ?? result?.kicked ?? [];
|
|
6257
|
+
if (peers.length === 0)
|
|
6258
|
+
render.info("No peers matched.");
|
|
6259
|
+
else {
|
|
6260
|
+
render.ok(`Disconnected ${peers.length} peer(s): ${peers.join(", ")}`);
|
|
6261
|
+
render.hint("They will auto-reconnect within seconds. For a session-ending kick, use `claudemesh kick`.");
|
|
6218
6262
|
}
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6263
|
+
return EXIT.SUCCESS;
|
|
6264
|
+
});
|
|
6265
|
+
}
|
|
6266
|
+
async function runKick(target, opts = {}) {
|
|
6267
|
+
const config = readConfig();
|
|
6268
|
+
const meshSlug = opts.mesh ?? config.meshes[0]?.slug;
|
|
6269
|
+
if (!meshSlug) {
|
|
6270
|
+
render.err("No mesh joined.");
|
|
6271
|
+
return EXIT.NOT_FOUND;
|
|
6272
|
+
}
|
|
6273
|
+
const built = buildPayload("kick", target, opts);
|
|
6274
|
+
if ("error" in built) {
|
|
6275
|
+
render.err(String(built.error));
|
|
6276
|
+
return EXIT.INVALID_ARGS;
|
|
6277
|
+
}
|
|
6278
|
+
return await withMesh({ meshSlug }, async (client) => {
|
|
6279
|
+
const result = await client.sendAndWait(built);
|
|
6280
|
+
const peers = result?.affected ?? result?.kicked ?? [];
|
|
6281
|
+
if (peers.length === 0)
|
|
6222
6282
|
render.info("No peers matched.");
|
|
6223
|
-
|
|
6224
|
-
render.ok(`Kicked ${
|
|
6283
|
+
else {
|
|
6284
|
+
render.ok(`Kicked ${peers.length} peer(s): ${peers.join(", ")}`);
|
|
6285
|
+
render.hint("Their Claude Code session ended. They can rejoin anytime by running `claudemesh`.");
|
|
6225
6286
|
}
|
|
6226
6287
|
return EXIT.SUCCESS;
|
|
6227
6288
|
});
|
|
@@ -12412,9 +12473,10 @@ Mesh
|
|
|
12412
12473
|
claudemesh delete [slug] delete a mesh (alias: rm)
|
|
12413
12474
|
claudemesh rename <slug> <name> rename a mesh
|
|
12414
12475
|
claudemesh share [email] share mesh (invite link / send email)
|
|
12415
|
-
claudemesh
|
|
12416
|
-
claudemesh kick
|
|
12417
|
-
claudemesh kick --
|
|
12476
|
+
claudemesh disconnect <peer> soft disconnect (peer auto-reconnects)
|
|
12477
|
+
claudemesh kick <peer> end session (peer must manually rejoin)
|
|
12478
|
+
claudemesh kick --stale 30m kick peers idle > duration
|
|
12479
|
+
claudemesh kick --all kick everyone except yourself
|
|
12418
12480
|
claudemesh ban <peer> kick + permanently revoke (can't rejoin)
|
|
12419
12481
|
claudemesh unban <peer> lift a ban
|
|
12420
12482
|
claudemesh bans list banned members
|
|
@@ -12556,6 +12618,11 @@ async function main() {
|
|
|
12556
12618
|
process.exit(await invite2(positionals[0], { mesh: flags.mesh, json: !!flags.json }));
|
|
12557
12619
|
break;
|
|
12558
12620
|
}
|
|
12621
|
+
case "disconnect": {
|
|
12622
|
+
const { runDisconnect: runDisconnect2 } = await Promise.resolve().then(() => (init_kick(), exports_kick));
|
|
12623
|
+
process.exit(await runDisconnect2(positionals[0], { mesh: flags.mesh, stale: flags.stale, all: !!flags.all }));
|
|
12624
|
+
break;
|
|
12625
|
+
}
|
|
12559
12626
|
case "kick": {
|
|
12560
12627
|
const { runKick: runKick2 } = await Promise.resolve().then(() => (init_kick(), exports_kick));
|
|
12561
12628
|
process.exit(await runKick2(positionals[0], { mesh: flags.mesh, stale: flags.stale, all: !!flags.all }));
|
|
@@ -12763,4 +12830,4 @@ main().catch((err) => {
|
|
|
12763
12830
|
process.exit(EXIT.INTERNAL_ERROR);
|
|
12764
12831
|
});
|
|
12765
12832
|
|
|
12766
|
-
//# debugId=
|
|
12833
|
+
//# debugId=4199659439A09F6C64756E2164756E21
|