ForcePilot/backend/package/yuxi/channel/errors.py
Kris a48f7ebf2a feat(channel): 新增通道基础模块与UI schema定义
本次提交新增了通道模块的完整基础实现:
1.  搭建了channel包的顶层导出结构,整合所有核心子模块接口
2.  实现了错误处理工具类与重试退避逻辑
3.  新增UI表单/页面/字段的schema定义与自动生成工具
4.  完成上下文管理模块,支持会话上下文、可见性过滤与运行时状态注册
5.  实现通道能力配置类,支持流式传输、功能开关等多维度能力定义
2026-05-21 10:35:30 +08:00

85 lines
2.4 KiB
Python

from __future__ import annotations
import logging
from typing import Any
from yuxi.channel.protocols import ClassifiedError, ErrorSeverity, ErrorHandlingProtocol
logger = logging.getLogger(__name__)
def capture_error(
logger_instance: logging.Logger,
error: BaseException,
*,
message: str = "",
context: dict[str, Any] | None = None,
level: str = "error",
) -> ClassifiedError:
if level == "warning":
logger_instance.warning(
"%s: %s | context=%s",
message or "Operation failed",
error,
context or {},
exc_info=True,
)
else:
logger_instance.exception(message or "Operation failed")
return ClassifiedError(
severity=_infer_severity(error),
original_error=error,
error_message=str(error),
)
def classify_error(error: BaseException) -> ClassifiedError:
return ClassifiedError(
severity=_infer_severity(error),
original_error=error,
error_message=str(error),
)
def is_retryable(error: BaseException) -> bool:
return _infer_severity(error) == ErrorSeverity.RETRYABLE
def should_backoff(error: BaseException, attempt: int) -> int:
if not is_retryable(error):
return 0
base_ms = 1000
max_ms = 30000
delay_ms = min(base_ms * (2 ** (attempt - 1)), max_ms)
return delay_ms
def _infer_severity(error: BaseException) -> ErrorSeverity:
import asyncio
import builtins
if isinstance(error, asyncio.TimeoutError):
return ErrorSeverity.NETWORK
if isinstance(error, builtins.TimeoutError):
return ErrorSeverity.NETWORK
if isinstance(error, ConnectionError):
return ErrorSeverity.NETWORK
if isinstance(error, PermissionError):
return ErrorSeverity.FORBIDDEN
if isinstance(error, (ValueError, TypeError, KeyError, IndexError, AttributeError)):
return ErrorSeverity.FATAL
if isinstance(error, asyncio.CancelledError):
return ErrorSeverity.FATAL
return ErrorSeverity.RETRYABLE
class DefaultErrorHandler(ErrorHandlingProtocol):
def classify_error(self, error: BaseException) -> ClassifiedError:
return classify_error(error)
def is_retryable(self, error: BaseException) -> bool:
return is_retryable(error)
def should_backoff(self, error: BaseException, attempt: int) -> int:
return should_backoff(error, attempt)