61 lines
2.4 KiB
Python
61 lines
2.4 KiB
Python
"""Typed Exception Hierarchy for Hermes Multi-Provider Router.
|
|
|
|
Ensures strict distinction between successful responses and provider errors,
|
|
enabling deterministic failover, health tracking, and error taxonomy.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from typing import Optional
|
|
|
|
|
|
class RouterError(Exception):
|
|
"""Base exception for all router errors."""
|
|
def __init__(self, message: str, provider: Optional[str] = None, profile_id: Optional[str] = None):
|
|
super().__init__(message)
|
|
self.message = message
|
|
self.provider = provider
|
|
self.profile_id = profile_id
|
|
|
|
|
|
class QuotaExceededError(RouterError):
|
|
"""Raised when provider returns HTTP 429 Resource Exhausted / Quota Limit."""
|
|
def __init__(self, message: str = "Quota limit exhausted", reset_in_sec: Optional[int] = None, **kwargs):
|
|
super().__init__(message, **kwargs)
|
|
self.reset_in_sec = reset_in_sec
|
|
|
|
|
|
class RateLimitedError(RouterError):
|
|
"""Raised when provider returns HTTP 429 Requests Per Minute (RPM) limit."""
|
|
def __init__(self, message: str = "Rate limit reached", **kwargs):
|
|
super().__init__(message, **kwargs)
|
|
|
|
|
|
class AuthRequiredError(RouterError):
|
|
"""Raised when profile credentials are missing or unconfigured."""
|
|
def __init__(self, message: str = "Profile credentials required", **kwargs):
|
|
super().__init__(message, **kwargs)
|
|
|
|
|
|
class AuthExpiredError(RouterError):
|
|
"""Raised when OAuth token or API key is invalid / expired (HTTP 401 / 403)."""
|
|
def __init__(self, message: str = "Authentication token expired or invalid", **kwargs):
|
|
super().__init__(message, **kwargs)
|
|
|
|
|
|
class ProviderUnavailableError(RouterError):
|
|
"""Raised when provider returns 5xx, network connection error, or timeout."""
|
|
def __init__(self, message: str = "Provider service unavailable", status_code: Optional[int] = None, **kwargs):
|
|
super().__init__(message, **kwargs)
|
|
self.status_code = status_code
|
|
|
|
|
|
class TimeoutError(ProviderUnavailableError):
|
|
"""Raised when inference request times out."""
|
|
def __init__(self, message: str = "Inference request timed out", **kwargs):
|
|
super().__init__(message, **kwargs)
|
|
|
|
|
|
class InvalidRequestError(RouterError):
|
|
"""Raised when request payload is malformed (HTTP 400)."""
|
|
def __init__(self, message: str = "Invalid request payload", **kwargs):
|
|
super().__init__(message, **kwargs)
|