use crate::request::ReasoningEffort;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum Effort {
Low,
Medium,
High,
XHigh,
Max,
}
impl Effort {
pub const ALL: [Effort; 5] = [
Effort::Low,
Effort::Medium,
Effort::High,
Effort::XHigh,
Effort::Max,
];
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
Effort::Low => "low",
Effort::Medium => "medium",
Effort::High => "high",
Effort::XHigh => "xhigh",
Effort::Max => "max",
}
}
#[must_use]
pub fn parse(name: &str) -> Option<Effort> {
let name = name.trim().to_ascii_lowercase();
Effort::ALL.into_iter().find(|e| e.as_str() == name)
}
#[must_use]
pub fn hint(self) -> &'static str {
match self {
Effort::Low => "fastest; short, scoped tasks",
Effort::Medium => "balanced",
Effort::High => "the API default",
Effort::XHigh => "best for coding and agentic work",
Effort::Max => "deepest; correctness over cost",
}
}
#[must_use]
pub fn maps_to(self, api_schema: &str) -> &'static str {
match api_schema {
"anthropic" | "openai-responses" => self.as_str(),
_ => "—",
}
}
}
impl From<Effort> for ReasoningEffort {
fn from(effort: Effort) -> Self {
match effort {
Effort::Low => ReasoningEffort::Low,
Effort::Medium => ReasoningEffort::Medium,
Effort::High => ReasoningEffort::High,
Effort::XHigh => ReasoningEffort::XHigh,
Effort::Max => ReasoningEffort::Max,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn names_round_trip_case_insensitively() {
for effort in Effort::ALL {
assert_eq!(Effort::parse(effort.as_str()), Some(effort));
assert_eq!(Effort::parse(&effort.as_str().to_uppercase()), Some(effort));
assert_eq!(
Effort::parse(&format!(" {} ", effort.as_str())),
Some(effort)
);
}
assert_eq!(Effort::parse("ultra"), None, "the ladder is closed");
assert_eq!(Effort::parse(""), None);
}
#[test]
fn the_ladder_is_ordered_shallow_to_deep() {
assert!(Effort::Low < Effort::Medium);
assert!(Effort::High < Effort::XHigh);
assert!(Effort::XHigh < Effort::Max);
}
#[test]
fn every_rung_has_a_distinct_neutral_tier() {
let tiers: Vec<ReasoningEffort> = Effort::ALL.into_iter().map(Into::into).collect();
for (i, a) in tiers.iter().enumerate() {
for b in &tiers[i + 1..] {
assert_ne!(a, b, "two rungs collapsed onto the same neutral tier");
}
}
}
#[test]
fn anthropic_mapping_is_identity_and_unknown_wires_say_so() {
for effort in Effort::ALL {
assert_eq!(effort.maps_to("anthropic"), effort.as_str());
}
assert_eq!(Effort::High.maps_to("mock"), "—");
}
}