From d87a91372919e3cc8c42d4b245cac20e3de05140 Mon Sep 17 00:00:00 2001 From: Samy <12219635+touzenesmy@users.noreply.github.com> Date: Tue, 11 Aug 2026 20:47:11 -0400 Subject: [PATCH] fix(ui): stop stripping the word assistant from rendered text (#5974) * fix: stop stripping the word 'assistant' from rendered text The QWEN_BARE_MARKER_RE regex in both the Python backend (tool_parsing.py) and JS frontend (chatRenderer.js) was matching any standalone occurrence of the word 'assistant' separated by any whitespace, then replacing it with a space. This caused normal English uses like 'Home assistant' to render as 'Home '. Fixed by narrowing the word-boundary check from [\t\r\n ] (any whitespace) to [\r\n] (line boundaries only), so only Qwen-format role-token leaks (where 'assistant' appears alone on a line) are stripped. * fix(tests): update bare-marker test expectations for #5971 Move 'x assistant y' from STRIPPED to KEPT (mid-sentence must survive). Add 'Before\nassistant\nAfter' to STRIPPED (bare-marker on own line). * fix(ui): strip whitespace-padded assistant role markers --------- Co-authored-by: samy Co-authored-by: Alexandre Teixeira --- src/tool_parsing.py | 2 +- static/js/chatRenderer.js | 2 +- tests/test_tool_parsing_bare_end_marker.py | 5 ++++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/tool_parsing.py b/src/tool_parsing.py index 98dc1b5f6..5b5d283ec 100644 --- a/src/tool_parsing.py +++ b/src/tool_parsing.py @@ -193,7 +193,7 @@ _QWEN_ROLE_MARKER_RE = re.compile(r"?|< // Keep in sync with _QWEN_BARE_MARKER_RE in src/tool_parsing.py. At least one // pipe is required around `end`: with both optional (`\|?end\|?`) this also ate // a bare `end` on its own line, breaking Ruby/Lua/shell snippets (#5547). -const QWEN_BARE_MARKER_RE = /(?:^|[\t\r\n ])(?:\/?\|end\||\|end|end\|)(?=[\t\r\n ]|$)|(?:^|[\t\r\n ])assistan(?:t)?(?=[\t\r\n ]|$)/gi; +const QWEN_BARE_MARKER_RE = /(?:^|[\t\r\n ])(?:\/?\|end\||\|end|end\|)(?=[\t\r\n ]|$)|(?:^|[\r\n])[ \t]*assistan(?:t)?[ \t]*(?=[\r\n]|$)/gi; // Self-narration about tool results (model echoing stdout/exit_code) const TOOL_NARRATION_RE = /(?:The (?:result|output) shows?:?\s*)?-?\s*(?:stdout|stderr|exit_code):\s*.+/gi; diff --git a/tests/test_tool_parsing_bare_end_marker.py b/tests/test_tool_parsing_bare_end_marker.py index 6167c8dde..703cf616d 100644 --- a/tests/test_tool_parsing_bare_end_marker.py +++ b/tests/test_tool_parsing_bare_end_marker.py @@ -34,6 +34,7 @@ KEPT = [ ("append end", "append end"), ("END", "END"), ("\nEnd\n", "End"), + ("x assistant y", "x assistant y"), # mid-sentence must survive (#5971) ] # Real markers — at least one pipe, plus the role word — with the exact output @@ -44,7 +45,9 @@ STRIPPED = [ ("a /|end| b", "a b"), ("a |end b", "a b"), ("a end| b", "a b"), - ("x assistant y", "x y"), + ("Before\nassistant\nAfter", "Before \nAfter"), # bare-marker on its own line still stripped + ("Before\n assistant\t \nAfter", "Before \nAfter"), # whitespace-padded marker still stripped + ("Before\n\tassistan \nAfter", "Before \nAfter"), # truncated marker variant still stripped ]