#11661: fix: Filter HEARTBEAT_OK from chat.history when showOk is false
app: web-ui
gateway
stale
Cluster:
Heartbeat Message Filtering
## Problem
HEARTBEAT_OK messages appeared in the Control UI chat tab after page load/refresh, even though `resolveHeartbeatVisibility` defaults `showOk` to `false` for webchat.
**Root cause:** The `chat.history` handler returned raw transcript messages without applying heartbeat visibility filtering. The live broadcast path correctly suppressed these via `shouldSuppressHeartbeatBroadcast()` in `server-chat.ts`, but history loads bypassed this logic.
## Solution
Apply the same heartbeat visibility filtering used by live broadcast:
1. Call `resolveHeartbeatVisibility({ cfg, channel: "webchat" })`
2. When `showOk` is `false`, filter out assistant messages where `content` is only `HEARTBEAT_OK`
3. Return the filtered message list
## Changes
- **Added imports**: `HEARTBEAT_TOKEN`, `resolveHeartbeatVisibility`
- **Added filtering logic** in `chat.history` handler before responding
- Matches the channel resolution used by live broadcast (webchat)
## Testing
### Before (reproducing the bug)
1. Run gateway with default heartbeat enabled
2. Wait for a heartbeat cycle → agent replies with HEARTBEAT_OK
3. Open Control UI chat tab → live broadcast correctly suppresses it
4. Refresh the page → **BUG: HEARTBEAT_OK appears in history**
### After (expected behavior)
1. Same steps as above
2. Refresh the page → HEARTBEAT_OK is filtered from history (matches live behavior)
## Implementation Notes
- Used the same `resolveHeartbeatVisibility` function as `server-chat.ts`
- Filter checks `msg.role === "assistant"` and `trimmed === HEARTBEAT_TOKEN`
- Preserves all other messages (user, system, assistant with content)
## References
Fixes #11630
---
**Related code:**
- Live broadcast filtering: `src/gateway/server-chat.ts` (`shouldSuppressHeartbeatBroadcast`)
- Heartbeat visibility resolution: `src/infra/heartbeat-visibility.ts`
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR updates the `chat.history` gateway method to apply the same heartbeat visibility behavior as the live webchat broadcast path: it resolves heartbeat visibility for the `webchat` channel and (when `showOk` is false) filters out assistant messages that are only `HEARTBEAT_OK` before returning history to the Control UI.
This change lives in `src/gateway/server-methods/chat.ts` and is meant to align history loads with the suppression already done during live broadcasts in `src/gateway/server-chat.ts`.
<h3>Confidence Score: 3/5</h3>
- This PR is close to safe, but the heartbeat history filter is likely ineffective for common transcript message shapes.
- The intent matches existing live-broadcast suppression, but the new filter only inspects string `msg.content` while stored transcript messages often use array-part content; that would leave HEARTBEAT_OK in history for the typical case, meaning the bug may persist.
- src/gateway/server-methods/chat.ts
<!-- greptile_other_comments_section -->
<sub>(4/5) You can add custom instructions or style guidelines for the agent [here](https://app.greptile.com/review/github)!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#11647: fix(webchat): filter HEARTBEAT_OK messages from chat.history response
by liuxiaopai-ai · 2026-02-08
94.1%
#11889: fix(chat): filter HEARTBEAT_OK messages in chat.history when showOk...
by bendyclaw · 2026-02-08
93.8%
#11859: fix: filter HEARTBEAT_OK messages from chat.history when showOk is ...
by Zjianru · 2026-02-08
90.9%
#12774: fix: webchat heartbeat should respect showAlerts config
by a2093930 · 2026-02-09
87.6%
#12240: fix: suppress heartbeat agent events from webchat broadcast
by Yida-Dev · 2026-02-09
87.2%
#8334: fix(webchat): Filter NO_REPLY messages from chat history
by vishaltandale00 · 2026-02-03
81.9%
#14966: fix(webchat): preserve user message visibility after chat.send
by BenediktSchackenberg · 2026-02-12
78.0%
#8742: fix(webchat): hide internal system messages from UI (#7440)
by revenuestack · 2026-02-04
77.0%
#14309: fix(ui): resolve chat event session key mismatch
by justonlyforyou · 2026-02-11
76.1%
#23144: fix(ui): strip reply directive tags from assistant messages in WebC...
by echoVic · 2026-02-22
76.0%