@clawchatsai/connector 0.0.88 → 0.0.90

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.
@@ -32,6 +32,10 @@ export interface PluginConfig {
32
32
  };
33
33
  sessionSecret?: string;
34
34
  backupCodeHashes?: string[];
35
+ totpPending?: {
36
+ secret: string;
37
+ generatedAt: string;
38
+ };
35
39
  }
36
40
  export interface BridgeConfig {
37
41
  gatewayToken: string;
package/dist/index.js CHANGED
@@ -752,7 +752,7 @@ function formatStatus() {
752
752
  // ---------------------------------------------------------------------------
753
753
  // CLI handlers
754
754
  // ---------------------------------------------------------------------------
755
- async function handleSetup(token) {
755
+ async function handleSetup(token, options = {}) {
756
756
  // Decode base64 token
757
757
  let tokenData;
758
758
  try {
@@ -842,21 +842,36 @@ async function handleSetup(token) {
842
842
  fs.mkdirSync(dataDir, { recursive: true });
843
843
  fs.mkdirSync(uploadsDir, { recursive: true });
844
844
  ws.close();
845
- // Enroll TOTP (interactive — single readline for the whole flow)
846
- const totpOk = await enrollTotp(config);
847
- if (!totpOk) {
845
+ if (options.skipTotp) {
846
+ // Agent-driven flow: skip interactive TOTP enrollment.
847
+ // User will run setup-totp + verify-totp separately.
848
848
  console.log('');
849
- console.log(' ⚠️ TOTP not configured. You can set it up later with: openclaw clawchats reauth');
850
- console.log(' ClawChats will not allow browser connections until 2FA is enabled.');
849
+ console.log(' Setup complete!');
850
+ console.log('');
851
+ console.log(' 2FA setup pending. Run these commands to enable it:');
852
+ console.log(' openclaw clawchats setup-totp');
853
+ console.log(' openclaw clawchats verify-totp <6-digit-code>');
854
+ console.log('');
855
+ console.log(' Then restart: openclaw gateway restart');
856
+ console.log('');
857
+ }
858
+ else {
859
+ // Interactive (human) flow: enroll TOTP now.
860
+ const totpOk = await enrollTotp(config);
861
+ if (!totpOk) {
862
+ console.log('');
863
+ console.log(' ⚠️ TOTP not configured. You can set it up later with: openclaw clawchats reauth');
864
+ console.log(' ClawChats will not allow browser connections until 2FA is enabled.');
865
+ }
866
+ console.log(' ✅ Setup complete!');
867
+ console.log('');
868
+ console.log(' Next steps:');
869
+ console.log(' 1. Restart your gateway: openclaw gateway restart');
870
+ console.log(' (or: systemctl --user restart openclaw-gateway)');
871
+ console.log(' 2. Open ClawChats: https://app.clawchats.ai');
872
+ console.log('');
873
+ console.log(' The gateway will connect automatically after restart.');
851
874
  }
852
- console.log(' ✅ Setup complete!');
853
- console.log('');
854
- console.log(' Next steps:');
855
- console.log(' 1. Restart your gateway: openclaw gateway restart');
856
- console.log(' (or: systemctl --user restart openclaw-gateway)');
857
- console.log(' 2. Open ClawChats: https://app.clawchats.ai');
858
- console.log('');
859
- console.log(' The gateway will connect automatically after restart.');
860
875
  resolve();
861
876
  }
862
877
  else if (msg.type === 'setup-error') {
@@ -985,6 +1000,105 @@ async function handleShowTotp() {
985
1000
  console.log(' 3. When prompted for a TOTP secret, paste the value above');
986
1001
  console.log('');
987
1002
  }
1003
+ // ---------------------------------------------------------------------------
1004
+ // Agent-driven TOTP setup (setup-totp + verify-totp)
1005
+ // ---------------------------------------------------------------------------
1006
+ async function handleSetupTotp() {
1007
+ const config = loadConfig();
1008
+ if (!config) {
1009
+ console.error('ClawChats not configured. Run: openclaw clawchats setup <token> --skip-totp');
1010
+ return;
1011
+ }
1012
+ if (config.schemaVersion >= 2 && config.totp) {
1013
+ console.error('TOTP already active. Use: openclaw clawchats reauth to reset.');
1014
+ return;
1015
+ }
1016
+ // Idempotency: reuse pending secret if generated within the last 24 hours.
1017
+ // Prevents stale-secret issues when the agent retries or the user reruns the command.
1018
+ const PENDING_TTL_MS = 24 * 60 * 60 * 1000;
1019
+ let totpSecret;
1020
+ const existing = config.totpPending;
1021
+ if (existing?.secret && existing.generatedAt) {
1022
+ const age = Date.now() - new Date(existing.generatedAt).getTime();
1023
+ if (age < PENDING_TTL_MS) {
1024
+ totpSecret = existing.secret;
1025
+ }
1026
+ else {
1027
+ // Expired — generate a fresh one
1028
+ totpSecret = generateTotpSecret();
1029
+ config.totpPending = { secret: totpSecret, generatedAt: new Date().toISOString() };
1030
+ saveConfig(config);
1031
+ }
1032
+ }
1033
+ else {
1034
+ totpSecret = generateTotpSecret();
1035
+ config.totpPending = { secret: totpSecret, generatedAt: new Date().toISOString() };
1036
+ saveConfig(config);
1037
+ }
1038
+ const formatted = totpSecret.match(/.{1,4}/g)?.join(' ') || totpSecret;
1039
+ const setupUrl = `${config.serverUrl.replace('wss://', 'https://').replace(/\/ws\/?$/, '')}/totp-setup#${totpSecret}`;
1040
+ console.log('');
1041
+ console.log(' 🔐 ClawChats Two-Factor Authentication Setup');
1042
+ console.log('');
1043
+ console.log(' Open this URL to scan the QR code with your authenticator app:');
1044
+ console.log(` ${setupUrl}`);
1045
+ console.log('');
1046
+ console.log(` Or enter manually: ${formatted}`);
1047
+ console.log('');
1048
+ console.log(' Once added, verify with:');
1049
+ console.log(' openclaw clawchats verify-totp <6-digit-code>');
1050
+ console.log('');
1051
+ }
1052
+ async function handleVerifyTotp(code) {
1053
+ const config = loadConfig();
1054
+ if (!config) {
1055
+ console.error('ClawChats not configured. Run: openclaw clawchats setup <token> --skip-totp');
1056
+ return;
1057
+ }
1058
+ if (config.schemaVersion >= 2 && config.totp) {
1059
+ console.error('TOTP already active. Use: openclaw clawchats reauth to reset.');
1060
+ return;
1061
+ }
1062
+ if (!config.totpPending?.secret) {
1063
+ console.error('No pending TOTP secret. Run: openclaw clawchats setup-totp first.');
1064
+ return;
1065
+ }
1066
+ const step = verifyTotp(code.trim(), config.totpPending.secret, 0);
1067
+ if (step < 0) {
1068
+ console.error(' ❌ Invalid code. Make sure you scanned the correct QR code and try again.');
1069
+ console.error(' Run: openclaw clawchats verify-totp <new-code>');
1070
+ process.exit(1);
1071
+ }
1072
+ // Generate backup codes
1073
+ const { codes, hashes } = generateBackupCodes();
1074
+ console.log('');
1075
+ console.log(' 🔑 Backup codes (save these somewhere safe — one-time use):');
1076
+ for (const backupCode of codes) {
1077
+ console.log(` ${backupCode}`);
1078
+ }
1079
+ console.log('');
1080
+ console.log(' ⚠️ These codes will NOT be shown again.');
1081
+ // Generate session secret and finalize config
1082
+ const sessionSecret = generateSessionSecret();
1083
+ config.totp = {
1084
+ secret: config.totpPending.secret,
1085
+ algorithm: 'SHA1',
1086
+ digits: 6,
1087
+ period: 30,
1088
+ enabledAt: new Date().toISOString(),
1089
+ };
1090
+ config.sessionSecret = sessionSecret;
1091
+ config.backupCodeHashes = hashes;
1092
+ config.schemaVersion = 2;
1093
+ delete config.totpPending;
1094
+ saveConfig(config);
1095
+ console.log('');
1096
+ console.log(' ✅ Two-factor authentication enabled!');
1097
+ console.log('');
1098
+ console.log(' Restart the gateway to apply:');
1099
+ console.log(' openclaw gateway restart');
1100
+ console.log('');
1101
+ }
988
1102
  async function handleReauth() {
989
1103
  const config = loadConfig();
990
1104
  if (!config) {
@@ -1170,11 +1284,18 @@ const plugin = {
1170
1284
  api.registerCli((ctx) => {
1171
1285
  const cmd = ctx.program.command('clawchats');
1172
1286
  cmd.command('setup <token>')
1173
- .description('Set up ClawChats with a setup token')
1174
- .action((token) => handleSetup(String(token)));
1287
+ .description('Set up ClawChats with a setup token (use --skip-totp for agent-driven installs)')
1288
+ .allowUnknownOption()
1289
+ .action((token) => handleSetup(String(token), { skipTotp: process.argv.includes('--skip-totp') }));
1175
1290
  cmd.command('status')
1176
1291
  .description('Show ClawChats connection status')
1177
1292
  .action(() => handleStatus());
1293
+ cmd.command('setup-totp')
1294
+ .description('Generate TOTP QR code for agent-driven 2FA setup (run after setup --skip-totp)')
1295
+ .action(() => handleSetupTotp());
1296
+ cmd.command('verify-totp <code>')
1297
+ .description('Verify TOTP code and finalize 2FA setup (agent-driven flow)')
1298
+ .action((code) => handleVerifyTotp(String(code)));
1178
1299
  cmd.command('reauth')
1179
1300
  .description('Reset two-factor authentication (new TOTP secret + invalidate sessions)')
1180
1301
  .action(() => handleReauth());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawchatsai/connector",
3
- "version": "0.0.88",
3
+ "version": "0.0.90",
4
4
  "type": "module",
5
5
  "description": "ClawChats OpenClaw plugin — P2P tunnel + local API bridge",
6
6
  "main": "dist/index.js",