fix(config): reasoning_effort accepts mixed case

`reasoning_effort = "High"` in config.toml failed the whole parse: the
derived Deserialize matched lowercase variants only, while FromStr
lowercased its input. Deserialize now routes through FromStr, so both
paths share one vocabulary. Unknown tokens and non-strings still error.

Ported from upstream (grok-build sampling-types/types.rs, 1.0.35).
This commit is contained in:
ZacharyZhang-NY committed 2026-09-19 01:51:55 -04:00
1 parent 0fb971e9aa
commit 3ccb6e5e91
1 file changed
+29 -1
@@ -897,7 +897,7 @@ impl CompactionsRemaining {
}
/// Reasoning effort level. `None`/`Minimal` are omitted on the Anthropic Messages API.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, serde::Serialize)]
#[serde(rename_all = "lowercase")]
pub enum ReasoningEffort {
None,
@@ -982,6 +982,16 @@ impl std::str::FromStr for ReasoningEffort {
}
}
impl<'de> serde::Deserialize<'de> for ReasoningEffort {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let raw = String::deserialize(deserializer)?;
raw.parse().map_err(serde::de::Error::custom)
}
}
/// Canonical wire parse; remapped menu ids need a model catalog.
pub fn parse_canonical_effort_token(token: &str) -> Option<ReasoningEffort> {
token.parse().ok()
@@ -1849,6 +1859,24 @@ mod tests {
assert!(serde_json::from_str::<ReasoningEffort>("\"BOGUS\"").is_err());
}
#[test]
fn reasoning_effort_deserializes_mixed_case() {
for (token, want) in [
("\"High\"", ReasoningEffort::High),
("\"XHIGH\"", ReasoningEffort::Xhigh),
("\"mAx\"", ReasoningEffort::Max),
] {
let got: ReasoningEffort = serde_json::from_str(token).unwrap();
assert_eq!(got, want, "deserialize {token}");
}
let err = serde_json::from_str::<ReasoningEffort>("\"Highest\"").unwrap_err();
assert!(
err.to_string().contains("invalid reasoning effort"),
"{err}"
);
assert!(serde_json::from_str::<ReasoningEffort>("7").is_err());
}
#[test]
fn reasoning_effort_from_str_max_and_xhigh_are_distinct() {
assert_eq!(