@cannbot-ai/install-helper 0.0.2-beta.5 → 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) {
@@ -630,7 +690,7 @@ function printBoxTitle(title, width = 65) {
630
690
  }
631
691
  function showOperationHints(isCheckbox = false) {
632
692
  if (isCheckbox) {
633
- console.log(` \u{1F4A1} \x1B[36m\u2191\u2193\x1B[0m \u79FB\u52A8 | \x1B[36m\u7A7A\u683C\x1B[0m \u52FE\u9009 | \x1B[36m\u23CE\x1B[0m \u786E\u8BA4
693
+ console.log(` \u{1F4A1} \x1B[36m\u2191\u2193\x1B[0m \u79FB\u52A8 | \x1B[36m\u7A7A\u683C\x1B[0m \u52FE\u9009 | \x1B[36m\u23CE\x1B[0m \u786E\u8BA4\uFF08\u4E0D\u9009\u6309\u56DE\u8F66\u53EF\u8FD4\u56DE\uFF09
634
694
  `);
635
695
  } else {
636
696
  console.log(` \u{1F4A1} \x1B[36m\u2191\u2193\x1B[0m \u79FB\u52A8 | \x1B[36m\u23CE\x1B[0m \u786E\u8BA4
@@ -909,9 +969,6 @@ async function stepPlugins(tool, level) {
909
969
  checked: false
910
970
  };
911
971
  });
912
- choices.push(new Separator("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
913
- choices.push({ name: "<- " + t("wizard_back"), value: BACK, checked: false });
914
- choices.push({ name: "x " + t("wizard_cancel"), value: CANCEL, checked: false });
915
972
  showOperationHints(true);
916
973
  const selected = await checkbox({
917
974
  message: t("wizard_select_plugins"),
@@ -921,13 +978,7 @@ async function stepPlugins(tool, level) {
921
978
  theme: checkboxTheme,
922
979
  pageSize: 15
923
980
  });
924
- if (selected.includes(CANCEL)) {
925
- return CANCEL;
926
- }
927
- if (selected.includes(BACK)) {
928
- return BACK;
929
- }
930
- const pluginIds = selected.filter((v) => v !== BACK && v !== CANCEL);
981
+ const pluginIds = selected;
931
982
  if (pluginIds.length === 0) {
932
983
  const action = await select({
933
984
  message: t("wizard_no_selection"),
@@ -979,7 +1030,7 @@ import { execa as execa2 } from "execa";
979
1030
 
980
1031
  // src/core/scanner.ts
981
1032
  import { existsSync as existsSync5, readdirSync, readFileSync as readFileSync3, statSync, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
982
- import { join as join5, dirname } from "path";
1033
+ import { join as join5 } from "path";
983
1034
  import { parse as parseYaml } from "yaml";
984
1035
  var EXCLUDE_DIRS = /* @__PURE__ */ new Set([
985
1036
  "node_modules",
@@ -1492,8 +1543,8 @@ function createRepositoryManager(customPath) {
1492
1543
  }
1493
1544
 
1494
1545
  // src/core/installer.ts
1495
- import { existsSync as existsSync8 } from "fs";
1496
- import { join as join8 } from "path";
1546
+ import { existsSync as existsSync9 } from "fs";
1547
+ import { join as join9 } from "path";
1497
1548
  import { execa as execa3 } from "execa";
1498
1549
 
1499
1550
  // src/core/record.ts
@@ -1667,6 +1718,179 @@ function getInstalledSkills(tool, level, installPath) {
1667
1718
  return record[tool]?.[level]?.[installPath]?.skills || [];
1668
1719
  }
1669
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
+
1670
1894
  // src/core/installer.ts
1671
1895
  async function installPlugin(opts) {
1672
1896
  const plugin = getPluginById(opts.pluginId);
@@ -1680,8 +1904,8 @@ async function installPlugin(opts) {
1680
1904
  warnings: []
1681
1905
  };
1682
1906
  }
1683
- const scriptPath = join8(opts.repoPath, plugin.dir, plugin.script);
1684
- if (!existsSync8(scriptPath)) {
1907
+ const scriptPath = join9(opts.repoPath, plugin.dir, plugin.script);
1908
+ if (!existsSync9(scriptPath)) {
1685
1909
  return {
1686
1910
  success: false,
1687
1911
  pluginId: opts.pluginId,
@@ -1696,13 +1920,44 @@ async function installPlugin(opts) {
1696
1920
  args.push(opts.installPath);
1697
1921
  }
1698
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
+ }
1699
1955
  try {
1700
1956
  await execa3("bash", [scriptPath, ...args], {
1701
1957
  cwd,
1702
1958
  timeout: 3e5,
1703
1959
  stdio: "pipe"
1704
1960
  });
1705
- const configRoot = getConfigRoot(opts.tool, opts.level, opts.installPath);
1706
1961
  const manifest = readManifest(configRoot);
1707
1962
  let skillsCount = 0;
1708
1963
  let agentsCount = 0;
@@ -1723,6 +1978,14 @@ async function installPlugin(opts) {
1723
1978
  configRoot,
1724
1979
  manifest
1725
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
+ }
1726
1989
  writeRecord(record);
1727
1990
  } catch {
1728
1991
  }
@@ -1748,16 +2011,16 @@ async function installPlugin(opts) {
1748
2011
  }
1749
2012
 
1750
2013
  // src/core/skill-installer.ts
1751
- import { existsSync as existsSync9, mkdirSync as mkdirSync5, symlinkSync, unlinkSync as unlinkSync2, readdirSync as readdirSync3, rmdirSync, realpathSync, lstatSync as lstatSync2 } from "fs";
1752
- import { join as join9 } from "path";
1753
- import { select as select2, checkbox as checkbox2, Separator as Separator2 } from "@inquirer/prompts";
1754
- 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";
1755
2018
  import Table from "cli-table3";
1756
2019
  async function installSkills(skillIds, tool, level, repoPath) {
1757
2020
  const configRoot = getConfigRoot(tool, level);
1758
- const skillsDir = join9(configRoot, "skills");
2021
+ const skillsDir = join10(configRoot, "skills");
1759
2022
  const installPath = level === "project" ? process.cwd() : configRoot;
1760
- if (!existsSync9(skillsDir)) {
2023
+ if (!existsSync10(skillsDir)) {
1761
2024
  mkdirSync5(skillsDir, { recursive: true });
1762
2025
  }
1763
2026
  const results = [];
@@ -1768,15 +2031,15 @@ async function installSkills(skillIds, tool, level, repoPath) {
1768
2031
  results.push({ skillId, success: false, error: "Skill not found in registry" });
1769
2032
  continue;
1770
2033
  }
1771
- const sourcePath = join9(repoPath, skill.source, skill.id);
1772
- const targetPath = join9(skillsDir, skillId);
1773
- if (!existsSync9(sourcePath)) {
2034
+ const sourcePath = join10(repoPath, skill.source, skill.id);
2035
+ const targetPath = join10(skillsDir, skillId);
2036
+ if (!existsSync10(sourcePath)) {
1774
2037
  results.push({ skillId, success: false, error: `Source not found: ${sourcePath}` });
1775
2038
  continue;
1776
2039
  }
1777
2040
  try {
1778
- if (existsSync9(targetPath) || isSymlink2(targetPath)) {
1779
- unlinkSync2(targetPath);
2041
+ if (existsSync10(targetPath) || isSymlink2(targetPath)) {
2042
+ unlinkSync3(targetPath);
1780
2043
  }
1781
2044
  symlinkSync(realpathSync(sourcePath), targetPath);
1782
2045
  results.push({ skillId, success: true });
@@ -1792,15 +2055,15 @@ async function installSkills(skillIds, tool, level, repoPath) {
1792
2055
  }
1793
2056
  async function uninstallSkills(skillIds, tool, level) {
1794
2057
  const configRoot = getConfigRoot(tool, level);
1795
- const skillsDir = join9(configRoot, "skills");
2058
+ const skillsDir = join10(configRoot, "skills");
1796
2059
  const installPath = level === "project" ? process.cwd() : configRoot;
1797
2060
  const results = [];
1798
2061
  const removedIds = [];
1799
2062
  for (const skillId of skillIds) {
1800
- const targetPath = join9(skillsDir, skillId);
2063
+ const targetPath = join10(skillsDir, skillId);
1801
2064
  try {
1802
- if (existsSync9(targetPath) || isSymlink2(targetPath)) {
1803
- unlinkSync2(targetPath);
2065
+ if (existsSync10(targetPath) || isSymlink2(targetPath)) {
2066
+ unlinkSync3(targetPath);
1804
2067
  results.push({ skillId, success: true });
1805
2068
  removedIds.push(skillId);
1806
2069
  logger.step(` \u79FB\u9664: ${skillId}`);
@@ -1815,9 +2078,9 @@ async function uninstallSkills(skillIds, tool, level) {
1815
2078
  if (removedIds.length > 0) {
1816
2079
  removeSkillsFromRecord(removedIds, tool, level, installPath);
1817
2080
  }
1818
- if (existsSync9(skillsDir)) {
2081
+ if (existsSync10(skillsDir)) {
1819
2082
  try {
1820
- const entries = readdirSync3(skillsDir);
2083
+ const entries = readdirSync4(skillsDir);
1821
2084
  if (entries.length === 0) {
1822
2085
  rmdirSync(skillsDir);
1823
2086
  logger.step(` \u6E05\u7406\u7A7A\u76EE\u5F55: skills/`);
@@ -1825,9 +2088,9 @@ async function uninstallSkills(skillIds, tool, level) {
1825
2088
  } catch {
1826
2089
  }
1827
2090
  }
1828
- if (existsSync9(configRoot)) {
2091
+ if (existsSync10(configRoot)) {
1829
2092
  try {
1830
- const entries = readdirSync3(configRoot);
2093
+ const entries = readdirSync4(configRoot);
1831
2094
  if (entries.length === 0) {
1832
2095
  rmdirSync(configRoot);
1833
2096
  logger.step(` \u6E05\u7406\u7A7A\u76EE\u5F55: ${configRoot.split("/").pop()}/`);
@@ -1857,7 +2120,7 @@ async function interactiveSkillSelect() {
1857
2120
  { name: "x " + t("wizard_cancel"), value: CANCEL3 }
1858
2121
  ];
1859
2122
  showOperationHints();
1860
- selectedCategoryId = await select2({
2123
+ selectedCategoryId = await select3({
1861
2124
  message: t("skill_select_category"),
1862
2125
  choices: categoryChoices,
1863
2126
  loop: false,
@@ -1892,9 +2155,6 @@ async function interactiveSkillSelect() {
1892
2155
  checked: false
1893
2156
  };
1894
2157
  });
1895
- skillChoices.push(new Separator2("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
1896
- skillChoices.push({ name: "<- " + t("wizard_back"), value: BACK3, checked: false });
1897
- skillChoices.push({ name: "x " + t("wizard_cancel"), value: CANCEL3, checked: false });
1898
2158
  showOperationHints(true);
1899
2159
  const selectedSkills = await checkbox2({
1900
2160
  message: t("skill_select_items"),
@@ -1904,16 +2164,9 @@ async function interactiveSkillSelect() {
1904
2164
  theme: checkboxTheme,
1905
2165
  pageSize: 15
1906
2166
  });
1907
- if (selectedSkills.includes(CANCEL3)) {
1908
- return "cancel";
1909
- }
1910
- if (selectedSkills.includes(BACK3)) {
1911
- step = 0;
1912
- break;
1913
- }
1914
- const skillIds = selectedSkills.filter((v) => v !== BACK3 && v !== CANCEL3);
2167
+ const skillIds = selectedSkills;
1915
2168
  if (skillIds.length === 0) {
1916
- const action = await select2({
2169
+ const action = await select3({
1917
2170
  message: t("wizard_no_selection"),
1918
2171
  choices: [
1919
2172
  new Separator2("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
@@ -1937,11 +2190,11 @@ async function interactiveSkillSelect() {
1937
2190
  function listAllSkills() {
1938
2191
  const categories = getAllCategories();
1939
2192
  console.log();
1940
- console.log(chalk3.bold(` ${t("skill_list_title")}`));
1941
- console.log(chalk3.dim(" " + "\u2500".repeat(60)));
2193
+ console.log(chalk4.bold(` ${t("skill_list_title")}`));
2194
+ console.log(chalk4.dim(" " + "\u2500".repeat(60)));
1942
2195
  for (const category of categories) {
1943
2196
  console.log();
1944
- 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)`));
1945
2198
  const table = new Table({
1946
2199
  style: { head: [], border: [] },
1947
2200
  colWidths: [35, 45],
@@ -1949,14 +2202,14 @@ function listAllSkills() {
1949
2202
  });
1950
2203
  for (const skill of category.skills) {
1951
2204
  table.push([
1952
- chalk3.cyan(skill.id),
2205
+ chalk4.cyan(skill.id),
1953
2206
  skill.description
1954
2207
  ]);
1955
2208
  }
1956
2209
  console.log(table.toString());
1957
2210
  }
1958
2211
  console.log();
1959
- console.log(chalk3.dim(` \u5171 ${getAllSkills().length} \u4E2A Skills`));
2212
+ console.log(chalk4.dim(` \u5171 ${getAllSkills().length} \u4E2A Skills`));
1960
2213
  console.log();
1961
2214
  }
1962
2215
  function isSymlink2(path) {
@@ -1968,22 +2221,22 @@ function isSymlink2(path) {
1968
2221
  }
1969
2222
 
1970
2223
  // src/ui/display.ts
1971
- import chalk4 from "chalk";
2224
+ import chalk5 from "chalk";
1972
2225
  import Table2 from "cli-table3";
1973
2226
  function printPluginList(plugins, installed) {
1974
2227
  const table = new Table2({
1975
2228
  head: [
1976
- chalk4.cyan(t("list_id")),
1977
- chalk4.cyan(t("list_name")),
1978
- chalk4.cyan(t("list_status")),
1979
- chalk4.cyan(t("list_skills")),
1980
- 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"))
1981
2234
  ],
1982
2235
  style: { head: [], border: [] }
1983
2236
  });
1984
2237
  plugins.forEach((plugin, index) => {
1985
2238
  const isInstalled = installed.has(plugin.id);
1986
- 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`);
1987
2240
  table.push([
1988
2241
  String(index + 1),
1989
2242
  plugin.displayName,
@@ -1993,7 +2246,7 @@ function printPluginList(plugins, installed) {
1993
2246
  ]);
1994
2247
  });
1995
2248
  console.log();
1996
- console.log(chalk4.bold(` ${t("list_title")} (${plugins.length} \u4E2A)`));
2249
+ console.log(chalk5.bold(` ${t("list_title")} (${plugins.length} \u4E2A)`));
1997
2250
  console.log(table.toString());
1998
2251
  console.log();
1999
2252
  }
@@ -2002,7 +2255,7 @@ function printInstallSummary(results) {
2002
2255
  const totalCount = results.length;
2003
2256
  console.log();
2004
2257
  console.log(
2005
- chalk4.bold(
2258
+ chalk5.bold(
2006
2259
  ` ${t("install_done")}! ${successCount}/${totalCount} ${t("install_success")}`
2007
2260
  )
2008
2261
  );
@@ -2010,10 +2263,10 @@ function printInstallSummary(results) {
2010
2263
  for (const result of results) {
2011
2264
  if (result.success) {
2012
2265
  console.log(
2013
- chalk4.green(" \u2713") + ` ${result.displayName} (${result.skillsCount} skills, ${result.agentsCount} agents)`
2266
+ chalk5.green(" \u2713") + ` ${result.displayName} (${result.skillsCount} skills, ${result.agentsCount} agents)`
2014
2267
  );
2015
2268
  } else {
2016
- console.log(chalk4.red(" \u2717") + ` ${result.displayName}`);
2269
+ console.log(chalk5.red(" \u2717") + ` ${result.displayName}`);
2017
2270
  }
2018
2271
  }
2019
2272
  console.log();
@@ -2027,21 +2280,21 @@ function printEnhancedSummary(results, tool, configRoot) {
2027
2280
  }
2028
2281
  const toolName = getToolDisplayName(tool);
2029
2282
  const lines = [
2030
- chalk4.bold(` ${t("install_done")}!`),
2283
+ chalk5.bold(` ${t("install_done")}!`),
2031
2284
  "",
2032
- ` ${chalk4.dim(t("install_installed_to") + ":")} ${configRoot}`,
2033
- ` ${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`,
2034
2287
  "",
2035
- chalk4.bold(` ${t("install_enhanced_next_steps")}:`),
2036
- ` ${chalk4.cyan("1.")} ${t("install_enhanced_launch")}: ${chalk4.green(toolName.toLowerCase())}`,
2037
- ` ${chalk4.cyan("2.")} ${t("install_enhanced_try")}: ${chalk4.green("\u5E2E\u6211\u5F00\u53D1\u4E00\u4E2A Abs \u7B97\u5B50")}`,
2038
- ` ${chalk4.cyan("3.")} ${t("install_enhanced_more")}: ${chalk4.green("install-helper list")}`,
2039
- ` ${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")}`,
2040
2293
  ""
2041
2294
  ];
2042
2295
  if (successResults.length === 1) {
2043
2296
  lines.push(
2044
- ` ${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`)}`
2045
2298
  );
2046
2299
  }
2047
2300
  console.log();
@@ -2052,23 +2305,23 @@ function printEnhancedSummary(results, tool, configRoot) {
2052
2305
  }
2053
2306
 
2054
2307
  // src/commands/init.ts
2055
- import { existsSync as existsSync10, readFileSync as readFileSync5 } from "fs";
2056
- import { join as join10 } from "path";
2308
+ import { existsSync as existsSync11, readFileSync as readFileSync5 } from "fs";
2309
+ import { join as join11 } from "path";
2057
2310
  var BACK2 = "__back__";
2058
2311
  var CANCEL2 = "__cancel__";
2059
2312
  async function initCommand() {
2060
2313
  const cwd = process.cwd();
2061
- if (existsSync10(join10(cwd, "package.json")) && (() => {
2314
+ if (existsSync11(join11(cwd, "package.json")) && (() => {
2062
2315
  try {
2063
- const pkg = JSON.parse(readFileSync5(join10(cwd, "package.json"), "utf-8"));
2316
+ const pkg = JSON.parse(readFileSync5(join11(cwd, "package.json"), "utf-8"));
2064
2317
  return pkg.name === "@cannbot-ai/install-helper";
2065
2318
  } catch {
2066
2319
  return false;
2067
2320
  }
2068
2321
  })()) {
2069
- logger.warn("\u5F53\u524D\u76EE\u5F55\u770B\u8D77\u6765\u662F install-helper \u5305\u76EE\u5F55");
2070
- 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");
2071
- 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"));
2072
2325
  return;
2073
2326
  }
2074
2327
  printBanner(t("wizard_title"));
@@ -2128,7 +2381,7 @@ async function selectMode() {
2128
2381
  { name: "x " + t("wizard_cancel"), value: CANCEL3 }
2129
2382
  ];
2130
2383
  showOperationHints();
2131
- const result = await select3({
2384
+ const result = await select4({
2132
2385
  message: t("wizard_select_mode"),
2133
2386
  choices,
2134
2387
  loop: false,
@@ -2141,7 +2394,7 @@ async function pluginInstallFlow() {
2141
2394
  const answers = await runWizard();
2142
2395
  if (!answers.confirmed) {
2143
2396
  if (answers.back) return "back";
2144
- logger.info("\u5DF2\u53D6\u6D88\u5B89\u88C5");
2397
+ logger.info(t("init_cancelled"));
2145
2398
  return "done";
2146
2399
  }
2147
2400
  const repoManager = createRepositoryManager();
@@ -2202,7 +2455,7 @@ async function skillInstallFlow() {
2202
2455
  const result = await selectToolWithDetection();
2203
2456
  if (result === "back") return "back";
2204
2457
  if (result === "cancel") {
2205
- logger.info("\u5DF2\u53D6\u6D88\u5B89\u88C5");
2458
+ logger.info(t("init_cancelled"));
2206
2459
  return "done";
2207
2460
  }
2208
2461
  tool = result;
@@ -2216,7 +2469,7 @@ async function skillInstallFlow() {
2216
2469
  break;
2217
2470
  }
2218
2471
  if (result === CANCEL2) {
2219
- logger.info("\u5DF2\u53D6\u6D88\u5B89\u88C5");
2472
+ logger.info(t("init_cancelled"));
2220
2473
  return "done";
2221
2474
  }
2222
2475
  level = result;
@@ -2230,7 +2483,7 @@ async function skillInstallFlow() {
2230
2483
  break;
2231
2484
  }
2232
2485
  if (selectedSkills === "cancel") {
2233
- logger.info("\u5DF2\u53D6\u6D88\u5B89\u88C5");
2486
+ logger.info(t("init_cancelled"));
2234
2487
  return "done";
2235
2488
  }
2236
2489
  if (selectedSkills.length === 0) {
@@ -2242,7 +2495,7 @@ async function skillInstallFlow() {
2242
2495
  spinner.start();
2243
2496
  const repoPath = await repoManager.ensureRepo();
2244
2497
  spinner.succeed("\u63D2\u4EF6\u6570\u636E\u52A0\u8F7D\u5B8C\u6210");
2245
- 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...`);
2246
2499
  const results = await installSkills(selectedSkills, tool, level, repoPath);
2247
2500
  let successCount = 0;
2248
2501
  let failCount = 0;
@@ -2260,10 +2513,10 @@ async function skillInstallFlow() {
2260
2513
  }
2261
2514
  const configRoot = getConfigRoot(tool, level);
2262
2515
  logger.blank();
2263
- 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")}`);
2264
2517
  logger.blank();
2265
- logger.info(`\u5B89\u88C5\u5230: ${chalk5.cyan(configRoot + "/skills/")}`);
2266
- 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`);
2267
2520
  logger.blank();
2268
2521
  return "done";
2269
2522
  }
@@ -2285,32 +2538,32 @@ async function listCommand() {
2285
2538
  }
2286
2539
 
2287
2540
  // src/commands/doctor.ts
2288
- import chalk6 from "chalk";
2289
- import { existsSync as existsSync11, readdirSync as readdirSync4, lstatSync as lstatSync3, unlinkSync as unlinkSync3, mkdirSync as mkdirSync6 } from "fs";
2290
- 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";
2291
2544
  async function doctorCommand(options = {}) {
2292
2545
  console.log();
2293
- console.log(chalk6.bold(` ${t("doctor_title")}`));
2294
- console.log(chalk6.dim(" " + "\u2500".repeat(46)));
2546
+ console.log(chalk7.bold(` ${t("doctor_title")}`));
2547
+ console.log(chalk7.dim(" " + "\u2500".repeat(46)));
2295
2548
  let errors = 0;
2296
2549
  let warnings = 0;
2297
2550
  let fixes = 0;
2298
2551
  console.log();
2299
- console.log(chalk6.bold(` ${t("doctor_tools")}`));
2552
+ console.log(chalk7.bold(` ${t("doctor_tools")}`));
2300
2553
  const detectedTools = await detectTools();
2301
2554
  const allTools = getAllTools();
2302
2555
  for (const tool of allTools) {
2303
2556
  const detected = detectedTools.find((d) => d.name === tool);
2304
2557
  if (detected) {
2305
2558
  console.log(
2306
- chalk6.green(" \u2713") + ` ${getToolDisplayName(tool)}${detected.version ? ` v${detected.version}` : ""}`
2559
+ chalk7.green(" \u2713") + ` ${getToolDisplayName(tool)}${detected.version ? ` v${detected.version}` : ""}`
2307
2560
  );
2308
2561
  } else {
2309
- console.log(chalk6.dim(" \u2014") + ` ${getToolDisplayName(tool)} \u2014 \u672A\u5B89\u88C5`);
2562
+ console.log(chalk7.dim(" \u2014") + ` ${getToolDisplayName(tool)} \u2014 \u672A\u5B89\u88C5`);
2310
2563
  }
2311
2564
  }
2312
2565
  console.log();
2313
- console.log(chalk6.bold(` ${t("doctor_plugins")}`));
2566
+ console.log(chalk7.bold(` ${t("doctor_plugins")}`));
2314
2567
  const plugins = getAllPlugins();
2315
2568
  const installed = scanInstalled();
2316
2569
  const installedMap = new Map(installed.map((p) => [p.id, p]));
@@ -2318,73 +2571,73 @@ async function doctorCommand(options = {}) {
2318
2571
  const inst = installedMap.get(plugin.id);
2319
2572
  if (inst) {
2320
2573
  console.log(
2321
- 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`
2322
2575
  );
2323
2576
  } else {
2324
- 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`);
2325
2578
  }
2326
2579
  }
2327
2580
  console.log();
2328
- console.log(chalk6.bold(` ${t("doctor_links")}`));
2581
+ console.log(chalk7.bold(` ${t("doctor_links")}`));
2329
2582
  const primaryTool = detectedTools[0]?.name || "opencode";
2330
2583
  const configRoot = getConfigRoot(primaryTool, "project");
2331
2584
  const skillsDir = getSkillsDir(configRoot);
2332
2585
  const agentsDir = getAgentsDir(configRoot);
2333
- if (existsSync11(skillsDir)) {
2586
+ if (existsSync12(skillsDir)) {
2334
2587
  const brokenLinks = checkBrokenLinks(skillsDir);
2335
2588
  if (brokenLinks === 0) {
2336
- const count = readdirSync4(skillsDir).length;
2337
- 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`);
2338
2591
  } else {
2339
- 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`);
2340
2593
  warnings++;
2341
2594
  if (options.fix) {
2342
2595
  const fixed = fixBrokenLinks(skillsDir);
2343
2596
  fixes += fixed;
2344
- 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`);
2345
2598
  }
2346
2599
  }
2347
2600
  } else {
2348
- console.log(chalk6.dim(" \u2014") + ` ${skillsDir} \u2014 \u4E0D\u5B58\u5728`);
2601
+ console.log(chalk7.dim(" \u2014") + ` ${skillsDir} \u2014 \u4E0D\u5B58\u5728`);
2349
2602
  if (options.fix) {
2350
2603
  mkdirSync6(skillsDir, { recursive: true });
2351
2604
  fixes++;
2352
- 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}`);
2353
2606
  }
2354
2607
  }
2355
- if (existsSync11(agentsDir)) {
2608
+ if (existsSync12(agentsDir)) {
2356
2609
  const brokenLinks = checkBrokenLinks(agentsDir);
2357
2610
  if (brokenLinks === 0) {
2358
- const count = readdirSync4(agentsDir).length;
2359
- 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`);
2360
2613
  } else {
2361
- 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`);
2362
2615
  warnings++;
2363
2616
  if (options.fix) {
2364
2617
  const fixed = fixBrokenLinks(agentsDir);
2365
2618
  fixes += fixed;
2366
- 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`);
2367
2620
  }
2368
2621
  }
2369
2622
  } else {
2370
- console.log(chalk6.dim(" \u2014") + ` ${agentsDir} \u2014 \u4E0D\u5B58\u5728`);
2623
+ console.log(chalk7.dim(" \u2014") + ` ${agentsDir} \u2014 \u4E0D\u5B58\u5728`);
2371
2624
  if (options.fix) {
2372
2625
  mkdirSync6(agentsDir, { recursive: true });
2373
2626
  fixes++;
2374
- 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}`);
2375
2628
  }
2376
2629
  }
2377
2630
  console.log();
2378
- console.log(chalk6.bold(` ${t("doctor_config")}`));
2631
+ console.log(chalk7.bold(` ${t("doctor_config")}`));
2379
2632
  const configFile = getConfigFileName(primaryTool);
2380
- const configPath = join11(process.cwd(), configFile);
2381
- if (existsSync11(configPath)) {
2382
- 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`);
2383
2636
  } else {
2384
- console.log(chalk6.dim(" \u2014") + ` ${configFile} \u4E0D\u5B58\u5728`);
2637
+ console.log(chalk7.dim(" \u2014") + ` ${configFile} \u4E0D\u5B58\u5728`);
2385
2638
  }
2386
2639
  console.log();
2387
- console.log(chalk6.dim(" " + "\u2500".repeat(46)));
2640
+ console.log(chalk7.dim(" " + "\u2500".repeat(46)));
2388
2641
  if (options.fix && fixes > 0) {
2389
2642
  console.log(
2390
2643
  ` ${t("doctor_result")}: ${warnings} \u4E2A\u8B66\u544A, ${errors} \u4E2A\u9519\u8BEF, ${fixes} \u9879\u5DF2\u4FEE\u590D`
@@ -2399,13 +2652,13 @@ async function doctorCommand(options = {}) {
2399
2652
  function checkBrokenLinks(dir) {
2400
2653
  let broken = 0;
2401
2654
  try {
2402
- const entries = readdirSync4(dir);
2655
+ const entries = readdirSync5(dir);
2403
2656
  for (const entry of entries) {
2404
- const fullPath = join11(dir, entry);
2657
+ const fullPath = join12(dir, entry);
2405
2658
  try {
2406
2659
  const stats = lstatSync3(fullPath);
2407
2660
  if (stats.isSymbolicLink()) {
2408
- if (!existsSync11(fullPath)) {
2661
+ if (!existsSync12(fullPath)) {
2409
2662
  broken++;
2410
2663
  }
2411
2664
  }
@@ -2420,14 +2673,14 @@ function checkBrokenLinks(dir) {
2420
2673
  function fixBrokenLinks(dir) {
2421
2674
  let fixed = 0;
2422
2675
  try {
2423
- const entries = readdirSync4(dir);
2676
+ const entries = readdirSync5(dir);
2424
2677
  for (const entry of entries) {
2425
- const fullPath = join11(dir, entry);
2678
+ const fullPath = join12(dir, entry);
2426
2679
  try {
2427
2680
  const stats = lstatSync3(fullPath);
2428
2681
  if (stats.isSymbolicLink()) {
2429
- if (!existsSync11(fullPath)) {
2430
- unlinkSync3(fullPath);
2682
+ if (!existsSync12(fullPath)) {
2683
+ unlinkSync4(fullPath);
2431
2684
  fixed++;
2432
2685
  }
2433
2686
  }
@@ -2440,36 +2693,36 @@ function fixBrokenLinks(dir) {
2440
2693
  }
2441
2694
 
2442
2695
  // src/commands/status.ts
2443
- import chalk7 from "chalk";
2696
+ import chalk8 from "chalk";
2444
2697
  async function statusCommand() {
2445
2698
  const plugins = getAllPlugins();
2446
2699
  const installed = scanInstalled();
2447
2700
  const installedMap = new Map(installed.map((p) => [p.id, p]));
2448
2701
  console.log();
2449
- console.log(chalk7.bold(` ${t("status_title")}`));
2702
+ console.log(chalk8.bold(` ${t("status_title")}`));
2450
2703
  console.log();
2451
2704
  if (installed.length === 0) {
2452
- console.log(chalk7.dim(` ${t("status_none")}`));
2453
- console.log(chalk7.dim(` ${t("status_hint")}`));
2705
+ console.log(chalk8.dim(` ${t("status_none")}`));
2706
+ console.log(chalk8.dim(` ${t("status_hint")}`));
2454
2707
  console.log();
2455
2708
  return;
2456
2709
  }
2457
2710
  for (const inst of installed) {
2458
2711
  console.log(
2459
- chalk7.green(" \u2713") + ` ${inst.displayName}` + chalk7.dim(` (${inst.tool}, ${inst.level})`)
2712
+ chalk8.green(" \u2713") + ` ${inst.displayName}` + chalk8.dim(` (${inst.tool}, ${inst.level})`)
2460
2713
  );
2461
2714
  console.log(
2462
- chalk7.dim(` ${inst.skillsCount} skills, ${inst.agentsCount} agents`)
2715
+ chalk8.dim(` ${inst.skillsCount} skills, ${inst.agentsCount} agents`)
2463
2716
  );
2464
- console.log(chalk7.dim(` ${inst.configRoot}`));
2465
- 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}`));
2466
2719
  console.log();
2467
2720
  }
2468
2721
  }
2469
2722
 
2470
2723
  // src/commands/install.ts
2471
2724
  import { confirm } from "@inquirer/prompts";
2472
- import chalk8 from "chalk";
2725
+ import chalk9 from "chalk";
2473
2726
  async function installCommand(names, options) {
2474
2727
  if (options.list) {
2475
2728
  try {
@@ -2515,30 +2768,33 @@ async function installCommand(names, options) {
2515
2768
  }
2516
2769
  names = selectedSkills;
2517
2770
  const repoManager = createRepositoryManager();
2518
- const spinner = createSpinner(t("install_cloning"));
2771
+ const spinner = createSpinner("\u6B63\u5728\u52A0\u8F7D\u63D2\u4EF6\u6570\u636E...");
2519
2772
  spinner.start();
2520
2773
  const repoPath = await repoManager.ensureRepo();
2521
- spinner.succeed(t("install_repo_ready"));
2522
- 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...`);
2523
2776
  const level2 = options.level || "project";
2524
2777
  const results = await installSkills(names, tool2, level2, repoPath);
2525
2778
  let successCount = 0;
2526
2779
  let failCount = 0;
2527
- 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}]`;
2528
2784
  if (result.success) {
2529
- logger.success(`${result.skillId}`);
2785
+ logger.success(`${progress} ${result.skillId}`);
2530
2786
  successCount++;
2531
2787
  } else {
2532
- logger.error(`${result.skillId}: ${result.error}`);
2788
+ logger.error(`${progress} ${result.skillId}: ${result.error}`);
2533
2789
  failCount++;
2534
2790
  }
2535
2791
  }
2536
2792
  const configRoot = getConfigRoot(tool2, level2);
2537
2793
  logger.blank();
2538
- 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")}`);
2539
2795
  logger.blank();
2540
- logger.info(`\u5B89\u88C5\u5230: ${chalk8.cyan(configRoot + "/skills/")}`);
2541
- 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`);
2542
2798
  logger.blank();
2543
2799
  return;
2544
2800
  }
@@ -2573,7 +2829,7 @@ async function installCommand(names, options) {
2573
2829
  for (const p of allPlugins) {
2574
2830
  logger.step(` ${p.id} (${p.aliases.join(", ")})`);
2575
2831
  }
2576
- logger.info(`\u53EF\u7528 Skills: ${chalk8.cyan("install-helper install --list")}`);
2832
+ logger.info(`\u53EF\u7528 Skills: ${chalk9.cyan("install-helper install --list")}`);
2577
2833
  return;
2578
2834
  }
2579
2835
  let tool;
@@ -2612,10 +2868,10 @@ async function installCommand(names, options) {
2612
2868
  }
2613
2869
  if (pluginsToInstall.length > 0) {
2614
2870
  const repoManager = createRepositoryManager();
2615
- const spinner = createSpinner(t("install_cloning"));
2871
+ const spinner = createSpinner("\u6B63\u5728\u52A0\u8F7D\u63D2\u4EF6\u6570\u636E...");
2616
2872
  spinner.start();
2617
2873
  const repoPath = await repoManager.ensureRepo();
2618
- spinner.succeed(t("install_repo_ready"));
2874
+ spinner.succeed("\u63D2\u4EF6\u6570\u636E\u52A0\u8F7D\u5B8C\u6210");
2619
2875
  const allPlugins = getAllPlugins();
2620
2876
  const results = await installPlugins(
2621
2877
  pluginsToInstall,
@@ -2639,28 +2895,31 @@ async function installCommand(names, options) {
2639
2895
  }
2640
2896
  if (skills.length > 0) {
2641
2897
  const repoManager = createRepositoryManager();
2642
- const spinner = createSpinner(t("install_cloning"));
2898
+ const spinner = createSpinner("\u6B63\u5728\u52A0\u8F7D\u63D2\u4EF6\u6570\u636E...");
2643
2899
  spinner.start();
2644
2900
  const repoPath = await repoManager.ensureRepo();
2645
- spinner.succeed(t("install_repo_ready"));
2646
- 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...`);
2647
2903
  const results = await installSkills(skills, tool, level, repoPath);
2648
2904
  let successCount = 0;
2649
2905
  let failCount = 0;
2650
- 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}]`;
2651
2910
  if (result.success) {
2652
- logger.success(`${result.skillId}`);
2911
+ logger.success(`${progress} ${result.skillId}`);
2653
2912
  successCount++;
2654
2913
  } else {
2655
- logger.error(`${result.skillId}: ${result.error}`);
2914
+ logger.error(`${progress} ${result.skillId}: ${result.error}`);
2656
2915
  failCount++;
2657
2916
  }
2658
2917
  }
2659
2918
  logger.blank();
2660
- 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")}`);
2661
2920
  logger.blank();
2662
- logger.info(`\u5B89\u88C5\u5230: ${chalk8.cyan(getConfigRoot(tool, level) + "/skills/")}`);
2663
- 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`);
2664
2923
  logger.blank();
2665
2924
  }
2666
2925
  }
@@ -2692,8 +2951,8 @@ async function installPlugins(pluginIds, tool, level, repoPath) {
2692
2951
  }
2693
2952
 
2694
2953
  // src/commands/uninstall.ts
2695
- import { existsSync as existsSync12, unlinkSync as unlinkSync4, rmdirSync as rmdirSync2, readdirSync as readdirSync5, lstatSync as lstatSync4 } from "fs";
2696
- 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";
2697
2956
  async function uninstallCommand(names, options) {
2698
2957
  const tool = options.tool || "opencode";
2699
2958
  const level = options.level || "project";
@@ -2710,24 +2969,24 @@ async function uninstallCommand(names, options) {
2710
2969
  skills.push(skill.id);
2711
2970
  continue;
2712
2971
  }
2713
- logger.error(`\u672A\u627E\u5230: ${name}`);
2972
+ logger.error(`${t("uninstall_not_found")}: ${name}`);
2714
2973
  }
2715
2974
  for (const pluginId of plugins) {
2716
2975
  const plugin = findPlugin(pluginId);
2717
2976
  if (!plugin) continue;
2718
2977
  const record = readRecord(plugin.id);
2719
2978
  if (!record) {
2720
- 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`);
2721
- 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")}`);
2722
2981
  continue;
2723
2982
  }
2724
- logger.info(`\u6B63\u5728\u5378\u8F7D ${plugin.displayName}...`);
2983
+ logger.info(`${t("uninstall_in_progress")} ${plugin.displayName}...`);
2725
2984
  let removedFiles = 0;
2726
2985
  let removedDirs = 0;
2727
2986
  for (const filePath of record.files) {
2728
2987
  try {
2729
- if (existsSync12(filePath) || isSymlink3(filePath)) {
2730
- unlinkSync4(filePath);
2988
+ if (existsSync13(filePath) || isSymlink3(filePath)) {
2989
+ unlinkSync5(filePath);
2731
2990
  const name = filePath.split("/").pop() || filePath;
2732
2991
  logger.step(` \u79FB\u9664: ${name}`);
2733
2992
  removedFiles++;
@@ -2738,8 +2997,8 @@ async function uninstallCommand(names, options) {
2738
2997
  const sortedDirs = [...record.directories].sort((a, b) => b.length - a.length);
2739
2998
  for (const dirPath of sortedDirs) {
2740
2999
  try {
2741
- if (existsSync12(dirPath)) {
2742
- const entries = readdirSync5(dirPath);
3000
+ if (existsSync13(dirPath)) {
3001
+ const entries = readdirSync6(dirPath);
2743
3002
  if (entries.length === 0) {
2744
3003
  rmdirSync2(dirPath);
2745
3004
  const name = dirPath.split("/").pop() || dirPath;
@@ -2752,15 +3011,33 @@ async function uninstallCommand(names, options) {
2752
3011
  }
2753
3012
  deleteRecord(plugin.id);
2754
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
+ }
2755
3032
  const totalRemoved = removedFiles + removedDirs;
2756
3033
  if (totalRemoved > 0) {
2757
- 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`);
2758
3035
  } else {
2759
- 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")}`);
2760
3037
  }
2761
3038
  }
2762
3039
  if (skills.length > 0) {
2763
- logger.info(`\u6B63\u5728\u5378\u8F7D ${skills.length} \u4E2A Skills...`);
3040
+ logger.info(`${t("uninstall_skills_in_progress")} ${skills.length} \u4E2A Skills...`);
2764
3041
  const results = await uninstallSkills(skills, tool, level);
2765
3042
  let successCount = 0;
2766
3043
  let failCount = 0;
@@ -2772,7 +3049,7 @@ async function uninstallCommand(names, options) {
2772
3049
  }
2773
3050
  }
2774
3051
  logger.blank();
2775
- 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")}`);
2776
3053
  logger.blank();
2777
3054
  }
2778
3055
  }
@@ -2785,7 +3062,7 @@ function isSymlink3(path) {
2785
3062
  }
2786
3063
 
2787
3064
  // src/commands/update.ts
2788
- import chalk10 from "chalk";
3065
+ import chalk11 from "chalk";
2789
3066
  async function updateCommand(pluginNames, options) {
2790
3067
  let tool;
2791
3068
  if (options.tool) {
@@ -2803,7 +3080,7 @@ async function updateCommand(pluginNames, options) {
2803
3080
  pluginsToUpdate = manifests.map((m) => m.team);
2804
3081
  if (pluginsToUpdate.length === 0) {
2805
3082
  logger.info(t("update_no_plugins"));
2806
- 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`);
2807
3084
  return;
2808
3085
  }
2809
3086
  } else {
@@ -2865,42 +3142,42 @@ async function updateCommand(pluginNames, options) {
2865
3142
  }
2866
3143
 
2867
3144
  // src/commands/info.ts
2868
- import chalk11 from "chalk";
2869
- import { existsSync as existsSync13, readdirSync as readdirSync6 } from "fs";
2870
- 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";
2871
3148
  async function infoCommand(pluginName) {
2872
3149
  const plugin = findPlugin(pluginName);
2873
3150
  if (!plugin) {
2874
- console.log(chalk11.red(` ${t("info_not_found")}: ${pluginName}`));
3151
+ console.log(chalk12.red(` ${t("info_not_found")}: ${pluginName}`));
2875
3152
  return;
2876
3153
  }
2877
3154
  const installed = scanInstalled();
2878
3155
  const isInstalled = installed.some((p) => p.id === plugin.id);
2879
- 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")}`);
2880
3157
  console.log();
2881
- console.log(chalk11.bold(` ${plugin.displayName}`));
2882
- console.log(chalk11.dim(" " + "\u2500".repeat(40)));
3158
+ console.log(chalk12.bold(` ${plugin.displayName}`));
3159
+ console.log(chalk12.dim(" " + "\u2500".repeat(40)));
2883
3160
  console.log();
2884
- console.log(` ${chalk11.dim(t("info_description") + ":")} ${plugin.description}`);
2885
- console.log(` ${chalk11.dim("ID:")} ${plugin.id}`);
2886
- console.log(` ${chalk11.dim(t("info_status") + ":")} ${statusText}`);
2887
- console.log(` ${chalk11.dim(t("info_skills") + ":")} ${plugin.skills}`);
2888
- console.log(` ${chalk11.dim(t("info_agents") + ":")} ${plugin.agents}`);
2889
- 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(", ")}`);
2890
3167
  console.log();
2891
3168
  try {
2892
3169
  const repoManager = createRepositoryManager();
2893
3170
  const repoPath = await repoManager.ensureRepo();
2894
- const quickstartPath = join12(repoPath, plugin.dir, "quickstart.md");
2895
- if (existsSync13(quickstartPath)) {
2896
- 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}`);
2897
3174
  }
2898
- const agentsDir = join12(repoPath, plugin.dir, "agents");
2899
- if (existsSync13(agentsDir)) {
2900
- 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"));
2901
3178
  if (agentFiles.length > 0) {
2902
3179
  console.log();
2903
- console.log(` ${chalk11.bold("Agents:")}`);
3180
+ console.log(` ${chalk12.bold("Agents:")}`);
2904
3181
  for (const agent of agentFiles) {
2905
3182
  console.log(` \u2022 ${agent.replace(".md", "")}`);
2906
3183
  }
@@ -2912,39 +3189,39 @@ async function infoCommand(pluginName) {
2912
3189
  }
2913
3190
 
2914
3191
  // src/commands/lang.ts
2915
- import chalk12 from "chalk";
3192
+ import chalk13 from "chalk";
2916
3193
  async function langCommand(action, value) {
2917
3194
  const config = readConfig();
2918
3195
  if (!action || action === "show") {
2919
3196
  console.log();
2920
- console.log(chalk12.bold(` ${t("lang_title")}`));
2921
- console.log(chalk12.dim(" " + "\u2500".repeat(40)));
3197
+ console.log(chalk13.bold(` ${t("lang_title")}`));
3198
+ console.log(chalk13.dim(" " + "\u2500".repeat(40)));
2922
3199
  console.log();
2923
- console.log(` ${chalk12.dim(t("lang_current") + ":")} ${config.language}`);
3200
+ console.log(` ${chalk13.dim(t("lang_current") + ":")} ${config.language}`);
2924
3201
  console.log();
2925
- console.log(chalk12.dim(" \u652F\u6301\u7684\u8BED\u8A00: zh_CN, en_US"));
2926
- 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")}`));
2927
3204
  console.log();
2928
3205
  return;
2929
3206
  }
2930
3207
  if (action === "set") {
2931
3208
  if (!value) {
2932
- console.log(chalk12.red(" \u8BF7\u6307\u5B9A\u8BED\u8A00: install-helper lang set zh_CN"));
3209
+ console.log(chalk13.red(` ${t("lang_specify")}`));
2933
3210
  return;
2934
3211
  }
2935
3212
  if (value !== "zh_CN" && value !== "en_US") {
2936
- console.log(chalk12.red(` ${t("lang_invalid")}`));
3213
+ console.log(chalk13.red(` ${t("lang_invalid")}`));
2937
3214
  return;
2938
3215
  }
2939
3216
  updateConfig({ language: value });
2940
3217
  setLanguage(value);
2941
3218
  console.log();
2942
- console.log(chalk12.green(` \u2713 ${t("lang_set")} ${value}`));
3219
+ console.log(chalk13.green(` \u2713 ${t("lang_set")} ${value}`));
2943
3220
  console.log();
2944
3221
  return;
2945
3222
  }
2946
- console.log(chalk12.red(` \u672A\u77E5\u64CD\u4F5C: ${action}`));
2947
- 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")}`));
2948
3225
  }
2949
3226
 
2950
3227
  // src/cli.ts
@@ -2954,7 +3231,7 @@ function createCLI() {
2954
3231
  setLanguage(config.language);
2955
3232
  }
2956
3233
  const program2 = new Command();
2957
- program2.name("install-helper").description("Install Helper - Interactive installer for CANN operator development skills").version("0.0.2-beta.5");
3234
+ program2.name("install-helper").description("CANNBot Install Helper - Interactive installer for CANN operator development skills").version("0.0.2-beta.7");
2958
3235
  program2.command("init", { isDefault: false }).description("Run interactive installation wizard").action(async () => {
2959
3236
  await initCommand();
2960
3237
  });