From e4515dc4e07a12464018c423370096d89e501218 Mon Sep 17 00:00:00 2001 From: nanoha <20983037+LyricalNanoha@users.noreply.github.com> Date: Thu, 27 Aug 2026 14:02:16 +0800 Subject: [PATCH] fix: omit tools field from provider requests when empty vLLM and some OpenAI-compatible APIs reject requests containing an empty `tools: []` array with a 400 Bad Request. This affects the model connectivity test which sends no tools. Instead of always including the tools field, conditionally add it only when tools are present. --- server/src/provider/anthropic.rs | 10 ++++++---- server/src/provider/openai_chat.rs | 8 +++++--- server/src/provider/openai_responses.rs | 10 ++++++---- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/server/src/provider/anthropic.rs b/server/src/provider/anthropic.rs index b11eecd..125a519 100644 --- a/server/src/provider/anthropic.rs +++ b/server/src/provider/anthropic.rs @@ -54,11 +54,13 @@ impl Provider for AnthropicProvider { .unwrap_or(DEFAULT_MAX_OUTPUT_TOKENS); let mut body = json!({ "model": request.model.model_id, "system": request.prompt.instructions, "messages": messages, - "max_tokens": max_tokens, "stream": true, - "tools": request.prompt.tools.iter().map(|tool| json!({ - "name": tool.name, "description": tool.description, "input_schema": tool.parameters - })).collect::>() + "max_tokens": max_tokens, "stream": true }); + if !request.prompt.tools.is_empty() { + body["tools"] = json!(request.prompt.tools.iter().map(|tool| json!({ + "name": tool.name, "description": tool.description, "input_schema": tool.parameters + })).collect::>()); + } apply_model(&mut body, &request.model)?; merge_extra_params(&mut body, &request.model.extra_params)?; if let Some(recorder) = &recorder { diff --git a/server/src/provider/openai_chat.rs b/server/src/provider/openai_chat.rs index bea7cb2..8a9847d 100644 --- a/server/src/provider/openai_chat.rs +++ b/server/src/provider/openai_chat.rs @@ -65,12 +65,14 @@ impl Provider for OpenAiChatProvider { let mut body = json!({ "model": request.model.model_id, "messages": messages, - "tools": request.prompt.tools.iter().map(|tool| json!({"type":"function","function":{ - "name": tool.name, "description": tool.description, "parameters": tool.parameters - }})).collect::>(), "stream": true, "stream_options": {"include_usage": true} }); + if !request.prompt.tools.is_empty() { + body["tools"] = json!(request.prompt.tools.iter().map(|tool| json!({"type":"function","function":{ + "name": tool.name, "description": tool.description, "parameters": tool.parameters + }})).collect::>()); + } apply_model(&mut body, &request.model, config.max_output_tokens)?; merge_extra_params(&mut body, &request.model.extra_params)?; apply_openai_prompt_cache_key(&mut body, &request.model.model_id)?; diff --git a/server/src/provider/openai_responses.rs b/server/src/provider/openai_responses.rs index f209328..ab6ce8d 100644 --- a/server/src/provider/openai_responses.rs +++ b/server/src/provider/openai_responses.rs @@ -69,12 +69,14 @@ impl Provider for OpenAiResponsesProvider { let mut body = json!({ "model": request.model.model_id, "input": input, "stream": true, "instructions": request.prompt.instructions, - "include": ["reasoning.encrypted_content"], - "tools": request.prompt.tools.iter().map(|tool| json!({ + "include": ["reasoning.encrypted_content"] + }); + if !request.prompt.tools.is_empty() { + body["tools"] = json!(request.prompt.tools.iter().map(|tool| json!({ "type":"function", "name":tool.name, "description":tool.description, "parameters":tool.parameters, "strict":false - })).collect::>() - }); + })).collect::>()); + } apply_model(&mut body, &request.model, config.max_output_tokens)?; merge_extra_params(&mut body, &request.model.extra_params)?; apply_openai_prompt_cache_key(&mut body, &request.model.model_id)?;