Skip to content

fix(desktop): preserve explicit text code fences - #57542

Open
Yuy1114 wants to merge 1 commit into
NousResearch:mainfrom
Yuy1114:fix/desktop-text-fence-leak
Open

fix(desktop): preserve explicit text code fences#57542
Yuy1114 wants to merge 1 commit into
NousResearch:mainfrom
Yuy1114:fix/desktop-text-fence-leak

Conversation

@Yuy1114

@Yuy1114 Yuy1114 commented Jul 3, 2026

Copy link
Copy Markdown

What does this PR do?

Prevents explicit text, plain, and plaintext fenced blocks from being
downgraded to prose by the desktop Markdown preprocessor.

Previously, prose-like content such as file paths could trigger the heuristic,
causing the language tag (text) to leak into the rendered response. Explicit
plain-text fences now remain code blocks. The fix also corrects previously
persisted messages when they are rendered again; it does not depend on the
agent producing a new response.

Related Issue

Fixes #57540

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • Preserve explicit text, plain, and plaintext fences in
    apps/desktop/src/lib/markdown-code.ts.
  • Add regression coverage for fence classification and end-to-end Markdown
    preprocessing.
  • Verify list-marker info strings continue to be treated as prose.

How to Test

  1. Open Hermes Desktop.

  2. Ask the assistant to return several file paths inside an explicitly tagged
    text fence.

  3. Confirm the paths remain inside a Code · text block and text does not
    leak into prose.

  4. Continue the conversation or reload the persisted session and confirm the
    existing block still renders correctly.

  5. Run:

    npm run test:ui --workspace apps/desktop -- \
      src/lib/markdown-code.test.ts \
      src/lib/markdown-preprocess.test.ts
    
    npm run typecheck --workspace apps/desktop
    npm exec --workspace apps/desktop eslint -- \
      src/lib/markdown-code.ts \
      src/lib/markdown-code.test.ts \
      src/lib/markdown-preprocess.test.ts

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS 26.5.2

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — N/A
  • I've considered cross-platform impact (Windows, macOS) — browser-side TypeScript logic with no platform-specific APIs
  • I've updated tool descriptions/schemas if I changed tool behavior — N/A

Screenshots / Logs

The before/after screenshots are attached to #57540. They show the same
persisted assistant message: before the fix, the text tag and file paths are
rendered as prose; after the fix, the message renders as a Code · text block.

Targeted verification completed:

  • 2 test files, 6 tests passed
  • Desktop TypeScript typecheck passed
  • ESLint passed for all changed files
  • Manual single-turn, multi-turn, and persisted-message Desktop rendering passed

@alt-glitch alt-glitch added type/bug Something isn't working comp/desktop Electron desktop app (apps/desktop/*) P3 Low — cosmetic, nice to have duplicate This issue or pull request already exists labels Jul 3, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Duplicate of #49972 — same file and mechanism (adds a Set(['text','plain','plaintext']) and short-circuits isLikelyProseFence() to return false for those explicit language tags in apps/desktop/src/lib/markdown-code.ts). #49972 is the earliest open PR of this fix. Both fix #57540 (which stays open as the spec).

@andyylin

Copy link
Copy Markdown
Contributor

Independently reproduced this on current main with an explicit text fence containing multi-line status counts and file paths: Desktop demotes the fence, leaks the text language label, and soft-wraps the lines into prose.

Revalidated this PR's exact commit on top of current upstream main (569b912d7):

  • merge/cherry-pick: clean
  • focused Desktop tests: 3 files, 26 tests passed
  • Desktop TypeScript check: passed
  • ESLint on all changed files: passed

This PR is the correct upstream fix; explicit text, plain, and plaintext tags should be treated as author intent at both preprocessing and render-time classification.

@andyylin

Copy link
Copy Markdown
Contributor

Confirming that we are also seeing this in a real Hermes Desktop session.

The backend stored valid fenced Markdown, but Desktop rendered multi-line text blocks as flattened prose: the text language label became visible and the original line breaks collapsed. We reproduced it with runtime summaries, test-result lists, and PID/status blocks. One-line text fences in the same message rendered normally, which matches the current proseLines >= 3 demotion heuristic.

So this is not only a synthetic test case; it is affecting normal Desktop output in active use.

@teknium1 teknium1 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.

Thanks for the focused Desktop fix. The premise is confirmed on current main: apps/desktop/src/lib/markdown-code.ts:301-308 demotes multi-line text-family fences, and apps/desktop/src/components/chat/shiki-highlighter.tsx:133 has a separate render-time prose classification path.

Problems

  • The new direct test in apps/desktop/src/lib/markdown-code.test.ts:5 covers isLikelyProseFence() only; it does not protect the new isLikelyProseCodeBlock() guard used at apps/desktop/src/components/chat/shiki-highlighter.tsx:133.
  • The one-line plaintext fixture in apps/desktop/src/lib/markdown-preprocess.test.ts:18-22 already passes on current main because apps/desktop/src/lib/markdown-code.ts:323-325 requires at least three prose lines to demote that language.

Suggested changes

  • Add a multi-line direct render-classification regression for isLikelyProseCodeBlock('text', body).
  • Parameterize multi-line preprocessing coverage across text, plain, and plaintext.

Automated hermes-sweeper review.


it('preserves explicit plain text fences', () => {
const input = ['```plaintext', 'hello world', '```'].join('\n')

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.

This one-line plaintext fixture already passes on current main: isLikelyProseFence() demotes this language only when proseLines >= 3 (markdown-code.ts:323-325). Use the same three-line body as the text case so the test fails before the new explicit-language guard.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/desktop Electron desktop app (apps/desktop/*) duplicate This issue or pull request already exists P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Desktop leaks explicit text fence language into rendered prose

4 participants