Skip to main content

distri_types/
models.rs

1//! Core model, provider, and audio types used across the entire system.
2
3use serde::{Deserialize, Serialize};
4
5// ── Provider identity ───────────────────────────────────────────────────
6
7/// Known provider types. Used for identity and dispatch.
8#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
9#[serde(rename_all = "snake_case")]
10pub enum ProviderType {
11    #[serde(rename = "openai")]
12    OpenAI,
13    Anthropic,
14    Azure,
15    Gemini,
16    AzureAiFoundry,
17    AwsBedrock,
18    GoogleVertex,
19    AlibabaCloud,
20    #[serde(rename = "elevenlabs")]
21    ElevenLabs,
22    /// User-defined provider (LangDB-compatible / OpenAI-compatible)
23    #[serde(untagged)]
24    Custom(String),
25}
26
27impl ProviderType {
28    pub fn as_str(&self) -> &str {
29        match self {
30            Self::OpenAI => "openai",
31            Self::Anthropic => "anthropic",
32            Self::Azure => "azure",
33            Self::Gemini => "gemini",
34            Self::AzureAiFoundry => "azure_ai_foundry",
35            Self::AwsBedrock => "aws_bedrock",
36            Self::GoogleVertex => "google_vertex",
37            Self::AlibabaCloud => "alibaba_cloud",
38            Self::ElevenLabs => "elevenlabs",
39            Self::Custom(id) => id.as_str(),
40        }
41    }
42
43    pub fn display_name(&self) -> &str {
44        match self {
45            Self::OpenAI => "OpenAI",
46            Self::Anthropic => "Anthropic",
47            Self::Azure => "Azure",
48            Self::Gemini => "Google Gemini",
49            Self::AzureAiFoundry => "Azure AI Foundry",
50            Self::AwsBedrock => "AWS Bedrock",
51            Self::GoogleVertex => "Google Vertex AI",
52            Self::AlibabaCloud => "Alibaba Cloud",
53            Self::ElevenLabs => "ElevenLabs",
54            Self::Custom(id) => id.as_str(),
55        }
56    }
57
58    pub fn from_id(id: &str) -> Self {
59        match id {
60            "openai" => Self::OpenAI,
61            "anthropic" => Self::Anthropic,
62            "azure" | "azure_openai" | "azure_speech" => Self::Azure,
63            "gemini" => Self::Gemini,
64            "azure_ai_foundry" => Self::AzureAiFoundry,
65            "aws_bedrock" => Self::AwsBedrock,
66            "google_vertex" => Self::GoogleVertex,
67            "alibaba_cloud" => Self::AlibabaCloud,
68            "elevenlabs" => Self::ElevenLabs,
69            other => Self::Custom(other.to_string()),
70        }
71    }
72}
73
74impl std::fmt::Display for ProviderType {
75    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76        f.write_str(self.as_str())
77    }
78}
79
80// ── Model types ─────────────────────────────────────────────────────────
81
82/// What a model can do.
83#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
84#[serde(rename_all = "snake_case")]
85pub enum ModelCapability {
86    Completion,
87    Tts,
88    Stt,
89}
90
91/// Pricing varies by capability type.
92#[derive(Debug, Clone, Serialize, Deserialize)]
93#[serde(tag = "type", rename_all = "snake_case")]
94pub enum ModelPricing {
95    /// Completion model pricing — per 1M tokens (USD).
96    Completion {
97        input: f64,
98        output: f64,
99        #[serde(default, skip_serializing_if = "Option::is_none")]
100        cached_input: Option<f64>,
101    },
102    /// TTS pricing — per 1M characters (USD).
103    Tts { per_1m_chars: f64 },
104    /// STT pricing — per minute of audio (USD).
105    Stt { per_minute: f64 },
106}
107
108/// A model with its capability, pricing, and metadata.
109#[derive(Debug, Clone, Serialize, Deserialize)]
110pub struct Model {
111    pub id: String,
112    pub name: String,
113    pub capability: ModelCapability,
114    #[serde(default, skip_serializing_if = "Option::is_none")]
115    pub context_window: Option<u32>,
116    #[serde(default, skip_serializing_if = "Option::is_none")]
117    pub pricing: Option<ModelPricing>,
118    #[serde(default, skip_serializing_if = "Vec::is_empty")]
119    pub voices: Vec<TtsVoiceInfo>,
120    #[serde(default, skip_serializing_if = "Vec::is_empty")]
121    pub formats: Vec<String>,
122}
123
124/// A model with denormalized provider info — returned by GET /v1/models.
125#[derive(Debug, Clone, Serialize, Deserialize)]
126pub struct ModelWithProvider {
127    #[serde(flatten)]
128    pub model: Model,
129    pub provider_id: String,
130    pub provider_label: String,
131    pub configured: bool,
132}
133
134// ── Provider definition ─────────────────────────────────────────────────
135
136/// Secret key definition for a provider.
137#[derive(Debug, Clone, Serialize, Deserialize)]
138pub struct ProviderKeyDefinition {
139    pub key: String,
140    pub label: String,
141    pub placeholder: String,
142    #[serde(default = "default_true")]
143    pub required: bool,
144    #[serde(default = "default_true")]
145    pub sensitive: bool,
146}
147
148/// A provider definition with its keys and available models.
149#[derive(Debug, Clone, Serialize, Deserialize)]
150pub struct ModelProviderDefinition {
151    pub id: String,
152    pub label: String,
153    pub keys: Vec<ProviderKeyDefinition>,
154    pub models: Vec<Model>,
155    #[serde(default)]
156    pub is_custom: bool,
157}
158
159// ── TTS voice info ──────────────────────────────────────────────────────
160
161/// Information about a TTS voice.
162#[derive(Debug, Clone, Serialize, Deserialize)]
163pub struct TtsVoiceInfo {
164    pub id: String,
165    pub name: String,
166    #[serde(skip_serializing_if = "Option::is_none")]
167    pub description: Option<String>,
168    #[serde(default, skip_serializing_if = "Vec::is_empty")]
169    pub languages: Vec<String>,
170}
171
172fn default_true() -> bool {
173    true
174}