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 #[error("git error: {0}")]
50 GitError(String),
51
52 #[error("github cli error: {0}")]
54 GitHubError(String),
55}
56
57impl EngineError {
58 pub fn io_error(path: impl Into<PathBuf>, source: std::io::Error) -> Self {
60 Self::IoError {
61 path: path.into(),
62 source,
63 }
64 }
65
66 pub fn yaml_error(path: impl Into<PathBuf>, source: serde_yaml::Error) -> Self {
68 Self::YamlError {
69 path: path.into(),
70 source,
71 }
72 }
73
74 pub fn config_error(message: impl Into<String>) -> Self {
76 Self::ConfigError(message.into())
77 }
78
79 pub fn git_error(message: impl Into<String>) -> Self {
81 Self::GitError(message.into())
82 }
83
84 pub fn github_error(message: impl Into<String>) -> Self {
86 Self::GitHubError(message.into())
87 }
88}
89
90pub type Result<T> = std::result::Result<T, EngineError>;
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96
97 #[test]
98 fn test_should_display_config_error() {
99 let err = EngineError::config_error("invalid model");
100 assert_eq!(err.to_string(), "configuration error: invalid model");
101 }
102
103 #[test]
104 fn test_should_display_io_error_with_path() {
105 let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
106 let err = EngineError::io_error("/path/to/config.yml", io_err);
107 assert!(err.to_string().contains("/path/to/config.yml"));
108 assert!(err.to_string().contains("I/O error"));
109 }
110
111 #[test]
112 fn test_should_display_task_config_not_found() {
113 let err = EngineError::TaskConfigNotFound("custom_task".to_string());
114 assert!(err.to_string().contains("custom_task"));
115 }
116
117 #[test]
118 fn test_should_display_git_error() {
119 let err = EngineError::git_error("failed to get branch");
120 assert_eq!(err.to_string(), "git error: failed to get branch");
121 }
122
123 #[test]
124 fn test_should_display_github_error() {
125 let err = EngineError::github_error("failed to get PR status");
126 assert_eq!(err.to_string(), "github cli error: failed to get PR status");
127 }
128}