#11889: fix(chat): filter HEARTBEAT_OK messages in chat.history when showOk is false
app: web-ui
gateway
stale
Cluster:
Heartbeat Message Filtering
## Summary
Fixes #11630 - HEARTBEAT_OK messages appearing in webchat after page refresh.
## Problem
The live broadcast path correctly suppresses heartbeat messages via `shouldSuppressHeartbeatBroadcast()`, but `chat.history` returned raw transcript messages with no heartbeat filtering applied.
This caused HEARTBEAT_OK messages to appear in the control-ui chat tab after any page load/refresh, even though they were correctly suppressed in real-time.
## Solution
Apply heartbeat visibility filtering in the `chat.history` handler:
- Check webchat heartbeat visibility using `resolveHeartbeatVisibility({ cfg, channel: "webchat" })`
- When `showOk` is false (the default), filter out assistant messages that are only HEARTBEAT_OK
- This matches the behavior of `shouldSuppressHeartbeatBroadcast()` used for live broadcasts
## Changes
- `src/gateway/server-methods/chat.ts`: Add `isHeartbeatOnlyMessage()` and `filterHeartbeatMessages()` helpers, apply filtering in `chat.history` handler
- `src/gateway/server-methods/chat.heartbeat-filter.test.ts`: Unit tests for the filtering logic
## Testing
- [x] Build passes (`pnpm build`)
- [x] Lint passes (`pnpm check`)
- [x] Unit tests pass (`pnpm exec vitest run src/gateway/server-methods/chat.heartbeat-filter.test.ts`)
- [x] Manually verified against the reproduction steps in #11630
## AI-Assisted
- [x] Built with AI assistance (OpenClaw/Claude)
- [x] Fully tested
- [x] I understand what the code does
---
*My first contribution to OpenClaw! 🦞*
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR updates `chat.history` to apply the same heartbeat visibility rules used by the live broadcast path, filtering `HEARTBEAT_OK` assistant messages out of returned transcript history when `resolveHeartbeatVisibility({ channel: "webchat" }).showOk` is false. It also adds a Vitest file to validate the intended filtering behavior.
The change fits into the gateway chat stack by aligning history replay (`src/gateway/server-methods/chat.ts`) with the existing broadcast suppression logic in `src/gateway/server-chat.ts` (`shouldSuppressHeartbeatBroadcast`).
<h3>Confidence Score: 3/5</h3>
- This PR is close to mergeable but has a correctness risk in heartbeat-only detection that can drop real assistant content from history.
- The overall approach (apply heartbeat visibility in chat.history) is sound and matches existing broadcast behavior, but the current `startsWith` logic will treat some non-heartbeat messages as heartbeat-only and filter them, which is user-visible data loss in history. Tests also currently re-implement the logic, so they wouldn’t catch divergence/regressions.
- src/gateway/server-methods/chat.ts; src/gateway/server-methods/chat.heartbeat-filter.test.ts
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#11647: fix(webchat): filter HEARTBEAT_OK messages from chat.history response
by liuxiaopai-ai · 2026-02-08
94.8%
#11661: fix: Filter HEARTBEAT_OK from chat.history when showOk is false
by veast · 2026-02-08
93.8%
#11859: fix: filter HEARTBEAT_OK messages from chat.history when showOk is ...
by Zjianru · 2026-02-08
91.8%
#12774: fix: webchat heartbeat should respect showAlerts config
by a2093930 · 2026-02-09
87.1%
#12240: fix: suppress heartbeat agent events from webchat broadcast
by Yida-Dev · 2026-02-09
85.5%
#8334: fix(webchat): Filter NO_REPLY messages from chat history
by vishaltandale00 · 2026-02-03
80.7%
#14309: fix(ui): resolve chat event session key mismatch
by justonlyforyou · 2026-02-11
80.6%
#14966: fix(webchat): preserve user message visibility after chat.send
by BenediktSchackenberg · 2026-02-12
79.6%
#14993: fix(webchat): add heartbeat detection to prevent zombie WebSocket c...
by BenediktSchackenberg · 2026-02-12
78.7%
#9218: Fix Control UI chat resync on gaps and terminal events
by figitaki · 2026-02-05
78.7%