@cannbot-ai/install-helper 0.0.2-beta.15 → 0.0.2-beta.16

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/index.js CHANGED
@@ -12,108 +12,45 @@ import { select, checkbox, Separator } from "@inquirer/prompts";
12
12
  import chalk2 from "chalk";
13
13
 
14
14
  // src/core/registry.ts
15
- var PLUGIN_REGISTRY = [
16
- {
17
- id: "ops-direct-invoke",
18
- dir: "plugins-official/ops-direct-invoke",
19
- displayName: "AscendC Kernel \u76F4\u8C03",
20
- script: "init.sh",
21
- aliases: ["ops-direct", "ascendc-direct", "direct", "kernel"],
22
- skills: 16,
23
- agents: 3,
24
- description: "Ascend C Kernel <<<>>> \u76F4\u8C03\u7B97\u5B50\u5F00\u53D1\u5168\u6D41\u7A0B"
25
- },
26
- {
27
- id: "ops-direct-invoke-flash",
28
- dir: "plugins-official/ops-direct-invoke-flash",
29
- displayName: "AscendC Kernel \u4ECE\u96F6\u6784\u5EFA",
30
- script: "init.sh",
31
- aliases: ["flash", "kernel-flash"],
32
- skills: 1,
33
- agents: 1,
34
- description: "Ascend C / Ascend950 Reg API \u6838\u51FD\u6570\u4ECE\u96F6\u6784\u5EFA"
35
- },
36
- {
37
- id: "ops-registry-invoke",
38
- dir: "plugins-official/ops-registry-invoke",
39
- displayName: "AscendC \u7B97\u5B50\u6CE8\u518C\u8C03\u7528",
40
- script: "init.sh",
41
- aliases: ["ops-registry", "ascendc-registry", "registry"],
42
- skills: 12,
43
- agents: 4,
44
- description: "Ascend C \u7B97\u5B50\u6CE8\u518C\u8C03\u7528\u5F00\u53D1\u6D41\u7A0B"
45
- },
46
- {
47
- id: "pypto-op-orchestrator",
48
- dir: "plugins-official/pypto-op-orchestrator",
49
- displayName: "PyPTO \u7B97\u5B50",
50
- script: "init.sh",
51
- aliases: ["pypto", "pytorch"],
52
- skills: 8,
53
- agents: 3,
54
- description: "PyPTO \u7B97\u5B50\u7AEF\u5230\u7AEF\u5F00\u53D1\u7F16\u6392"
55
- },
56
- {
57
- id: "triton-op-generator",
58
- dir: "plugins-official/triton-op-generator",
59
- displayName: "Triton \u7B97\u5B50\u751F\u6210",
60
- script: "install.sh",
61
- aliases: ["triton"],
62
- skills: 6,
63
- agents: 0,
64
- description: "Triton-Ascend \u7B97\u5B50\u4EE3\u7801\u751F\u6210\u4E0E\u4F18\u5316"
65
- },
66
- {
67
- id: "tilelang-op-orchestrator",
68
- dir: "plugins-official/tilelang-op-orchestrator",
69
- displayName: "TileLang \u7B97\u5B50",
70
- script: "init.sh",
71
- aliases: ["tilelang"],
72
- skills: 9,
73
- agents: 3,
74
- description: "TileLang \u7B97\u5B50\u5F00\u53D1\u6D41\u7A0B"
75
- },
76
- {
77
- id: "model-infer-optimize",
78
- dir: "plugins-official/model-infer-optimize",
79
- displayName: "NPU \u63A8\u7406\u4F18\u5316",
80
- script: "init.sh",
81
- aliases: ["model-infer", "infer", "inference"],
82
- skills: 11,
83
- agents: 3,
84
- description: "NPU \u6A21\u578B\u63A8\u7406\u7AEF\u5230\u7AEF\u4F18\u5316"
85
- },
86
- {
87
- id: "catlass-op-generator",
88
- dir: "plugins-official/catlass-op-generator",
89
- displayName: "Catlass \u7B97\u5B50\u76F4\u8C03",
90
- script: "init.sh",
91
- aliases: ["catlass"],
92
- skills: 10,
93
- agents: 3,
94
- description: "Catlass \u7B97\u5B50\u76F4\u8C03\u5F00\u53D1"
95
- },
96
- {
97
- id: "ops-code-reviewer",
98
- dir: "plugins-official/ops-code-reviewer",
99
- displayName: "\u4EE3\u7801\u68C0\u89C6",
100
- script: "init.sh",
101
- aliases: ["code-review", "reviewer", "review"],
102
- skills: 5,
103
- agents: 1,
104
- description: "\u4EE3\u7801\u68C0\u89C6\u4E0E\u89C4\u8303\u68C0\u67E5"
105
- },
106
- {
107
- id: "torch-compile",
108
- dir: "plugins-official/torch-compile",
109
- displayName: "torch.compile \u56FE\u6A21\u5F0F",
110
- script: "init.sh",
111
- aliases: ["torch", "compile", "graph"],
112
- skills: 6,
113
- agents: 1,
114
- description: "PyTorch torch.compile \u56FE\u6A21\u5F0F\u9002\u914D"
15
+ import { readdirSync, readFileSync } from "fs";
16
+ import { join, dirname } from "path";
17
+ import { fileURLToPath } from "url";
18
+ import { parse as parseYaml } from "yaml";
19
+ var __filename = fileURLToPath(import.meta.url);
20
+ var __dirname = dirname(__filename);
21
+ function loadPluginsFromYaml() {
22
+ const pluginsDir = join(__dirname, "plugins.d");
23
+ const defaultsPath = join(pluginsDir, "_defaults.yml");
24
+ let defaults = {};
25
+ try {
26
+ defaults = parseYaml(readFileSync(defaultsPath, "utf-8")) || {};
27
+ } catch {
115
28
  }
116
- ];
29
+ const plugins = [];
30
+ try {
31
+ for (const file of readdirSync(pluginsDir)) {
32
+ if (file.startsWith("_") || !file.endsWith(".yml")) continue;
33
+ try {
34
+ const content = parseYaml(readFileSync(join(pluginsDir, file), "utf-8"));
35
+ if (!content || !content.id) continue;
36
+ plugins.push({
37
+ id: content.id,
38
+ dir: content.dir,
39
+ displayName: content.displayName || content.id,
40
+ script: content.script || defaults.script || "init.sh",
41
+ aliases: content.aliases || [],
42
+ skills: content.skills ?? defaults.skills ?? 0,
43
+ agents: content.agents ?? defaults.agents ?? 0,
44
+ description: content.description || ""
45
+ });
46
+ } catch {
47
+ }
48
+ }
49
+ } catch {
50
+ }
51
+ return plugins;
52
+ }
53
+ var PLUGIN_REGISTRY = loadPluginsFromYaml();
117
54
  function findPlugin(query) {
118
55
  const normalized = query.toLowerCase().trim();
119
56
  const exactMatch = PLUGIN_REGISTRY.find(
@@ -139,11 +76,11 @@ function getPluginById(id) {
139
76
  import { execa } from "execa";
140
77
  import { existsSync as existsSync2 } from "fs";
141
78
  import { homedir as homedir2 } from "os";
142
- import { join as join2 } from "path";
79
+ import { join as join3 } from "path";
143
80
 
144
81
  // src/utils/paths.ts
145
82
  import { homedir } from "os";
146
- import { join } from "path";
83
+ import { join as join2 } from "path";
147
84
  import { existsSync } from "fs";
148
85
 
149
86
  // src/utils/i18n.ts
@@ -512,9 +449,9 @@ function validateLevel(level) {
512
449
  }
513
450
  function detectTraeVariant() {
514
451
  const home = homedir();
515
- if (existsSync(join(home, ".trae-cn"))) return "ide";
516
- if (existsSync(join(home, ".marscode"))) return "plugin";
517
- if (existsSync(join(home, ".traecli"))) return "cli";
452
+ if (existsSync(join2(home, ".trae-cn"))) return "ide";
453
+ if (existsSync(join2(home, ".marscode"))) return "plugin";
454
+ if (existsSync(join2(home, ".traecli"))) return "cli";
518
455
  return "unknown";
519
456
  }
520
457
  function getConfigRoot(tool, level, base) {
@@ -522,24 +459,24 @@ function getConfigRoot(tool, level, base) {
522
459
  if (level === "global") {
523
460
  switch (tool) {
524
461
  case "opencode":
525
- return join(home, ".config", "opencode");
462
+ return join2(home, ".config", "opencode");
526
463
  case "claude":
527
- return join(home, ".claude");
464
+ return join2(home, ".claude");
528
465
  case "trae": {
529
466
  const variant = detectTraeVariant();
530
467
  switch (variant) {
531
468
  case "plugin":
532
- return join(home, ".marscode");
469
+ return join2(home, ".marscode");
533
470
  case "cli":
534
- return join(home, ".traecli");
471
+ return join2(home, ".traecli");
535
472
  default:
536
- return join(home, ".trae-cn");
473
+ return join2(home, ".trae-cn");
537
474
  }
538
475
  }
539
476
  case "cursor":
540
- return join(home, ".cursor");
477
+ return join2(home, ".cursor");
541
478
  case "copilot":
542
- return join(home, ".copilot");
479
+ return join2(home, ".copilot");
543
480
  default:
544
481
  throw new Error(
545
482
  t("error_invalid_tool").replace("{tool}", tool).replace("{tools}", VALID_TOOLS.join(", "))
@@ -549,24 +486,24 @@ function getConfigRoot(tool, level, base) {
549
486
  const baseDir = base || process.cwd();
550
487
  switch (tool) {
551
488
  case "opencode":
552
- return join(baseDir, ".opencode");
489
+ return join2(baseDir, ".opencode");
553
490
  case "claude":
554
- return join(baseDir, ".claude");
491
+ return join2(baseDir, ".claude");
555
492
  case "trae": {
556
493
  const variant = detectTraeVariant();
557
494
  switch (variant) {
558
495
  case "plugin":
559
- return join(baseDir, ".marscode");
496
+ return join2(baseDir, ".marscode");
560
497
  case "cli":
561
- return join(baseDir, ".traecli");
498
+ return join2(baseDir, ".traecli");
562
499
  default:
563
- return join(baseDir, ".trae");
500
+ return join2(baseDir, ".trae");
564
501
  }
565
502
  }
566
503
  case "cursor":
567
- return join(baseDir, ".cursor");
504
+ return join2(baseDir, ".cursor");
568
505
  case "copilot":
569
- return join(baseDir, ".github");
506
+ return join2(baseDir, ".github");
570
507
  default:
571
508
  throw new Error(
572
509
  t("error_invalid_tool").replace("{tool}", tool).replace("{tools}", VALID_TOOLS.join(", "))
@@ -577,19 +514,19 @@ function getConfigFileName(tool) {
577
514
  return tool === "claude" ? "CLAUDE.md" : "AGENTS.md";
578
515
  }
579
516
  function getSkillsDir(configRoot) {
580
- return join(configRoot, "skills");
517
+ return join2(configRoot, "skills");
581
518
  }
582
519
  function getAgentsDir(configRoot) {
583
- return join(configRoot, "agents");
520
+ return join2(configRoot, "agents");
584
521
  }
585
522
  function getManifestPath(configRoot) {
586
- return join(configRoot, "cannbot-manifest.json");
523
+ return join2(configRoot, "cannbot-manifest.json");
587
524
  }
588
525
  function getCannbotConfigDir() {
589
- return join(homedir(), ".cannbot");
526
+ return join2(homedir(), ".cannbot");
590
527
  }
591
528
  function getCannbotRepoPath() {
592
- return join(getCannbotConfigDir(), "repo");
529
+ return join2(getCannbotConfigDir(), "repo");
593
530
  }
594
531
 
595
532
  // src/core/detector.ts
@@ -627,12 +564,12 @@ async function detectTrae() {
627
564
  const home = homedir2();
628
565
  const variant = detectTraeVariant();
629
566
  let path;
630
- if (variant === "ide" && existsSync2(join2(home, ".trae-cn"))) {
631
- path = join2(home, ".trae-cn");
632
- } else if (variant === "plugin" && existsSync2(join2(home, ".marscode"))) {
633
- path = join2(home, ".marscode");
634
- } else if (variant === "cli" && existsSync2(join2(home, ".traecli"))) {
635
- path = join2(home, ".traecli");
567
+ if (variant === "ide" && existsSync2(join3(home, ".trae-cn"))) {
568
+ path = join3(home, ".trae-cn");
569
+ } else if (variant === "plugin" && existsSync2(join3(home, ".marscode"))) {
570
+ path = join3(home, ".marscode");
571
+ } else if (variant === "cli" && existsSync2(join3(home, ".traecli"))) {
572
+ path = join3(home, ".traecli");
636
573
  } else if (variant === "unknown") {
637
574
  const cmdPath = await getCommandPath("trae");
638
575
  if (cmdPath) path = cmdPath;
@@ -696,13 +633,13 @@ function getAllTools() {
696
633
  }
697
634
 
698
635
  // src/core/manifest.ts
699
- import { existsSync as existsSync3, readFileSync } from "fs";
700
- import { join as join3 } from "path";
636
+ import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
637
+ import { join as join4 } from "path";
701
638
  function readManifest(configRoot) {
702
639
  const manifestPath = getManifestPath(configRoot);
703
640
  if (existsSync3(manifestPath)) {
704
641
  try {
705
- const content = readFileSync(manifestPath, "utf-8");
642
+ const content = readFileSync2(manifestPath, "utf-8");
706
643
  return JSON.parse(content);
707
644
  } catch {
708
645
  }
@@ -715,16 +652,16 @@ function readAllManifests(configRoot) {
715
652
  const standardPath = getManifestPath(configRoot);
716
653
  if (existsSync3(standardPath)) {
717
654
  try {
718
- const content = readFileSync(standardPath, "utf-8");
655
+ const content = readFileSync2(standardPath, "utf-8");
719
656
  manifests.push(JSON.parse(content));
720
657
  } catch {
721
658
  }
722
659
  }
723
660
  for (const plugin of plugins) {
724
- const pluginManifestPath = join3(configRoot, `${plugin.id}-manifest.json`);
661
+ const pluginManifestPath = join4(configRoot, `${plugin.id}-manifest.json`);
725
662
  if (existsSync3(pluginManifestPath)) {
726
663
  try {
727
- const content = readFileSync(pluginManifestPath, "utf-8");
664
+ const content = readFileSync2(pluginManifestPath, "utf-8");
728
665
  manifests.push(JSON.parse(content));
729
666
  } catch {
730
667
  }
@@ -767,27 +704,27 @@ function scanInstalled() {
767
704
  return installed;
768
705
  }
769
706
  function verifyPluginFilesExist(configRoot, manifest, tool, level) {
770
- const skillsDir = join3(configRoot, "skills");
771
- const agentsDir = join3(configRoot, "agents");
707
+ const skillsDir = join4(configRoot, "skills");
708
+ const agentsDir = join4(configRoot, "agents");
772
709
  if (manifest.installed_skills && manifest.installed_skills.length > 0) {
773
710
  const hasAnySkill = manifest.installed_skills.some((skillId) => {
774
- const skillPath = join3(skillsDir, skillId);
711
+ const skillPath = join4(skillsDir, skillId);
775
712
  return existsSync3(skillPath);
776
713
  });
777
714
  if (!hasAnySkill) return false;
778
715
  }
779
716
  if (manifest.installed_agents && manifest.installed_agents.length > 0) {
780
717
  const hasAnyAgent = manifest.installed_agents.some((agentId) => {
781
- const agentPath = join3(agentsDir, agentId);
718
+ const agentPath = join4(agentsDir, agentId);
782
719
  return existsSync3(agentPath);
783
720
  });
784
721
  if (!hasAnyAgent) return false;
785
722
  }
786
723
  let agentsMdPath;
787
724
  if (tool === "opencode" && level === "project") {
788
- agentsMdPath = join3(configRoot, "..", "AGENTS.md");
725
+ agentsMdPath = join4(configRoot, "..", "AGENTS.md");
789
726
  } else {
790
- agentsMdPath = join3(configRoot, "AGENTS.md");
727
+ agentsMdPath = join4(configRoot, "AGENTS.md");
791
728
  }
792
729
  if (!existsSync3(agentsMdPath)) return false;
793
730
  return true;
@@ -856,15 +793,15 @@ function showOperationHints(isCheckbox = false) {
856
793
  }
857
794
 
858
795
  // src/utils/config.ts
859
- import { existsSync as existsSync4, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
860
- import { join as join4 } from "path";
796
+ import { existsSync as existsSync4, mkdirSync, readFileSync as readFileSync3, writeFileSync } from "fs";
797
+ import { join as join5 } from "path";
861
798
  import { homedir as homedir3 } from "os";
862
799
  import { parse, stringify } from "yaml";
863
800
  function getConfigDir() {
864
- return join4(homedir3(), ".cannbot");
801
+ return join5(homedir3(), ".cannbot");
865
802
  }
866
803
  function getConfigPath() {
867
- return join4(getConfigDir(), "config.yaml");
804
+ return join5(getConfigDir(), "config.yaml");
868
805
  }
869
806
  function readConfig() {
870
807
  const configPath = getConfigPath();
@@ -875,7 +812,7 @@ function readConfig() {
875
812
  };
876
813
  }
877
814
  try {
878
- const content = readFileSync2(configPath, "utf-8");
815
+ const content = readFileSync3(configPath, "utf-8");
879
816
  const parsed = parse(content);
880
817
  return {
881
818
  language: parsed.language || "zh_CN",
@@ -1181,14 +1118,19 @@ async function stepConfirm(tool, level, plugins) {
1181
1118
  }
1182
1119
 
1183
1120
  // src/core/repository.ts
1184
- import { existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
1185
- import { join as join6 } from "path";
1121
+ import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync5 } from "fs";
1122
+ import { join as join7, dirname as dirname3 } from "path";
1123
+ import { fileURLToPath as fileURLToPath3 } from "url";
1186
1124
  import { execa as execa2 } from "execa";
1125
+ import { parse as parseYaml3 } from "yaml";
1187
1126
 
1188
1127
  // src/core/scanner.ts
1189
- import { existsSync as existsSync5, readdirSync, readFileSync as readFileSync3, statSync, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
1190
- import { join as join5, dirname } from "path";
1191
- import { parse as parseYaml } from "yaml";
1128
+ import { existsSync as existsSync5, readdirSync as readdirSync2, readFileSync as readFileSync4, statSync, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
1129
+ import { join as join6, dirname as dirname2 } from "path";
1130
+ import { fileURLToPath as fileURLToPath2 } from "url";
1131
+ import { parse as parseYaml2 } from "yaml";
1132
+ var __filename2 = fileURLToPath2(import.meta.url);
1133
+ var __dirname2 = dirname2(__filename2);
1192
1134
  var EXCLUDE_DIRS = /* @__PURE__ */ new Set([
1193
1135
  "node_modules",
1194
1136
  ".git",
@@ -1209,36 +1151,43 @@ var EXCLUDE_DIRS = /* @__PURE__ */ new Set([
1209
1151
  "docs",
1210
1152
  "scripts"
1211
1153
  ]);
1212
- var SKILL_SCAN_DIRS = [
1213
- "ops",
1214
- "model",
1215
- "graph",
1216
- "infra",
1217
- "ops-lab"
1218
- ];
1219
- var PLUGIN_SCAN_DIRS = [
1220
- "plugins-official",
1221
- "plugins-community"
1222
- ];
1154
+ function loadScanConfig() {
1155
+ const configPath = join6(__dirname2, "config", "defaults.yaml");
1156
+ try {
1157
+ const config = parseYaml2(readFileSync4(configPath, "utf-8"));
1158
+ return {
1159
+ skillDirs: config.scanDirs || ["ops", "model", "graph", "infra", "ops-lab"],
1160
+ pluginDirs: config.pluginDirs || ["plugins-official", "plugins-community"]
1161
+ };
1162
+ } catch {
1163
+ return {
1164
+ skillDirs: ["ops", "model", "graph", "infra", "ops-lab"],
1165
+ pluginDirs: ["plugins-official", "plugins-community"]
1166
+ };
1167
+ }
1168
+ }
1169
+ var scanConfig = loadScanConfig();
1170
+ var SKILL_SCAN_DIRS = scanConfig.skillDirs;
1171
+ var PLUGIN_SCAN_DIRS = scanConfig.pluginDirs;
1223
1172
  function scanSkills(repoPath) {
1224
1173
  const skills = [];
1225
1174
  const seen = /* @__PURE__ */ new Set();
1226
1175
  for (const dir of SKILL_SCAN_DIRS) {
1227
- const fullPath = join5(repoPath, dir);
1176
+ const fullPath = join6(repoPath, dir);
1228
1177
  if (!existsSync5(fullPath)) continue;
1229
1178
  scanDirectory(fullPath, repoPath, dir, skills, seen);
1230
1179
  }
1231
1180
  for (const pluginDir of PLUGIN_SCAN_DIRS) {
1232
- const pluginParent = join5(repoPath, pluginDir);
1181
+ const pluginParent = join6(repoPath, pluginDir);
1233
1182
  if (!existsSync5(pluginParent)) continue;
1234
1183
  for (const plugin of safeReaddir(pluginParent)) {
1235
- const pluginPath = join5(pluginParent, plugin);
1184
+ const pluginPath = join6(pluginParent, plugin);
1236
1185
  if (!isDirectory(pluginPath)) continue;
1237
- const skillsDir = join5(pluginPath, "skills");
1186
+ const skillsDir = join6(pluginPath, "skills");
1238
1187
  if (existsSync5(skillsDir)) {
1239
1188
  scanDirectory(skillsDir, repoPath, `${pluginDir}/${plugin}/skills`, skills, seen);
1240
1189
  }
1241
- const skillDir = join5(pluginPath, "skill");
1190
+ const skillDir = join6(pluginPath, "skill");
1242
1191
  if (existsSync5(skillDir)) {
1243
1192
  scanDirectory(skillDir, repoPath, `${pluginDir}/${plugin}/skill`, skills, seen);
1244
1193
  }
@@ -1248,7 +1197,7 @@ function scanSkills(repoPath) {
1248
1197
  }
1249
1198
  function parseFrontmatter(filePath) {
1250
1199
  try {
1251
- const content = readFileSync3(filePath, "utf-8");
1200
+ const content = readFileSync4(filePath, "utf-8");
1252
1201
  const lines = content.split("\n");
1253
1202
  if (lines.length < 3) return null;
1254
1203
  if (lines[0].trim() !== "---") return null;
@@ -1261,7 +1210,7 @@ function parseFrontmatter(filePath) {
1261
1210
  }
1262
1211
  if (endIndex === -1) return null;
1263
1212
  const yamlBlock = lines.slice(1, endIndex).map((l) => l.replace(/\r$/, "")).join("\n");
1264
- const parsed = parseYaml(yamlBlock);
1213
+ const parsed = parseYaml2(yamlBlock);
1265
1214
  if (!parsed || typeof parsed !== "object") return null;
1266
1215
  if (!parsed.name || typeof parsed.name !== "string") return null;
1267
1216
  return {
@@ -1274,17 +1223,17 @@ function parseFrontmatter(filePath) {
1274
1223
  }
1275
1224
  function getCurrentCommit(repoPath) {
1276
1225
  try {
1277
- const headFile = join5(repoPath, ".git", "HEAD");
1226
+ const headFile = join6(repoPath, ".git", "HEAD");
1278
1227
  if (!existsSync5(headFile)) return "unknown";
1279
- const headContent = readFileSync3(headFile, "utf-8").trim();
1228
+ const headContent = readFileSync4(headFile, "utf-8").trim();
1280
1229
  if (headContent.startsWith("ref: ")) {
1281
- const refPath = join5(repoPath, ".git", headContent.slice(5));
1230
+ const refPath = join6(repoPath, ".git", headContent.slice(5));
1282
1231
  if (existsSync5(refPath)) {
1283
- return readFileSync3(refPath, "utf-8").trim();
1232
+ return readFileSync4(refPath, "utf-8").trim();
1284
1233
  }
1285
- const packedRefsPath = join5(repoPath, ".git", "packed-refs");
1234
+ const packedRefsPath = join6(repoPath, ".git", "packed-refs");
1286
1235
  if (existsSync5(packedRefsPath)) {
1287
- const packedRefs = readFileSync3(packedRefsPath, "utf-8");
1236
+ const packedRefs = readFileSync4(packedRefsPath, "utf-8");
1288
1237
  const refName = headContent.slice(5);
1289
1238
  const lines = packedRefs.split("\n");
1290
1239
  for (const line of lines) {
@@ -1303,7 +1252,7 @@ function readScanCache() {
1303
1252
  try {
1304
1253
  const cachePath = getCachePath();
1305
1254
  if (!existsSync5(cachePath)) return null;
1306
- const content = readFileSync3(cachePath, "utf-8");
1255
+ const content = readFileSync4(cachePath, "utf-8");
1307
1256
  const cache = JSON.parse(content);
1308
1257
  if (!cache.skills || !cache.timestamp) return null;
1309
1258
  const age = Date.now() - cache.timestamp;
@@ -1316,7 +1265,7 @@ function readScanCache() {
1316
1265
  function writeScanCache(cache) {
1317
1266
  try {
1318
1267
  const cachePath = getCachePath();
1319
- const cacheDir = dirname(cachePath);
1268
+ const cacheDir = dirname2(cachePath);
1320
1269
  if (!existsSync5(cacheDir)) {
1321
1270
  mkdirSync2(cacheDir, { recursive: true });
1322
1271
  }
@@ -1325,10 +1274,10 @@ function writeScanCache(cache) {
1325
1274
  }
1326
1275
  }
1327
1276
  function getCachePath() {
1328
- return join5(getCannbotConfigDir(), "scan-cache.json");
1277
+ return join6(getCannbotConfigDir(), "scan-cache.json");
1329
1278
  }
1330
1279
  function scanDirectory(dirPath, repoPath, sourcePrefix, skills, seen) {
1331
- const selfSkillMd = join5(dirPath, "SKILL.md");
1280
+ const selfSkillMd = join6(dirPath, "SKILL.md");
1332
1281
  if (existsSync5(selfSkillMd)) {
1333
1282
  const frontmatter = parseFrontmatter(selfSkillMd);
1334
1283
  if (frontmatter && !seen.has(frontmatter.name)) {
@@ -1343,10 +1292,10 @@ function scanDirectory(dirPath, repoPath, sourcePrefix, skills, seen) {
1343
1292
  return;
1344
1293
  }
1345
1294
  for (const entry of safeReaddir(dirPath)) {
1346
- const fullPath = join5(dirPath, entry);
1295
+ const fullPath = join6(dirPath, entry);
1347
1296
  if (EXCLUDE_DIRS.has(entry)) continue;
1348
1297
  if (!isDirectory(fullPath)) continue;
1349
- const skillMd = join5(fullPath, "SKILL.md");
1298
+ const skillMd = join6(fullPath, "SKILL.md");
1350
1299
  if (existsSync5(skillMd)) {
1351
1300
  const frontmatter = parseFrontmatter(skillMd);
1352
1301
  if (frontmatter && !seen.has(frontmatter.name)) {
@@ -1365,7 +1314,7 @@ function scanDirectory(dirPath, repoPath, sourcePrefix, skills, seen) {
1365
1314
  }
1366
1315
  function safeReaddir(dir) {
1367
1316
  try {
1368
- return readdirSync(dir);
1317
+ return readdirSync2(dir);
1369
1318
  } catch {
1370
1319
  return [];
1371
1320
  }
@@ -1605,7 +1554,21 @@ function getAllCategories() {
1605
1554
  }
1606
1555
 
1607
1556
  // src/core/repository.ts
1608
- var REPO_URL = "https://gitcode.com/cann/cannbot-skills.git";
1557
+ var __filename3 = fileURLToPath3(import.meta.url);
1558
+ var __dirname3 = dirname3(__filename3);
1559
+ function loadRepoUrl() {
1560
+ if (process.env.CANNBOT_REPO_URL) {
1561
+ return process.env.CANNBOT_REPO_URL;
1562
+ }
1563
+ const configPath = join7(__dirname3, "config", "defaults.yaml");
1564
+ try {
1565
+ const config = parseYaml3(readFileSync5(configPath, "utf-8"));
1566
+ return config.repository?.url || "https://gitcode.com/cann/cannbot-skills.git";
1567
+ } catch {
1568
+ return "https://gitcode.com/cann/cannbot-skills.git";
1569
+ }
1570
+ }
1571
+ var REPO_URL = loadRepoUrl();
1609
1572
  var RepositoryManager = class {
1610
1573
  repoPath;
1611
1574
  constructor(customPath) {
@@ -1663,8 +1626,8 @@ var RepositoryManager = class {
1663
1626
  }
1664
1627
  isValidRepo(path) {
1665
1628
  if (!existsSync6(path)) return false;
1666
- const gitDir = join6(path, ".git");
1667
- const pluginsDir = join6(path, "plugins-official");
1629
+ const gitDir = join7(path, ".git");
1630
+ const pluginsDir = join7(path, "plugins-official");
1668
1631
  return existsSync6(gitDir) && existsSync6(pluginsDir);
1669
1632
  }
1670
1633
  async cloneRepo() {
@@ -1700,17 +1663,17 @@ function createRepositoryManager(customPath) {
1700
1663
 
1701
1664
  // src/core/installer.ts
1702
1665
  import { existsSync as existsSync9 } from "fs";
1703
- import { join as join9 } from "path";
1666
+ import { join as join10 } from "path";
1704
1667
  import { execa as execa3 } from "execa";
1705
1668
 
1706
1669
  // src/core/record.ts
1707
- import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4, lstatSync, unlinkSync } from "fs";
1708
- import { join as join7 } from "path";
1670
+ import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4, lstatSync, unlinkSync } from "fs";
1671
+ import { join as join8 } from "path";
1709
1672
  function getInstallsDir() {
1710
- return join7(getCannbotConfigDir(), "installs");
1673
+ return join8(getCannbotConfigDir(), "installs");
1711
1674
  }
1712
1675
  function getRecordPath(pluginId) {
1713
- return join7(getInstallsDir(), `${pluginId}.json`);
1676
+ return join8(getInstallsDir(), `${pluginId}.json`);
1714
1677
  }
1715
1678
  function readRecord(pluginId) {
1716
1679
  const recordPath = getRecordPath(pluginId);
@@ -1718,7 +1681,7 @@ function readRecord(pluginId) {
1718
1681
  return null;
1719
1682
  }
1720
1683
  try {
1721
- const content = readFileSync4(recordPath, "utf-8");
1684
+ const content = readFileSync6(recordPath, "utf-8");
1722
1685
  return JSON.parse(content);
1723
1686
  } catch {
1724
1687
  return null;
@@ -1742,22 +1705,22 @@ function scanInstalledFiles(pluginId, displayName, tool, level, installPath, con
1742
1705
  const files = [];
1743
1706
  const directories = [];
1744
1707
  if (manifest) {
1745
- const skillsDir = join7(configRoot, "skills");
1708
+ const skillsDir = join8(configRoot, "skills");
1746
1709
  if (existsSync7(skillsDir)) {
1747
1710
  directories.push(skillsDir);
1748
1711
  for (const skillName of manifest.installed_skills || []) {
1749
- const skillPath = join7(skillsDir, skillName);
1712
+ const skillPath = join8(skillsDir, skillName);
1750
1713
  if (existsSync7(skillPath) || isSymlink(skillPath)) {
1751
1714
  files.push(skillPath);
1752
1715
  }
1753
1716
  }
1754
1717
  }
1755
- const agentsDir = join7(configRoot, "agents");
1718
+ const agentsDir = join8(configRoot, "agents");
1756
1719
  if (existsSync7(agentsDir)) {
1757
1720
  directories.push(agentsDir);
1758
1721
  for (const agentName of manifest.installed_agents || []) {
1759
- const agentPath = join7(agentsDir, agentName);
1760
- const agentPathMd = join7(agentsDir, agentName + ".md");
1722
+ const agentPath = join8(agentsDir, agentName);
1723
+ const agentPathMd = join8(agentsDir, agentName + ".md");
1761
1724
  if (existsSync7(agentPath) || isSymlink(agentPath)) {
1762
1725
  files.push(agentPath);
1763
1726
  } else if (existsSync7(agentPathMd) || isSymlink(agentPathMd)) {
@@ -1766,30 +1729,30 @@ function scanInstalledFiles(pluginId, displayName, tool, level, installPath, con
1766
1729
  }
1767
1730
  }
1768
1731
  }
1769
- const workflowsLink = join7(configRoot, "workflows");
1732
+ const workflowsLink = join8(configRoot, "workflows");
1770
1733
  if (isSymlink(workflowsLink)) {
1771
1734
  files.push(workflowsLink);
1772
1735
  }
1773
- const manifestPath = join7(configRoot, "cannbot-manifest.json");
1736
+ const manifestPath = join8(configRoot, "cannbot-manifest.json");
1774
1737
  if (existsSync7(manifestPath)) {
1775
1738
  files.push(manifestPath);
1776
1739
  }
1777
- const pluginManifestPath = join7(configRoot, `${pluginId}-manifest.json`);
1740
+ const pluginManifestPath = join8(configRoot, `${pluginId}-manifest.json`);
1778
1741
  if (existsSync7(pluginManifestPath)) {
1779
1742
  files.push(pluginManifestPath);
1780
1743
  }
1781
1744
  const configFileName = tool === "claude" ? "CLAUDE.md" : "AGENTS.md";
1782
- const configFilePath = level === "project" ? join7(installPath, configFileName) : join7(configRoot, configFileName);
1745
+ const configFilePath = level === "project" ? join8(installPath, configFileName) : join8(configRoot, configFileName);
1783
1746
  if (existsSync7(configFilePath)) {
1784
1747
  files.push(configFilePath);
1785
1748
  }
1786
1749
  const repoLinks = ["asc-devkit", "pypto", "tilelang-ascend", "cann-recipes-infer", "cann-samples"];
1787
1750
  for (const repoName of repoLinks) {
1788
- const repoLinkPath = join7(installPath, repoName);
1751
+ const repoLinkPath = join8(installPath, repoName);
1789
1752
  if (isSymlink(repoLinkPath)) {
1790
1753
  files.push(repoLinkPath);
1791
1754
  }
1792
- const repoLinkInConfig = join7(configRoot, repoName);
1755
+ const repoLinkInConfig = join8(configRoot, repoName);
1793
1756
  if (isSymlink(repoLinkInConfig)) {
1794
1757
  files.push(repoLinkInConfig);
1795
1758
  }
@@ -1814,7 +1777,7 @@ function isSymlink(path) {
1814
1777
  }
1815
1778
  }
1816
1779
  function getSkillRecordPath() {
1817
- return join7(getInstallsDir(), "skills.json");
1780
+ return join8(getInstallsDir(), "skills.json");
1818
1781
  }
1819
1782
  function readSkillRecord() {
1820
1783
  const recordPath = getSkillRecordPath();
@@ -1822,7 +1785,7 @@ function readSkillRecord() {
1822
1785
  return {};
1823
1786
  }
1824
1787
  try {
1825
- const content = readFileSync4(recordPath, "utf-8");
1788
+ const content = readFileSync6(recordPath, "utf-8");
1826
1789
  return JSON.parse(content);
1827
1790
  } catch {
1828
1791
  return {};
@@ -1872,16 +1835,16 @@ function getInstalledSkills(tool, level, installPath) {
1872
1835
  const record = readSkillRecord();
1873
1836
  const recordedSkills = record[tool]?.[level]?.[installPath]?.skills || [];
1874
1837
  const configRoot = getConfigRoot(tool, level);
1875
- const skillsDir = join7(configRoot, "skills");
1838
+ const skillsDir = join8(configRoot, "skills");
1876
1839
  return recordedSkills.filter((skillId) => {
1877
- const skillPath = join7(skillsDir, skillId);
1840
+ const skillPath = join8(skillsDir, skillId);
1878
1841
  return existsSync7(skillPath) || isSymlink(skillPath);
1879
1842
  });
1880
1843
  }
1881
1844
 
1882
1845
  // src/core/backup.ts
1883
- import { existsSync as existsSync8, copyFileSync, readdirSync as readdirSync2, unlinkSync as unlinkSync2 } from "fs";
1884
- import { join as join8 } from "path";
1846
+ import { existsSync as existsSync8, copyFileSync, readdirSync as readdirSync3, unlinkSync as unlinkSync2 } from "fs";
1847
+ import { join as join9 } from "path";
1885
1848
  function getAgentsFileName(tool) {
1886
1849
  return tool === "claude" ? "CLAUDE.md" : "AGENTS.md";
1887
1850
  }
@@ -1896,7 +1859,7 @@ function detectCurrentPlugin(configRoot, tool) {
1896
1859
  };
1897
1860
  }
1898
1861
  }
1899
- const agentsFile = join8(configRoot, getAgentsFileName(tool));
1862
+ const agentsFile = join9(configRoot, getAgentsFileName(tool));
1900
1863
  if (!existsSync8(agentsFile)) {
1901
1864
  return null;
1902
1865
  }
@@ -1915,13 +1878,13 @@ function detectCurrentPlugin(configRoot, tool) {
1915
1878
  return null;
1916
1879
  }
1917
1880
  function createBackup(configRoot, tool, fromPluginId, fromPluginName) {
1918
- const agentsFile = join8(configRoot, getAgentsFileName(tool));
1881
+ const agentsFile = join9(configRoot, getAgentsFileName(tool));
1919
1882
  if (!existsSync8(agentsFile)) {
1920
1883
  return null;
1921
1884
  }
1922
1885
  const timestamp = formatTimestamp(/* @__PURE__ */ new Date());
1923
1886
  const backupFileName = `${getAgentsFileName(tool)}.cannbot-backup.${fromPluginId}.${timestamp}`;
1924
- const backupPath = join8(configRoot, backupFileName);
1887
+ const backupPath = join9(configRoot, backupFileName);
1925
1888
  try {
1926
1889
  copyFileSync(agentsFile, backupPath);
1927
1890
  return {
@@ -1938,7 +1901,7 @@ function findBackups(configRoot) {
1938
1901
  if (!existsSync8(configRoot)) {
1939
1902
  return [];
1940
1903
  }
1941
- const files = readdirSync2(configRoot);
1904
+ const files = readdirSync3(configRoot);
1942
1905
  const backups = [];
1943
1906
  for (const file of files) {
1944
1907
  if (file.includes(".cannbot-backup.")) {
@@ -1951,7 +1914,7 @@ function findBackups(configRoot) {
1951
1914
  const timestamp = pluginIdAndTime.substring(lastDotIndex + 1);
1952
1915
  const plugin = findPlugin(pluginId);
1953
1916
  backups.push({
1954
- filePath: join8(configRoot, file),
1917
+ filePath: join9(configRoot, file),
1955
1918
  pluginId,
1956
1919
  pluginName: plugin?.displayName || pluginId,
1957
1920
  backupTime: timestamp
@@ -1964,7 +1927,7 @@ function findBackups(configRoot) {
1964
1927
  }
1965
1928
  function restoreBackup(backupPath, configRoot, tool) {
1966
1929
  try {
1967
- const agentsFile = join8(configRoot, getAgentsFileName(tool));
1930
+ const agentsFile = join9(configRoot, getAgentsFileName(tool));
1968
1931
  copyFileSync(backupPath, agentsFile);
1969
1932
  return true;
1970
1933
  } catch {
@@ -2065,7 +2028,7 @@ async function installPlugin(opts) {
2065
2028
  warnings: []
2066
2029
  };
2067
2030
  }
2068
- const scriptPath = join9(opts.repoPath, plugin.dir, plugin.script);
2031
+ const scriptPath = join10(opts.repoPath, plugin.dir, plugin.script);
2069
2032
  if (!existsSync9(scriptPath)) {
2070
2033
  return {
2071
2034
  success: false,
@@ -2082,7 +2045,7 @@ async function installPlugin(opts) {
2082
2045
  }
2083
2046
  const cwd = opts.installPath || process.cwd();
2084
2047
  const configRoot = getConfigRoot(opts.tool, opts.level, opts.installPath);
2085
- const agentsFile = join9(configRoot, getAgentsFileName(opts.tool));
2048
+ const agentsFile = join10(configRoot, getAgentsFileName(opts.tool));
2086
2049
  let backupInfo = null;
2087
2050
  if (existsSync9(agentsFile)) {
2088
2051
  const currentPlugin = detectCurrentPlugin(configRoot, opts.tool);
@@ -2177,14 +2140,14 @@ async function installPlugin(opts) {
2177
2140
  }
2178
2141
 
2179
2142
  // src/core/skill-installer.ts
2180
- import { existsSync as existsSync10, mkdirSync as mkdirSync5, symlinkSync, unlinkSync as unlinkSync3, readdirSync as readdirSync3, rmdirSync, realpathSync, lstatSync as lstatSync2 } from "fs";
2181
- import { join as join10 } from "path";
2143
+ import { existsSync as existsSync10, mkdirSync as mkdirSync5, symlinkSync, unlinkSync as unlinkSync3, readdirSync as readdirSync4, rmdirSync, realpathSync, lstatSync as lstatSync2 } from "fs";
2144
+ import { join as join11 } from "path";
2182
2145
  import { select as select3, checkbox as checkbox2, Separator as Separator2 } from "@inquirer/prompts";
2183
2146
  import chalk4 from "chalk";
2184
2147
  import Table from "cli-table3";
2185
2148
  async function installSkills(skillIds, tool, level, repoPath) {
2186
2149
  const configRoot = getConfigRoot(tool, level);
2187
- const skillsDir = join10(configRoot, "skills");
2150
+ const skillsDir = join11(configRoot, "skills");
2188
2151
  const installPath = level === "project" ? process.cwd() : configRoot;
2189
2152
  if (!existsSync10(skillsDir)) {
2190
2153
  mkdirSync5(skillsDir, { recursive: true });
@@ -2197,8 +2160,8 @@ async function installSkills(skillIds, tool, level, repoPath) {
2197
2160
  results.push({ skillId, success: false, error: "Skill not found in registry" });
2198
2161
  continue;
2199
2162
  }
2200
- const sourcePath = join10(repoPath, skill.source, skill.id);
2201
- const targetPath = join10(skillsDir, skillId);
2163
+ const sourcePath = join11(repoPath, skill.source, skill.id);
2164
+ const targetPath = join11(skillsDir, skillId);
2202
2165
  if (!existsSync10(sourcePath)) {
2203
2166
  results.push({ skillId, success: false, error: `Source not found: ${sourcePath}` });
2204
2167
  continue;
@@ -2221,12 +2184,12 @@ async function installSkills(skillIds, tool, level, repoPath) {
2221
2184
  }
2222
2185
  async function uninstallSkills(skillIds, tool, level) {
2223
2186
  const configRoot = getConfigRoot(tool, level);
2224
- const skillsDir = join10(configRoot, "skills");
2187
+ const skillsDir = join11(configRoot, "skills");
2225
2188
  const installPath = level === "project" ? process.cwd() : configRoot;
2226
2189
  const results = [];
2227
2190
  const removedIds = [];
2228
2191
  for (const skillId of skillIds) {
2229
- const targetPath = join10(skillsDir, skillId);
2192
+ const targetPath = join11(skillsDir, skillId);
2230
2193
  try {
2231
2194
  if (existsSync10(targetPath) || isSymlink2(targetPath)) {
2232
2195
  unlinkSync3(targetPath);
@@ -2246,7 +2209,7 @@ async function uninstallSkills(skillIds, tool, level) {
2246
2209
  }
2247
2210
  if (existsSync10(skillsDir)) {
2248
2211
  try {
2249
- const entries = readdirSync3(skillsDir);
2212
+ const entries = readdirSync4(skillsDir);
2250
2213
  if (entries.length === 0) {
2251
2214
  rmdirSync(skillsDir);
2252
2215
  logger.step(` ${t("uninstall_clean_empty_dir")}: skills/`);
@@ -2444,8 +2407,10 @@ function printEnhancedSummary(results, tool, configRoot) {
2444
2407
  ""
2445
2408
  ];
2446
2409
  if (successResults.length === 1) {
2410
+ const plugin = findPlugin(successResults[0].pluginId);
2411
+ const docsPath = plugin ? `${plugin.dir}/quickstart.md` : `${successResults[0].pluginId}/quickstart.md`;
2447
2412
  lines.push(
2448
- ` ${chalk5.dim(t("install_enhanced_docs"))}: ${chalk5.dim(`plugins-official/${successResults[0].pluginId}/quickstart.md`)}`
2413
+ ` ${chalk5.dim(t("install_enhanced_docs"))}: ${chalk5.dim(docsPath)}`
2449
2414
  );
2450
2415
  }
2451
2416
  console.log();
@@ -2456,15 +2421,15 @@ function printEnhancedSummary(results, tool, configRoot) {
2456
2421
  }
2457
2422
 
2458
2423
  // src/commands/init.ts
2459
- import { existsSync as existsSync11, readFileSync as readFileSync5 } from "fs";
2460
- import { join as join11 } from "path";
2424
+ import { existsSync as existsSync11, readFileSync as readFileSync7 } from "fs";
2425
+ import { join as join12 } from "path";
2461
2426
  var BACK2 = "__back__";
2462
2427
  var CANCEL2 = "__cancel__";
2463
2428
  async function initCommand() {
2464
2429
  const cwd = process.cwd();
2465
- if (existsSync11(join11(cwd, "package.json")) && (() => {
2430
+ if (existsSync11(join12(cwd, "package.json")) && (() => {
2466
2431
  try {
2467
- const pkg = JSON.parse(readFileSync5(join11(cwd, "package.json"), "utf-8"));
2432
+ const pkg = JSON.parse(readFileSync7(join12(cwd, "package.json"), "utf-8"));
2468
2433
  return pkg.name === "@cannbot-ai/install-helper";
2469
2434
  } catch {
2470
2435
  return false;
@@ -2690,8 +2655,8 @@ async function listCommand() {
2690
2655
 
2691
2656
  // src/commands/doctor.ts
2692
2657
  import chalk7 from "chalk";
2693
- import { existsSync as existsSync12, readdirSync as readdirSync4, lstatSync as lstatSync3, unlinkSync as unlinkSync4, mkdirSync as mkdirSync6 } from "fs";
2694
- import { join as join12 } from "path";
2658
+ import { existsSync as existsSync12, readdirSync as readdirSync5, lstatSync as lstatSync3, unlinkSync as unlinkSync4, mkdirSync as mkdirSync6 } from "fs";
2659
+ import { join as join13 } from "path";
2695
2660
  async function doctorCommand(options = {}) {
2696
2661
  console.log();
2697
2662
  console.log(chalk7.bold(` ${t("doctor_title")}`));
@@ -2737,7 +2702,7 @@ async function doctorCommand(options = {}) {
2737
2702
  if (existsSync12(skillsDir)) {
2738
2703
  const brokenLinks = checkBrokenLinks(skillsDir);
2739
2704
  if (brokenLinks === 0) {
2740
- const count = readdirSync4(skillsDir).length;
2705
+ const count = readdirSync5(skillsDir).length;
2741
2706
  console.log(chalk7.green(" \u2713") + ` ${skillsDir} \u2014 ${t("doctor_links_valid").replace("{count}", String(count))}`);
2742
2707
  } else {
2743
2708
  console.log(chalk7.yellow(" \u26A0") + ` ${skillsDir} \u2014 ${t("doctor_broken_links").replace("{count}", String(brokenLinks))}`);
@@ -2759,7 +2724,7 @@ async function doctorCommand(options = {}) {
2759
2724
  if (existsSync12(agentsDir)) {
2760
2725
  const brokenLinks = checkBrokenLinks(agentsDir);
2761
2726
  if (brokenLinks === 0) {
2762
- const count = readdirSync4(agentsDir).length;
2727
+ const count = readdirSync5(agentsDir).length;
2763
2728
  console.log(chalk7.green(" \u2713") + ` ${agentsDir} \u2014 ${t("doctor_links_valid").replace("{count}", String(count))}`);
2764
2729
  } else {
2765
2730
  console.log(chalk7.yellow(" \u26A0") + ` ${agentsDir} \u2014 ${t("doctor_broken_links").replace("{count}", String(brokenLinks))}`);
@@ -2781,7 +2746,7 @@ async function doctorCommand(options = {}) {
2781
2746
  console.log();
2782
2747
  console.log(chalk7.bold(` ${t("doctor_config")}`));
2783
2748
  const configFile = getConfigFileName(primaryTool);
2784
- const configPath = join12(process.cwd(), configFile);
2749
+ const configPath = join13(process.cwd(), configFile);
2785
2750
  if (existsSync12(configPath)) {
2786
2751
  console.log(chalk7.green(" \u2713") + ` ${configFile} ${t("doctor_config_exists")}`);
2787
2752
  } else {
@@ -2803,9 +2768,9 @@ async function doctorCommand(options = {}) {
2803
2768
  function checkBrokenLinks(dir) {
2804
2769
  let broken = 0;
2805
2770
  try {
2806
- const entries = readdirSync4(dir);
2771
+ const entries = readdirSync5(dir);
2807
2772
  for (const entry of entries) {
2808
- const fullPath = join12(dir, entry);
2773
+ const fullPath = join13(dir, entry);
2809
2774
  try {
2810
2775
  const stats = lstatSync3(fullPath);
2811
2776
  if (stats.isSymbolicLink()) {
@@ -2824,9 +2789,9 @@ function checkBrokenLinks(dir) {
2824
2789
  function fixBrokenLinks(dir) {
2825
2790
  let fixed = 0;
2826
2791
  try {
2827
- const entries = readdirSync4(dir);
2792
+ const entries = readdirSync5(dir);
2828
2793
  for (const entry of entries) {
2829
- const fullPath = join12(dir, entry);
2794
+ const fullPath = join13(dir, entry);
2830
2795
  try {
2831
2796
  const stats = lstatSync3(fullPath);
2832
2797
  if (stats.isSymbolicLink()) {
@@ -3105,7 +3070,7 @@ async function installPlugins(pluginIds, tool, level, repoPath) {
3105
3070
  }
3106
3071
 
3107
3072
  // src/commands/uninstall.ts
3108
- import { existsSync as existsSync13, unlinkSync as unlinkSync5, rmdirSync as rmdirSync2, readdirSync as readdirSync5, lstatSync as lstatSync4 } from "fs";
3073
+ import { existsSync as existsSync13, unlinkSync as unlinkSync5, rmdirSync as rmdirSync2, readdirSync as readdirSync6, lstatSync as lstatSync4 } from "fs";
3109
3074
  import chalk10 from "chalk";
3110
3075
  async function uninstallCommand(names, options) {
3111
3076
  const tool = options.tool ? validateTool(options.tool) : "opencode";
@@ -3156,7 +3121,7 @@ async function uninstallCommand(names, options) {
3156
3121
  continue;
3157
3122
  }
3158
3123
  if (existsSync13(dirPath)) {
3159
- const entries = readdirSync5(dirPath);
3124
+ const entries = readdirSync6(dirPath);
3160
3125
  if (entries.length === 0) {
3161
3126
  rmdirSync2(dirPath);
3162
3127
  const name = dirPath.split("/").pop() || dirPath;
@@ -3300,8 +3265,8 @@ async function updateCommand(pluginNames, options) {
3300
3265
 
3301
3266
  // src/commands/info.ts
3302
3267
  import chalk12 from "chalk";
3303
- import { existsSync as existsSync14, readdirSync as readdirSync6 } from "fs";
3304
- import { join as join13 } from "path";
3268
+ import { existsSync as existsSync14, readdirSync as readdirSync7 } from "fs";
3269
+ import { join as join14 } from "path";
3305
3270
  async function infoCommand(pluginName) {
3306
3271
  const plugin = findPlugin(pluginName);
3307
3272
  if (!plugin) {
@@ -3325,13 +3290,13 @@ async function infoCommand(pluginName) {
3325
3290
  try {
3326
3291
  const repoManager = createRepositoryManager();
3327
3292
  const repoPath = await repoManager.ensureRepo();
3328
- const quickstartPath = join13(repoPath, plugin.dir, "quickstart.md");
3293
+ const quickstartPath = join14(repoPath, plugin.dir, "quickstart.md");
3329
3294
  if (existsSync14(quickstartPath)) {
3330
3295
  console.log(` ${chalk12.dim(t("info_quickstart") + ":")} ${quickstartPath}`);
3331
3296
  }
3332
- const agentsDir = join13(repoPath, plugin.dir, "agents");
3297
+ const agentsDir = join14(repoPath, plugin.dir, "agents");
3333
3298
  if (existsSync14(agentsDir)) {
3334
- const agentFiles = readdirSync6(agentsDir).filter((f) => f.endsWith(".md"));
3299
+ const agentFiles = readdirSync7(agentsDir).filter((f) => f.endsWith(".md"));
3335
3300
  if (agentFiles.length > 0) {
3336
3301
  console.log();
3337
3302
  console.log(` ${chalk12.bold("Agents:")}`);
@@ -3388,7 +3353,7 @@ function createCLI() {
3388
3353
  setLanguage(config.language);
3389
3354
  }
3390
3355
  const program2 = new Command();
3391
- program2.name("install-helper").description("CANNBot Install Helper - Interactive installer for CANN operator development skills").version("0.0.2-beta.15");
3356
+ program2.name("install-helper").description("CANNBot Install Helper - Interactive installer for CANN operator development skills").version("0.0.2-beta.16");
3392
3357
  program2.command("init", { isDefault: false }).description("Run interactive installation wizard").action(async () => {
3393
3358
  await initCommand();
3394
3359
  });