From a3c20531e5db28004aab90c8031ae331ff334f04 Mon Sep 17 00:00:00 2001 From: morgmart <98432065+morgmart@users.noreply.github.com> Date: Thu, 23 Jul 2026 17:40:27 -0700 Subject: [PATCH] fix overlong function names in provider requests (#10659) --- .../src/formats/openai.rs | 18 ++++++++++++- .../src/formats/openai_responses.rs | 26 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/crates/goose-provider-types/src/formats/openai.rs b/crates/goose-provider-types/src/formats/openai.rs index f03411b24..0cb9a4f1f 100644 --- a/crates/goose-provider-types/src/formats/openai.rs +++ b/crates/goose-provider-types/src/formats/openai.rs @@ -1577,10 +1577,15 @@ pub(crate) fn openai_reasoning_efforts_for_model(model_name: &str) -> &'static [ } } +const MAX_FUNCTION_NAME_LENGTH: usize = 128; + pub fn sanitize_function_name(name: &str) -> String { static RE: OnceLock = OnceLock::new(); let re = RE.get_or_init(|| Regex::new(r"[^a-zA-Z0-9_-]").unwrap()); - re.replace_all(name, "_").to_string() + re.replace_all(name, "_") + .chars() + .take(MAX_FUNCTION_NAME_LENGTH) + .collect() } pub fn is_valid_function_name(name: &str) -> bool { @@ -4160,12 +4165,23 @@ data: [DONE]"#; assert_eq!(sanitize_function_name("hello-world"), "hello-world"); assert_eq!(sanitize_function_name("hello world"), "hello_world"); assert_eq!(sanitize_function_name("hello@world"), "hello_world"); + assert_eq!( + sanitize_function_name(&"a".repeat(MAX_FUNCTION_NAME_LENGTH)), + "a".repeat(MAX_FUNCTION_NAME_LENGTH) + ); + assert_eq!( + sanitize_function_name(&"a".repeat(MAX_FUNCTION_NAME_LENGTH + 32)), + "a".repeat(MAX_FUNCTION_NAME_LENGTH) + ); } #[test] fn test_is_valid_function_name() { assert!(is_valid_function_name("hello-world")); assert!(is_valid_function_name("hello_world")); + assert!(is_valid_function_name( + &"a".repeat(MAX_FUNCTION_NAME_LENGTH + 1) + )); assert!(!is_valid_function_name("hello world")); assert!(!is_valid_function_name("hello@world")); } diff --git a/crates/goose-provider-types/src/formats/openai_responses.rs b/crates/goose-provider-types/src/formats/openai_responses.rs index 6f555a1aa..3802e78f5 100644 --- a/crates/goose-provider-types/src/formats/openai_responses.rs +++ b/crates/goose-provider-types/src/formats/openai_responses.rs @@ -2157,6 +2157,32 @@ mod tests { assert_eq!(input[1]["name"], "_Review_Agent"); } + #[test] + fn test_responses_request_limits_replayed_function_call_names() { + use crate::conversation::message::Message; + + let messages = vec![Message::assistant().with_tool_request( + "call_long_name", + Ok(CallToolRequestParams::new("a".repeat(160))), + )]; + let model_config = ModelConfig { + model_name: "gpt-5.5".to_string(), + context_limit: None, + temperature: None, + max_tokens: None, + toolshim: false, + toolshim_model: None, + request_params: None, + reasoning: None, + request_headers: None, + }; + + let result = create_responses_request(&model_config, "", &messages, &[]).unwrap(); + let name = result["input"][0]["name"].as_str().unwrap(); + + assert_eq!(name.len(), 128); + } + #[test] fn test_tool_request_error_emits_function_call_output() { use crate::conversation::message::Message;