diff --git a/crates/copilot_chat/src/copilot_chat.rs b/crates/copilot_chat/src/copilot_chat.rs index d1f339f89a01d1ed0d17e03b8712b42232177db8..850190701e526fe3fad896a17cdc704b89253fea 100644 --- a/crates/copilot_chat/src/copilot_chat.rs +++ b/crates/copilot_chat/src/copilot_chat.rs @@ -370,7 +370,7 @@ pub enum Tool { #[serde(rename_all = "lowercase")] pub enum ToolChoice { Auto, - Any, + Required, None, } @@ -1736,4 +1736,22 @@ mod tests { // Only /v1/messages endpoint -> supports_response = false (doesn't have /responses) assert!(!model_with_messages.supports_response()); } + + #[test] + fn test_tool_choice_required_serializes_as_required() { + // Regression test: ToolChoice::Required must serialize as "required" (not "any") + // for OpenAI-compatible APIs. Reverting the rename would break this. + assert_eq!( + serde_json::to_string(&ToolChoice::Required).unwrap(), + "\"required\"" + ); + assert_eq!( + serde_json::to_string(&ToolChoice::Auto).unwrap(), + "\"auto\"" + ); + assert_eq!( + serde_json::to_string(&ToolChoice::None).unwrap(), + "\"none\"" + ); + } } diff --git a/crates/copilot_chat/src/responses.rs b/crates/copilot_chat/src/responses.rs index 4f30ba1eb083c8a70c9a91853c7df37e65783ce3..1241a76fb1410461cef7337e2339180b18da7a3f 100644 --- a/crates/copilot_chat/src/responses.rs +++ b/crates/copilot_chat/src/responses.rs @@ -52,7 +52,7 @@ pub enum ToolDefinition { #[serde(rename_all = "lowercase")] pub enum ToolChoice { Auto, - Any, + Required, None, #[serde(untagged)] Other(ToolDefinition), @@ -408,3 +408,26 @@ pub async fn stream_response( } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_tool_choice_required_serializes_as_required() { + // Regression test: ToolChoice::Required must serialize as "required" (not "any") + // for OpenAI Responses API. Reverting the rename would break this. + assert_eq!( + serde_json::to_string(&ToolChoice::Required).unwrap(), + "\"required\"" + ); + assert_eq!( + serde_json::to_string(&ToolChoice::Auto).unwrap(), + "\"auto\"" + ); + assert_eq!( + serde_json::to_string(&ToolChoice::None).unwrap(), + "\"none\"" + ); + } +} diff --git a/crates/language_models/src/provider/copilot_chat.rs b/crates/language_models/src/provider/copilot_chat.rs index 7063db83bf65b82a4f314ad97e9463b106400c0b..e90d8208b4f37cfc31487768b94a2b943e2320ce 100644 --- a/crates/language_models/src/provider/copilot_chat.rs +++ b/crates/language_models/src/provider/copilot_chat.rs @@ -1046,7 +1046,7 @@ fn into_copilot_chat( tools, tool_choice: tool_choice.map(|choice| match choice { LanguageModelToolChoice::Auto => ToolChoice::Auto, - LanguageModelToolChoice::Any => ToolChoice::Any, + LanguageModelToolChoice::Any => ToolChoice::Required, LanguageModelToolChoice::None => ToolChoice::None, }), thinking_budget: None, @@ -1255,7 +1255,7 @@ fn into_copilot_responses( let mapped_tool_choice = tool_choice.map(|choice| match choice { LanguageModelToolChoice::Auto => responses::ToolChoice::Auto, - LanguageModelToolChoice::Any => responses::ToolChoice::Any, + LanguageModelToolChoice::Any => responses::ToolChoice::Required, LanguageModelToolChoice::None => responses::ToolChoice::None, });