Spaces:
Sleeping
Sleeping
Upgrade ClearCast: Docker Space with Node.js gateway, FastAPI orchestrator, validated plans (GitHub 84b0cf9)
79c4c46 verified Download agent/errors.py from abhinavvathadi/ClearCast-AI: direct link, hf CLI and curl.
- Browser
- Download file 3.48 kB
-
https://huggingface.co/spaces/abhinavvathadi/ClearCast-AI/resolve/main/agent/errors.py
- Command line
-
hf download hf://spaces/abhinavvathadi/ClearCast-AI/agent/errors.py
-
curl -L -o errors.py https://huggingface.co/spaces/abhinavvathadi/ClearCast-AI/resolve/main/agent/errors.py
3.48 kB
| """Error taxonomy shared by the agent service, the internal API, and the UI. | |
| Every error carries a stable ``code``, an HTTP status for the internal API, and | |
| a message that is safe to show to users (no keys, URLs, or prompt content). | |
| """ | |
| from __future__ import annotations | |
| import asyncio | |
| import httpx | |
| class ClearCastError(Exception): | |
| """Base error with a stable code and a client-safe message.""" | |
| code = "internal_error" | |
| http_status = 500 | |
| retryable = False | |
| def __init__( | |
| self, | |
| message: str, | |
| *, | |
| code: str | None = None, | |
| http_status: int | None = None, | |
| retryable: bool | None = None, | |
| ) -> None: | |
| super().__init__(message) | |
| self.message = message | |
| if code is not None: | |
| self.code = code | |
| if http_status is not None: | |
| self.http_status = http_status | |
| if retryable is not None: | |
| self.retryable = retryable | |
| class ServiceUnavailableError(ClearCastError): | |
| code = "service_unavailable" | |
| http_status = 503 | |
| retryable = True | |
| class ConfigurationError(ServiceUnavailableError): | |
| code = "configuration_missing" | |
| retryable = False | |
| class ToolServiceUnavailableError(ServiceUnavailableError): | |
| """The MCP weather tool subprocess could not be started or reached.""" | |
| code = "tool_service_unavailable" | |
| class ModelProviderError(ClearCastError): | |
| code = "model_provider_error" | |
| http_status = 502 | |
| class SessionBusyError(ClearCastError): | |
| code = "session_busy" | |
| http_status = 429 | |
| retryable = True | |
| class PlanNotFoundError(ClearCastError): | |
| code = "plan_not_found" | |
| http_status = 404 | |
| class ReviewConflictError(ClearCastError): | |
| code = "review_conflict" | |
| http_status = 409 | |
| def classify_model_exception(exc: BaseException) -> ModelProviderError | None: | |
| """Map OpenAI/httpx/timeout failures to a categorised, client-safe error.""" | |
| import openai | |
| if isinstance(exc, openai.APITimeoutError | httpx.TimeoutException | asyncio.TimeoutError): | |
| return ModelProviderError( | |
| "The language model did not respond in time.", | |
| code="model_timeout", | |
| http_status=504, | |
| retryable=True, | |
| ) | |
| if isinstance(exc, openai.RateLimitError): | |
| return ModelProviderError( | |
| "The language model provider is rate limiting requests.", | |
| code="model_rate_limited", | |
| http_status=503, | |
| retryable=True, | |
| ) | |
| if isinstance(exc, openai.AuthenticationError | openai.PermissionDeniedError): | |
| return ModelProviderError( | |
| "The language model provider rejected the configured credentials.", | |
| code="model_auth_error", | |
| ) | |
| if isinstance(exc, openai.APIConnectionError): | |
| return ModelProviderError( | |
| "The language model provider could not be reached.", | |
| code="model_unavailable", | |
| retryable=True, | |
| ) | |
| if isinstance(exc, openai.BadRequestError): | |
| return ModelProviderError("The language model provider rejected the request.", code="model_bad_request") | |
| if isinstance(exc, openai.APIStatusError): | |
| return ModelProviderError( | |
| f"The language model provider returned an error (HTTP {exc.status_code}).", | |
| retryable=exc.status_code >= 500, | |
| ) | |
| return None | |