1use thiserror::Error;
2
3#[derive(Debug, Error)]
4pub enum AgentForgeError {
5 #[error("Parse error: {0}")]
6 ParseError(String),
7
8 #[error("Validation error: {0}")]
9 ValidationError(String),
10
11 #[error("Invalid format: {0}")]
12 InvalidFormat(String),
13
14 #[error("Database error: {0}")]
15 DatabaseError(String),
16
17 #[error("LLM error: {provider} - {message}")]
18 LlmError { provider: String, message: String },
19
20 #[error("LLM error: judge model and agent model must differ (both are {model})")]
21 CircularBiasError { model: String },
22
23 #[error("Scoring error: {0}")]
24 ScoringError(String),
25
26 #[error("Optimization error: {0}")]
27 OptimizationError(String),
28
29 #[error("Promotion failed: {reason}")]
30 PromotionFailed { reason: String },
31
32 #[error("Gatekeeper failed - score gate: current={current:.3} champion={champion:.3} required_delta={required:.3}")]
33 ScoreGateFailed {
34 current: f64,
35 champion: f64,
36 required: f64,
37 },
38
39 #[error(
40 "Gatekeeper failed - regression gate: pass_rate={pass_rate:.3} required={required:.3}"
41 )]
42 RegressionGateFailed { pass_rate: f64, required: f64 },
43
44 #[error("Gatekeeper failed - stability gate: only {seeds} seeds run, need {required}")]
45 StabilityGateFailed { seeds: usize, required: usize },
46
47 #[error("Not found: {resource} with id {id}")]
48 NotFound { resource: &'static str, id: String },
49
50 #[error("Configuration error: {0}")]
51 ConfigError(String),
52
53 #[error("IO error: {0}")]
54 IoError(#[from] std::io::Error),
55
56 #[error("Serialization error: {0}")]
57 SerializationError(String),
58
59 #[error("HTTP error: {0}")]
60 HttpError(String),
61
62 #[error("Timeout after {seconds}s")]
63 Timeout { seconds: u64 },
64
65 #[error("Rate limit exceeded for provider {provider}")]
66 RateLimitExceeded { provider: String },
67}
68
69pub type Result<T> = std::result::Result<T, AgentForgeError>;
71
72impl From<serde_json::Error> for AgentForgeError {
73 fn from(e: serde_json::Error) -> Self {
74 AgentForgeError::SerializationError(e.to_string())
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn error_display_score_gate() {
84 let err = AgentForgeError::ScoreGateFailed {
85 current: 0.82,
86 champion: 0.85,
87 required: 0.03,
88 };
89 let msg = err.to_string();
90 assert!(msg.contains("score gate"));
91 assert!(msg.contains("0.820"));
92 }
93
94 #[test]
95 fn error_display_circular_bias() {
96 let err = AgentForgeError::CircularBiasError {
97 model: "gpt-4o".to_string(),
98 };
99 assert!(err.to_string().contains("gpt-4o"));
100 }
101}