feat: update openclaw and polish desktop flows
This commit is contained in:
@@ -5,6 +5,12 @@ import { EventEmitter } from 'events';
|
||||
import { existsSync, mkdirSync, rmSync, readdirSync } from 'fs';
|
||||
import { deflateSync } from 'zlib';
|
||||
import { getOpenClawDir, getOpenClawResolvedDir } from './paths';
|
||||
import { getAllSettings } from './store';
|
||||
import {
|
||||
isSocksProxyUrl,
|
||||
redactProxyUrlForLog,
|
||||
resolveWhatsAppProxyUrl,
|
||||
} from './whatsapp-proxy';
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
@@ -76,6 +82,32 @@ type ConnectionState = {
|
||||
const QRCode = QRCodeModule;
|
||||
const QRErrorCorrectLevel = QRErrorCorrectLevelModule;
|
||||
|
||||
function loadProxyAgentConstructor(proxyUrl: string) {
|
||||
const moduleName = isSocksProxyUrl(proxyUrl) ? 'socks-proxy-agent' : 'https-proxy-agent';
|
||||
const agentModule = require(resolveOpenClawModule(moduleName));
|
||||
return agentModule.SocksProxyAgent
|
||||
|| agentModule.HttpsProxyAgent
|
||||
|| agentModule.default
|
||||
|| agentModule;
|
||||
}
|
||||
|
||||
async function createWhatsAppSocketAgent(): Promise<unknown | undefined> {
|
||||
let settings: Awaited<ReturnType<typeof getAllSettings>>;
|
||||
try {
|
||||
settings = await getAllSettings();
|
||||
} catch (error) {
|
||||
console.warn('[WhatsAppLogin] Failed to read proxy settings; connecting directly', error);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const proxyUrl = resolveWhatsAppProxyUrl(settings);
|
||||
if (!proxyUrl) return undefined;
|
||||
|
||||
const AgentCtor = loadProxyAgentConstructor(proxyUrl);
|
||||
console.log(`[WhatsAppLogin] Using proxy for WhatsApp WebSocket: ${redactProxyUrlForLog(proxyUrl)}`);
|
||||
return new AgentCtor(proxyUrl);
|
||||
}
|
||||
|
||||
function createQrMatrix(input: string) {
|
||||
const qr = new QRCode(-1, QRErrorCorrectLevel.L);
|
||||
qr.addData(input);
|
||||
@@ -201,6 +233,7 @@ export class WhatsAppLoginManager extends EventEmitter {
|
||||
private loginSucceeded: boolean = false;
|
||||
private retryCount: number = 0;
|
||||
private maxRetries: number = 5;
|
||||
private lastConnectionError: string | null = null;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@@ -242,10 +275,16 @@ export class WhatsAppLoginManager extends EventEmitter {
|
||||
this.loginSucceeded = false;
|
||||
this.qr = null;
|
||||
this.retryCount = 0;
|
||||
this.lastConnectionError = null;
|
||||
|
||||
await this.connectToWhatsApp(accountId);
|
||||
}
|
||||
|
||||
private buildConnectionFailureMessage(fallback: string): string {
|
||||
const details = this.lastConnectionError ? ` Last error: ${this.lastConnectionError}` : '';
|
||||
return `${fallback}. Check network connectivity or enable a proxy in Advanced Settings.${details}`;
|
||||
}
|
||||
|
||||
private async connectToWhatsApp(accountId: string): Promise<void> {
|
||||
if (!this.active) return;
|
||||
|
||||
@@ -292,6 +331,7 @@ export class WhatsAppLoginManager extends EventEmitter {
|
||||
const { version } = await fetchLatestBaileysVersion();
|
||||
|
||||
console.log(`[WhatsAppLogin] Starting login for ${accountId}, version: ${version}`);
|
||||
const socketAgent = await createWhatsAppSocketAgent();
|
||||
|
||||
this.socket = makeWASocket({
|
||||
version,
|
||||
@@ -299,6 +339,7 @@ export class WhatsAppLoginManager extends EventEmitter {
|
||||
printQRInTerminal: false,
|
||||
logger: pino({ level: 'silent' }), // Silent logger
|
||||
connectTimeoutMs: 60000,
|
||||
...(socketAgent ? { agent: socketAgent } : {}),
|
||||
// mobile: false,
|
||||
// browser: ['ClawX', 'Chrome', '1.0.0'],
|
||||
});
|
||||
@@ -333,6 +374,8 @@ export class WhatsAppLoginManager extends EventEmitter {
|
||||
if (connection === 'close') {
|
||||
const error = lastDisconnect?.error as BaileysError | undefined;
|
||||
const statusCode = error?.output?.statusCode;
|
||||
this.lastConnectionError = error?.message
|
||||
|| (statusCode ? `statusCode=${statusCode}` : this.lastConnectionError);
|
||||
const isLoggedOut = statusCode === DisconnectReason.loggedOut;
|
||||
// Treat 401 as transient if we haven't exhausted retries (max 2 attempts)
|
||||
// This handles the case where WhatsApp's session hasn't fully released
|
||||
@@ -351,7 +394,7 @@ export class WhatsAppLoginManager extends EventEmitter {
|
||||
} else {
|
||||
console.log('[WhatsAppLogin] Max retries reached, stopping.');
|
||||
this.active = false;
|
||||
this.emit('error', 'Connection failed after multiple retries');
|
||||
this.emit('error', this.buildConnectionFailureMessage('Connection failed after multiple retries'));
|
||||
}
|
||||
} else {
|
||||
// Logged out or explicitly stopped
|
||||
@@ -384,6 +427,12 @@ export class WhatsAppLoginManager extends EventEmitter {
|
||||
}
|
||||
} catch (innerErr) {
|
||||
console.error('[WhatsAppLogin] Error in connection update:', innerErr);
|
||||
const msg = innerErr instanceof Error ? innerErr.message : String(innerErr);
|
||||
this.lastConnectionError = msg;
|
||||
if (this.active) {
|
||||
this.active = false;
|
||||
this.emit('error', this.buildConnectionFailureMessage('Failed to generate WhatsApp QR code'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -395,7 +444,8 @@ export class WhatsAppLoginManager extends EventEmitter {
|
||||
} else {
|
||||
this.active = false;
|
||||
const msg = error instanceof Error ? error.message : String(error);
|
||||
this.emit('error', msg);
|
||||
this.lastConnectionError = msg;
|
||||
this.emit('error', this.buildConnectionFailureMessage('Failed to start WhatsApp login'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -408,6 +458,7 @@ export class WhatsAppLoginManager extends EventEmitter {
|
||||
const cleanupAccountId = this.accountId;
|
||||
this.active = false;
|
||||
this.qr = null;
|
||||
this.lastConnectionError = null;
|
||||
if (this.socket) {
|
||||
try {
|
||||
// Remove listeners to prevent handling closure as error
|
||||
|
||||
Reference in New Issue
Block a user