Repository navigation
fix: 修复skill_exec 工具调用中产物丢失的问题 (#350) - #356
Conversation
AI Code Review审查结论通过 审查范围: base 02509b2..HEAD ee29597,共 12 个文件(1 处 SDK 源码修改、1 处测试修改、10 个示例文件新增)。核心变更是将 计划符合性: 修复方向正确,变更最小且聚焦—— 主要风险: ① 测试充分性: 新测试覆盖主路径(runtime 传递、output_files/primary_output 断言、finalized 置位),但未覆盖 门禁结论: 无阻断性(SEVERE)缺陷,修复达成了预期目标,3 条均为中等/低级别可改进项,评审通过。 发现的问题中等
问题: 触发条件: 调用方以 实际影响: 返回的 修正方向: 在 中等
问题: 触发条件: 用户以 实际影响: 同一 run_tool 下 skill_run 会无条件保存产物,而 skill_exec 路径的最终 修正方向: 在 较低
问题: 新增测试 触发条件: 回归测试运行期无法发现此分支的行为变化;真实运行时 实际影响: 若未来再次引入 修正方向: 增加用例: |
| try: | ||
| files, manifest = await run_tool._prepare_outputs(ctx, exec_session.ws, fake_run_input) | ||
| files, manifest = await run_tool._prepare_outputs( | ||
| ctx, | ||
| exec_session.ws, | ||
| exec_session.workspace_runtime, | ||
| fake_run_input, | ||
| ) |
There was a problem hiding this comment.
问题: _collect_final_result 用 ExecInput 的原始 in_data.save_as_artifacts 构造 fake_run_input(第 784 行),绕过了 SkillRunTool._run_async_impl 中 _force_save_artifacts 的覆盖逻辑(_skill_run.py:664-669 会把 save_as_artifacts 强制置 True),_skill_exec.py 全文也无任何 _force_save_artifacts 引用。
触发条件: 用户以 SkillRunTool(force_save_artifacts=True) 构造 run_tool,经 create_exec_tools 或 SkillToolSet 配对的 skill_exec 调用未显式传 save_as_artifacts=true 时。
实际影响: 同一 run_tool 下 skill_run 会无条件保存产物,而 skill_exec 路径的最终 result.artifact_files 为空、不做任何保存,与构造参数声明的 "always attempt to persist collected output files via the artifact service" 契约不符;同样因本次修复让收集生效,该配置绕过才首次表现为可见缺陷。
修正方向: 在 _collect_final_result 构造 fake_run_input 时读取 run_tool._force_save_artifacts(为真时置 save_as_artifacts=True,outputs 非空时同步置 outputs.save=True),或把 _run_async_impl 中的覆盖逻辑抽成共享辅助函数供两条路径复用。
| files, manifest = await run_tool._prepare_outputs( | ||
| ctx, | ||
| exec_session.ws, | ||
| exec_session.workspace_runtime, | ||
| fake_run_input, | ||
| ) | ||
| except Exception as ex: # pylint: disable=broad-except | ||
| logger.warning("skill_exec: collect outputs failed: %s", ex) | ||
| files, manifest = [], None |
There was a problem hiding this comment.
问题: 新增测试 test_collect_final_result_passes_workspace_runtime_and_returns_files(tests/skills/tools/test_skill_exec.py:117-168)用 mock 的 _prepare_outputs 只覆盖成功路径,未覆盖 _collect_final_result 中 _prepare_outputs 抛异常后被吞掉并置空 files 的降级分支(_skill_exec.py:797-799)——该分支正是本修复前产物丢失的故障点(缺参 TypeError 在此被 except 吞掉、文件静默丢失)。
触发条件: 回归测试运行期无法发现此分支的行为变化;真实运行时 fs.collect/fs.collect_outputs 抛错时该分支无测试保障。
实际影响: 若未来再次引入 _prepare_outputs 签名或调用错误(本次修复的对象),mock 会绕过真实 fs 使测试继续通过,无法防止同类"产物静默丢失"回归;异常降级路径(返回空输出而非崩溃)与 manifest 合并分支、run_result 抛错回退 proc.log 的分支均无覆盖。
修正方向: 增加用例:run_tool._prepare_outputs 抛异常时断言 _collect_final_result 返回的 result 的 output_files 为空且 finalized=True(验证降级不阻塞轮询);并可补充 manifest 非空(_merge_manifest_artifact_refs)与 run_result 失败回退 proc.log 两个分支。
No description provided.