gestura_core/
openai_compat.rs1pub fn should_retry_without_temperature(status_code: u16, body_text: &str) -> bool {
14 if status_code != 400 {
15 return false;
16 }
17
18 let Ok(v) = serde_json::from_str::<serde_json::Value>(body_text) else {
19 return body_text.to_ascii_lowercase().contains("temperature")
20 && body_text.to_ascii_lowercase().contains("unsupported");
21 };
22
23 let err = &v["error"];
24 let param = err["param"].as_str().unwrap_or_default();
25 let code = err["code"].as_str().unwrap_or_default();
26 let msg = err["message"]
27 .as_str()
28 .unwrap_or_default()
29 .to_ascii_lowercase();
30
31 (param == "temperature" && code == "unsupported_value")
32 || (msg.contains("temperature")
33 && (msg.contains("unsupported") || msg.contains("only the default")))
34}
35
36#[cfg(test)]
37mod tests {
38 use super::*;
39
40 #[test]
41 fn detects_structured_temperature_unsupported_error() {
42 let body = r#"{
43 \"error\": {
44 \"message\": \"Unsupported value: 'temperature' does not support 0.2 with this model. Only the default (1) value is supported.\",
45 \"type\": \"invalid_request_error\",
46 \"param\": \"temperature\",
47 \"code\": \"unsupported_value\"
48 }
49 }"#;
50 assert!(should_retry_without_temperature(400, body));
51 }
52
53 #[test]
54 fn does_not_retry_on_non_400() {
55 let body = r#"{\"error\":{\"param\":\"temperature\",\"code\":\"unsupported_value\"}}"#;
56 assert!(!should_retry_without_temperature(401, body));
57 }
58
59 #[test]
60 fn tolerant_to_non_json_body() {
61 let body = "Unsupported value: temperature";
62 assert!(should_retry_without_temperature(400, body));
63 }
64}