fix(chat): restore fenced code blocks (placeholder used escaped backslashes)#70
Merged
xaspx merged 1 commit intoJun 4, 2026
Conversation
…lashes)
renderChatContent extracts ```fenced``` blocks and replaces each with a
sentinel containing literal NULL bytes:
return `\x00CODE${id}\x00`; // \x00 = one byte (U+0000)
The restore step then searched for a literal-text version of the same
string:
html.replace(`\\x00CODE${i}\\x00`, '<pre>...</pre>');
^^ ^^ in a template literal these are
backslash + 'x' + '0' + '0',
not the U+0000 escape.
So the search needle never matched the sentinel actually present in
`html`. The unreplaced sentinel reached `element.innerHTML = ...`; per
the HTML spec the parser drops U+0000 characters, leaving the visible
text "CODE0", "CODE1", … inside the message.
Repro:
1. Have Hermes return any reply containing a ```fenced``` code block
2. Notice the rendered bubble shows "CODE0" instead of the code
3. Confused users then ask the model what CODE0 means; the model has
no idea and starts hallucinating explanations
Fix: drop the extra backslashes so the needle is the same NULL-bracketed
sentinel that was inserted in step 1.
sidneysimas
pushed a commit
to sidneysimas/hermes-control-interface
that referenced
this pull request
Jun 15, 2026
- Add office-kanban.js with Swarm Monitor (agent states + kanban board) - Add Quick Actions popup (Unblock, Mark Done, Approve, Start, Reopen, Reassign) - CSRF bridge: window.__csrfToken synced from main.js to office-kanban.js - Read-write DB split: openKanbanDB() readonly, openKanbanDBWritable() for actions - HCI color palette (amber, green, accent) for action buttons - Hover-linked highlighting on agent tasks - 18 modules, 478KB JS (131KB gzipped), 72KB CSS (12.6KB gzipped) - Deployed and tested on staging at agent2.panji.me
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
renderChatContentextracts```fenced```blocks and replaces each with a sentinel containing real NULL bytes:The restore step searches for the literal-text version of that string instead:
So the needle never matches the sentinel actually present in
html. The unreplaced sentinel reacheselement.innerHTML = ...; per the HTML spec the parser drops U+0000 characters, leaving the visible textCODE0,CODE1… inside the rendered message.fixCodeBlockContentcan't recover because it looks for__CODE_CONTENT_${i}__inside<pre><code>— but those wrappers are never produced when the upstreamreplacesilently fails.Repro (deterministic)
Any reply containing a fenced code block reproduces the bug. Verified with a small Node script:
Confused users then ask the model what
CODE0means; the model has no idea and starts hallucinating explanations from its own corrupted history.The SQLite DB row content has the original markdown with backticks intact — this is purely a render-side regression, no data corruption.
Fix
Drop the extra backslashes so the search needle is the NULL-bracketed sentinel that step 1 actually inserts.
Regression source
Introduced in 6b54d8b (v3.6.0) when
renderChatContentwas extracted intosrc/js/chat/cli.jsand the__CODE_CONTENT_${i}__two-stage hand-off was added.Verified by
Tested locally on top of v3.6.0 — historical sessions that previously showed
CODE0/CODE1now render the original code blocks correctly.