pub use api::{ApiError, ApiErrorKind};
use eventsource_stream::EventStreamError;
pub use processing::ProcessingError;
pub use request::RequestError;
use thiserror::Error;
use crate::error::sse::SseError;
pub mod api;
pub mod processing;
pub mod request;
pub mod sse;
#[derive(Debug, Error)]
pub enum OpenAIError {
#[error("请求错误: {0}")]
Request(#[from] RequestError),
#[error("API 错误: {0}")]
Api(#[from] ApiError),
#[error("处理错误: {0}")]
Processing(#[from] ProcessingError),
}
impl OpenAIError {
pub fn is_request_error(&self) -> bool {
matches!(self, Self::Request(_))
}
pub fn is_api_error(&self) -> bool {
matches!(self, Self::Api(_))
}
pub fn is_processing_error(&self) -> bool {
matches!(self, Self::Processing(_))
}
pub fn is_timeout(&self) -> bool {
matches!(self, Self::Request(err) if err.is_timeout())
}
pub fn is_connection(&self) -> bool {
matches!(self, Self::Request(err) if err.is_connection())
}
pub fn is_authentication(&self) -> bool {
matches!(self, Self::Api(err) if err.is_authentication())
}
pub fn is_rate_limit(&self) -> bool {
matches!(self, Self::Api(err) if err.is_rate_limit())
}
pub fn is_server_error(&self) -> bool {
matches!(self, Self::Api(err) if err.is_server_error())
}
pub fn is_bad_request(&self) -> bool {
matches!(self, Self::Api(err) if err.is_bad_request())
}
pub fn is_deserialization(&self) -> bool {
matches!(self, Self::Processing(ProcessingError::Deserialization(_)))
}
pub fn as_api_error(&self) -> Option<&ApiError> {
match self {
Self::Api(err) => Some(err),
_ => None,
}
}
pub fn status_code(&self) -> Option<u16> {
match self {
Self::Request(err) => err.status().map(|s| s.as_u16()),
Self::Api(err) => Some(err.status),
Self::Processing(_) => None,
}
}
pub fn is_retryable(&self) -> bool {
match self {
Self::Request(err) if err.is_timeout() || err.is_connection() => true,
Self::Api(err) if err.is_rate_limit() || err.is_server_error() || err.is_conflict() => {
true
}
Self::Processing(ProcessingError::TextRead(err)) if err.is_decode() => true,
_ => false,
}
}
pub fn message(&self) -> String {
match self {
Self::Request(err) => err.to_string(),
Self::Api(err) => err.message.clone(),
Self::Processing(err) => err.to_string(),
}
}
}
impl OpenAIError {
pub fn from_eventsource_stream_error(err: EventStreamError<reqwest::Error>) -> Self {
match err {
EventStreamError::Utf8(utf8_err) => {
ProcessingError::Sse(SseError::Utf8(utf8_err)).into()
}
EventStreamError::Transport(e) => RequestError::from(e).into(),
EventStreamError::Parser(parse_err) => {
ProcessingError::Sse(SseError::Parser(parse_err.to_string())).into()
}
}
}
}