[Bugfix] Handle parenthesized Gemma4 tool calls (#53657)

Signed-off-by: Taneem Ibrahim <taneem.ibrahim@gmail.com>

Taneem Ibrahim committed Aug 25, 2026 at 08:21 UTC 9c8e90eb2637a863ca14e47fd436b10ed7ba6536
1 file changed +10 -1
vllm/parser/gemma4.py
+10 -1
@@ -285,7 +285,7 @@ def _parse_gemma4_array(arr_str: str, *, partial: bool = False) -> list:
285 def _gemma4_arg_converter(raw_args: str, partial: bool) -> str:
286 """Convert Gemma4 custom arg format to a JSON string."""
287 text = raw_args.strip()
288 - if text.endswith("}"):
288 + if text.endswith("}") or text.endswith(")") and text.count("(") < text.count(")"):
289 text = text[:-1]
290
291 parsed = _parse_gemma4_args(text, partial=partial)
@@ -304,6 +304,7 @@ def gemma4_config() -> ParserEngineConfig:
304 "TOOL_END": TOOL_CALL_END,
305 "CALL_PREFIX": "call:",
306 "OPEN_BRACE": "{",
307 + "OPEN_PAREN": "(",
308 },
309 token_id_terminals={
310 "THINK_START": CHANNEL_START,
@@ -351,6 +352,14 @@ def gemma4_config() -> ParserEngineConfig:
352 ParserState.TOOL_ARGS,
353 (),
354 ),
355 + (ParserState.TOOL_NAME, "OPEN_PAREN"): Transition(
356 + ParserState.TOOL_ARGS,
357 + (),
358 + ),
359 + (ParserState.TOOL_NAME, "TOOL_END"): Transition(
360 + ParserState.CONTENT,
361 + (EventType.TOOL_CALL_END,),
362 + ),
363 (ParserState.TOOL_ARGS, "TOOL_END"): Transition(
364 ParserState.CONTENT,
365 (EventType.TOOL_CALL_END,),