Skip to content

feat(chat): add reply-to-selection with quoted context#36

Merged
tyulyukov merged 3 commits into
mainfrom
marcode/feat/quote-reply
Apr 9, 2026
Merged

feat(chat): add reply-to-selection with quoted context#36
tyulyukov merged 3 commits into
mainfrom
marcode/feat/quote-reply

Conversation

@tyulyukov
Copy link
Copy Markdown
Owner

Summary

Implements the ability to reply to specific text selections within assistant messages. Users can:

  • Select text in an agent response → a floating toolbar appears with "Reply" and "Copy" buttons
  • Click "Reply" (or use Cmd/Ctrl+Shift+R) to quote the selected text as structured context
  • Code block language is auto-detected when selecting from code blocks
  • Quoted contexts appear as violet inline chips in the composer (with preview text and remove button)
  • Sent messages with quoted context display an expandable label showing the quoted text

Key Design Decisions:

  • Quoted contexts are prepended to the prompt (unlike terminal/Jira which append) as <quoted_context> XML blocks
  • Transient draft state — not persisted to localStorage, cleared on thread switch or send
  • 5000 character truncation limit with ...[truncated] suffix
  • Deduplication by message ID and text offset to prevent duplicate quotes
  • Floating toolbar uses createPortal for positioning above assistant message content

Changes

  • apps/web/src/lib/quotedContext.ts (new) — Core types and utilities: QuotedContext, truncation, formatting, parsing leading quoted blocks, deduplication
  • apps/web/src/components/chat/SelectionReplyToolbar.tsx (new) — Floating toolbar on text selection; detects code block context; handles Cmd/Ctrl+Shift+R and Escape
  • apps/web/src/components/chat/QuotedContextInlineChip.tsx (new) — Violet inline chip in composer showing preview + remove button
  • apps/web/src/components/chat/UserMessageQuotedContextLabel.tsx (new) — Expandable label in message timeline showing quoted context when user message includes it
  • apps/web/src/composerDraftStore.ts — Added quotedContexts field, addQuotedContext(), removeQuotedContext(), clearQuotedContexts() actions
  • apps/web/src/components/chat/MessagesTimeline.tsx — Integrated AssistantMessageContentWithReply wrapper, SelectionReplyToolbar integration, timeline label display
  • apps/web/src/components/ChatView.tsx — Integrated quoted context into composer, send flow, and send state derivation
  • AGENTS.md — Documented the feature architecture and key patterns

Testing

  • Text selection: Select plain text in assistant message → toolbar appears above selection with Reply and Copy buttons
  • Code block selection: Select text from a code block → language tag is extracted and shown in the chip preview (e.g., "Quoted code (typescript)")
  • Keyboard shortcuts: Press Cmd/Ctrl+Shift+R on a selection → quoted context added to composer; press Escape → toolbar dismisses
  • Copy to clipboard: Click Copy button → selected text copied without adding to composer
  • Composer display: After replying to selection, a violet chip appears above editor showing preview; can remove via chip button
  • Truncation: Select >5000 characters → text truncated with ...[truncated] suffix and warning logged
  • Deduplication: Reply to identical selection twice → only one quote added (dedup by message ID + offset)
  • Timeline display: Send message with quoted context → expandable label shows quoted text preview; can expand to see full context with language tags
  • Draft lifecycle: Switch threads → quoted contexts cleared; send message → quoted contexts cleared; reload → quoted contexts NOT restored (transient)
  • Toolbar positioning: Selection in different positions on screen → toolbar appears above selection, centered horizontally

- Users can select text in assistant messages and click "Reply" in floating toolbar
- Quoted text prepended to prompts as <quoted_context> XML blocks
- Keyboard shortcut: Cmd/Ctrl+Shift+R to reply, Escape to dismiss
- New components: SelectionReplyToolbar, QuotedContextInlineChip, UserMessageQuotedContextLabel
- Quoted contexts stored transiently in composerDraftStore, cleared on send
- Expandable label displays quoted context in message timeline
- Quoted text truncated at 5000 chars with ...[truncated] suffix
- Code block selections automatically detect language
- Add electron to trustedDependencies in bun.lock and package.json
- Consolidate tailwindcss version references in lockfile
- Display checkmark icon when selection is copied to clipboard
- Fix toolbar positioning to use fixed positioning correctly
- Sanitize code language attributes and escape quoted context body
- Extract formatQuotedContextTooltip utility function
- Add TOOLBAR_HEIGHT_PX and TOOLBAR_GAP_PX constants
- Replace custom ID generation with randomUUID()
- Remove unused stripAllQuotedContextBlocks() and related pattern
@tyulyukov tyulyukov merged commit 14d65c4 into main Apr 9, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant