From d6f07c9f919ff1f7f396b7713bec3fe62cb8e6f3 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 26 Dec 2025 09:08:37 +0000 Subject: [PATCH] chore: fix lint after logging tweaks --- src/agents/model-selection.test.ts | 5 ++- src/infra/heartbeat-runner.test.ts | 3 +- src/infra/heartbeat-runner.ts | 50 ++++++++++++++++-------------- src/infra/heartbeat-wake.ts | 5 ++- src/web/auto-reply.ts | 6 ++-- 5 files changed, 39 insertions(+), 30 deletions(-) diff --git a/src/agents/model-selection.test.ts b/src/agents/model-selection.test.ts index 021aa6ff1..23d3eaf04 100644 --- a/src/agents/model-selection.test.ts +++ b/src/agents/model-selection.test.ts @@ -30,7 +30,10 @@ describe("resolveConfiguredModelRef", () => { defaultModel: DEFAULT_MODEL, }); - expect(resolved).toEqual({ provider: "anthropic", model: "claude-opus-4-5" }); + expect(resolved).toEqual({ + provider: "anthropic", + model: "claude-opus-4-5", + }); }); it("falls back to defaults when agent.model is missing", () => { diff --git a/src/infra/heartbeat-runner.test.ts b/src/infra/heartbeat-runner.test.ts index 36f63a4ea..ad26c65db 100644 --- a/src/infra/heartbeat-runner.test.ts +++ b/src/infra/heartbeat-runner.test.ts @@ -1,7 +1,6 @@ import { describe, expect, it } from "vitest"; - -import type { ClawdisConfig } from "../config/config.js"; import { HEARTBEAT_PROMPT } from "../auto-reply/heartbeat.js"; +import type { ClawdisConfig } from "../config/config.js"; import { resolveHeartbeatDeliveryTarget, resolveHeartbeatIntervalMs, diff --git a/src/infra/heartbeat-runner.ts b/src/infra/heartbeat-runner.ts index dc0045c1d..5d937a4c9 100644 --- a/src/infra/heartbeat-runner.ts +++ b/src/infra/heartbeat-runner.ts @@ -1,5 +1,8 @@ import { chunkText } from "../auto-reply/chunk.js"; -import { HEARTBEAT_PROMPT, stripHeartbeatToken } from "../auto-reply/heartbeat.js"; +import { + HEARTBEAT_PROMPT, + stripHeartbeatToken, +} from "../auto-reply/heartbeat.js"; import { getReplyFromConfig } from "../auto-reply/reply.js"; import type { ReplyPayload } from "../auto-reply/types.js"; import { parseDurationMs } from "../cli/parse-duration.js"; @@ -8,21 +11,21 @@ import { loadConfig } from "../config/config.js"; import { loadSessionStore, resolveStorePath, - saveSessionStore, type SessionEntry, + saveSessionStore, } from "../config/sessions.js"; import { formatErrorMessage } from "../infra/errors.js"; import { createSubsystemLogger } from "../logging.js"; import { getQueueSize } from "../process/command-queue.js"; import { defaultRuntime, type RuntimeEnv } from "../runtime.js"; -import { normalizeE164 } from "../utils.js"; import { sendMessageTelegram } from "../telegram/send.js"; +import { normalizeE164 } from "../utils.js"; import { sendMessageWhatsApp } from "../web/outbound.js"; import { emitHeartbeatEvent } from "./heartbeat-events.js"; import { + type HeartbeatRunResult, requestHeartbeatNow, setHeartbeatWakeHandler, - type HeartbeatRunResult, } from "./heartbeat-wake.js"; export type HeartbeatTarget = "last" | "whatsapp" | "telegram" | "none"; @@ -93,7 +96,7 @@ function resolveHeartbeatSender(params: { lastTo?.trim(), lastChannel === "telegram" && lastTo ? `telegram:${lastTo}` : undefined, lastChannel === "whatsapp" && lastTo ? `whatsapp:${lastTo}` : undefined, - ].filter((val): val is string => Boolean(val && val.trim())); + ].filter((val): val is string => Boolean(val?.trim())); const allowList = allowFrom .map((entry) => String(entry)) @@ -156,23 +159,8 @@ export function resolveHeartbeatDeliveryTarget(params: { (target === "last" ? lastTo : undefined); if (!channel || !to) { - return { channel: "none", reason: "no-target" }; -} - -async function restoreHeartbeatUpdatedAt(params: { - storePath: string; - sessionKey: string; - updatedAt?: number; -}) { - const { storePath, sessionKey, updatedAt } = params; - if (typeof updatedAt !== "number") return; - const store = loadSessionStore(storePath); - const entry = store[sessionKey]; - if (!entry) return; - if (entry.updatedAt === updatedAt) return; - store[sessionKey] = { ...entry, updatedAt }; - await saveSessionStore(storePath, store); -} + return { channel: "none", reason: "no-target" }; + } if (channel !== "whatsapp") { return { channel, to }; @@ -190,6 +178,21 @@ async function restoreHeartbeatUpdatedAt(params: { return { channel, to: allowFrom[0], reason: "allowFrom-fallback" }; } +async function restoreHeartbeatUpdatedAt(params: { + storePath: string; + sessionKey: string; + updatedAt?: number; +}) { + const { storePath, sessionKey, updatedAt } = params; + if (typeof updatedAt !== "number") return; + const store = loadSessionStore(storePath); + const entry = store[sessionKey]; + if (!entry) return; + if (entry.updatedAt === updatedAt) return; + store[sessionKey] = { ...entry, updatedAt }; + await saveSessionStore(storePath, store); +} + function normalizeHeartbeatReply( payload: ReplyPayload, responsePrefix?: string, @@ -334,7 +337,8 @@ export async function runHeartbeatOnce(opts: { const delivery = resolveHeartbeatDeliveryTarget({ cfg, entry }); const mediaUrls = - replyPayload.mediaUrls ?? (replyPayload.mediaUrl ? [replyPayload.mediaUrl] : []); + replyPayload.mediaUrls ?? + (replyPayload.mediaUrl ? [replyPayload.mediaUrl] : []); if (delivery.channel === "none" || !delivery.to) { emitHeartbeatEvent({ diff --git a/src/infra/heartbeat-wake.ts b/src/infra/heartbeat-wake.ts index 39c09e7c8..88a20cb4b 100644 --- a/src/infra/heartbeat-wake.ts +++ b/src/infra/heartbeat-wake.ts @@ -58,7 +58,10 @@ export function setHeartbeatWakeHandler(next: HeartbeatWakeHandler | null) { } } -export function requestHeartbeatNow(opts?: { reason?: string; coalesceMs?: number }) { +export function requestHeartbeatNow(opts?: { + reason?: string; + coalesceMs?: number; +}) { pendingReason = opts?.reason ?? pendingReason ?? "requested"; schedule(opts?.coalesceMs ?? DEFAULT_COALESCE_MS); } diff --git a/src/web/auto-reply.ts b/src/web/auto-reply.ts index 0393386d2..a3adbc5f6 100644 --- a/src/web/auto-reply.ts +++ b/src/web/auto-reply.ts @@ -4,11 +4,11 @@ import { normalizeGroupActivation, parseActivationCommand, } from "../auto-reply/group-activation.js"; -import { getReplyFromConfig } from "../auto-reply/reply.js"; import { HEARTBEAT_PROMPT, stripHeartbeatToken, } from "../auto-reply/heartbeat.js"; +import { getReplyFromConfig } from "../auto-reply/reply.js"; import { HEARTBEAT_TOKEN, SILENT_REPLY_TOKEN } from "../auto-reply/tokens.js"; import type { ReplyPayload } from "../auto-reply/types.js"; import { waitForever } from "../cli/wait.js"; @@ -876,7 +876,7 @@ export async function monitorWebProvider( let watchdogTimer: NodeJS.Timeout | null = null; let lastMessageAt: number | null = null; let handledMessages = 0; - let lastInboundMsg: WebInboundMsg | null = null; + let _lastInboundMsg: WebInboundMsg | null = null; // Watchdog to detect stuck message processing (e.g., event emitter died) // Should be significantly longer than the reply heartbeat interval to avoid false positives @@ -1184,7 +1184,7 @@ export async function monitorWebProvider( status.lastMessageAt = lastMessageAt; status.lastEventAt = lastMessageAt; emitStatus(); - lastInboundMsg = msg; + _lastInboundMsg = msg; const conversationId = msg.conversationId ?? msg.from; // Same-phone mode logging retained