fix: escape triple-backtick inside reasoning before wrapping in outer code block - #48477
fix: escape triple-backtick inside reasoning before wrapping in outer code block#48477Skywind5487 wants to merge 1 commit into
Conversation
…e block B1: When reasoning content contains ``` e.g. model quoting code in its thinking, wrapping it in an outer ``` for display causes the inner fence to break the outer block. Adds escape_code_fences_for_display() in gateway/stream_consumer.py, called from gateway/run.py before wrapping reasoning in the outer ``` display block.
There was a problem hiding this comment.
Pull request overview
This PR fixes markdown rendering issues in gateway platforms (Discord/Slack/etc.) when the model’s reasoning text contains triple-backtick fences, by escaping inner ``` sequences before wrapping reasoning in an outer fenced code block.
Changes:
- Add
escape_code_fences_for_display()helper to replace inner ``` markers with a non-fence sequence suitable for embedding inside an outer fenced block. - Apply the escaping in
gateway/run.pywhenshow_reasoningis enabled and reasoning is prepended to the final response. - Add unit + integration-style tests covering no-op, single/multiple fences, empty/None handling, and outer-fence preservation.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
gateway/stream_consumer.py |
Adds escape_code_fences_for_display() used to prevent nested code fences from breaking outer reasoning blocks. |
gateway/run.py |
Escapes reasoning fences before wrapping reasoning in an outer ``` block for display. |
tests/gateway/test_escape_reasoning_fences.py |
Adds tests validating escaping behavior and that the outer fence remains intact. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def escape_code_fences_for_display(text: str) -> str: | ||
| """Escape triple-backtick markers so text can be safely wrapped | ||
| inside an outer ``` code block without breaking the fence. | ||
|
|
||
| When reasoning content contains ``` (e.g. the model quotes code | ||
| in its thinking), wrapping it in an outer ``` for display causes | ||
| the inner fence to break the outer block. Solution: replace each | ||
| `` ``` `` with `` \\`\\`\\` `` before wrapping. | ||
|
|
||
| Returns: | ||
| The input text with each `` ``` `` replaced by `` \\`\\`\\` ``, | ||
| or the input unchanged if no triple-backticks are present. | ||
| """ | ||
| if not isinstance(text, str) or "```" not in text: | ||
| return text | ||
| return text.replace("```", "\\`\\`\\`") |
teknium1
left a comment
There was a problem hiding this comment.
Thanks for isolating a real fence-rendering failure.
Problems
- Current main now selects
subtext,blockquote, or fencedcoderendering ingateway/run.py:11807-11818(introduced by6cc07b6cd). The proposed unconditional escape ingateway/run.pywould also alter subtext and blockquote reasoning even though neither creates an outer fence. - The submitted integration test only assembles an f-string; it does not cover the current gateway style-selection path at
gateway/run.py:11784-11818. - The existing Copilot review correctly notes the helper's
str -> strannotation conflicts with its intentionalNonepassthrough and test.
Suggested changes
- Apply the escape only in the current
codebranch beforegateway/run.py:11818. - Add gateway-level cases for code, subtext, and blockquote styles.
- Align the helper annotation with its accepted inputs.
This is an automated hermes-sweeper review.
| # break the outer code block used to render it. | ||
| display_reasoning = escape_code_fences_for_display(display_reasoning) | ||
| response = f"💭 **Reasoning:**\n```\n{display_reasoning}\n```\n\n{response}" | ||
|
|
There was a problem hiding this comment.
Current main now chooses subtext, blockquote, or code after building display_reasoning (gateway/run.py:11807-11818). Apply this transformation only in the fenced code branch; otherwise Discord's default subtext and blockquote output gain visible backslashes despite having no enclosing fence.
| """ | ||
| if not isinstance(text, str) or "```" not in text: | ||
| return text | ||
| return text.replace("```", "\\`\\`\\`") |
There was a problem hiding this comment.
The function is annotated str -> str, but this branch intentionally returns None and the added test asserts that behavior. Please either annotate the accepted/returned optional type or make the helper strictly string-only and remove the None case.
|
Merged via #70191 — your commit was cherry-picked/reapplied onto current main with your authorship preserved in git history: your reasoning-backtick escaping was cherry-picked, applied to the code-style branch. Thanks for the contribution! |
Summary
When reasoning content contains ``` (e.g. the model quotes code in its thinking), wrapping it in an outer ``` display block causes the inner fence to break the outer one. The result is mangled markdown rendering on Discord, Slack, and other platforms.
Adds
escape_code_fences_for_display()ingateway/stream_consumer.py. Called fromgateway/run.pybefore reasoning text is wrapped in the outer ``` block — replaces each inner ``` with escaped backticks so the outer fence stays intact.Testing
6 tests: no-fence passthrough, single/multiple fence escape, empty/null handling, and integration test verifying the outer fence is preserved after escaping.