kcode_openai_api/
error.rs1use std::{error::Error as StdError, fmt};
2
3pub type Result<T> = std::result::Result<T, Error>;
5
6#[derive(Debug)]
8pub enum Error {
9 InvalidApiKey,
11 InvalidInput(String),
13 Transport(String),
15 Provider {
17 status: u16,
19 code: Option<String>,
21 message: String,
23 request_id: Option<String>,
25 },
26 Protocol(String),
28}
29
30impl fmt::Display for Error {
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 match self {
33 Self::InvalidApiKey => f.write_str("the OpenAI API key is empty or invalid"),
34 Self::InvalidInput(message) => write!(f, "invalid OpenAI request: {message}"),
35 Self::Transport(message) => write!(f, "OpenAI transport failed: {message}"),
36 Self::Provider {
37 status,
38 code,
39 message,
40 request_id,
41 } => {
42 write!(f, "OpenAI returned HTTP {status}")?;
43 if let Some(code) = code {
44 write!(f, " ({code})")?;
45 }
46 write!(f, ": {message}")?;
47 if let Some(request_id) = request_id {
48 write!(f, " [request_id: {request_id}]")?;
49 }
50 Ok(())
51 }
52 Self::Protocol(message) => write!(f, "invalid OpenAI response: {message}"),
53 }
54 }
55}
56
57impl StdError for Error {}
58
59pub(crate) fn transport(error: impl fmt::Display) -> Error {
60 let message = error.to_string();
61 Error::Transport(if message.to_ascii_lowercase().contains("timed out") {
62 "the request timed out".into()
63 } else {
64 "the service could not be reached".into()
65 })
66}
67
68pub(crate) fn clean_message(value: &str, limit: usize) -> String {
69 let value = value
70 .chars()
71 .map(|character| {
72 if character.is_control() {
73 ' '
74 } else {
75 character
76 }
77 })
78 .take(limit)
79 .collect::<String>()
80 .split_whitespace()
81 .collect::<Vec<_>>()
82 .join(" ");
83 if value.is_empty() {
84 "unknown error".into()
85 } else {
86 value
87 }
88}