"""统一收尾能力不足、资源缺失和动作修正失败 这里只整理内部失败原因,面向用户的说明由回答节点交给模型总结,代码中不写死给用户的文案 """ from app.processor.base import BaseNode from app.processor.state import QueryState def failure_notice(state: QueryState) -> str: """汇总上游记录的失败原因、最近一次修正分析和校验错误,作为交给模型的事实说明""" facts = [] if reason := state.get("failure_reason"): facts.append(reason) plan = state.get("repair_plan") if plan is not None and plan.reason not in facts: facts.append(f"失败分析:{plan.reason}") if errors := state.get("validation_errors"): facts.append("校验错误:" + ";".join(error.message for error in errors)) facts.append(f"已自动修正 {state.get('retry_count', 0)} 次") detail = "\n".join(facts) if facts else "没有记录具体原因" return f"本次修改请求没有执行,内部原因如下:\n{detail}" class FallbackNode(BaseNode): name = "fallback_node" def process(self, state: QueryState) -> QueryState: # 浅拷贝状态 updated_state: QueryState = state.copy() notice = failure_notice(state) self.logger.warning(notice) # 将任务标记为最终失败,由回答节点向用户说明原因 updated_state["status"] = "failed" updated_state["failure_reason"] = notice updated_state["notice"] = notice # 显式标记校验未通过,防止残留动作被当作可执行结果 updated_state["validation_passed"] = False # 清空旧模拟快照,避免失败结果中仍携带之前的成功快照 updated_state["simulated_screen"] = None # 返回统一的失败状态,保留原动作和错误信息供排查 return updated_state