use thiserror::Error;
#[derive(Debug, Error)]
pub enum GEPAError {
#[error("Adapter evaluation failed: {0}")]
AdapterEvaluation(String),
#[error("Adapter reflective dataset build failed: {0}")]
AdapterReflectiveDataset(String),
#[error("Evaluation error: {0}")]
Evaluation(String),
#[error("Proposal failed: {0}")]
ProposalFailed(String),
#[error("Proposal error: {0}")]
Proposal(String),
#[error("LM call failed: {0}")]
LMError(String),
#[error("LM API error: {0}")]
LmApi(String),
#[error("LM retries exhausted: {0}")]
RetriesExhausted(String),
#[error("No candidates available")]
NoCandidates,
#[error("Empty Pareto frontier")]
EmptyFrontier,
#[error("Empty dataset: {0}")]
EmptyDataset(String),
#[error("Configuration error: {0}")]
Config(String),
#[error("Adapter error: {0}")]
AdapterError(String),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Serialization error: {0}")]
Serde(#[from] serde_json::Error),
#[error("HTTP error: {0}")]
Http(#[from] reqwest::Error),
}
pub type Result<T, E = GEPAError> = std::result::Result<T, E>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn display_messages_are_readable() {
let err = GEPAError::AdapterEvaluation("timeout".into());
assert_eq!(err.to_string(), "Adapter evaluation failed: timeout");
let err = GEPAError::NoCandidates;
assert_eq!(err.to_string(), "No candidates available");
let err = GEPAError::Config("missing api_key".into());
assert_eq!(err.to_string(), "Configuration error: missing api_key");
}
#[test]
fn from_io_error_conversion() {
let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
let gepa_err = GEPAError::from(io_err);
assert!(gepa_err.to_string().contains("IO error"));
}
#[test]
fn from_serde_error_conversion() {
let serde_err: serde_json::Error =
serde_json::from_str::<serde_json::Value>("{invalid}").unwrap_err();
let gepa_err = GEPAError::from(serde_err);
assert!(gepa_err.to_string().contains("Serialization error"));
}
}