agentsmesh 0.24.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/targets.js CHANGED
@@ -685,6 +685,33 @@ async function readDirRecursive(dir, visited, branchSegments) {
685
685
  );
686
686
  }
687
687
  }
688
+ async function readDirRecursiveNoSymlinks(dir, branchSegments) {
689
+ const currentBranchSegments = branchSegments ?? [basename(dir)];
690
+ try {
691
+ const entries = await readdir(dir, { withFileTypes: true });
692
+ const files = [];
693
+ for (const ent of entries) {
694
+ if (ent.isSymbolicLink()) continue;
695
+ const full = join(dir, ent.name);
696
+ if (ent.isDirectory()) {
697
+ const nextSegments = [...currentBranchSegments, ent.name];
698
+ if (shouldSkipRecursiveBranch(nextSegments)) continue;
699
+ files.push(...await readDirRecursiveNoSymlinks(full, nextSegments));
700
+ } else if (ent.isFile()) {
701
+ files.push(full);
702
+ }
703
+ }
704
+ return files;
705
+ } catch (err) {
706
+ const e = err;
707
+ if (e.code === "ENOENT" || e.code === "ENOTDIR" || e.code === "EACCES") return [];
708
+ throw new FileSystemError(
709
+ dir,
710
+ `Failed to read directory ${dir}: ${e.message}. Check permissions.`,
711
+ { cause: err, errnoCode: e.code }
712
+ );
713
+ }
714
+ }
688
715
  var MAX_RECURSIVE_DEPTH, MAX_SEGMENT_REPETITIONS;
