Skip to main content

visual_rubric/pool/
config.rs

1use std::ffi::OsString;
2use std::path::PathBuf;
3use std::time::Duration;
4
5use crate::{
6    DEFAULT_CODEX_ACP_MODEL, DEFAULT_CODEX_ACP_REASONING_EFFORT, DEFAULT_SYSTEM_PROMPT,
7    RubricEffort, RubricOptions, default_codex_acp_binary,
8};
9
10pub(super) const DEFAULT_SUBMIT_TIMEOUT: Duration = Duration::from_secs(600);
11
12/// Configuration for a [`crate::RubricPool`].
13#[derive(Clone, Debug, PartialEq, Eq)]
14pub struct PoolConfig {
15    /// Number of worker processes to keep alive.
16    pub workers: usize,
17    /// Number of prompts after which a worker is recycled.
18    pub max_prompts_per_worker: u32,
19    /// Number of retries for recoverable worker or rate-limit failures.
20    pub max_retries: u32,
21    /// Initial retry backoff.
22    pub backoff_base: Duration,
23    /// Maximum retry backoff.
24    pub backoff_cap: Duration,
25    /// Options applied when a submitted job omits an override.
26    pub default_options: RubricOptions,
27    /// Path to the `codex-acp` executable.
28    pub codex_acp_binary: PathBuf,
29    /// Extra environment variables for worker processes.
30    pub extra_env: Vec<(OsString, OsString)>,
31    /// Maximum time to wait for one submitted job.
32    pub submit_timeout: Duration,
33    /// Optional Codex home directory to seed into worker-local homes.
34    pub source_codex_home: Option<PathBuf>,
35    /// Optional ACP log capture directories.
36    pub log_capture: Option<LogCaptureConfig>,
37}
38
39impl Default for PoolConfig {
40    fn default() -> Self {
41        Self {
42            workers: 4,
43            max_prompts_per_worker: 50,
44            max_retries: 4,
45            backoff_base: Duration::from_secs(30),
46            backoff_cap: Duration::from_secs(300),
47            default_options: default_options(),
48            codex_acp_binary: default_codex_acp_binary(),
49            extra_env: Vec::new(),
50            submit_timeout: DEFAULT_SUBMIT_TIMEOUT,
51            source_codex_home: None,
52            log_capture: None,
53        }
54    }
55}
56
57fn default_options() -> RubricOptions {
58    RubricOptions {
59        model: Some(DEFAULT_CODEX_ACP_MODEL.to_string()),
60        effort: Some(RubricEffort::from(DEFAULT_CODEX_ACP_REASONING_EFFORT)),
61        system_prompt: Some(DEFAULT_SYSTEM_PROMPT.to_string()),
62    }
63}
64
65/// Directories used to capture logs produced by Codex ACP.
66#[derive(Clone, Debug, PartialEq, Eq)]
67pub struct LogCaptureConfig {
68    /// Temporary root exposed to worker processes through `TMPDIR`.
69    pub temp_dir: PathBuf,
70    /// Destination directory where selected log files are copied.
71    pub output_dir: PathBuf,
72    /// How copied log paths are represented in reports.
73    pub path_mode: LogPathMode,
74}
75
76/// Path representation for copied ACP logs in batch reports.
77#[derive(Clone, Debug, Default, PartialEq, Eq)]
78pub enum LogPathMode {
79    /// Report paths relative to this root when possible.
80    RelativeTo(PathBuf),
81    /// Report absolute paths.
82    #[default]
83    Absolute,
84}
85
86/// Snapshot of pool execution counters.
87#[derive(Clone, Debug, Default, PartialEq, Eq)]
88pub struct PoolStats {
89    /// Successfully completed jobs.
90    pub completed: u64,
91    /// Failed jobs.
92    pub failures: u64,
93    /// Rate-limit events observed by workers.
94    pub rate_limit_events: Vec<crate::RateLimitEvent>,
95    /// Number of worker runtime recycles.
96    pub worker_recycles: u64,
97}