From 0c969d8aea84f6b4bc102cf2f1f88a6676df3a00 Mon Sep 17 00:00:00 2001 From: Philipp Henkel Date: Sat, 25 Apr 2026 16:47:12 +0200 Subject: [PATCH] fix: convert quoted numeric values to numbers Signed-off-by: Philipp Henkel --- crates/goose/src/config/base.rs | 64 +++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/crates/goose/src/config/base.rs b/crates/goose/src/config/base.rs index 93b562ca9c8e..7b569a9c573a 100644 --- a/crates/goose/src/config/base.rs +++ b/crates/goose/src/config/base.rs @@ -732,10 +732,20 @@ impl Config { } let values = self.load()?; - values + let value = values .get(key) - .ok_or_else(|| ConfigError::NotFound(key.to_string())) - .and_then(|v| Ok(serde_yaml::from_value(v.clone())?)) + .ok_or_else(|| ConfigError::NotFound(key.to_string()))?; + + match serde_yaml::from_value(value.clone()) { + Ok(value) => Ok(value), + Err(yaml_err) => { + let Some(string_value) = value.as_str() else { + return Err(yaml_err.into()); + }; + let parsed = Self::parse_env_value(string_value)?; + serde_json::from_value(parsed).map_err(|_| yaml_err.into()) + } + } } fn load_defaults(&self) -> Option { @@ -1164,6 +1174,54 @@ mod tests { assert!(matches!(result, Err(ConfigError::NotFound(_)))); } + #[test] + fn test_get_param_reads_numeric_yaml_as_u64() -> Result<(), ConfigError> { + let _guard = env_lock::lock_env([("XXX_TIMEOUT", None::<&str>)]); + let config = new_test_config(); + + config.set_param("XXX_TIMEOUT", 300_u64)?; + + let value: u64 = config.get_param("XXX_TIMEOUT")?; + assert_eq!(value, 300); + Ok(()) + } + + #[test] + fn test_get_param_reads_quoted_numeric_yaml_as_u64() -> Result<(), ConfigError> { + let _guard = env_lock::lock_env([("XXX_TIMEOUT", None::<&str>)]); + let config = new_test_config(); + + config.set_param("XXX_TIMEOUT", "300")?; + + let value: u64 = config.get_param("XXX_TIMEOUT")?; + assert_eq!(value, 300); + Ok(()) + } + + #[test] + fn test_get_param_reads_quoted_numeric_yaml_as_string() -> Result<(), ConfigError> { + let _guard = env_lock::lock_env([("XXX_TIMEOUT", None::<&str>)]); + let config = new_test_config(); + + config.set_param("XXX_TIMEOUT", "300")?; + + let value: String = config.get_param("XXX_TIMEOUT")?; + assert_eq!(value, "300"); + Ok(()) + } + + #[test] + fn test_get_param_rejects_invalid_string_as_u64() -> Result<(), ConfigError> { + let _guard = env_lock::lock_env([("XXX_TIMEOUT", None::<&str>)]); + let config = new_test_config(); + + config.set_param("XXX_TIMEOUT", "invalid")?; + + let result: Result = config.get_param("XXX_TIMEOUT"); + assert!(matches!(result, Err(ConfigError::DeserializeError(_)))); + Ok(()) + } + #[test] fn test_yaml_formatting() -> Result<(), ConfigError> { let config_file = NamedTempFile::new().unwrap();