Expand description
Qwen-style XML tool-call parser.
Rewrites <tool_call>...</tool_call> markup — emitted by Qwen 2 / 2.5 / 3
family models in either the text or reasoning channel — into proper
ToolCall values. Bytes outside of <tool_call> regions are forwarded
verbatim on the channel they arrived on.
Two body dialects are accepted inside the wrapper, tried in order — see
finalize_tool_call for the detail:
- JSON —
{"name":"foo","arguments":{...}}(Qwen 2 / 2.5). - Inner XML —
<function=NAME><parameter=KEY>VALUE</parameter>...</function>, one or more back-to-back inside a single wrapper (Qwen 3 +--jinja, Hermes-style).
§Chunk safety
Both the open marker (<tool_call>, 11 bytes) and the close marker
(</tool_call>, 12 bytes) may straddle SSE chunk boundaries. The parser
holds back at most CLOSE_MARKER.len() - 1 = 11 bytes per channel as a
lookahead buffer. The buffered bytes are flushed on the next push or at
ToolCallParser::finish.
§Cross-channel handling
In practice a Qwen tool call appears entirely on one channel — either
text (no reasoning split) or reasoning (when --reasoning-format is on).
Each channel therefore maintains its own independent parser state
(ChannelState) so that markup never crosses channels. The synthesised
tool-call IDs share a single monotonic counter across both channels.
Structs§
- Channel
State 🔒 - Per-channel scanning state. The text and reasoning channels each own one of these; they never share buffers.
- Qwen
XmlParser - Parser for the Qwen XML tool-call dialect. See module docs.
Enums§
- Channel 🔒
- Output channel selector — keeps
scanchannel-agnostic.
Constants§
Functions§
- finalize_
tool_ 🔒call - Parse the accumulated tool-call body and push the resulting
ToolCalls (or aNormalizationError) ontoout. - find_
own_ 🔒close - Find this tag’s own closing marker inside
rest: the LAST occurrence ofclosebefore the next siblingnext_openmarker (or before the end ofrest, if there is no next sibling). - forward 🔒
- Append
bytesto the channel-appropriate field ofout. - parse_
function_ 🔒xml_ body - Try to interpret
bodyas one or more back-to-back Hermes/Qwen3 inner-XML tool calls:<function=NAME><parameter=KEY>VALUE</parameter>...</function>, repeated. - parse_
json_ 🔒body - Try to interpret
bodyas a Qwen JSON tool call. - parse_
param_ 🔒value - Best-effort coercion of a
<parameter>body to a JSON value. Falls back to a string literal when the body is not valid JSON. - partial_
suffix_ 🔒len - Largest
nin[0, marker.len())such that the lastnbytes ofbufare a prefix ofmarker. Used as the lookahead window for chunk-safe marker detection.