fix(agents): 修复 HIL 工具审批 interrupt 被误当 ask_user_question 处理#784
fix(agents): 修复 HIL 工具审批 interrupt 被误当 ask_user_question 处理#784xiangfei258 wants to merge 6 commits into
Conversation
合并上游 68 个提交,主要包含: - CLI 上传与认证登录流程 - Agent 评估运行流式入口 + Langfuse 观测性,AgentRun 接口重构 - 文件预览/渲染组件解耦,知识库文件列表分页懒加载 - FastAPI 查询链路并发优化与限流信号量修复 - YUXI_CORS_ORIGINS、API Key/Dashboard 权限收紧 (xerrors#783) - 超大数量文件场景批量解析/入库优化 本地定制改动(logo/首页/登录页/配置)保留,自动合并无冲突。
合并上游 SubagentTransformer 字段冲突修复(fd9558c): langchain 1.3.10 的 create_agent 内置 native SubagentTransformer 注册 subagents key,与项目 YuxiSubAgentMiddleware 注册的同名 key 冲突。 上游改用 yuxi_subagents key 避冲突并保留可见性过滤。
HumanInTheLoopMiddleware 触发的工具审批 interrupt 载荷为 action_requests/review_configs(HITLRequest),与 ask_user_question 的 questions 结构不同,原有逻辑在三处按 questions 假设导致 HIL 不可用: 1. check_and_handle_interrupts 无 questions 时塞默认空问题 「请选择一个选项」,前端收到空弹窗。现按 payload 是否含 action_requests 分流,HIL 中断发 human_approval_required 并携带 action_requests/review_configs,ask_user_question 保持原有行为。 2. _compact_stream_chunk 的 verbose=false 精简白名单漏掉 action_requests/review_configs,前端拿不到审批载荷。白名单补入 这两个字段。 3. run_worker 的 interrupt 摘要只取 questions,HIL 摘要为空。 _interrupt_summary 兼容两类载荷,HIL 摘要改为 「操作需要确认: 工具名(参数)」。 补充单元测试覆盖 payload 分流、compact 字段保留与摘要生成。
前端按 interrupt 类型分流:
- human_approval_required 渲染新的 HumanToolApprovalModal,
展示待审批工具名与参数,提供确认执行/编辑参数/拒绝三种决策,
提交 { decisions: [{ type: "approve" | "reject" | "edit", ... }] }
与后端 Command(resume=...) 恢复语义一致
- ask_user_question_required 仍走原有选项式弹窗,行为不变
useApproval 与 useAgentRunStream 的 hasPendingInterruptForRun
兼容 actionRequests(HIL 中断无 questions),避免弹窗一闪而过。
将 extractPendingInterrupt 抽到 approvalInterrupt.js 纯函数文件,
便于纯 node 单测。补充前端分流单测。
There was a problem hiding this comment.
Code Review
This pull request introduces support for LangChain's HumanInTheLoopMiddleware tool approval interrupts, distinguishing them from standard user questions across both the backend and frontend. It also adds Docker configurations for the MinerU GPU service, updates branding to '楚天智航', and removes GitHub star/link integrations. Feedback on the backend implementation suggests using or operators in chat_service.py to correctly handle None values when formatting tool descriptions, and using json.dumps in run_worker.py to format complex tool arguments as standard JSON in the interrupt summary.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| action["description"] = "操作需要确认\n\nTool: {name}\nArgs: {args}".format( | ||
| name=action.get("name", ""), | ||
| args=action.get("args", {}), | ||
| ) |
There was a problem hiding this comment.
如果 action 字典中存在 "name" 或 "args" 键但其值为 None,action.get("name", "") 和 action.get("args", {}) 仍会返回 None(因为 get 的默认值仅在键不存在时生效)。这会导致格式化后的描述中显示 Tool: None 或 Args: None。\n\n建议使用 or 运算符来确保在值为 None 时也能正确回退到默认值:
action["description"] = "操作需要确认\\n\\nTool: {name}\\nArgs: {args}".format(\n name=action.get("name") or "",\n args=action.get("args") or {},\n )| if args: | ||
| return f"操作需要确认: {name}({args})" | ||
| return f"操作需要确认: {name}" | ||
|
|
There was a problem hiding this comment.
当 args 是字典或列表等复杂对象时,直接使用 f-string 格式化 {args} 会输出 Python 特有的字符串表示形式(例如使用单引号 {'path': '/x'},布尔值首字母大写 True 等)。\n\n为了使输出的摘要更符合标准的 JSON 格式且更具可读性,建议使用 json.dumps 进行序列化:
if name:\n if args:\n try:\n args_str = json.dumps(args, ensure_ascii=False)\n except Exception:\n args_str = str(args)\n return f"操作需要确认: {name}({args_str})"\n return f"操作需要确认: {name}"|
提交有误 |
变更描述
修复 LangChain
HumanInTheLoopMiddleware(HIL)工具审批 interrupt 在前后端多处被按ask_user_question误处理的问题,使 HIL 工具审批端到端可用。HIL 触发的 interrupt 载荷为
action_requests/review_configs结构(HITLRequest),与 ask_user_question 的questions结构不同。原有逻辑在三处按questions假设,导致 HIL 不可用:check_and_handle_interrupts:无questions时塞默认空问题「请选择一个选项」,前端收到空弹窗。现按 payload 是否含action_requests分流,HIL 中断发human_approval_required并携带action_requests/review_configs,ask_user_question 保持原有行为。_compact_stream_chunk:verbose=false 精简白名单漏掉action_requests/review_configs,前端拿不到审批载荷。白名单补入这两个字段。hasPendingInterruptForRun:只认questions,HIL 中断被判为非 interrupt,弹窗一闪而过。兼容actionRequests。run_worker摘要:只取questions,HIL 摘要为空。_interrupt_summary兼容两类载荷,HIL 摘要改为「操作需要确认: 工具名(参数)」。前端新增
HumanToolApprovalModal:HIL 中断渲染待审批工具名与参数,提供「确认执行/编辑参数/拒绝」三种决策,提交{ decisions: [{ type: "approve" | "reject" | "edit", ... }] },与 LangGraphCommand(resume=...)恢复语义一致。ask_user_question 中断仍走原有选项式弹窗,行为不变。变更类型
测试
测试结果
make format/make lint通过说明
fd9558cf修复,本分支已 merge 同步