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") == []