From ad1ecade28a3909da212c36da108a8357056970d Mon Sep 17 00:00:00 2001 From: AshtonVaughan Date: Thu, 30 Apr 2026 19:32:53 +1000 Subject: [PATCH] fix: include closing brace in tool call arguments substring extraction 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. --- src/common/AutoModel/modeling_nanbeige.cpp | 2 +- src/common/AutoModel/modeling_qwen2.cpp | 2 +- src/common/AutoModel/modeling_qwen3.cpp | 6 +++--- src/common/AutoModel/modeling_qwen3_5vl.cpp | 2 +- src/common/AutoModel/modeling_qwen3vl.cpp | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/common/AutoModel/modeling_nanbeige.cpp b/src/common/AutoModel/modeling_nanbeige.cpp index edfe7b64..57c16349 100644 --- a/src/common/AutoModel/modeling_nanbeige.cpp +++ b/src/common/AutoModel/modeling_nanbeige.cpp @@ -295,7 +295,7 @@ NonStreamResult Nanbeige::parse_nstream_content(const std::string response_text) size_t brace_end = json_str.rfind("}"); // Find the last closing brace if (brace_start != std::string::npos && brace_end != std::string::npos && brace_end > brace_start) { - arguments = json_str.substr(brace_start, brace_end - brace_start); + arguments = json_str.substr(brace_start, brace_end - brace_start + 1); } } diff --git a/src/common/AutoModel/modeling_qwen2.cpp b/src/common/AutoModel/modeling_qwen2.cpp index efc02774..50aab355 100644 --- a/src/common/AutoModel/modeling_qwen2.cpp +++ b/src/common/AutoModel/modeling_qwen2.cpp @@ -133,7 +133,7 @@ NonStreamResult Qwen2::parse_nstream_content(const std::string response_text) { size_t brace_end = json_str.rfind("}"); // Find the last closing brace if (brace_start != std::string::npos && brace_end != std::string::npos && brace_end > brace_start) { - arguments = json_str.substr(brace_start, brace_end - brace_start); + arguments = json_str.substr(brace_start, brace_end - brace_start + 1); } } diff --git a/src/common/AutoModel/modeling_qwen3.cpp b/src/common/AutoModel/modeling_qwen3.cpp index 4881e291..1104179c 100644 --- a/src/common/AutoModel/modeling_qwen3.cpp +++ b/src/common/AutoModel/modeling_qwen3.cpp @@ -148,7 +148,7 @@ NonStreamResult Qwen3::parse_nstream_content(const std::string response_text) { size_t brace_end = json_str.rfind("}"); // Find the last closing brace if (brace_start != std::string::npos && brace_end != std::string::npos && brace_end > brace_start) { - arguments = json_str.substr(brace_start, brace_end - brace_start); + arguments = json_str.substr(brace_start, brace_end - brace_start + 1); } } @@ -293,7 +293,7 @@ NonStreamResult Qwen3_IT::parse_nstream_content(const std::string response_text) size_t brace_end = json_str.rfind("}"); // Find the last closing brace if (brace_start != std::string::npos && brace_end != std::string::npos && brace_end > brace_start) { - arguments = json_str.substr(brace_start, brace_end - brace_start); + arguments = json_str.substr(brace_start, brace_end - brace_start + 1); } } @@ -497,7 +497,7 @@ NonStreamResult Qwen3_TK::parse_nstream_content(const std::string response_text) size_t brace_end = json_str.rfind("}"); // Find the last closing brace if (brace_start != std::string::npos && brace_end != std::string::npos && brace_end > brace_start) { - arguments = json_str.substr(brace_start, brace_end - brace_start); + arguments = json_str.substr(brace_start, brace_end - brace_start + 1); } } diff --git a/src/common/AutoModel/modeling_qwen3_5vl.cpp b/src/common/AutoModel/modeling_qwen3_5vl.cpp index 0ce0e2a7..87e66fca 100644 --- a/src/common/AutoModel/modeling_qwen3_5vl.cpp +++ b/src/common/AutoModel/modeling_qwen3_5vl.cpp @@ -255,7 +255,7 @@ NonStreamResult Qwen3_5VL::parse_nstream_content(const std::string response_text size_t brace_end = json_str.rfind("}"); // Find the last closing brace if (brace_start != std::string::npos && brace_end != std::string::npos && brace_end > brace_start) { - arguments = json_str.substr(brace_start, brace_end - brace_start); + arguments = json_str.substr(brace_start, brace_end - brace_start + 1); } } diff --git a/src/common/AutoModel/modeling_qwen3vl.cpp b/src/common/AutoModel/modeling_qwen3vl.cpp index 884314b7..22107215 100644 --- a/src/common/AutoModel/modeling_qwen3vl.cpp +++ b/src/common/AutoModel/modeling_qwen3vl.cpp @@ -245,7 +245,7 @@ NonStreamResult Qwen3VL::parse_nstream_content(const std::string response_text) size_t brace_end = json_str.rfind("}"); // Find the last closing brace if (brace_start != std::string::npos && brace_end != std::string::npos && brace_end > brace_start) { - arguments = json_str.substr(brace_start, brace_end - brace_start); + arguments = json_str.substr(brace_start, brace_end - brace_start + 1); } }