Pull Request已成功合入, 合并人@CANN-robot
(感谢 高煜博 的贡献)变更摘要
此 PR 重写了 .opencode/plugins/install-default-skills.ts 中默认 skills 的安装逻辑,用 Node.js 原生 API(fs/path/os/child_process)替代原有的 bash 脚本调用,移除了对 Unix 环境的硬依赖,使插件在 Linux 与 Windows 上均能自动完成四个默认 skill(gitcode-pr、gitcode-issue、api-doc-generator、gitcode-pipeline)的安装。
主要改动
- 移除 bash 环境检测与脚本调用:删除了
hasBash检测逻辑(原通过bash --version判断)及bash ${scriptPath}调用,消除 Windows 上因缺少 bash 导致的安装短路。 - 新增
cloneSkillsRepo函数:使用execFileSync调用git clone --depth 1从REPO_URL浅克隆 skills 仓库,并设 20 秒超时,替代原 shell 脚本中的网络拉取逻辑。 - 新增
createSkillLink跨平台符号链接函数:在 Linux 上使用path.relative计算相对路径后调用fs.symlinkSync,在 Windows(win32)上使用junction选项创建目录链接,解决原ln -sfn在 Windows 下的权限问题。 - 新增
installSkillsToRemote核心安装函数:在临时目录中克隆仓库 → 将各 skill 目录复制到_remote/→ 创建一级目录链接 → 调用ensureGitignore维护.gitignore条目,完成后清理临时目录。 - 新增
ensureGitignore函数:自动读取根目录.gitignore,对每个默认 skill 检查是否存在.claude/skills/<skill>条目,缺失则追加。 - 错误处理兼容 Windows:将捕获的错误断言为
Error & { stderr?: Buffer },对stderr做toString()转换后再写入日志,兼容 Windows 上execFileSync返回 Buffer 类型的情况。


代码审查
审查总结
我对 .opencode/plugins/install-default-skills.ts 的变更进行了全面审查,共发现 3 个问题:
| 优先级 | 数量 | 说明 |
|---|---|---|
| P1 | 1 | Windows junction 创建时 targetPath 可能为相对路径,导致 fs.symlinkSync 抛出异常,Windows 上默认 skills 安装失败——正是本 PR 要修复的核心场景 |
| P2 | 1 | execFileSync 超时错误的检测逻辑(error.message.includes("timed out"))在 Node.js 18+ 中无法匹配,超时场景将退化到通用错误提示 |
| P3 | 1 | catch 块未记录 error.stdout,对于 git clone 等操作可能导致错误日志不完整(可选改进) |
整体风险判断:中等风险。P1 问题会直接导致 Windows 上默认 skills 安装失败(PR 的核心目标受损),需要在合入前修复;P2 问题影响超时场景下的用户体验;P3 为可选改进项。
已审查文件:
.opencode/plugins/install-default-skills.ts✅ — 发现 3 个问题
| 类型 | 数量 |
|---|---|
| 🔴 阻塞 | 1 |
| 🟡 建议 | 1 |
⛔ 需要修改


Thanks for your pull-request.
The full list of commands accepted by me can be found at here。
You can get sig-info at here
PR Approval Progress
✅ Congratulations! All modules have met the lgtm and approve requirements.
Module Approval Details
| module | lgtm status | approve status |
|---|---|---|
| repo-cann/graph-autofusion | ✅ zhanj, xchu42, xuyafei (3/2) | ✅ zhanj (1/1) |
💡 Tip:
- Committer can comment
/approveor/lgtm- Commenting
/approveimplies both code review (lgtm) and intent to merge (approve)
CLA Signature Pass
hamburgerbobo, thanks for your pull request. All authors of the commits have signed the CLA. 👍


/compile


流水线任务触发成功
任务链接 [bdac8945096c4445a8164a7ddca10f32][流水线指导]
| 任务名称 | 状态 | 日志 | 下载链接 |
|---|---|---|---|
| UT_Test_Python_superkernel | ✅ SUCCESS | >>>>> | |
| ST_Test_Python_superkernel | ✅ SUCCESS | >>>>> | |
| UT_Test_superkernel | ✅ SUCCESS | >>>>> | |
| UT_Test_autofuse_framework | ✅ SUCCESS | >>>>> | |
| ST_Test_autofuse_framework | ✅ SUCCESS | >>>>> | |
| UT_Test_autofuse_ascendc_api | ✅ SUCCESS | >>>>> | |
| ST_Test_autofuse_ascendc_api | ✅ SUCCESS | >>>>> | |
| ST_Test_autofuse_e2e | ✅ SUCCESS | >>>>> | |
| pre_comment | ✅ SUCCESS | >>>>> |
[2026-07-21 10:19:04] CI执行结束


/lgtm


