Skip to content

feat(chat): rich citation cards, excerpt rewrite, inline annotations, and A2UI rendering#4

Merged
sylvanding merged 8 commits intomainfrom
feat/rich-citation-rewrite
Mar 12, 2026
Merged

feat(chat): rich citation cards, excerpt rewrite, inline annotations, and A2UI rendering#4
sylvanding merged 8 commits intomainfrom
feat/rich-citation-rewrite

Conversation

@sylvanding
Copy link
Copy Markdown
Owner

@sylvanding sylvanding commented Mar 12, 2026

Summary

Complete implementation of the Rich Citation & Rewrite Enhancement feature across 4 phases, transforming the chat playground into a powerful scientific literature interaction experience.

Phase 1: Rich Citation Cards + Loading Animation

  • Citation cards with collapsible metadata (authors, year, DOI, relevance score with color grading)
  • Multi-stage loading animation (searching → citations → generating → complete)
  • 80ms text_delta throttling to reduce Markdown re-parsing overhead during streaming
  • Backend batch Paper metadata query (eliminates N+1)

Phase 2: Excerpt Rewrite + Diff Comparison

  • POST /api/v1/chat/rewrite SSE streaming endpoint with 5 styles (simplify, academic, translate_en, translate_zh, custom)
  • Pydantic validation (2000 char limit, custom_prompt requirement)
  • asyncio.Semaphore(3) rate limiting + 30s timeout
  • RewritePanel with react-diff-viewer-continued for original vs rewritten comparison
  • RewriteStyleSelector with preset and custom prompt options

Phase 3: Inline Citation Tags + Cross-referencing

  • Custom remark-citation plugin transforms [N] patterns into interactive colored tags
  • InlineCitationTag with Radix HoverCard for paper preview (title, authors, excerpt)
  • Click-to-scroll linking: clicking inline tag scrolls to and highlights the corresponding citation card
  • Out-of-range citation graceful fallback (gray, non-interactive)
  • Progressive activation during streaming

Phase 4: A2UI Rich Media + Parallel Retrieval

  • @a2ui-sdk/react v0.8 integration with 3 custom Omelette components (CitationCard, RewriteDiff, StatsDashboard)
  • a2ui_surface SSE event handling with automatic fallback for invalid messages
  • Multi-KB RAG retrieval parallelized with asyncio.gather() (significant latency reduction)
  • ConnectRPC deferred due to connect-python Alpha status

New Dependencies

  • Frontend: react-diff-viewer-continued, @radix-ui/react-hover-card, @a2ui-sdk/react, @a2ui-sdk/types, unist-util-visit
  • Backend: No new dependencies (uses existing LangChain + asyncio)

Files Changed (29 files, +4972/-96)

  • Backend: rewrite.py (new), chat.py (parallel RAG), __init__.py (router)
  • Frontend: 12 new components/services, 5 modified files
  • Docs: Plan completed, brainstorm, research docs

Testing

  • TypeScript compilation: 0 errors
  • Ruff lint: All checks passed
  • Pre-commit hooks: All passed (5 commits)
  • Browser E2E: Playwright headless verification — UI renders correctly, components load, i18n working

Post-Deploy Monitoring & Validation

  • What to monitor: Backend logs for [LLM:*] rewrite task entries, SSE a2ui_surface event emission
  • Validation checks: curl -X POST /api/v1/chat/rewrite with sample excerpt
  • Expected healthy behavior: Rewrite SSE stream completes with rewrite_end event; parallel RAG queries complete faster than sequential
  • Failure signal: asyncio.Semaphore exhaustion (>3 concurrent rewrites), A2UI JSON parse errors in frontend console
  • Validation window: 48h post-deploy

Version

  • Frontend: 0.2.0
  • Backend: 0.2.0

Compound Engineered

…ream throttling

Phase 1 of knowledge base retrieval enhancement:
- Backend: batch Paper query for citation metadata (authors/year/doi/chunk_type)
- Frontend: CitationCard with collapsible excerpts, relevance badges, DOI links
- CitationCardList with stagger animations and show-more pagination
- MessageLoadingStages: searching → citations → generating → complete
- Stream throttling: text_delta batched at 80ms intervals to reduce Markdown re-parses
- Type safety: isCitation guard + normalizeCitation for snippet→excerpt compat
- Version bump to v0.2.0

Made-with: Cursor
…selector

Phase 2: adds POST /api/v1/chat/rewrite endpoint with 5 rewrite styles
(simplify, academic, translate_en, translate_zh, custom), Pydantic
validation, semaphore-based rate limiting, and 30s timeout. Frontend
adds RewritePanel with react-diff-viewer-continued for original vs
rewritten comparison, RewriteStyleSelector with preset and custom
options, and activates the rewrite button on CitationCard.

Made-with: Cursor
…d linking

Phase 3: adds remark-citation plugin to transform [N] patterns into
interactive colored tags in AI responses. InlineCitationTag renders
with citation color, HoverCard preview (title, authors, excerpt),
and click-to-scroll linking. CitationCardList gains highlight flash
animation on targeted scroll. Supports out-of-range graceful fallback
and progressive activation during streaming.

Made-with: Cursor
Phase 4: integrates @a2ui-sdk/react v0.8 with 3 custom Omelette
components (CitationCard, RewriteDiff, StatsDashboard). Backend
multi-KB retrieval parallelized with asyncio.gather() for
significant latency reduction. Frontend handles a2ui_surface SSE
events with automatic fallback for invalid messages. ConnectRPC
deferred to future iteration due to connect-python Alpha status.

Made-with: Cursor
…ad link

- Move onAction from A2UIProvider to A2UIRenderer (matches SDK API)
- Inline A2UIComponentProps type (not exported from @a2ui-sdk/react/0.8)
- Cast citation-ref custom component to bypass react-markdown Components type
- Fix useRef<ReturnType<typeof setTimeout>> requiring initial value
- Rename snippet to excerpt in MessageBubble test fixture
- Prefix unused ocrMutation with underscore
- Fix relative link path in plan document for VitePress

Made-with: Cursor
…crMutation

- Cast custom A2UI components to CatalogComponent (runtime props injected by framework)
- Remove unused ocrMutation and ocrApi import from PapersPage

Made-with: Cursor
…ge mock provider

- Add aria-label to ChatInput submit button for accessibility
- Use specific button name selector in ChatInput tests (attach vs send)
- Fix SettingsPage test: verify test-connection hidden for mock provider

Made-with: Cursor
@sylvanding sylvanding merged commit 59651f2 into main Mar 12, 2026
4 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