use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VisionRetryConfig {
pub max_retries: u32,
pub initial_backoff_ms: u64,
pub backoff_multiplier: f64,
}
impl Default for VisionRetryConfig {
fn default() -> Self {
Self {
max_retries: 3,
initial_backoff_ms: 1000,
backoff_multiplier: 2.0,
}
}
}
impl VisionRetryConfig {
pub fn validate(&self) -> Result<(), String> {
if self.backoff_multiplier <= 0.0 {
return Err("backoff_multiplier must be greater than 0".to_string());
}
if self.backoff_multiplier < 1.0 {
return Err(
"backoff_multiplier should be at least 1.0 for effective backoff".to_string(),
);
}
Ok(())
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VisionProviderConfig {
pub max_tokens: usize,
}
impl Default for VisionProviderConfig {
fn default() -> Self {
Self { max_tokens: 4096 }
}
}
impl VisionProviderConfig {
pub fn validate(&self) -> Result<(), String> {
if self.max_tokens == 0 {
return Err("max_tokens must be greater than 0".to_string());
}
Ok(())
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct VisionConfig {
pub retry: VisionRetryConfig,
pub openai: VisionProviderConfig,
pub anthropic: VisionProviderConfig,
}
impl VisionConfig {
pub fn validate(&self) -> Result<(), String> {
self.retry.validate()?;
self.openai.validate()?;
self.anthropic.validate()?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_vision_config_defaults() {
let config = VisionConfig::default();
assert_eq!(config.retry.max_retries, 3);
assert_eq!(config.retry.initial_backoff_ms, 1000);
assert_eq!(config.retry.backoff_multiplier, 2.0);
assert_eq!(config.openai.max_tokens, 4096);
assert_eq!(config.anthropic.max_tokens, 4096);
}
#[test]
fn test_vision_retry_config_validation_success() {
let config = VisionRetryConfig {
max_retries: 3,
initial_backoff_ms: 1000,
backoff_multiplier: 2.0,
};
assert!(config.validate().is_ok());
}
#[test]
fn test_vision_retry_config_validation_invalid_multiplier() {
let config = VisionRetryConfig {
max_retries: 3,
initial_backoff_ms: 1000,
backoff_multiplier: 0.0,
};
let result = config.validate();
assert!(result.is_err());
assert!(result.unwrap_err().contains("must be greater than 0"));
}
#[test]
fn test_vision_retry_config_validation_low_multiplier() {
let config = VisionRetryConfig {
max_retries: 3,
initial_backoff_ms: 1000,
backoff_multiplier: 0.5,
};
let result = config.validate();
assert!(result.is_err());
assert!(result.unwrap_err().contains("should be at least 1.0"));
}
#[test]
fn test_vision_provider_config_validation_success() {
let config = VisionProviderConfig { max_tokens: 4096 };
assert!(config.validate().is_ok());
}
#[test]
fn test_vision_provider_config_validation_zero_tokens() {
let config = VisionProviderConfig { max_tokens: 0 };
let result = config.validate();
assert!(result.is_err());
assert!(result.unwrap_err().contains("must be greater than 0"));
}
#[test]
fn test_vision_config_validation_success() {
let config = VisionConfig::default();
assert!(config.validate().is_ok());
}
}