ardabot 0.1.0 → 0.2.0

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.
Files changed (2) hide show
  1. package/dist/index.js +72 -15
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -227,6 +227,22 @@ var ApiClient = class {
227
227
  }
228
228
  return await res.json();
229
229
  }
230
+ /**
231
+ * Recover an account using a recovery phrase.
232
+ * Returns a JWT token or throws on invalid phrase.
233
+ */
234
+ async recover(recoveryPhrase) {
235
+ const res = await fetch(`${this.baseUrl}/api/v1/auth/recover`, {
236
+ method: "POST",
237
+ headers: this.authHeaders(),
238
+ body: JSON.stringify({ recoveryPhrase })
239
+ });
240
+ if (!res.ok) {
241
+ const err = await res.json();
242
+ throw new Error(err.error.message);
243
+ }
244
+ return await res.json();
245
+ }
230
246
  // =========================================================================
231
247
  // Account endpoints (JWT auth)
232
248
  // =========================================================================
@@ -451,33 +467,45 @@ async function loginCommand(options) {
451
467
  const promoCode = options.promo ?? gateResult.promoCode;
452
468
  const action = await promptChoice(rl, "What would you like to do?", [
453
469
  "Link existing account",
454
- "Sign up"
470
+ "Sign up",
471
+ "Recover account"
455
472
  ]);
456
473
  if (action === null) return;
474
+ if (action === 3) {
475
+ const recovered = await handleRecoverAccount(rl, client);
476
+ if (recovered) {
477
+ console.log(chalk.green("\nYou're ready to go! Run `ardabot chat` to talk to your agent.\n"));
478
+ }
479
+ return;
480
+ }
457
481
  const authOptions = action === 2 ? ["SMS", "Telegram", "CLI only"] : ["SMS", "Telegram"];
458
482
  const authMethod = await promptChoice(rl, "How would you like to verify?", authOptions);
459
483
  if (authMethod === null) return;
460
484
  let jwt;
485
+ let recoveryPhrase;
461
486
  const isAnonymous = action === 2 && authMethod === 3;
462
487
  if (authMethod === 1) {
463
488
  const result = await authenticateViaSms(rl, client);
464
489
  if (result === null) return;
465
490
  jwt = result.jwt;
491
+ recoveryPhrase = result.recoveryPhrase;
466
492
  } else if (authMethod === 2) {
467
493
  const result = await authenticateViaTelegram(rl, client);
468
494
  if (result === null) return;
469
495
  jwt = result.jwt;
496
+ recoveryPhrase = result.recoveryPhrase;
470
497
  } else {
471
498
  const result = await authenticateViaCli(rl, client);
472
499
  if (result === null) return;
473
500
  jwt = result.jwt;
501
+ recoveryPhrase = result.recoveryPhrase;
474
502
  }
475
503
  client.setJwt(jwt);
476
504
  setJwt(jwt);
477
505
  if (action === 1) {
478
506
  await handleLinkExisting(client);
479
507
  } else {
480
- await handleSignUp(rl, client, promoCode, isAnonymous);
508
+ await handleSignUp(rl, client, promoCode, isAnonymous, recoveryPhrase);
481
509
  }
482
510
  console.log(chalk.green("\nYou're ready to go! Run `ardabot chat` to talk to your agent.\n"));
483
511
  } finally {
@@ -520,10 +548,10 @@ async function authenticateViaSms(rl, client) {
520
548
  return null;
521
549
  }
522
550
  retrySpinner.succeed(retryResult.isNew ? "Account created \u2014 welcome!" : "Welcome back!");
523
- return { jwt: retryResult.token, isNew: retryResult.isNew };
551
+ return { jwt: retryResult.token, isNew: retryResult.isNew, recoveryPhrase: retryResult.recoveryPhrase };
524
552
  }
525
553
  verifySpinner.succeed(result.isNew ? "Account created \u2014 welcome!" : "Welcome back!");
526
- return { jwt: result.token, isNew: result.isNew };
554
+ return { jwt: result.token, isNew: result.isNew, recoveryPhrase: result.recoveryPhrase };
527
555
  } catch (err) {
528
556
  verifySpinner.fail("Couldn't verify that code");
529
557
  console.log(chalk.red(err.message));
@@ -555,10 +583,10 @@ async function authenticateViaTelegram(rl, client) {
555
583
  return null;
556
584
  }
557
585
  retrySpinner.succeed(retryResult.isNew ? "Account created \u2014 welcome!" : "Welcome back!");
558
- return { jwt: retryResult.token, isNew: retryResult.isNew };
586
+ return { jwt: retryResult.token, isNew: retryResult.isNew, recoveryPhrase: retryResult.recoveryPhrase };
559
587
  }
560
588
  verifySpinner.succeed(result.isNew ? "Account created \u2014 welcome!" : "Welcome back!");
