fix(whatsapp): auto-reconnect after manual login in recovery mode
## Problem After WhatsApp Web disconnects with status codes 428, 503, or 408, Clawdbot does not automatically reconnect. When the reconnect loop reaches maxAttempts (default 12), it exits completely and stops monitoring. A subsequent manual `clawdbot channels login` successfully re-authenticates, but the internal listener is not restarted, requiring a gateway restart to restore functionality. ## Root Cause The `monitorWebChannel` function in `src/web/auto-reply/monitor.ts` breaks out of its main loop when `maxAttempts` is reached, setting `running=false`. The CLI `channels login` command uses `loginWeb()` which only handles authentication - it does not signal the gateway to restart the channel monitoring loop. ## Solution Instead of completely exiting when max attempts is reached, the monitor now enters a 'recovery mode' that: 1. Periodically checks (every 30 seconds) if valid auth exists 2. When auth is detected (e.g., after `clawdbot channels login`), resets reconnect attempts and resumes the monitoring loop automatically 3. Properly handles abort signals during recovery for clean shutdown This makes the system self-healing without requiring gateway restarts after manual re-authentication. ## Testing To verify the fix: 1. Start the gateway with WhatsApp connected 2. Simulate disconnects until max attempts is reached 3. Run `clawdbot channels login` to re-authenticate 4. Verify the gateway automatically resumes monitoring within 30 seconds Fixes: WhatsApp Web auto-reconnect after disconnect
This commit is contained in:
parent
9daa846457
commit
6ec0a6a9a2
@ -22,7 +22,7 @@ import {
|
||||
resolveReconnectPolicy,
|
||||
sleepWithAbort,
|
||||
} from "../reconnect.js";
|
||||
import { formatError, getWebAuthAgeMs, readWebSelfId } from "../session.js";
|
||||
import { formatError, getWebAuthAgeMs, readWebSelfId, webAuthExists } from "../session.js";
|
||||
import { DEFAULT_WEB_MEDIA_BYTES } from "./constants.js";
|
||||
import { whatsappHeartbeatLog, whatsappLog } from "./loggers.js";
|
||||
import { buildMentionConfig } from "./mentions.js";
|
||||
@ -385,6 +385,12 @@ export async function monitorWebChannel(
|
||||
reconnectAttempts += 1;
|
||||
status.reconnectAttempts = reconnectAttempts;
|
||||
emitStatus();
|
||||
|
||||
// Recovery mode: when max attempts is reached, don't exit completely.
|
||||
// Instead, wait longer and periodically check if auth has been refreshed
|
||||
// (e.g., via manual `clawdbot channels login`). This enables self-healing
|
||||
// without requiring a gateway restart.
|
||||
const RECOVERY_CHECK_INTERVAL_MS = 30_000; // Check every 30 seconds in recovery mode
|
||||
if (reconnectPolicy.maxAttempts > 0 && reconnectAttempts >= reconnectPolicy.maxAttempts) {
|
||||
reconnectLogger.warn(
|
||||
{
|
||||
@ -393,13 +399,45 @@ export async function monitorWebChannel(
|
||||
reconnectAttempts,
|
||||
maxAttempts: reconnectPolicy.maxAttempts,
|
||||
},
|
||||
"web reconnect: max attempts reached; continuing in degraded mode",
|
||||
"web reconnect: max attempts reached; entering recovery mode",
|
||||
);
|
||||
runtime.error(
|
||||
`WhatsApp Web reconnect: max attempts reached (${reconnectAttempts}/${reconnectPolicy.maxAttempts}). Stopping web monitoring.`,
|
||||
`WhatsApp Web reconnect: max attempts reached (${reconnectAttempts}/${reconnectPolicy.maxAttempts}). ` +
|
||||
`Entering recovery mode - will auto-resume when auth is refreshed via 'clawdbot channels login'.`,
|
||||
);
|
||||
await closeListener();
|
||||
break;
|
||||
|
||||
// Recovery loop: wait and check for valid auth periodically
|
||||
while (!stopRequested() && !sigintStop) {
|
||||
try {
|
||||
await sleep(RECOVERY_CHECK_INTERVAL_MS, abortSignal);
|
||||
} catch {
|
||||
break;
|
||||
}
|
||||
if (stopRequested() || sigintStop) break;
|
||||
|
||||
// Check if auth has been refreshed (e.g., user ran `clawdbot channels login`)
|
||||
const authValid = await webAuthExists(account.authDir);
|
||||
if (authValid) {
|
||||
reconnectLogger.info(
|
||||
{ connectionId, reconnectAttempts },
|
||||
"web reconnect: auth detected in recovery mode; resetting attempts and resuming",
|
||||
);
|
||||
runtime.error(
|
||||
`WhatsApp Web: Valid auth detected. Resetting reconnect attempts and resuming monitoring.`,
|
||||
);
|
||||
// Reset attempts and continue the main loop to reconnect
|
||||
reconnectAttempts = 0;
|
||||
status.reconnectAttempts = 0;
|
||||
status.lastError = null;
|
||||
emitStatus();
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If we exited recovery due to stop request, break out of main loop
|
||||
if (stopRequested() || sigintStop) break;
|
||||
// Otherwise, continue to the next iteration of the main loop to reconnect
|
||||
continue;
|
||||
}
|
||||
|
||||
const delay = computeBackoff(reconnectPolicy, reconnectAttempts);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user