Skip to main content

gba_core/
error.rs

1//! Error types for the GBA core engine.
2//!
3//! This module defines error types for engine operations including
4//! configuration, prompt rendering, agent execution, and I/O operations.
5
6use std::path::PathBuf;
7
8/// Error type for engine operations.
9#[derive(Debug, thiserror::Error)]
10#[non_exhaustive]
11pub enum EngineError {
12    /// Configuration error.
13    #[error("configuration error: {0}")]
14    ConfigError(String),
15
16    /// Error from the prompt manager.
17    #[error("prompt error: {0}")]
18    PromptError(#[from] gba_pm::PromptError),
19
20    /// Error from the Claude agent SDK.
21    #[error("agent error: {0}")]
22    AgentError(#[from] claude_agent_sdk_rs::ClaudeError),
23
24    /// I/O error during file operations.
25    #[error("I/O error at '{path}': {source}")]
26    IoError {
27        /// The path that caused the error.
28        path: PathBuf,
29        /// The underlying I/O error.
30        #[source]
31        source: std::io::Error,
32    },
33
34    /// YAML parsing error.
35    #[error("YAML parse error at '{path}': {source}")]
36    YamlError {
37        /// The path that caused the error.
38        path: PathBuf,
39        /// The underlying YAML error.
40        #[source]
41        source: serde_yaml::Error,
42    },
43
44    /// Task configuration not found.
45    #[error("task configuration not found for task kind: {0}")]
46    TaskConfigNotFound(String),
47
48    /// Git operation error.
49    #[error("git error: {0}")]
50    GitError(String),
51
52    /// GitHub CLI operation error.
53    #[error("github cli error: {0}")]
54    GitHubError(String),
55}
56
57impl EngineError {
58    /// Create a new I/O error with path context.
59    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    /// Create a new YAML error with path context.
67    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    /// Create a new configuration error.
75    pub fn config_error(message: impl Into<String>) -> Self {
76        Self::ConfigError(message.into())
77    }
78
79    /// Create a new Git error.
80    pub fn git_error(message: impl Into<String>) -> Self {
81        Self::GitError(message.into())
82    }
83
84    /// Create a new GitHub CLI error.
85    pub fn github_error(message: impl Into<String>) -> Self {
86        Self::GitHubError(message.into())
87    }
88}
89
90/// Result type alias for engine operations.
91pub 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}