claudemesh-cli 1.0.0-alpha.1 → 1.0.0-alpha.10

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.
@@ -82,6 +82,12 @@ var init_exit_codes = __esm(() => {
82
82
  });
83
83
 
84
84
  // src/constants/urls.ts
85
+ var exports_urls = {};
86
+ __export(exports_urls, {
87
+ env: () => env,
88
+ VERSION: () => VERSION,
89
+ URLS: () => URLS
90
+ });
85
91
  var URLS, VERSION = "1.0.0-alpha.0", env;
86
92
  var init_urls = __esm(() => {
87
93
  URLS = {
@@ -226,9 +232,6 @@ async function get(path, token) {
226
232
  async function post(path, body, token) {
227
233
  return request({ path, method: "POST", body, token });
228
234
  }
229
- async function del(path, token) {
230
- return request({ path, method: "DELETE", token });
231
- }
232
235
  var init_client = __esm(() => {
233
236
  init_urls();
234
237
  init_timings();
@@ -268,7 +271,13 @@ async function createInvite(token, meshSlug, body) {
268
271
  return post(`/api/my/meshes/${meshSlug}/invites`, body, token);
269
272
  }
270
273
  async function revokeSession(token) {
271
- return del("/api/my/sessions/current", token);
274
+ const BROKER_HTTP = (await Promise.resolve().then(() => (init_urls(), exports_urls))).URLS.BROKER.replace("wss://", "https://").replace("ws://", "http://").replace("/ws", "");
275
+ return request({
276
+ path: "/cli/session/revoke",
277
+ method: "POST",
278
+ body: { token },
279
+ baseUrl: BROKER_HTTP
280
+ });
272
281
  }
273
282
  async function cliSync(token) {
274
283
  return post("/cli-sync", undefined, token);
@@ -288,13 +297,24 @@ async function claimInvite(code, body) {
288
297
  return post(`/api/public/invites/${code}/claim`, body);
289
298
  }
290
299
  async function requestDeviceCode(deviceInfo) {
291
- return post("/api/auth/cli/device-code/new", deviceInfo);
300
+ return request({
301
+ path: "/cli/device-code",
302
+ method: "POST",
303
+ body: deviceInfo,
304
+ baseUrl: BROKER_HTTP
305
+ });
292
306
  }
293
307
  async function pollDeviceCode(deviceCode) {
294
- return get(`/api/auth/cli/device-code/${deviceCode}`);
308
+ return request({
309
+ path: `/cli/device-code/${deviceCode}`,
310
+ baseUrl: BROKER_HTTP
311
+ });
295
312
  }
313
+ var BROKER_HTTP;
296
314
  var init_public = __esm(() => {
297
315
  init_client();
316
+ init_urls();
317
+ BROKER_HTTP = URLS.BROKER.replace("wss://", "https://").replace("ws://", "http://").replace("/ws", "");
298
318
  });
299
319
 
300
320
  // src/services/api/facade.ts
@@ -597,14 +617,26 @@ async function loginWithDeviceCode() {
597
617
  platform: device.platform,
598
618
  arch: device.arch
599
619
  });
600
- log(`
601
- Opening browser for sign-in…
602
- `);
603
- log(` If your browser didn't open, visit:`);
604
- log(` ${verification_url}?code=${user_code}
605
- `);
606
- log(` Waiting for confirmation…
607
- `);
620
+ const url = `${verification_url}?code=${user_code}`;
621
+ const isTTY2 = process.stdout.isTTY && !process.env.NO_COLOR;
622
+ const orange2 = (s) => isTTY2 ? `\x1B[38;5;208m${s}\x1B[0m` : s;
623
+ const bold2 = (s) => isTTY2 ? `\x1B[1m${s}\x1B[0m` : s;
624
+ const dim2 = (s) => isTTY2 ? `\x1B[2m${s}\x1B[0m` : s;
625
+ log("");
626
+ log(" " + orange2("claudemesh") + " — sign in to connect your terminal");
627
+ log("");
628
+ log(" ┌──────────────────────────────────┐");
629
+ log(" │ │");
630
+ log(" │ Your code: " + bold2(user_code) + " │");
631
+ log(" │ │");
632
+ log(" └──────────────────────────────────┘");
633
+ log("");
634
+ log(" " + dim2("Confirm this code matches your browser."));
635
+ log(" " + dim2("If your browser didn't open, visit:"));
636
+ log(" " + dim2(url));
637
+ log("");
638
+ log(" Waiting for confirmation… " + dim2("(Ctrl-C to cancel)"));
639
+ log("");
608
640
  try {
609
641
  await openBrowser(`${verification_url}?code=${user_code}`);
610
642
  } catch {
@@ -1384,17 +1416,103 @@ var exports_login = {};
1384
1416
  __export(exports_login, {
1385
1417
  login: () => login
1386
1418
  });
1419
+ import { createInterface } from "node:readline";
1420
+ function prompt(question) {
1421
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
1422
+ return new Promise((resolve) => {
1423
+ rl.question(question, (answer) => {
1424
+ rl.close();
1425
+ resolve(answer.trim());
1426
+ });
1427
+ });
1428
+ }
1429
+ async function loginWithToken() {
1430
+ console.log(`
1431
+ Paste a token from ${dim(URLS.API_BASE + "/token")}`);
1432
+ console.log(` ${dim("Generate one in your browser, then paste it here.")}
1433
+ `);
1434
+ const token = await prompt(" Token: ");
1435
+ if (!token) {
1436
+ console.error(` ${icons.cross} No token provided.`);
1437
+ return EXIT.AUTH_FAILED;
1438
+ }
1439
+ let user = { id: "", display_name: "", email: "" };
1440
+ try {
1441
+ const parts = token.split(".");
1442
+ if (parts[1]) {
1443
+ const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString());
1444
+ if (payload.exp && payload.exp < Date.now() / 1000) {
1445
+ console.error(` ${icons.cross} Token expired. Generate a new one.`);
1446
+ return EXIT.AUTH_FAILED;
1447
+ }
1448
+ user = {
1449
+ id: payload.sub ?? "",
1450
+ display_name: payload.name ?? payload.email ?? "",
1451
+ email: payload.email ?? ""
1452
+ };
1453
+ }
1454
+ } catch {
1455
+ console.error(` ${icons.cross} Invalid token format.`);
1456
+ return EXIT.AUTH_FAILED;
1457
+ }
1458
+ storeToken({ session_token: token, user, token_source: "manual" });
1459
+ console.log(` ${green(icons.check)} Signed in as ${user.display_name || user.email || "user"}.`);
1460
+ return EXIT.SUCCESS;
1461
+ }
1462
+ async function syncMeshes(token) {
1463
+ try {
1464
+ const meshes = await exports_my.getMeshes(token);
1465
+ if (meshes.length > 0) {
1466
+ const names = meshes.map((m) => m.slug).join(", ");
1467
+ console.log(` ${green(icons.check)} Synced ${meshes.length} mesh${meshes.length === 1 ? "" : "es"}: ${names}`);
1468
+ }
1469
+ } catch {}
1470
+ }
1387
1471
  async function login() {
1472
+ const existing = getStoredToken();
1473
+ if (existing) {
1474
+ const name = existing.user.display_name || existing.user.email || "unknown";
1475
+ console.log(`
1476
+ Already signed in as ${bold(name)}.`);
1477
+ console.log("");
1478
+ console.log(` ${bold("1)")} Continue as ${name}`);
1479
+ console.log(` ${bold("2)")} Sign in via browser`);
1480
+ console.log(` ${bold("3)")} Paste a token from ${dim("claudemesh.com/token")}`);
1481
+ console.log(` ${bold("4)")} Sign out`);
1482
+ console.log("");
1483
+ const choice = await prompt(" Choice [1]: ") || "1";
1484
+ if (choice === "1") {
1485
+ console.log(`
1486
+ ${green(icons.check)} Continuing as ${name}.`);
1487
+ return EXIT.SUCCESS;
1488
+ }
1489
+ if (choice === "4") {
1490
+ clearToken();
1491
+ console.log(` ${green(icons.check)} Signed out.`);
1492
+ return EXIT.SUCCESS;
1493
+ }
1494
+ if (choice === "3") {
1495
+ clearToken();
1496
+ return loginWithToken();
1497
+ }
1498
+ clearToken();
1499
+ console.log(` ${dim("Signing in…")}`);
1500
+ } else {
1501
+ console.log(`
1502
+ ${bold("claudemesh")} — sign in to connect your terminal`);
1503
+ console.log("");
1504
+ console.log(` ${bold("1)")} Sign in via browser ${dim("(opens automatically)")}`);
1505
+ console.log(` ${bold("2)")} Paste a token from ${dim("claudemesh.com/token")}`);
1506
+ console.log("");
1507
+ const choice = await prompt(" Choice [1]: ") || "1";
1508
+ if (choice === "2") {
1509
+ return loginWithToken();
1510
+ }
1511
+ }
1388
1512
  try {
1389
1513
  const result = await loginWithDeviceCode();
1390
1514
  console.log(` ${green(icons.check)} Signed in as ${result.user.display_name}.`);
1391
- try {
1392
- const meshes = await exports_my.getMeshes(result.session_token);
1393
- if (meshes.length > 0) {
1394
- const names = meshes.map((m) => m.slug).join(", ");
1395
- console.log(` ${green(icons.check)} Synced ${meshes.length} mesh${meshes.length === 1 ? "" : "es"}: ${names}`);
1396
- }
1397
- } catch {}
1515
+ await syncMeshes(result.session_token);
1398
1516
  return EXIT.SUCCESS;
1399
1517
  } catch (err) {
1400
1518
  console.error(` ${icons.cross} Login failed: ${err instanceof Error ? err.message : err}`);
@@ -1406,6 +1524,7 @@ var init_login = __esm(() => {
1406
1524
  init_facade2();
1407
1525
  init_styles();
1408
1526
  init_exit_codes();
1527
+ init_urls();
1409
1528
  });
1410
1529
 
1411
1530
  // src/commands/register.ts
@@ -1414,48 +1533,10 @@ __export(exports_register, {
1414
1533
  register: () => register2
1415
1534
  });
1416
1535
  async function register2() {
1417
- try {
1418
- const listener = await startCallbackListener();
1419
- console.log(`
1420
- Opening browser for account signup…
1421
- `);
1422
- const url = `https://claudemesh.com/register?source=cli&callback=http://localhost:${listener.port}`;
1423
- try {
1424
- await openBrowser(url);
1425
- } catch {
1426
- console.log(` Could not open browser. Visit:
1427
- ${url}
1428
- `);
1429
- }
1430
- console.log(` Waiting for signup to complete…
1431
- `);
1432
- const token = await Promise.race([
1433
- listener.token,
1434
- new Promise((_, reject) => setTimeout(() => reject(new Error("Timed out waiting for signup (5 min). Try again.")), 5 * 60 * 1000))
1435
- ]).finally(() => listener.close());
1436
- let user = { id: "", display_name: "", email: "" };
1437
- try {
1438
- user = await exports_my.getProfile(token);
1439
- } catch {}
1440
- storeToken({
1441
- session_token: token,
1442
- user,
1443
- token_source: "callback"
1444
- });
1445
- const name = user.display_name || user.email || "you";
1446
- console.log(` ${green(icons.check)} Account created. Signed in as ${name}.`);
1447
- return EXIT.SUCCESS;
1448
- } catch (err) {
1449
- console.error(` ${icons.cross} Registration failed: ${err instanceof Error ? err.message : err}`);
1450
- return EXIT.AUTH_FAILED;
1451
- }
1536
+ return login();
1452
1537
  }
1453
1538
  var init_register = __esm(() => {
1454
- init_facade6();
1455
- init_facade2();
1456
- init_facade4();
1457
- init_styles();
1458
- init_exit_codes();
1539
+ init_login();
1459
1540
  });
1460
1541
 
1461
1542
  // src/commands/welcome.ts
@@ -1464,13 +1545,13 @@ __export(exports_welcome, {
1464
1545
  runWelcome: () => runWelcome,
1465
1546
  _stub: () => runWelcome
1466
1547
  });
1467
- import { createInterface } from "node:readline";
1548
+ import { createInterface as createInterface2 } from "node:readline";
1468
1549
  async function runWelcome() {
1469
1550
  const config = readConfig();
1470
1551
  if (config.meshes.length > 0)
1471
1552
  return EXIT.SUCCESS;
1472
1553
  renderWelcome();
1473
- const rl = createInterface({ input: process.stdin, output: process.stdout });
1554
+ const rl = createInterface2({ input: process.stdin, output: process.stdout });
1474
1555
  return new Promise((resolve) => {
1475
1556
  rl.question(" Choice [1]: ", async (answer) => {
1476
1557
  rl.close();
@@ -3532,7 +3613,7 @@ var init_facade9 = __esm(() => {
3532
3613
  });
3533
3614
 
3534
3615
  // src/ui/screen.ts
3535
- import { createInterface as createInterface2 } from "node:readline";
3616
+ import { createInterface as createInterface3 } from "node:readline";
3536
3617
  function termSize() {
3537
3618
  return { cols: process.stdout.columns || 80, rows: process.stdout.rows || 24 };
3538
3619
  }
@@ -3560,37 +3641,46 @@ function enterFullScreen() {
3560
3641
  function exitFullScreen() {
3561
3642
  process.stdout.write(SHOW_CURSOR + CLEAR_SCREEN);
3562
3643
  }
3563
- async function menuSelect(items, prompt = "Choice") {
3644
+ async function menuSelect(itemsOrOpts, prompt2 = "Choice") {
3645
+ const items = Array.isArray(itemsOrOpts) ? itemsOrOpts : itemsOrOpts.items;
3646
+ const title = !Array.isArray(itemsOrOpts) ? itemsOrOpts.title : undefined;
3647
+ if (title)
3648
+ console.log(`
3649
+ ${title}`);
3564
3650
  items.forEach((item, i) => console.log(` ${bold(String(i + 1) + ")")} ${item}`));
3565
3651
  console.log("");
3566
- const rl = createInterface2({ input: process.stdin, output: process.stdout });
3652
+ const rl = createInterface3({ input: process.stdin, output: process.stdout });
3567
3653
  return new Promise((resolve) => {
3568
- rl.question(` ${prompt} [1]: `, (answer) => {
3654
+ rl.question(` ${prompt2} [1]: `, (answer) => {
3569
3655
  rl.close();
3570
3656
  const idx = parseInt(answer || "1", 10) - 1;
3571
3657
  resolve(idx >= 0 && idx < items.length ? idx : 0);
3572
3658
  });
3573
3659
  });
3574
3660
  }
3575
- async function textInput(prompt, defaultVal = "") {
3576
- const rl = createInterface2({ input: process.stdin, output: process.stdout });
3661
+ async function textInput(promptOrOpts, defaultVal = "") {
3662
+ const label = typeof promptOrOpts === "string" ? promptOrOpts : promptOrOpts.label;
3663
+ const placeholder = typeof promptOrOpts === "object" ? promptOrOpts.placeholder : undefined;
3664
+ const rl = createInterface3({ input: process.stdin, output: process.stdout });
3577
3665
  return new Promise((resolve) => {
3578
- const hint = defaultVal ? ` [${defaultVal}]` : "";
3579
- rl.question(` ${prompt}${hint}: `, (answer) => {
3666
+ const hint = placeholder ? ` (${placeholder})` : defaultVal ? ` [${defaultVal}]` : "";
3667
+ rl.question(` ${label}${hint}: `, (answer) => {
3580
3668
  rl.close();
3581
3669
  resolve(answer.trim() || defaultVal);
3582
3670
  });
3583
3671
  });
3584
3672
  }
3585
- async function confirmPrompt(prompt, defaultYes = true) {
3586
- const rl = createInterface2({ input: process.stdin, output: process.stdout });
3587
- const hint = defaultYes ? "[Y/n]" : "[y/N]";
3673
+ async function confirmPrompt(promptOrOpts, defaultYes = true) {
3674
+ const message = typeof promptOrOpts === "string" ? promptOrOpts : promptOrOpts.message;
3675
+ const defYes = typeof promptOrOpts === "object" && promptOrOpts.defaultYes !== undefined ? promptOrOpts.defaultYes : defaultYes;
3676
+ const rl = createInterface3({ input: process.stdin, output: process.stdout });
3677
+ const hint = defYes ? "[Y/n]" : "[y/N]";
3588
3678
  return new Promise((resolve) => {
3589
- rl.question(` ${prompt} ${hint}: `, (answer) => {
3679
+ rl.question(` ${message} ${hint}: `, (answer) => {
3590
3680
  rl.close();
3591
3681
  const a = answer.trim().toLowerCase();
3592
3682
  if (!a)
3593
- resolve(defaultYes);
3683
+ resolve(defYes);
3594
3684
  else
3595
3685
  resolve(a === "y" || a === "yes");
3596
3686
  });
@@ -3698,7 +3788,7 @@ import { randomUUID } from "node:crypto";
3698
3788
  import { mkdtempSync, writeFileSync as writeFileSync4, rmSync, readdirSync, statSync, existsSync as existsSync4, readFileSync as readFileSync3 } from "node:fs";
3699
3789
  import { tmpdir, hostname as hostname3, homedir as homedir3 } from "node:os";
3700
3790
  import { join as join3 } from "node:path";
3701
- import { createInterface as createInterface3 } from "node:readline";
3791
+ import { createInterface as createInterface4 } from "node:readline";
3702
3792
  async function pickMesh(meshes) {
3703
3793
  if (meshes.length === 1)
3704
3794
  return meshes[0];
@@ -3708,7 +3798,7 @@ async function pickMesh(meshes) {
3708
3798
  console.log(` ${i + 1}) ${m.slug}`);
3709
3799
  });
3710
3800
  console.log("");
3711
- const rl = createInterface3({ input: process.stdin, output: process.stdout });
3801
+ const rl = createInterface4({ input: process.stdin, output: process.stdout });
3712
3802
  return new Promise((resolve) => {
3713
3803
  rl.question(" Choice [1]: ", (answer) => {
3714
3804
  rl.close();
@@ -3950,7 +4040,7 @@ async function runLaunch(flags, rawArgs) {
3950
4040
  console.log(` ${dim2(`Or join with invite: claudemesh launch --join <url>`)}
3951
4041
  `);
3952
4042
  const manualPromise = new Promise((resolve) => {
3953
- const rl = createInterface3({ input: process.stdin, output: process.stdout });
4043
+ const rl = createInterface4({ input: process.stdin, output: process.stdout });
3954
4044
  rl.question(" Paste sync token (or wait for browser): ", (answer) => {
3955
4045
  rl.close();
3956
4046
  if (answer.trim())
@@ -7668,7 +7758,7 @@ var init_rename2 = __esm(() => {
7668
7758
 
7669
7759
  // src/commands/connect.ts
7670
7760
  import { hostname as hostname4 } from "node:os";
7671
- import { createInterface as createInterface4 } from "node:readline";
7761
+ import { createInterface as createInterface5 } from "node:readline";
7672
7762
  async function pickMesh2(meshes) {
7673
7763
  console.log(`
7674
7764
  Select mesh:`);
@@ -7676,7 +7766,7 @@ async function pickMesh2(meshes) {
7676
7766
  console.log(` ${i + 1}) ${m.slug}`);
7677
7767
  });
7678
7768
  console.log("");
7679
- const rl = createInterface4({ input: process.stdin, output: process.stdout });
7769
+ const rl = createInterface5({ input: process.stdin, output: process.stdout });
7680
7770
  return new Promise((resolve) => {
7681
7771
  rl.question(" Choice [1]: ", (answer) => {
7682
7772
  rl.close();
@@ -8971,7 +9061,7 @@ var exports_sync = {};
8971
9061
  __export(exports_sync, {
8972
9062
  runSync: () => runSync
8973
9063
  });
8974
- import { createInterface as createInterface5 } from "node:readline";
9064
+ import { createInterface as createInterface6 } from "node:readline";
8975
9065
  import { hostname as hostname5 } from "node:os";
8976
9066
  async function runSync(args) {
8977
9067
  const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
@@ -8985,7 +9075,7 @@ async function runSync(args) {
8985
9075
  console.log(dim2(`Visit: ${url}`));
8986
9076
  await openBrowser(url);
8987
9077
  const manualPromise = new Promise((resolve2) => {
8988
- const rl = createInterface5({ input: process.stdin, output: process.stdout });
9078
+ const rl = createInterface6({ input: process.stdin, output: process.stdout });
8989
9079
  rl.question("Paste sync token (or wait for browser): ", (answer) => {
8990
9080
  rl.close();
8991
9081
  if (answer.trim())
@@ -10620,4 +10710,4 @@ main().catch((err) => {
10620
10710
  process.exit(EXIT.INTERNAL_ERROR);
10621
10711
  });
10622
10712
 
10623
- //# debugId=1E53C7F6AC10DB9F64756E2164756E21
10713
+ //# debugId=A4C7B40E17EDD0C564756E2164756E21