Skip to content

feat: quote-reply popover — quick answers, quote any block, open mentioned files - #350

Open
windli2018 wants to merge 4 commits into
agegr:mainfrom
windli2018:feat/quote-reply
Open

feat: quote-reply popover — quick answers, quote any block, open mentioned files#350
windli2018 wants to merge 4 commits into
agegr:mainfrom
windli2018:feat/quote-reply

Conversation

@windli2018

@windli2018 windli2018 commented Aug 2, 2026

Copy link
Copy Markdown

What

Click any assistant paragraph, list item, or table row to pop a quote-reply popover. It does three things in one small UI:

  1. Quick answers — closed questions get option buttons:
    • yes/no (要X吗 / 是否X / 需要我X吗) → [好,X] [不用]
    • choices (A 还是 B / A 或者 B) → [A] [B]
  2. Quote anything — open questions and non-questions get a plain quote button. Clicking fills the input box with a markdown blockquote (> text) plus an optional pre-filled answer, email-reply style. It never sends — the user decides prompt / steer / followUp.
  3. Open mentioned files — assistant replies often list file paths as plain text (lib/foo.ts, design/spec.md). The popover detects them, verifies each against the backend, and offers an Open button per existing file.

How

  • lib/quote-reply.ts (new): pure-text helpers, no NLP deps.
    • splitQuestions — split on ?/? ;;, keeps A 还是 B whole.
    • detectOptions — yes/no, choice (还是/或者/or with word boundaries so store/word don't false-positive), open-question detection (怎么/哪个/什么…) → fall back to quote.
    • extractFilePaths — candidate file paths from plain text (dir/name.ext + bare filenames with common extensions), de-duplicated.
    • formatQuote> seg\n + optional answer line.
  • QuoteReplyPopover (new): option buttons per question, fallback quote button, and Open-file buttons (existence verified via /api/files?type=meta before rendering).
  • MarkdownBody: QuoteableParagraph wraps <p>, <li>, <tr> (table row cells joined with |). Exactly one popover open at a time (context); re-click toggles it closed; a follow-mouse tooltip hints "click to quote reply" on hover. Popover is flow layout (expands the message, no clipping) and stays open until explicitly closed.
  • MessageView → ChatWindow: threads onQuoteReply / onOpenFile down; insert uses the existing chatInputRef.prependText; opening reuses the existing file-tab machinery.

Design choices

  • Click to open, not hover — hover just shows a tooltip. Avoids popover flicker while reading.
  • Stays open until closed — no auto-dismiss racing the pointer (which made the popover vanish mid-travel in early iterations).
  • Never sends — fills the input box only; works identically mid-stream (quote something the model just wrote and steer to correct it).
  • Open ≠ quote — file buttons and quote buttons are visually distinct; opening a file is one click, quoting is one click.
  • Verified opens — files are checked against the backend so dead buttons never render.
  • No external deps — pure regex/strings.

Validation

  • 24+ real phrasings from this project's conversations (closed/open/non-questions, A/B, multi-question) classified correctly.
  • Manual dev flows: paragraph → options → input filled; table row → > 快速排序 | O(n log n) | O(n log n) | O(n²); assistant file list → Open button → file panel opens the file.
  • or word-boundary fix verified against Word?/More?/queue-store false positives.

Notes

  • Detection is heuristic; exotic phrasings won't produce buttons (fallback quote always works). Could layer an LLM on top later without changing this surface.

@windli2018

Copy link
Copy Markdown
Author

Final appearance (screenshot)

quote-reply popover

Behavior:

  • Hover (desktop) or click (mobile / anywhere) on any assistant paragraph or list item (<p> / <li>) pops the overlay right below it.
  • Closed questions get quick option buttons:
    • yes/no (要X吗 / 是否X) → [好,X] [不用] (action surfaced when short)
    • A/B choices (A 还是 B / A 或者 B) → [A] [B]
  • Open questions and non-questions get a single fallback 引用回复 (quote reply) button — every paragraph is quoteable.
  • Clicking any button fills the input box with > quote + optional pre-filled answer (email-reply style). It never sends — the user picks prompt / steer / followUp.
  • Works mid-stream too (an answer the model just wrote can be quoted to steer immediately).

Screenshot hosted on the docs/quote-reply-screenshot branch of the fork (raw.githubusercontent link).

@windli2018 windli2018 changed the title feat: quote-reply popover on assistant messages feat: quote-reply popover — quick answers, quote any block, open mentioned files Aug 2, 2026
# Conflicts:
#	components/MarkdownBody.tsx
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