@clawchatsai/connector 0.0.54 β 0.0.56
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/gateway-bridge.d.ts +1 -0
- package/dist/index.js +73 -21
- package/dist/signaling-client.d.ts +6 -1
- package/dist/signaling-client.js +7 -1
- package/package.json +1 -1
package/dist/gateway-bridge.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -213,7 +213,16 @@ async function startClawChats(ctx, api, mediaStash) {
|
|
|
213
213
|
}
|
|
214
214
|
});
|
|
215
215
|
// 5. Connect to signaling server
|
|
216
|
-
|
|
216
|
+
const _hostname = (() => { try {
|
|
217
|
+
return require('os').hostname();
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
return undefined;
|
|
221
|
+
} })();
|
|
222
|
+
signaling = new SignalingClient(config.serverUrl, config.userId, config.apiKey, {
|
|
223
|
+
gatewayId: config.gatewayId,
|
|
224
|
+
hostname: _hostname,
|
|
225
|
+
});
|
|
217
226
|
signaling.on('connected', () => {
|
|
218
227
|
ctx.logger.info('Connected to signaling server');
|
|
219
228
|
});
|
|
@@ -755,6 +764,7 @@ async function handleSetup(token) {
|
|
|
755
764
|
userId: msg.userId,
|
|
756
765
|
serverUrl: tokenData.serverUrl,
|
|
757
766
|
apiKey,
|
|
767
|
+
gatewayId: msg.gatewayId,
|
|
758
768
|
gatewayToken,
|
|
759
769
|
schemaVersion: 1,
|
|
760
770
|
installedAt: new Date().toISOString(),
|
|
@@ -803,29 +813,38 @@ async function handleSetup(token) {
|
|
|
803
813
|
});
|
|
804
814
|
});
|
|
805
815
|
}
|
|
806
|
-
async function enrollTotp(config) {
|
|
816
|
+
async function enrollTotp(config, existingSecret) {
|
|
807
817
|
const readline = await import('node:readline');
|
|
808
818
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
809
819
|
const ask = (q) => new Promise(r => rl.question(q, r));
|
|
810
820
|
try {
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
821
|
+
let totpSecret;
|
|
822
|
+
if (existingSecret) {
|
|
823
|
+
// Reusing secret from another gateway β strip spaces, uppercase
|
|
824
|
+
totpSecret = existingSecret.replace(/\s+/g, '').toUpperCase();
|
|
825
|
+
console.log('');
|
|
826
|
+
console.log(' π Verifying existing TOTP secretβ¦');
|
|
827
|
+
console.log('');
|
|
828
|
+
}
|
|
829
|
+
else {
|
|
830
|
+
// Generate a brand new TOTP secret
|
|
831
|
+
totpSecret = generateTotpSecret();
|
|
832
|
+
const email = config.google?.authorizedEmail || config.userId;
|
|
833
|
+
void buildOtpauthUri(totpSecret, email); // keep import used
|
|
834
|
+
const formatted = totpSecret.match(/.{1,4}/g)?.join(' ') || totpSecret;
|
|
835
|
+
console.log('');
|
|
836
|
+
console.log(' π Setting up two-factor authentication');
|
|
837
|
+
console.log('');
|
|
838
|
+
console.log(' Open this link to scan the QR code with your authenticator app:');
|
|
839
|
+
console.log(` ${config.serverUrl.replace('wss://', 'https://').replace(/\/ws\/?$/, '')}/totp-setup#${totpSecret}`);
|
|
840
|
+
console.log('');
|
|
841
|
+
console.log(` Or enter this code manually: ${formatted}`);
|
|
842
|
+
console.log('');
|
|
843
|
+
console.log(" Don't have an authenticator app?");
|
|
844
|
+
console.log(' Google Authenticator: https://apps.apple.com/app/google-authenticator/id388497605');
|
|
845
|
+
console.log(' https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2');
|
|
846
|
+
console.log('');
|
|
847
|
+
}
|
|
829
848
|
// Verification loop
|
|
830
849
|
let verified = false;
|
|
831
850
|
for (let attempt = 0; attempt < 5; attempt++) {
|
|
@@ -876,6 +895,27 @@ async function enrollTotp(config) {
|
|
|
876
895
|
return false;
|
|
877
896
|
}
|
|
878
897
|
}
|
|
898
|
+
async function handleShowTotp() {
|
|
899
|
+
const config = loadConfig();
|
|
900
|
+
if (!config) {
|
|
901
|
+
console.error('ClawChats not configured. Run: openclaw clawchats setup <token>');
|
|
902
|
+
return;
|
|
903
|
+
}
|
|
904
|
+
if (!config.totp?.secret) {
|
|
905
|
+
console.error('No TOTP secret found. Run: openclaw clawchats reauth to set one up first.');
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
console.log('');
|
|
909
|
+
console.log('Your TOTP secret (account-level, keep this safe):');
|
|
910
|
+
console.log('');
|
|
911
|
+
console.log(` ${config.totp.secret}`);
|
|
912
|
+
console.log('');
|
|
913
|
+
console.log('To reuse this on a new gateway:');
|
|
914
|
+
console.log(' 1. Generate a setup token at login.clawchats.ai/dashboard');
|
|
915
|
+
console.log(' 2. On the new machine: openclaw clawchats setup <token>');
|
|
916
|
+
console.log(' 3. When prompted for a TOTP secret, paste the value above');
|
|
917
|
+
console.log('');
|
|
918
|
+
}
|
|
879
919
|
async function handleReauth() {
|
|
880
920
|
const config = loadConfig();
|
|
881
921
|
if (!config) {
|
|
@@ -886,7 +926,16 @@ async function handleReauth() {
|
|
|
886
926
|
console.log('');
|
|
887
927
|
console.log(' β οΈ This will invalidate all existing sessions.');
|
|
888
928
|
console.log(' All connected browsers will need to re-authenticate.');
|
|
889
|
-
|
|
929
|
+
console.log('');
|
|
930
|
+
const readline = await import('node:readline');
|
|
931
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
932
|
+
const ask = (q) => new Promise(r => rl.question(q, r));
|
|
933
|
+
let existingSecret;
|
|
934
|
+
const reuseAnswer = await ask(' Reuse TOTP from another gateway? Paste secret (or press Enter to generate new): ');
|
|
935
|
+
rl.close();
|
|
936
|
+
if (reuseAnswer.trim())
|
|
937
|
+
existingSecret = reuseAnswer.trim();
|
|
938
|
+
const success = await enrollTotp(config, existingSecret);
|
|
890
939
|
if (success) {
|
|
891
940
|
console.log(' All previous sessions have been invalidated.');
|
|
892
941
|
console.log(' Restart the gateway for changes to take effect: systemctl --user restart openclaw-gateway');
|
|
@@ -1063,6 +1112,9 @@ const plugin = {
|
|
|
1063
1112
|
cmd.command('reauth')
|
|
1064
1113
|
.description('Reset two-factor authentication (new TOTP secret + invalidate sessions)')
|
|
1065
1114
|
.action(() => handleReauth());
|
|
1115
|
+
cmd.command('show-totp')
|
|
1116
|
+
.description('Show your TOTP secret (use when adding ClawChats to a second gateway)')
|
|
1117
|
+
.action(() => handleShowTotp());
|
|
1066
1118
|
cmd.command('reset')
|
|
1067
1119
|
.description('Disconnect and remove all ClawChats data')
|
|
1068
1120
|
.action(() => handleReset());
|
|
@@ -17,6 +17,8 @@ export declare class SignalingClient extends EventEmitter {
|
|
|
17
17
|
private readonly serverUrl;
|
|
18
18
|
private readonly userId;
|
|
19
19
|
private readonly apiKey;
|
|
20
|
+
private readonly gatewayId?;
|
|
21
|
+
private readonly hostname?;
|
|
20
22
|
private ws;
|
|
21
23
|
/** True only after gateway-auth-ok has been received. */
|
|
22
24
|
private _connected;
|
|
@@ -31,7 +33,10 @@ export declare class SignalingClient extends EventEmitter {
|
|
|
31
33
|
private reconnectTimer;
|
|
32
34
|
/** Timer handle for ping-timeout watchdog. */
|
|
33
35
|
private pingWatchdog;
|
|
34
|
-
constructor(serverUrl: string, userId: string, apiKey: string
|
|
36
|
+
constructor(serverUrl: string, userId: string, apiKey: string, opts?: {
|
|
37
|
+
gatewayId?: string;
|
|
38
|
+
hostname?: string;
|
|
39
|
+
});
|
|
35
40
|
/** Returns true when gateway-auth-ok has been received on the current socket. */
|
|
36
41
|
get isConnected(): boolean;
|
|
37
42
|
/**
|
package/dist/signaling-client.js
CHANGED
|
@@ -33,6 +33,8 @@ export class SignalingClient extends EventEmitter {
|
|
|
33
33
|
serverUrl;
|
|
34
34
|
userId;
|
|
35
35
|
apiKey;
|
|
36
|
+
gatewayId;
|
|
37
|
+
hostname;
|
|
36
38
|
ws = null;
|
|
37
39
|
/** True only after gateway-auth-ok has been received. */
|
|
38
40
|
_connected = false;
|
|
@@ -47,11 +49,13 @@ export class SignalingClient extends EventEmitter {
|
|
|
47
49
|
reconnectTimer = null;
|
|
48
50
|
/** Timer handle for ping-timeout watchdog. */
|
|
49
51
|
pingWatchdog = null;
|
|
50
|
-
constructor(serverUrl, userId, apiKey) {
|
|
52
|
+
constructor(serverUrl, userId, apiKey, opts) {
|
|
51
53
|
super();
|
|
52
54
|
this.serverUrl = serverUrl;
|
|
53
55
|
this.userId = userId;
|
|
54
56
|
this.apiKey = apiKey;
|
|
57
|
+
this.gatewayId = opts?.gatewayId;
|
|
58
|
+
this.hostname = opts?.hostname;
|
|
55
59
|
}
|
|
56
60
|
// -------------------------------------------------------------------------
|
|
57
61
|
// Public API
|
|
@@ -132,6 +136,8 @@ export class SignalingClient extends EventEmitter {
|
|
|
132
136
|
userId: this.userId,
|
|
133
137
|
apiKey: this.apiKey,
|
|
134
138
|
pluginVersion: PLUGIN_VERSION,
|
|
139
|
+
...(this.gatewayId ? { gatewayId: this.gatewayId } : {}),
|
|
140
|
+
...(this.hostname ? { hostname: this.hostname } : {}),
|
|
135
141
|
});
|
|
136
142
|
// Resolve the connect() promise: the socket is open and auth is in flight
|
|
137
143
|
settle();
|