[Bug] .zcode/agents 扫描静默跳过符号链接/junction(软链接的 subagent 定义不加载)
Nobody has claimed this yet.
- Dominant language
- No language data
- Stars
- 22
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
提交前确认 · Pre-submission checklist
- 我已搜索过现有 issue,确认这不是重复提议 / I searched existing issues and confirmed this isn't a duplicate.
- 我已阅读 CONTRIBUTING.md / I've read CONTRIBUTING.md.
问题类别 · Category
缺陷 / Bug(子智能体配置发现)
涉及的 Agent 框架 · Agent framework
ZCode Agent(自研)
问题描述 · Bug description
.zcode/agents/(项目级)与 ~/.zcode/agents/(用户级)目录扫描会静默跳过所有符号链接条目:软链接的 .md 定义文件不加载,软链接/junction 的子目录整棵子树丢失。用硬链接或真实文件则正常加载。
根因分析 · Root cause
zcode.cjs 中 subagent 目录扫描(反混淆后逻辑如下):
function scanAgents(dir) {
if (!fs.existsSync(dir)) return [];
if (!fs.statSync(dir).isDirectory()) return [];
const out = [];
for (const ent of fs.readdirSync(dir, { withFileTypes: true })) {
const p = path.join(dir, ent.name);
if (ent.isDirectory()) { out.push(...scanAgents(p)); continue; }
ent.isFile() && /\.(md|markdown)$/i.test(ent.name) && out.push(p);
}
return out.sort();
}
readdirSync(..., { withFileTypes: true }) 返回的 Dirent 基于 lstat 语义:符号链接条目的 isFile() 和 isDirectory() 均为 false(它是 isSymbolicLink()),于是既不进文件分支也不进目录分支,被静默丢弃。
同类扫描在本产品内处理不一致:skills 的目录扫描(skillFilesUnderRoot 等)过滤条件是 isDirectory() || isSymbolicLink(),明确处理了软链接;agents 的扫描没有。这应当是实现疏漏而非设计约定。(次要观察:commands 的 .md 列表过滤也是 isFile() 单条件,疑似同病,供一并核查。)
复现步骤 · Reproduce
Windows 11 + ZCode 桌面版 v3.7.x(自带 CLI 0.16.3):
- 在任意工作区建
.zcode/agents/,放一个正常的real.md(frontmatter + 正文,可被加载); - 再放一个软链接定义文件:
mklink link.md <某个外部的合法 agent 定义.md>(或开发者模式下ln -s);以及一个目录联接:mklink /J linkdir <外部目录>(内含合法.md); - 启动会话查看实际加载的 subagent profiles。
实测结果(直接用与 zcode.cjs 一字不差的扫描逻辑跑真实目录):
| 条目 | Dirent 判定 | 是否被收集 |
|---|---|---|
real.md 普通文件 |
isFile=true | ✅ |
shared/sub.md 普通子目录 |
isDirectory=true | ✅ |
hardlink.md(mklink /H 硬链接) |
isFile=true | ✅ |
link.md 符号链接文件 |
isFile=false, isSymbolicLink=true | ❌ 跳过 |
linkdir(junction / 符号链接目录) |
isDirectory=false, isSymbolicLink=true | ❌ 整棵子树丢失 |
期望行为 · Expected behavior
扫描跟随符号链接:文件与目录分支都应兼容 isSymbolicLink() 条目,例如 ent.isFile() || ent.isSymbolicLink()(再配合 statSync(p) 判定目标类型与扩展名),目录分支同理——与 skills 扫描的既有做法对齐。若出于安全考虑决定不跟随软链接,至少应在 doctor / 日志中给出明确诊断,而不是静默丢弃。
影响 · Impact
- 团队把 subagent 定义集中存放、按仓库软链引入的用法完全不可用(这是 #269 之后"项目级 subagent 共享"的一个常见延伸用法);
- Windows 上 junction(
mklink /J,无需管理员权限,最常用的目录链接手段)同样中招; - 用户级
~/.zcode/agents/走同一扫描函数,一样受影响。
临时绕过 · Workaround
文件级共享可改用硬链接 cmd /c mklink /H <link.md> <target.md>(无需管理员权限,Dirent 表现为普通文件,实测可被加载);目录级共享暂时只能复制文件。
你认为的优先级 · Your perceived priority
中 · Medium(有硬链接绕过,但静默失败 + 与 skills 行为不一致,容易让人误以为项目级 subagent 不生效)
你使用的 ZCode 版本 / 环境 · ZCode version / environment
- Windows 11 桌面版 v3.7.x,自带 CLI 0.16.3(
F:\soft\ZCode\resources\glm\zcode.cjs) - 复现为对 bundle 内实际扫描函数的等价执行,非猜测
补充材料 · Additional context
- 相关:#269(项目级 subagent 已支持;本 bug 发生在其配置发现环节)
- 对照证据:skills 扫描已处理
isSymbolicLink()(zcode.cjs内skillFilesUnderRoot的过滤条件)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in zcode.cjs at scanAgents and compare its Dirent handling with the skillFilesUnderRoot scan, which already considers symbolic links. Reproduce the scan with a linked .md file and linked directory on Windows, then verify that both linked agent definitions are loaded without silently skipping them.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100