use gcloud_auth::error::Error as GCloudAuthError;
use pyo3::exceptions::PyRuntimeError;
use pyo3::pyclass::PyClassGuardError;
use pyo3::PyErr;
use reqwest::StatusCode;
use thiserror::Error;
use tracing::error;
#[derive(Error, Debug)]
pub enum ProviderError {
#[error("Error: {0}")]
Error(String),
#[error("Failed to downcast Python object: {0}")]
DowncastError(String),
#[error("Client did not provide response")]
ClientNoResponseError,
#[error("Failed to create header value for the agent client")]
CreateHeaderValueError(#[from] reqwest::header::InvalidHeaderValue),
#[error("Failed to create header name for the agent client")]
CreateHeaderNameError(#[from] reqwest::header::InvalidHeaderName),
#[error("Failed to create agent client: {0}")]
CreateClientError(#[source] reqwest::Error),
#[error("Request failed: {0}")]
RequestError(#[from] reqwest::Error),
#[error("Failed to serialize chat request: {0}")]
SerializationError(#[from] serde_json::Error),
#[error("Failed to deserialize response into provider type")]
DeserializationError,
#[error("Failed to extract embedding config. Check provider and config compatibility: {0}")]
EmbeddingConfigExtractionError(String),
#[error("Missing authentication information. Failed to find API_KEY or credentials in environment variables.")]
MissingAuthenticationError,
#[error("Unsupported content type")]
UnsupportedContentTypeError,
#[error("Failed to get response: {0} with status code {1}")]
CompletionError(String, StatusCode),
#[error("Provider not supported: {0}")]
ProviderNotSupportedError(String),
#[error("No provider specified in GenAiClient")]
NoProviderError,
#[error("Undefined error: {0}")]
UndefinedError(String),
#[error("Invalid response type")]
InvalidResponseType(String),
#[error("Failed to create tokio runtime: {0}")]
RuntimeError(String),
#[error("No embeddings found in the response")]
NoEmbeddingsFound,
#[error(transparent)]
TypeError(#[from] potato_type::error::TypeError),
#[error(transparent)]
UtilError(#[from] potato_util::UtilError),
#[error(transparent)]
DecodeError(#[from] base64::DecodeError),
#[error(transparent)]
Utf8Error(#[from] std::string::FromUtf8Error),
#[error(transparent)]
GCloudAuthError(#[from] GCloudAuthError),
#[error("No Google credentials found in environment variables")]
NoCredentialsFound,
#[error("No project ID found in credentials or environment variables")]
NoProjectIdFound,
#[error("Failed to retrieve access token: {0}")]
TokenError(String),
#[error("Failed to retrieve OPENAI_API_KEY from the environment")]
MissingOpenAIApiKeyError,
#[error("{0}")]
NotImplementedError(String),
#[error("Method does not support PredictRequest")]
DoesNotSupportPredictRequest,
#[error("Method does not support array inputs")]
DoesNotSupportArray,
#[error("{0}")]
InvalidInputType(String),
#[error("{0}")]
InvalidConfigType(String),
#[error("Embedding not supported for this provider")]
EmbeddingNotSupported,
#[error(transparent)]
MacroError(#[from] potatohead_macro::error::MacroError),
}
impl<'a, 'py> From<pyo3::CastError<'a, 'py>> for ProviderError {
fn from(err: pyo3::CastError<'a, 'py>) -> Self {
ProviderError::DowncastError(err.to_string())
}
}
impl From<ProviderError> for PyErr {
fn from(err: ProviderError) -> PyErr {
let msg = err.to_string();
error!("{}", msg);
PyRuntimeError::new_err(msg)
}
}
impl From<PyErr> for ProviderError {
fn from(err: PyErr) -> Self {
ProviderError::Error(err.to_string())
}
}
impl<'a, 'py> From<PyClassGuardError<'a, 'py>> for ProviderError {
fn from(err: PyClassGuardError<'a, 'py>) -> Self {
ProviderError::Error(err.to_string())
}
}