diff --git a/crates/goose/src/providers/formats/openai.rs b/crates/goose/src/providers/formats/openai.rs index 7633b857..ec880c6a 100644 --- a/crates/goose/src/providers/formats/openai.rs +++ b/crates/goose/src/providers/formats/openai.rs @@ -32,10 +32,17 @@ type ToolCallData = HashMap< ), >; +fn deserialize_null_default_string<'de, D>(deserializer: D) -> Result +where + D: serde::Deserializer<'de>, +{ + Ok(Option::::deserialize(deserializer)?.unwrap_or_default()) +} + #[derive(Serialize, Deserialize, Debug, Default)] struct DeltaToolCallFunction { name: Option, - #[serde(default)] + #[serde(default, deserialize_with = "deserialize_null_default_string")] arguments: String, } @@ -2435,4 +2442,21 @@ data: [DONE]"#; ); Ok(()) } + + #[test] + fn test_delta_tool_call_function_accepts_null_arguments() { + let raw = r#"{"arguments":null}"#; + let parsed: DeltaToolCallFunction = + serde_json::from_str(raw).expect("null arguments must deserialize"); + assert_eq!(parsed.arguments, ""); + + let raw = r#"{}"#; + let parsed: DeltaToolCallFunction = + serde_json::from_str(raw).expect("missing arguments must deserialize"); + assert_eq!(parsed.arguments, ""); + + let raw = r#"{"arguments":"{\"k\":1}"}"#; + let parsed: DeltaToolCallFunction = serde_json::from_str(raw).unwrap(); + assert_eq!(parsed.arguments, "{\"k\":1}"); + } }