@cannbot-ai/install-helper 0.0.1-beta.1 → 0.0.1-beta.3

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
@@ -471,7 +471,11 @@ var zh_CN = {
471
471
  wizard_back: "\u8FD4\u56DE",
472
472
  wizard_cancel: "\u9000\u51FA",
473
473
  wizard_no_selection: "\u672A\u9009\u62E9\u4EFB\u4F55\u9879\uFF0C\u8BF7\u9009\u62E9\u64CD\u4F5C",
474
- wizard_back_to_reselect: "\u8FD4\u56DE"
474
+ wizard_back_to_reselect: "\u8FD4\u56DE",
475
+ status_title: "\u5DF2\u5B89\u88C5\u63D2\u4EF6",
476
+ status_none: "\u6682\u65E0\u5DF2\u5B89\u88C5\u7684\u63D2\u4EF6",
477
+ status_hint: "\u8FD0\u884C install-helper init \u5F00\u59CB\u5B89\u88C5",
478
+ status_install_time: "\u5B89\u88C5\u65F6\u95F4"
475
479
  };
476
480
  var en_US = {
477
481
  wizard_title: "CANNBot Skills Setup Wizard",
@@ -552,7 +556,11 @@ var en_US = {
552
556
  wizard_back: "Go back",
553
557
  wizard_cancel: "Cancel installation",
554
558
  wizard_no_selection: "No items selected, please choose an action",
555
- wizard_back_to_reselect: "Go back"
559
+ wizard_back_to_reselect: "Go back",
560
+ status_title: "Installed Plugins",
561
+ status_none: "No installed plugins",
562
+ status_hint: "Run install-helper init to start",
563
+ status_install_time: "Installed at"
556
564
  };
557
565
  var currentLang = "zh_CN";
558
566
  function setLanguage(lang) {
@@ -593,7 +601,7 @@ function getDisplayWidth(str) {
593
601
  let width = 0;
594
602
  for (const ch of str) {
595
603
  const code = ch.codePointAt(0);
596
- if (code >= 11904 && code <= 40959 || code >= 63744 && code <= 64255 || code >= 65072 && code <= 65103 || code >= 65280 && code <= 65519) {
604
+ if (code >= 11904 && code <= 40959 || code >= 63744 && code <= 64255 || code >= 65072 && code <= 65103 || code >= 65280 && code <= 65519 || code >= 13312 && code <= 19903 || code >= 131072 && code <= 173791 || code >= 173824 && code <= 177983 || code >= 177984 && code <= 178207 || code >= 178208 && code <= 183983) {
597
605
  width += 2;
598
606
  } else {
599
607
  width += 1;
@@ -705,7 +713,7 @@ var checkboxTheme = {
705
713
 
706
714
  // src/ui/wizard.ts
707
715
  var BACK = "__back__";
708
- var CANCEL = "__cancel__";
716
+ var CANCEL2 = "__cancel__";
709
717
  async function selectToolWithDetection() {
710
718
  const config = readConfig();
711
719
  logger.blank();
@@ -715,7 +723,7 @@ async function selectToolWithDetection() {
715
723
  spinner.stop();
716
724
  const result = await stepTool(detectedTools, config.lastTool);
717
725
  if (result === BACK) return "back";
718
- if (result === CANCEL) return "cancel";
726
+ if (result === CANCEL2) return "cancel";
719
727
  return result;
720
728
  }
721
729
  async function runWizard() {
@@ -736,7 +744,7 @@ async function runWizard() {
736
744
  if (result === BACK) {
737
745
  return { language: config.language || "zh_CN", tool: "opencode", level: "project", plugins: [], confirmed: false, back: true };
738
746
  }
739
- if (result === CANCEL) {
747
+ if (result === CANCEL2) {
740
748
  return { language: config.language || "zh_CN", tool: "opencode", level: "project", plugins: [], confirmed: false };
741
749
  }
742
750
  selectedTool = result;
@@ -749,7 +757,7 @@ async function runWizard() {
749
757
  step = 0;
750
758
  break;
751
759
  }
752
- if (result === CANCEL) {
760
+ if (result === CANCEL2) {
753
761
  return { language: config.language || "zh_CN", tool: selectedTool, level: "project", plugins: [], confirmed: false };
754
762
  }
755
763
  level = result;
@@ -762,7 +770,7 @@ async function runWizard() {
762
770
  step = 1;
763
771
  break;
764
772
  }
765
- if (result === CANCEL) {
773
+ if (result === CANCEL2) {
766
774
  return { language: config.language || "zh_CN", tool: selectedTool, level, plugins: [], confirmed: false };
767
775
  }
768
776
  plugins = result;
@@ -775,7 +783,7 @@ async function runWizard() {
775
783
  step = 2;
776
784
  break;
777
785
  }
778
- if (result === CANCEL || result === false) {
786
+ if (result === CANCEL2 || result === false) {
779
787
  return { language: config.language || "zh_CN", tool: selectedTool, level, plugins: [], confirmed: false };
780
788
  }
781
789
  updateConfig({ lastTool: selectedTool, lastLevel: level });
@@ -795,12 +803,12 @@ async function stepTool(detectedTools, lastTool) {
795
803
  })),
796
804
  new Separator("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
797
805
  { name: "<- " + t("wizard_back"), value: BACK },
798
- { name: "x " + t("wizard_cancel"), value: CANCEL }
806
+ { name: "x " + t("wizard_cancel"), value: CANCEL2 }
799
807
  ];
800
808
  showOperationHints();
801
809
  const result2 = await select({ message: t("wizard_select_tool"), choices: choices2, default: lastTool, loop: false, theme: selectTheme });
802
810
  if (result2 === BACK) return BACK;
803
- if (result2 === CANCEL) return CANCEL;
811
+ if (result2 === CANCEL2) return CANCEL2;
804
812
  return result2;
805
813
  }
806
814
  if (detectedTools.length === 1) {
@@ -815,12 +823,12 @@ async function stepTool(detectedTools, lastTool) {
815
823
  { name: `> ${t("wizard_select_tool")}`, value: "manual" },
816
824
  new Separator("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
817
825
  { name: "<- " + t("wizard_back"), value: BACK },
818
- { name: "x " + t("wizard_cancel"), value: CANCEL }
826
+ { name: "x " + t("wizard_cancel"), value: CANCEL2 }
819
827
  ];
820
828
  showOperationHints();
821
829
  const result2 = await select({ message: t("wizard_select_tool"), choices: choices2, loop: false, theme: selectTheme });
822
830
  if (result2 === BACK) return BACK;
823
- if (result2 === CANCEL) return CANCEL;
831
+ if (result2 === CANCEL2) return CANCEL2;
824
832
  if (result2 === "manual") {
825
833
  return stepToolManual(lastTool);
826
834
  }
@@ -836,11 +844,11 @@ async function stepTool(detectedTools, lastTool) {
836
844
  });
837
845
  choices.push(new Separator("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
838
846
  choices.push({ name: "<- " + t("wizard_back"), value: BACK });
839
- choices.push({ name: "x " + t("wizard_cancel"), value: CANCEL });
847
+ choices.push({ name: "x " + t("wizard_cancel"), value: CANCEL2 });
840
848
  showOperationHints();
841
849
  const result = await select({ message: t("wizard_select_tool"), choices, default: lastTool, loop: false, theme: selectTheme });
842
850
  if (result === BACK) return BACK;
843
- if (result === CANCEL) return CANCEL;
851
+ if (result === CANCEL2) return CANCEL2;
844
852
  return result;
845
853
  }
846
854
  async function stepToolManual(lastTool) {
@@ -851,12 +859,12 @@ async function stepToolManual(lastTool) {
851
859
  })),
852
860
  new Separator("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
853
861
  { name: "<- " + t("wizard_back"), value: BACK },
854
- { name: "x " + t("wizard_cancel"), value: CANCEL }
862
+ { name: "x " + t("wizard_cancel"), value: CANCEL2 }
855
863
  ];
856
864
  showOperationHints();
857
865
  const result = await select({ message: t("wizard_select_tool"), choices, default: lastTool, loop: false, theme: selectTheme });
858
866
  if (result === BACK) return BACK;
859
- if (result === CANCEL) return CANCEL;
867
+ if (result === CANCEL2) return CANCEL2;
860
868
  return result;
861
869
  }
862
870
  async function stepLevel(lastLevel) {
@@ -866,7 +874,7 @@ async function stepLevel(lastLevel) {
866
874
  { name: "> global \u2014 \u5B89\u88C5\u5230\u5168\u5C40\uFF08\u6240\u6709\u9879\u76EE\u5171\u4EAB\uFF09", value: "global" },
867
875
  new Separator("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
868
876
  { name: "<- " + t("wizard_back"), value: BACK },
869
- { name: "x " + t("wizard_cancel"), value: CANCEL }
877
+ { name: "x " + t("wizard_cancel"), value: CANCEL2 }
870
878
  ];
871
879
  showOperationHints();
872
880
  const result = await select({
@@ -877,7 +885,7 @@ async function stepLevel(lastLevel) {
877
885
  theme: selectTheme
878
886
  });
879
887
  if (result === BACK) return BACK;
880
- if (result === CANCEL) return CANCEL;
888
+ if (result === CANCEL2) return CANCEL2;
881
889
  return result;
882
890
  }
883
891
  async function stepPlugins(tool, level) {
@@ -897,7 +905,7 @@ async function stepPlugins(tool, level) {
897
905
  });
898
906
  choices.push(new Separator("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
899
907
  choices.push({ name: "<- " + t("wizard_back"), value: BACK, checked: false });
900
- choices.push({ name: "x " + t("wizard_cancel"), value: CANCEL, checked: false });
908
+ choices.push({ name: "x " + t("wizard_cancel"), value: CANCEL2, checked: false });
901
909
  showOperationHints(true);
902
910
  const selected = await checkbox({
903
911
  message: t("wizard_select_plugins"),
@@ -907,8 +915,8 @@ async function stepPlugins(tool, level) {
907
915
  theme: checkboxTheme
908
916
  });
909
917
  if (selected.includes(BACK)) return BACK;
910
- if (selected.includes(CANCEL)) return CANCEL;
911
- const pluginIds = selected.filter((v) => v !== BACK && v !== CANCEL);
918
+ if (selected.includes(CANCEL2)) return CANCEL2;
919
+ const pluginIds = selected.filter((v) => v !== BACK && v !== CANCEL2);
912
920
  if (pluginIds.length === 0) {
913
921
  const action = await select({
914
922
  message: t("wizard_no_selection"),
@@ -921,7 +929,7 @@ async function stepPlugins(tool, level) {
921
929
  theme: selectTheme
922
930
  });
923
931
  if (action === "back") return BACK;
924
- return CANCEL;
932
+ return CANCEL2;
925
933
  }
926
934
  return pluginIds;
927
935
  }
@@ -929,7 +937,7 @@ async function stepConfirm(tool, level, plugins) {
929
937
  printBoxTitle("\u786E\u8BA4\u5B89\u88C5");
930
938
  const allPlugins = getAllPlugins();
931
939
  const selectedPlugins = plugins.map((id) => allPlugins.find((p) => p.id === id));
932
- const displayPath = level === "project" ? `.${tool}/` : getConfigRoot(tool, level);
940
+ const displayPath = getConfigRoot(tool, level);
933
941
  logger.info(`\u5373\u5C06\u5B89\u88C5 ${chalk2.bold(plugins.length)} \u4E2A\u573A\u666F\u5230 ${chalk2.cyan(displayPath)}\uFF1A`);
934
942
  for (const plugin of selectedPlugins) {
935
943
  if (plugin) {
@@ -941,12 +949,12 @@ async function stepConfirm(tool, level, plugins) {
941
949
  { name: "> " + t("wizard_confirm"), value: "confirm" },
942
950
  new Separator("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
943
951
  { name: "<- " + t("wizard_back"), value: BACK },
944
- { name: "x " + t("wizard_cancel"), value: CANCEL }
952
+ { name: "x " + t("wizard_cancel"), value: CANCEL2 }
945
953
  ];
946
954
  showOperationHints();
947
955
  const result = await select({ message: t("wizard_confirm"), choices, loop: false, theme: selectTheme });
948
956
  if (result === BACK) return BACK;
949
- if (result === CANCEL) return CANCEL;
957
+ if (result === CANCEL2) return CANCEL2;
950
958
  return true;
951
959
  }
952
960
 
@@ -968,8 +976,16 @@ var EXCLUDE_DIRS = /* @__PURE__ */ new Set([
968
976
  ".agents",
969
977
  ".opencode",
970
978
  ".claude",
979
+ ".claude-plugin",
971
980
  "dist",
972
- "build"
981
+ "build",
982
+ "references",
983
+ "hooks",
984
+ "operators",
985
+ "workflows",
986
+ "tests",
987
+ "docs",
988
+ "scripts"
973
989
  ]);
974
990
  var SKILL_SCAN_DIRS = [
975
991
  "ops",
@@ -1044,6 +1060,17 @@ function getCurrentCommit(repoPath) {
1044
1060
  if (existsSync5(refPath)) {
1045
1061
  return readFileSync3(refPath, "utf-8").trim();
1046
1062
  }
1063
+ const packedRefsPath = join5(repoPath, ".git", "packed-refs");
1064
+ if (existsSync5(packedRefsPath)) {
1065
+ const packedRefs = readFileSync3(packedRefsPath, "utf-8");
1066
+ const refName = headContent.slice(5);
1067
+ const lines = packedRefs.split("\n");
1068
+ for (const line of lines) {
1069
+ if (line.endsWith(refName)) {
1070
+ return line.split(" ")[0];
1071
+ }
1072
+ }
1073
+ }
1047
1074
  }
1048
1075
  return headContent;
1049
1076
  } catch {
@@ -1080,6 +1107,20 @@ function getCachePath() {
1080
1107
  return join5(homeDir, ".cannbot", "scan-cache.json");
1081
1108
  }
1082
1109
  function scanDirectory(dirPath, repoPath, sourcePrefix, skills, seen) {
1110
+ const selfSkillMd = join5(dirPath, "SKILL.md");
1111
+ if (existsSync5(selfSkillMd)) {
1112
+ const frontmatter = parseFrontmatter(selfSkillMd);
1113
+ if (frontmatter && !seen.has(frontmatter.name)) {
1114
+ seen.add(frontmatter.name);
1115
+ skills.push({
1116
+ id: frontmatter.name,
1117
+ description: frontmatter.description,
1118
+ source: sourcePrefix,
1119
+ filePath: selfSkillMd
1120
+ });
1121
+ }
1122
+ return;
1123
+ }
1083
1124
  for (const entry of safeReaddir(dirPath)) {
1084
1125
  const fullPath = join5(dirPath, entry);
1085
1126
  if (EXCLUDE_DIRS.has(entry)) continue;
@@ -1215,7 +1256,7 @@ var STATIC_SKILL_CATEGORIES = [
1215
1256
  { id: "cuda2ascend-simt", description: "CUDA \u8FC1\u79FB\u5230 Ascend C SIMT", source: "ops-lab" },
1216
1257
  { id: "ops-direct-invoke-flash", description: "\u4ECE\u96F6\u6784\u5EFA Ascend C \u6838\u51FD\u6570", source: "plugins-official/ops-direct-invoke-flash/skills" },
1217
1258
  { id: "ops-registry-invoke-workflow", description: "\u6CE8\u518C\u8C03\u7528\u5DE5\u4F5C\u6D41", source: "plugins-official/ops-registry-invoke" },
1218
- { id: "ops-easyasc-dsl", description: "EasyASC DSL \u7B97\u5B50\u5F00\u53D1", source: "plugins-community/ops-easyasc-dsl" }
1259
+ { id: "ops-easyasc-dsl", description: "EasyASC DSL \u7B97\u5B50\u5F00\u53D1", source: "plugins-community/ops-easyasc-dsl/skill" }
1219
1260
  ]
1220
1261
  },
1221
1262
  {
@@ -1783,8 +1824,8 @@ async function uninstallSkills(skillIds, tool, level) {
1783
1824
  return results;
1784
1825
  }
1785
1826
  async function interactiveSkillSelect() {
1786
- const BACK2 = "__back__";
1787
- const CANCEL2 = "__cancel__";
1827
+ const BACK3 = "__back__";
1828
+ const CANCEL3 = "__cancel__";
1788
1829
  const categories = getAllCategories();
1789
1830
  let step = 0;
1790
1831
  let selectedCategoryId = "";
@@ -1798,8 +1839,8 @@ async function interactiveSkillSelect() {
1798
1839
  value: cat.id
1799
1840
  })),
1800
1841
  new Separator2("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
1801
- { name: "<- " + t("wizard_back"), value: BACK2 },
1802
- { name: "x " + t("wizard_cancel"), value: CANCEL2 }
1842
+ { name: "<- " + t("wizard_back"), value: BACK3 },
1843
+ { name: "x " + t("wizard_cancel"), value: CANCEL3 }
1803
1844
  ];
1804
1845
  showOperationHints();
1805
1846
  selectedCategoryId = await select2({
@@ -1808,8 +1849,8 @@ async function interactiveSkillSelect() {
1808
1849
  loop: false,
1809
1850
  theme: selectTheme
1810
1851
  });
1811
- if (selectedCategoryId === BACK2) return "back";
1812
- if (selectedCategoryId === CANCEL2) return "cancel";
1852
+ if (selectedCategoryId === BACK3) return "back";
1853
+ if (selectedCategoryId === CANCEL3) return "cancel";
1813
1854
  step = 1;
1814
1855
  break;
1815
1856
  }
@@ -1820,10 +1861,10 @@ async function interactiveSkillSelect() {
1820
1861
  const tools = ["opencode", "claude", "trae", "cursor", "copilot"];
1821
1862
  const levels = ["project", "global"];
1822
1863
  const installedSkills = [];
1823
- for (const t2 of tools) {
1864
+ for (const tk of tools) {
1824
1865
  for (const l of levels) {
1825
- const path = l === "project" ? process.cwd() : getConfigRoot(t2, l);
1826
- installedSkills.push(...getInstalledSkills(t2, l, path));
1866
+ const path = l === "project" ? process.cwd() : getConfigRoot(tk, l);
1867
+ installedSkills.push(...getInstalledSkills(tk, l, path));
1827
1868
  }
1828
1869
  }
1829
1870
  const installedSet = new Set(installedSkills);
@@ -1837,8 +1878,8 @@ async function interactiveSkillSelect() {
1837
1878
  };
1838
1879
  });
1839
1880
  skillChoices.push(new Separator2("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
1840
- skillChoices.push({ name: "<- " + t("wizard_back"), value: BACK2, checked: false });
1841
- skillChoices.push({ name: "x " + t("wizard_cancel"), value: CANCEL2, checked: false });
1881
+ skillChoices.push({ name: "<- " + t("wizard_back"), value: BACK3, checked: false });
1882
+ skillChoices.push({ name: "x " + t("wizard_cancel"), value: CANCEL3, checked: false });
1842
1883
  showOperationHints(true);
1843
1884
  const selectedSkills = await checkbox2({
1844
1885
  message: t("skill_select_items"),
@@ -1847,12 +1888,12 @@ async function interactiveSkillSelect() {
1847
1888
  instructions: false,
1848
1889
  theme: checkboxTheme
1849
1890
  });
1850
- if (selectedSkills.includes(BACK2)) {
1891
+ if (selectedSkills.includes(BACK3)) {
1851
1892
  step = 0;
1852
1893
  break;
1853
1894
  }
1854
- if (selectedSkills.includes(CANCEL2)) return "cancel";
1855
- const skillIds = selectedSkills.filter((v) => v !== BACK2 && v !== CANCEL2);
1895
+ if (selectedSkills.includes(CANCEL3)) return "cancel";
1896
+ const skillIds = selectedSkills.filter((v) => v !== BACK3 && v !== CANCEL3);
1856
1897
  if (skillIds.length === 0) {
1857
1898
  const action = await select2({
1858
1899
  message: t("wizard_no_selection"),
@@ -1995,6 +2036,7 @@ function printEnhancedSummary(results, tool, configRoot) {
1995
2036
  // src/commands/init.ts
1996
2037
  import { existsSync as existsSync10, readFileSync as readFileSync5 } from "fs";
1997
2038
  import { join as join10 } from "path";
2039
+ var BACK2 = "__back__";
1998
2040
  async function initCommand() {
1999
2041
  const cwd = process.cwd();
2000
2042
  if (existsSync10(join10(cwd, "package.json")) && (() => {
@@ -2053,7 +2095,7 @@ async function initCommand() {
2053
2095
  }
2054
2096
  async function selectMode() {
2055
2097
  printBoxTitle("\u9009\u62E9\u5B89\u88C5\u7C7B\u578B");
2056
- const CANCEL2 = "__cancel__";
2098
+ const CANCEL3 = "__cancel__";
2057
2099
  const choices = [
2058
2100
  {
2059
2101
  name: `> ${t("wizard_mode_plugin")} \u2014 ${t("wizard_mode_plugin_desc")}`,
@@ -2064,7 +2106,7 @@ async function selectMode() {
2064
2106
  value: "skill"
2065
2107
  },
2066
2108
  new Separator3("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
2067
- { name: "x " + t("wizard_cancel"), value: CANCEL2 }
2109
+ { name: "x " + t("wizard_cancel"), value: CANCEL3 }
2068
2110
  ];
2069
2111
  showOperationHints();
2070
2112
  const result = await select3({
@@ -2073,7 +2115,7 @@ async function selectMode() {
2073
2115
  loop: false,
2074
2116
  theme: selectTheme
2075
2117
  });
2076
- if (result === CANCEL2) return null;
2118
+ if (result === CANCEL3) return null;
2077
2119
  return result;
2078
2120
  }
2079
2121
  async function pluginInstallFlow() {
@@ -2134,6 +2176,7 @@ async function pluginInstallFlow() {
2134
2176
  async function skillInstallFlow() {
2135
2177
  let step = 0;
2136
2178
  let tool = "opencode";
2179
+ let level = "project";
2137
2180
  while (true) {
2138
2181
  switch (step) {
2139
2182
  case 0: {
@@ -2148,9 +2191,23 @@ async function skillInstallFlow() {
2148
2191
  break;
2149
2192
  }
2150
2193
  case 1: {
2194
+ const result = await stepLevel();
2195
+ if (result === BACK2) {
2196
+ step = 0;
2197
+ break;
2198
+ }
2199
+ if (result === CANCEL) {
2200
+ logger.info("\u5DF2\u53D6\u6D88\u5B89\u88C5");
2201
+ return "done";
2202
+ }
2203
+ level = result;
2204
+ step = 2;
2205
+ break;
2206
+ }
2207
+ case 2: {
2151
2208
  const selectedSkills = await interactiveSkillSelect();
2152
2209
  if (selectedSkills === "back") {
2153
- step = 0;
2210
+ step = 1;
2154
2211
  break;
2155
2212
  }
2156
2213
  if (selectedSkills === "cancel") {
@@ -2167,7 +2224,7 @@ async function skillInstallFlow() {
2167
2224
  const repoPath = await repoManager.ensureRepo();
2168
2225
  spinner.succeed(t("install_repo_ready"));
2169
2226
  logger.info(`${t("skill_install_progress")} ${chalk5.bold(selectedSkills.length)} \u4E2A Skills...`);
2170
- const results = await installSkills(selectedSkills, tool, "project", repoPath);
2227
+ const results = await installSkills(selectedSkills, tool, level, repoPath);
2171
2228
  let successCount = 0;
2172
2229
  let failCount = 0;
2173
2230
  for (const result of results) {
@@ -2179,7 +2236,7 @@ async function skillInstallFlow() {
2179
2236
  failCount++;
2180
2237
  }
2181
2238
  }
2182
- const configRoot = getConfigRoot(tool, "project");
2239
+ const configRoot = getConfigRoot(tool, level);
2183
2240
  logger.blank();
2184
2241
  logger.success(`${t("skill_install_done")}: ${chalk5.green(successCount + " \u6210\u529F")}, ${failCount > 0 ? chalk5.red(failCount + " \u5931\u8D25") : chalk5.dim(failCount + " \u5931\u8D25")}`);
2185
2242
  logger.blank();
@@ -2367,11 +2424,11 @@ async function statusCommand() {
2367
2424
  const installed = scanInstalled();
2368
2425
  const installedMap = new Map(installed.map((p) => [p.id, p]));
2369
2426
  console.log();
2370
- console.log(chalk7.bold(" \u5DF2\u5B89\u88C5\u63D2\u4EF6"));
2427
+ console.log(chalk7.bold(` ${t("status_title")}`));
2371
2428
  console.log();
2372
2429
  if (installed.length === 0) {
2373
- console.log(chalk7.dim(" \u6682\u65E0\u5DF2\u5B89\u88C5\u7684\u63D2\u4EF6"));
2374
- console.log(chalk7.dim(" \u8FD0\u884C install-helper init \u5F00\u59CB\u5B89\u88C5"));
2430
+ console.log(chalk7.dim(` ${t("status_none")}`));
2431
+ console.log(chalk7.dim(` ${t("status_hint")}`));
2375
2432
  console.log();
2376
2433
  return;
2377
2434
  }
@@ -2383,7 +2440,7 @@ async function statusCommand() {
2383
2440
  chalk7.dim(` ${inst.skillsCount} skills, ${inst.agentsCount} agents`)
2384
2441
  );
2385
2442
  console.log(chalk7.dim(` ${inst.configRoot}`));
2386
- console.log(chalk7.dim(` \u5B89\u88C5\u65F6\u95F4: ${inst.installTime}`));
2443
+ console.log(chalk7.dim(` ${t("status_install_time")}: ${inst.installTime}`));
2387
2444
  console.log();
2388
2445
  }
2389
2446
  }
@@ -2402,6 +2459,15 @@ async function installCommand(names, options) {
2402
2459
  return;
2403
2460
  }
2404
2461
  if (names.length === 0) {
2462
+ const scanSpinner2 = createSpinner("\u6B63\u5728\u52A0\u8F7D Skills \u5217\u8868...");
2463
+ scanSpinner2.start();
2464
+ try {
2465
+ const scanRepoManager = createRepositoryManager();
2466
+ await scanRepoManager.ensureRepoAndScan();
2467
+ scanSpinner2.succeed("Skills \u5217\u8868\u52A0\u8F7D\u5B8C\u6210");
2468
+ } catch {
2469
+ scanSpinner2.warn("Skills \u5217\u8868\u52A0\u8F7D\u5931\u8D25\uFF0C\u5C06\u4F7F\u7528\u5185\u7F6E\u6570\u636E");
2470
+ }
2405
2471
  let tool2;
2406
2472
  if (options.tool) {
2407
2473
  tool2 = options.tool;
@@ -2432,7 +2498,8 @@ async function installCommand(names, options) {
2432
2498
  const repoPath = await repoManager.ensureRepo();
2433
2499
  spinner.succeed(t("install_repo_ready"));
2434
2500
  logger.info(`${t("skill_install_progress")} ${chalk8.bold(names.length)} \u4E2A Skills...`);
2435
- const results = await installSkills(names, tool2, "project", repoPath);
2501
+ const level2 = options.level || "project";
2502
+ const results = await installSkills(names, tool2, level2, repoPath);
2436
2503
  let successCount = 0;
2437
2504
  let failCount = 0;
2438
2505
  for (const result of results) {
@@ -2444,7 +2511,7 @@ async function installCommand(names, options) {
2444
2511
  failCount++;
2445
2512
  }
2446
2513
  }
2447
- const configRoot = getConfigRoot(tool2, "project");
2514
+ const configRoot = getConfigRoot(tool2, level2);
2448
2515
  logger.blank();
2449
2516
  logger.success(`${t("skill_install_done")}: ${chalk8.green(successCount + " \u6210\u529F")}, ${failCount > 0 ? chalk8.red(failCount + " \u5931\u8D25") : chalk8.dim(failCount + " \u5931\u8D25")}`);
2450
2517
  logger.blank();
@@ -2732,6 +2799,7 @@ async function updateCommand(pluginNames, options) {
2732
2799
  updateSpinner.start();
2733
2800
  await repoManager.updateRepo();
2734
2801
  const repoPath = repoManager.getRepoPath();
2802
+ await repoManager.ensureRepoAndScan();
2735
2803
  updateSpinner.succeed(t("install_repo_ready"));
2736
2804
  const allPlugins = getAllPlugins();
2737
2805
  const results = [];
@@ -2776,7 +2844,7 @@ async function updateCommand(pluginNames, options) {
2776
2844
 
2777
2845
  // src/commands/info.ts
2778
2846
  import chalk11 from "chalk";
2779
- import { existsSync as existsSync13 } from "fs";
2847
+ import { existsSync as existsSync13, readdirSync as readdirSync6 } from "fs";
2780
2848
  import { join as join12 } from "path";
2781
2849
  async function infoCommand(pluginName) {
2782
2850
  const plugin = findPlugin(pluginName);
@@ -2807,7 +2875,6 @@ async function infoCommand(pluginName) {
2807
2875
  }
2808
2876
  const agentsDir = join12(repoPath, plugin.dir, "agents");
2809
2877
  if (existsSync13(agentsDir)) {
2810
- const { readdirSync: readdirSync6 } = await import("fs");
2811
2878
  const agentFiles = readdirSync6(agentsDir).filter((f) => f.endsWith(".md"));
2812
2879
  if (agentFiles.length > 0) {
2813
2880
  console.log();
@@ -2865,7 +2932,7 @@ function createCLI() {
2865
2932
  setLanguage(config.language);
2866
2933
  }
2867
2934
  const program2 = new Command();
2868
- program2.name("install-helper").description("Install Helper - Interactive installer for CANN operator development skills").version("0.0.1-beta.1");
2935
+ program2.name("install-helper").description("Install Helper - Interactive installer for CANN operator development skills").version("0.0.1-beta.3");
2869
2936
  program2.command("init", { isDefault: false }).description("Run interactive installation wizard").action(async () => {
2870
2937
  await initCommand();
2871
2938
  });