From 25ced2e3c2e1c5aa81c8b51fec721613563687a6 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 9 May 2025 14:14:36 +0200 Subject: [PATCH] Fix error when Copilot calls tools without arguments (#30371) Fixes https://github.com/zed-industries/zed/issues/30346 The model can output an empty string to indicate the absence of arguments, which can't be parsed as a `serde_json::Value`. When that happens, we now create an empty object instead on behalf of the model. Release Notes: - Fixed a bug that prevented Copilot models from calling the `diagnostic` tool. --- .../src/provider/copilot_chat.rs | 47 +++++++++++-------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/crates/language_models/src/provider/copilot_chat.rs b/crates/language_models/src/provider/copilot_chat.rs index fe11458282..d200248269 100644 --- a/crates/language_models/src/provider/copilot_chat.rs +++ b/crates/language_models/src/provider/copilot_chat.rs @@ -368,25 +368,34 @@ pub fn map_to_language_model_completion_events( } Some("tool_calls") => { events.extend(state.tool_calls_by_index.drain().map( - |(_, tool_call)| match serde_json::Value::from_str( - &tool_call.arguments, - ) { - Ok(input) => Ok(LanguageModelCompletionEvent::ToolUse( - LanguageModelToolUse { - id: tool_call.id.clone().into(), - name: tool_call.name.as_str().into(), - is_input_complete: true, - input, - raw_input: tool_call.arguments.clone(), - }, - )), - Err(error) => { - Err(LanguageModelCompletionError::BadInputJson { - id: tool_call.id.into(), - tool_name: tool_call.name.as_str().into(), - raw_input: tool_call.arguments.into(), - json_parse_error: error.to_string(), - }) + |(_, tool_call)| { + // The model can output an empty string + // to indicate the absence of arguments. + // When that happens, create an empty + // object instead. + let arguments = if tool_call.arguments.is_empty() { + Ok(serde_json::Value::Object(Default::default())) + } else { + serde_json::Value::from_str(&tool_call.arguments) + }; + match arguments { + Ok(input) => Ok(LanguageModelCompletionEvent::ToolUse( + LanguageModelToolUse { + id: tool_call.id.clone().into(), + name: tool_call.name.as_str().into(), + is_input_complete: true, + input, + raw_input: tool_call.arguments.clone(), + }, + )), + Err(error) => { + Err(LanguageModelCompletionError::BadInputJson { + id: tool_call.id.into(), + tool_name: tool_call.name.as_str().into(), + raw_input: tool_call.arguments.into(), + json_parse_error: error.to_string(), + }) + } } }, ));