Skip to content

fix: render the assistant answer as markdown - #745

Open
Anchel123 wants to merge 4 commits into
stagingfrom
fix/markdown-answer-rendering
Open

fix: render the assistant answer as markdown#745
Anchel123 wants to merge 4 commits into
stagingfrom
fix/markdown-answer-rendering

Conversation

@Anchel123

@Anchel123 Anchel123 commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Closes #310

Problem

The final natural-language answer is written by the model in markdown, but the chat rendered it as plain text. Users saw literal **bold** markers and - bullets instead of formatting, and the structure of multi-section answers was hard to read.

Change

Render only the ai message (the string answer) through react-markdown:

  • remark-gfm — tables, strikethrough, autolinks.
  • remark-breaks — keeps single newlines as line breaks, matching the whitespace-pre-line behaviour it replaces.
  • Element styling comes from a local components map using the existing theme tokens, so no Tailwind typography plugin wiring is needed.

The generated SQL block and the query-results table are deliberately untouched — those must stay verbatim.

Security

Raw HTML is not enabled (no rehype-raw), so model output cannot inject markup.

Verification

  • npx tsc --noEmit — no new errors.
  • npm run lint — clean for the touched file.
  • npm run build — succeeds.
  • Rendered a representative answer through the same pipeline: **London** becomes <strong>, - lines become a real list.

Summary by CodeRabbit

  • New Features
    • AI chat messages now support Markdown formatting, including headings, lists, links, code blocks, blockquotes, tables, and line breaks.
    • Improved readability and visual presentation of formatted chat responses.
    • Inline code is displayed with distinct chip styling, while fenced code blocks receive clear block formatting.
    • Images in chat responses display a safe placeholder instead of loading external content.

The final natural-language answer is written by the model in markdown, but
it was rendered as plain text, so readers saw literal `**bold**` markers and
`-` bullets, and paragraph structure was lost.

Render only that message through react-markdown (remark-gfm for tables and
strikethrough, remark-breaks to keep the single-newline behaviour the old
`whitespace-pre-line` gave). The generated SQL and the results table are
untouched — they must stay verbatim. Raw HTML is not enabled, so model
output cannot inject markup.

Closes #310

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings August 31, 2026 10:48
@railway-app

railway-app Bot commented Aug 31, 2026

Copy link
Copy Markdown

This PR was not deployed automatically as @Anchel123 does not have access to the Railway project.

In order to get automatic PR deploys, please add @Anchel123 to your workspace on Railway.

@github-actions

github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown

Dependency Review

The following issues were found:

  • ✅ 0 vulnerable package(s)
  • ✅ 0 package(s) with incompatible licenses
  • ✅ 0 package(s) with invalid SPDX license definitions
  • ✅ 0 package(s) with unknown licenses.
  • ⚠️ 42 packages with OpenSSF Scorecard issues.

View full job summary

@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6e2004d6-87e6-44ac-a470-3cdd1f5522bd

📥 Commits

Reviewing files that changed from the base of the PR and between 13eb77a and eeaf9ea.

📒 Files selected for processing (1)
  • app/src/components/chat/ChatMessage.tsx

Included review availability: Your plan provides up to 4 included reviews per hour; 1 remains after this review.


📝 Walkthrough

Walkthrough

AI chat messages now render Markdown with GitHub Flavored Markdown, preserved line breaks, custom styling, and image placeholders.

Changes

Markdown chat rendering

Layer / File(s) Summary
Configure and apply Markdown rendering
app/package.json, app/src/components/chat/ChatMessage.tsx
Adds Markdown runtime dependencies and renders AI messages with GFM, preserved line breaks, styled elements, code formatting, and image placeholders.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: 🔵 Low · up to eeaf9

