Skip to content

feat(chat): hide agent replies from chat, keep them on thread cards#32

Merged
clintberry merged 2 commits into
mainfrom
feat/hide-agent-chat-messages
Jun 9, 2026
Merged

feat(chat): hide agent replies from chat, keep them on thread cards#32
clintberry merged 2 commits into
mainfrom
feat/hide-agent-chat-messages

Conversation

@clintberry

Copy link
Copy Markdown
Contributor

Summary

Agent task replies used to show up twice: once as a chat bubble and again as the reply text in the inline super-thread card under the @mention that spawned them. The chat now shows only the card — agent replies live exclusively on the thread surfaces (inline AgentTaskCard and the agent thread drawer), while human messages and system notices ("Workspace is still starting", queue-full, etc.) stay in chat.

This is display-only: agent messages are still persisted and broadcast (they feed buildChatHistory for agent context continuity); they're just filtered out of the rendered list. A message is hidden only when it's agent-typed and its author matches a real session agent — system notices are posted with a nil author UUID, so they fall through the filter and remain visible. The predicate lives in a pure module (message-visibility.ts) with a colocated Vitest-style spec, following the repo.test.ts convention (type-checked now, runs once a test runner is wired).

Header grouping and the empty state derive from the visible sequence, so no phantom gaps appear where bubbles were removed. Auto-scroll deliberately stays keyed on the raw message count: an arriving (hidden) reply still scrolls the freshly-updated task card into view.

Notes

  • Unread counts still include hidden agent replies — explicitly deferred by the plan (the card is new content); a separate change if the team wants unread to track only visible chat.
  • Legacy harness caveat: on the deprecated claude -p path, finishAgent can attach expandableContent to agent messages, which the hidden bubble would have rendered. The Pi path (default, and sole harness going forward) always posts replies with expandableContent: nil, so nothing is lost there.

Test plan

  • npx tsc --noEmit and npm run lint clean (one pre-existing warning in an untouched file).
  • New spec src/components/chat/message-visibility.test.ts covers: human messages always visible, session-agent replies hidden, nil-author system notices visible, agent-typed messages from non-session agents visible (defensive), empty agent set hides nothing, and order-preserving non-mutating filtering.
  • Manual walkthrough per the plan: @mention an agent → reply appears only in the card; system notices still appear in chat; consecutive human messages still collapse headers.

Post-Deploy Monitoring & Validation

No additional operational monitoring required — frontend display-only change; no backend, persistence, or WebSocket behavior touched. Validation: in any active session, @mention an agent and confirm the reply renders in the task card but not as a bubble, and that operational notices still appear in chat. Rollback is reverting this PR.


Compound Engineering
Claude Code

🤖 Generated with Claude Code

Hides a message only when authorType is agent AND its authorId matches a
real session agent — nil-author system notices and human messages stay
visible.
Agent replies now surface only on the super-thread surfaces (inline
AgentTaskCard and the agent thread drawer). Header grouping and the
empty state derive from the visible sequence; auto-scroll stays keyed
on the raw message count so an arriving reply still scrolls its card
into view.
@clintberry clintberry merged commit 3a8c6a1 into main Jun 9, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant