← Back to PRs

#11661: fix: Filter HEARTBEAT_OK from chat.history when showOk is false

by veast open 2026-02-08 03:53 View on GitHub →
app: web-ui gateway stale
## 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