@cannbot-ai/install-helper 0.0.2-beta.6 → 0.0.2-beta.7

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
@@ -4,8 +4,8 @@
4
4
  import { Command } from "commander";
5
5
 
6
6
  // src/commands/init.ts
7
- import { select as select3, Separator as Separator3 } from "@inquirer/prompts";
8
- import chalk5 from "chalk";
7
+ import { select as select4, Separator as Separator3 } from "@inquirer/prompts";
8
+ import chalk6 from "chalk";
9
9
 
10
10
  // src/ui/wizard.ts
11
11
  import { select, checkbox, Separator } from "@inquirer/prompts";
@@ -478,10 +478,40 @@ var zh_CN = {
478
478
  status_install_time: "\u5B89\u88C5\u65F6\u95F4",
479
479
  install_installed_to: "\u5B89\u88C5\u5230",
480
480
  install_skills_count: "Skills",
481
- install_agents_count: "Agents"
481
+ install_agents_count: "Agents",
482
+ lang_supported: "\u652F\u6301\u7684\u8BED\u8A00: zh_CN, en_US",
483
+ lang_usage: "\u7528\u6CD5: install-helper lang set <language>",
484
+ lang_specify: "\u8BF7\u6307\u5B9A\u8BED\u8A00: install-helper lang set zh_CN",
485
+ lang_unknown_action: "\u672A\u77E5\u64CD\u4F5C",
486
+ lang_supported_actions: "\u652F\u6301\u7684\u64CD\u4F5C: show, set",
487
+ info_aliases: "\u522B\u540D",
488
+ uninstall_not_found: "\u672A\u627E\u5230",
489
+ uninstall_no_record: "\u672A\u627E\u5230\u5B89\u88C5\u8BB0\u5F55\uFF0C\u53EF\u80FD\u672A\u5B89\u88C5\u6216\u5B89\u88C5\u8BB0\u5F55\u5DF2\u635F\u574F",
490
+ uninstall_no_record_hint: "\u5982\u9700\u5F3A\u5236\u6E05\u7406\uFF0C\u8BF7\u624B\u52A8\u5220\u9664 .opencode/ \u6216 .claude/ \u76EE\u5F55\u4E2D\u7684\u76F8\u5173\u6587\u4EF6",
491
+ uninstall_in_progress: "\u6B63\u5728\u5378\u8F7D",
492
+ uninstall_removed: "\u5DF2\u5378\u8F7D",
493
+ uninstall_files_gone: "\u7684\u6587\u4EF6\u5DF2\u4E0D\u5B58\u5728\uFF0C\u5DF2\u6E05\u7406\u5B89\u88C5\u8BB0\u5F55",
494
+ uninstall_skills_in_progress: "\u6B63\u5728\u5378\u8F7D",
495
+ init_pkg_dir_warn: "\u5F53\u524D\u76EE\u5F55\u770B\u8D77\u6765\u662F install-helper \u5305\u76EE\u5F55",
496
+ init_pkg_dir_hint: "\u8BF7\u5728\u4F60\u7684\u9879\u76EE\u76EE\u5F55\u4E2D\u8FD0\u884C\u6B64\u547D\u4EE4\uFF0C\u800C\u4E0D\u662F\u5728 install-helper \u5B89\u88C5\u76EE\u5F55\u4E2D",
497
+ init_pkg_dir_example: "\u793A\u4F8B\uFF1Acd ~/my-project && install-helper",
498
+ init_cancelled: "\u5DF2\u53D6\u6D88\u5B89\u88C5",
499
+ backup_detected: "\u68C0\u6D4B\u5230\u5F53\u524D\u76EE\u5F55\u5DF2\u5B89\u88C5\u63D2\u4EF6",
500
+ backup_current: "\u5F53\u524D\u5B89\u88C5",
501
+ backup_installing: "\u5373\u5C06\u5B89\u88C5",
502
+ backup_overwrite_warning: "\u7EE7\u7EED\u5B89\u88C5\u5C06\u8986\u76D6\u73B0\u6709\u7684 AGENTS.md \u914D\u7F6E\u6587\u4EF6\u3002",
503
+ backup_auto_create: "\u7CFB\u7EDF\u4F1A\u81EA\u52A8\u521B\u5EFA\u5907\u4EFD\uFF0C\u4EE5\u4FBF\u540E\u7EED\u6062\u590D\u3002",
504
+ backup_overwrite: "\u8986\u76D6\u5B89\u88C5\uFF08\u81EA\u52A8\u5907\u4EFD\uFF09",
505
+ backup_cancel: "\u53D6\u6D88\u5B89\u88C5",
506
+ backup_restore_prompt: "\u68C0\u6D4B\u5230\u5907\u4EFD\u914D\u7F6E\uFF0C\u662F\u5426\u6062\u590D\uFF1F",
507
+ backup_restore: "\u6062\u590D",
508
+ backup_only_uninstall: "\u4EC5\u5378\u8F7D\uFF08\u4E0D\u6062\u590D\uFF09",
509
+ backup_select_action: "\u8BF7\u9009\u62E9\u64CD\u4F5C",
510
+ backup_restore_success: "\u5DF2\u6062\u590D\u914D\u7F6E",
511
+ backup_created: "\u5DF2\u521B\u5EFA\u5907\u4EFD"
482
512
  };
