Skip to content

Fix HTML-escaped JSON in tool call arguments for v2/v3/v7 templates - #312

Open
AmirF194 wants to merge 1 commit into
mistralai:mainfrom
AmirF194:fix/tool-call-arguments-markup-escaping
Open

AmirF194 wants to merge 1 commit into
mistralai:mainfrom
AmirF194:fix/tool-call-arguments-markup-escaping

Conversation

@AmirF194

Copy link
Copy Markdown

Fixes #311.

tojson returns a markupsafe.Markup (a str subclass), and Markup.__radd__ takes priority over str.__add__ on a plain-string left operand. _emit_argument_normalization marked the normalized arguments |safe, so every place that later did '{"name": "' + name + ...' + arguments + '}' got the literal quotes around name/arguments/id HTML-escaped to ", corrupting the JSON. The arguments value itself was never touched, which is why it was easy to miss in a spot check: only the surrounding hand-written punctuation broke.

Jinja's string filter doesn't fix this (it's soft_str, which deliberately preserves Markup so escape() still runs on it later). ~ '' does, since ~ compiles to str_join, which plain-str()s every piece before joining, same as the reproduction in the issue confirmed by hand.

Added test_tool_call_dict_arguments_produce_valid_json (v2/v3/v3-spm/v7) asserting no " in the output and that both "name" and "arguments" render as literal JSON. Reverting just the ~ '' line turns it red again, same container both times. Regenerated the 26 golden .jinja fixtures that embed _emit_argument_normalization's output; each diff is the single changed line. pytest tests/, --doctest-modules ./src, ruff, mypy and pre-commit are all clean, and the full tests/integrations/ suite (parity + transformers) passes.

_emit_argument_normalization marked non-string arguments |tojson|safe, which
stays a markupsafe.Markup. Markup.__radd__ takes priority over str.__add__,
so concatenating it into the hand-written JSON scaffolding with '+'
HTML-escaped the surrounding literal quotes instead of leaving them alone.

Use `~ ''` instead, which forces Jinja's str_join path (plain str() on
every piece) rather than the Markup-preserving `string` filter.

Fixes mistralai#311.
@AmirF194

Copy link
Copy Markdown
Author

Flagging this one, green for about a week with no review yet. The fix is one call in template_generator.py (swap the Markup concatenation for a plain str), the rest of the diff is the jinja fixture regeneration.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dict tool-call arguments render as HTML-escaped JSON in v2/v3/v7 chat templates

1 participant