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

@pranav100000pranav100000 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

coderabbitaiBot 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-actionsgithub-actionsBot 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 threadapps/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-connectorchatgpt-codex-connectorBot 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

macroscopeappBot 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 threadapps/web/src/markdown-codex-file-citations.ts

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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-connectorchatgpt-codex-connectorBot 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 threadapps/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 threadapps/web/src/markdown-codex-file-citations.ts Outdated
Comment threadapps/web/src/markdown-codex-file-citations.ts

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 CursorFix 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-connectorchatgpt-codex-connectorBot 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 👍 / 👎.

@cursorcursorBot 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 threadapps/web/src/markdown-codex-file-citations.ts Outdated
pranav100000and 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

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

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR 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

@pranav100000@Yash-Singh1
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
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

@pranav100000pranav100000 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

coderabbitaiBot 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-actionsgithub-actionsBot 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 threadapps/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-connectorchatgpt-codex-connectorBot 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&amp;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

macroscopeappBot 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 threadapps/web/src/markdown-codex-file-citations.ts

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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-connectorchatgpt-codex-connectorBot 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 threadapps/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 threadapps/web/src/markdown-codex-file-citations.ts Outdated
Comment threadapps/web/src/markdown-codex-file-citations.ts

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 CursorFix 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-connectorchatgpt-codex-connectorBot 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 👍 / 👎.

@cursorcursorBot 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 threadapps/web/src/markdown-codex-file-citations.ts Outdated
pranav100000and 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

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

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR 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

@pranav100000@Yash-Singh1
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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

@pranav100000pranav100000 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

coderabbitaiBot 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-actionsgithub-actionsBot 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 threadapps/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-connectorchatgpt-codex-connectorBot 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&amp;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

macroscopeappBot 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 threadapps/web/src/markdown-codex-file-citations.ts

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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-connectorchatgpt-codex-connectorBot 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 threadapps/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 threadapps/web/src/markdown-codex-file-citations.ts Outdated
Comment threadapps/web/src/markdown-codex-file-citations.ts

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 CursorFix 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-connectorchatgpt-codex-connectorBot 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 👍 / 👎.

@cursorcursorBot 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 threadapps/web/src/markdown-codex-file-citations.ts Outdated
pranav100000and 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

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

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR 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

@pranav100000@Yash-Singh1
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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

@pranav100000pranav100000 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

coderabbitaiBot 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-actionsgithub-actionsBot 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 threadapps/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-connectorchatgpt-codex-connectorBot 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&amp;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

macroscopeappBot 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 threadapps/web/src/markdown-codex-file-citations.ts

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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-connectorchatgpt-codex-connectorBot 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 threadapps/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 threadapps/web/src/markdown-codex-file-citations.ts Outdated
Comment threadapps/web/src/markdown-codex-file-citations.ts

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 CursorFix 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-connectorchatgpt-codex-connectorBot 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 👍 / 👎.

@cursorcursorBot 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 threadapps/web/src/markdown-codex-file-citations.ts Outdated
pranav100000and 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

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

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR 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

@pranav100000@Yash-Singh1
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
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

@pranav100000pranav100000 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

coderabbitaiBot 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-actionsgithub-actionsBot 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 threadapps/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-connectorchatgpt-codex-connectorBot 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&amp;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

macroscopeappBot 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 threadapps/web/src/markdown-codex-file-citations.ts

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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-connectorchatgpt-codex-connectorBot 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 threadapps/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 threadapps/web/src/markdown-codex-file-citations.ts Outdated
Comment threadapps/web/src/markdown-codex-file-citations.ts

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 CursorFix 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-connectorchatgpt-codex-connectorBot 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 👍 / 👎.

@cursorcursorBot 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 threadapps/web/src/markdown-codex-file-citations.ts Outdated
pranav100000and 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

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

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR 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

@pranav100000@Yash-Singh1
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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

@pranav100000pranav100000 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

coderabbitaiBot 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-actionsgithub-actionsBot 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 threadapps/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-connectorchatgpt-codex-connectorBot 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&amp;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

macroscopeappBot 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 threadapps/web/src/markdown-codex-file-citations.ts

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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-connectorchatgpt-codex-connectorBot 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 threadapps/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 threadapps/web/src/markdown-codex-file-citations.ts Outdated
Comment threadapps/web/src/markdown-codex-file-citations.ts

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 CursorFix 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-connectorchatgpt-codex-connectorBot 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 👍 / 👎.

@cursorcursorBot 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 threadapps/web/src/markdown-codex-file-citations.ts Outdated
pranav100000and 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

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

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR 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

@pranav100000@Yash-Singh1
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
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

@pranav100000pranav100000 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

coderabbitaiBot 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-actionsgithub-actionsBot 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 threadapps/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-connectorchatgpt-codex-connectorBot 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&amp;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

macroscopeappBot 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 threadapps/web/src/markdown-codex-file-citations.ts

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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-connectorchatgpt-codex-connectorBot 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 threadapps/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 threadapps/web/src/markdown-codex-file-citations.ts Outdated
Comment threadapps/web/src/markdown-codex-file-citations.ts

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 CursorFix 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-connectorchatgpt-codex-connectorBot 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 👍 / 👎.

@cursorcursorBot 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 threadapps/web/src/markdown-codex-file-citations.ts Outdated
pranav100000and 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

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

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR 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

@pranav100000@Yash-Singh1
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
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

@pranav100000pranav100000 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

coderabbitaiBot 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-actionsgithub-actionsBot 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 threadapps/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-connectorchatgpt-codex-connectorBot 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&amp;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

macroscopeappBot 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 threadapps/web/src/markdown-codex-file-citations.ts

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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-connectorchatgpt-codex-connectorBot 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 threadapps/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 threadapps/web/src/markdown-codex-file-citations.ts Outdated
Comment threadapps/web/src/markdown-codex-file-citations.ts

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 CursorFix 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-connectorchatgpt-codex-connectorBot 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 👍 / 👎.

@cursorcursorBot 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 threadapps/web/src/markdown-codex-file-citations.ts Outdated
pranav100000and 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

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

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR 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

@pranav100000@Yash-Singh1