@clawchatsai/connector 0.0.55 β†’ 0.0.57

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 +76 -21
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -785,8 +785,21 @@ async function handleSetup(token) {
785
785
  fs.mkdirSync(dataDir, { recursive: true });
786
786
  fs.mkdirSync(uploadsDir, { recursive: true });
787
787
  ws.close();
788
+ // Ask if user wants to reuse TOTP from another gateway
789
+ let reuseSecret;
790
+ if (config.schemaVersion === 1) {
791
+ const rlSetup = (await import('node:readline')).createInterface({ input: process.stdin, output: process.stdout });
792
+ const askSetup = (q) => new Promise(r => rlSetup.question(q, r));
793
+ console.log('');
794
+ console.log(' πŸ’‘ Already have ClawChats on another gateway?');
795
+ console.log(' Run \`openclaw clawchats show-totp\` on that machine and paste the secret below.');
796
+ const reuseAnswer = await askSetup(' Paste existing TOTP secret to reuse it (or press Enter to set up new): ');
797
+ rlSetup.close();
798
+ if (reuseAnswer.trim())
799
+ reuseSecret = reuseAnswer.trim();
800
+ }
788
801
  // Enroll TOTP (interactive β€” requires stdin)
789
- const totpOk = await enrollTotp(config);
802
+ const totpOk = await enrollTotp(config, reuseSecret);
790
803
  if (!totpOk) {
791
804
  console.log('');
792
805
  console.log(' ⚠️ TOTP not configured. You can set it up later with: openclaw clawchats reauth');
@@ -813,29 +826,38 @@ async function handleSetup(token) {
813
826
  });
814
827
  });
815
828
  }
816
- async function enrollTotp(config) {
829
+ async function enrollTotp(config, existingSecret) {
817
830
  const readline = await import('node:readline');
818
831
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
819
832
  const ask = (q) => new Promise(r => rl.question(q, r));
820
833
  try {
821
- // Generate TOTP secret
822
- const totpSecret = generateTotpSecret();
823
- const email = config.google?.authorizedEmail || config.userId;
824
- const otpauthUri = buildOtpauthUri(totpSecret, email);
825
- // Format secret with spaces for readability
826
- const formatted = totpSecret.match(/.{1,4}/g)?.join(' ') || totpSecret;
827
- console.log('');
828
- console.log(' πŸ” Setting up two-factor authentication');
829
- console.log('');
830
- console.log(' Open this link to scan the QR code with your authenticator app:');
831
- console.log(` ${config.serverUrl.replace('wss://', 'https://').replace(/\/ws\/?$/, '')}/totp-setup#${totpSecret}`);
832
- console.log('');
833
- console.log(` Or enter this code manually: ${formatted}`);
834
- console.log('');
835
- console.log(" Don't have an authenticator app?");
836
- console.log(' Google Authenticator: https://apps.apple.com/app/google-authenticator/id388497605');
837
- console.log(' https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2');
838
- console.log('');
834
+ let totpSecret;
835
+ if (existingSecret) {
836
+ // Reusing secret from another gateway β€” strip spaces, uppercase
837
+ totpSecret = existingSecret.replace(/\s+/g, '').toUpperCase();
838
+ console.log('');
839
+ console.log(' πŸ” Verifying existing TOTP secret…');
840
+ console.log('');
841
+ }
842
+ else {
843
+ // Generate a brand new TOTP secret
844
+ totpSecret = generateTotpSecret();
845
+ const email = config.google?.authorizedEmail || config.userId;
846
+ void buildOtpauthUri(totpSecret, email); // keep import used
847
+ const formatted = totpSecret.match(/.{1,4}/g)?.join(' ') || totpSecret;
848
+ console.log('');
849
+ console.log(' πŸ” Setting up two-factor authentication');
850
+ console.log('');
851
+ console.log(' Open this link to scan the QR code with your authenticator app:');
852
+ console.log(` ${config.serverUrl.replace('wss://', 'https://').replace(/\/ws\/?$/, '')}/totp-setup#${totpSecret}`);
853
+ console.log('');
854
+ console.log(` Or enter this code manually: ${formatted}`);
855
+ console.log('');
856
+ console.log(" Don't have an authenticator app?");
857
+ console.log(' Google Authenticator: https://apps.apple.com/app/google-authenticator/id388497605');
858
+ console.log(' https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2');
859
+ console.log('');
860
+ }
839
861
  // Verification loop
840
862
  let verified = false;
841
863
  for (let attempt = 0; attempt < 5; attempt++) {
@@ -886,6 +908,27 @@ async function enrollTotp(config) {
886
908
  return false;
887
909
  }
888
910
  }
911
+ async function handleShowTotp() {
912
+ const config = loadConfig();
913
+ if (!config) {
914
+ console.error('ClawChats not configured. Run: openclaw clawchats setup <token>');
915
+ return;
916
+ }
917
+ if (!config.totp?.secret) {
918
+ console.error('No TOTP secret found. Run: openclaw clawchats reauth to set one up first.');
919
+ return;
920
+ }
921
+ console.log('');
922
+ console.log('Your TOTP secret (account-level, keep this safe):');
923
+ console.log('');
924
+ console.log(` ${config.totp.secret}`);
925
+ console.log('');
926
+ console.log('To reuse this on a new gateway:');
927
+ console.log(' 1. Generate a setup token at login.clawchats.ai/dashboard');
928
+ console.log(' 2. On the new machine: openclaw clawchats setup <token>');
929
+ console.log(' 3. When prompted for a TOTP secret, paste the value above');
930
+ console.log('');
931
+ }
889
932
  async function handleReauth() {
890
933
  const config = loadConfig();
891
934
  if (!config) {
@@ -896,7 +939,16 @@ async function handleReauth() {
896
939
  console.log('');
897
940
  console.log(' ⚠️ This will invalidate all existing sessions.');
898
941
  console.log(' All connected browsers will need to re-authenticate.');
899
- const success = await enrollTotp(config);
942
+ console.log('');
943
+ const readline = await import('node:readline');
944
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
945
+ const ask = (q) => new Promise(r => rl.question(q, r));
946
+ let existingSecret;
947
+ const reuseAnswer = await ask(' Reuse TOTP from another gateway? Paste secret (or press Enter to generate new): ');
948
+ rl.close();
949
+ if (reuseAnswer.trim())
950
+ existingSecret = reuseAnswer.trim();
951
+ const success = await enrollTotp(config, existingSecret);
900
952
  if (success) {
901
953
  console.log(' All previous sessions have been invalidated.');
902
954
  console.log(' Restart the gateway for changes to take effect: systemctl --user restart openclaw-gateway');
@@ -1073,6 +1125,9 @@ const plugin = {
1073
1125
  cmd.command('reauth')
1074
1126
  .description('Reset two-factor authentication (new TOTP secret + invalidate sessions)')
1075
1127
  .action(() => handleReauth());
1128
+ cmd.command('show-totp')
1129
+ .description('Show your TOTP secret (use when adding ClawChats to a second gateway)')
1130
+ .action(() => handleShowTotp());
1076
1131
  cmd.command('reset')
1077
1132
  .description('Disconnect and remove all ClawChats data')
1078
1133
  .action(() => handleReset());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawchatsai/connector",
3
- "version": "0.0.55",
3
+ "version": "0.0.57",
4
4
  "type": "module",
5
5
  "description": "ClawChats OpenClaw plugin β€” P2P tunnel + local API bridge",
6
6
  "main": "dist/index.js",