Skip to content

fix: hide heartbeat tool prompts from chat history#76896

Open
karbzclaw-web wants to merge 1 commit intoopenclaw:mainfrom
karbzclaw-web:fix/heartbeat-display-history-58287
Open

fix: hide heartbeat tool prompts from chat history#76896
karbzclaw-web wants to merge 1 commit intoopenclaw:mainfrom
karbzclaw-web:fix/heartbeat-display-history-58287

Conversation

@karbzclaw-web
Copy link
Copy Markdown

@karbzclaw-web karbzclaw-web commented May 3, 2026

Fixes #58287.

Summary

  • Treat the default heartbeat prompt and heartbeat response-tool prompt as internal heartbeat user messages in the shared heartbeat filter.
  • Keep those prompts out of projected chat display history.
  • Add Control UI defense-in-depth so live rendered chat also hides heartbeat user prompts, async internal completion prompts, HEARTBEAT_OK deltas/finals, and HEARTBEAT_OK stream fallback text.
  • Deduplicate adjacent duplicate transcript entries with the same timestamp/text or assistant signature/response id, which prevents duplicated Control UI user/assistant bubbles when the same event is recorded twice.
  • Normalize the synthetic openclaw-control-ui sender label out of user-message display so local Control UI messages render as You.
  • Add regression coverage for gateway projection and the actual UI controller/rendering paths.

Tests

  • corepack pnpm exec vitest run ui/src/ui/controllers/chat.test.ts ui/src/ui/chat/message-normalizer.test.ts src/auto-reply/heartbeat-filter.test.ts src/gateway/server-methods/server-methods.test.ts

@openclaw-barnacle openclaw-barnacle Bot added gateway Gateway runtime size: XS labels May 3, 2026
@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented May 3, 2026

Codex review: needs changes before merge.

Summary
The branch updates heartbeat filtering, Gateway chat-history projection, Control UI live/history suppression, duplicate display-message handling, sender-label normalization, and regression tests for heartbeat prompt visibility.

Reproducibility: yes. Source inspection gives a high-confidence path: current main defines HEARTBEAT_RESPONSE_TOOL_PROMPT separately, while chat.history projection only passes HEARTBEAT_PROMPT into isHeartbeatUserMessage.

Next step before merge
A repair worker can safely add the missing changelog entry without changing the TypeScript implementation.

Security
Cleared: The diff only changes TypeScript heartbeat display filtering and tests, with no dependency, workflow, secret, install, publish, or code-execution surface changes.

Review findings

  • [P3] Add the required changelog entry — src/auto-reply/heartbeat-filter.ts:50-52
Review details

Best possible solution:

Land the shared Gateway filter and Control UI defense after adding one concise Unreleased Fixes changelog entry and letting exact-head CI finish cleanly.

Do we have a high-confidence way to reproduce the issue?

Yes. Source inspection gives a high-confidence path: current main defines HEARTBEAT_RESPONSE_TOOL_PROMPT separately, while chat.history projection only passes HEARTBEAT_PROMPT into isHeartbeatUserMessage.

Is this the best way to solve the issue?

Yes. Updating the shared projection filter is the narrow maintainable fix for history, and the UI-side suppression is reasonable defense-in-depth; the remaining gap is release-note hygiene.

Full review comments:

  • [P3] Add the required changelog entry — src/auto-reply/heartbeat-filter.ts:50-52
    This changes user-facing Control UI/Gateway chat-history behavior, but the PR does not update CHANGELOG.md. Repo policy requires user-facing fixes to be recorded under Unreleased Fixes before merge.
    Confidence: 0.92

Overall correctness: patch is correct
Overall confidence: 0.88

Acceptance criteria:

  • pnpm exec oxfmt --check --threads=1 CHANGELOG.md
  • pnpm test ui/src/ui/controllers/chat.test.ts ui/src/ui/chat/message-normalizer.test.ts src/auto-reply/heartbeat-filter.test.ts src/gateway/server-methods/server-methods.test.ts