🟡 Medium Priority
变更链路:原代码通过 $bash ...`` 调用 shell 脚本,超时由 timeout 命令产生,错误信息中包含 "timed out" 字符串。PR 将调用替换为 execFileSync('git', ['clone', ...], { timeout: CLONE_TIMEOUT_MS })(第 80 行),但在第 174 行的 catch 块中仍使用 error.message.includes("timed out") 检测超时。
在 Node.js 18+ 中,execFileSync 超时行为为:向子进程发送 SIGTERM → 子进程被杀死 → 抛出 Error 对象,其 error.killed === true、error.signal === 'SIGTERM',但 error.message 中不包含 "timed out" 字符串(格式类似 "Command failed: git clone ... \n")。
因此第 174 行的 error.message.includes("timed out") 将始终返回 false,导致超时场景落入第 176–177 行的通用错误分支,用户无法看到第 175 行的超时专用中文提示("网络连接超时,无法访问远程仓库。请检查网络连接后重试。"),体验退化。
触发条件:git clone 操作超时(网络慢或仓库不可达,超过 20 秒)。
建议:将超时检测从单一的 error.message.includes("timed out") 扩展为同时检查 error.killed 属性。execFileSync 超时时会杀死子进程,设置 error.killed = true 和 error.signal = 'SIGTERM',这比检查 message 字符串更可靠。也可以保留原字符串检测作为向后兼容。
| 174
| - if (error.message && error.message.includes("timed out")) { |
|
174 | + if (error.message && (error.message.includes("timed out") || (error as any).killed)) { |


🟠 High Priority
变更链路:InstallSkillsPlugin 接收的 directory 参数未经过 path.resolve() 处理 → findGitRoot(directory) 在第 35–44 行直接返回 startDir(可能是相对路径如 ".") → installSkillsToRemote(rootDir) 在第 87–88 行通过 path.join 拼接出 skillsDir/remoteDir → 第 107 行的 dest(即 _remote/<skill> 真实目录路径)同样继承了相对性 → 第 110 行调用 createSkillLink(dest, ...)。
在 createSkillLink 的第 49 行,Windows 分支执行 fs.symlinkSync(targetPath, linkPath, 'junction')。Node.js 文档明确要求:Windows junction 的 target 必须是绝对路径("Junctions require the destination path to be absolute")。当 targetPath 为相对路径(如 .claude/skills/_remote/gitcode-pr)时,fs.symlinkSync 会抛出异常,导致整个安装流程失败。
这正是本 PR 要解决的 Windows 兼容性问题的核心场景——PR 设计文档也明确写了"Windows junction 不需要管理员权限,但仅对目录有效且 target 需绝对路径"。当前实现违背了这一设计约束。
触发条件:opencode 传入的 directory 为非绝对路径(例如工作目录为 "." 、相对路径 "../project" 等),这在实践中很常见。
建议:在 createSkillLink 的 Windows 分支中,对 targetPath 使用 path.resolve() 转为绝对路径后再传给 fs.symlinkSync。同时也可以考虑在 installSkillsToRemote 入口处对 rootDir 做一次 path.resolve(),确保所有衍生路径都是绝对的。
| 49
| - fs.symlinkSync(targetPath, linkPath, 'junction') |
|
49 | + fs.symlinkSync(path.resolve(targetPath), linkPath, 'junction') |


/approve


描述
.opencode/plugins/install-default-skills.ts在 opencode 启动时自动安装四个默认 skill(gitcode-pr、gitcode-issue、api-doc-generator、gitcode-pipeline)。原实现委托给 bash 脚本.claude/skills/default-skills/scripts/install-default-skills.sh,在 Windows 上存在两层阻断:bash --version,原生 Windows 无 bash 时直接return,不执行任何安装。install-default-skills.sh使用ln -sfn(Windows 普通用户无符号链接权限)、/tmp、mktemp、timeout等 Unix 专有依赖。本 PR 用 Node.js 原生 API(
fs/path/os/child_process)重写安装逻辑,移除 bash 硬依赖,使插件在 Linux 与 Windows 上均能自动安装默认 skills,且不破坏现有 Linux 行为。.sh脚本保留不动,供 Claude Code 手动场景(Linux)使用。变更类型
关联的Issue
#194
如何测试
前提条件:系统已安装
git并在 PATH 中(Linux/Windows 均默认随 Git for Windows 提供)。Linux 验证(等价性):
.claude/skills/_remote/与四个 skill 一级目录链接_remote/<skill>/真实目录存在,一级目录为相对路径符号链接-> _remote/<skill>.opencode_skills_errormarker 与提示打印Windows 验证(新增能力):
_remote/<skill>/SKILL.md可访问已执行验证(Linux 环境):
SKILL.md可访问.opencode_skills_error并打印清晰提示.gitignore幂等更新,无重复条目,保留尾换行核对清单
其他信息
设计要点:
junction(无需管理员权限,目录专用,target 用绝对路径);Unix 保持相对路径 symlink(与.shln -sfn _remote/$skill等价,仓库内可移植)os.tmpdir()+fs.mkdtempSync替代硬编码/tmp,try/finally+fs.rmSync force:true清理git clone --depth 1(带CLONE_TIMEOUT_MS超时),去除 curl/wget 预检测,减少平台分支DEFAULT_SKILLS、REPO_URL、CLONE_TIMEOUT_MS集中在文件顶部常量,与.sh保持一致.opencode_skills_errormarker + 延迟打印逻辑,catch 块按 strict 模式类型安全处理unknownerror红线自查:不硬编码敏感信息(
REPO_URL为公开仓库地址);资源释放覆盖异常分支;仅改 TS 插件,不扩大修改范围。安全提示:issue 创建过程中误建了测试 issue #193(已加评论标注,GitCode API 关闭端点有兼容问题未能关闭,请社区协助关闭)。