The change makes links in AI-generated answers clickable, creating a bounded risk of directing users to deceptive external destinations. Existing protections limit the impact, so the PR is mergeable with owner awareness or follow-up to enforce an explicit link policy.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: rendering assistant answers as Markdown.
Linked Issues check ✅ Passed The PR addresses issue #310 by rendering assistant responses with react-markdown and remark-breaks, which restores Markdown formatting and preserves single-newline line breaks.
Out of Scope Changes check ✅ Passed The dependency additions and ChatMessage rendering changes directly support issue #310 and the stated PR objectives. No unrelated code changes are identified.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 1…
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 1 files.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/markdown-answer-rendering

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.

Copilot AI 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.

Pull request overview

This PR fixes chat readability by rendering only the assistant’s natural-language response as Markdown (GFM + single-newline breaks) while leaving SQL and result-table rendering unchanged.

Changes:

  • Render type === 'ai' message content via react-markdown with remark-gfm and remark-breaks.
  • Add a local components map to style common Markdown elements using existing theme tokens.
  • Add frontend dependencies: react-markdown, remark-gfm, and remark-breaks.

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 2 comments.

File Description
app/src/components/chat/ChatMessage.tsx Renders assistant messages as Markdown with custom-styled elements.
app/package.json Adds Markdown rendering dependencies to the frontend app.
app/package-lock.json Locks newly added Markdown-related packages and transitive deps.
Files not reviewed (1)
  • app/package-lock.json: Generated file

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread app/src/components/chat/ChatMessage.tsx Outdated
Comment thread app/package.json
The repo root depends on the app via `file:app`, so its lockfile inlines
the app's tree. Updating only `app/package-lock.json` left `npm ci` at the
root out of sync and failed the test job.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 31, 2026 10:54

Copilot AI 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.

Pull request overview

Copilot reviewed 2 out of 4 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • app/package-lock.json: Generated file
Suppressed comments (1)

app/src/components/chat/ChatMessage.tsx:68

  • code blocks are detected via className?.startsWith('language-'), which misclassifies fenced code blocks that omit a language (withoutlang). Those blocks will get the inline-code styling (bg/padding) even though they render inside <pre>. Use react-markdown’s inline flag to distinguish inline vs block code, and keep any existing className on block code for future highlighting.
  code: ({ className, children }) => {
    const isBlock = Boolean(className?.startsWith('language-'));
    if (isBlock) {
      return <code className="font-mono text-sm">{children}</code>;
    }

Comment thread app/src/components/chat/ChatMessage.tsx
Two review findings on the markdown renderer:

* The inline-vs-block check keyed off `language-*`, so a fence opened
  without a language got the inline chip styling inside its own frame.
  Style `code` once and cancel it for descendants of `pre` instead.
* Markdown image syntax rendered a real `<img>`, so the answer could make
  the browser fetch an arbitrary URL chosen by the model. Render the alt
  text instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 31, 2026 11:30

Copilot AI 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.

Pull request overview

Copilot reviewed 2 out of 4 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • app/package-lock.json: Generated file
Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

app/src/components/chat/ChatMessage.tsx:63

  • a renderer passes href through directly even when it’s undefined (allowed by the react-markdown types). This can produce non-link <a> elements with target/rel, which is confusing for keyboard users and can surface as invalid markup when the model emits []() or other malformed links. Guard href and render a non-link fallback when missing.
  a: ({ children, href }) => (
    <a href={href} target="_blank" rel="noopener noreferrer" className="text-primary underline underline-offset-2">
      {children}
    </a>
  ),

Comment thread app/src/components/chat/ChatMessage.tsx Outdated
react-markdown puts the fence's `language-*` marker on `code`; dropping it
threw away the only hint about the language. Merge it with the local
styling instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 31, 2026 11:41

Copilot AI 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.

Pull request overview

Copilot reviewed 2 out of 4 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • app/package-lock.json: Generated file

@Anchel123
Anchel123 requested a review from galshubeli August 31, 2026 11:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

User friendly response is not showing new lines

2 participants