Skip to main content

bookforge_core/
run_snapshot.rs

1use std::path::PathBuf;
2
3use crate::{
4    BatchConfig, DoubleCheckConfig, JsonMode, ProviderPreset, ProviderRuntimeConfig, QaRunConfig,
5    ResolvedRunSettings, RetryAfterPolicy, SchedulerConfig, SegmentationConfig, TranslationProfile,
6};
7
8#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
9pub struct RunConfigSnapshot {
10    pub input_path: PathBuf,
11    #[serde(default)]
12    pub input_snapshot_path: Option<PathBuf>,
13    #[serde(default)]
14    pub input_sha256: Option<String>,
15    pub output_path: PathBuf,
16    pub events_path: Option<PathBuf>,
17    pub report_json_path: Option<PathBuf>,
18    pub report_markdown_path: Option<PathBuf>,
19    pub source_language: Option<String>,
20    pub target_language: String,
21    pub provider: String,
22    pub model: String,
23    pub base_url: Option<String>,
24    pub api_key_env: Option<String>,
25    pub profile: TranslationProfile,
26    pub provider_preset: Option<ProviderPreset>,
27    pub prompt_version: String,
28    pub cache_namespace: String,
29    pub settings: ResolvedRunSettingsSnapshot,
30}
31
32#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
33pub struct ResolvedRunSettingsSnapshot {
34    pub profile: TranslationProfile,
35    pub segmentation: SegmentationConfigSnapshot,
36    pub batch: BatchConfigSnapshot,
37    pub scheduler: SchedulerConfigSnapshot,
38    pub provider: ProviderRuntimeConfigSnapshot,
39    pub compact_prompts: bool,
40    pub retry_failed_only: bool,
41    pub adaptive_concurrency: bool,
42    pub qa: QaRunConfigSnapshot,
43    pub double_check: DoubleCheckConfigSnapshot,
44}
45
46#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
47pub struct SegmentationConfigSnapshot {
48    pub max_segment_tokens: usize,
49    pub context_tokens: usize,
50}
51
52#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
53pub struct BatchConfigSnapshot {
54    pub enabled: bool,
55    pub target_tokens: usize,
56    pub max_items: usize,
57    pub adaptive_sizing: bool,
58    pub split_on_json_failure: bool,
59    pub repair_invalid_items: bool,
60}
61
62#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
63pub struct SchedulerConfigSnapshot {
64    pub concurrency: usize,
65    pub max_attempts: usize,
66}
67
68#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
69pub struct ProviderRuntimeConfigSnapshot {
70    pub timeout_seconds: u64,
71    pub provider_max_attempts: usize,
72    pub validation_max_attempts: usize,
73    pub retry_after_policy: RetryAfterPolicy,
74    pub max_backoff_seconds: u64,
75    pub thinking_disabled: bool,
76    pub model_context_tokens: Option<u32>,
77    pub max_output_tokens: Option<u32>,
78    pub batch_max_output_tokens: Option<u32>,
79    pub json_mode: JsonMode,
80    pub max_idle_per_host: usize,
81}
82
83#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
84pub struct QaRunConfigSnapshot {
85    pub concurrency: usize,
86    pub batch_target_tokens: usize,
87    pub model: Option<String>,
88    pub provider: Option<String>,
89    pub base_url: Option<String>,
90    pub api_key_env: Option<String>,
91}
92
93#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
94pub struct DoubleCheckConfigSnapshot {
95    pub mode: crate::DoubleCheckMode,
96    pub model: Option<String>,
97    pub provider: Option<String>,
98    pub base_url: Option<String>,
99    pub api_key_env: Option<String>,
100    pub concurrency: usize,
101    pub batch_target_tokens: usize,
102    pub auto_correct: bool,
103    pub correction_rounds: usize,
104}
105
106impl ResolvedRunSettingsSnapshot {
107    pub fn from_settings(settings: &ResolvedRunSettings) -> Self {
108        Self {
109            profile: settings.profile,
110            segmentation: SegmentationConfigSnapshot {
111                max_segment_tokens: settings.segmentation.max_segment_tokens,
112                context_tokens: settings.segmentation.context_tokens,
113            },
114            batch: BatchConfigSnapshot {
115                enabled: settings.batch.enabled,
116                target_tokens: settings.batch.target_tokens,
117                max_items: settings.batch.max_items,
118                adaptive_sizing: settings.batch.adaptive_sizing,
119                split_on_json_failure: settings.batch.split_on_json_failure,
120                repair_invalid_items: settings.batch.repair_invalid_items,
121            },
122            scheduler: SchedulerConfigSnapshot {
123                concurrency: settings.scheduler.concurrency,
124                max_attempts: settings.scheduler.max_attempts,
125            },
126            provider: ProviderRuntimeConfigSnapshot {
127                timeout_seconds: settings.provider.timeout_seconds,
128                provider_max_attempts: settings.provider.provider_max_attempts,
129                validation_max_attempts: settings.provider.validation_max_attempts,
130                retry_after_policy: settings.provider.retry_after_policy,
131                max_backoff_seconds: settings.provider.max_backoff_seconds,
132                thinking_disabled: settings.provider.thinking_disabled,
133                model_context_tokens: settings.provider.model_context_tokens,
134                max_output_tokens: settings.provider.max_output_tokens,
135                batch_max_output_tokens: settings.provider.batch_max_output_tokens,
136                json_mode: settings.provider.json_mode,
137                max_idle_per_host: settings.provider.max_idle_per_host,
138            },
139            compact_prompts: settings.compact_prompts,
140            retry_failed_only: settings.retry_failed_only,
141            adaptive_concurrency: settings.adaptive_concurrency,
142            qa: QaRunConfigSnapshot {
143                concurrency: settings.qa.concurrency,
144                batch_target_tokens: settings.qa.batch_target_tokens,
145                model: settings.qa.model.clone(),
146                provider: settings.qa.provider.clone(),
147                base_url: settings.qa.base_url.clone(),
148                api_key_env: settings.qa.api_key_env.clone(),
149            },
150            double_check: DoubleCheckConfigSnapshot {
151                mode: settings.double_check.mode,
152                model: settings.double_check.model.clone(),
153                provider: settings.double_check.provider.clone(),
154                base_url: settings.double_check.base_url.clone(),
155                api_key_env: settings.double_check.api_key_env.clone(),
156                concurrency: settings.double_check.concurrency,
157                batch_target_tokens: settings.double_check.batch_target_tokens,
158                auto_correct: settings.double_check.auto_correct,
159                correction_rounds: settings.double_check.correction_rounds,
160            },
161        }
162    }
163
164    pub fn to_settings(&self) -> ResolvedRunSettings {
165        ResolvedRunSettings {
166            profile: self.profile,
167            segmentation: SegmentationConfig {
168                max_segment_tokens: self.segmentation.max_segment_tokens,
169                context_tokens: self.segmentation.context_tokens,
170            },
171            batch: BatchConfig {
172                enabled: self.batch.enabled,
173                target_tokens: self.batch.target_tokens,
174                max_items: self.batch.max_items,
175                adaptive_sizing: self.batch.adaptive_sizing,
176                split_on_json_failure: self.batch.split_on_json_failure,
177                repair_invalid_items: self.batch.repair_invalid_items,
178            },
179            scheduler: SchedulerConfig {
180                concurrency: self.scheduler.concurrency,
181                max_attempts: self.scheduler.max_attempts,
182            },
183            provider: ProviderRuntimeConfig {
184                timeout_seconds: self.provider.timeout_seconds,
185                provider_max_attempts: self.provider.provider_max_attempts,
186                validation_max_attempts: self.provider.validation_max_attempts,
187                retry_after_policy: self.provider.retry_after_policy,
188                max_backoff_seconds: self.provider.max_backoff_seconds,
189                thinking_disabled: self.provider.thinking_disabled,
190                model_context_tokens: self.provider.model_context_tokens,
191                max_output_tokens: self.provider.max_output_tokens,
192                batch_max_output_tokens: self.provider.batch_max_output_tokens,
193                json_mode: self.provider.json_mode,
194                max_idle_per_host: self.provider.max_idle_per_host,
195            },
196            compact_prompts: self.compact_prompts,
197            retry_failed_only: self.retry_failed_only,
198            adaptive_concurrency: self.adaptive_concurrency,
199            qa: QaRunConfig {
200                concurrency: self.qa.concurrency,
201                batch_target_tokens: self.qa.batch_target_tokens,
202                model: self.qa.model.clone(),
203                provider: self.qa.provider.clone(),
204                base_url: self.qa.base_url.clone(),
205                api_key_env: self.qa.api_key_env.clone(),
206            },
207            double_check: DoubleCheckConfig {
208                mode: self.double_check.mode,
209                model: self.double_check.model.clone(),
210                provider: self.double_check.provider.clone(),
211                base_url: self.double_check.base_url.clone(),
212                api_key_env: self.double_check.api_key_env.clone(),
213                concurrency: self.double_check.concurrency,
214                batch_target_tokens: self.double_check.batch_target_tokens,
215                auto_correct: self.double_check.auto_correct,
216                correction_rounds: self.double_check.correction_rounds,
217            },
218        }
219    }
220}