diff --git a/CHANGELOG.md b/CHANGELOG.md index ba6829ada..c4a655c12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## 1.2.3 — Unreleased +### Bug Fixes +- **Empty result field handling:** Fixed bug where Claude CLI returning `result: ""` (empty string) would cause raw JSON to be sent to WhatsApp instead of being treated as valid empty output. Changed truthy check to explicit type check in `command-reply.ts`. +- **Response prefix on heartbeat replies:** Fixed `responsePrefix` (e.g., `🦞`) not being applied to heartbeat alert messages. The prefix was only applied in the regular message handler, not in `runReplyHeartbeat`. + ### Changes - **Auto-recovery from stuck WhatsApp sessions:** Added watchdog timer that detects when WhatsApp event emitter stops firing (e.g., after Bad MAC decryption errors) and automatically restarts the connection after 30 minutes of no message activity. Heartbeat logging now includes `minutesSinceLastMessage` and warns when >30 minutes without messages. The 30-minute timeout is intentionally longer than typical `heartbeatMinutes` configs to avoid false positives. - **Early allowFrom filtering:** Unauthorized senders are now blocked in `inbound.ts` BEFORE encryption/decryption attempts, preventing Bad MAC errors from corrupting session state. Previously, messages from unauthorized senders would trigger decryption failures that could silently kill the event emitter. diff --git a/src/auto-reply/command-reply.ts b/src/auto-reply/command-reply.ts index 914f25d96..4d8b7141f 100644 --- a/src/auto-reply/command-reply.ts +++ b/src/auto-reply/command-reply.ts @@ -230,7 +230,7 @@ export async function runCommandReply( `Claude JSON raw: ${JSON.stringify(parsed.parsed, null, 2)}`, ); } - if (parsed?.text) { + if (typeof parsed?.text === "string") { logVerbose( `Claude JSON parsed -> ${parsed.text.slice(0, 120)}${parsed.text.length > 120 ? "…" : ""}`, ); diff --git a/src/web/auto-reply.ts b/src/web/auto-reply.ts index 2b1c358ff..858a3f7a8 100644 --- a/src/web/auto-reply.ts +++ b/src/web/auto-reply.ts @@ -862,9 +862,16 @@ export async function monitorWebProvider( return; } + // Apply response prefix if configured (same as regular messages) + let finalText = stripped.text; + const responsePrefix = cfg.inbound?.responsePrefix; + if (responsePrefix && finalText && !finalText.startsWith(responsePrefix)) { + finalText = `${responsePrefix} ${finalText}`; + } + const cleanedReply: ReplyPayload = { ...replyResult, - text: stripped.text, + text: finalText, }; await deliverWebReply({