1use thiserror::Error;
2
3pub type DoumResult<T> = std::result::Result<T, DoumError>;
5
6#[derive(Error, Debug)]
8pub enum DoumError {
9 #[error("Configuration error: {0}")]
11 Config(String),
12
13 #[error("LLM API error: {0}")]
15 LLM(String),
16
17 #[error("Parse error: {0}")]
19 Parse(String),
20
21 #[error("IO error: {0}")]
23 Io(#[from] std::io::Error),
24
25 #[error("Command execution failed: {0}")]
27 CommandExecution(String),
28
29 #[error("User cancelled operation")]
31 UserCancelled,
32
33 #[error("Invalid configuration: {0}")]
35 InvalidConfig(String),
36
37 #[error("Request timeout")]
39 Timeout,
40
41 #[error("HTTP request error: {0}")]
43 Reqwest(#[from] reqwest::Error),
44
45 #[error("JSON error: {0}")]
47 Json(#[from] serde_json::Error),
48
49 #[error("TOML error: {0}")]
51 Toml(#[from] toml::de::Error),
52
53 #[error("User interaction error: {0}")]
55 Dialoguer(String),
56}
57
58impl DoumError {
59 pub fn user_message(&self) -> String {
61 match self {
62 DoumError::Config(msg) => {
63 format!("Configuration error: {}", msg)
64 }
65 DoumError::LLM(msg) => {
66 if msg.contains("401") || msg.contains("unauthorized") {
67 format!(
68 "Authentication error (LLM API): {}. Check your API key.",
69 msg
70 )
71 } else if msg.contains("timeout") || msg.contains("timed out") {
72 "LLM request timed out. Please try again or increase the timeout.".to_string()
73 } else if msg.contains("rate limit") || msg.contains("429") {
74 "Rate limit exceeded. Please wait a moment and try again.".to_string()
75 } else {
76 format!("LLM API error: {}", msg)
77 }
78 }
79 DoumError::Parse(msg) => {
80 format!("Failed to parse LLM response: {}", msg)
81 }
82 DoumError::Io(err) => {
83 format!("I/O error: {}", err)
84 }
85 DoumError::CommandExecution(msg) => {
86 format!("Command execution failed: {}", msg)
87 }
88 DoumError::UserCancelled => "Operation cancelled by user.".to_string(),
89 DoumError::InvalidConfig(msg) => {
90 format!("Invalid configuration: {}", msg)
91 }
92 DoumError::Timeout => "Request timed out. Please try again.".to_string(),
93 DoumError::Reqwest(err) => {
94 if err.is_timeout() {
95 "Network timeout. Please check your connection and try again.".to_string()
96 } else if err.is_connect() {
97 "Failed to connect to server. Please check your network connection.".to_string()
98 } else {
99 format!("Network error: {}", err)
100 }
101 }
102 DoumError::Json(err) => {
103 format!("JSON error: {}", err)
104 }
105 DoumError::Toml(err) => {
106 format!("TOML error: {}", err)
107 }
108 DoumError::Dialoguer(msg) => {
109 format!("User interaction error: {}", msg)
110 }
111 }
112 }
113}
114
115impl From<dialoguer::Error> for DoumError {
116 fn from(err: dialoguer::Error) -> Self {
117 DoumError::Dialoguer(err.to_string())
118 }
119}