1use pyo3::exceptions::PyRuntimeError;
2use pyo3::pyclass::PyClassGuardError;
3use pyo3::PyErr;
4use pythonize::PythonizeError;
5use thiserror::Error;
6use tracing::error;
7
8#[derive(Error, Debug)]
9pub enum TypeError {
10 #[error("Error: {0}")]
11 Error(String),
12
13 #[error("Unknown provider: {0}")]
14 UnknownProviderError(String),
15
16 #[error("Unknown model: {0}")]
17 UnknownModelError(String),
18
19 #[error("{0}")]
20 InvalidInput(String),
21
22 #[error(transparent)]
23 UtilError(#[from] potato_util::UtilError),
24
25 #[error(transparent)]
26 SerdeError(#[from] serde_json::Error),
27
28 #[error(transparent)]
29 StdError(#[from] std::io::Error),
30
31 #[error("Failed to create GeminiEmbeddingConfig: {0}")]
32 GeminiEmbeddingConfigError(String),
33
34 #[error("Invalid media type: {0}")]
35 InvalidMediaType(String),
36
37 #[error("Unsupported prompt content type")]
38 UnsupportedTypeError,
39
40 #[error("Cannot bind non-string content")]
41 CannotBindNonStringContent,
42
43 #[error("Failed to serialize Python object: {0}")]
44 PySerializationError(String),
45
46 #[error("Content type is not supported")]
47 UnsupportedContentType,
48
49 #[error("Invalid model settings provided. ModelSettings expects either OpenAIChatSettings, GeminiSettings, or AnthropicSettings.")]
50 InvalidModelSettings,
51
52 #[error("Expected string, Message, or list of messages")]
53 MessageParseError,
54
55 #[error("Invalid message type in list. Received: {0}")]
56 InvalidMessageTypeInList(String),
57
58 #[error("Either 'auto_mode' or 'manual_mode' must be provided, but not both.")]
59 MissingRoutingConfigMode,
60
61 #[error("Invalid data type for Part. Expected String, Blob, FileData, FunctionCall, FunctionResponse, ExecutableCode, or CodeExecutionResult. Got: {0}")]
62 InvalidDataType(String),
63
64 #[error("Invalid list type for Part. Expected a list of Strings or a list of Message objects. Got: {0}")]
65 InvalidListType(String),
66
67 #[error("Parts must be a string, Part, DataNum variant, or a list of these types")]
68 InvalidPartType,
69
70 #[error("Invalid ranking config provided.")]
71 InvalidRankingConfig,
72
73 #[error("Invalid retrieval source provided.")]
74 InvalidRetrievalSource,
75
76 #[error("Invalid authentication configuration provided.")]
77 InvalidAuthConfig,
78
79 #[error("Invalid OAuth configuration provided.")]
80 InvalidOauthConfig,
81
82 #[error("Invalid OIDC configuration provided.")]
83 InvalidOidcConfig,
84
85 #[error("More than one system instruction provided where only one is allowed.")]
86 MoreThanOneSystemInstruction,
87
88 #[error("Invalid request type for Anthropic provider.")]
89 InvalidRequestTypeForAnthropic,
90
91 #[error("Invalid request type for Gemini provider.")]
92 InvalidRequestTypeForGemini,
93
94 #[error("Invalid request type for OpenAI provider.")]
95 InvalidRequestTypeForOpenAI,
96
97 #[error("Unsupported provider for request creation.")]
98 UnsupportedProviderForRequestCreation,
99
100 #[error("OpenAI response content is empty.")]
101 EmptyOpenAIResponseContent,
102
103 #[error("{0}")]
104 UnsupportedConversion(String),
105
106 #[error("Cannot convert message to self")]
107 CantConvertSelf,
108
109 #[error("Unsupported provider for message conversion")]
110 UnsupportedProviderError,
111
112 #[error("Message is not an OpenAI ChatMessage")]
113 MessageIsNotOpenAIChatMessage,
114
115 #[error("Message is not a Google GeminiContent")]
116 MessageIsNotGoogleGeminiContent,
117
118 #[error("Message is not an Anthropic MessageParam")]
119 MessageIsNotAnthropicMessageParam,
120}
121
122impl From<TypeError> for PyErr {
123 fn from(err: TypeError) -> PyErr {
124 let msg = err.to_string();
125 error!("{}", msg);
126 PyRuntimeError::new_err(msg)
127 }
128}
129
130impl From<PythonizeError> for TypeError {
131 fn from(err: PythonizeError) -> Self {
132 TypeError::Error(err.to_string())
133 }
134}
135
136impl From<PyErr> for TypeError {
137 fn from(err: PyErr) -> Self {
138 TypeError::Error(err.to_string())
139 }
140}
141
142impl<'a, 'py> From<PyClassGuardError<'a, 'py>> for TypeError {
143 fn from(err: PyClassGuardError<'a, 'py>) -> Self {
144 TypeError::Error(err.to_string())
145 }
146}
147
148impl<'a, 'py> From<pyo3::CastError<'a, 'py>> for TypeError {
149 fn from(err: pyo3::CastError<'a, 'py>) -> Self {
150 TypeError::Error(err.to_string())
151 }
152}