openmemory 0.1.1

OpenMemory - Cognitive memory system for AI applications
Documentation
//! Error types for OpenMemory SDK
//!
//! This module defines all error types used throughout the library.

use thiserror::Error;

/// Main error type for OpenMemory operations
#[derive(Error, Debug)]
pub enum Error {
    /// Database operation failed
    #[error("Database error: {0}")]
    Database(#[from] rusqlite::Error),

    /// HTTP request failed
    #[error("HTTP error: {0}")]
    Http(#[from] reqwest::Error),

    /// JSON serialization/deserialization failed
    #[error("JSON error: {0}")]
    Json(#[from] serde_json::Error),

    /// Configuration error
    #[error("Configuration error: {0}")]
    Config(String),

    /// Embedding generation failed
    #[error("Embedding error: {0}")]
    Embedding(String),

    /// Resource not found
    #[error("Not found: {0}")]
    NotFound(String),

    /// Invalid input provided
    #[error("Invalid input: {0}")]
    InvalidInput(String),

    /// IO error
    #[error("IO error: {0}")]
    Io(#[from] std::io::Error),

    /// Rate limit exceeded
    #[error("Rate limit exceeded: retry after {retry_after_secs} seconds")]
    RateLimit { retry_after_secs: u64 },

    /// Authentication failed
    #[error("Authentication error: {0}")]
    Auth(String),

    /// Vector dimension mismatch
    #[error("Vector dimension mismatch: expected {expected}, got {actual}")]
    DimensionMismatch { expected: usize, actual: usize },

    /// Operation timed out
    #[error("Operation timed out after {0} seconds")]
    Timeout(u64),

    /// Internal error (should not happen)
    #[error("Internal error: {0}")]
    Internal(String),
}

/// Result type alias for OpenMemory operations
pub type Result<T> = std::result::Result<T, Error>;

impl Error {
    /// Check if the error is retryable
    pub fn is_retryable(&self) -> bool {
        matches!(
            self,
            Error::Http(_) | Error::RateLimit { .. } | Error::Timeout(_)
        )
    }

    /// Create a configuration error
    pub fn config(msg: impl Into<String>) -> Self {
        Error::Config(msg.into())
    }

    /// Create an embedding error
    pub fn embedding(msg: impl Into<String>) -> Self {
        Error::Embedding(msg.into())
    }

    /// Create a not found error
    pub fn not_found(msg: impl Into<String>) -> Self {
        Error::NotFound(msg.into())
    }

    /// Create an invalid input error
    pub fn invalid_input(msg: impl Into<String>) -> Self {
        Error::InvalidInput(msg.into())
    }

    /// Create an internal error
    pub fn internal(msg: impl Into<String>) -> Self {
        Error::Internal(msg.into())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_error_display() {
        let err = Error::config("missing API key");
        assert_eq!(err.to_string(), "Configuration error: missing API key");
    }

    #[test]
    fn test_retryable() {
        assert!(Error::RateLimit { retry_after_secs: 5 }.is_retryable());
        assert!(Error::Timeout(30).is_retryable());
        assert!(!Error::config("test").is_retryable());
        assert!(!Error::NotFound("test".into()).is_retryable());
    }

    #[test]
    fn test_dimension_mismatch() {
        let err = Error::DimensionMismatch {
            expected: 256,
            actual: 384,
        };
        assert_eq!(
            err.to_string(),
            "Vector dimension mismatch: expected 256, got 384"
        );
    }
}