use crate::llm_config::{model_catalog_entry, FastModeDef};
const DEPRECATED_STATUS: &str = "deprecated";
pub(crate) fn lookup(model: &str) -> Option<FastModeDef> {
model_catalog_entry(model).and_then(|entry| entry.fast_mode)
}
pub(crate) fn is_usable(fast_mode: &FastModeDef) -> bool {
fast_mode.status.as_deref() != Some(DEPRECATED_STATUS)
}
pub(crate) enum FastModeGate {
Usable,
Unsupported,
Deprecated { note: Option<String> },
}
pub(crate) fn gate(model: &str) -> FastModeGate {
match lookup(model) {
None => FastModeGate::Unsupported,
Some(fast_mode) if !is_usable(&fast_mode) => FastModeGate::Deprecated {
note: fast_mode.note,
},
Some(_) => FastModeGate::Usable,
}
}
pub(crate) fn apply_request_knob(body: &mut serde_json::Value, model: &str, fast: bool) {
if !fast {
return;
}
let Some(fast_mode) = lookup(model).filter(is_usable) else {
return;
};
if let Some(object) = body.as_object_mut() {
object.insert(fast_mode.param, serde_json::Value::String(fast_mode.value));
}
}
pub(crate) fn beta_header(model: &str, fast: bool) -> Option<String> {
if !fast {
return None;
}
lookup(model)
.filter(is_usable)
.and_then(|fast_mode| fast_mode.beta_header)
}
pub(crate) fn served_fast(model: &str, obj: &serde_json::Value) -> bool {
let Some(fast_mode) = lookup(model) else {
return false;
};
let matches = |scope: &serde_json::Value| {
scope.get(&fast_mode.param).and_then(|v| v.as_str()) == Some(fast_mode.value.as_str())
};
matches(obj) || obj.get("usage").map(matches).unwrap_or(false)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn lookup_resolves_anthropic_speed_knob() {
let fast = lookup("claude-opus-4-8").expect("opus 4.8 advertises fast mode");
assert_eq!(fast.param, "speed");
assert_eq!(fast.value, "fast");
assert_eq!(fast.beta_header.as_deref(), Some("fast-mode-2026-02-01"));
assert!(is_usable(&fast));
}
#[test]
fn gate_rejects_unsupported_and_deprecated() {
assert!(matches!(gate("gpt-4o"), FastModeGate::Unsupported));
assert!(matches!(
gate("claude-opus-4-6"),
FastModeGate::Deprecated { .. }
));
assert!(matches!(gate("gpt-5.5"), FastModeGate::Usable));
}
#[test]
fn apply_request_knob_sets_provider_field() {
let mut anthropic = serde_json::json!({"model": "claude-opus-4-8"});
apply_request_knob(&mut anthropic, "claude-opus-4-8", true);
assert_eq!(anthropic["speed"], serde_json::json!("fast"));
let mut openai = serde_json::json!({"model": "gpt-5.5"});
apply_request_knob(&mut openai, "gpt-5.5", true);
assert_eq!(openai["service_tier"], serde_json::json!("fast"));
}
#[test]
fn apply_request_knob_is_noop_when_off_or_unsupported() {
let mut body = serde_json::json!({"model": "claude-opus-4-8"});
apply_request_knob(&mut body, "claude-opus-4-8", false);
assert!(body.get("speed").is_none());
let mut unsupported = serde_json::json!({"model": "gpt-4o"});
apply_request_knob(&mut unsupported, "gpt-4o", true);
assert!(unsupported.get("service_tier").is_none());
}
#[test]
fn beta_header_only_for_beta_gated_tiers() {
assert_eq!(
beta_header("claude-opus-4-8", true).as_deref(),
Some("fast-mode-2026-02-01")
);
assert_eq!(beta_header("gpt-5.5", true), None);
assert_eq!(beta_header("claude-opus-4-8", false), None);
}
#[test]
fn served_fast_reads_echo_at_root_or_in_usage() {
let anthropic = serde_json::json!({"usage": {"speed": "fast", "output_tokens": 10}});
assert!(served_fast("claude-opus-4-8", &anthropic));
let openai = serde_json::json!({"service_tier": "fast", "usage": {"completion_tokens": 5}});
assert!(served_fast("gpt-5.5", &openai));
let downgraded = serde_json::json!({"service_tier": "default"});
assert!(!served_fast("gpt-5.5", &downgraded));
assert!(!served_fast(
"gpt-4o",
&serde_json::json!({"service_tier": "fast"})
));
}
}