WechatOnCloud/bridge/woc_bridge/ui/errors.py
Kris 15fc62d478 feat: 完成微信UI自动化新架构全量开发与集成
- 新增六层UI自动化架构:从Backend到Capabilities的完整分层实现
- 添加WeChat 4.0分辨率适配Profile与图像模板资源
- 实现幂等缓存、熔断器、重试策略、链路追踪与监控指标
- 新增头像下载安全校验、发布朋友圈路径白名单防护
- 优化密钥缓存、DB校验逻辑与初始化流程
- 补充完整错误码体系与启动清场机制
2026-07-16 01:19:47 +08:00

121 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""UI 自动化错误码分类与异常体系。
定义可重试/不可重试错误码集合,以及 Flow 异常体系。
供 RetryPolicy.should_retry / CircuitBreaker / Flow 状态机使用。
错误码分类spec 第十节):
- RETRYABLE_CODES4 类):瞬时故障,最多重试 1 次
- NON_RETRYABLE_CODES7 类):永久故障,不重试
"""
from __future__ import annotations
from typing import Optional
# 可重试错误码瞬时故障RetryPolicy.should_retry 返回 True
RETRYABLE_CODES: frozenset[str] = frozenset({
"RATE_LIMITED", # 限流,需退避后重试
"SEND_TIMEOUT", # 发送超时,可能下次成功
"STATE_DIRTY", # UI 状态脏,重置后可重试
"X11_TEMP_UNAVAILABLE", # X11 临时不可用,重试可能恢复
})
# 不可重试错误码:永久故障,重试无意义
NON_RETRYABLE_CODES: frozenset[str] = frozenset({
"WECHAT_NOT_LOGGED_IN", # 未登录,需人工介入
"WINDOW_NOT_FOUND", # 窗口未找到,需检查微信运行
"ELEMENT_NOT_FOUND", # 元素未找到,需检查 UI 布局
"DB_VERIFY_FAILED", # DB 校验失败(防串号),需人工排查
"AMBIGUOUS_CONTACT", # 联系人歧义,需修正 display_name
"X11_UNAVAILABLE", # X11 持续不可用,需检查容器
"BRIDGE_CIRCUITED", # bridge 熔断,需等待恢复
})
def is_retryable(code: str) -> bool:
"""判断错误码是否可重试。"""
return code in RETRYABLE_CODES
class FlowError(Exception):
"""Flow 执行异常基类。
Attributes:
code: 错误码(如 WINDOW_NOT_FOUND / SEND_TIMEOUT
message: 人类可读错误信息
retryable: 是否可重试(根据 code 自动推断,可显式覆盖)
details: 额外上下文dict可选
"""
def __init__(
self,
code: str,
message: str = "",
*,
retryable: Optional[bool] = None,
details: Optional[dict] = None,
) -> None:
self.code = code
self.message = message or code
# 未显式指定时按 code 推断
self.retryable = (
retryable if retryable is not None else is_retryable(code)
)
self.details = details or {}
super().__init__(self.message)
def __repr__(self) -> str:
return (
f"FlowError(code={self.code!r}, retryable={self.retryable}, "
f"message={self.message!r})"
)
class TransientError(FlowError):
"""瞬时错误(可重试)。
用于 RETRYABLE_CODES 中的错误码,或显式指定 retryable=True。
"""
def __init__(
self,
code: str,
message: str = "",
*,
details: Optional[dict] = None,
) -> None:
super().__init__(code, message, retryable=True, details=details)
class PermanentError(FlowError):
"""永久错误(不可重试)。
用于 NON_RETRYABLE_CODES 中的错误码,或显式指定 retryable=False。
"""
def __init__(
self,
code: str,
message: str = "",
*,
details: Optional[dict] = None,
) -> None:
super().__init__(code, message, retryable=False, details=details)
class ElementNotFoundError(FlowError):
"""元素未找到(图像匹配失败且 require_image=True或几何规格缺失
默认 code=ELEMENT_NOT_FOUNDretryable=False。
"""
def __init__(
self,
message: str = "",
*,
code: str = "ELEMENT_NOT_FOUND",
details: Optional[dict] = None,
) -> None:
super().__init__(code, message, retryable=False, details=details)