1use std::path::PathBuf;
2use thiserror::Error;
3
4#[derive(Debug, Error)]
5pub enum DotAgentError {
6 #[error("Profile not found: {name}")]
7 ProfileNotFound { name: String },
8
9 #[error("Target directory does not exist: {path}")]
10 TargetNotFound { path: PathBuf },
11
12 #[error("Profile already exists: {name}")]
13 ProfileAlreadyExists { name: String },
14
15 #[error("Invalid profile name: '{name}' - must contain only alphanumeric, hyphen, underscore")]
16 InvalidProfileName { name: String },
17
18 #[error("Conflict detected - file exists with different content: {path}")]
19 Conflict { path: PathBuf },
20
21 #[error("Local modifications detected: {paths:?}")]
22 LocalModifications { paths: Vec<PathBuf> },
23
24 #[error("IO error: {0}")]
25 Io(#[from] std::io::Error),
26
27 #[error("TOML serialization error: {0}")]
28 TomlSer(#[from] toml::ser::Error),
29
30 #[error("TOML deserialization error: {0}")]
31 TomlDe(#[from] toml::de::Error),
32
33 #[error("Home directory not found")]
34 HomeNotFound,
35
36 #[error("GUI error: {0}")]
37 Gui(String),
38
39 #[error("Git error: {0}")]
40 Git(String),
41
42 #[error("Rule not found: {name}")]
43 RuleNotFound { name: String },
44
45 #[error("Rule already exists: {name}")]
46 RuleAlreadyExists { name: String },
47
48 #[error("Invalid rule name: '{name}' - must be alphanumeric, hyphen, underscore, 1-64 chars")]
49 InvalidRuleName { name: String },
50
51 #[error("Claude CLI not found. Install with: brew install claude")]
52 ClaudeNotFound,
53
54 #[error("Claude CLI execution failed: {message}")]
55 ClaudeExecutionFailed { message: String },
56
57 #[error("Glob pattern error: {0}")]
58 GlobPattern(#[from] glob::PatternError),
59
60 #[error("Glob error: {0}")]
61 Glob(#[from] glob::GlobError),
62
63 #[error("Snapshot not found: {id}")]
64 SnapshotNotFound { id: String },
65
66 #[error("Config parse error in {path}: {message}")]
67 ConfigParse { path: PathBuf, message: String },
68
69 #[error("Config key not found: {key}")]
70 ConfigKeyNotFound { key: String },
71
72 #[error("Config parse error: {message}")]
73 ConfigParseSimple { message: String },
74
75 #[error("GitHub CLI (gh) not found. Install with: brew install gh")]
76 GitHubCliNotFound,
77
78 #[error("GitHub API error: {message}")]
79 GitHubApiError { message: String },
80
81 #[error("Hub already exists: {name}")]
82 HubAlreadyExists { name: String },
83
84 #[error("Hub not found: {name}")]
85 HubNotFound { name: String },
86
87 #[error("Cannot remove default hub")]
88 CannotRemoveDefaultHub,
89
90 #[error("Channel already exists: {name}")]
91 ChannelAlreadyExists { name: String },
92
93 #[error("Channel not found: {name}")]
94 ChannelNotFound { name: String },
95
96 #[error("Cannot remove built-in channel: {name}")]
97 CannotRemoveBuiltinChannel { name: String },
98
99 #[error("JSON parse error: {message}")]
100 JsonParseError { message: String },
101
102 #[error("JSON error: {0}")]
103 Json(#[from] serde_json::Error),
104
105 #[error("TOML parse error in {path}: {message}")]
106 TomlError { path: PathBuf, message: String },
107
108 #[error("Category not found: {name}")]
109 CategoryNotFound { name: String },
110
111 #[error("Fusion conflict: {path} exists in multiple profiles")]
112 FusionConflict { path: PathBuf },
113
114 #[error("LLM classification failed: {message}")]
115 LlmClassificationFailed { message: String },
116
117 #[error("Internal error: {0}")]
118 Internal(String),
119
120 #[error("Not found: {0}")]
121 NotFound(String),
122
123 #[error("Operation not found: {id}")]
124 OperationNotFound { id: String },
125
126 #[error("Checkpoint not found: {id}")]
127 CheckpointNotFound { id: String },
128}
129
130pub type Result<T> = std::result::Result<T, DotAgentError>;
131
132impl DotAgentError {
133 pub fn exit_code(&self) -> i32 {
134 match self {
135 Self::ProfileNotFound { .. } => 2,
136 Self::TargetNotFound { .. } => 3,
137 Self::LocalModifications { .. } => 4,
138 Self::InvalidProfileName { .. } => 5,
139 Self::Conflict { .. } => 6,
140 Self::RuleNotFound { .. } => 7,
141 Self::RuleAlreadyExists { .. } => 8,
142 Self::InvalidRuleName { .. } => 9,
143 Self::ClaudeNotFound => 10,
144 Self::ClaudeExecutionFailed { .. } => 11,
145 Self::SnapshotNotFound { .. } => 12,
146 Self::ConfigParse { .. } => 13,
147 Self::ConfigKeyNotFound { .. } => 14,
148 Self::ConfigParseSimple { .. } => 15,
149 Self::GitHubCliNotFound => 16,
150 Self::GitHubApiError { .. } => 17,
151 Self::HubAlreadyExists { .. } => 18,
152 Self::HubNotFound { .. } => 19,
153 Self::CannotRemoveDefaultHub => 20,
154 Self::ChannelAlreadyExists { .. } => 21,
155 Self::ChannelNotFound { .. } => 22,
156 Self::CannotRemoveBuiltinChannel { .. } => 23,
157 Self::JsonParseError { .. } => 24,
158 Self::CategoryNotFound { .. } => 25,
159 Self::FusionConflict { .. } => 26,
160 Self::LlmClassificationFailed { .. } => 27,
161 Self::Internal(_) => 28,
162 Self::NotFound(_) => 29,
163 Self::OperationNotFound { .. } => 30,
164 Self::CheckpointNotFound { .. } => 31,
165 _ => 1,
166 }
167 }
168}