From 3175d7ca211a539d401e3de08179667f0231bfb8 Mon Sep 17 00:00:00 2001 From: Afonso Coutinho Date: Wed, 3 Jun 2026 00:59:42 +0100 Subject: [PATCH] fix: tool-block parsing crashes on a non-string input (#1628) --- src/tool_parsing.py | 2 ++ tests/test_tool_parsing_nonstring.py | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 tests/test_tool_parsing_nonstring.py diff --git a/src/tool_parsing.py b/src/tool_parsing.py index cd9ecd1..b31e114 100644 --- a/src/tool_parsing.py +++ b/src/tool_parsing.py @@ -69,6 +69,8 @@ _TOOL_CODE_RE = re.compile( # fullwidth (U+FF5C) and ascii '|' in any count. _DSML_PIPES = r"[||]+" def _normalize_dsml(text: str) -> str: + if not isinstance(text, str): + return "" if "DSML" not in text: return text t = text diff --git a/tests/test_tool_parsing_nonstring.py b/tests/test_tool_parsing_nonstring.py new file mode 100644 index 0000000..7bd1975 --- /dev/null +++ b/tests/test_tool_parsing_nonstring.py @@ -0,0 +1,19 @@ +"""Regression: tool-block parsing must tolerate a non-string input. + +`_normalize_dsml` did `if "DSML" not in text` (TypeError on None) and the public +`parse_tool_blocks`/`strip_tool_blocks` then ran regexes on it. Coercing a +non-string to "" in `_normalize_dsml` makes the whole chain safe. +""" +import src.agent_tools # noqa: F401 (break agent_tools<->tool_parsing import cycle) +from src.tool_parsing import _normalize_dsml, parse_tool_blocks, strip_tool_blocks + + +def test_non_string_does_not_crash(): + assert _normalize_dsml(None) == "" + assert parse_tool_blocks(None) == [] + assert strip_tool_blocks(None) == "" + + +def test_plain_text_passes_through(): + assert strip_tool_blocks("hello world") == "hello world" + assert parse_tool_blocks("no tools here") == []