169 lines
4.4 KiB
Python
169 lines
4.4 KiB
Python
"""
|
|
Custom exceptions for the Honcho application.
|
|
"""
|
|
|
|
import json
|
|
from typing import Any, final
|
|
|
|
from src.config import settings
|
|
|
|
|
|
class HonchoException(Exception):
|
|
"""Base exception for all Honcho-specific errors."""
|
|
|
|
status_code: int = 500
|
|
detail: str = "An unexpected error occurred"
|
|
|
|
def __init__(self, detail: str | None = None, status_code: int | None = None):
|
|
self.detail = detail or self.detail
|
|
self.status_code = status_code or self.status_code
|
|
super().__init__(self.detail)
|
|
|
|
|
|
@final
|
|
class ResourceNotFoundException(HonchoException):
|
|
"""Exception raised when a requested resource is not found."""
|
|
|
|
status_code = 404
|
|
detail = "Resource not found"
|
|
|
|
|
|
@final
|
|
class ObserverException(HonchoException):
|
|
"""Exception raised when a request tries to add too many observers to a session"""
|
|
|
|
status_code = 400
|
|
|
|
def __init__(self, session_name: str, extra_count: int):
|
|
self.detail = (
|
|
f"Cannot create session {session_name} with {extra_count} observers. "
|
|
+ f"Maximum allowed is {settings.SESSION_OBSERVERS_LIMIT} observers per session. "
|
|
+ "Observers are peers with 'observe_others' set to true."
|
|
)
|
|
super().__init__(self.detail)
|
|
|
|
|
|
@final
|
|
class ValidationException(HonchoException):
|
|
"""Exception raised when validation fails."""
|
|
|
|
status_code = 422
|
|
detail = "Validation error"
|
|
|
|
|
|
@final
|
|
class ConflictException(HonchoException):
|
|
"""Exception raised when there's a resource conflict."""
|
|
|
|
status_code = 409
|
|
detail = "Resource conflict"
|
|
|
|
|
|
@final
|
|
class AuthenticationException(HonchoException):
|
|
"""Exception raised when authentication fails."""
|
|
|
|
status_code = 401
|
|
detail = "Authentication failed"
|
|
|
|
|
|
@final
|
|
class AuthorizationException(HonchoException):
|
|
"""Exception raised when authorization fails."""
|
|
|
|
status_code = 403
|
|
detail = "Not authorized to access this resource"
|
|
|
|
|
|
@final
|
|
class DisabledException(HonchoException):
|
|
"""Exception raised when a feature is disabled."""
|
|
|
|
status_code = 405
|
|
detail = "Feature is disabled"
|
|
|
|
|
|
@final
|
|
class FilterError(HonchoException):
|
|
"""Exception raised when a filter is misconfigured or invalid."""
|
|
|
|
status_code = 422
|
|
detail = "Invalid filter configuration"
|
|
|
|
|
|
@final
|
|
class UnsupportedFileTypeError(HonchoException):
|
|
status_code = 415
|
|
detail = "Unsupported file type"
|
|
|
|
|
|
@final
|
|
class FileTooLargeError(HonchoException):
|
|
status_code = 413
|
|
detail = "File too large"
|
|
|
|
|
|
@final
|
|
class FileProcessingError(HonchoException):
|
|
status_code = 500
|
|
detail = "File processing error"
|
|
|
|
|
|
@final
|
|
class SurprisalError(HonchoException):
|
|
"""Exception raised when surprisal sampling fails during a dream cycle."""
|
|
|
|
status_code = 500
|
|
detail = "Surprisal sampling failed"
|
|
|
|
|
|
@final
|
|
class SpecialistExecutionError(HonchoException):
|
|
"""Exception raised when a specialist fails during dream orchestration."""
|
|
|
|
status_code = 500
|
|
detail = "Specialist execution failed"
|
|
|
|
|
|
@final
|
|
class VectorStoreError(HonchoException):
|
|
"""Exception raised when a vector store operation fails."""
|
|
|
|
status_code = 500
|
|
detail = "Vector store operation failed"
|
|
|
|
|
|
class LLMError(Exception):
|
|
"""Exception raised when an LLM call fails.
|
|
|
|
Accepts arbitrary positional and keyword inputs, normalizes them into a
|
|
JSON-serializable object, and uses the resulting JSON string as the
|
|
exception message. The normalized object is available via ``to_dict()``
|
|
and the ``data`` attribute.
|
|
|
|
Positional and keyword inputs are represented as a JSON object. If a
|
|
single positional argument is a mapping and there are no keyword
|
|
arguments, that mapping is used as the root object; otherwise the shape is
|
|
``{"args": [...], "kwargs": {...}}``. Values that are not natively
|
|
serializable are converted using ``repr``.
|
|
"""
|
|
|
|
data: dict[str, Any]
|
|
|
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
normalized = {"args": list(args), "kwargs": kwargs}
|
|
message = json.dumps(
|
|
normalized, default=self._json_fallback, ensure_ascii=False
|
|
)
|
|
self.data = normalized
|
|
super().__init__(message)
|
|
|
|
@staticmethod
|
|
def _json_fallback(value: Any) -> str:
|
|
"""Fallback serializer that returns ``repr(value)`` for unsupported types."""
|
|
return repr(value)
|
|
|
|
def to_dict(self) -> dict[str, Any]:
|
|
"""Return the normalized JSON object for programmatic access."""
|
|
return self.data
|