Skip to content

feat(web): render Codex file-citation chips - #6103

Closed
pranav100000 wants to merge 7 commits into
pingdotgg:mainfrom
pranav100000:feat/codex-citation-chips-5813
Closed

feat(web): render Codex file-citation chips#6103
pranav100000 wants to merge 7 commits into
pingdotgg:mainfrom
pranav100000:feat/codex-citation-chips-5813

Conversation

@pranav100000

@pranav100000 pranav100000 commented Aug 11, 2026

Copy link
Copy Markdown

What Changed

Render :codex-file-citation{path="..."} directives in assistant messages as clickable local-file chips (reusing the existing Markdown file-link open/preview), instead of showing the raw directive text. Directives inside code spans/blocks are left untouched; Windows/UNC paths, escaped quotes, and malformed directives (kept literal) are handled.

Why

Closes #5813. Codex emits these citation directives; today they render as raw :codex-file-citation{...} markup the user can't act on.

UI Changes

The citation directive renders as an openable file chip (theme.ts below) instead of raw text:

Codex citation rendered as a file chip

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Medium Risk
Touches the chat markdown AST pipeline and local file-path resolution/opening. Parsing is carefully guarded, but edge cases around Windows/UNC paths and encoding could mis-link or leave citations unusable.

Overview
Turns Codex :codex-file-citation{path="..."} directives in assistant messages into the same clickable local-file chips already used for Markdown file links, instead of leaving the raw directive text.

Adds a remarkCodexFileCitations plugin that rewrites resolvable citations into link nodes (run before other remark plugins so source positions stay intact), and includes those citation hrefs in ChatMarkdown's file-link metadata lookup. Malformed, half-streamed, non-local, code-span/fence, and nested-in-link directives stay literal.

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

Codex's artifact skills cite the files they write with a
`:codex-file-citation{path="..." purpose="..."}` directive, which nothing
in the renderer parsed, so the whole directive showed up as literal text.

A remark plugin rewrites each directive into a link node, which lands it
on the file chip Markdown file links already get — same path resolution,
same open-in-editor and preview behavior. A directive is only rewritten
when its path resolves to a file, so half-streamed and non-file
directives keep reading as text; code spans and fences are untouched.
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a7393b79-b700-4236-9225-5fdebb99ce85

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 11, 2026
Comment thread apps/web/src/markdown-codex-file-citations.ts Outdated
@pranav100000
pranav100000 marked this pull request as ready for review August 11, 2026 07:53

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7847f539bc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +46 to +48
const path = CITATION_PATH_ATTRIBUTE_PATTERN.exec(attributes)?.[1]
?.replace(MARKDOWN_ESCAPE_PATTERN, "$1")
.trim();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve native Windows separators in citation paths

When Codex emits a native Windows path containing consecutive backslashes or a separator before punctuation, this replacement treats that separator as a Markdown escape. For example, \\server\share\report.docx is reduced to a single leading slash and no longer resolves as UNC, while C:\repo\.env becomes C:\repo.env and opens the wrong file. Parse or protect the directive before CommonMark escape processing instead of stripping every backslash before ASCII punctuation.

Useful? React with 👍 / 👎.

