Skip to main content

wesichain_core/
error.rs

1use std::{error::Error as StdError, fmt, time::Duration};
2
3use thiserror::Error;
4
5#[derive(Debug, Error)]
6pub enum WesichainError {
7    #[error("LLM provider failed: {0}")]
8    LlmProvider(String),
9    #[error("Tool call failed for '{tool_name}': {reason}")]
10    ToolCallFailed { tool_name: String, reason: String },
11    #[error("Parsing failed on output '{output}': {reason}")]
12    ParseFailed { output: String, reason: String },
13    #[error("Operation timed out after {0:?}")]
14    Timeout(Duration),
15    #[error("Max retries ({max}) exceeded")]
16    MaxRetriesExceeded { max: usize },
17    #[error("Checkpoint failed: {0}")]
18    CheckpointFailed(String),
19    #[error("Operation was cancelled")]
20    Cancelled,
21    #[error("Invalid configuration: {0}")]
22    InvalidConfig(String),
23    #[error("Serialization/deserialization error: {0}")]
24    Serde(#[from] serde_json::Error),
25    #[error("{0}")]
26    Custom(String),
27    #[error("authentication failed for '{provider}': {message}")]
28    AuthenticationFailed { provider: String, message: String },
29    #[error("rate limit exceeded (retry after {retry_after:?})")]
30    RateLimitExceeded { retry_after: Option<Duration> },
31    #[error("context window exceeded: limit {limit} tokens, got {actual}")]
32    ContextWindowExceeded { limit: usize, actual: usize },
33    #[error("content policy violation: {reason}")]
34    ContentPolicyViolation { reason: String },
35}
36
37impl From<EmbeddingError> for WesichainError {
38    fn from(err: EmbeddingError) -> Self {
39        WesichainError::Custom(err.to_string())
40    }
41}
42
43impl From<StoreError> for WesichainError {
44    fn from(err: StoreError) -> Self {
45        WesichainError::Custom(err.to_string())
46    }
47}
48
49#[derive(Debug)]
50pub enum EmbeddingError {
51    InvalidResponse(String),
52    RateLimited { retry_after: Option<Duration> },
53    Timeout(Duration),
54    Provider(String),
55    Other(Box<dyn StdError + Send + Sync>),
56}
57
58impl fmt::Display for EmbeddingError {
59    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60        match self {
61            EmbeddingError::InvalidResponse(message) => {
62                write!(f, "Embedding invalid response: {message}")
63            }
64            EmbeddingError::RateLimited { retry_after } => match retry_after {
65                Some(duration) => write!(f, "Embedding rate limited (retry_after={duration:?})"),
66                None => write!(f, "Embedding rate limited (retry_after=unknown)"),
67            },
68            EmbeddingError::Timeout(duration) => write!(f, "Embedding timeout after {duration:?}"),
69            EmbeddingError::Provider(message) => write!(f, "Embedding provider error: {message}"),
70            EmbeddingError::Other(error) => write!(f, "Embedding error: {error}"),
71        }
72    }
73}
74
75impl StdError for EmbeddingError {
76    fn source(&self) -> Option<&(dyn StdError + 'static)> {
77        match self {
78            EmbeddingError::Other(error) => Some(error.as_ref()),
79            _ => None,
80        }
81    }
82}
83
84#[derive(Debug, Error)]
85pub enum StoreError {
86    #[error("dimension mismatch: expected {expected}, got {got}")]
87    DimensionMismatch { expected: usize, got: usize },
88    #[error("invalid document id: {0}")]
89    InvalidId(String),
90    #[error("Store error: {0}")]
91    Internal(#[source] Box<dyn StdError + Send + Sync>),
92}