Fix empty result JSON dump and missing heartbeat prefix
Bug fixes: - Empty result field handling: Changed truthy check to explicit type check (`typeof parsed?.text === "string"`) in command-reply.ts. Previously, Claude CLI returning `result: ""` would cause raw JSON to be sent to WhatsApp. - Response prefix on heartbeat: Apply `responsePrefix` to heartbeat alert messages in runReplyHeartbeat, matching behavior of regular message handler.
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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 ? "…" : ""}`,
|
||||
);
|
||||
|
||||
@@ -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({
|
||||
|
||||
Reference in New Issue
Block a user