1use serde::{Deserialize, Serialize};
2
3use crate::TokenEstimator;
4
5#[derive(Clone, Debug, Serialize, Deserialize, Default)]
6pub struct LatchConfig {
7 pub compression: Option<CompressionConfig>,
8 pub cache: Option<CacheConfig>,
9 pub router: Option<RouterConfig>,
10 pub retry: Option<RetryConfig>,
11 pub meter: Option<MeterConfig>,
12}
13
14#[derive(Clone, Serialize, Deserialize)]
15pub struct CompressionConfig {
16 pub min_tokens_to_compress: usize,
18 pub max_turns: usize,
20 pub max_system_tokens: usize,
22 pub strategy: CompressionStrategy,
24 pub dedup_max_merged_chars: usize,
26 #[serde(skip, default = "super::default_token_estimator")]
28 pub token_estimator: TokenEstimator,
29}
30
31impl std::fmt::Debug for CompressionConfig {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 f.debug_struct("CompressionConfig")
34 .field("min_tokens_to_compress", &self.min_tokens_to_compress)
35 .field("max_turns", &self.max_turns)
36 .field("max_system_tokens", &self.max_system_tokens)
37 .field("strategy", &self.strategy)
38 .field("dedup_max_merged_chars", &self.dedup_max_merged_chars)
39 .field("token_estimator", &"<TokenEstimator>")
40 .finish()
41 }
42}
43
44#[derive(Clone, Debug, Serialize, Deserialize)]
45pub enum CompressionStrategy {
46 None,
47 SlidingWindow,
48 Dedup,
49 DedupThenWindow,
50}
51
52#[derive(Clone, Debug, Serialize, Deserialize)]
53pub struct CacheConfig {
54 pub prompt_caching: PromptCachingConfig,
55}
56
57#[derive(Clone, Debug, Serialize, Deserialize)]
58#[serde(default = "PromptCachingConfig::default")]
59pub struct PromptCachingConfig {
60 pub enabled: bool,
61 pub provider: PromptCacheProvider,
62 pub cache_roles: Vec<String>,
64 pub min_content_chars: usize,
66}
67
68impl Default for PromptCachingConfig {
69 fn default() -> Self {
70 Self {
71 enabled: false,
72 provider: PromptCacheProvider::default(), cache_roles: vec!["system".to_string()],
74 min_content_chars: 0,
75 }
76 }
77}
78
79#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq)]
80pub enum PromptCacheProvider {
81 #[default]
82 None,
83 Anthropic,
84 OpenAiCompatible,
85}
86
87#[derive(Clone, Serialize, Deserialize)]
88pub struct RouterConfig {
89 pub pools: Vec<PoolRoute>,
91 pub confidence_threshold: f32,
93 pub long_request_tokens: usize,
95 #[serde(skip, default = "super::default_token_estimator")]
97 pub token_estimator: TokenEstimator,
98}
99
100impl std::fmt::Debug for RouterConfig {
101 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102 f.debug_struct("RouterConfig")
103 .field("pools", &self.pools)
104 .field("confidence_threshold", &self.confidence_threshold)
105 .field("long_request_tokens", &self.long_request_tokens)
106 .field("token_estimator", &"<TokenEstimator>")
107 .finish()
108 }
109}
110
111#[derive(Clone, Debug, Serialize, Deserialize)]
112pub struct PoolRoute {
113 pub pool_id: String,
115 pub tier: PoolTier,
117 pub weight: f32,
119 pub match_keywords: Vec<String>,
121 pub keyword_score: f32,
123 pub images: Option<bool>,
125}
126
127#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
128pub enum PoolTier {
129 Fast,
130 Standard,
131 Premium,
132 Backup,
133}
134
135#[derive(Clone, Debug, Serialize, Deserialize)]
136pub struct PoolFeedback {
137 #[serde(default)]
139 pub recent_failures: std::collections::HashMap<String, u32>,
140 #[serde(default)]
142 pub endpoint_scores: std::collections::HashMap<String, f32>,
143 #[serde(default = "default_penalty_per_failure")]
145 pub penalty_per_failure: f32,
146}
147
148impl Default for PoolFeedback {
149 fn default() -> Self {
150 PoolFeedback {
151 recent_failures: std::collections::HashMap::new(),
152 endpoint_scores: std::collections::HashMap::new(),
153 penalty_per_failure: default_penalty_per_failure(),
154 }
155 }
156}
157
158fn default_penalty_per_failure() -> f32 {
159 0.8
160}
161
162#[derive(Clone, Debug, Serialize, Deserialize)]
163pub struct RetryConfig {
164 pub max_attempts: usize,
165 pub backoff_ms: u64,
166 pub max_backoff_ms: Option<u64>,
167 pub fallback_provider: Option<String>,
168 pub circuit_breaker: Option<CircuitBreakerConfig>,
169 #[serde(default = "default_jitter_ratio")]
171 pub jitter_ratio: f64,
172}
173
174fn default_jitter_ratio() -> f64 {
175 0.2
176}
177
178#[derive(Clone, Debug, Serialize, Deserialize)]
179pub struct CircuitBreakerConfig {
180 pub failure_threshold: usize,
181 pub open_ms: u64,
182 pub half_open_max_attempts: usize,
183}
184
185#[derive(Clone, Debug, Serialize, Deserialize)]
186pub struct MeterConfig {
187 pub session_token_limit: Option<u64>,
188 pub session_request_limit: Option<u64>,
189 pub price_per_1k_input_tokens: f64,
190 pub price_per_1k_output_tokens: f64,
191 pub currency: String,
192}
193