Comment on lines +69 to +73
for (const match of value.matchAll(CODEX_FILE_CITATION_PATTERN)) {
const path = readCitationPath(match[1] ?? "");
if (!path) continue;
const href = codexFileCitationHref(path);
const fileLinkMeta = resolveMarkdownFileLinkMeta(href, cwd);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve entity-like substrings in cited filenames

When a filename contains a CommonMark entity sequence such as /tmp/report&notes.pdf, the Markdown parser decodes the text node to /tmp/report&notes.pdf before this rewrite, while extractCodexFileCitationPaths scans the raw message and stores metadata for the original path. The generated href therefore misses the metadata map and targets a different filename, rendering as an ordinary link instead of an openable file chip. Citation directives need to be parsed from their raw source or otherwise protected from entity decoding.

Useful? React with 👍 / 👎.

Comment on lines +1351 to +1355
const markdownRemarkPlugins = useMemo<NonNullable<ReactMarkdownOptions["remarkPlugins"]>>(
() => [
...(lineBreaks ? CHAT_MARKDOWN_REMARK_PLUGINS_WITH_BREAKS : CHAT_MARKDOWN_REMARK_PLUGINS),
[remarkCodexFileCitations, { cwd }],
],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Normalize citation directives in the mobile thread feed

This installs the citation transformation only in the web ChatMarkdown pipeline. The mobile assistant feed still passes message.text unchanged to SelectableMarkdownText or Markdown in apps/mobile/src/features/threads/ThreadFeed.tsx:966-982, so mobile users see the raw :codex-file-citation{...} directive and cannot open the generated artifact even though mobile already supports Markdown file links. Apply equivalent normalization in the shared/mobile rendering path.

AGENTS.md reference: AGENTS.md:L67-L71

Useful? React with 👍 / 👎.

@macroscopeapp

macroscopeapp Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

New feature introducing user-facing rendering behavior for Codex file citations. Multiple unresolved review comments identify edge cases (Windows paths, entities, mobile support) that may cause citations to fail or render incorrectly.

You can customize Macroscope's approvability policy. Learn more.

Markdown spends a text node's backslash escapes and character references
before the citation plugin sees it, so the path in the tree was no longer
the path Codex wrote: `C:\repo\.env` arrived as `C:\repo.env`,
`\\server\share\report.docx` lost the pair that makes it UNC, and
`report&amp;notes.pdf` decoded to a different filename — each of which
opens the wrong file, or no file at all. The path is now read from the
source each text node was parsed from, with the parsed value only saying
where in the node the directive sits, so the plugin runs before anything
that rewrites text nodes and drops the position that source is found by.

`codexFileCitationHref` also has no href for a path `encodeURI` refuses:
an unpaired surrogate threw a URIError out of render.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread apps/web/src/markdown-codex-file-citations.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0584217630

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +107 to +108
const fileLinkMeta = resolveMarkdownFileLinkMeta(href, cwd);
if (!fileLinkMeta) continue;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Resolve explicit citations without Markdown path heuristics

When a directive names a valid path that the generic Markdown-link heuristic does not recognize—such as path="Makefile", path="/data/output", or the Windows-relative path="output\\report.docx"resolveMarkdownFileLinkMeta returns null, so the directive remains raw text instead of becoming a chip. These paths are already explicitly identified as filesystem paths by the citation syntax; resolve them directly against cwd (while separately rejecting URLs) rather than requiring the narrower link-shape patterns in markdown-links.ts.

Useful? React with 👍 / 👎.

The path attribute was matched lazily up to a quote whose lookahead said
another attribute followed, which an escaped quote inside the path can
satisfy on its own: `path="/tmp/report \" purpose=notes.pdf"` stopped at
the escape and chipped `/tmp/report \`, a path the message never cited.

The lookahead was there to find the closing quote in a parsed text node,
where an escaped quote had already collapsed into a bare one and the two
were no longer distinguishable. The path is read from the message source
now, where only the closing quote is unescaped, so the path is the run of
characters before it and the lookahead goes away.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7a9fe99e24

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


import { resolveMarkdownFileLinkMeta } from "./markdown-links";

const CODEX_FILE_CITATION_PATTERN = /:codex-file-citation\{([^{}\r\n]*)\}/g;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Allow braces inside quoted citation paths

When a cited filename or directory contains { or }—both legal path characters, for example /tmp/build/{draft}/report.pdf—this outer pattern rejects the entire directive before the quoted path attribute is parsed. Consequently both extraction and AST rewriting skip it, leaving raw citation markup instead of an openable chip. The directive scanner should distinguish braces inside quoted attribute values from the closing directive brace.

Useful? React with 👍 / 👎.

Comment thread apps/web/src/markdown-codex-file-citations.ts Outdated
…review)

The directive escapes " inside a value but leaves backslashes literal, so a
Windows path ending in a separator ("C:\build\\") is byte-identical to a
path with an escaped quote. The round-2 regex read every \" as an escaped
quote, so a trailing separator swallowed the following ` purpose=` into the
path and the chip opened the wrong target. The closer is now the first quote
after which the rest of the directive parses as attributes, which lands the
escaped-quote case and the trailing-separator case each without a lookahead
the other would satisfy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread apps/web/src/markdown-codex-file-citations.ts Outdated
Comment thread apps/web/src/markdown-codex-file-citations.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1453d9a0d9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// would nest an anchor inside the link's anchor.
const childInsideLink = insideLink || node.type === "link" || node.type === "linkReference";
node.children = node.children.flatMap((child) => {
if (child.type === "text" && typeof child.value === "string" && !childInsideLink) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Protect citation directives before Markdown tokenization

When a legal filename contains balanced Markdown delimiters, such as /tmp/*draft*.pdf or paired backticks, remark parses the path into separate text, emphasis, or inline-code nodes before this visitor runs. Since rewriteCitations is invoked on each text child independently and requires the complete directive, the citation is never converted into a file chip and instead renders as fragmented raw markup. Extract or protect directives before Markdown parsing so delimiter characters inside quoted paths remain part of the citation.

Useful? React with 👍 / 👎.

Comment on lines +68 to +71
const path = attributes
.slice(valueStart, i)
.replace(CITATION_ESCAPED_QUOTE_PATTERN, '"')
.trim();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve whitespace inside quoted citation paths

When a POSIX artifact filename begins or ends with whitespace, .trim() changes the quoted path before resolving it; for example, path="/tmp/report.pdf " links to /tmp/report.pdf rather than the distinct file /tmp/report.pdf . Because the directive already delimits the value with quotes, preserve its leading and trailing characters instead of trimming them.

Useful? React with 👍 / 👎.

.replace(CITATION_ESCAPED_QUOTE_PATTERN, '"')
.trim();
return path ? path : null;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blank chip for trailing separators

Low Severity

The new closer scan correctly accepts Windows paths that end with a trailing separator, such as C:\build\. Those paths then flow into rewriteCitations, where basenameOfPath yields an empty string, so the file chip label is blank. The added coverage only asserts extraction, so the empty-label render path is untested.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1453d9a. Configure here.

…refix (review)

Two edges the scan left open. The value's leading and trailing spaces are
part of the path — the quotes delimit it exactly — so trimming them resolved
a different file; only a genuinely empty value is now rejected. And the path
attribute was read from anywhere in the directive, so junk before it
(`purpose="x"junk path="…"`) still produced a link; the text before the
keyword must now itself be a valid run of attributes or the directive stays
literal.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 880703daa3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1356 to +1357
[remarkCodexFileCitations, { cwd }],
...(lineBreaks ? CHAT_MARKDOWN_REMARK_PLUGINS_WITH_BREAKS : CHAT_MARKDOWN_REMARK_PLUGINS),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Process citations recovered from over-indented list items

When assistant output contains an accidentally over-indented bullet such as - :codex-file-citation{path="/tmp/export.zip"}, CommonMark initially represents the body as a code node, so this first plugin deliberately skips it. The later remarkNormalizeListItemIndentation plugin in the spread reparses that node into ordinary text, but the citation pass has already finished, leaving the raw directive visible instead of a file chip. Ensure normalization-produced text also passes through citation rewriting, or protect directives before parsing.

Useful? React with 👍 / 👎.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 880703d. Configure here.

Comment thread apps/web/src/markdown-codex-file-citations.ts Outdated
pranav100000 and others added 2 commits August 11, 2026 17:57
…view)

The prefix gate rejected a directive written `{ path="…"}` or with a space
before the first attribute, leaving well-formed citations literal; it now
allows leading whitespace while still rejecting junk between attributes.

Documents two edges left as known limitations rather than shipped with a
regression: a `{`/`}` inside a quoted path terminates the brace-agnostic
scan (a quote-aware scan breaks the escaped-quote case, whose parsed value
and raw source carry different quote counts), and a citation inside an
over-indented bullet reaches this plugin as position-less text a later
normalization pass produced, so it cannot be read from source.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Yash-Singh1

Copy link
Copy Markdown
Collaborator

Superseded by #8584

@Yash-Singh1 Yash-Singh1 closed this Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Codex artifact citations render as raw codex-file-citation markup

2 participants