From 82ee6d4410cfad52b0d5d73d00737864297a9950 Mon Sep 17 00:00:00 2001 From: Javinator9889 Date: Fri, 18 Sep 2026 12:42:31 +0200 Subject: [PATCH] fix: drop a tool call that generation never finished When neither nor is present the call was cut off, normally by the output limit while writing a large argument. Taking the remainder of the text fabricates a complete-looking call from a partial one, and the client cannot tell: the arguments JSON is well formed because it is rebuilt from the parsed parameters. A shell heredoc cut mid-body becomes an unterminated `cat < fallback is kept: a block missing only the outer tag is complete. Measured on qwen3.5:9b, a 300-line heredoc at max_tokens=400: before, tool_calls=true with 1580 chars of arguments and no closing EOF; after, tool_calls=false with finish_reason "length". A complete call is unaffected: finish_reason "tool_calls", arguments {"command":"echo hello"}. Refs #741 --- src/common/AutoModel/modeling_qwen3_5_omni.cpp | 11 ++++++++++- src/common/AutoModel/modeling_qwen3_5vl.cpp | 11 ++++++++++- src/common/AutoModel/modeling_qwen3_6_moe.cpp | 11 ++++++++++- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/common/AutoModel/modeling_qwen3_5_omni.cpp b/src/common/AutoModel/modeling_qwen3_5_omni.cpp index 28695786d..682fcaa0e 100644 --- a/src/common/AutoModel/modeling_qwen3_5_omni.cpp +++ b/src/common/AutoModel/modeling_qwen3_5_omni.cpp @@ -793,7 +793,16 @@ NonStreamResult Qwen3_5_Omni::parse_nstream_content(const std::string response_t if (func_end_pos != std::string::npos) { block_end = func_end_pos + func_end_tag.length(); } else { - block_end = response_text.length(); + // Neither closing tag is present, so generation stopped inside + // the call -- almost always because it hit the output limit + // while writing a large argument. Taking the remainder here + // fabricates a complete-looking call from a partial one: the + // arguments JSON is well formed, because it is rebuilt from the + // parsed parameters, so the client cannot tell it is truncated + // and runs it. A heredoc cut mid-body becomes an unterminated + // `cat <