561
- return { jwt: result.token, isNew: result.isNew };
589
+ return { jwt: result.token, isNew: result.isNew, recoveryPhrase: result.recoveryPhrase };
562
590
  } catch (err) {
563
591
  verifySpinner.fail("Couldn't verify that code");
564
592
  console.log(chalk.red(err.message));
@@ -582,10 +610,10 @@ async function authenticateViaCli(rl, client) {
582
610
  return null;
583
611
  }
584
612
  retrySpinner.succeed("Account created \u2014 welcome!");
585
- return { jwt: retryResult.token };
613
+ return { jwt: retryResult.token, recoveryPhrase: retryResult.recoveryPhrase };
586
614
  }
587
615
  spinner.succeed("Account created \u2014 welcome!");
588
- return { jwt: result.token };
616
+ return { jwt: result.token, recoveryPhrase: result.recoveryPhrase };
589
617
  } catch (err) {
590
618
  spinner.fail("Couldn't create account");
591
619
  console.log(chalk.red(err.message));
@@ -609,7 +637,7 @@ async function handleLinkExisting(client) {
609
637
  }
610
638
  await createCliApiKey(client);
611
639
  }
612
- async function handleSignUp(_rl, client, promoCode, isAnonymous = false) {
640
+ async function handleSignUp(_rl, client, promoCode, isAnonymous = false, recoveryPhrase) {
613
641
  if (promoCode) {
614
642
  const promoSpinner = ora({ text: "Redeeming promo code...", discardStdin: false }).start();
615
643
  try {
@@ -657,7 +685,29 @@ async function handleSignUp(_rl, client, promoCode, isAnonymous = false) {
657
685
  return;
658
686
  }
659
687
  instanceSpinner.succeed("Agent is running!");
660
- await createCliApiKey(client, isAnonymous);
688
+ await createCliApiKey(client, isAnonymous, recoveryPhrase);
689
+ }
690
+ async function handleRecoverAccount(rl, client) {
691
+ console.log(chalk.cyan("\nEnter your 6-word recovery phrase.\n"));
692
+ const phrase = await prompt(rl, "Recovery phrase:\n");
693
+ const trimmed = phrase.trim();
694
+ if (!trimmed) {
695
+ console.log(chalk.red("Please enter your recovery phrase."));
696
+ return false;
697
+ }
698
+ const spinner = ora({ text: "Recovering account...", discardStdin: false }).start();
699
+ try {
700
+ const result = await client.recover(trimmed);
701
+ spinner.succeed("Account recovered!");
702
+ client.setJwt(result.token);
703
+ setJwt(result.token);
704
+ await handleLinkExisting(client);
705
+ return true;
706
+ } catch (err) {
707
+ spinner.fail("Couldn't recover account");
708
+ console.log(chalk.red(err.message));
709
+ return false;
710
+ }
661
711
  }
662
712
  var POLL_INTERVAL_MS = 3e3;
663
713
  var POLL_TIMEOUT_MS = 5 * 60 * 1e3;
@@ -695,19 +745,26 @@ async function waitForInstance(client) {
695
745
  function sleep(ms) {
696
746
  return new Promise((resolve) => setTimeout(resolve, ms));
697
747
  }
698
- async function createCliApiKey(client, isAnonymous = false) {
748
+ async function createCliApiKey(client, isAnonymous = false, recoveryPhrase) {
699
749
  const keySpinner = ora({ text: "Setting up CLI access...", discardStdin: false }).start();
700
750
  try {
701
751
  const { key } = await client.createApiKeyForInstance("cli");
702
752
  setApiKey(key);
703
753
  keySpinner.succeed("All set!");
704
- if (isAnonymous) {
754
+ if (isAnonymous && recoveryPhrase) {
705
755
  console.log();
706
- console.log(chalk.yellow.bold(" Important: Save your API key!"));
756
+ console.log(chalk.yellow.bold(" Important: Save your recovery phrase!"));
707
757
  console.log(chalk.yellow(" Your account has no linked phone or Telegram."));
708
- console.log(chalk.yellow(" If you lose access, run `ardabot devices` to link one."));
758
+ console.log(chalk.yellow(" This is the ONLY way to recover your account."));
759
+ console.log();
760
+ console.log(` Recovery phrase: ${chalk.cyan(recoveryPhrase)}`);
761
+ console.log();
762
+ console.log(chalk.dim(" Write it down and keep it safe."));
763
+ console.log();
764
+ } else if (recoveryPhrase) {
709
765
  console.log();
710
- console.log(` API key: ${chalk.cyan(key)}`);
766
+ console.log(chalk.dim(` Recovery phrase: ${recoveryPhrase}`));
767
+ console.log(chalk.dim(" Save this if you want an alternative way to recover your account."));
711
768
  console.log();
712
769
  }
713
770
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ardabot",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Terminal client for the Arda platform",
5
5
  "author": "r4v3n LLC",
6
6
  "license": "SEE LICENSE IN LICENSE",