Skip to main content

agentkit_provider_cerebras/
error.rs

1//! Error types for the Cerebras adapter.
2
3use agentkit_core::ItemKind;
4use agentkit_http::HttpError;
5use agentkit_loop::LoopError;
6use thiserror::Error;
7
8use crate::config::PartKindName;
9
10/// Errors produced at adapter construction or external-endpoint call time.
11#[derive(Debug, Error)]
12pub enum CerebrasError {
13    /// Configuration validation failed.
14    #[error(transparent)]
15    Build(#[from] BuildError),
16
17    /// A required environment variable is missing or unparseable.
18    #[error("missing or invalid environment variable {0}")]
19    MissingEnv(&'static str),
20
21    /// Cerebras returned a non-success HTTP status.
22    #[error("Cerebras request failed with status {status}: {body}")]
23    Status {
24        /// HTTP status code.
25        status: u16,
26        /// Body of the failing response (best-effort).
27        body: String,
28    },
29
30    /// Underlying HTTP transport error.
31    #[error(transparent)]
32    Http(#[from] HttpError),
33
34    /// Response JSON could not be parsed.
35    #[error(transparent)]
36    Response(#[from] ResponseError),
37
38    /// Generic provider-side error surfaced through the adapter.
39    #[error("{0}")]
40    Other(String),
41}
42
43impl From<CerebrasError> for LoopError {
44    fn from(error: CerebrasError) -> Self {
45        match error {
46            CerebrasError::Other(msg) => LoopError::Provider(msg),
47            other => LoopError::Provider(other.to_string()),
48        }
49    }
50}
51
52/// Errors produced while assembling a Cerebras chat-completions request body.
53#[derive(Debug, Error)]
54pub enum BuildError {
55    /// Transcript contained a content part the Cerebras API cannot accept for
56    /// the given role (e.g. a raw `Custom` part on a user message).
57    #[error("unsupported content part {part_kind:?} on role {role:?}")]
58    UnsupportedPart {
59        /// Role of the offending transcript item.
60        role: ItemKind,
61        /// Kind of the offending part.
62        part_kind: PartKindName,
63    },
64
65    /// Tool name failed the Cerebras name regex (`^[a-zA-Z0-9_-]{1,64}$`).
66    #[error("tool name {0:?} does not match ^[a-zA-Z0-9_-]{{1,64}}$")]
67    InvalidToolName(String),
68
69    /// JSON-Schema passed to `OutputFormat::JsonSchema` violated a documented
70    /// Cerebras constraint (e.g. `pattern`, `$ref` outside `$defs`, nest depth).
71    #[error("response_format schema violates Cerebras constraint: {0}")]
72    SchemaViolation(String),
73
74    /// `prediction` was set together with an incompatible parameter.
75    #[error("prediction cannot be combined with {0}")]
76    PredictionConflicts(&'static str),
77
78    /// A field fell outside the documented valid range.
79    #[error("{field} out of range: {message}")]
80    OutOfRange {
81        /// Name of the offending field.
82        field: &'static str,
83        /// Human-readable description of the violation.
84        message: String,
85    },
86
87    /// `from_env()` could not locate a required variable.
88    #[error("missing or invalid environment variable {0}")]
89    MissingEnv(&'static str),
90
91    /// `top_logprobs` was set without `logprobs: true`.
92    #[error("top_logprobs requires logprobs = true")]
93    TopLogprobsWithoutLogprobs,
94
95    /// Generic JSON serialization failure.
96    #[error(transparent)]
97    Serialize(#[from] serde_json::Error),
98}
99
100impl From<BuildError> for LoopError {
101    fn from(error: BuildError) -> Self {
102        LoopError::Provider(error.to_string())
103    }
104}
105
106/// Errors produced while parsing a Cerebras response (buffered or streaming).
107#[derive(Debug, Error)]
108pub enum ResponseError {
109    /// Malformed or unexpected JSON / missing required field. Reserved for
110    /// protocol-level breakage, not for server-reported errors.
111    #[error("protocol error: {0}")]
112    Protocol(String),
113
114    /// Server-reported error surfaced mid-stream via `event: error` or an
115    /// unnamed frame whose JSON carries a top-level `error` key.
116    #[error("stream error ({status_code:?}): {message}")]
117    StreamError {
118        /// Error message reported by Cerebras.
119        message: String,
120        /// Optional HTTP status the server attached to the frame.
121        status_code: Option<u16>,
122    },
123}
124
125impl From<ResponseError> for LoopError {
126    fn from(error: ResponseError) -> Self {
127        LoopError::Provider(error.to_string())
128    }
129}