use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GatewayConfig {
pub base_url: String,
pub default_model: Option<String>,
pub timeout_ms: u32,
pub debug: bool,
pub max_retries: u32,
pub rate_limit: Option<RateLimitConfig>,
}
impl Default for GatewayConfig {
fn default() -> Self {
Self {
base_url: "https://api.xybrid.dev/v1".to_string(),
default_model: Some("gpt-4o-mini".to_string()),
timeout_ms: 60000,
debug: false,
max_retries: 3,
rate_limit: None,
}
}
}
impl GatewayConfig {
pub fn new(base_url: impl Into<String>) -> Self {
Self {
base_url: base_url.into(),
..Default::default()
}
}
pub fn with_default_model(mut self, model: impl Into<String>) -> Self {
self.default_model = Some(model.into());
self
}
pub fn with_timeout(mut self, timeout_ms: u32) -> Self {
self.timeout_ms = timeout_ms;
self
}
pub fn with_debug(mut self, debug: bool) -> Self {
self.debug = debug;
self
}
pub fn with_rate_limit(mut self, config: RateLimitConfig) -> Self {
self.rate_limit = Some(config);
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RateLimitConfig {
pub requests_per_minute: u32,
pub tokens_per_minute: u32,
pub max_concurrent: u32,
}
impl Default for RateLimitConfig {
fn default() -> Self {
Self {
requests_per_minute: 60,
tokens_per_minute: 100000,
max_concurrent: 10,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelRouting {
pub alias: String,
pub model_id: String,
pub provider: String,
pub priority: u32,
pub enabled: bool,
}
#[derive(Debug, Clone)]
pub struct ProviderCredentials {
pub provider: String,
pub api_key: Option<String>,
pub base_url: Option<String>,
pub org_id: Option<String>,
}
impl ProviderCredentials {
pub fn new(provider: impl Into<String>) -> Self {
Self {
provider: provider.into(),
api_key: None,
base_url: None,
org_id: None,
}
}
pub fn with_api_key(mut self, key: impl Into<String>) -> Self {
self.api_key = Some(key.into());
self
}
pub fn with_base_url(mut self, url: impl Into<String>) -> Self {
self.base_url = Some(url.into());
self
}
pub fn with_org_id(mut self, org_id: impl Into<String>) -> Self {
self.org_id = Some(org_id.into());
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = GatewayConfig::default();
assert_eq!(config.base_url, "https://api.xybrid.dev/v1");
assert_eq!(config.default_model, Some("gpt-4o-mini".to_string()));
assert_eq!(config.timeout_ms, 60000);
}
#[test]
fn test_config_builder() {
let config = GatewayConfig::new("https://custom.gateway.com/v1")
.with_default_model("claude-3-sonnet")
.with_timeout(30000)
.with_debug(true);
assert_eq!(config.base_url, "https://custom.gateway.com/v1");
assert_eq!(config.default_model, Some("claude-3-sonnet".to_string()));
assert_eq!(config.timeout_ms, 30000);
assert!(config.debug);
}
#[test]
fn test_provider_credentials() {
let creds = ProviderCredentials::new("openai")
.with_api_key("sk-test")
.with_org_id("org-123");
assert_eq!(creds.provider, "openai");
assert_eq!(creds.api_key, Some("sk-test".to_string()));
assert_eq!(creds.org_id, Some("org-123".to_string()));
}
}