fix: skip whatsapp heartbeat when provider inactive

This commit is contained in:
Peter Steinberger
2025-12-27 19:34:01 +00:00
parent a61c27c4d0
commit 3a485a14a4
3 changed files with 104 additions and 1 deletions

View File

@@ -18,9 +18,11 @@ import { sendMessageDiscord } from "../discord/send.js";
import { formatErrorMessage } from "../infra/errors.js";
import { createSubsystemLogger } from "../logging.js";
import { getQueueSize } from "../process/command-queue.js";
import { webAuthExists } from "../providers/web/index.js";
import { defaultRuntime, type RuntimeEnv } from "../runtime.js";
import { sendMessageTelegram } from "../telegram/send.js";
import { normalizeE164 } from "../utils.js";
import { getActiveWebListener } from "../web/active-listener.js";
import { sendMessageWhatsApp } from "../web/outbound.js";
import { emitHeartbeatEvent } from "./heartbeat-events.js";
import {
@@ -49,6 +51,8 @@ type HeartbeatDeps = {
sendDiscord?: typeof sendMessageDiscord;
getQueueSize?: (lane?: string) => number;
nowMs?: () => number;
webAuthExists?: () => Promise<boolean>;
hasActiveWebListener?: () => boolean;
};
const log = createSubsystemLogger("gateway/heartbeat");
@@ -143,6 +147,26 @@ function resolveHeartbeatSender(params: {
return candidates[0] ?? "heartbeat";
}
async function resolveWhatsAppReadiness(
cfg: ClawdisConfig,
deps?: HeartbeatDeps,
): Promise<{ ok: boolean; reason: string }> {
if (cfg.web?.enabled === false) {
return { ok: false, reason: "whatsapp-disabled" };
}
const authExists = await (deps?.webAuthExists ?? webAuthExists)();
if (!authExists) {
return { ok: false, reason: "whatsapp-not-linked" };
}
const listenerActive = deps?.hasActiveWebListener
? deps.hasActiveWebListener()
: Boolean(getActiveWebListener());
if (!listenerActive) {
return { ok: false, reason: "whatsapp-not-running" };
}
return { ok: true, reason: "ok" };
}
export function resolveHeartbeatDeliveryTarget(params: {
cfg: ClawdisConfig;
entry?: SessionEntry;
@@ -392,6 +416,23 @@ export async function runHeartbeatOnce(opts: {
return { status: "ran", durationMs: Date.now() - startedAt };
}
if (delivery.channel === "whatsapp") {
const readiness = await resolveWhatsAppReadiness(cfg, opts.deps);
if (!readiness.ok) {
emitHeartbeatEvent({
status: "skipped",
reason: readiness.reason,
preview: normalized.text?.slice(0, 200),
durationMs: Date.now() - startedAt,
hasMedia: mediaUrls.length > 0,
});
log.info("heartbeat: whatsapp not ready", {
reason: readiness.reason,
});
return { status: "skipped", reason: readiness.reason };
}
}
const deps = {
sendWhatsApp: opts.deps?.sendWhatsApp ?? sendMessageWhatsApp,
sendTelegram: opts.deps?.sendTelegram ?? sendMessageTelegram,