What I checked:

  • Current main has a distinct response-tool heartbeat prompt: HEARTBEAT_RESPONSE_TOOL_PROMPT is separate from the legacy HEARTBEAT_PROMPT, so response-tool heartbeat turns can have a different user prompt string. (src/auto-reply/heartbeat.ts:19, a0e0bf58486d)
  • Current main filter does not know that prompt by default: isHeartbeatUserMessage only normalizes the caller-provided heartbeatPrompt plus transcript/task forms; it does not include HEARTBEAT_RESPONSE_TOOL_PROMPT. (src/auto-reply/heartbeat-filter.ts:49, a0e0bf58486d)
  • chat.history uses the shared projection path: The chat.history handler feeds transcript rows through projectRecentChatDisplayMessages, whose current projection passes HEARTBEAT_PROMPT into isHeartbeatUserMessage. (src/gateway/server-methods/chat.ts:1720, a0e0bf58486d)
  • PR head adds focused filtering and coverage: The diff adds HEARTBEAT_RESPONSE_TOOL_PROMPT to the shared known-heartbeat prompts and adds tests for heartbeat prompt suppression in the shared filter, Gateway projection, and Control UI paths. (src/auto-reply/heartbeat-filter.ts:50, 7a72bdf4572f)
  • Required changelog entry is missing: The PR files list seven changed files and none is CHANGELOG.md, while the repository has an Unreleased Fixes section for user-facing fixes. (CHANGELOG.md:30, a0e0bf58486d)
  • Exact-head CI is not fully complete: The check-runs API for the PR head shows many successful checks, but several exact-head check runs are still in progress. (7a72bdf4572f)

Likely related people:

  • steipete: Recent path history shows shared chat-display projection and Control UI chat event handling work in the same Gateway/UI surfaces affected by this PR. (role: recent maintainer; confidence: high; commits: 5f2273e81efc, a7237ea44fc0, f739edcf4c7e; files: src/gateway/chat-display-projection.ts, ui/src/ui/controllers/chat.ts, src/auto-reply/heartbeat-filter.ts)
  • pashpashpash: The distinct heartbeat response-tool prompt that current chat-history filtering misses appears in recent heartbeat-tool work. (role: introduced adjacent behavior; confidence: medium; commits: 8f4eaa9c00be; files: src/auto-reply/heartbeat.ts, src/infra/heartbeat-runner.ts)
  • vincentkoc: Recent Control UI chat reconciliation changes touch the same live/history filtering area that this PR updates. (role: recent adjacent maintainer; confidence: medium; commits: 02908db62b30, cff991c88d04; files: ui/src/ui/controllers/chat.ts)

Remaining risk / open question:

  • Exact PR-head CI still has in-progress check runs, and targeted tests were not run locally because this was a read-only review.

Codex review notes: model gpt-5.5, reasoning high; reviewed against a0e0bf58486d.

@karbzclaw-web karbzclaw-web force-pushed the fix/heartbeat-display-history-58287 branch from e571a43 to 1d252f8 Compare May 3, 2026 19:20
@openclaw-barnacle openclaw-barnacle Bot added app: web-ui App: web-ui size: S and removed size: XS labels May 3, 2026
@karbzclaw-web karbzclaw-web force-pushed the fix/heartbeat-display-history-58287 branch from 1d252f8 to 7a72bdf Compare May 3, 2026 19:34
Copy link
Copy Markdown

@byungskers byungskers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice cleanup of heartbeat noise in the chat history. The deduplication logic in "projectedHistoryDedupeKey" is a good addition. One minor note: the hardcoded "HEARTBEAT_USER_PROMPT_PREFIXES" array in the UI controller duplicates prefixes from heartbeat.ts — consider importing them from a shared source to avoid drift if heartbeat prompts evolve.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: web-ui App: web-ui gateway Gateway runtime size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Heartbeat prompt visible as user message in Control UI chat

2 participants