Skip to content

Add assistant message copy action and harden related test/storage fallbacks#1211

Merged
juliusmarminge merged 25 commits intopingdotgg:mainfrom
shivamhwp:feature/assistant-copy-state
Apr 11, 2026
Merged

Add assistant message copy action and harden related test/storage fallbacks#1211
juliusmarminge merged 25 commits intopingdotgg:mainfrom
shivamhwp:feature/assistant-copy-state

Conversation

@shivamhwp
Copy link
Copy Markdown
Collaborator

@shivamhwp shivamhwp commented Mar 19, 2026

What Changed

Added a copy action for assistant messages in the chat timeline. The control lives in the assistant footer, copies only the assistant response text, stays visible but disabled while the message is still streaming, and becomes clickable once the response is complete.

The shared message copy button was also extended so it can be rendered as a compact muted button for this footer treatment. Tests were updated to cover the assistant copy visibility and streaming-disabled behavior.

Why

The app already supported copying code blocks and user messages, but not full assistant responses.

This approach keeps the behavior predictable by sourcing the copied content directly from the assistant message text already stored in the timeline, so it does not include work-log entries, command metadata, timestamps, or diff UI. Keeping the button disabled during streaming also avoids partial-copy behavior and makes the interaction state explicit.

UI Changes

This adds a small muted copy button next to the assistant message timestamp in the footer. It is disabled while the assistant is streaming and enabled after the response completes.

Before
image
After
image

Fixes #1164

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Add copy button to terminal assistant messages in MessagesTimeline

  • Adds a copy button to the last assistant message in each turn, visible on hover next to the timestamp in MessagesTimeline.tsx.
  • Introduces resolveAssistantMessageCopyState and deriveTerminalAssistantMessageIds in MessagesTimeline.logic.ts to determine which messages show the copy button; active/streaming turns are excluded.
  • MessageCopyButton.tsx now shows an anchored toast on copy success or failure and supports size, variant, and className props.
  • Hardens useTheme.ts to skip DOM and storage operations during SSR or when window/localStorage are unavailable.
  • Improves height estimates in timelineHeight.ts for assistant messages containing inline code by expanding backtick spans before wrapping calculations.

Macroscope summarized 90a1b7a.


Note

Medium Risk
Moderate risk due to changes in chat timeline rendering/state (new assistant-copy eligibility logic and streaming/turn handling) and useTheme initialization/SSR guards that affect app-wide theming behavior.

Overview
Adds a hover-revealed copy-to-clipboard action for assistant responses in MessagesTimeline, shown only for the terminal assistant message of each turn and suppressed while the turn/message is still streaming.

Extends MessageCopyButton to support compact icon styling with tooltip and anchored success/error toasts, and updates timeline row derivation/tests to track copy eligibility.

Improves virtualized timeline height estimation for assistant/system messages by accounting for inline code width, and hardens useTheme with SSR/non-browser fallbacks (safe localStorage/window access plus useSyncExternalStore server snapshot).

Reviewed by Cursor Bugbot for commit 90a1b7a. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 19, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 253b1e15-5949-41d9-bc28-d14e34df706f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Mar 19, 2026
@shivamhwp shivamhwp changed the title Refine assistant message copy button state and UX Add muted assistant message copy action and harden related test/storage fallbacks Mar 19, 2026
@shivamhwp shivamhwp changed the title Add muted assistant message copy action and harden related test/storage fallbacks Add assistant message copy action and harden related test/storage fallbacks Mar 19, 2026
@shivamhwp shivamhwp closed this Mar 22, 2026
@shivamhwp
Copy link
Copy Markdown
Collaborator Author

no need for this

@shivamhwp shivamhwp reopened this Apr 4, 2026
@github-actions github-actions bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. and removed vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Apr 4, 2026
- make `MessageCopyButton` configurable with disabled state, titles, style props, and copy/error callbacks
- show assistant copy action in timeline metadata, disable it while streaming, and add toast feedback
- extract and test copy-visibility logic for streaming/empty assistant messages
- guard theme hook against missing window/document/localStorage and add server snapshot
- add in-memory fallback storage for persisted terminal state when localStorage is unavailable
- simplify brittle platform/global test setup to match new runtime-safe behavior
@shivamhwp shivamhwp force-pushed the feature/assistant-copy-state branch from 928a793 to 741eb41 Compare April 4, 2026 15:30
@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp bot commented Apr 4, 2026

Approvability

Verdict: Needs human review

This PR introduces a new user-facing feature (copy button for assistant messages) with new UI components, state derivation logic, and prop threading, plus SSR hardening changes. While each individual change is straightforward, the aggregate introduces meaningful new capability. The open review comment about an incorrect aria-label also needs addressing.

You can customize Macroscope's approvability policy. Learn more.

- Remove the optional label prop from the copy button
- Show only the icon while preserving copied state feedback
- Gate assistant copy button to the final assistant message in each turn
- Update copy-state logic and tests for streaming and non-terminal messages
- Reorder the assistant message footer so metadata appears before the copy actions
- Preserve the existing timestamp and elapsed-time display
- simplify assistant copy state to only track text and visibility
- stop passing always-false disabled props to the copy button
- update tests to match the narrower state shape
- Simplify `MessageCopyButton` to always be enabled
- Keep copy feedback limited to the copied state
macroscopeapp[bot]
macroscopeapp bot previously approved these changes Apr 7, 2026
@macroscopeapp macroscopeapp bot dismissed their stale review April 10, 2026 23:27

Dismissing prior approval to re-evaluate 1d34730

@juliusmarminge juliusmarminge force-pushed the feature/assistant-copy-state branch from 486c004 to 5ee8129 Compare April 11, 2026 02:21
@juliusmarminge juliusmarminge enabled auto-merge (squash) April 11, 2026 02:25
@juliusmarminge juliusmarminge merged commit 26cc1ff into pingdotgg:main Apr 11, 2026
12 checks passed
Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 90a1b7a. Configure here.

<TooltipTrigger
render={
<Button
aria-label="Copy link"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Incorrect aria-label says "Copy link" instead of message

Medium Severity

The aria-label on the copy button is "Copy link" but the button actually copies message text to the clipboard. The old code correctly used title="Copy message". This mislabels the action for screen reader users and is inconsistent with the tooltip text "Copy to clipboard".

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 90a1b7a. Configure here.

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

Labels

size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Add one-click copy action for assistant responses

2 participants