use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "lowercase")]
pub enum ReasoningEffort {
Minimal,
Low,
#[default]
Medium,
High,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "lowercase")]
pub enum SummaryVerbosity {
#[default]
Auto,
Concise,
Detailed,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReasoningConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub enabled: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub effort: Option<ReasoningEffort>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_tokens: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub exclude: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub summary: Option<SummaryVerbosity>,
}
impl Default for ReasoningConfig {
fn default() -> Self {
Self {
enabled: Some(true), effort: Some(ReasoningEffort::Medium),
max_tokens: None,
exclude: Some(false), summary: Some(SummaryVerbosity::Auto),
}
}
}
impl ReasoningConfig {
pub fn high_effort(max_tokens: u32) -> Self {
Self {
enabled: Some(true),
effort: Some(ReasoningEffort::High),
max_tokens: Some(max_tokens),
exclude: Some(false),
summary: Some(SummaryVerbosity::Detailed),
}
}
pub fn excluded() -> Self {
Self {
enabled: Some(true),
effort: Some(ReasoningEffort::Medium),
max_tokens: None,
exclude: Some(true), summary: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OpenRouterConfig {
#[serde(default)]
pub api_key: Option<String>,
#[serde(default = "OpenRouterConfig::default_base_url")]
pub base_url: String,
#[serde(default = "OpenRouterConfig::default_model")]
pub model: String,
#[serde(default)]
pub http_referer: Option<String>,
#[serde(default)]
pub x_title: Option<String>,
#[serde(default = "OpenRouterConfig::default_stream")]
pub stream: bool,
#[serde(default)]
pub max_output_tokens: Option<u32>,
#[serde(default)]
pub parallel_tool_calls: Option<bool>,
#[serde(default)]
pub temperature: Option<f32>,
#[serde(default)]
pub top_p: Option<f32>,
#[serde(default)]
pub reasoning: Option<ReasoningConfig>,
#[serde(default)]
pub provider_preferences: Option<ProviderPreferences>,
#[serde(default)]
pub transforms: Option<Vec<String>>,
#[serde(default)]
pub models: Option<Vec<String>>,
}
impl OpenRouterConfig {
pub fn default_base_url() -> String {
"https://openrouter.ai/api/v1".to_string()
}
pub fn default_model() -> String {
"openai/gpt-5".to_string()
}
pub fn default_stream() -> bool {
true
}
}
impl Default for OpenRouterConfig {
fn default() -> Self {
Self {
api_key: None,
base_url: Self::default_base_url(),
model: Self::default_model(),
http_referer: None,
x_title: None,
stream: Self::default_stream(),
max_output_tokens: Some(9000),
parallel_tool_calls: Some(false),
temperature: None,
top_p: None,
reasoning: None,
provider_preferences: None,
transforms: None,
models: None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ProviderSort {
Price,
Throughput,
Latency,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum DataCollection {
Allow,
Deny,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum QuantizationLevel {
Int4,
Int8,
Fp4,
Fp6,
Fp8,
Fp16,
Bf16,
Fp32,
Unknown,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MaxPrice {
#[serde(skip_serializing_if = "Option::is_none")]
pub prompt: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub completion: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub request: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub image: Option<f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProviderPreferences {
#[serde(skip_serializing_if = "Option::is_none")]
pub order: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub allow_fallbacks: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub require_parameters: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub data_collection: Option<DataCollection>,
#[serde(skip_serializing_if = "Option::is_none")]
pub zdr: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub only: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ignore: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub quantizations: Option<Vec<QuantizationLevel>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sort: Option<ProviderSort>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_price: Option<MaxPrice>,
}
impl Default for ProviderPreferences {
fn default() -> Self {
Self {
order: None,
allow_fallbacks: Some(true),
require_parameters: None,
data_collection: None,
zdr: None,
only: None,
ignore: None,
quantizations: None,
sort: None,
max_price: None,
}
}
}