claudemesh-cli 1.0.0-alpha.14 → 1.0.0-alpha.16
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 +255 -184
- package/dist/entrypoints/cli.js.map +7 -7
- package/package.json +3 -3
package/dist/entrypoints/cli.js
CHANGED
|
@@ -1078,11 +1078,23 @@ async function createMesh2(name, opts) {
|
|
|
1078
1078
|
const auth = getStoredToken();
|
|
1079
1079
|
if (!auth)
|
|
1080
1080
|
throw new Error("Not signed in");
|
|
1081
|
-
|
|
1081
|
+
let userId = "";
|
|
1082
|
+
try {
|
|
1083
|
+
const payload = JSON.parse(Buffer.from(auth.session_token.split(".")[1], "base64url").toString());
|
|
1084
|
+
userId = payload.sub ?? "";
|
|
1085
|
+
} catch {}
|
|
1086
|
+
if (!userId)
|
|
1087
|
+
throw new Error("Invalid token — run `claudemesh login` again");
|
|
1088
|
+
const result = await request({
|
|
1089
|
+
path: "/cli/mesh/create",
|
|
1090
|
+
method: "POST",
|
|
1091
|
+
body: { user_id: userId, name, ...opts },
|
|
1092
|
+
baseUrl: BROKER_HTTP2
|
|
1093
|
+
});
|
|
1082
1094
|
const kp = await generateKeypair3();
|
|
1083
1095
|
const mesh = {
|
|
1084
1096
|
meshId: result.id,
|
|
1085
|
-
memberId:
|
|
1097
|
+
memberId: result.member_id,
|
|
1086
1098
|
slug: result.slug,
|
|
1087
1099
|
name: result.name,
|
|
1088
1100
|
pubkey: kp.publicKey,
|
|
@@ -1093,12 +1105,14 @@ async function createMesh2(name, opts) {
|
|
|
1093
1105
|
setMeshConfig(result.slug, mesh);
|
|
1094
1106
|
return { slug: result.slug, id: result.id };
|
|
1095
1107
|
}
|
|
1108
|
+
var BROKER_HTTP2;
|
|
1096
1109
|
var init_create = __esm(() => {
|
|
1097
1110
|
init_facade3();
|
|
1098
1111
|
init_facade6();
|
|
1099
1112
|
init_facade7();
|
|
1100
1113
|
init_facade();
|
|
1101
1114
|
init_urls();
|
|
1115
|
+
BROKER_HTTP2 = URLS.BROKER.replace("wss://", "https://").replace("ws://", "http://").replace("/ws", "");
|
|
1102
1116
|
});
|
|
1103
1117
|
|
|
1104
1118
|
// src/services/mesh/rename.ts
|
|
@@ -1160,12 +1174,141 @@ var init_facade9 = __esm(() => {
|
|
|
1160
1174
|
init_errors3();
|
|
1161
1175
|
});
|
|
1162
1176
|
|
|
1177
|
+
// src/commands/login.ts
|
|
1178
|
+
var exports_login = {};
|
|
1179
|
+
__export(exports_login, {
|
|
1180
|
+
login: () => login
|
|
1181
|
+
});
|
|
1182
|
+
import { createInterface as createInterface2 } from "node:readline";
|
|
1183
|
+
function prompt(question) {
|
|
1184
|
+
const rl = createInterface2({ input: process.stdin, output: process.stdout });
|
|
1185
|
+
return new Promise((resolve) => {
|
|
1186
|
+
rl.question(question, (answer) => {
|
|
1187
|
+
rl.close();
|
|
1188
|
+
resolve(answer.trim());
|
|
1189
|
+
});
|
|
1190
|
+
});
|
|
1191
|
+
}
|
|
1192
|
+
async function loginWithToken() {
|
|
1193
|
+
console.log(`
|
|
1194
|
+
Paste a token from ${dim(URLS.API_BASE + "/token")}`);
|
|
1195
|
+
console.log(` ${dim("Generate one in your browser, then paste it here.")}
|
|
1196
|
+
`);
|
|
1197
|
+
const token = await prompt(" Token: ");
|
|
1198
|
+
if (!token) {
|
|
1199
|
+
console.error(` ${icons.cross} No token provided.`);
|
|
1200
|
+
return EXIT.AUTH_FAILED;
|
|
1201
|
+
}
|
|
1202
|
+
let user = { id: "", display_name: "", email: "" };
|
|
1203
|
+
try {
|
|
1204
|
+
const parts = token.split(".");
|
|
1205
|
+
if (parts[1]) {
|
|
1206
|
+
const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString());
|
|
1207
|
+
if (payload.exp && payload.exp < Date.now() / 1000) {
|
|
1208
|
+
console.error(` ${icons.cross} Token expired. Generate a new one.`);
|
|
1209
|
+
return EXIT.AUTH_FAILED;
|
|
1210
|
+
}
|
|
1211
|
+
user = {
|
|
1212
|
+
id: payload.sub ?? "",
|
|
1213
|
+
display_name: payload.name ?? payload.email ?? "",
|
|
1214
|
+
email: payload.email ?? ""
|
|
1215
|
+
};
|
|
1216
|
+
}
|
|
1217
|
+
} catch {
|
|
1218
|
+
console.error(` ${icons.cross} Invalid token format.`);
|
|
1219
|
+
return EXIT.AUTH_FAILED;
|
|
1220
|
+
}
|
|
1221
|
+
storeToken({ session_token: token, user, token_source: "manual" });
|
|
1222
|
+
console.log(` ${green(icons.check)} Signed in as ${user.display_name || user.email || "user"}.`);
|
|
1223
|
+
return EXIT.SUCCESS;
|
|
1224
|
+
}
|
|
1225
|
+
async function syncMeshes(token) {
|
|
1226
|
+
try {
|
|
1227
|
+
const meshes = await exports_my.getMeshes(token);
|
|
1228
|
+
if (meshes.length > 0) {
|
|
1229
|
+
const names = meshes.map((m) => m.slug).join(", ");
|
|
1230
|
+
console.log(` ${green(icons.check)} Synced ${meshes.length} mesh${meshes.length === 1 ? "" : "es"}: ${names}`);
|
|
1231
|
+
}
|
|
1232
|
+
} catch {}
|
|
1233
|
+
}
|
|
1234
|
+
async function login() {
|
|
1235
|
+
const existing = getStoredToken();
|
|
1236
|
+
if (existing) {
|
|
1237
|
+
const name = existing.user.display_name || existing.user.email || "unknown";
|
|
1238
|
+
console.log(`
|
|
1239
|
+
Already signed in as ${bold(name)}.`);
|
|
1240
|
+
console.log("");
|
|
1241
|
+
console.log(` ${bold("1)")} Continue as ${name}`);
|
|
1242
|
+
console.log(` ${bold("2)")} Sign in via browser`);
|
|
1243
|
+
console.log(` ${bold("3)")} Paste a token from ${dim("claudemesh.com/token")}`);
|
|
1244
|
+
console.log(` ${bold("4)")} Sign out`);
|
|
1245
|
+
console.log("");
|
|
1246
|
+
const choice = await prompt(" Choice [1]: ") || "1";
|
|
1247
|
+
if (choice === "1") {
|
|
1248
|
+
console.log(`
|
|
1249
|
+
${green(icons.check)} Continuing as ${name}.`);
|
|
1250
|
+
return EXIT.SUCCESS;
|
|
1251
|
+
}
|
|
1252
|
+
if (choice === "4") {
|
|
1253
|
+
clearToken();
|
|
1254
|
+
console.log(` ${green(icons.check)} Signed out.`);
|
|
1255
|
+
return EXIT.SUCCESS;
|
|
1256
|
+
}
|
|
1257
|
+
if (choice === "3") {
|
|
1258
|
+
clearToken();
|
|
1259
|
+
return loginWithToken();
|
|
1260
|
+
}
|
|
1261
|
+
clearToken();
|
|
1262
|
+
console.log(` ${dim("Signing in…")}`);
|
|
1263
|
+
} else {
|
|
1264
|
+
console.log(`
|
|
1265
|
+
${bold("claudemesh")} — sign in to connect your terminal`);
|
|
1266
|
+
console.log("");
|
|
1267
|
+
console.log(` ${bold("1)")} Sign in via browser ${dim("(opens automatically)")}`);
|
|
1268
|
+
console.log(` ${bold("2)")} Paste a token from ${dim("claudemesh.com/token")}`);
|
|
1269
|
+
console.log("");
|
|
1270
|
+
const choice = await prompt(" Choice [1]: ") || "1";
|
|
1271
|
+
if (choice === "2") {
|
|
1272
|
+
return loginWithToken();
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
try {
|
|
1276
|
+
const result = await loginWithDeviceCode();
|
|
1277
|
+
console.log(` ${green(icons.check)} Signed in as ${result.user.display_name}.`);
|
|
1278
|
+
await syncMeshes(result.session_token);
|
|
1279
|
+
return EXIT.SUCCESS;
|
|
1280
|
+
} catch (err) {
|
|
1281
|
+
console.error(` ${icons.cross} Login failed: ${err instanceof Error ? err.message : err}`);
|
|
1282
|
+
return EXIT.AUTH_FAILED;
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
var init_login = __esm(() => {
|
|
1286
|
+
init_facade6();
|
|
1287
|
+
init_facade3();
|
|
1288
|
+
init_styles();
|
|
1289
|
+
init_exit_codes();
|
|
1290
|
+
init_urls();
|
|
1291
|
+
});
|
|
1292
|
+
|
|
1163
1293
|
// src/commands/new.ts
|
|
1164
1294
|
var exports_new = {};
|
|
1165
1295
|
__export(exports_new, {
|
|
1166
1296
|
newMesh: () => newMesh
|
|
1167
1297
|
});
|
|
1168
1298
|
async function newMesh(name, opts) {
|
|
1299
|
+
if (!name) {
|
|
1300
|
+
console.error(" Usage: claudemesh mesh create <name>");
|
|
1301
|
+
return EXIT.INVALID_ARGS;
|
|
1302
|
+
}
|
|
1303
|
+
if (!getStoredToken()) {
|
|
1304
|
+
console.log(dim(` Not signed in — starting login…
|
|
1305
|
+
`));
|
|
1306
|
+
const { login: login2 } = await Promise.resolve().then(() => (init_login(), exports_login));
|
|
1307
|
+
const loginResult = await login2();
|
|
1308
|
+
if (loginResult !== EXIT.SUCCESS)
|
|
1309
|
+
return loginResult;
|
|
1310
|
+
console.log("");
|
|
1311
|
+
}
|
|
1169
1312
|
try {
|
|
1170
1313
|
const result = await createMesh2(name, {
|
|
1171
1314
|
template: opts.template,
|
|
@@ -1179,22 +1322,23 @@ async function newMesh(name, opts) {
|
|
|
1179
1322
|
console.log(` ${green(icons.check)} You're the owner`);
|
|
1180
1323
|
console.log(` ${green(icons.check)} Joined locally`);
|
|
1181
1324
|
console.log(`
|
|
1182
|
-
|
|
1325
|
+
Share with: claudemesh mesh share
|
|
1183
1326
|
`);
|
|
1184
1327
|
}
|
|
1185
1328
|
return EXIT.SUCCESS;
|
|
1186
1329
|
} catch (err) {
|
|
1187
1330
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1188
|
-
if (msg.includes("
|
|
1189
|
-
console.error(
|
|
1190
|
-
|
|
1331
|
+
if (msg.includes("409") || msg.includes("already exists")) {
|
|
1332
|
+
console.error(` ${icons.cross} A mesh with this name already exists. Try a different name.`);
|
|
1333
|
+
} else {
|
|
1334
|
+
console.error(` ${icons.cross} Failed: ${msg}`);
|
|
1191
1335
|
}
|
|
1192
|
-
console.error(` ${icons.cross} Failed: ${msg}`);
|
|
1193
1336
|
return EXIT.INTERNAL_ERROR;
|
|
1194
1337
|
}
|
|
1195
1338
|
}
|
|
1196
1339
|
var init_new = __esm(() => {
|
|
1197
1340
|
init_facade9();
|
|
1341
|
+
init_facade6();
|
|
1198
1342
|
init_styles();
|
|
1199
1343
|
init_exit_codes();
|
|
1200
1344
|
});
|
|
@@ -3601,7 +3745,7 @@ var init_facade11 = __esm(() => {
|
|
|
3601
3745
|
});
|
|
3602
3746
|
|
|
3603
3747
|
// src/ui/screen.ts
|
|
3604
|
-
import { createInterface as
|
|
3748
|
+
import { createInterface as createInterface3 } from "node:readline";
|
|
3605
3749
|
function termSize() {
|
|
3606
3750
|
return { cols: process.stdout.columns || 80, rows: process.stdout.rows || 24 };
|
|
3607
3751
|
}
|
|
@@ -3629,7 +3773,7 @@ function enterFullScreen() {
|
|
|
3629
3773
|
function exitFullScreen() {
|
|
3630
3774
|
process.stdout.write(SHOW_CURSOR + CLEAR_SCREEN);
|
|
3631
3775
|
}
|
|
3632
|
-
async function menuSelect(itemsOrOpts,
|
|
3776
|
+
async function menuSelect(itemsOrOpts, prompt2 = "Choice") {
|
|
3633
3777
|
const items = Array.isArray(itemsOrOpts) ? itemsOrOpts : itemsOrOpts.items;
|
|
3634
3778
|
const title = !Array.isArray(itemsOrOpts) ? itemsOrOpts.title : undefined;
|
|
3635
3779
|
if (title)
|
|
@@ -3637,9 +3781,9 @@ async function menuSelect(itemsOrOpts, prompt = "Choice") {
|
|
|
3637
3781
|
${title}`);
|
|
3638
3782
|
items.forEach((item, i) => console.log(` ${bold(String(i + 1) + ")")} ${item}`));
|
|
3639
3783
|
console.log("");
|
|
3640
|
-
const rl =
|
|
3784
|
+
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
3641
3785
|
return new Promise((resolve) => {
|
|
3642
|
-
rl.question(` ${
|
|
3786
|
+
rl.question(` ${prompt2} [1]: `, (answer) => {
|
|
3643
3787
|
rl.close();
|
|
3644
3788
|
const idx = parseInt(answer || "1", 10) - 1;
|
|
3645
3789
|
resolve(idx >= 0 && idx < items.length ? idx : 0);
|
|
@@ -3649,7 +3793,7 @@ async function menuSelect(itemsOrOpts, prompt = "Choice") {
|
|
|
3649
3793
|
async function textInput(promptOrOpts, defaultVal = "") {
|
|
3650
3794
|
const label = typeof promptOrOpts === "string" ? promptOrOpts : promptOrOpts.label;
|
|
3651
3795
|
const placeholder = typeof promptOrOpts === "object" ? promptOrOpts.placeholder : undefined;
|
|
3652
|
-
const rl =
|
|
3796
|
+
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
3653
3797
|
return new Promise((resolve) => {
|
|
3654
3798
|
const hint = placeholder ? ` (${placeholder})` : defaultVal ? ` [${defaultVal}]` : "";
|
|
3655
3799
|
rl.question(` ${label}${hint}: `, (answer) => {
|
|
@@ -3661,7 +3805,7 @@ async function textInput(promptOrOpts, defaultVal = "") {
|
|
|
3661
3805
|
async function confirmPrompt(promptOrOpts, defaultYes = true) {
|
|
3662
3806
|
const message = typeof promptOrOpts === "string" ? promptOrOpts : promptOrOpts.message;
|
|
3663
3807
|
const defYes = typeof promptOrOpts === "object" && promptOrOpts.defaultYes !== undefined ? promptOrOpts.defaultYes : defaultYes;
|
|
3664
|
-
const rl =
|
|
3808
|
+
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
3665
3809
|
const hint = defYes ? "[Y/n]" : "[y/N]";
|
|
3666
3810
|
return new Promise((resolve) => {
|
|
3667
3811
|
rl.question(` ${message} ${hint}: `, (answer) => {
|
|
@@ -3776,7 +3920,7 @@ import { randomUUID } from "node:crypto";
|
|
|
3776
3920
|
import { mkdtempSync, writeFileSync as writeFileSync4, rmSync, readdirSync, statSync, existsSync as existsSync4, readFileSync as readFileSync3 } from "node:fs";
|
|
3777
3921
|
import { tmpdir, hostname as hostname3, homedir as homedir3 } from "node:os";
|
|
3778
3922
|
import { join as join3 } from "node:path";
|
|
3779
|
-
import { createInterface as
|
|
3923
|
+
import { createInterface as createInterface4 } from "node:readline";
|
|
3780
3924
|
async function pickMesh(meshes) {
|
|
3781
3925
|
if (meshes.length === 1)
|
|
3782
3926
|
return meshes[0];
|
|
@@ -3786,7 +3930,7 @@ async function pickMesh(meshes) {
|
|
|
3786
3930
|
console.log(` ${i + 1}) ${m.slug}`);
|
|
3787
3931
|
});
|
|
3788
3932
|
console.log("");
|
|
3789
|
-
const rl =
|
|
3933
|
+
const rl = createInterface4({ input: process.stdin, output: process.stdout });
|
|
3790
3934
|
return new Promise((resolve) => {
|
|
3791
3935
|
rl.question(" Choice [1]: ", (answer) => {
|
|
3792
3936
|
rl.close();
|
|
@@ -4028,7 +4172,7 @@ async function runLaunch(flags, rawArgs) {
|
|
|
4028
4172
|
console.log(` ${dim2(`Or join with invite: claudemesh launch --join <url>`)}
|
|
4029
4173
|
`);
|
|
4030
4174
|
const manualPromise = new Promise((resolve) => {
|
|
4031
|
-
const rl =
|
|
4175
|
+
const rl = createInterface4({ input: process.stdin, output: process.stdout });
|
|
4032
4176
|
rl.question(" Paste sync token (or wait for browser): ", (answer) => {
|
|
4033
4177
|
rl.close();
|
|
4034
4178
|
if (answer.trim())
|
|
@@ -4345,7 +4489,7 @@ async function runList() {
|
|
|
4345
4489
|
if (userId) {
|
|
4346
4490
|
const res = await request({
|
|
4347
4491
|
path: `/cli/meshes?user_id=${userId}`,
|
|
4348
|
-
baseUrl:
|
|
4492
|
+
baseUrl: BROKER_HTTP3
|
|
4349
4493
|
});
|
|
4350
4494
|
serverMeshes = res.meshes ?? [];
|
|
4351
4495
|
}
|
|
@@ -4401,14 +4545,14 @@ async function runList() {
|
|
|
4401
4545
|
console.log(dim(` Config: ${getConfigPath()}`));
|
|
4402
4546
|
console.log("");
|
|
4403
4547
|
}
|
|
4404
|
-
var
|
|
4548
|
+
var BROKER_HTTP3;
|
|
4405
4549
|
var init_list2 = __esm(() => {
|
|
4406
4550
|
init_facade();
|
|
4407
4551
|
init_facade6();
|
|
4408
4552
|
init_facade3();
|
|
4409
4553
|
init_urls();
|
|
4410
4554
|
init_styles();
|
|
4411
|
-
|
|
4555
|
+
BROKER_HTTP3 = URLS.BROKER.replace("wss://", "https://").replace("ws://", "http://").replace("/ws", "");
|
|
4412
4556
|
});
|
|
4413
4557
|
|
|
4414
4558
|
// src/commands/delete-mesh.ts
|
|
@@ -4416,31 +4560,50 @@ var exports_delete_mesh = {};
|
|
|
4416
4560
|
__export(exports_delete_mesh, {
|
|
4417
4561
|
deleteMesh: () => deleteMesh
|
|
4418
4562
|
});
|
|
4419
|
-
import { createInterface as
|
|
4420
|
-
function
|
|
4421
|
-
const rl =
|
|
4563
|
+
import { createInterface as createInterface5 } from "node:readline";
|
|
4564
|
+
function prompt2(question) {
|
|
4565
|
+
const rl = createInterface5({ input: process.stdin, output: process.stdout });
|
|
4422
4566
|
return new Promise((resolve) => {
|
|
4423
4567
|
rl.question(question, (a) => {
|
|
4424
4568
|
rl.close();
|
|
4425
|
-
resolve(a.trim()
|
|
4569
|
+
resolve(a.trim());
|
|
4426
4570
|
});
|
|
4427
4571
|
});
|
|
4428
4572
|
}
|
|
4573
|
+
function getUserId(token) {
|
|
4574
|
+
try {
|
|
4575
|
+
const payload = JSON.parse(Buffer.from(token.split(".")[1], "base64url").toString());
|
|
4576
|
+
return payload.sub ?? "";
|
|
4577
|
+
} catch {
|
|
4578
|
+
return "";
|
|
4579
|
+
}
|
|
4580
|
+
}
|
|
4581
|
+
async function isOwner(slug, userId) {
|
|
4582
|
+
try {
|
|
4583
|
+
const res = await request({
|
|
4584
|
+
path: `/cli/meshes?user_id=${userId}`,
|
|
4585
|
+
baseUrl: BROKER_HTTP4
|
|
4586
|
+
});
|
|
4587
|
+
return res.meshes?.find((m) => m.slug === slug)?.is_owner ?? false;
|
|
4588
|
+
} catch {
|
|
4589
|
+
return false;
|
|
4590
|
+
}
|
|
4591
|
+
}
|
|
4429
4592
|
async function deleteMesh(slug, opts = {}) {
|
|
4593
|
+
const config = readConfig();
|
|
4430
4594
|
if (!slug) {
|
|
4431
|
-
const config = readConfig();
|
|
4432
4595
|
if (config.meshes.length === 0) {
|
|
4433
|
-
console.error(" No meshes to
|
|
4596
|
+
console.error(" No meshes to remove.");
|
|
4434
4597
|
return EXIT.NOT_FOUND;
|
|
4435
4598
|
}
|
|
4436
4599
|
console.log(`
|
|
4437
|
-
Select mesh to
|
|
4600
|
+
Select mesh to remove:
|
|
4438
4601
|
`);
|
|
4439
4602
|
config.meshes.forEach((m, i) => {
|
|
4440
4603
|
console.log(` ${bold(String(i + 1) + ")")} ${m.slug} ${dim("(" + m.name + ")")}`);
|
|
4441
4604
|
});
|
|
4442
4605
|
console.log("");
|
|
4443
|
-
const choice = await
|
|
4606
|
+
const choice = await prompt2(" Choice: ");
|
|
4444
4607
|
const idx = parseInt(choice, 10) - 1;
|
|
4445
4608
|
if (idx < 0 || idx >= config.meshes.length) {
|
|
4446
4609
|
console.log(" Cancelled.");
|
|
@@ -4448,48 +4611,72 @@ async function deleteMesh(slug, opts = {}) {
|
|
|
4448
4611
|
}
|
|
4449
4612
|
slug = config.meshes[idx].slug;
|
|
4450
4613
|
}
|
|
4614
|
+
const auth = getStoredToken();
|
|
4615
|
+
const userId = auth ? getUserId(auth.session_token) : "";
|
|
4616
|
+
const ownerCheck = userId ? await isOwner(slug, userId) : false;
|
|
4451
4617
|
if (!opts.yes) {
|
|
4452
4618
|
console.log(`
|
|
4453
|
-
${
|
|
4454
|
-
|
|
4455
|
-
if (
|
|
4456
|
-
console.log("
|
|
4457
|
-
|
|
4458
|
-
}
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4619
|
+
${bold(slug)}
|
|
4620
|
+
`);
|
|
4621
|
+
if (ownerCheck) {
|
|
4622
|
+
console.log(` ${bold("1)")} Remove from this device only ${dim("(keep on server)")}`);
|
|
4623
|
+
console.log(` ${bold("2)")} ${red("Delete everywhere")} ${dim("(removes for all members)")}`);
|
|
4624
|
+
console.log(` ${bold("3)")} Cancel`);
|
|
4625
|
+
console.log("");
|
|
4626
|
+
const choice = await prompt2(" Choice [1]: ") || "1";
|
|
4627
|
+
if (choice === "3") {
|
|
4628
|
+
console.log(" Cancelled.");
|
|
4629
|
+
return EXIT.USER_CANCELLED;
|
|
4630
|
+
}
|
|
4631
|
+
if (choice === "2") {
|
|
4632
|
+
console.log(`
|
|
4633
|
+
${red("Warning:")} This will delete ${bold(slug)} for all members.`);
|
|
4634
|
+
const confirm = await prompt2(` Type "${slug}" to confirm: `);
|
|
4635
|
+
if (confirm.toLowerCase() !== slug.toLowerCase()) {
|
|
4636
|
+
console.log(" Cancelled.");
|
|
4637
|
+
return EXIT.USER_CANCELLED;
|
|
4638
|
+
}
|
|
4639
|
+
try {
|
|
4640
|
+
await request({
|
|
4641
|
+
path: `/cli/mesh/${slug}`,
|
|
4642
|
+
method: "DELETE",
|
|
4643
|
+
body: { user_id: userId },
|
|
4644
|
+
baseUrl: BROKER_HTTP4
|
|
4645
|
+
});
|
|
4646
|
+
console.log(` ${green(icons.check)} Deleted "${slug}" from server.`);
|
|
4647
|
+
} catch (err) {
|
|
4648
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
4649
|
+
console.error(` ${icons.cross} Server delete failed: ${msg}`);
|
|
4650
|
+
}
|
|
4651
|
+
leaveMesh(slug);
|
|
4652
|
+
console.log(` ${green(icons.check)} Removed from local config.`);
|
|
4653
|
+
return EXIT.SUCCESS;
|
|
4654
|
+
}
|
|
4655
|
+
} else {
|
|
4656
|
+
console.log(` ${bold("1)")} Remove from this device ${dim("(you can re-add later)")}`);
|
|
4657
|
+
console.log(` ${bold("2)")} Cancel`);
|
|
4658
|
+
if (!ownerCheck && userId) {
|
|
4659
|
+
console.log(dim(`
|
|
4660
|
+
${yellow(icons.warn)} Only the mesh owner can delete it from the server.`));
|
|
4661
|
+
}
|
|
4662
|
+
console.log("");
|
|
4663
|
+
const choice = await prompt2(" Choice [1]: ") || "1";
|
|
4664
|
+
if (choice === "2") {
|
|
4665
|
+
console.log(" Cancelled.");
|
|
4666
|
+
return EXIT.USER_CANCELLED;
|
|
4485
4667
|
}
|
|
4486
4668
|
}
|
|
4487
4669
|
}
|
|
4488
|
-
leaveMesh(slug);
|
|
4489
|
-
|
|
4670
|
+
const removed = leaveMesh(slug);
|
|
4671
|
+
if (removed) {
|
|
4672
|
+
console.log(` ${green(icons.check)} Removed "${slug}" from this device.`);
|
|
4673
|
+
console.log(dim(` Re-add anytime with: claudemesh mesh add <invite-url>`));
|
|
4674
|
+
} else {
|
|
4675
|
+
console.error(` Mesh "${slug}" not found in local config.`);
|
|
4676
|
+
}
|
|
4490
4677
|
return EXIT.SUCCESS;
|
|
4491
4678
|
}
|
|
4492
|
-
var
|
|
4679
|
+
var BROKER_HTTP4;
|
|
4493
4680
|
var init_delete_mesh = __esm(() => {
|
|
4494
4681
|
init_facade();
|
|
4495
4682
|
init_facade9();
|
|
@@ -4498,7 +4685,7 @@ var init_delete_mesh = __esm(() => {
|
|
|
4498
4685
|
init_urls();
|
|
4499
4686
|
init_styles();
|
|
4500
4687
|
init_exit_codes();
|
|
4501
|
-
|
|
4688
|
+
BROKER_HTTP4 = URLS.BROKER.replace("wss://", "https://").replace("ws://", "http://").replace("/ws", "");
|
|
4502
4689
|
});
|
|
4503
4690
|
|
|
4504
4691
|
// src/commands/rename.ts
|
|
@@ -4561,9 +4748,9 @@ var exports_invite = {};
|
|
|
4561
4748
|
__export(exports_invite, {
|
|
4562
4749
|
invite: () => invite
|
|
4563
4750
|
});
|
|
4564
|
-
import { createInterface as
|
|
4565
|
-
function
|
|
4566
|
-
const rl =
|
|
4751
|
+
import { createInterface as createInterface6 } from "node:readline";
|
|
4752
|
+
function prompt3(question) {
|
|
4753
|
+
const rl = createInterface6({ input: process.stdin, output: process.stdout });
|
|
4567
4754
|
return new Promise((resolve) => {
|
|
4568
4755
|
rl.question(question, (a) => {
|
|
4569
4756
|
rl.close();
|
|
@@ -4594,7 +4781,7 @@ async function invite(email, opts = {}) {
|
|
|
4594
4781
|
console.log(` ${bold(String(i + 1) + ")")} ${m.slug} ${dim("(" + m.name + ")")}`);
|
|
4595
4782
|
});
|
|
4596
4783
|
console.log("");
|
|
4597
|
-
const choice = await
|
|
4784
|
+
const choice = await prompt3(" Choice [1]: ") || "1";
|
|
4598
4785
|
const idx = parseInt(choice, 10) - 1;
|
|
4599
4786
|
meshSlug = config.meshes[idx >= 0 && idx < config.meshes.length ? idx : 0].slug;
|
|
4600
4787
|
}
|
|
@@ -4673,122 +4860,6 @@ var init_welcome = __esm(() => {
|
|
|
4673
4860
|
init_MeshPickerStep();
|
|
4674
4861
|
});
|
|
4675
4862
|
|
|
4676
|
-
// src/commands/login.ts
|
|
4677
|
-
var exports_login = {};
|
|
4678
|
-
__export(exports_login, {
|
|
4679
|
-
login: () => login
|
|
4680
|
-
});
|
|
4681
|
-
import { createInterface as createInterface6 } from "node:readline";
|
|
4682
|
-
function prompt3(question) {
|
|
4683
|
-
const rl = createInterface6({ input: process.stdin, output: process.stdout });
|
|
4684
|
-
return new Promise((resolve) => {
|
|
4685
|
-
rl.question(question, (answer) => {
|
|
4686
|
-
rl.close();
|
|
4687
|
-
resolve(answer.trim());
|
|
4688
|
-
});
|
|
4689
|
-
});
|
|
4690
|
-
}
|
|
4691
|
-
async function loginWithToken() {
|
|
4692
|
-
console.log(`
|
|
4693
|
-
Paste a token from ${dim(URLS.API_BASE + "/token")}`);
|
|
4694
|
-
console.log(` ${dim("Generate one in your browser, then paste it here.")}
|
|
4695
|
-
`);
|
|
4696
|
-
const token = await prompt3(" Token: ");
|
|
4697
|
-
if (!token) {
|
|
4698
|
-
console.error(` ${icons.cross} No token provided.`);
|
|
4699
|
-
return EXIT.AUTH_FAILED;
|
|
4700
|
-
}
|
|
4701
|
-
let user = { id: "", display_name: "", email: "" };
|
|
4702
|
-
try {
|
|
4703
|
-
const parts = token.split(".");
|
|
4704
|
-
if (parts[1]) {
|
|
4705
|
-
const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString());
|
|
4706
|
-
if (payload.exp && payload.exp < Date.now() / 1000) {
|
|
4707
|
-
console.error(` ${icons.cross} Token expired. Generate a new one.`);
|
|
4708
|
-
return EXIT.AUTH_FAILED;
|
|
4709
|
-
}
|
|
4710
|
-
user = {
|
|
4711
|
-
id: payload.sub ?? "",
|
|
4712
|
-
display_name: payload.name ?? payload.email ?? "",
|
|
4713
|
-
email: payload.email ?? ""
|
|
4714
|
-
};
|
|
4715
|
-
}
|
|
4716
|
-
} catch {
|
|
4717
|
-
console.error(` ${icons.cross} Invalid token format.`);
|
|
4718
|
-
return EXIT.AUTH_FAILED;
|
|
4719
|
-
}
|
|
4720
|
-
storeToken({ session_token: token, user, token_source: "manual" });
|
|
4721
|
-
console.log(` ${green(icons.check)} Signed in as ${user.display_name || user.email || "user"}.`);
|
|
4722
|
-
return EXIT.SUCCESS;
|
|
4723
|
-
}
|
|
4724
|
-
async function syncMeshes(token) {
|
|
4725
|
-
try {
|
|
4726
|
-
const meshes = await exports_my.getMeshes(token);
|
|
4727
|
-
if (meshes.length > 0) {
|
|
4728
|
-
const names = meshes.map((m) => m.slug).join(", ");
|
|
4729
|
-
console.log(` ${green(icons.check)} Synced ${meshes.length} mesh${meshes.length === 1 ? "" : "es"}: ${names}`);
|
|
4730
|
-
}
|
|
4731
|
-
} catch {}
|
|
4732
|
-
}
|
|
4733
|
-
async function login() {
|
|
4734
|
-
const existing = getStoredToken();
|
|
4735
|
-
if (existing) {
|
|
4736
|
-
const name = existing.user.display_name || existing.user.email || "unknown";
|
|
4737
|
-
console.log(`
|
|
4738
|
-
Already signed in as ${bold(name)}.`);
|
|
4739
|
-
console.log("");
|
|
4740
|
-
console.log(` ${bold("1)")} Continue as ${name}`);
|
|
4741
|
-
console.log(` ${bold("2)")} Sign in via browser`);
|
|
4742
|
-
console.log(` ${bold("3)")} Paste a token from ${dim("claudemesh.com/token")}`);
|
|
4743
|
-
console.log(` ${bold("4)")} Sign out`);
|
|
4744
|
-
console.log("");
|
|
4745
|
-
const choice = await prompt3(" Choice [1]: ") || "1";
|
|
4746
|
-
if (choice === "1") {
|
|
4747
|
-
console.log(`
|
|
4748
|
-
${green(icons.check)} Continuing as ${name}.`);
|
|
4749
|
-
return EXIT.SUCCESS;
|
|
4750
|
-
}
|
|
4751
|
-
if (choice === "4") {
|
|
4752
|
-
clearToken();
|
|
4753
|
-
console.log(` ${green(icons.check)} Signed out.`);
|
|
4754
|
-
return EXIT.SUCCESS;
|
|
4755
|
-
}
|
|
4756
|
-
if (choice === "3") {
|
|
4757
|
-
clearToken();
|
|
4758
|
-
return loginWithToken();
|
|
4759
|
-
}
|
|
4760
|
-
clearToken();
|
|
4761
|
-
console.log(` ${dim("Signing in…")}`);
|
|
4762
|
-
} else {
|
|
4763
|
-
console.log(`
|
|
4764
|
-
${bold("claudemesh")} — sign in to connect your terminal`);
|
|
4765
|
-
console.log("");
|
|
4766
|
-
console.log(` ${bold("1)")} Sign in via browser ${dim("(opens automatically)")}`);
|
|
4767
|
-
console.log(` ${bold("2)")} Paste a token from ${dim("claudemesh.com/token")}`);
|
|
4768
|
-
console.log("");
|
|
4769
|
-
const choice = await prompt3(" Choice [1]: ") || "1";
|
|
4770
|
-
if (choice === "2") {
|
|
4771
|
-
return loginWithToken();
|
|
4772
|
-
}
|
|
4773
|
-
}
|
|
4774
|
-
try {
|
|
4775
|
-
const result = await loginWithDeviceCode();
|
|
4776
|
-
console.log(` ${green(icons.check)} Signed in as ${result.user.display_name}.`);
|
|
4777
|
-
await syncMeshes(result.session_token);
|
|
4778
|
-
return EXIT.SUCCESS;
|
|
4779
|
-
} catch (err) {
|
|
4780
|
-
console.error(` ${icons.cross} Login failed: ${err instanceof Error ? err.message : err}`);
|
|
4781
|
-
return EXIT.AUTH_FAILED;
|
|
4782
|
-
}
|
|
4783
|
-
}
|
|
4784
|
-
var init_login = __esm(() => {
|
|
4785
|
-
init_facade6();
|
|
4786
|
-
init_facade3();
|
|
4787
|
-
init_styles();
|
|
4788
|
-
init_exit_codes();
|
|
4789
|
-
init_urls();
|
|
4790
|
-
});
|
|
4791
|
-
|
|
4792
4863
|
// src/commands/register.ts
|
|
4793
4864
|
var exports_register = {};
|
|
4794
4865
|
__export(exports_register, {
|
|
@@ -9876,4 +9947,4 @@ main().catch((err) => {
|
|
|
9876
9947
|
process.exit(EXIT.INTERNAL_ERROR);
|
|
9877
9948
|
});
|
|
9878
9949
|
|
|
9879
|
-
//# debugId=
|
|
9950
|
+
//# debugId=7B7B5BCFBFB57ADE64756E2164756E21
|