1use std::path::PathBuf;
7
8#[derive(Debug, thiserror::Error)]
10#[non_exhaustive]
11pub enum EngineError {
12 #[error("configuration error: {0}")]
14 ConfigError(String),
15
16 #[error("prompt error: {0}")]
18 PromptError(#[from] gba_pm::PromptError),
19
20 #[error("agent error: {0}")]
22 AgentError(#[from] claude_agent_sdk_rs::ClaudeError),
23
24 #[error("I/O error at '{path}': {source}")]
26 IoError {
27 path: PathBuf,
29 #[source]
31 source: std::io::Error,
32 },
33
34 #[error("YAML parse error at '{path}': {source}")]
36 YamlError {
37 path: PathBuf,
39 #[source]
41 source: serde_yaml::Error,
42 },
43
44 #[error("task configuration not found for task kind: {0}")]
46 TaskConfigNotFound(String),
47}
48
49impl EngineError {
50 pub fn io_error(path: impl Into<PathBuf>, source: std::io::Error) -> Self {
52 Self::IoError {
53 path: path.into(),
54 source,
55 }
56 }
57
58 pub fn yaml_error(path: impl Into<PathBuf>, source: serde_yaml::Error) -> Self {
60 Self::YamlError {
61 path: path.into(),
62 source,
63 }
64 }
65
66 pub fn config_error(message: impl Into<String>) -> Self {
68 Self::ConfigError(message.into())
69 }
70}
71
72pub type Result<T> = std::result::Result<T, EngineError>;
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78
79 #[test]
80 fn test_should_display_config_error() {
81 let err = EngineError::config_error("invalid model");
82 assert_eq!(err.to_string(), "configuration error: invalid model");
83 }
84
85 #[test]
86 fn test_should_display_io_error_with_path() {
87 let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
88 let err = EngineError::io_error("/path/to/config.yml", io_err);
89 assert!(err.to_string().contains("/path/to/config.yml"));
90 assert!(err.to_string().contains("I/O error"));
91 }
92
93 #[test]
94 fn test_should_display_task_config_not_found() {
95 let err = EngineError::TaskConfigNotFound("custom_task".to_string());
96 assert!(err.to_string().contains("custom_task"));
97 }
98}