feat: publish workphone SDK deployment and API docs
This commit is contained in:
166
sdk/agent/error_handler.py
Normal file
166
sdk/agent/error_handler.py
Normal file
@@ -0,0 +1,166 @@
|
||||
"""
|
||||
错误处理和重试机制
|
||||
"""
|
||||
|
||||
import logging
|
||||
import time
|
||||
from typing import Callable, Any, Dict, Optional
|
||||
from functools import wraps
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def retry(max_retries: int = 3, delay: float = 1.0, backoff: float = 2.0,
|
||||
exceptions: tuple = (Exception,)):
|
||||
"""
|
||||
重试装饰器
|
||||
|
||||
Args:
|
||||
max_retries: 最大重试次数
|
||||
delay: 初始延迟(秒)
|
||||
backoff: 退避倍数
|
||||
exceptions: 需要重试的异常类型
|
||||
"""
|
||||
def decorator(func: Callable) -> Callable:
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
current_delay = delay
|
||||
last_exception = None
|
||||
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
except exceptions as e:
|
||||
last_exception = e
|
||||
if attempt < max_retries - 1:
|
||||
logger.warning(
|
||||
f"{func.__name__} 失败 (尝试 {attempt + 1}/{max_retries}): {e}, "
|
||||
f"{current_delay}秒后重试"
|
||||
)
|
||||
time.sleep(current_delay)
|
||||
current_delay *= backoff
|
||||
else:
|
||||
logger.error(f"{func.__name__} 最终失败: {e}")
|
||||
|
||||
# 所有重试都失败,抛出最后一个异常
|
||||
raise last_exception
|
||||
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
|
||||
class ErrorHandler:
|
||||
"""错误处理器"""
|
||||
|
||||
@staticmethod
|
||||
def handle_ui_error(error: Exception, context: str = "") -> Dict[str, Any]:
|
||||
"""
|
||||
处理UI操作错误
|
||||
|
||||
Args:
|
||||
error: 异常对象
|
||||
context: 上下文信息
|
||||
|
||||
Returns:
|
||||
错误信息字典
|
||||
"""
|
||||
error_msg = str(error)
|
||||
|
||||
# 常见错误分类
|
||||
if "timeout" in error_msg.lower() or "等待" in error_msg:
|
||||
return {
|
||||
"success": False,
|
||||
"error": "操作超时",
|
||||
"type": "timeout",
|
||||
"context": context,
|
||||
"suggestion": "检查元素是否存在或增加等待时间"
|
||||
}
|
||||
elif "not found" in error_msg.lower() or "未找到" in error_msg:
|
||||
return {
|
||||
"success": False,
|
||||
"error": "元素未找到",
|
||||
"type": "element_not_found",
|
||||
"context": context,
|
||||
"suggestion": "检查选择器或使用AI Agent模式"
|
||||
}
|
||||
elif "permission" in error_msg.lower() or "权限" in error_msg:
|
||||
return {
|
||||
"success": False,
|
||||
"error": "权限不足",
|
||||
"type": "permission_denied",
|
||||
"context": context,
|
||||
"suggestion": "检查ADB权限或Root权限"
|
||||
}
|
||||
else:
|
||||
return {
|
||||
"success": False,
|
||||
"error": error_msg,
|
||||
"type": "unknown",
|
||||
"context": context,
|
||||
"suggestion": "查看日志获取详细信息"
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def should_retry(error: Exception) -> bool:
|
||||
"""
|
||||
判断是否应该重试
|
||||
|
||||
Args:
|
||||
error: 异常对象
|
||||
|
||||
Returns:
|
||||
是否应该重试
|
||||
"""
|
||||
error_msg = str(error).lower()
|
||||
|
||||
# 这些错误可以重试
|
||||
retryable_errors = [
|
||||
"timeout",
|
||||
"等待",
|
||||
"network",
|
||||
"连接",
|
||||
"temporary",
|
||||
"临时"
|
||||
]
|
||||
|
||||
# 这些错误不应该重试
|
||||
non_retryable_errors = [
|
||||
"permission",
|
||||
"权限",
|
||||
"not found",
|
||||
"未找到",
|
||||
"invalid",
|
||||
"无效"
|
||||
]
|
||||
|
||||
for retryable in retryable_errors:
|
||||
if retryable in error_msg:
|
||||
return True
|
||||
|
||||
for non_retryable in non_retryable_errors:
|
||||
if non_retryable in error_msg:
|
||||
return False
|
||||
|
||||
# 默认可以重试
|
||||
return True
|
||||
|
||||
|
||||
def with_error_handling(context: str = ""):
|
||||
"""
|
||||
错误处理装饰器
|
||||
|
||||
Args:
|
||||
context: 上下文信息
|
||||
"""
|
||||
def decorator(func: Callable) -> Callable:
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
try:
|
||||
result = func(*args, **kwargs)
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error(f"{func.__name__} 执行失败: {e}")
|
||||
return ErrorHandler.handle_ui_error(e, context or func.__name__)
|
||||
|
||||
return wrapper
|
||||
return decorator
|
||||
Reference in New Issue
Block a user