Skip to content

Commit 32bae79

Browse files
committed
fix: handle OpenAI API error variants 🐛
- Improve error handling for various OpenAI API errors. - Enhance user feedback for network, JSON, and other API errors. - Refactor Result type for consistency across the `openai` module.
1 parent 3bee44a commit 32bae79

File tree

2 files changed

+47
-26
lines changed

2 files changed

+47
-26
lines changed

src/main.rs

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@
99
* File Created: 2025-03-01 17:17:30
1010
*
1111
* Modified By: mingcheng ([email protected])
12-
* Last Modified: 2025-03-05 10:12:30
12+
* Last Modified: 2025-03-17 12:14:41
1313
*/
1414

1515
use aigitcommit::cli::Cli;
1616
use aigitcommit::git::Git;
1717
use aigitcommit::openai;
1818
use aigitcommit::openai::OpenAI;
1919
use arboard::Clipboard;
20+
use async_openai::error::OpenAIError;
2021
use async_openai::types::{
2122
ChatCompletionRequestSystemMessageArgs, ChatCompletionRequestUserMessageArgs,
2223
};
@@ -34,17 +35,17 @@ async fn main() -> std::result::Result<(), Box<dyn Error>> {
3435
let cli = Cli::parse();
3536

3637
// Initialize logging
37-
tracing_subscriber::fmt()
38-
.with_max_level(if cli.verbose {
39-
trace!("Verbose mode enabled, set the log level to TRACE. It will makes a little bit noise.");
40-
Level::TRACE
41-
} else {
42-
debug!("Verbose mode disabled, set the default log level to WARN");
43-
Level::WARN
44-
})
45-
.without_time()
46-
.with_target(false)
47-
.init();
38+
if cli.verbose {
39+
tracing_subscriber::fmt()
40+
.with_max_level(Level::TRACE)
41+
.without_time()
42+
.with_target(false)
43+
.init();
44+
45+
trace!(
46+
"Verbose mode enabled, set the log level to TRACE. It will makes a little bit noise."
47+
);
48+
}
4849

4950
// Check if the specified path is a valid directory
5051
let repo_dir = fs::canonicalize(&cli.repo_path)?;
@@ -68,11 +69,11 @@ async fn main() -> std::result::Result<(), Box<dyn Error>> {
6869
// Get the last 5 commit logs
6970
// if the repository has less than 5 commits, it will return all logs
7071
let logs = repository.get_logs(5)?;
71-
debug!("Got logs size is {}", logs.len());
72+
debug!("got logs size is {}", logs.len());
7273

7374
// If git commit log is empty, return error
7475
if logs.is_empty() {
75-
return Err("No commit logs found".into());
76+
return Err("no commit logs found".into());
7677
}
7778

7879
// Instantiate OpenAI client, ready to send requests to the OpenAI API
@@ -107,7 +108,24 @@ async fn main() -> std::result::Result<(), Box<dyn Error>> {
107108
];
108109

109110
// Send the request to OpenAI API and get the response
110-
let result = client.chat(&model_name.to_string(), messages).await?;
111+
let result = match client.chat(&model_name.to_string(), messages).await {
112+
Ok(s) => s,
113+
Err(e) => {
114+
let message = match e {
115+
OpenAIError::Reqwest(_) | OpenAIError::StreamError(_) => {
116+
"network request error".to_string()
117+
}
118+
OpenAIError::JSONDeserialize(_err) => "json deserialization error".to_string(),
119+
OpenAIError::InvalidArgument(_) => "invalid argument".to_string(),
120+
OpenAIError::FileSaveError(_) | OpenAIError::FileReadError(_) => {
121+
"io error".to_string()
122+
}
123+
OpenAIError::ApiError(e) => format!("api error {:?}", e),
124+
};
125+
126+
return Err(message.into());
127+
}
128+
};
111129

112130
trace!("write to stdout, and finish the process");
113131
writeln!(std::io::stdout(), "{}", result)?;
@@ -124,36 +142,36 @@ async fn main() -> std::result::Result<(), Box<dyn Error>> {
124142

125143
// directly commit the changes to the repository if the --commit option is enabled
126144
if cli.commit {
127-
trace!("Commit option is enabled, will commit the changes to the repository");
145+
trace!("commit option is enabled, will commit the changes to the repository");
128146
let mut confirm = Confirm::new();
129147
confirm
130-
.with_prompt("Do you want to commit the changes with the generated commit message?")
148+
.with_prompt("do you want to commit the changes with the generated commit message?")
131149
.default(false);
132150

133151
// Prompt the user for confirmation if --yes option is not enabled
134152
if cli.yes || confirm.interact()? {
135153
match repository.commit(&result) {
136154
Ok(_) => {
137-
writeln!(std::io::stdout(), "Commit successful!")?;
155+
writeln!(std::io::stdout(), "commit successful!")?;
138156
}
139157
Err(e) => {
140-
writeln!(std::io::stderr(), "Commit failed: {}", e)?;
158+
writeln!(std::io::stderr(), "commit failed: {}", e)?;
141159
}
142160
}
143161
}
144162
}
145163

146164
// If the --save option is enabled, save the commit message to a file
147165
if !cli.save.is_empty() {
148-
trace!("Save option is enabled, will save the commit message to a file");
166+
trace!("save option is enabled, will save the commit message to a file");
149167
let save_path = &cli.save;
150-
debug!("The save file path is {:?}", &save_path);
168+
debug!("the save file path is {:?}", &save_path);
151169

152170
let mut file = File::create(save_path)?;
153171
file.write_all(result.as_bytes())?;
154172
file.flush()?;
155173

156-
writeln!(std::io::stdout(), "Commit message saved to {}", &save_path)?;
174+
writeln!(std::io::stdout(), "commit message saved to {}", &save_path)?;
157175
}
158176

159177
Ok(())

src/openai.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
* Modified By: mingcheng ([email protected])
1212
* Last Modified: 2025-03-06 17:59:08
1313
*/
14-
1514
use askama::Template;
1615
use async_openai::config::OPENAI_API_BASE;
16+
use async_openai::error::OpenAIError;
1717
use async_openai::{
1818
Client,
1919
config::OpenAIConfig,
@@ -102,13 +102,16 @@ impl OpenAI {
102102
&self,
103103
model_name: &str,
104104
message: Vec<ChatCompletionRequestMessage>,
105-
) -> Result<String, Box<dyn Error>> {
105+
) -> Result<String, OpenAIError> {
106106
let request = CreateChatCompletionRequestArgs::default()
107107
.model(model_name)
108108
.messages(message)
109109
.build()?;
110110

111-
let response = self.client.chat().create(request).await?;
111+
let response = match self.client.chat().create(request).await {
112+
Ok(s) => s,
113+
Err(e) => return Err(e),
114+
};
112115

113116
let mut result = vec![];
114117
response.choices.iter().for_each(|choice| {
@@ -117,7 +120,7 @@ impl OpenAI {
117120

118121
if let Option::Some(usage) = response.usage {
119122
debug!(
120-
"Usage: completion_tokens: {}, prompt_tokens: {}, total_tokens: {}",
123+
"usage: completion_tokens: {}, prompt_tokens: {}, total_tokens: {}",
121124
usage.completion_tokens, usage.prompt_tokens, usage.total_tokens
122125
);
123126
}

0 commit comments

Comments
 (0)