483
513
  var en_US = {
484
- wizard_title: "CANNBot Skills Setup Wizard",
514
+ wizard_title: "CANNBot Install Helper",
485
515
  wizard_detect: "Detecting installed AI coding tools...",
486
516
  wizard_select_tool: "Select AI coding tool",
487
517
  wizard_select_level: "Select install level",
@@ -566,7 +596,37 @@ var en_US = {
566
596
  status_install_time: "Installed at",
567
597
  install_installed_to: "Installed to",
568
598
  install_skills_count: "Skills",
569
- install_agents_count: "Agents"
599
+ install_agents_count: "Agents",
600
+ lang_supported: "Supported languages: zh_CN, en_US",
601
+ lang_usage: "Usage: install-helper lang set <language>",
602
+ lang_specify: "Please specify language: install-helper lang set zh_CN",
603
+ lang_unknown_action: "Unknown action",
604
+ lang_supported_actions: "Supported actions: show, set",
605
+ info_aliases: "Aliases",
606
+ uninstall_not_found: "Not found",
607
+ uninstall_no_record: "No install record found, may not be installed or record is corrupted",
608
+ uninstall_no_record_hint: "For manual cleanup, delete related files in .opencode/ or .claude/ directory",
609
+ uninstall_in_progress: "Uninstalling",
610
+ uninstall_removed: "Uninstalled",
611
+ uninstall_files_gone: " files no longer exist, install record cleaned",
612
+ uninstall_skills_in_progress: "Uninstalling",
613
+ init_pkg_dir_warn: "Current directory appears to be the install-helper package directory",
614
+ init_pkg_dir_hint: "Please run this command in your project directory, not in the install-helper package directory",
615
+ init_pkg_dir_example: "Example: cd ~/my-project && install-helper",
616
+ init_cancelled: "Installation cancelled",
617
+ backup_detected: "Plugin already installed in current directory",
618
+ backup_current: "Currently installed",
619
+ backup_installing: "About to install",
620
+ backup_overwrite_warning: "Continuing will overwrite existing AGENTS.md configuration.",
621
+ backup_auto_create: "System will automatically create backup for future restoration.",
622
+ backup_overwrite: "Overwrite (auto backup)",
623
+ backup_cancel: "Cancel installation",
624
+ backup_restore_prompt: "Backup configuration detected, restore?",
625
+ backup_restore: "Restore",
626
+ backup_only_uninstall: "Uninstall only (no restore)",
627
+ backup_select_action: "Please select an action",
628
+ backup_restore_success: "Configuration restored",
629
+ backup_created: "Backup created"
570
630
  };
571
631
  var currentLang = "zh_CN";
572
632
  function setLanguage(lang) {
@@ -970,7 +1030,7 @@ import { execa as execa2 } from "execa";
970
1030
 
971
1031
  // src/core/scanner.ts
972
1032
  import { existsSync as existsSync5, readdirSync, readFileSync as readFileSync3, statSync, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
973
- import { join as join5, dirname } from "path";
1033
+ import { join as join5 } from "path";
974
1034
  import { parse as parseYaml } from "yaml";
975
1035
  var EXCLUDE_DIRS = /* @__PURE__ */ new Set([
976
1036
  "node_modules",
@@ -1483,8 +1543,8 @@ function createRepositoryManager(customPath) {
1483
1543
  }
1484
1544
 
1485
1545
  // src/core/installer.ts
1486
- import { existsSync as existsSync8 } from "fs";
1487
- import { join as join8 } from "path";
1546
+ import { existsSync as existsSync9 } from "fs";
1547
+ import { join as join9 } from "path";
1488
1548
  import { execa as execa3 } from "execa";
1489
1549
 
1490
1550
  // src/core/record.ts
@@ -1658,6 +1718,179 @@ function getInstalledSkills(tool, level, installPath) {
1658
1718
  return record[tool]?.[level]?.[installPath]?.skills || [];
1659
1719
  }
1660
1720
 
1721
+ // src/core/backup.ts
1722
+ import { existsSync as existsSync8, copyFileSync, readdirSync as readdirSync3, unlinkSync as unlinkSync2 } from "fs";
1723
+ import { join as join8 } from "path";
1724
+ function getAgentsFileName(tool) {
1725
+ return tool === "claude" ? "CLAUDE.md" : "AGENTS.md";
1726
+ }
1727
+ function detectCurrentPlugin(configRoot, tool) {
1728
+ const manifest = readManifest(configRoot);
1729
+ if (manifest?.team) {
1730
+ const plugin = findPlugin(manifest.team);
1731
+ if (plugin) {
1732
+ return {
1733
+ pluginId: plugin.id,
1734
+ pluginName: plugin.displayName
1735
+ };
1736
+ }
1737
+ }
1738
+ const agentsFile = join8(configRoot, getAgentsFileName(tool));
1739
+ if (!existsSync8(agentsFile)) {
1740
+ return null;
1741
+ }
1742
+ const allRecords = readAllRecords();
1743
+ for (const record of allRecords) {
1744
+ if (record.configRoot === configRoot && record.tool === tool) {
1745
+ const plugin = findPlugin(record.pluginId);
1746
+ if (plugin) {
1747
+ return {
1748
+ pluginId: plugin.id,
1749
+ pluginName: plugin.displayName
1750
+ };
1751
+ }
1752
+ }
1753
+ }
1754
+ return null;
1755
+ }
1756
+ function createBackup(configRoot, tool, fromPluginId, fromPluginName) {
1757
+ const agentsFile = join8(configRoot, getAgentsFileName(tool));
1758
+ if (!existsSync8(agentsFile)) {
1759
+ return null;
1760
+ }
1761
+ const timestamp = formatTimestamp(/* @__PURE__ */ new Date());
1762
+ const backupFileName = `${getAgentsFileName(tool)}.cannbot-backup.${fromPluginId}.${timestamp}`;
1763
+ const backupPath = join8(configRoot, backupFileName);
1764
+ try {
1765
+ copyFileSync(agentsFile, backupPath);
1766
+ return {
1767
+ filePath: backupPath,
1768
+ pluginId: fromPluginId,
1769
+ pluginName: fromPluginName,
1770
+ backupTime: timestamp
1771
+ };
1772
+ } catch {
1773
+ return null;
1774
+ }
1775
+ }
1776
+ function findBackups(configRoot) {
1777
+ if (!existsSync8(configRoot)) {
1778
+ return [];
1779
+ }
1780
+ const files = readdirSync3(configRoot);
1781
+ const backups = [];
1782
+ for (const file of files) {
1783
+ if (file.includes(".cannbot-backup.")) {
1784
+ const parts = file.split(".cannbot-backup.");
1785
+ if (parts.length === 2) {
1786
+ const pluginIdAndTime = parts[1];
1787
+ const lastDotIndex = pluginIdAndTime.lastIndexOf(".");
1788
+ if (lastDotIndex > 0) {
1789
+ const pluginId = pluginIdAndTime.substring(0, lastDotIndex);
1790
+ const timestamp = pluginIdAndTime.substring(lastDotIndex + 1);
1791
+ const plugin = findPlugin(pluginId);
1792
+ backups.push({
1793
+ filePath: join8(configRoot, file),
1794
+ pluginId,
1795
+ pluginName: plugin?.displayName || pluginId,
1796
+ backupTime: timestamp
1797
+ });
1798
+ }
1799
+ }
1800
+ }
1801
+ }
1802
+ return backups.sort((a, b) => b.backupTime.localeCompare(a.backupTime));
1803
+ }
1804
+ function restoreBackup(backupPath, configRoot, tool) {
1805
+ try {
1806
+ const agentsFile = join8(configRoot, getAgentsFileName(tool));
1807
+ copyFileSync(backupPath, agentsFile);
1808
+ return true;
1809
+ } catch {
1810
+ return false;
1811
+ }
1812
+ }
1813
+ function deleteBackup(backupPath) {
1814
+ try {
1815
+ if (existsSync8(backupPath)) {
1816
+ unlinkSync2(backupPath);
1817
+ return true;
1818
+ }
1819
+ return false;
1820
+ } catch {
1821
+ return false;
1822
+ }
1823
+ }
1824
+ function formatTimestamp(date) {
1825
+ const year = date.getFullYear();
1826
+ const month = String(date.getMonth() + 1).padStart(2, "0");
1827
+ const day = String(date.getDate()).padStart(2, "0");
1828
+ const hours = String(date.getHours()).padStart(2, "0");
1829
+ const minutes = String(date.getMinutes()).padStart(2, "0");
1830
+ const seconds = String(date.getSeconds()).padStart(2, "0");
1831
+ return `${year}${month}${day}-${hours}${minutes}${seconds}`;
1832
+ }
1833
+ function readAllRecords() {
1834
+ const records = [];
1835
+ const plugins = [
1836
+ "ops-direct-invoke",
1837
+ "ops-direct-invoke-flash",
1838
+ "ops-registry-invoke",
1839
+ "pypto-op-orchestrator",
1840
+ "triton-op-generator",
1841
+ "tilelang-op-orchestrator",
1842
+ "model-infer-optimize",
1843
+ "catlass-op-generator",
1844
+ "ops-code-reviewer",
1845
+ "torch-compile"
1846
+ ];
1847
+ for (const pluginId of plugins) {
1848
+ const record = readRecord(pluginId);
1849
+ if (record) {
1850
+ records.push(record);
1851
+ }
1852
+ }
1853
+ return records;
1854
+ }
1855
+
1856
+ // src/ui/backup-prompts.ts
1857
+ import { select as select2 } from "@inquirer/prompts";
1858
+ import chalk3 from "chalk";
1859
+ async function showOverwriteWarning(currentPluginName, newPluginName) {
1860
+ console.log();
1861
+ console.log(chalk3.yellow(` \u26A0\uFE0F ${t("backup_detected")}`));
1862
+ console.log();
1863
+ console.log(` ${t("backup_current")}: ${chalk3.cyan(currentPluginName)}`);
1864
+ console.log(` ${t("backup_installing")}: ${chalk3.cyan(newPluginName)}`);
1865
+ console.log();
1866
+ console.log(` ${t("backup_overwrite_warning")}`);
1867
+ console.log(` ${t("backup_auto_create")}`);
1868
+ console.log();
1869
+ const choice = await select2({
1870
+ message: t("backup_select_action"),
1871
+ choices: [
1872
+ { name: t("backup_overwrite"), value: "overwrite" },
1873
+ { name: t("backup_cancel"), value: "cancel" }
1874
+ ]
1875
+ });
1876
+ return choice;
1877
+ }
1878
+ async function showRestorePrompt(backups) {
1879
+ console.log();
1880
+ console.log(chalk3.cyan(` ${t("backup_restore_prompt")}`));
1881
+ console.log();
1882
+ const choices = backups.map((b) => ({
1883
+ name: `${t("backup_restore")} ${b.pluginName} (${b.backupTime})`,
1884
+ value: b.filePath
1885
+ }));
1886
+ choices.push({ name: t("backup_only_uninstall"), value: "none" });
1887
+ const choice = await select2({
1888
+ message: t("backup_select_action"),
1889
+ choices
1890
+ });
1891
+ return choice;
1892
+ }
1893
+
1661
1894
  // src/core/installer.ts
1662
1895
  async function installPlugin(opts) {
1663
1896
  const plugin = getPluginById(opts.pluginId);
@@ -1671,8 +1904,8 @@ async function installPlugin(opts) {
1671
1904
  warnings: []
1672
1905
  };
1673
1906
  }
1674
- const scriptPath = join8(opts.repoPath, plugin.dir, plugin.script);
1675
- if (!existsSync8(scriptPath)) {
1907
+ const scriptPath = join9(opts.repoPath, plugin.dir, plugin.script);
1908
+ if (!existsSync9(scriptPath)) {
1676
1909
  return {
1677
1910
  success: false,
1678
1911
  pluginId: opts.pluginId,
@@ -1687,13 +1920,44 @@ async function installPlugin(opts) {
1687
1920
  args.push(opts.installPath);
1688
1921
  }
1689
1922
  const cwd = opts.installPath || process.cwd();
1923
+ const configRoot = getConfigRoot(opts.tool, opts.level, opts.installPath);
1924
+ const agentsFile = join9(configRoot, getAgentsFileName(opts.tool));
1925
+ let backupInfo = null;
1926
+ if (existsSync9(agentsFile)) {
1927
+ const currentPlugin = detectCurrentPlugin(configRoot, opts.tool);
1928
+ if (currentPlugin && currentPlugin.pluginId !== opts.pluginId) {
1929
+ const choice = await showOverwriteWarning(
1930
+ currentPlugin.pluginName,
1931
+ plugin.displayName
1932
+ );
1933
+ if (choice === "cancel") {
1934
+ logger.info(t("backup_cancel"));
1935
+ return {
1936
+ success: false,
1937
+ pluginId: opts.pluginId,
1938
+ skillsCount: 0,
1939
+ agentsCount: 0,
1940
+ errors: [t("backup_cancel")],
1941
+ warnings: []
1942
+ };
1943
+ }
1944
+ backupInfo = createBackup(
1945
+ configRoot,
1946
+ opts.tool,
1947
+ currentPlugin.pluginId,
1948
+ currentPlugin.pluginName
1949
+ );
1950
+ if (backupInfo) {
1951
+ logger.success(`${t("backup_created")}: ${backupInfo.filePath}`);
1952
+ }
1953
+ }
1954
+ }
1690
1955
  try {
1691
1956
  await execa3("bash", [scriptPath, ...args], {
1692
1957
  cwd,
1693
1958
  timeout: 3e5,
1694
1959
  stdio: "pipe"
1695
1960
  });
1696
- const configRoot = getConfigRoot(opts.tool, opts.level, opts.installPath);
1697
1961
  const manifest = readManifest(configRoot);
1698
1962
  let skillsCount = 0;
1699
1963
  let agentsCount = 0;
@@ -1714,6 +1978,14 @@ async function installPlugin(opts) {
1714
1978
  configRoot,
1715
1979
  manifest
1716
1980
  );
1981
+ if (backupInfo) {
1982
+ record.backup = {
1983
+ filePath: backupInfo.filePath,
1984
+ fromPluginId: backupInfo.pluginId,
1985
+ fromPluginName: backupInfo.pluginName,
1986
+ backupTime: backupInfo.backupTime
1987
+ };
1988
+ }
1717
1989
  writeRecord(record);
1718
1990
  } catch {
1719
1991
  }
@@ -1739,16 +2011,16 @@ async function installPlugin(opts) {
1739
2011
  }
1740
2012
 
1741
2013
  // src/core/skill-installer.ts
1742
- import { existsSync as existsSync9, mkdirSync as mkdirSync5, symlinkSync, unlinkSync as unlinkSync2, readdirSync as readdirSync3, rmdirSync, realpathSync, lstatSync as lstatSync2 } from "fs";
1743
- import { join as join9 } from "path";
1744
- import { select as select2, checkbox as checkbox2, Separator as Separator2 } from "@inquirer/prompts";
1745
- import chalk3 from "chalk";
2014
+ import { existsSync as existsSync10, mkdirSync as mkdirSync5, symlinkSync, unlinkSync as unlinkSync3, readdirSync as readdirSync4, rmdirSync, realpathSync, lstatSync as lstatSync2 } from "fs";
2015
+ import { join as join10 } from "path";
2016
+ import { select as select3, checkbox as checkbox2, Separator as Separator2 } from "@inquirer/prompts";
2017
+ import chalk4 from "chalk";
1746
2018
  import Table from "cli-table3";
1747
2019
  async function installSkills(skillIds, tool, level, repoPath) {
1748
2020
  const configRoot = getConfigRoot(tool, level);
1749
- const skillsDir = join9(configRoot, "skills");
2021
+ const skillsDir = join10(configRoot, "skills");
1750
2022
  const installPath = level === "project" ? process.cwd() : configRoot;
1751
- if (!existsSync9(skillsDir)) {
2023
+ if (!existsSync10(skillsDir)) {
1752
2024
  mkdirSync5(skillsDir, { recursive: true });
1753
2025
  }
1754
2026
  const results = [];
@@ -1759,15 +2031,15 @@ async function installSkills(skillIds, tool, level, repoPath) {
1759
2031
  results.push({ skillId, success: false, error: "Skill not found in registry" });
1760
2032
  continue;
1761
2033
  }
1762
- const sourcePath = join9(repoPath, skill.source, skill.id);
1763
- const targetPath = join9(skillsDir, skillId);
1764
- if (!existsSync9(sourcePath)) {
2034
+ const sourcePath = join10(repoPath, skill.source, skill.id);
2035
+ const targetPath = join10(skillsDir, skillId);
2036
+ if (!existsSync10(sourcePath)) {
1765
2037
  results.push({ skillId, success: false, error: `Source not found: ${sourcePath}` });
1766
2038
  continue;
1767
2039
  }
1768
2040
  try {
1769
- if (existsSync9(targetPath) || isSymlink2(targetPath)) {
1770
- unlinkSync2(targetPath);
2041
+ if (existsSync10(targetPath) || isSymlink2(targetPath)) {
2042
+ unlinkSync3(targetPath);
1771
2043
  }
1772
2044
  symlinkSync(realpathSync(sourcePath), targetPath);
1773
2045
  results.push({ skillId, success: true });
@@ -1783,15 +2055,15 @@ async function installSkills(skillIds, tool, level, repoPath) {
1783
2055
  }
1784
2056
  async function uninstallSkills(skillIds, tool, level) {
1785
2057
  const configRoot = getConfigRoot(tool, level);
1786
- const skillsDir = join9(configRoot, "skills");
2058
+ const skillsDir = join10(configRoot, "skills");
1787
2059
  const installPath = level === "project" ? process.cwd() : configRoot;
1788
2060
  const results = [];
1789
2061
  const removedIds = [];
1790
2062
  for (const skillId of skillIds) {
1791
- const targetPath = join9(skillsDir, skillId);
2063
+ const targetPath = join10(skillsDir, skillId);
1792
2064
  try {
1793
- if (existsSync9(targetPath) || isSymlink2(targetPath)) {
1794
- unlinkSync2(targetPath);
2065
+ if (existsSync10(targetPath) || isSymlink2(targetPath)) {
2066
+ unlinkSync3(targetPath);
1795
2067
  results.push({ skillId, success: true });
1796
2068
  removedIds.push(skillId);
1797
2069
  logger.step(` \u79FB\u9664: ${skillId}`);
@@ -1806,9 +2078,9 @@ async function uninstallSkills(skillIds, tool, level) {
1806
2078
  if (removedIds.length > 0) {
1807
2079
  removeSkillsFromRecord(removedIds, tool, level, installPath);
1808
2080
  }
1809
- if (existsSync9(skillsDir)) {
2081
+ if (existsSync10(skillsDir)) {
1810
2082
  try {
1811
- const entries = readdirSync3(skillsDir);
2083
+ const entries = readdirSync4(skillsDir);
1812
2084
  if (entries.length === 0) {
1813
2085
  rmdirSync(skillsDir);
1814
2086
  logger.step(` \u6E05\u7406\u7A7A\u76EE\u5F55: skills/`);
@@ -1816,9 +2088,9 @@ async function uninstallSkills(skillIds, tool, level) {
1816
2088
  } catch {
1817
2089
  }
1818
2090
  }
1819
- if (existsSync9(configRoot)) {
2091
+ if (existsSync10(configRoot)) {
1820
2092
  try {
1821
- const entries = readdirSync3(configRoot);
2093
+ const entries = readdirSync4(configRoot);
1822
2094
  if (entries.length === 0) {
1823
2095
  rmdirSync(configRoot);
1824
2096
  logger.step(` \u6E05\u7406\u7A7A\u76EE\u5F55: ${configRoot.split("/").pop()}/`);
@@ -1848,7 +2120,7 @@ async function interactiveSkillSelect() {
1848
2120
  { name: "x " + t("wizard_cancel"), value: CANCEL3 }
1849
2121
  ];
1850
2122
  showOperationHints();
1851
- selectedCategoryId = await select2({
2123
+ selectedCategoryId = await select3({
1852
2124
  message: t("skill_select_category"),
1853
2125
  choices: categoryChoices,
1854
2126
  loop: false,
@@ -1894,7 +2166,7 @@ async function interactiveSkillSelect() {
1894
2166
  });
1895
2167
  const skillIds = selectedSkills;
1896
2168
  if (skillIds.length === 0) {
1897
- const action = await select2({
2169
+ const action = await select3({
1898
2170
  message: t("wizard_no_selection"),
1899
2171
  choices: [
1900
2172
  new Separator2("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
@@ -1918,11 +2190,11 @@ async function interactiveSkillSelect() {
1918
2190
  function listAllSkills() {
1919
2191
  const categories = getAllCategories();
1920
2192
  console.log();
1921
- console.log(chalk3.bold(` ${t("skill_list_title")}`));
1922
- console.log(chalk3.dim(" " + "\u2500".repeat(60)));
2193
+ console.log(chalk4.bold(` ${t("skill_list_title")}`));
2194
+ console.log(chalk4.dim(" " + "\u2500".repeat(60)));
1923
2195
  for (const category of categories) {
1924
2196
  console.log();
1925
- console.log(chalk3.bold(` ${category.name}`) + chalk3.dim(` (${category.skills.length} skills)`));
2197
+ console.log(chalk4.bold(` ${category.name}`) + chalk4.dim(` (${category.skills.length} skills)`));
1926
2198
  const table = new Table({
1927
2199
  style: { head: [], border: [] },
1928
2200
  colWidths: [35, 45],
@@ -1930,14 +2202,14 @@ function listAllSkills() {
1930
2202
  });
1931
2203
  for (const skill of category.skills) {
1932
2204
  table.push([
1933
- chalk3.cyan(skill.id),
2205
+ chalk4.cyan(skill.id),
1934
2206
  skill.description
1935
2207
  ]);
1936
2208
  }
1937
2209
  console.log(table.toString());
1938
2210
  }
1939
2211
  console.log();
1940
- console.log(chalk3.dim(` \u5171 ${getAllSkills().length} \u4E2A Skills`));
2212
+ console.log(chalk4.dim(` \u5171 ${getAllSkills().length} \u4E2A Skills`));
1941
2213
  console.log();
1942
2214
  }
1943
2215
  function isSymlink2(path) {
@@ -1949,22 +2221,22 @@ function isSymlink2(path) {
1949
2221
  }
1950
2222
 
1951
2223
  // src/ui/display.ts
1952
- import chalk4 from "chalk";
2224
+ import chalk5 from "chalk";
1953
2225
  import Table2 from "cli-table3";
1954
2226
  function printPluginList(plugins, installed) {
1955
2227
  const table = new Table2({
1956
2228
  head: [
1957
- chalk4.cyan(t("list_id")),
1958
- chalk4.cyan(t("list_name")),
1959
- chalk4.cyan(t("list_status")),
1960
- chalk4.cyan(t("list_skills")),
1961
- chalk4.cyan(t("list_agents"))
2229
+ chalk5.cyan(t("list_id")),
2230
+ chalk5.cyan(t("list_name")),
2231
+ chalk5.cyan(t("list_status")),
2232
+ chalk5.cyan(t("list_skills")),
2233
+ chalk5.cyan(t("list_agents"))
1962
2234
  ],
1963
2235
  style: { head: [], border: [] }
1964
2236
  });
1965
2237
  plugins.forEach((plugin, index) => {
1966
2238
  const isInstalled = installed.has(plugin.id);
1967
- const status = isInstalled ? chalk4.green(`\u2713 ${t("status_installed")}`) : chalk4.dim(`\u2014`);
2239
+ const status = isInstalled ? chalk5.green(`\u2713 ${t("status_installed")}`) : chalk5.dim(`\u2014`);
1968
2240
  table.push([
1969
2241
  String(index + 1),
1970
2242
  plugin.displayName,
@@ -1974,7 +2246,7 @@ function printPluginList(plugins, installed) {
1974
2246
  ]);
1975
2247
  });
1976
2248
  console.log();
1977
- console.log(chalk4.bold(` ${t("list_title")} (${plugins.length} \u4E2A)`));
2249
+ console.log(chalk5.bold(` ${t("list_title")} (${plugins.length} \u4E2A)`));
1978
2250
  console.log(table.toString());
1979
2251
  console.log();
1980
2252
  }
@@ -1983,7 +2255,7 @@ function printInstallSummary(results) {
1983
2255
  const totalCount = results.length;
1984
2256
  console.log();
1985
2257
  console.log(
1986
- chalk4.bold(
2258
+ chalk5.bold(
1987
2259
  ` ${t("install_done")}! ${successCount}/${totalCount} ${t("install_success")}`
1988
2260
  )
1989
2261
  );
@@ -1991,10 +2263,10 @@ function printInstallSummary(results) {
1991
2263
  for (const result of results) {
1992
2264
  if (result.success) {
1993
2265
  console.log(
1994
- chalk4.green(" \u2713") + ` ${result.displayName} (${result.skillsCount} skills, ${result.agentsCount} agents)`
2266
+ chalk5.green(" \u2713") + ` ${result.displayName} (${result.skillsCount} skills, ${result.agentsCount} agents)`
1995
2267
  );
1996
2268
  } else {
1997
- console.log(chalk4.red(" \u2717") + ` ${result.displayName}`);
2269
+ console.log(chalk5.red(" \u2717") + ` ${result.displayName}`);
1998
2270
  }
1999
2271
  }
2000
2272
  console.log();
@@ -2008,21 +2280,21 @@ function printEnhancedSummary(results, tool, configRoot) {
2008
2280
  }
2009
2281
  const toolName = getToolDisplayName(tool);
2010
2282
  const lines = [
2011
- chalk4.bold(` ${t("install_done")}!`),
2283
+ chalk5.bold(` ${t("install_done")}!`),
2012
2284
  "",
2013
- ` ${chalk4.dim(t("install_installed_to") + ":")} ${configRoot}`,
2014
- ` ${chalk4.dim(t("install_skills_count") + ":")} ${totalSkills} \u4E2A ${chalk4.dim("|")} ${chalk4.dim(t("install_agents_count") + ":")} ${totalAgents} \u4E2A`,
2285
+ ` ${chalk5.dim(t("install_installed_to") + ":")} ${configRoot}`,
2286
+ ` ${chalk5.dim(t("install_skills_count") + ":")} ${totalSkills} \u4E2A ${chalk5.dim("|")} ${chalk5.dim(t("install_agents_count") + ":")} ${totalAgents} \u4E2A`,
2015
2287
  "",
2016
- chalk4.bold(` ${t("install_enhanced_next_steps")}:`),
2017
- ` ${chalk4.cyan("1.")} ${t("install_enhanced_launch")}: ${chalk4.green(toolName.toLowerCase())}`,
2018
- ` ${chalk4.cyan("2.")} ${t("install_enhanced_try")}: ${chalk4.green("\u5E2E\u6211\u5F00\u53D1\u4E00\u4E2A Abs \u7B97\u5B50")}`,
2019
- ` ${chalk4.cyan("3.")} ${t("install_enhanced_more")}: ${chalk4.green("install-helper list")}`,
2020
- ` ${chalk4.cyan("4.")} ${t("install_enhanced_check")}: ${chalk4.green("install-helper doctor")}`,
2288
+ chalk5.bold(` ${t("install_enhanced_next_steps")}:`),
2289
+ ` ${chalk5.cyan("1.")} ${t("install_enhanced_launch")}: ${chalk5.green(toolName.toLowerCase())}`,
2290
+ ` ${chalk5.cyan("2.")} ${t("install_enhanced_try")}: ${chalk5.green("\u5E2E\u6211\u5F00\u53D1\u4E00\u4E2A Abs \u7B97\u5B50")}`,
2291
+ ` ${chalk5.cyan("3.")} ${t("install_enhanced_more")}: ${chalk5.green("install-helper list")}`,
2292
+ ` ${chalk5.cyan("4.")} ${t("install_enhanced_check")}: ${chalk5.green("install-helper doctor")}`,
2021
2293
  ""
2022
2294
  ];
2023
2295
  if (successResults.length === 1) {
2024
2296
  lines.push(
2025
- ` ${chalk4.dim(t("install_enhanced_docs"))}: ${chalk4.dim(`plugins-official/${successResults[0].pluginId}/quickstart.md`)}`
2297
+ ` ${chalk5.dim(t("install_enhanced_docs"))}: ${chalk5.dim(`plugins-official/${successResults[0].pluginId}/quickstart.md`)}`
2026
2298
  );
2027
2299
  }
2028
2300
  console.log();
@@ -2033,23 +2305,23 @@ function printEnhancedSummary(results, tool, configRoot) {
2033
2305
  }
2034
2306
 
2035
2307
  // src/commands/init.ts
2036
- import { existsSync as existsSync10, readFileSync as readFileSync5 } from "fs";
2037
- import { join as join10 } from "path";
2308
+ import { existsSync as existsSync11, readFileSync as readFileSync5 } from "fs";
2309
+ import { join as join11 } from "path";
2038
2310
  var BACK2 = "__back__";
2039
2311
  var CANCEL2 = "__cancel__";
2040
2312
  async function initCommand() {
2041
2313
  const cwd = process.cwd();
2042
- if (existsSync10(join10(cwd, "package.json")) && (() => {
2314
+ if (existsSync11(join11(cwd, "package.json")) && (() => {
2043
2315
  try {
2044
- const pkg = JSON.parse(readFileSync5(join10(cwd, "package.json"), "utf-8"));
2316
+ const pkg = JSON.parse(readFileSync5(join11(cwd, "package.json"), "utf-8"));
2045
2317
  return pkg.name === "@cannbot-ai/install-helper";
2046
2318
  } catch {
2047
2319
  return false;
2048
2320
  }
2049
2321
  })()) {
2050
- logger.warn("\u5F53\u524D\u76EE\u5F55\u770B\u8D77\u6765\u662F install-helper \u5305\u76EE\u5F55");
2051
- logger.info("\u8BF7\u5728\u4F60\u7684\u9879\u76EE\u76EE\u5F55\u4E2D\u8FD0\u884C\u6B64\u547D\u4EE4\uFF0C\u800C\u4E0D\u662F\u5728 install-helper \u5B89\u88C5\u76EE\u5F55\u4E2D");
2052
- logger.info("\u793A\u4F8B\uFF1Acd ~/my-project && install-helper");
2322
+ logger.warn(t("init_pkg_dir_warn"));
2323
+ logger.info(t("init_pkg_dir_hint"));
2324
+ logger.info(t("init_pkg_dir_example"));
2053
2325
  return;
2054
2326
  }
2055
2327
  printBanner(t("wizard_title"));
@@ -2109,7 +2381,7 @@ async function selectMode() {
2109
2381
  { name: "x " + t("wizard_cancel"), value: CANCEL3 }
2110
2382
  ];
2111
2383
  showOperationHints();
2112
- const result = await select3({
2384
+ const result = await select4({
2113
2385
  message: t("wizard_select_mode"),
2114
2386
  choices,
2115
2387
  loop: false,
@@ -2122,7 +2394,7 @@ async function pluginInstallFlow() {
2122
2394
  const answers = await runWizard();
2123
2395
  if (!answers.confirmed) {
2124
2396
  if (answers.back) return "back";
2125
- logger.info("\u5DF2\u53D6\u6D88\u5B89\u88C5");
2397
+ logger.info(t("init_cancelled"));
2126
2398
  return "done";
2127
2399
  }
2128
2400
  const repoManager = createRepositoryManager();
@@ -2183,7 +2455,7 @@ async function skillInstallFlow() {
2183
2455
  const result = await selectToolWithDetection();
2184
2456
  if (result === "back") return "back";
2185
2457
  if (result === "cancel") {
2186
- logger.info("\u5DF2\u53D6\u6D88\u5B89\u88C5");
2458
+ logger.info(t("init_cancelled"));
2187
2459
  return "done";
2188
2460
  }
2189
2461
  tool = result;
@@ -2197,7 +2469,7 @@ async function skillInstallFlow() {
2197
2469
  break;
2198
2470
  }
2199
2471
  if (result === CANCEL2) {
2200
- logger.info("\u5DF2\u53D6\u6D88\u5B89\u88C5");
2472
+ logger.info(t("init_cancelled"));
2201
2473
  return "done";
2202
2474
  }
2203
2475
  level = result;
@@ -2211,7 +2483,7 @@ async function skillInstallFlow() {
2211
2483
  break;
2212
2484
  }
2213
2485
  if (selectedSkills === "cancel") {
2214
- logger.info("\u5DF2\u53D6\u6D88\u5B89\u88C5");
2486
+ logger.info(t("init_cancelled"));
2215
2487
  return "done";
2216
2488
  }
2217
2489
  if (selectedSkills.length === 0) {
@@ -2223,7 +2495,7 @@ async function skillInstallFlow() {
2223
2495
  spinner.start();
2224
2496
  const repoPath = await repoManager.ensureRepo();
2225
2497
  spinner.succeed("\u63D2\u4EF6\u6570\u636E\u52A0\u8F7D\u5B8C\u6210");
2226
- logger.info(`${t("skill_install_progress")} ${chalk5.bold(selectedSkills.length)} \u4E2A Skills...`);
2498
+ logger.info(`${t("skill_install_progress")} ${chalk6.bold(selectedSkills.length)} \u4E2A Skills...`);
2227
2499
  const results = await installSkills(selectedSkills, tool, level, repoPath);
2228
2500
  let successCount = 0;
2229
2501
  let failCount = 0;
@@ -2241,10 +2513,10 @@ async function skillInstallFlow() {
2241
2513
  }
2242
2514
  const configRoot = getConfigRoot(tool, level);
2243
2515
  logger.blank();
2244
- logger.success(`${t("skill_install_done")}: ${chalk5.green(successCount + " \u6210\u529F")}, ${failCount > 0 ? chalk5.red(failCount + " \u5931\u8D25") : chalk5.dim(failCount + " \u5931\u8D25")}`);
2516
+ logger.success(`${t("skill_install_done")}: ${chalk6.green(successCount + " \u6210\u529F")}, ${failCount > 0 ? chalk6.red(failCount + " \u5931\u8D25") : chalk6.dim(failCount + " \u5931\u8D25")}`);
2245
2517
  logger.blank();
2246
- logger.info(`\u5B89\u88C5\u5230: ${chalk5.cyan(configRoot + "/skills/")}`);
2247
- logger.info(`\u542F\u52A8 ${chalk5.green(tool)} \u5373\u53EF\u4F7F\u7528`);
2518
+ logger.info(`\u5B89\u88C5\u5230: ${chalk6.cyan(configRoot + "/skills/")}`);
2519
+ logger.info(`\u542F\u52A8 ${chalk6.green(tool)} \u5373\u53EF\u4F7F\u7528`);
2248
2520
  logger.blank();
2249
2521
  return "done";
2250
2522
  }
@@ -2266,32 +2538,32 @@ async function listCommand() {
2266
2538
  }
2267
2539
 
2268
2540
  // src/commands/doctor.ts
2269
- import chalk6 from "chalk";
2270
- import { existsSync as existsSync11, readdirSync as readdirSync4, lstatSync as lstatSync3, unlinkSync as unlinkSync3, mkdirSync as mkdirSync6 } from "fs";
2271
- import { join as join11 } from "path";
2541
+ import chalk7 from "chalk";
2542
+ import { existsSync as existsSync12, readdirSync as readdirSync5, lstatSync as lstatSync3, unlinkSync as unlinkSync4, mkdirSync as mkdirSync6 } from "fs";
2543
+ import { join as join12 } from "path";
2272
2544
  async function doctorCommand(options = {}) {
2273
2545
  console.log();
2274
- console.log(chalk6.bold(` ${t("doctor_title")}`));
2275
- console.log(chalk6.dim(" " + "\u2500".repeat(46)));
2546
+ console.log(chalk7.bold(` ${t("doctor_title")}`));
2547
+ console.log(chalk7.dim(" " + "\u2500".repeat(46)));
2276
2548
  let errors = 0;
2277
2549
  let warnings = 0;
2278
2550
  let fixes = 0;
2279
2551
  console.log();
2280
- console.log(chalk6.bold(` ${t("doctor_tools")}`));
2552
+ console.log(chalk7.bold(` ${t("doctor_tools")}`));
2281
2553
  const detectedTools = await detectTools();
2282
2554
  const allTools = getAllTools();
2283
2555
  for (const tool of allTools) {
2284
2556
  const detected = detectedTools.find((d) => d.name === tool);
2285
2557
  if (detected) {
2286
2558
  console.log(
2287
- chalk6.green(" \u2713") + ` ${getToolDisplayName(tool)}${detected.version ? ` v${detected.version}` : ""}`
2559
+ chalk7.green(" \u2713") + ` ${getToolDisplayName(tool)}${detected.version ? ` v${detected.version}` : ""}`
2288
2560
  );
2289
2561
  } else {
2290
- console.log(chalk6.dim(" \u2014") + ` ${getToolDisplayName(tool)} \u2014 \u672A\u5B89\u88C5`);
2562
+ console.log(chalk7.dim(" \u2014") + ` ${getToolDisplayName(tool)} \u2014 \u672A\u5B89\u88C5`);
2291
2563
  }
2292
2564
  }
2293
2565
  console.log();
2294
- console.log(chalk6.bold(` ${t("doctor_plugins")}`));
2566
+ console.log(chalk7.bold(` ${t("doctor_plugins")}`));
2295
2567
  const plugins = getAllPlugins();
2296
2568
  const installed = scanInstalled();
2297
2569
  const installedMap = new Map(installed.map((p) => [p.id, p]));
@@ -2299,73 +2571,73 @@ async function doctorCommand(options = {}) {
2299
2571
  const inst = installedMap.get(plugin.id);
2300
2572
  if (inst) {
2301
2573
  console.log(
2302
- chalk6.green(" \u2713") + ` ${plugin.id.padEnd(30)} ${inst.skillsCount} skills, ${inst.agentsCount} agents`
2574
+ chalk7.green(" \u2713") + ` ${plugin.id.padEnd(30)} ${inst.skillsCount} skills, ${inst.agentsCount} agents`
2303
2575
  );
2304
2576
  } else {
2305
- console.log(chalk6.dim(" \u2014") + ` ${plugin.id.padEnd(30)} \u2014 \u672A\u5B89\u88C5`);
2577
+ console.log(chalk7.dim(" \u2014") + ` ${plugin.id.padEnd(30)} \u2014 \u672A\u5B89\u88C5`);
2306
2578
  }
2307
2579
  }
2308
2580
  console.log();
2309
- console.log(chalk6.bold(` ${t("doctor_links")}`));
2581
+ console.log(chalk7.bold(` ${t("doctor_links")}`));
2310
2582
  const primaryTool = detectedTools[0]?.name || "opencode";
2311
2583
  const configRoot = getConfigRoot(primaryTool, "project");
2312
2584
  const skillsDir = getSkillsDir(configRoot);
2313
2585
  const agentsDir = getAgentsDir(configRoot);
2314
- if (existsSync11(skillsDir)) {
2586
+ if (existsSync12(skillsDir)) {
2315
2587
  const brokenLinks = checkBrokenLinks(skillsDir);
2316
2588
  if (brokenLinks === 0) {
2317
- const count = readdirSync4(skillsDir).length;
2318
- console.log(chalk6.green(" \u2713") + ` ${skillsDir} \u2014 ${count} \u4E2A\u8F6F\u94FE\u63A5\u5747\u6709\u6548`);
2589
+ const count = readdirSync5(skillsDir).length;
2590
+ console.log(chalk7.green(" \u2713") + ` ${skillsDir} \u2014 ${count} \u4E2A\u8F6F\u94FE\u63A5\u5747\u6709\u6548`);
2319
2591
  } else {
2320
- console.log(chalk6.yellow(" \u26A0") + ` ${skillsDir} \u2014 ${brokenLinks} \u4E2A\u5931\u6548\u94FE\u63A5`);
2592
+ console.log(chalk7.yellow(" \u26A0") + ` ${skillsDir} \u2014 ${brokenLinks} \u4E2A\u5931\u6548\u94FE\u63A5`);
2321
2593
  warnings++;
2322
2594
  if (options.fix) {
2323
2595
  const fixed = fixBrokenLinks(skillsDir);
2324
2596
  fixes += fixed;
2325
- console.log(chalk6.green(" \u2713") + ` ${t("doctor_fix_cleaning")}: \u5DF2\u6E05\u7406 ${fixed} \u4E2A\u5931\u6548\u94FE\u63A5`);
2597
+ console.log(chalk7.green(" \u2713") + ` ${t("doctor_fix_cleaning")}: \u5DF2\u6E05\u7406 ${fixed} \u4E2A\u5931\u6548\u94FE\u63A5`);
2326
2598
  }
2327
2599
  }
2328
2600
  } else {
2329
- console.log(chalk6.dim(" \u2014") + ` ${skillsDir} \u2014 \u4E0D\u5B58\u5728`);
2601
+ console.log(chalk7.dim(" \u2014") + ` ${skillsDir} \u2014 \u4E0D\u5B58\u5728`);
2330
2602
  if (options.fix) {
2331
2603
  mkdirSync6(skillsDir, { recursive: true });
2332
2604
  fixes++;
2333
- console.log(chalk6.green(" \u2713") + ` ${t("doctor_fix_rebuilding")}: \u5DF2\u521B\u5EFA ${skillsDir}`);
2605
+ console.log(chalk7.green(" \u2713") + ` ${t("doctor_fix_rebuilding")}: \u5DF2\u521B\u5EFA ${skillsDir}`);
2334
2606
  }
2335
2607
  }
2336
- if (existsSync11(agentsDir)) {
2608
+ if (existsSync12(agentsDir)) {
2337
2609
  const brokenLinks = checkBrokenLinks(agentsDir);
2338
2610
  if (brokenLinks === 0) {
2339
- const count = readdirSync4(agentsDir).length;
2340
- console.log(chalk6.green(" \u2713") + ` ${agentsDir} \u2014 ${count} \u4E2A\u8F6F\u94FE\u63A5\u5747\u6709\u6548`);
2611
+ const count = readdirSync5(agentsDir).length;
2612
+ console.log(chalk7.green(" \u2713") + ` ${agentsDir} \u2014 ${count} \u4E2A\u8F6F\u94FE\u63A5\u5747\u6709\u6548`);
2341
2613
  } else {
2342
- console.log(chalk6.yellow(" \u26A0") + ` ${agentsDir} \u2014 ${brokenLinks} \u4E2A\u5931\u6548\u94FE\u63A5`);
2614
+ console.log(chalk7.yellow(" \u26A0") + ` ${agentsDir} \u2014 ${brokenLinks} \u4E2A\u5931\u6548\u94FE\u63A5`);
2343
2615
  warnings++;
2344
2616
  if (options.fix) {
2345
2617
  const fixed = fixBrokenLinks(agentsDir);
2346
2618
  fixes += fixed;
2347
- console.log(chalk6.green(" \u2713") + ` ${t("doctor_fix_cleaning")}: \u5DF2\u6E05\u7406 ${fixed} \u4E2A\u5931\u6548\u94FE\u63A5`);
2619
+ console.log(chalk7.green(" \u2713") + ` ${t("doctor_fix_cleaning")}: \u5DF2\u6E05\u7406 ${fixed} \u4E2A\u5931\u6548\u94FE\u63A5`);
2348
2620
  }
2349
2621
  }
2350
2622
  } else {
2351
- console.log(chalk6.dim(" \u2014") + ` ${agentsDir} \u2014 \u4E0D\u5B58\u5728`);
2623
+ console.log(chalk7.dim(" \u2014") + ` ${agentsDir} \u2014 \u4E0D\u5B58\u5728`);
2352
2624
  if (options.fix) {
2353
2625
  mkdirSync6(agentsDir, { recursive: true });
2354
2626
  fixes++;
2355
- console.log(chalk6.green(" \u2713") + ` ${t("doctor_fix_rebuilding")}: \u5DF2\u521B\u5EFA ${agentsDir}`);
2627
+ console.log(chalk7.green(" \u2713") + ` ${t("doctor_fix_rebuilding")}: \u5DF2\u521B\u5EFA ${agentsDir}`);
2356
2628
  }
2357
2629
  }
2358
2630
  console.log();
2359
- console.log(chalk6.bold(` ${t("doctor_config")}`));
2631
+ console.log(chalk7.bold(` ${t("doctor_config")}`));
2360
2632
  const configFile = getConfigFileName(primaryTool);
2361
- const configPath = join11(process.cwd(), configFile);
2362
- if (existsSync11(configPath)) {
2363
- console.log(chalk6.green(" \u2713") + ` ${configFile} \u5B58\u5728`);
2633
+ const configPath = join12(process.cwd(), configFile);
2634
+ if (existsSync12(configPath)) {
2635
+ console.log(chalk7.green(" \u2713") + ` ${configFile} \u5B58\u5728`);
2364
2636
  } else {
2365
- console.log(chalk6.dim(" \u2014") + ` ${configFile} \u4E0D\u5B58\u5728`);
2637
+ console.log(chalk7.dim(" \u2014") + ` ${configFile} \u4E0D\u5B58\u5728`);
2366
2638
  }
2367
2639
  console.log();
2368
- console.log(chalk6.dim(" " + "\u2500".repeat(46)));
2640
+ console.log(chalk7.dim(" " + "\u2500".repeat(46)));
2369
2641
  if (options.fix && fixes > 0) {
2370
2642
  console.log(
2371
2643
  ` ${t("doctor_result")}: ${warnings} \u4E2A\u8B66\u544A, ${errors} \u4E2A\u9519\u8BEF, ${fixes} \u9879\u5DF2\u4FEE\u590D`
@@ -2380,13 +2652,13 @@ async function doctorCommand(options = {}) {
2380
2652
  function checkBrokenLinks(dir) {
2381
2653
  let broken = 0;
2382
2654
  try {
2383
- const entries = readdirSync4(dir);
2655
+ const entries = readdirSync5(dir);
2384
2656
  for (const entry of entries) {
2385
- const fullPath = join11(dir, entry);
2657
+ const fullPath = join12(dir, entry);
2386
2658
  try {
2387
2659
  const stats = lstatSync3(fullPath);
2388
2660
  if (stats.isSymbolicLink()) {
2389
- if (!existsSync11(fullPath)) {
2661
+ if (!existsSync12(fullPath)) {
2390
2662
  broken++;
2391
2663
  }
2392
2664
  }
@@ -2401,14 +2673,14 @@ function checkBrokenLinks(dir) {
2401
2673
  function fixBrokenLinks(dir) {
2402
2674
  let fixed = 0;
2403
2675
  try {
2404
- const entries = readdirSync4(dir);
2676
+ const entries = readdirSync5(dir);
2405
2677
  for (const entry of entries) {
2406
- const fullPath = join11(dir, entry);
2678
+ const fullPath = join12(dir, entry);
2407
2679
  try {
2408
2680
  const stats = lstatSync3(fullPath);
2409
2681
  if (stats.isSymbolicLink()) {
2410
- if (!existsSync11(fullPath)) {
2411
- unlinkSync3(fullPath);
2682
+ if (!existsSync12(fullPath)) {
2683
+ unlinkSync4(fullPath);
2412
2684
  fixed++;
2413
2685
  }
2414
2686
  }
@@ -2421,36 +2693,36 @@ function fixBrokenLinks(dir) {
2421
2693
  }
2422
2694
 
2423
2695
  // src/commands/status.ts
2424
- import chalk7 from "chalk";
2696
+ import chalk8 from "chalk";
2425
2697
  async function statusCommand() {
2426
2698
  const plugins = getAllPlugins();
2427
2699
  const installed = scanInstalled();
2428
2700
  const installedMap = new Map(installed.map((p) => [p.id, p]));
2429
2701
  console.log();
2430
- console.log(chalk7.bold(` ${t("status_title")}`));
2702
+ console.log(chalk8.bold(` ${t("status_title")}`));
2431
2703
  console.log();
2432
2704
  if (installed.length === 0) {
2433
- console.log(chalk7.dim(` ${t("status_none")}`));
2434
- console.log(chalk7.dim(` ${t("status_hint")}`));
2705
+ console.log(chalk8.dim(` ${t("status_none")}`));
2706
+ console.log(chalk8.dim(` ${t("status_hint")}`));
2435
2707
  console.log();
2436
2708
  return;
2437
2709
  }
2438
2710
  for (const inst of installed) {
2439
2711
  console.log(
2440
- chalk7.green(" \u2713") + ` ${inst.displayName}` + chalk7.dim(` (${inst.tool}, ${inst.level})`)
2712
+ chalk8.green(" \u2713") + ` ${inst.displayName}` + chalk8.dim(` (${inst.tool}, ${inst.level})`)
2441
2713
  );
2442
2714
  console.log(
2443
- chalk7.dim(` ${inst.skillsCount} skills, ${inst.agentsCount} agents`)
2715
+ chalk8.dim(` ${inst.skillsCount} skills, ${inst.agentsCount} agents`)
2444
2716
  );
2445
- console.log(chalk7.dim(` ${inst.configRoot}`));
2446
- console.log(chalk7.dim(` ${t("status_install_time")}: ${inst.installTime}`));
2717
+ console.log(chalk8.dim(` ${inst.configRoot}`));
2718
+ console.log(chalk8.dim(` ${t("status_install_time")}: ${inst.installTime}`));
2447
2719
  console.log();
2448
2720
  }
2449
2721
  }
2450
2722
 
2451
2723
  // src/commands/install.ts
2452
2724
  import { confirm } from "@inquirer/prompts";
2453
- import chalk8 from "chalk";
2725
+ import chalk9 from "chalk";
2454
2726
  async function installCommand(names, options) {
2455
2727
  if (options.list) {
2456
2728
  try {
@@ -2496,30 +2768,33 @@ async function installCommand(names, options) {
2496
2768
  }
2497
2769
  names = selectedSkills;
2498
2770
  const repoManager = createRepositoryManager();
2499
- const spinner = createSpinner(t("install_cloning"));
2771
+ const spinner = createSpinner("\u6B63\u5728\u52A0\u8F7D\u63D2\u4EF6\u6570\u636E...");
2500
2772
  spinner.start();
2501
2773
  const repoPath = await repoManager.ensureRepo();
2502
- spinner.succeed(t("install_repo_ready"));
2503
- logger.info(`${t("skill_install_progress")} ${chalk8.bold(names.length)} \u4E2A Skills...`);
2774
+ spinner.succeed("\u63D2\u4EF6\u6570\u636E\u52A0\u8F7D\u5B8C\u6210");
2775
+ logger.info(`${t("skill_install_progress")} ${chalk9.bold(names.length)} \u4E2A Skills...`);
2504
2776
  const level2 = options.level || "project";
2505
2777
  const results = await installSkills(names, tool2, level2, repoPath);
2506
2778
  let successCount = 0;
2507
2779
  let failCount = 0;
2508
- for (const result of results) {
2780
+ const total = results.length;
2781
+ for (let i = 0; i < results.length; i++) {
2782
+ const result = results[i];
2783
+ const progress = `[${i + 1}/${total}]`;
2509
2784
  if (result.success) {
2510
- logger.success(`${result.skillId}`);
2785
+ logger.success(`${progress} ${result.skillId}`);
2511
2786
  successCount++;
2512
2787
  } else {
2513
- logger.error(`${result.skillId}: ${result.error}`);
2788
+ logger.error(`${progress} ${result.skillId}: ${result.error}`);
2514
2789
  failCount++;
2515
2790
  }
2516
2791
  }
2517
2792
  const configRoot = getConfigRoot(tool2, level2);
2518
2793
  logger.blank();
2519
- logger.success(`${t("skill_install_done")}: ${chalk8.green(successCount + " \u6210\u529F")}, ${failCount > 0 ? chalk8.red(failCount + " \u5931\u8D25") : chalk8.dim(failCount + " \u5931\u8D25")}`);
2794
+ logger.success(`${t("skill_install_done")}: ${chalk9.green(successCount + " \u6210\u529F")}, ${failCount > 0 ? chalk9.red(failCount + " \u5931\u8D25") : chalk9.dim(failCount + " \u5931\u8D25")}`);
2520
2795
  logger.blank();
2521
- logger.info(`\u5B89\u88C5\u5230: ${chalk8.cyan(configRoot + "/skills/")}`);
2522
- logger.info(`\u542F\u52A8 ${chalk8.green(tool2)} \u5373\u53EF\u4F7F\u7528`);
2796
+ logger.info(`\u5B89\u88C5\u5230: ${chalk9.cyan(configRoot + "/skills/")}`);
2797
+ logger.info(`\u542F\u52A8 ${chalk9.green(tool2)} \u5373\u53EF\u4F7F\u7528`);
2523
2798
  logger.blank();
2524
2799
  return;
2525
2800
  }
@@ -2554,7 +2829,7 @@ async function installCommand(names, options) {
2554
2829
  for (const p of allPlugins) {
2555
2830
  logger.step(` ${p.id} (${p.aliases.join(", ")})`);
2556
2831
  }
2557
- logger.info(`\u53EF\u7528 Skills: ${chalk8.cyan("install-helper install --list")}`);
2832
+ logger.info(`\u53EF\u7528 Skills: ${chalk9.cyan("install-helper install --list")}`);
2558
2833
  return;
2559
2834
  }
2560
2835
  let tool;
@@ -2593,10 +2868,10 @@ async function installCommand(names, options) {
2593
2868
  }
2594
2869
  if (pluginsToInstall.length > 0) {
2595
2870
  const repoManager = createRepositoryManager();
2596
- const spinner = createSpinner(t("install_cloning"));
2871
+ const spinner = createSpinner("\u6B63\u5728\u52A0\u8F7D\u63D2\u4EF6\u6570\u636E...");
2597
2872
  spinner.start();
2598
2873
  const repoPath = await repoManager.ensureRepo();
2599
- spinner.succeed(t("install_repo_ready"));
2874
+ spinner.succeed("\u63D2\u4EF6\u6570\u636E\u52A0\u8F7D\u5B8C\u6210");
2600
2875
  const allPlugins = getAllPlugins();
2601
2876
  const results = await installPlugins(
2602
2877
  pluginsToInstall,
@@ -2620,28 +2895,31 @@ async function installCommand(names, options) {
2620
2895
  }
2621
2896
  if (skills.length > 0) {
2622
2897
  const repoManager = createRepositoryManager();
2623
- const spinner = createSpinner(t("install_cloning"));
2898
+ const spinner = createSpinner("\u6B63\u5728\u52A0\u8F7D\u63D2\u4EF6\u6570\u636E...");
2624
2899
  spinner.start();
2625
2900
  const repoPath = await repoManager.ensureRepo();
2626
- spinner.succeed(t("install_repo_ready"));
2627
- logger.info(`${t("skill_install_progress")} ${chalk8.bold(skills.length)} \u4E2A Skills...`);
2901
+ spinner.succeed("\u63D2\u4EF6\u6570\u636E\u52A0\u8F7D\u5B8C\u6210");
2902
+ logger.info(`${t("skill_install_progress")} ${chalk9.bold(skills.length)} \u4E2A Skills...`);
2628
2903
  const results = await installSkills(skills, tool, level, repoPath);
2629
2904
  let successCount = 0;
2630
2905
  let failCount = 0;
2631
- for (const result of results) {
2906
+ const total = results.length;
2907
+ for (let i = 0; i < results.length; i++) {
2908
+ const result = results[i];
2909
+ const progress = `[${i + 1}/${total}]`;
2632
2910
  if (result.success) {
2633
- logger.success(`${result.skillId}`);
2911
+ logger.success(`${progress} ${result.skillId}`);
2634
2912
  successCount++;
2635
2913
  } else {
2636
- logger.error(`${result.skillId}: ${result.error}`);
2914
+ logger.error(`${progress} ${result.skillId}: ${result.error}`);
2637
2915
  failCount++;
2638
2916
  }
2639
2917
  }
2640
2918
  logger.blank();
2641
- logger.success(`${t("skill_install_done")}: ${chalk8.green(successCount + " \u6210\u529F")}, ${failCount > 0 ? chalk8.red(failCount + " \u5931\u8D25") : chalk8.dim(failCount + " \u5931\u8D25")}`);
2919
+ logger.success(`${t("skill_install_done")}: ${chalk9.green(successCount + " \u6210\u529F")}, ${failCount > 0 ? chalk9.red(failCount + " \u5931\u8D25") : chalk9.dim(failCount + " \u5931\u8D25")}`);
2642
2920
  logger.blank();
2643
- logger.info(`\u5B89\u88C5\u5230: ${chalk8.cyan(getConfigRoot(tool, level) + "/skills/")}`);
2644
- logger.info(`\u542F\u52A8 ${chalk8.green(tool)} \u5373\u53EF\u4F7F\u7528`);
2921
+ logger.info(`\u5B89\u88C5\u5230: ${chalk9.cyan(getConfigRoot(tool, level) + "/skills/")}`);
2922
+ logger.info(`\u542F\u52A8 ${chalk9.green(tool)} \u5373\u53EF\u4F7F\u7528`);
2645
2923
  logger.blank();
2646
2924
  }
2647
2925
  }
@@ -2673,8 +2951,8 @@ async function installPlugins(pluginIds, tool, level, repoPath) {
2673
2951
  }
2674
2952
 
2675
2953
  // src/commands/uninstall.ts
2676
- import { existsSync as existsSync12, unlinkSync as unlinkSync4, rmdirSync as rmdirSync2, readdirSync as readdirSync5, lstatSync as lstatSync4 } from "fs";
2677
- import chalk9 from "chalk";
2954
+ import { existsSync as existsSync13, unlinkSync as unlinkSync5, rmdirSync as rmdirSync2, readdirSync as readdirSync6, lstatSync as lstatSync4 } from "fs";
2955
+ import chalk10 from "chalk";
2678
2956
  async function uninstallCommand(names, options) {
2679
2957
  const tool = options.tool || "opencode";
2680
2958
  const level = options.level || "project";
@@ -2691,24 +2969,24 @@ async function uninstallCommand(names, options) {
2691
2969
  skills.push(skill.id);
2692
2970
  continue;
2693
2971
  }
2694
- logger.error(`\u672A\u627E\u5230: ${name}`);
2972
+ logger.error(`${t("uninstall_not_found")}: ${name}`);
2695
2973
  }
2696
2974
  for (const pluginId of plugins) {
2697
2975
  const plugin = findPlugin(pluginId);
2698
2976
  if (!plugin) continue;
2699
2977
  const record = readRecord(plugin.id);
2700
2978
  if (!record) {
2701
- logger.warn(`${plugin.displayName} \u672A\u627E\u5230\u5B89\u88C5\u8BB0\u5F55\uFF0C\u53EF\u80FD\u672A\u5B89\u88C5\u6216\u5B89\u88C5\u8BB0\u5F55\u5DF2\u635F\u574F`);
2702
- logger.info(`\u5982\u9700\u5F3A\u5236\u6E05\u7406\uFF0C\u8BF7\u624B\u52A8\u5220\u9664 .opencode/ \u6216 .claude/ \u76EE\u5F55\u4E2D\u7684\u76F8\u5173\u6587\u4EF6`);
2979
+ logger.warn(`${plugin.displayName} ${t("uninstall_no_record")}`);
2980
+ logger.info(`${t("uninstall_no_record_hint")}`);
2703
2981
  continue;
2704
2982
  }
2705
- logger.info(`\u6B63\u5728\u5378\u8F7D ${plugin.displayName}...`);
2983
+ logger.info(`${t("uninstall_in_progress")} ${plugin.displayName}...`);
2706
2984
  let removedFiles = 0;
2707
2985
  let removedDirs = 0;
2708
2986
  for (const filePath of record.files) {
2709
2987
  try {
2710
- if (existsSync12(filePath) || isSymlink3(filePath)) {
2711
- unlinkSync4(filePath);
2988
+ if (existsSync13(filePath) || isSymlink3(filePath)) {
2989
+ unlinkSync5(filePath);
2712
2990
  const name = filePath.split("/").pop() || filePath;
2713
2991
  logger.step(` \u79FB\u9664: ${name}`);
2714
2992
  removedFiles++;
@@ -2719,8 +2997,8 @@ async function uninstallCommand(names, options) {
2719
2997
  const sortedDirs = [...record.directories].sort((a, b) => b.length - a.length);
2720
2998
  for (const dirPath of sortedDirs) {
2721
2999
  try {
2722
- if (existsSync12(dirPath)) {
2723
- const entries = readdirSync5(dirPath);
3000
+ if (existsSync13(dirPath)) {
3001
+ const entries = readdirSync6(dirPath);
2724
3002
  if (entries.length === 0) {
2725
3003
  rmdirSync2(dirPath);
2726
3004
  const name = dirPath.split("/").pop() || dirPath;
@@ -2733,15 +3011,33 @@ async function uninstallCommand(names, options) {
2733
3011
  }
2734
3012
  deleteRecord(plugin.id);
2735
3013
  removeInstalledPlugin(plugin.id);
3014
+ const configRoot = getConfigRoot(record.tool, record.level);
3015
+ const backups = findBackups(configRoot);
3016
+ const otherBackups = backups.filter((b) => b.pluginId !== pluginId);
3017
+ if (otherBackups.length > 0) {
3018
+ const choice = await showRestorePrompt(otherBackups);
3019
+ if (choice !== "none") {
3020
+ const restored = restoreBackup(choice, configRoot, record.tool);
3021
+ if (restored) {
3022
+ const backupInfo = otherBackups.find((b) => b.filePath === choice);
3023
+ logger.success(`${t("backup_restore_success")}: ${backupInfo?.pluginName || ""}`);
3024
+ deleteBackup(choice);
3025
+ }
3026
+ }
3027
+ }
3028
+ const currentBackups = backups.filter((b) => b.pluginId === pluginId);
3029
+ for (const backup of currentBackups) {
3030
+ deleteBackup(backup.filePath);
3031
+ }
2736
3032
  const totalRemoved = removedFiles + removedDirs;
2737
3033
  if (totalRemoved > 0) {
2738
- logger.success(`\u5DF2\u5378\u8F7D ${plugin.displayName}\uFF08\u79FB\u9664 ${removedFiles} \u4E2A\u6587\u4EF6\uFF0C${removedDirs} \u4E2A\u76EE\u5F55\uFF09`);
3034
+ logger.success(`${t("uninstall_removed")} ${plugin.displayName}\uFF08\u79FB\u9664 ${removedFiles} \u4E2A\u6587\u4EF6\uFF0C${removedDirs} \u4E2A\u76EE\u5F55\uFF09`);
2739
3035
  } else {
2740
- logger.warn(`${plugin.displayName} \u7684\u6587\u4EF6\u5DF2\u4E0D\u5B58\u5728\uFF0C\u5DF2\u6E05\u7406\u5B89\u88C5\u8BB0\u5F55`);
3036
+ logger.warn(`${plugin.displayName}${t("uninstall_files_gone")}`);
2741
3037
  }
2742
3038
  }
2743
3039
  if (skills.length > 0) {
2744
- logger.info(`\u6B63\u5728\u5378\u8F7D ${skills.length} \u4E2A Skills...`);
3040
+ logger.info(`${t("uninstall_skills_in_progress")} ${skills.length} \u4E2A Skills...`);
2745
3041
  const results = await uninstallSkills(skills, tool, level);
2746
3042
  let successCount = 0;
2747
3043
  let failCount = 0;
@@ -2753,7 +3049,7 @@ async function uninstallCommand(names, options) {
2753
3049
  }
2754
3050
  }
2755
3051
  logger.blank();
2756
- logger.success(`${t("skill_uninstall_done")}: ${chalk9.green(successCount + " \u6210\u529F")}, ${failCount > 0 ? chalk9.red(failCount + " \u5931\u8D25") : chalk9.dim(failCount + " \u5931\u8D25")}`);
3052
+ logger.success(`${t("skill_uninstall_done")}: ${chalk10.green(successCount + " \u6210\u529F")}, ${failCount > 0 ? chalk10.red(failCount + " \u5931\u8D25") : chalk10.dim(failCount + " \u5931\u8D25")}`);
2757
3053
  logger.blank();
2758
3054
  }
2759
3055
  }
@@ -2766,7 +3062,7 @@ function isSymlink3(path) {
2766
3062
  }
2767
3063
 
2768
3064
  // src/commands/update.ts
2769
- import chalk10 from "chalk";
3065
+ import chalk11 from "chalk";
2770
3066
  async function updateCommand(pluginNames, options) {
2771
3067
  let tool;
2772
3068
  if (options.tool) {
@@ -2784,7 +3080,7 @@ async function updateCommand(pluginNames, options) {
2784
3080
  pluginsToUpdate = manifests.map((m) => m.team);
2785
3081
  if (pluginsToUpdate.length === 0) {
2786
3082
  logger.info(t("update_no_plugins"));
2787
- logger.info(`\u4F7F\u7528 ${chalk10.cyan("install-helper install <plugin>")} \u5B89\u88C5\u63D2\u4EF6`);
3083
+ logger.info(`\u4F7F\u7528 ${chalk11.cyan("install-helper install <plugin>")} \u5B89\u88C5\u63D2\u4EF6`);
2788
3084
  return;
2789
3085
  }
2790
3086
  } else {
@@ -2846,42 +3142,42 @@ async function updateCommand(pluginNames, options) {
2846
3142
  }
2847
3143
 
2848
3144
  // src/commands/info.ts
2849
- import chalk11 from "chalk";
2850
- import { existsSync as existsSync13, readdirSync as readdirSync6 } from "fs";
2851
- import { join as join12 } from "path";
3145
+ import chalk12 from "chalk";
3146
+ import { existsSync as existsSync14, readdirSync as readdirSync7 } from "fs";
3147
+ import { join as join13 } from "path";
2852
3148
  async function infoCommand(pluginName) {
2853
3149
  const plugin = findPlugin(pluginName);
2854
3150
  if (!plugin) {
2855
- console.log(chalk11.red(` ${t("info_not_found")}: ${pluginName}`));
3151
+ console.log(chalk12.red(` ${t("info_not_found")}: ${pluginName}`));
2856
3152
  return;
2857
3153
  }
2858
3154
  const installed = scanInstalled();
2859
3155
  const isInstalled = installed.some((p) => p.id === plugin.id);
2860
- const statusText = isInstalled ? chalk11.green(`\u2713 ${t("status_installed")}`) : chalk11.dim(`\u2014 ${t("status_not_installed")}`);
3156
+ const statusText = isInstalled ? chalk12.green(`\u2713 ${t("status_installed")}`) : chalk12.dim(`\u2014 ${t("status_not_installed")}`);
2861
3157
  console.log();
2862
- console.log(chalk11.bold(` ${plugin.displayName}`));
2863
- console.log(chalk11.dim(" " + "\u2500".repeat(40)));
3158
+ console.log(chalk12.bold(` ${plugin.displayName}`));
3159
+ console.log(chalk12.dim(" " + "\u2500".repeat(40)));
2864
3160
  console.log();
2865
- console.log(` ${chalk11.dim(t("info_description") + ":")} ${plugin.description}`);
2866
- console.log(` ${chalk11.dim("ID:")} ${plugin.id}`);
2867
- console.log(` ${chalk11.dim(t("info_status") + ":")} ${statusText}`);
2868
- console.log(` ${chalk11.dim(t("info_skills") + ":")} ${plugin.skills}`);
2869
- console.log(` ${chalk11.dim(t("info_agents") + ":")} ${plugin.agents}`);
2870
- console.log(` ${chalk11.dim("\u522B\u540D:")} ${plugin.aliases.join(", ")}`);
3161
+ console.log(` ${chalk12.dim(t("info_description") + ":")} ${plugin.description}`);
3162
+ console.log(` ${chalk12.dim("ID:")} ${plugin.id}`);
3163
+ console.log(` ${chalk12.dim(t("info_status") + ":")} ${statusText}`);
3164
+ console.log(` ${chalk12.dim(t("info_skills") + ":")} ${plugin.skills}`);
3165
+ console.log(` ${chalk12.dim(t("info_agents") + ":")} ${plugin.agents}`);
3166
+ console.log(` ${chalk12.dim(t("info_aliases") + ":")} ${plugin.aliases.join(", ")}`);
2871
3167
  console.log();
2872
3168
  try {
2873
3169
  const repoManager = createRepositoryManager();
2874
3170
  const repoPath = await repoManager.ensureRepo();
2875
- const quickstartPath = join12(repoPath, plugin.dir, "quickstart.md");
2876
- if (existsSync13(quickstartPath)) {
2877
- console.log(` ${chalk11.dim(t("info_quickstart") + ":")} ${quickstartPath}`);
3171
+ const quickstartPath = join13(repoPath, plugin.dir, "quickstart.md");
3172
+ if (existsSync14(quickstartPath)) {
3173
+ console.log(` ${chalk12.dim(t("info_quickstart") + ":")} ${quickstartPath}`);
2878
3174
  }
2879
- const agentsDir = join12(repoPath, plugin.dir, "agents");
2880
- if (existsSync13(agentsDir)) {
2881
- const agentFiles = readdirSync6(agentsDir).filter((f) => f.endsWith(".md"));
3175
+ const agentsDir = join13(repoPath, plugin.dir, "agents");
3176
+ if (existsSync14(agentsDir)) {
3177
+ const agentFiles = readdirSync7(agentsDir).filter((f) => f.endsWith(".md"));
2882
3178
  if (agentFiles.length > 0) {
2883
3179
  console.log();
2884
- console.log(` ${chalk11.bold("Agents:")}`);
3180
+ console.log(` ${chalk12.bold("Agents:")}`);
2885
3181
  for (const agent of agentFiles) {
2886
3182
  console.log(` \u2022 ${agent.replace(".md", "")}`);
2887
3183
  }
@@ -2893,39 +3189,39 @@ async function infoCommand(pluginName) {
2893
3189
  }
2894
3190
 
2895
3191
  // src/commands/lang.ts
2896
- import chalk12 from "chalk";
3192
+ import chalk13 from "chalk";
2897
3193
  async function langCommand(action, value) {
2898
3194
  const config = readConfig();
2899
3195
  if (!action || action === "show") {
2900
3196
  console.log();
2901
- console.log(chalk12.bold(` ${t("lang_title")}`));
2902
- console.log(chalk12.dim(" " + "\u2500".repeat(40)));
3197
+ console.log(chalk13.bold(` ${t("lang_title")}`));
3198
+ console.log(chalk13.dim(" " + "\u2500".repeat(40)));
2903
3199
  console.log();
2904
- console.log(` ${chalk12.dim(t("lang_current") + ":")} ${config.language}`);
3200
+ console.log(` ${chalk13.dim(t("lang_current") + ":")} ${config.language}`);
2905
3201
  console.log();
2906
- console.log(chalk12.dim(" \u652F\u6301\u7684\u8BED\u8A00: zh_CN, en_US"));
2907
- console.log(chalk12.dim(" \u7528\u6CD5: install-helper lang set <language>"));
3202
+ console.log(chalk13.dim(` ${t("lang_supported")}`));
3203
+ console.log(chalk13.dim(` ${t("lang_usage")}`));
2908
3204
  console.log();
2909
3205
  return;
2910
3206
  }
2911
3207
  if (action === "set") {
2912
3208
  if (!value) {
2913
- console.log(chalk12.red(" \u8BF7\u6307\u5B9A\u8BED\u8A00: install-helper lang set zh_CN"));
3209
+ console.log(chalk13.red(` ${t("lang_specify")}`));
2914
3210
  return;
2915
3211
  }
2916
3212
  if (value !== "zh_CN" && value !== "en_US") {
2917
- console.log(chalk12.red(` ${t("lang_invalid")}`));
3213
+ console.log(chalk13.red(` ${t("lang_invalid")}`));
2918
3214
  return;
2919
3215
  }
2920
3216
  updateConfig({ language: value });
2921
3217
  setLanguage(value);
2922
3218
  console.log();
2923
- console.log(chalk12.green(` \u2713 ${t("lang_set")} ${value}`));
3219
+ console.log(chalk13.green(` \u2713 ${t("lang_set")} ${value}`));
2924
3220
  console.log();
2925
3221
  return;
2926
3222
  }
2927
- console.log(chalk12.red(` \u672A\u77E5\u64CD\u4F5C: ${action}`));
2928
- console.log(chalk12.dim(" \u652F\u6301\u7684\u64CD\u4F5C: show, set"));
3223
+ console.log(chalk13.red(` ${t("lang_unknown_action")}: ${action}`));
3224
+ console.log(chalk13.dim(` ${t("lang_supported_actions")}`));
2929
3225
  }
2930
3226
 
2931
3227
  // src/cli.ts
@@ -2935,7 +3231,7 @@ function createCLI() {
2935
3231
  setLanguage(config.language);
2936
3232
  }
2937
3233
  const program2 = new Command();
2938
- program2.name("install-helper").description("Install Helper - Interactive installer for CANN operator development skills").version("0.0.2-beta.6");
3234
+ program2.name("install-helper").description("CANNBot Install Helper - Interactive installer for CANN operator development skills").version("0.0.2-beta.7");
2939
3235
  program2.command("init", { isDefault: false }).description("Run interactive installation wizard").action(async () => {
2940
3236
  await initCommand();
2941
3237
  });