Files
AstrBot/src-new/astrbot_sdk/errors.py

120 lines
3.2 KiB
Python

"""跨运行时边界传递的统一错误模型。"""
from __future__ import annotations
from dataclasses import dataclass
class ErrorCodes:
"""AstrBot v4 的稳定错误码常量。"""
UNKNOWN_ERROR = "unknown_error"
# retryable = False
LLM_NOT_CONFIGURED = "llm_not_configured"
CAPABILITY_NOT_FOUND = "capability_not_found"
PERMISSION_DENIED = "permission_denied"
LLM_ERROR = "llm_error"
INVALID_INPUT = "invalid_input"
CANCELLED = "cancelled"
PROTOCOL_VERSION_MISMATCH = "protocol_version_mismatch"
PROTOCOL_ERROR = "protocol_error"
INTERNAL_ERROR = "internal_error"
# retryable = True
CAPABILITY_TIMEOUT = "capability_timeout"
NETWORK_ERROR = "network_error"
LLM_TEMPORARY_ERROR = "llm_temporary_error"
@dataclass(slots=True)
class AstrBotError(Exception):
code: str
message: str
hint: str = ""
retryable: bool = False
def __str__(self) -> str:
return self.message
@classmethod
def cancelled(cls, message: str = "调用被取消") -> "AstrBotError":
return cls(
code=ErrorCodes.CANCELLED,
message=message,
hint="",
retryable=False,
)
@classmethod
def capability_not_found(cls, name: str) -> "AstrBotError":
return cls(
code=ErrorCodes.CAPABILITY_NOT_FOUND,
message=f"未找到能力:{name}",
hint="请确认 AstrBot Core 是否已注册该 capability",
retryable=False,
)
@classmethod
def invalid_input(
cls,
message: str,
*,
hint: str = "请检查调用参数",
) -> "AstrBotError":
return cls(
code=ErrorCodes.INVALID_INPUT,
message=message,
hint=hint,
retryable=False,
)
@classmethod
def protocol_version_mismatch(cls, message: str) -> "AstrBotError":
return cls(
code=ErrorCodes.PROTOCOL_VERSION_MISMATCH,
message=message,
hint="请升级 astrbot_sdk 至最新版本",
retryable=False,
)
@classmethod
def protocol_error(cls, message: str) -> "AstrBotError":
return cls(
code=ErrorCodes.PROTOCOL_ERROR,
message=message,
hint="请检查通信双方的协议实现",
retryable=False,
)
@classmethod
def internal_error(
cls,
message: str,
*,
hint: str = "请联系插件作者",
) -> "AstrBotError":
return cls(
code=ErrorCodes.INTERNAL_ERROR,
message=message,
hint=hint,
retryable=False,
)
def to_payload(self) -> dict[str, object]:
return {
"code": self.code,
"message": self.message,
"hint": self.hint,
"retryable": self.retryable,
}
@classmethod
def from_payload(cls, payload: dict[str, object]) -> "AstrBotError":
return cls(
code=str(payload.get("code", ErrorCodes.UNKNOWN_ERROR)),
message=str(payload.get("message", "未知错误")),
hint=str(payload.get("hint", "")),
retryable=bool(payload.get("retryable", False)),
)