use super::{DeepSeekAdapter, OllamaAdapter};
use crate::adapter::AdapterDispatcher;
use crate::adapter::{Adapter, AdapterKind, ServiceType};
use crate::chat::{ChatOptions, ChatOptionsSet, ChatRequest, ReasoningEffort};
use crate::resolver::{AuthData, Endpoint};
use crate::{ModelIden, ServiceTarget};
use serde_json::Value;
type Result<T> = core::result::Result<T, Box<dyn std::error::Error>>;
#[test]
fn test_api_route_dispatch_preserves_model_and_uses_gateway_endpoint() -> Result<()> {
for model_name in ["gpt-6.1-sol", "claude-fable-5-1", "vendor/model-id"] {
let namespaced = format!("api_route::{model_name}");
let kind = AdapterKind::from_model(&namespaced)?;
assert_eq!(kind, AdapterKind::ApiRoute);
assert_eq!(kind.default_key_env_name(), Some("API_ROUTE_API_KEY"));
let request = AdapterDispatcher::to_web_request_data(
ServiceTarget {
model: ModelIden::new(kind, namespaced),
auth: AuthData::from_single("test-route-key"),
endpoint: AdapterDispatcher::default_endpoint(kind),
},
ServiceType::Chat,
ChatRequest::from_user("hello"),
ChatOptionsSet::default(),
)?;
assert_eq!(request.url, "https://global.api-route.com/v1/chat/completions");
assert_eq!(request.payload["model"], model_name);
assert!(
request.headers.iter().any(|(name, value)| {
name.eq_ignore_ascii_case("authorization") && value == "Bearer test-route-key"
})
);
}
assert_eq!(AdapterKind::from_model("claude-fable-5-1")?, AdapterKind::Anthropic);
Ok(())
}
#[test]
fn test_deepseek_managed_body_thinking_enables_non_zero_effort() -> Result<()> {
let reasoning_effort = Some(ReasoningEffort::Max);
let payload = support_deepseek_payload(reasoning_effort)?;
assert_eq!(payload["thinking"]["type"], "enabled");
assert_eq!(payload["reasoning_effort"], "max");
Ok(())
}
#[test]
fn test_deepseek_managed_body_thinking_disables_zero_effort() -> Result<()> {
let reasoning_effort = Some(ReasoningEffort::Zero);
let payload = support_deepseek_payload(reasoning_effort)?;
assert_eq!(payload["thinking"]["type"], "disabled");
assert!(payload.get("reasoning_effort").is_none());
Ok(())
}
#[test]
fn test_deepseek_managed_body_thinking_omits_fields_without_effort() -> Result<()> {
let reasoning_effort = None;
let payload = support_deepseek_payload(reasoning_effort)?;
assert!(payload.get("thinking").is_none());
assert!(payload.get("reasoning_effort").is_none());
Ok(())
}
#[test]
fn test_ollama_think_omitted_without_effort() -> Result<()> {
let reasoning_effort = None;
let payload = support_ollama_payload(reasoning_effort)?;
assert!(payload.get("think").is_none());
Ok(())
}
#[test]
fn test_ollama_think_disabled_for_zero_effort() -> Result<()> {
let reasoning_effort = Some(ReasoningEffort::Zero);
let payload = support_ollama_payload(reasoning_effort)?;
assert_eq!(payload["think"], false);
Ok(())
}
#[test]
fn test_ollama_think_maps_efforts_to_string_levels() -> Result<()> {
for (effort, expected) in [
(ReasoningEffort::Minimal, "low"),
(ReasoningEffort::Low, "low"),
(ReasoningEffort::Medium, "medium"),
(ReasoningEffort::High, "high"),
(ReasoningEffort::XHigh, "max"),
(ReasoningEffort::Max, "max"),
] {
let payload = support_ollama_payload(Some(effort.clone()))?;
assert_eq!(payload["think"], expected, "unexpected think level for {effort:?}");
}
Ok(())
}
#[test]
fn test_ollama_think_enabled_for_budget_effort() -> Result<()> {
let reasoning_effort = Some(ReasoningEffort::Budget(1024));
let payload = support_ollama_payload(reasoning_effort)?;
assert_eq!(payload["think"], true);
Ok(())
}
fn support_deepseek_payload(reasoning_effort: Option<ReasoningEffort>) -> Result<Value> {
let chat_options = reasoning_effort.map(|effort| ChatOptions::default().with_reasoning_effort(effort));
let options_set = ChatOptionsSet::default().with_chat_options(chat_options.as_ref());
let request = DeepSeekAdapter::to_web_request_data(
ServiceTarget {
model: ModelIden::new(AdapterKind::DeepSeek, "deepseek-v4-flash"),
auth: AuthData::from_single("test-key"),
endpoint: Endpoint::from_static("https://api.deepseek.com/v1/"),
},
ServiceType::Chat,
ChatRequest::from_user("hello"),
options_set,
)?;
Ok(request.payload)
}
fn support_ollama_payload(reasoning_effort: Option<ReasoningEffort>) -> Result<Value> {
let chat_options = reasoning_effort.map(|effort| ChatOptions::default().with_reasoning_effort(effort));
let options_set = ChatOptionsSet::default().with_chat_options(chat_options.as_ref());
let request = OllamaAdapter::to_web_request_data(
ServiceTarget {
model: ModelIden::new(AdapterKind::Ollama, "qwen3"),
auth: AuthData::from_single("test-key"),
endpoint: Endpoint::from_static("http://localhost:11434/"),
},
ServiceType::Chat,
ChatRequest::from_user("hello"),
options_set,
)?;
Ok(request.payload)
}