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 ]