Skip to content

[Bug]: Inline code with a slash and a numeric suffix renders as a file chip and hides the prefix #13899

Description

@adinschmidt

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/web

The mobile Markdown renderer uses the same inline-code classifier from packages/client-runtime and produces the same shortened label.

Steps to reproduce

  1. Open any thread.

  2. Have an assistant response include a namespaced model ID in inline code, for example:

    Switch from `glm-5.3` to `z-ai/glm-5.3`.
  3. Read the rendered message, then click the z-ai/glm-5.3 span.

For a direct check, inlineCodeFilePathCandidate("z-ai/glm-5.3") in packages/client-runtime/src/markdownLinks.ts returns "z-ai/glm-5.3" instead of null.

Expected behavior

z-ai/glm-5.3 renders as ordinary inline code with its full text, the same as glm-5.3.

Actual behavior

z-ai/glm-5.3 renders as a file-link chip labeled glm-5.3. The z-ai/ prefix is gone from the visible text, so the sentence reads "Switch from glm-5.3 to glm-5.3." Clicking the chip fails with Failed to read workspace file 'z-ai/glm-5.3' in '<workspace>'.

Reproduced examples include:

Inline code Rendered chip label
z-ai/glm-5.3 glm-5.3
openai/gpt-5.1 gpt-5.1
deepseek-ai/DeepSeek-V3.1 DeepSeek-V3.1
python/3.12 3.12

glm-5.3, z-ai/glm-5, and origin/main stay ordinary code. A span needs a slash or a :line suffix to be considered, and then its last segment needs something extension-shaped. FILE_EXTENSION_PATTERN is /\.[A-Za-z0-9_-]+$/, so .3 in glm-5.3 counts as a file extension.

Impact

Minor bug or occasional failure

The rendered message loses part of what the agent wrote, and the chip links to a file that does not exist.

Version or commit

main @ c9a0e8a

Environment

Reproduced on macOS 27.0 using the web development app at commit c9a0e8a, viewed in Chromium 152. The mobile Markdown text-rendering function also reproduces the shortened label. Provider-independent.

Supporting evidence

Activity

  1. juliusmarminge commented on Sep 27, 2026

    @juliusmarminge
    Member

    Confirmed on main @ c9a0e8a119, the commit in the report. Still present. Checked from source only; this was not re-run in a client.

    `glm-5.3` stays ordinary code because inlineCodeFilePathCandidate returns null when the span has no slash and no :line suffix (packages/client-runtime/src/markdownLinks.ts:163-164). A slash continues, and the last segment then has to match FILE_EXTENSION_PATTERN (/\.[A-Za-z0-9_-]+$/, markdownLinks.ts:16). .3 in glm-5.3 matches, so z-ai/glm-5.3, openai/gpt-5.1, deepseek-ai/DeepSeek-V3.1, and python/3.12 all come back as candidates. The same pattern matches .5-Coder and .1-8B, so Qwen/Qwen2.5-Coder and meta-llama/Llama-3.1-8B are chips too. z-ai/glm-5 and origin/main stay code because the last segment has no dot (apps/web/src/markdown-links.test.ts:487-489). The "versions" cases in that file are hosts and ports, not this shape.

    parseMarkdownFileLink does not undo that. For a relative path, RELATIVE_FILE_PATH_PATTERN accepts any slash-separated token and does not require an extension. Web turns the candidate into a chip in resolveInlineCodeFileLinkMeta (apps/web/src/markdown-links.ts:88-96) and renders it from the inline-code branch (apps/web/src/components/ChatMarkdown.tsx:3114-3124). The visible label is the basename (ChatMarkdown.tsx:2618). A parent suffix is added only when two file links in the message share a basename (ChatMarkdown.tsx:1232-1234), so one z-ai/glm-5.3 shows as glm-5.3 and the sentence collapses to two copies of glm-5.3.

    The click opens that path as written. It contains a slash, so basename lookup is skipped (apps/web/src/workspaceBasenameLookup.ts:26-28). The preview reads z-ai/glm-5.3 and shows Failed to read workspace file 'z-ai/glm-5.3' in '<workspace>' (packages/contracts/src/project.ts:267, rendered at apps/web/src/components/files/FilePreviewPanel.tsx:1232).

    The desktop app uses this web renderer. Mobile classifies the span with the same function and labels it with the same basename (apps/mobile/modules/t3-markdown-text/src/markdownLinks.ts:287 and :300-307). Fenced code is a different node and is not tagged; inline code nested inside a link is not tagged either (ChatMarkdown.tsx:651).

    No open issue is this false positive. #10794 keeps authored link text, and #8254 looks up real slashed paths in the workspace index.

    The extension check should stop treating a version-shaped last segment as a file. A digit-dot-digit run in the basename (5.3, 3.12, 2.5-Coder, 3.1-8B) covers the reported spans and the hyphenated model ids. Letter-led extensions stay files (src/main.ts, archive.tar.gz, bar.mp3). A numeric suffix after a letter stays a file too (share/man/ls.1, usr/lib/libfoo.so.1): those match today only because the final suffix is numeric, and requiring a letter in that suffix would drop them. Apply the version check to the basename even when a :line suffix is present. z-ai/glm-5.3:12 currently skips the extension test because hasPosition short-circuits it (markdownLinks.ts:179). Authored markdown links go through parseMarkdownFileLink on their own and should keep linking.

  2. added
    bugSomething is broken or behaving incorrectly.
    acceptedfeature request accepted
    via-triageFiled through npx t3 triage
    on Sep 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    acceptedfeature request acceptedbugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions