[feat-007a] Live citation rendering for vision mode
Three pieces working together so pills appear progressively as the
model streams, instead of all-at-once at end-of-turn:
1) Stream-parse the hidden <CITATIONS> JSON block. Once <CITATIONS>
opens we accumulate into a buffer and brace-depth scan for newly
completed {...} entries every delta, emitting a citation_added SSE
event per entry the moment it's parseable. Each ref is deduped via
a per-turn Set so the end-of-turn batched citations event doesn't
re-emit. Resets the per-iter buffer in flushText.
2) Per-marker citation verifier (Olava non-streaming, parallel). When
exactly one PDF is in scope we pre-extract its text once, then in
onContentDelta scan iterText for newly-complete [N] or superscript
runs and fire a verifyCitation Promise per marker without awaiting.
Each resolution emits citation_added live + pushes to events. v1
currently misses 0/N - debug logging added but the stream-parser
path covers the live-pill UX independently.
3) Frontend rAF coalescer. A burst of 30+ citation_added events would
otherwise yield 30 setMessages calls → 30 ChatView re-renders → 30
updateScrollButton invocations, compounding into max-update-depth.
Buffer pending citations in a ref and flush once per animation
frame; force-flush at end-of-stream.
Plus: PDF render swapped from @napi-rs/canvas to node-canvas (napi
rejects pdfjs's internal Path2D objects in ctx.fill, breaking the
very first page). Frontend preprocessCitations also matches Unicode
superscript marker runs (¹²³⁴), which Olava sometimes prefers in
legal-style prose.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| Repository | nwhitehouse/mike |
|---|---|
| Author | Nick Whitehouse <nick.whitehouse@mccarthyfinch.com> |
| Authored | |
| Parents | f870b0a2 |
| Stats | 7 files changed , +584 , -46 |
| Part of | Vision mode: PDF page images → Olava (feat-007a / 008 / 009 / 010 / bug-005) |
Capture this commit into my fork
Download a Markdown prompt that tells Claude how to port this
exact commit into your working tree. Run it via
claude -p < capture-commit-436d028d.md
from inside the repo you want the change in.