mudler / mudler/vllm.cpp

fix(TOOLS-STREAMING-PARSER): a parenthesized Gemma-4 tool call does not parse, in both gemma4 surfaces

Open
#2,725 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
423
Forks
53
Avg merge
20h 26m
Merged PRs (30d)
310

Description

Row: TOOLS-STREAMING-PARSER (.agents/engine-matrix.md:165) for the engine config, and TOOLS-PARSER-BREADTH (.agents/engine-matrix.md:166) for the text-seam copy. Both resolved by line number before filing.

Found by wave PORTQ-7 (#2717) re-deriving PORT-NOW entry [246], upstream 9c8e90eb26 vllm#53657. Nothing was executed.

What is missing

A Gemma-4 tool call written with parentheses — call:name(a:1)<tool_call|> — is not parsed. Upstream added an OPEN_PAREN terminal, two TOOL_NAME transitions, and an unbalanced-trailing-paren strip. This tree carries the exact pre-commit state in two places.

Engine config, src/vllm/parser/engine/configs.cpp:

  • the terminal map at :820-824 is {THINK_START, THINK_END, TOOL_START, TOOL_END, CALL_PREFIX, OPEN_BRACE} — no OPEN_PAREN;
  • the transition table at :829-843 holds exactly the eleven pre-commit entries, and jumps straight from {{S::TOOL_NAME, "OPEN_BRACE"}, ...} at :839 to {{S::TOOL_ARGS, "TOOL_END"}, ...} at :840. Both transitions the commit adds are absent;
  • the converter at :800-804 is if (!text.empty() && text.back() == '}') text.pop_back(); — the endswith(")") and count("(") < count(")") arm is not there.

Text seam, src/vllm/entrypoints/openai/tool_parsers/gemma4.cpp:256, is the identical single-condition strip, under a comment at :252 that names _gemma4_arg_converter.

Both sites are the claim's full enumeration, not a sample: gemma4_arg_converter has exactly two implementations in this tree (configs.cpp:800, gemma4.cpp:256) and one config (configs.cpp:811). functiongemma is a different wire format and structural_tags.cpp carries no gemma4 mapping.

grep -rn "OPEN_PAREN" src/ include/ tests/ returns rc 1 with no hits; the positive control OPEN_BRACE through the identical probe form and scope returns 2 (configs.cpp:823, :839).

The commit is the whole distance

git show 5559679229:vllm/parser/gemma4.py:285-380 is character-for-character this tree's shape — same six terminals, same eleven transitions, same one-condition strip — and include/vllm/parser/gemma4.h:1 records the port as "@ 555967922". Not a pre-pin hole.

The second transition is a separate fix and must not be dropped

{S::TOOL_NAME, "TOOL_END"} -> CONTENT/{TOOL_CALL_END} is what keeps a call with no arguments at all from wedging in TOOL_NAME. It is independent of the paren handling, and reading the change as "add paren support" loses it.

Size

~12-16 product lines across two files. Tests must be authored, not ported: git show --stat 9c8e90eb26 lists one file and ships no test, so there is no upstream case to mirror. Budget ~60-100 test lines covering call:name(a:1)<tool_call|>, a balanced paren inside a delimited string (which must not be stripped), and the bare no-arguments call:name<tool_call|>, in both tests/vllm/parser/engine/ and tests/vllm/entrypoints/openai/tool_parsers/test_gemma4*.

Not to be confused with

d29dc3ab87 vllm#52430, the other in-range touch of gemma4.py, which flips the enable_thinking default and touches neither the converter nor the transitions. PORTQ-5 read it as entry [192]; it is a disjoint gap.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the converter and transition definitions in src/vllm/parser/engine/configs.cpp and the matching converter in src/vllm/entrypoints/openai/tool_parsers/gemma4.cpp. Run the parser tests under tests/vllm/parser/engine/ and tests/vllm/entrypoints/openai/tool_parsers/test_gemma4* before adding cases for parenthesized arguments, balanced parentheses in strings, and bare calls. Done means all cases pass in both Gemma-4 surfaces.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
backend, testing-qa
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.