2026-09-09 21:55:37 +08:00
|
|
|
class AgentError(Exception):
|
|
|
|
|
"""Base error with a stable public code."""
|
|
|
|
|
|
2026-09-11 09:47:40 +08:00
|
|
|
code = "AGENT_INTERNAL_ERROR"
|
2026-09-09 21:55:37 +08:00
|
|
|
status_code = 500
|
2026-09-11 09:47:40 +08:00
|
|
|
retryable: bool | None = False
|
2026-09-09 21:55:37 +08:00
|
|
|
|
|
|
|
|
def __init__(self, message: str) -> None:
|
|
|
|
|
super().__init__(message)
|
|
|
|
|
self.message = message
|
2026-09-11 09:47:40 +08:00
|
|
|
declared = type(self).retryable
|
|
|
|
|
self.retryable = self.status_code >= 500 if declared is None else declared
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def is_retryable(self) -> bool:
|
|
|
|
|
return bool(self.retryable)
|
2026-09-09 21:55:37 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class ValidationAgentError(AgentError):
|
2026-09-11 09:47:40 +08:00
|
|
|
code = "AGENT_INPUT_INVALID"
|
|
|
|
|
status_code = 422
|
2026-09-09 21:55:37 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class UnauthorizedAgentError(AgentError):
|
2026-09-11 09:47:40 +08:00
|
|
|
code = "AUTHENTICATION_REQUIRED"
|
2026-09-09 21:55:37 +08:00
|
|
|
status_code = 401
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class AgentTypeNotFoundError(ValidationAgentError):
|
|
|
|
|
code = "AGENT_TYPE_NOT_FOUND"
|
|
|
|
|
status_code = 404
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ForbiddenAgentError(AgentError):
|
2026-09-11 09:47:40 +08:00
|
|
|
code = "AGENT_PERMISSION_DENIED"
|
2026-09-09 21:55:37 +08:00
|
|
|
status_code = 403
|
|
|
|
|
|
|
|
|
|
|
2026-09-11 09:47:40 +08:00
|
|
|
class OnboardingRequiredError(ForbiddenAgentError):
|
|
|
|
|
code = "ONBOARDING_REQUIRED"
|
|
|
|
|
|
|
|
|
|
|
2026-09-09 21:55:37 +08:00
|
|
|
class ConflictAgentError(AgentError):
|
2026-09-11 09:47:40 +08:00
|
|
|
code = "RUN_NOT_CANCELLABLE"
|
2026-09-09 21:55:37 +08:00
|
|
|
status_code = 409
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class IdempotencyConflictError(ConflictAgentError):
|
|
|
|
|
code = "IDEMPOTENCY_CONFLICT"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class RecoverableAgentError(AgentError):
|
2026-09-11 09:47:40 +08:00
|
|
|
code = "DEPENDENCY_UNAVAILABLE"
|
2026-09-09 21:55:37 +08:00
|
|
|
status_code = 503
|
2026-09-11 09:47:40 +08:00
|
|
|
retryable = True
|
2026-09-09 21:55:37 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class RunLeaseLostError(ConflictAgentError):
|
2026-09-11 09:47:40 +08:00
|
|
|
code = "RUN_NOT_CANCELLABLE"
|
2026-09-09 21:55:37 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class ResourceNotFoundError(AgentError):
|
2026-09-11 09:47:40 +08:00
|
|
|
code = "SESSION_NOT_FOUND"
|
2026-09-09 21:55:37 +08:00
|
|
|
status_code = 404
|
2026-09-11 09:47:40 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class RunNotFoundError(ResourceNotFoundError):
|
|
|
|
|
code = "RUN_NOT_FOUND"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class InvalidCursorError(AgentError):
|
|
|
|
|
code = "INVALID_CURSOR"
|
|
|
|
|
status_code = 400
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class RateLimitedError(AgentError):
|
|
|
|
|
code = "RATE_LIMITED"
|
|
|
|
|
status_code = 429
|
|
|
|
|
retryable = True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SseNotAcceptableError(AgentError):
|
|
|
|
|
code = "SSE_NOT_ACCEPTABLE"
|
|
|
|
|
status_code = 406
|