689
716
  var init_fs_traverse = __esm({
690
717
  "src/utils/filesystem/fs-traverse.ts"() {
@@ -1210,7 +1237,7 @@ async function importEmbeddedSkills(projectRoot, skillsDir, fromTool, results, n
1210
1237
  toPath: `${AB_SKILLS}/${entry.name}/SKILL.md`,
1211
1238
  feature: "skills"
1212
1239
  });
1213
- const sourceFiles = await readDirRecursive(sourceSkillDir);
1240
+ const sourceFiles = await readDirRecursiveNoSymlinks(sourceSkillDir);
1214
1241
  for (const sourcePath of sourceFiles) {
1215
1242
  if (sourcePath === sourceSkillFile) continue;
1216
1243
  const relativePath = relative(sourceSkillDir, sourcePath).replace(/\\/g, "/");
@@ -2158,7 +2185,7 @@ function matchesExtension(path, extensions) {
2158
2185
  return extensions.some((extension) => path.endsWith(extension));
2159
2186
  }
2160
2187
  async function importFileDirectory(opts) {
2161
- const files = await readDirRecursive(opts.srcDir);
2188
+ const files = await readDirRecursiveNoSymlinks(opts.srcDir);
2162
2189
  const matchedFiles = files.filter((path) => matchesExtension(path, opts.extensions));
2163
2190
  const results = [];
2164
2191
  for (const srcPath of matchedFiles) {
@@ -6547,7 +6574,7 @@ var init_settings_helpers2 = __esm({
6547
6574
  async function importClaudeSkills(projectRoot, results, normalize) {
6548
6575
  const skillsBaseDir = join(projectRoot, CLAUDE_SKILLS_DIR);
6549
6576
  const destBase = join(projectRoot, CLAUDE_CANONICAL_SKILLS_DIR);
6550
- const allFiles = await readDirRecursive(skillsBaseDir);
6577
+ const allFiles = await readDirRecursiveNoSymlinks(skillsBaseDir);
6551
6578
  const skillMdFiles = allFiles.filter((f) => f.endsWith("SKILL.md"));
6552
6579
  for (const skillMdPath of skillMdFiles) {
6553
6580
  const skillDir = dirname(skillMdPath);
@@ -6566,7 +6593,7 @@ async function importClaudeSkills(projectRoot, results, normalize) {
6566
6593
  `);
6567
6594
  continue;
6568
6595
  }
6569
- const skillFiles = await readDirRecursive(skillDir);
6596
+ const skillFiles = await readDirRecursiveNoSymlinks(skillDir);
6570
6597
  for (const filePath of skillFiles) {
6571
6598
  const fileContent = await readFileSafe(filePath);
6572
6599
  if (fileContent === null) continue;
@@ -7191,7 +7218,7 @@ async function importClineRules(projectRoot, results, normalize) {
7191
7218
  feature: "rules"
7192
7219
  });
7193
7220
  } else {
7194
- const ruleFiles = await readDirRecursive(clineRulesPath);
7221
+ const ruleFiles = await readDirRecursiveNoSymlinks(clineRulesPath);
7195
7222
  const mdFiles = ruleFiles.filter((f) => f.endsWith(".md") && !f.includes("/workflows/")).sort();
7196
7223
  const first = mdFiles[0];
7197
7224
  if (first) {
@@ -7255,27 +7282,40 @@ var init_importer_rules = __esm({
7255
7282
  init_constants8();
7256
7283
  }
7257
7284
  });
7285
+ function toStringRecord2(raw) {
7286
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return {};
7287
+ return Object.fromEntries(
7288
+ Object.entries(raw).filter((entry) => typeof entry[1] === "string")
7289
+ );
7290
+ }
7258
7291
  function mapClineServerToCanonical(raw) {
7259
7292
  if (!raw || typeof raw !== "object") return null;
7260
7293
  const obj = raw;
7261
- const command = typeof obj.command === "string" ? obj.command : "";
7262
- if (!command) return null;
7263
- const type = typeof obj.type === "string" ? obj.type : typeof obj.transportType === "string" ? obj.transportType : "stdio";
7264
- const args = Array.isArray(obj.args) ? obj.args.filter((x) => typeof x === "string") : [];
7265
- const envRaw = obj.env;
7266
- const env = envRaw !== null && typeof envRaw === "object" && !Array.isArray(envRaw) ? Object.fromEntries(
7267
- Object.entries(envRaw).filter(
7268
- (entry) => typeof entry[1] === "string"
7269
- )
7270
- ) : {};
7294
+ const transport = typeof obj.type === "string" ? obj.type : void 0;
7295
+ const transportType = typeof obj.transportType === "string" ? obj.transportType : void 0;
7296
+ const env = toStringRecord2(obj.env);
7271
7297
  const description = typeof obj.description === "string" ? obj.description : void 0;
7272
- return {
7273
- ...description !== void 0 && { description },
7274
- type,
7275
- command,
7276
- args,
7277
- env
7278
- };
7298
+ const command = typeof obj.command === "string" ? obj.command : "";
7299
+ if (command) {
7300
+ const args = Array.isArray(obj.args) ? obj.args.filter((x) => typeof x === "string") : [];
7301
+ return {
7302
+ ...description !== void 0 && { description },
7303
+ type: transport ?? transportType ?? "stdio",
7304
+ command,
7305
+ args,
7306
+ env
7307
+ };
7308
+ }
7309
+ if (typeof obj.url === "string") {
7310
+ return {
7311
+ ...description !== void 0 && { description },
7312
+ type: transport ?? transportType ?? "http",
7313
+ url: obj.url,
7314
+ headers: toStringRecord2(obj.headers),
7315
+ env
7316
+ };
7317
+ }
7318
+ return null;
7279
7319
  }
7280
7320
  async function importClineMcp(projectRoot, results) {
7281
7321
  const candidatePaths = [CLINE_MCP_SETTINGS, CLINE_MCP_SETTINGS_LEGACY].map(
@@ -7349,7 +7389,7 @@ var init_reserved = __esm({
7349
7389
  }
7350
7390
  });
7351
7391
  async function readNativeSkill(skillDir) {
7352
- const allFiles = await readDirRecursive(skillDir).catch(() => []);
7392
+ const allFiles = await readDirRecursiveNoSymlinks(skillDir).catch(() => []);
7353
7393
  const entries = [];
7354
7394
  for (const absPath of allFiles) {
7355
7395
  const relPath = relative(skillDir, absPath).replace(/\\/g, "/");
@@ -7415,7 +7455,7 @@ async function importFlatSkill(skillName, srcPath, content, options) {
7415
7455
  async function findDirectorySkills(skillsDir) {
7416
7456
  const skills = /* @__PURE__ */ new Map();
7417
7457
  try {
7418
- const allFiles = await readDirRecursive(skillsDir);
7458
+ const allFiles = await readDirRecursiveNoSymlinks(skillsDir);
7419
7459
  const skillMdFiles = allFiles.filter((f) => basename(f) === "SKILL.md");
7420
7460
  for (const skillMdPath of skillMdFiles) {
7421
7461
  const skillDir = dirname(skillMdPath);
@@ -7546,7 +7586,7 @@ function extractMeta(content, key) {
7546
7586
  return match?.[1]?.trim() ?? null;
7547
7587
  }
7548
7588
  async function loadHooksFromDir(dir, hooks) {
7549
- const files = await readDirRecursive(dir).catch(() => []);
7589
+ const files = await readDirRecursiveNoSymlinks(dir).catch(() => []);
7550
7590
  const shFiles = files.filter((f) => basename(f).endsWith(".sh") && dirname(f) === dir);
7551
7591
  for (const srcPath of shFiles) {
7552
7592
  const content = await readFileSafe(srcPath);
@@ -8281,7 +8321,7 @@ async function importCodexAgentsFromToml(projectRoot, results, normalize) {
8281
8321
  const agentsPath = join(projectRoot, CODEX_AGENTS_DIR);
8282
8322
  const agentsDestDir = join(projectRoot, CODEX_CANONICAL_AGENTS_DIR);
8283
8323
  try {
8284
- const agentFiles = await readDirRecursive(agentsPath);
8324
+ const agentFiles = await readDirRecursiveNoSymlinks(agentsPath);
8285
8325
  const tomlFiles = agentFiles.filter((f) => f.endsWith(".toml"));
8286
8326
  for (const srcPath of tomlFiles) {
8287
8327
  const content = await readFileSafe(srcPath);
@@ -8377,7 +8417,7 @@ async function importCodexNonRootRuleFiles(projectRoot, destDir, normalize) {
8377
8417
  const results = [];
8378
8418
  const codexRulesPath = join(projectRoot, CODEX_RULES_DIR);
8379
8419
  try {
8380
- const ruleFiles = await readDirRecursive(codexRulesPath);
8420
+ const ruleFiles = await readDirRecursiveNoSymlinks(codexRulesPath);
8381
8421
  const mdFiles = ruleFiles.filter((f) => f.endsWith(".md"));
8382
8422
  for (const srcPath of mdFiles) {
8383
8423
  const content = await readFileSafe(srcPath);
@@ -8534,7 +8574,7 @@ async function importCodexRules(projectRoot, results, normalize, normalizeWindsu
8534
8574
  }
8535
8575
  async function importInstructionMirrors(projectRoot, destDir, results, normalize) {
8536
8576
  try {
8537
- const files = await readDirRecursive(join(projectRoot, CODEX_INSTRUCTIONS_DIR));
8577
+ const files = await readDirRecursiveNoSymlinks(join(projectRoot, CODEX_INSTRUCTIONS_DIR));
8538
8578
  const instructionFiles = files.filter((file) => file.endsWith(".md"));
8539
8579
  const instructionsRoot = join(projectRoot, CODEX_INSTRUCTIONS_DIR);
8540
8580
  for (const srcPath of instructionFiles) {
@@ -8980,19 +9020,31 @@ function readMcpServers(content, extension) {
8980
9020
  for (const [name, value] of Object.entries(rawServers)) {
8981
9021
  if (!value || typeof value !== "object" || Array.isArray(value)) continue;
8982
9022
  const server = value;
8983
- if (typeof server.command !== "string") continue;
8984
- servers[name] = {
8985
- type: typeof server.type === "string" ? server.type : "stdio",
8986
- command: server.command,
8987
- args: toStringArray5(server.args),
8988
- env: toStringRecord(server.env),
8989
- description: typeof server.description === "string" ? server.description : void 0
8990
- };
9023
+ const description = typeof server.description === "string" ? server.description : void 0;
9024
+ if (typeof server.command === "string") {
9025
+ servers[name] = {
9026
+ type: typeof server.type === "string" ? server.type : "stdio",
9027
+ command: server.command,
9028
+ args: toStringArray5(server.args),
9029
+ env: toStringRecord(server.env),
9030
+ description
9031
+ };
9032
+ continue;
9033
+ }
9034
+ if (typeof server.url === "string") {
9035
+ servers[name] = {
9036
+ type: typeof server.type === "string" ? server.type : "http",
9037
+ url: server.url,
9038
+ headers: toStringRecord(server.headers),
9039
+ env: toStringRecord(server.env),
9040
+ description
9041
+ };
9042
+ }
8991
9043
  }
8992
9044
  return servers;
8993
9045
  }
8994
9046
  async function importMcp2(projectRoot, results) {
8995
- const files = (await readDirRecursive(join(projectRoot, CONTINUE_MCP_DIR))).filter(
9047
+ const files = (await readDirRecursiveNoSymlinks(join(projectRoot, CONTINUE_MCP_DIR))).filter(
8996
9048
  (file) => [".json", ".yaml", ".yml"].includes(extname(file))
8997
9049
  );
8998
9050
  const merged = {};
@@ -9652,7 +9704,7 @@ function extractWrapperCommand(content) {
9652
9704
  }
9653
9705
  async function importHooks(projectRoot, results) {
9654
9706
  const hooksDir = join(projectRoot, COPILOT_HOOKS_DIR);
9655
- const allFiles = await readDirRecursive(hooksDir).catch(() => []);
9707
+ const allFiles = await readDirRecursiveNoSymlinks(hooksDir).catch(() => []);
9656
9708
  const jsonFiles = allFiles.filter((file) => file.endsWith(".json"));
9657
9709
  const hooks = {};
9658
9710
  for (const srcPath of jsonFiles) {
@@ -9688,7 +9740,7 @@ async function importHooks(projectRoot, results) {
9688
9740
  }
9689
9741
  }
9690
9742
  const legacyDir = join(projectRoot, COPILOT_LEGACY_HOOKS_DIR);
9691
- const legacyFiles = await readDirRecursive(legacyDir).catch(() => []);
9743
+ const legacyFiles = await readDirRecursiveNoSymlinks(legacyDir).catch(() => []);
9692
9744
  const shFiles = legacyFiles.filter(
9693
9745
  (file) => dirname(file) === legacyDir && /^[^-]+-\d+\.sh$/i.test(basename(file))
9694
9746
  );
@@ -9765,7 +9817,7 @@ var init_importer10 = __esm({
9765
9817
  }
9766
9818
  });
9767
9819
  async function skillNamesFromNativeSkillDir(scanRoot) {
9768
- const files = await readDirRecursive(scanRoot);
9820
+ const files = await readDirRecursiveNoSymlinks(scanRoot);
9769
9821
  const names = /* @__PURE__ */ new Set();
9770
9822
  for (const f of files) {
9771
9823
  if (basename(f) === "SKILL.md") {
@@ -9787,7 +9839,7 @@ var init_native_skill_scan = __esm({
9787
9839
  async function inferCopilotPickFromPath(repoRoot, posixPath) {
9788
9840
  const scan = join(repoRoot, ...posixPath.split("/"));
9789
9841
  if (posixPath.startsWith(COPILOT_PROMPTS_DIR)) {
9790
- const files = await readDirRecursive(scan);
9842
+ const files = await readDirRecursiveNoSymlinks(scan);
9791
9843
  const commands = [
9792
9844
  ...new Set(
9793
9845
  files.filter((f) => f.toLowerCase().endsWith(".prompt.md")).map((f) => basename(f, ".prompt.md"))
@@ -9796,7 +9848,7 @@ async function inferCopilotPickFromPath(repoRoot, posixPath) {
9796
9848
  return commands.length ? { commands } : {};
9797
9849
  }
9798
9850
  if (posixPath.startsWith(".github/copilot") && !posixPath.includes("copilot-instructions.md")) {
9799
- const files = await readDirRecursive(scan);
9851
+ const files = await readDirRecursiveNoSymlinks(scan);
9800
9852
  const rules = [
9801
9853
  ...new Set(
9802
9854
  files.filter((f) => f.includes(".instructions.md")).map((f) => basename(f).replace(/\.instructions\.md$/i, ""))
@@ -9805,7 +9857,7 @@ async function inferCopilotPickFromPath(repoRoot, posixPath) {
9805
9857
  return rules.length ? { rules } : {};
9806
9858
  }
9807
9859
  if (posixPath.startsWith(".github/instructions")) {
9808
- const files = await readDirRecursive(scan);
9860
+ const files = await readDirRecursiveNoSymlinks(scan);
9809
9861
  const names = /* @__PURE__ */ new Set();
9810
9862
  for (const f of files) {
9811
9863
  const b = basename(f);
@@ -9821,7 +9873,7 @@ async function inferCopilotPickFromPath(repoRoot, posixPath) {
9821
9873
  return skills.length ? { skills } : {};
9822
9874
  }
9823
9875
  if (posixPath.startsWith(".github/agents")) {
9824
- const files = await readDirRecursive(scan);
9876
+ const files = await readDirRecursiveNoSymlinks(scan);
9825
9877
  const agents = [
9826
9878
  ...new Set(
9827
9879
  files.filter((f) => f.toLowerCase().endsWith(".agent.md")).map((f) => basename(f, ".agent.md"))
@@ -11369,7 +11421,7 @@ async function importSkills3(projectRoot, results, normalize, skillsRelDir = CUR
11369
11421
  for (const [skillName, skillDir] of directorySkills) {
11370
11422
  await importDirectorySkill(skillName, skillDir, options);
11371
11423
  }
11372
- const allFiles = await readDirRecursive(skillsDir).catch(() => []);
11424
+ const allFiles = await readDirRecursiveNoSymlinks(skillsDir).catch(() => []);
11373
11425
  const mdFiles = allFiles.filter((f) => f.endsWith(".md"));
11374
11426
  const handledPaths = new Set(
11375
11427
  Array.from(directorySkills.values()).flatMap(
@@ -11407,11 +11459,11 @@ async function hasGlobalCursorArtifacts(projectRoot) {
11407
11459
  const stat5 = await readFileSafe(p);
11408
11460
  if (stat5 !== null && stat5.trim() !== "") return true;
11409
11461
  }
11410
- const skillFiles = await readDirRecursive(join(projectRoot, CURSOR_SKILLS_DIR));
11462
+ const skillFiles = await readDirRecursiveNoSymlinks(join(projectRoot, CURSOR_SKILLS_DIR));
11411
11463
  if (skillFiles.some((f) => f.endsWith(".md"))) return true;
11412
- const agentFiles = await readDirRecursive(join(projectRoot, CURSOR_AGENTS_DIR));
11464
+ const agentFiles = await readDirRecursiveNoSymlinks(join(projectRoot, CURSOR_AGENTS_DIR));
11413
11465
  if (agentFiles.some((f) => f.endsWith(".md"))) return true;
11414
- const commandFiles = await readDirRecursive(join(projectRoot, CURSOR_COMMANDS_DIR));
11466
+ const commandFiles = await readDirRecursiveNoSymlinks(join(projectRoot, CURSOR_COMMANDS_DIR));
11415
11467
  if (commandFiles.some((f) => f.endsWith(".md"))) return true;
11416
11468
  return false;
11417
11469
  }
@@ -12999,7 +13051,7 @@ async function importGeminiPolicies(projectRoot) {
12999
13051
  const policiesDir = join(projectRoot, GEMINI_POLICIES_DIR);
13000
13052
  let policyFiles;
13001
13053
  try {
13002
- policyFiles = await readDirRecursive(policiesDir);
13054
+ policyFiles = await readDirRecursiveNoSymlinks(policiesDir);
13003
13055
  } catch {
13004
13056
  return results;
13005
13057
  }
@@ -13098,7 +13150,7 @@ var init_importer_strip = __esm({
13098
13150
  });
13099
13151
  async function importGeminiSkillsAndAgents(projectRoot, results, normalize) {
13100
13152
  const geminiSkillsPath = join(projectRoot, GEMINI_SKILLS_DIR);
13101
- const skillDirs = await readDirRecursive(geminiSkillsPath);
13153
+ const skillDirs = await readDirRecursiveNoSymlinks(geminiSkillsPath);
13102
13154
  const skillMdFiles = skillDirs.filter((f) => basename(f) === "SKILL.md");
13103
13155
  for (const srcPath of skillMdFiles) {
13104
13156
  const content = await readFileSafe(srcPath);
@@ -13137,7 +13189,7 @@ async function importGeminiSkillsAndAgents(projectRoot, results, normalize) {
13137
13189
  toPath: `${GEMINI_CANONICAL_SKILLS_DIR}/${skillName}/SKILL.md`,
13138
13190
  feature: "skills"
13139
13191
  });
13140
- const allSkillFiles = await readDirRecursive(dirname(srcPath));
13192
+ const allSkillFiles = await readDirRecursiveNoSymlinks(dirname(srcPath));
13141
13193
  for (const absPath of allSkillFiles) {
13142
13194
  if (absPath === srcPath) continue;
13143
13195
  const supportContent = await readFileSafe(absPath);
@@ -13156,7 +13208,7 @@ async function importGeminiSkillsAndAgents(projectRoot, results, normalize) {
13156
13208
  }
13157
13209
  const geminiAgentsPath = join(projectRoot, GEMINI_AGENTS_DIR);
13158
13210
  try {
13159
- const agentFiles = await readDirRecursive(geminiAgentsPath);
13211
+ const agentFiles = await readDirRecursiveNoSymlinks(geminiAgentsPath);
13160
13212
  const agentMdFiles = agentFiles.filter((f) => f.endsWith(".md"));
13161
13213
  for (const srcPath of agentMdFiles) {
13162
13214
  const content = await readFileSafe(srcPath);
@@ -13289,7 +13341,7 @@ function isUnderGeminiCommands(pathInRepoPosix) {
13289
13341
  async function inferGeminiCommandNamesFromFiles(repoRoot, pathInRepoPosix) {
13290
13342
  const commandsRoot = join(repoRoot, ...GEMINI_COMMANDS_DIR.split("/"));
13291
13343
  const scanDir = join(repoRoot, ...pathInRepoPosix.split("/"));
13292
- const files = await readDirRecursive(scanDir);
13344
+ const files = await readDirRecursiveNoSymlinks(scanDir);
13293
13345
  const names = [];
13294
13346
  for (const f of files) {
13295
13347
  if (!/\.(toml|md)$/i.test(f)) continue;
@@ -15501,7 +15553,7 @@ async function importNonRootRules(projectRoot, results, normalize) {
15501
15553
  }
15502
15554
  async function importHooks2(projectRoot, results) {
15503
15555
  const hooks = {};
15504
- for (const absPath of await readDirRecursive(join(projectRoot, KIRO_HOOKS_DIR))) {
15556
+ for (const absPath of await readDirRecursiveNoSymlinks(join(projectRoot, KIRO_HOOKS_DIR))) {
15505
15557
  if (!absPath.endsWith(".kiro.hook")) continue;
15506
15558
  const parsed = parseKiroHookFile(await readFileSafe(absPath) ?? "");
15507
15559
  if (!parsed) continue;
@@ -15853,7 +15905,7 @@ var init_generator24 = __esm({
15853
15905
  init_constants19();
15854
15906
  }
15855
15907
  });
15856
- function toStringRecord2(value) {
15908
+ function toStringRecord3(value) {
15857
15909
  if (!value || typeof value !== "object" || Array.isArray(value)) return {};
15858
15910
  const out = {};
15859
15911
  for (const [k, v] of Object.entries(value)) {
@@ -15879,8 +15931,8 @@ function parseOpenCodeMcp(content) {
15879
15931
  out[name] = {
15880
15932
  type: "url",
15881
15933
  url: entry.url,
15882
- headers: toStringRecord2(entry.headers),
15883
- env: toStringRecord2(entry.environment),
15934
+ headers: toStringRecord3(entry.headers),
15935
+ env: toStringRecord3(entry.environment),
15884
15936
  ...typeof entry.description === "string" ? { description: entry.description } : {}
15885
15937
  };
15886
15938
  continue;
@@ -15894,7 +15946,7 @@ function parseOpenCodeMcp(content) {
15894
15946
  type: "stdio",
15895
15947
  command,
15896
15948
  args,
15897
- env: toStringRecord2(entry.environment),
15949
+ env: toStringRecord3(entry.environment),
15898
15950
  ...typeof entry.description === "string" ? { description: entry.description } : {}
15899
15951
  };
15900
15952
  }
@@ -18716,7 +18768,7 @@ function toStringArray8(value) {
18716
18768
  }
18717
18769
  async function importWorkflows(projectRoot, results, normalize) {
18718
18770
  const workflowsDir = join(projectRoot, WINDSURF_WORKFLOWS_DIR);
18719
- const workflowFiles = await readDirRecursive(workflowsDir);
18771
+ const workflowFiles = await readDirRecursiveNoSymlinks(workflowsDir);
18720
18772
  const workflowMdFiles = workflowFiles.filter((f) => f.endsWith(".md"));
18721
18773
  const destCommandsDir = join(projectRoot, WINDSURF_CANONICAL_COMMANDS_DIR);
18722
18774
  for (const srcPath of workflowMdFiles) {