fix(agent): validate non-empty retry delays; pin exhaustion semantics
核心算法 #10(Agent Loop):Codex 质量审查跟进,仅加固防御与 可观测,不改变循环语义。 - __init__ 校验 step_retry_delays 非空,空序列直接抛 ValueError (P5 fail-fast,避免首次可重试异常时 IndexError 掩盖原始 LLM 异常、违背方法契约) - 补耗尽语义窄测试(耗尽后原样抛出最后一次原始异常)与空序列 构造校验测试 - run() 最终失败日志补异常类型名,便于回溯归因
This commit is contained in:
+5
-2
@@ -73,7 +73,8 @@ class AgentLoop:
|
||||
max_steps: 最大有效步数(每次成功工具调用计一步)。
|
||||
max_retries: JSON 解析连续失败的最大容忍次数。
|
||||
step_retries: LLM 瞬时异常的步级重试次数(不含首次调用)。
|
||||
step_retry_delays: 步级重试的退避秒数序列,超出部分取末值。
|
||||
step_retry_delays: 步级重试的退避秒数序列,超出部分取末值;
|
||||
不得为空(空序列构造时抛 ValueError,fail-fast)。
|
||||
retryable_exceptions: 可重试异常元组,默认 (TimeoutError, OSError)——
|
||||
ssl.SSLError/ConnectionError 均为 OSError 子类,覆盖穿透
|
||||
GovernedLLMClient 内部重试栈的瞬时异常;openai API 类异常由
|
||||
@@ -90,6 +91,8 @@ class AgentLoop:
|
||||
step_retry_delays: tuple[float, ...] = (20.0, 40.0),
|
||||
retryable_exceptions: tuple[type[BaseException], ...] = (TimeoutError, OSError),
|
||||
) -> None:
|
||||
if not step_retry_delays:
|
||||
raise ValueError("step_retry_delays 不得为空")
|
||||
self._llm = llm
|
||||
self._max_steps = max_steps
|
||||
self._max_retries = max_retries
|
||||
@@ -138,7 +141,7 @@ class AgentLoop:
|
||||
messages, token_usage, session_id=session_id
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error("LLM API 调用失败: {}", e)
|
||||
logger.error("LLM API 调用失败({}): {}", type(e).__name__, e)
|
||||
result = LoopResult(
|
||||
steps=steps,
|
||||
steps_used=step_count,
|
||||
|
||||
Reference in New Issue
Block a user