[Bugfix] fix: stream Mimimax m2 tool call string arguments (#46382)

Signed-off-by: chaunceyjiang <chaunceyjiang@gmail.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Flora Feng <4florafeng@gmail.com>

Chauncey committed Jun 25, 2026 at 11:12 UTC efb5acffd54ba52c6c76e2395283448d7d8a1e9d
1 file changed +33 -2
vllm/parser/minimax_m2.py
+33 -2
@@ -38,13 +38,21 @@ INVOKE_END = "</invoke>"
38 NAME_END_DQ = '">'
39 NAME_END_SQ = "'>"
40 NAME_END_UNQUOTED = ">"
41 -
41 +PARAM_START = "<parameter name="
42 +PARAM_END = "</parameter>"
43 _PARAM_RE = re.compile(
44 r"<\s*parameter\s+name\s*=\s*"
45 r"(?:\"(?P<dq_name>[^\"]*)\"|'(?P<sq_name>[^']*)'|(?P<bare_name>[^>\s]+))"
46 r"\s*>"
47 r"(?P<value>.*?)"
47 - r"<\s*/\s*parameter\s*>",
48 + r"(?:<\s*/\s*parameter\s*>|(?=<\s*parameter\s+name\s*=))",
49 + re.DOTALL,
50 +)
51 +_PARTIAL_PARAM_RE = re.compile(
52 + r"<\s*parameter\s+name\s*=\s*"
53 + r"(?:\"(?P<dq_name>[^\"]*)\"|'(?P<sq_name>[^']*)'|(?P<bare_name>[^>\s]+))"
54 + r"\s*>"
55 + r"(?P<value>.*)$",
56 re.DOTALL,
57 )
58
@@ -63,6 +71,19 @@ def _minimax_m2_arg_converter(raw_args: str, partial: bool) -> str:
71 continue
72 params[name] = match.group("value").strip()
73
74 + if partial:
75 + remaining = _PARAM_RE.sub("", raw_args)
76 + match = _PARTIAL_PARAM_RE.search(remaining)
77 + if match:
78 + name = (
79 + match.group("dq_name")
80 + or match.group("sq_name")
81 + or match.group("bare_name")
82 + or ""
83 + ).strip()
84 + if name:
85 + params[name] = match.group("value").strip()
86 +
87 return json.dumps(params, ensure_ascii=False)
88
89
@@ -75,6 +96,8 @@ def minimax_m2_config() -> ParserEngineConfig:
96 "THINK_START": THINK_START,
97 "THINK_END": THINK_END,
98 "TOOL_START": TOOL_CALL_START,
99 + "PARAM_START": PARAM_START,
100 + "PARAM_END": PARAM_END,
101 "TOOL_END": TOOL_CALL_END,
102 "INVOKE_PREFIX_DQ": INVOKE_PREFIX_DQ,
103 "INVOKE_PREFIX_SQ": INVOKE_PREFIX_SQ,
@@ -111,6 +134,14 @@ def minimax_m2_config() -> ParserEngineConfig:
134 ParserState.TOOL_PREAMBLE,
135 (),
136 ),
137 + (ParserState.TOOL_ARGS, "PARAM_START"): Transition(
138 + ParserState.TOOL_ARGS,
139 + (EventType.ARG_VALUE_CHUNK,),
140 + ),
141 + (ParserState.TOOL_ARGS, "PARAM_END"): Transition(
142 + ParserState.TOOL_ARGS,
143 + (EventType.ARG_VALUE_CHUNK,),
144 + ),
145 (ParserState.TOOL_PREAMBLE, "TOOL_END"): Transition(
146 ParserState.CONTENT,
147 (),