Skip to content

fix(chat): render Codex source citations - #9605

Open
juliusmarminge wants to merge 2 commits into
mainfrom
t3code/fix-citation-markdown-rendering
Open

juliusmarminge wants to merge 2 commits into
mainfrom
t3code/fix-citation-markdown-rendering

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Sep 4, 2026 •

Copy link
Copy Markdown
Member

Codex source citations currently appear as raw marker text in chat. Render them as numbered chips on web and desktop, with a popover showing the original source IDs and optional line ranges.

Mobile responses and copy/paste use readable references with the same numbering. Code and link examples stay literal, incomplete streaming markers stay hidden until resolved, and stored message text is unchanged. Shared list recovery keeps citation positions correct when copying over-indented content.

Source IDs do not contain destination URLs. The popover explains when the source URL is unavailable; this change does not guess links or add server requests.

Verification

  • 334 focused Markdown, citation, clipboard, list-recovery, and mobile tests passed.
  • Web, mobile, and client-runtime typechecks passed.
  • Targeted formatting and lint passed, with existing lint warnings in unchanged code.
  • Browser verification covered single and grouped citations, line ranges, literal code, closing source details with Escape, and plain/rich-text copy from within citation labels and across surrounding prose.
  • Before and after use the same synthetic response and viewport. No conversation data or model selectors are included in the public evidence. The follow-up selection-copy and locator-ID fixes leave these captured visual states unchanged.

Before and after

Before, from base f559fe0ba:

Before: raw citation markers remain visible in prose and code

After, from head 5014ada6a:

After: prose citations render as numbered chips while the code example stays literal

Recording, including grouped source details and line ranges:

Before and after citation rendering and source details

Implemented with Codex.


Note

Medium Risk
Touches shared Markdown parsing, streaming display, and clipboard serialization across web and mobile; regressions could affect copy behavior or citation rendering without changing stored data.

Overview
Codex’s private-use citation markers in assistant Markdown are now parsed and shown as numbered source references instead of raw marker text. A new shared @t3tools/client-runtime/codex-citations module owns parsing, first-appearance numbering, remarkCodexCitations, and renderCodexCitationsAsMarkdown (with streaming tail hiding for incomplete markers).

Web/desktop wires the remark plugin into ChatMarkdown, sanitizes citation payload on span, and renders CodexCitationChip popovers (source IDs and line locators; no invented URLs). Mobile converts citations before native Markdown and artifact splitting, and passes isStreaming through.

Copy/paste applies the same readable [Source N: …] text for whole-message copy (MessagesTimeline.logic, mobile copy button) and improves clipboard handling so partial selections of citation chips and data-markdown-copy-text paste correctly. List-indentation recovery moves into client-runtime with source-position remapping so over-indented bullets and citations keep correct offsets. Stored message text is unchanged; code, links, and directives still leave markers literal.

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

Note

Add Codex source citation rendering across web and mobile chat

  • Adds a shared Codex citation parser and renderer in codexCitations.ts that tokenizes private-use citation syntax, validates source IDs and locators, deduplicates and numbers sources by first appearance, and excludes code/link/image/directive contexts
  • Integrates citation rendering into web ChatMarkdown.tsx with a memoized remark plugin list and streaming-tail hiding, plus a new CodexCitationChip.tsx interactive control with a source-details popover
  • Integrates the same renderer into mobile ThreadFeed.tsx via AssistantMarkdownContent with an isStreaming prop
  • Updates clipboard handling in markdown-clipboard.ts and MessagesTimeline.logic.ts so copied text contains readable citation references instead of raw markers, and partial selection of a citation control preserves full citation details
  • Moves the list-indentation normalizer into client-runtime (markdownListIndentation.ts) with source-position recovery for relocated nodes; web now re-exports from client-runtime
  • Risk: list-indentation logic moved cross-package; consumers importing markdown-list-indentation from the web path now get a re-export of the client-runtime implementation, and the new remarkCodexCitations plugin changes remark plugin ordering in ChatMarkdown

Macroscope summarized 5014ada.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XL 500-999 changed lines (additions + deletions). labels Sep 4, 2026
Comment thread packages/client-runtime/src/codexCitations.ts Outdated
Comment thread apps/web/src/components/chat/CodexCitationChip.tsx
@github-actions

github-actions Bot commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 13.6 KiB 13.5 KiB −54 B (−0.4%) 15.1 KiB ✅
Codex Thread snapshot wire 7.0 KiB 7.0 KiB +2 B (+0.0%) 7.3 KiB ✅
Codex Live turn WebSocket wire 6.6 KiB 6.5 KiB −56 B (−0.8%) 7.8 KiB ✅
Codex Live turn WebSocket decoded 57.1 KiB 57.0 KiB −88 B (−0.2%) 66.4 KiB ✅
Codex Live turn messages 10 8 −2 (−20.0%) 21 ✅
Claude Total thread wire 13.7 KiB 13.8 KiB +15 B (+0.1%) 15.1 KiB ✅
Claude Thread snapshot wire 7.0 KiB 7.0 KiB +1 B (+0.0%) 7.3 KiB ✅
Claude Live turn WebSocket wire 6.7 KiB 6.7 KiB +14 B (+0.2%) 7.8 KiB ✅
Claude Live turn WebSocket decoded 59.3 KiB 59.3 KiB 0 B (0.0%) 66.4 KiB ✅
Claude Live turn messages 10 10 0 (0.0%) 21 ✅

Baseline: f559fe0 · PR result: 5014ada · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 113.8 KiB
  • Claude decoded thread snapshot: 114.5 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@macroscopeapp

macroscopeapp Bot commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces a shared Markdown citation parser, interactive source chips, streaming handling, and clipboard/list-position changes across web and mobile chat. These changes alter multiple existing production paths and add substantial new runtime logic rather than remaining a small isolated adjustment.

Notes:

  • Diff unchanged. Approvability was decided on eligibility alone.

You can add or adjust custom eligibility rules. Learn more.

This branch has not been deployed

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

Labels

macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews size:XL 500-999 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.

1 participant