use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Deserialize)]
pub struct HealthcheckDef {
pub method: String,
#[serde(default)]
pub path: Option<String>,
#[serde(default)]
pub url: Option<String>,
#[serde(default)]
pub body: Option<String>,
}
#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq, Eq)]
pub struct LocalRuntimeDef {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub kind: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub command: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub prefix_args: Vec<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub model_source: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub model_source_env: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub default_port: Option<u16>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub model_arg: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub served_model_arg: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub host_arg: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub port_arg: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ctx_arg: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub parallel_arg: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub gpu_layers_arg: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cache_type_k_arg: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cache_type_v_arg: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cache_ram_arg: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub enable_lora_arg: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub lora_modules_arg: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub lora_modules_value_format: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub max_lora_rank_arg: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub default_args: Vec<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub stop: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source_url: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub last_verified: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub notes: Option<String>,
}
#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq)]
pub struct LocalMemoryDef {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub measured_resident_gib: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub measured_context_window: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub measured_cache_type: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub base_resident_gib: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub kv_cache_gib_per_1k_ctx: Option<f64>,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub cache_type_multipliers: BTreeMap<String, f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub default_cache_type: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub safety_margin_gib: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub max_recommended_context: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source_url: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub last_verified: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub notes: Option<String>,
}
impl LocalMemoryDef {
pub fn is_empty(&self) -> bool {
self.measured_resident_gib.is_none()
&& self.measured_context_window.is_none()
&& self.measured_cache_type.is_none()
&& self.base_resident_gib.is_none()
&& self.kv_cache_gib_per_1k_ctx.is_none()
&& self.cache_type_multipliers.is_empty()
&& self.default_cache_type.is_none()
&& self.safety_margin_gib.is_none()
&& self.max_recommended_context.is_none()
&& self.source_url.is_none()
&& self.last_verified.is_none()
&& self.notes.is_none()
}
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
pub struct AliasDef {
pub id: String,
pub provider: String,
#[serde(default)]
pub tool_format: Option<String>,
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
pub struct AliasToolCallingDef {
#[serde(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub native: Option<String>,
#[serde(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub text: Option<String>,
#[serde(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub streaming_native: Option<String>,
#[serde(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub fallback_mode: Option<String>,
#[serde(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub failure_reason: Option<String>,
#[serde(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub last_probe_at: Option<String>,
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
pub struct ModelPricing {
pub input_per_mtok: f64,
pub output_per_mtok: f64,
#[serde(default)]
pub cache_read_per_mtok: Option<f64>,
#[serde(default)]
pub cache_write_per_mtok: Option<f64>,
}
#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq, Eq)]
pub struct RateLimitsDef {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub rpm: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub rph: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub rpd: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tpm: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tph: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tpd: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub input_tpm: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub output_tpm: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub concurrency: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tier: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source_url: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub last_verified: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub notes: Option<String>,
}
impl RateLimitsDef {
pub fn is_empty(&self) -> bool {
self.rpm.is_none()
&& self.rph.is_none()
&& self.rpd.is_none()
&& self.tpm.is_none()
&& self.tph.is_none()
&& self.tpd.is_none()
&& self.input_tpm.is_none()
&& self.output_tpm.is_none()
&& self.concurrency.is_none()
&& self.tier.is_none()
&& self.source_url.is_none()
&& self.last_verified.is_none()
&& self.notes.is_none()
}
pub fn with_rpm_fallback(mut self, rpm: Option<u32>) -> Option<Self> {
if self.rpm.is_none() {
self.rpm = rpm;
}
(!self.is_empty()).then_some(self)
}
}
#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq)]
pub struct ServingPerformanceDef {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub observed_ttft_ms: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub output_tokens_per_sec: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub time_to_answer_s: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source_url: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub last_verified: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub sample_size: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub notes: Option<String>,
}
impl ServingPerformanceDef {
pub fn is_empty(&self) -> bool {
self.observed_ttft_ms.is_none()
&& self.output_tokens_per_sec.is_none()
&& self.time_to_answer_s.is_none()
&& self.source.is_none()
&& self.source_url.is_none()
&& self.last_verified.is_none()
&& self.sample_size.is_none()
&& self.notes.is_none()
}
}
#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq)]
pub struct ModelArchitectureDef {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub parameter_count_b: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub active_parameter_count_b: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub moe: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub quantization: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub precision: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub license: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tokenizer: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub knowledge_cutoff: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source_url: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub last_verified: Option<String>,
}
impl ModelArchitectureDef {
pub fn is_empty(&self) -> bool {
self.parameter_count_b.is_none()
&& self.active_parameter_count_b.is_none()
&& self.moe.is_none()
&& self.quantization.is_none()
&& self.precision.is_none()
&& self.license.is_none()
&& self.tokenizer.is_none()
&& self.knowledge_cutoff.is_none()
&& self.source_url.is_none()
&& self.last_verified.is_none()
}
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
pub struct FastModeDef {
pub param: String,
pub value: String,
#[serde(default)]
pub beta_header: Option<String>,
#[serde(default)]
pub otps_speedup: Option<f64>,
#[serde(default)]
pub status: Option<String>,
#[serde(default)]
pub pricing: Option<ModelPricing>,
#[serde(default)]
pub note: Option<String>,
}
#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq, Eq)]
pub struct ModelLadderDef {
#[serde(default)]
pub steps: Vec<ModelLadderStepDef>,
#[serde(default)]
pub label: Option<String>,
}
#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq, Eq)]
pub struct ModelLadderStepDef {
pub model: String,
#[serde(default)]
pub provider: Option<String>,
#[serde(default)]
pub label: Option<String>,
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
pub struct ModelDef {
pub name: String,
pub provider: String,
pub context_window: u64,
#[serde(default)]
pub logical_model: Option<String>,
#[serde(default)]
pub equivalence_group: Option<String>,
#[serde(default)]
pub served_variant: Option<String>,
#[serde(default)]
pub wire_model: Option<String>,
#[serde(default)]
pub api_dialect: Option<String>,
#[serde(default)]
pub rate_limits: Option<RateLimitsDef>,
#[serde(default)]
pub performance: Option<ServingPerformanceDef>,
#[serde(default)]
pub architecture: Option<ModelArchitectureDef>,
#[serde(default)]
pub local_memory: Option<LocalMemoryDef>,
#[serde(default)]
pub runtime_context_window: Option<u64>,
#[serde(default)]
pub stream_timeout: Option<f64>,
#[serde(default)]
pub capabilities: Vec<String>,
#[serde(default)]
pub pricing: Option<ModelPricing>,
#[serde(default)]
pub deprecated: bool,
#[serde(default)]
pub deprecation_note: Option<String>,
#[serde(default)]
pub superseded_by: Option<String>,
#[serde(default)]
pub fast_mode: Option<FastModeDef>,
#[serde(default)]
pub quality_tags: Vec<String>,
#[serde(default)]
pub availability: ModelAvailability,
#[serde(default)]
pub tier: Option<String>,
#[serde(default)]
pub open_weight: Option<bool>,
#[serde(default)]
pub strengths: Vec<String>,
#[serde(default)]
pub benchmarks: BTreeMap<String, f64>,
#[serde(default)]
pub family: Option<String>,
#[serde(default)]
pub lineage: Option<String>,
#[serde(default)]
pub complementary_with: Vec<String>,
#[serde(default)]
pub avoid_as_reviewer_for: Vec<String>,
}
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, Default)]
#[serde(rename_all = "snake_case")]
pub enum ModelAvailability {
#[default]
Serverless,
Dedicated,
Unknown,
}
impl ModelAvailability {
pub fn as_str(self) -> &'static str {
match self {
Self::Serverless => "serverless",
Self::Dedicated => "dedicated",
Self::Unknown => "unknown",
}
}
pub fn parse(value: &str) -> Option<Self> {
match value {
"serverless" => Some(Self::Serverless),
"dedicated" => Some(Self::Dedicated),
"unknown" => Some(Self::Unknown),
_ => None,
}
}
}