From 46df7e2421381bf8dd43cb40fdb84e29e7ecb986 Mon Sep 17 00:00:00 2001 From: dongdong <42494191+arkyu2077@users.noreply.github.com> Date: Tue, 3 Mar 2026 09:11:47 +0800 Subject: [PATCH] fix(feishu): skip typing indicator keepalive re-adds to prevent notification spam (#31580) * fix(feishu): skip typing indicator keepalive re-adds to prevent notification spam The typing keepalive loop calls addTypingIndicator() every 3 seconds, which creates a new messageReaction.create API call each time. Feishu treats each re-add as a new reaction event and fires a push notification, causing users to receive repeated notifications while waiting for a response. Unlike Telegram/Discord where typing status expires after a few seconds, Feishu reactions persist until explicitly removed. Skip the keepalive re-add when a reaction already exists (reactionId is set) since there is no need to refresh it. Closes #28660 * Changelog: note Feishu typing keepalive suppression --------- Co-authored-by: yuxh1996 Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com> --- CHANGELOG.md | 1 + extensions/feishu/src/reply-dispatcher.ts | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cc6263f245..36025d7e48d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -176,6 +176,7 @@ Docs: https://docs.openclaw.ai - Feishu/Inbound debounce: debounce rapid same-chat sender bursts into one ordered dispatch turn, skip already-processed retries when composing merged text, and preserve bot-mention intent across merged entries to reduce duplicate or late inbound handling. (#31548) - Feishu/Inbound ordering: serialize message handling per chat while preserving cross-chat concurrency to avoid same-chat race drops under bursty inbound traffic. (#31807) - Feishu/Dedup restart resilience: warm persistent dedup state into memory on monitor startup so retry events after gateway restart stay suppressed without requiring initial on-disk probe misses. (#31605) +- Feishu/Typing notification suppression: skip typing keepalive reaction re-adds when the indicator is already active, preventing duplicate notification pings from repeated identical emoji adds. (#31580) - BlueBubbles/Message metadata: harden send response ID extraction, include sender identity in DM context, and normalize inbound `message_id` selection to avoid duplicate ID metadata. (#23970) Thanks @tyler6204. - Docker/Image health checks: add Dockerfile `HEALTHCHECK` that probes gateway `GET /healthz` so container runtimes can mark unhealthy instances without requiring auth credentials in the probe command. (#11478) Thanks @U-C4N and @vincentkoc. - Docker/Sandbox bootstrap hardening: make `OPENCLAW_SANDBOX` opt-in parsing explicit (`1|true|yes|on`), support custom Docker socket paths via `OPENCLAW_DOCKER_SOCKET`, defer docker.sock exposure until sandbox prerequisites pass, and reset/roll back persisted sandbox mode to `off` when setup is skipped or partially fails to avoid stale broken sandbox state. (#29974) Thanks @jamtujest and @vincentkoc. diff --git a/extensions/feishu/src/reply-dispatcher.ts b/extensions/feishu/src/reply-dispatcher.ts index ffc945513d9..a98ae3094a1 100644 --- a/extensions/feishu/src/reply-dispatcher.ts +++ b/extensions/feishu/src/reply-dispatcher.ts @@ -94,6 +94,12 @@ export function createFeishuReplyDispatcher(params: CreateFeishuReplyDispatcherP ) { return; } + // Feishu reactions persist until explicitly removed, so skip keepalive + // re-adds when a reaction already exists. Re-adding the same emoji + // triggers a new push notification for every call (#28660). + if (typingState?.reactionId) { + return; + } typingState = await addTypingIndicator({ cfg, messageId: replyToMessageId,