fix: include closing brace in tool call arguments substring extraction - #531
Open
AshtonVaughan wants to merge 1 commit into
Open
fix: include closing brace in tool call arguments substring extraction#531AshtonVaughan wants to merge 1 commit into
AshtonVaughan wants to merge 1 commit into
Conversation
std::string::substr(pos, count) takes length as second arg, not end
position. The existing extraction:
arguments = json_str.substr(brace_start, brace_end - brace_start);
returns the substring [brace_start, brace_end), excluding the closing
brace at position brace_end. The resulting JSON is malformed:
{"limit": 6
instead of:
{"limit": 6}
Adding +1 to the length includes the closing brace.
Affects 7 sites across 5 model parsers: qwen2, qwen3, qwen3vl,
qwen3_5vl, nanbeige.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR aims to fix non-stream tool-call argument extraction by adjusting std::string::substr(pos, count) length calculations so the closing brace is included.
Changes:
- Update 7 tool-call argument substring extractions to use
brace_end - brace_start + 1. - Apply the same fix across Qwen2, Qwen3 (and variants), Qwen3VL, Qwen3.5VL, and Nanbeige non-stream parsers.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/common/AutoModel/modeling_qwen3vl.cpp | Adjusts non-stream tool-call arguments substring length. |
| src/common/AutoModel/modeling_qwen3_5vl.cpp | Adjusts non-stream tool-call arguments substring length. |
| src/common/AutoModel/modeling_qwen3.cpp | Adjusts non-stream tool-call arguments substring length in 3 parsers. |
| src/common/AutoModel/modeling_qwen2.cpp | Adjusts non-stream tool-call arguments substring length. |
| src/common/AutoModel/modeling_nanbeige.cpp | Adjusts non-stream tool-call arguments substring length. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug
std::string::substr(pos, count)takes length as the second argument, not end position. The current extraction in 7 places drops the closing brace:For input
"arguments": {"limit": 6}wherebrace_start=13andbrace_end=23, this returns 10 characters starting at index 13, which gives{"limit": 6instead of{"limit": 6}. The closing brace at position 23 is excluded.Fix
Add
+ 1to the length argument so the closing brace is included.Affected files
7 occurrences across 5 model parsers:
src/common/AutoModel/modeling_qwen2.cpp:136src/common/AutoModel/modeling_qwen3.cpp:151src/common/AutoModel/modeling_qwen3.cpp:296src/common/AutoModel/modeling_qwen3.cpp:500src/common/AutoModel/modeling_qwen3vl.cpp:248src/common/AutoModel/modeling_qwen3_5vl.cpp:258src/common/AutoModel/modeling_nanbeige.cpp:298Verification
C++ standard says
substr(pos, count)returns a substring of length up tocountstarting at positionpos. Last character is atpos + count - 1, so the original code excludes the character atbrace_end. After the fix, last character is atbrace_end, which is the closing brace.The streaming parsers (
parse_stream_content) usenlohmann::json::parseand were not affected by this bug. Only the non-streaming substring path was missing the closing brace.Possible related issue
This may explain part of #483 (tool call arguments serialization). When the closing brace is missing, downstream JSON parsers either fail or attempt error recovery, which could plausibly produce the int-as-string behaviour reported there. Recommend testing against #483's reproduction after this fix lands.