✨ feat(sidecar): 防护性终止独立 repeat_guard reason 与恢复上下文 - #466
Conversation
repeat guard 硬停(SDK error_completion_guard + errorCode repeated_tool_call) 此前被 run-loop 归入泛化 errored → 对外 failed,下条消息拿不到任何 runtime-recovery-state。 - run-loop 将其映射为带标记的 turn_limited(terminationReason: repeat_guard), 不新增状态枚举,其余状态消费者零波及;宿主自有 completionGuard stop (无 errorCode)保持 errored 不变 - recordTurnLimited 落盘 item 携带 terminationReason 标记 - hasTurnLimitedMarker 语义不变;新增 isRepeatGuardLimitedItem 区分, 恢复上下文按标记分流:<runtime-recovery-state reason="repeat_guard"> 文案说明因重复操作被保护机制停止并建议调整指令(风格对齐 turn_limit) - onComplete reason 扩为 max_turns | repeat_guard 并透传 - web 端 #390 固定提示与 turn_limit 提示本就分事件/分文案呈现,无需改动 Fixes #392
Review结论:Approve(可合,无阻塞项)。核心映射、传播链、恢复分流逐条实证正确;以下三条 P3 均不阻塞。 发现[P3] PR 描述对区分机制的表述与实现不符 描述称「宿主自有 completionGuard stop(无 errorCode)保持 errored」。实际现网唯一的宿主 stop 来源 [P3] 第二个 commit(f2e9ac11b)与本主题无关且 PR body 零提及 「Retry-After 解析收敛至 SDK 导出」(packages/sdk/src/index.ts 三符号导出 + pi-ai-provider.ts 去重 -6 行):已核实三个符号在 main 的 [P3] web 对两类 guard stop 仍不可区分(既有局限,非本 PR 引入) lifecycle-projector 的 run.end detail 只含 stopReason/isError/numTurns/usage/cost,不透传 errorCode/errors[]。web adapter 对一切 另注一处测试缺口(不计级):生产端(run-loop)与消费端(agent-service)分别钉死,但缺 items.jsonl 落盘→读回的序列化往返用例;两端各自覆盖下实际风险很低。 已核实
|
3959b42 to
8f6c9a6
Compare
与 PR 描述对齐:宿主 completionGuard stop 同样带结构化 errorCode(verification_inconclusive / verification_failed_after_repair 等),与 repeat guard 的区分机制是取值不同而非有无字段。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
背景
repeat guard 硬停经 SDK 的
error_completion_guardsubtype 收场(errorCode: 'repeated_tool_call')。此前 sidecar run-loop 把它归入泛化status: 'errored'→ 对外failed,导致:hasTurnLimitedMarker只认error_max_turns)状态机改动:带标记的 turn_limited(非新枚举)
选了**「带标记的 turn_limited」**而非新增状态枚举:新增一个状态会波及所有状态消费者(LumeRunStatus、fromAgentRuntimeRunResult、事件总线、web 适配层),而 repeat guard 硬停的下游语义(进度保留、可恢复、markCompleted)与 turn_limit 完全一致,差异只在恢复文案。
error_completion_guard+errorCode === 'repeated_tool_call'→{ status: 'turn_limited', terminationReason: 'repeat_guard' }。宿主自有 completionGuard stop 保持 errored 不变——两者共用 subtype 且都带结构化 errorCode,靠取值区分(repeat guard 为repeated_tool_call,宿主 stop 为verification_inconclusive/verification_failed_after_repair等其他取值),不做英文文案匹配。terminationReason?: 'repeat_guard';fromAgentRuntimeRunResult无需改动(turn_limited → completed 路径天然覆盖带标记结果,测试钉住)。terminationReason标记;item name 保持turn_limited,hasTurnLimitedMarker 判定语义零变化。max_turns | repeat_guard并透传(im-message-router / rpc 测试 mock 同步类型)。恢复上下文与文案
isRepeatGuardLimitedItem,按落盘标记把恢复上下文分流到新的buildRepeatGuardRecoveryContext:<runtime-recovery-state reason="repeat_guard">reason="turn_limit"恢复文案。completion_guard→ run.failed + coderepeated_tool_call专属文案)与 turn_limit 提示本就分事件、分文案呈现,无需改动。测试
验证
bun run typecheck六包全绿Fixes #392
🤖 Generated with Claude Code