@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 +486 -190
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
8
|
-
import
|
|
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
|
|
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
|
|
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
|
|
1487
|
-
import { join as
|
|
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 =
|
|
1675
|
-
if (!
|
|
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
|
|
1743
|
-
import { join as
|
|
1744
|
-
import { select as
|
|
1745
|
-
import
|
|
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 =
|
|
2021
|
+
const skillsDir = join10(configRoot, "skills");
|
|
1750
2022
|
const installPath = level === "project" ? process.cwd() : configRoot;
|
|
1751
|
-
if (!
|
|
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 =
|
|
1763
|
-
const targetPath =
|
|
1764
|
-
if (!
|
|
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 (
|
|
1770
|
-
|
|
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 =
|
|
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 =
|
|
2063
|
+
const targetPath = join10(skillsDir, skillId);
|
|
1792
2064
|
try {
|
|
1793
|
-
if (
|
|
1794
|
-
|
|
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 (
|
|
2081
|
+
if (existsSync10(skillsDir)) {
|
|
1810
2082
|
try {
|
|
1811
|
-
const entries =
|
|
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 (
|
|
2091
|
+
if (existsSync10(configRoot)) {
|
|
1820
2092
|
try {
|
|
1821
|
-
const entries =
|
|
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
|
|
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
|
|
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(
|
|
1922
|
-
console.log(
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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
|
|
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
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
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 ?
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
2266
|
+
chalk5.green(" \u2713") + ` ${result.displayName} (${result.skillsCount} skills, ${result.agentsCount} agents)`
|
|
1995
2267
|
);
|
|
1996
2268
|
} else {
|
|
1997
|
-
console.log(
|
|
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
|
-
|
|
2283
|
+
chalk5.bold(` ${t("install_done")}!`),
|
|
2012
2284
|
"",
|
|
2013
|
-
` ${
|
|
2014
|
-
` ${
|
|
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
|
-
|
|
2017
|
-
` ${
|
|
2018
|
-
` ${
|
|
2019
|
-
` ${
|
|
2020
|
-
` ${
|
|
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
|
-
` ${
|
|
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
|
|
2037
|
-
import { join as
|
|
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 (
|
|
2314
|
+
if (existsSync11(join11(cwd, "package.json")) && (() => {
|
|
2043
2315
|
try {
|
|
2044
|
-
const pkg = JSON.parse(readFileSync5(
|
|
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("
|
|
2051
|
-
logger.info("
|
|
2052
|
-
logger.info("
|
|
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
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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")} ${
|
|
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")}: ${
|
|
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: ${
|
|
2247
|
-
logger.info(`\u542F\u52A8 ${
|
|
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
|
|
2270
|
-
import { existsSync as
|
|
2271
|
-
import { join as
|
|
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(
|
|
2275
|
-
console.log(
|
|
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(
|
|
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
|
-
|
|
2559
|
+
chalk7.green(" \u2713") + ` ${getToolDisplayName(tool)}${detected.version ? ` v${detected.version}` : ""}`
|
|
2288
2560
|
);
|
|
2289
2561
|
} else {
|
|
2290
|
-
console.log(
|
|
2562
|
+
console.log(chalk7.dim(" \u2014") + ` ${getToolDisplayName(tool)} \u2014 \u672A\u5B89\u88C5`);
|
|
2291
2563
|
}
|
|
2292
2564
|
}
|
|
2293
2565
|
console.log();
|
|
2294
|
-
console.log(
|
|
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
|
-
|
|
2574
|
+
chalk7.green(" \u2713") + ` ${plugin.id.padEnd(30)} ${inst.skillsCount} skills, ${inst.agentsCount} agents`
|
|
2303
2575
|
);
|
|
2304
2576
|
} else {
|
|
2305
|
-
console.log(
|
|
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(
|
|
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 (
|
|
2586
|
+
if (existsSync12(skillsDir)) {
|
|
2315
2587
|
const brokenLinks = checkBrokenLinks(skillsDir);
|
|
2316
2588
|
if (brokenLinks === 0) {
|
|
2317
|
-
const count =
|
|
2318
|
-
console.log(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
2605
|
+
console.log(chalk7.green(" \u2713") + ` ${t("doctor_fix_rebuilding")}: \u5DF2\u521B\u5EFA ${skillsDir}`);
|
|
2334
2606
|
}
|
|
2335
2607
|
}
|
|
2336
|
-
if (
|
|
2608
|
+
if (existsSync12(agentsDir)) {
|
|
2337
2609
|
const brokenLinks = checkBrokenLinks(agentsDir);
|
|
2338
2610
|
if (brokenLinks === 0) {
|
|
2339
|
-
const count =
|
|
2340
|
-
console.log(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
2631
|
+
console.log(chalk7.bold(` ${t("doctor_config")}`));
|
|
2360
2632
|
const configFile = getConfigFileName(primaryTool);
|
|
2361
|
-
const configPath =
|
|
2362
|
-
if (
|
|
2363
|
-
console.log(
|
|
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(
|
|
2637
|
+
console.log(chalk7.dim(" \u2014") + ` ${configFile} \u4E0D\u5B58\u5728`);
|
|
2366
2638
|
}
|
|
2367
2639
|
console.log();
|
|
2368
|
-
console.log(
|
|
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 =
|
|
2655
|
+
const entries = readdirSync5(dir);
|
|
2384
2656
|
for (const entry of entries) {
|
|
2385
|
-
const fullPath =
|
|
2657
|
+
const fullPath = join12(dir, entry);
|
|
2386
2658
|
try {
|
|
2387
2659
|
const stats = lstatSync3(fullPath);
|
|
2388
2660
|
if (stats.isSymbolicLink()) {
|
|
2389
|
-
if (!
|
|
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 =
|
|
2676
|
+
const entries = readdirSync5(dir);
|
|
2405
2677
|
for (const entry of entries) {
|
|
2406
|
-
const fullPath =
|
|
2678
|
+
const fullPath = join12(dir, entry);
|
|
2407
2679
|
try {
|
|
2408
2680
|
const stats = lstatSync3(fullPath);
|
|
2409
2681
|
if (stats.isSymbolicLink()) {
|
|
2410
|
-
if (!
|
|
2411
|
-
|
|
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
|
|
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(
|
|
2702
|
+
console.log(chalk8.bold(` ${t("status_title")}`));
|
|
2431
2703
|
console.log();
|
|
2432
2704
|
if (installed.length === 0) {
|
|
2433
|
-
console.log(
|
|
2434
|
-
console.log(
|
|
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
|
-
|
|
2712
|
+
chalk8.green(" \u2713") + ` ${inst.displayName}` + chalk8.dim(` (${inst.tool}, ${inst.level})`)
|
|
2441
2713
|
);
|
|
2442
2714
|
console.log(
|
|
2443
|
-
|
|
2715
|
+
chalk8.dim(` ${inst.skillsCount} skills, ${inst.agentsCount} agents`)
|
|
2444
2716
|
);
|
|
2445
|
-
console.log(
|
|
2446
|
-
console.log(
|
|
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
|
|
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(
|
|
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(
|
|
2503
|
-
logger.info(`${t("skill_install_progress")} ${
|
|
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
|
-
|
|
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")}: ${
|
|
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: ${
|
|
2522
|
-
logger.info(`\u542F\u52A8 ${
|
|
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: ${
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
2627
|
-
logger.info(`${t("skill_install_progress")} ${
|
|
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
|
-
|
|
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")}: ${
|
|
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: ${
|
|
2644
|
-
logger.info(`\u542F\u52A8 ${
|
|
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
|
|
2677
|
-
import
|
|
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(
|
|
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}
|
|
2702
|
-
logger.info(
|
|
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(
|
|
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 (
|
|
2711
|
-
|
|
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 (
|
|
2723
|
-
const entries =
|
|
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(
|
|
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}
|
|
3036
|
+
logger.warn(`${plugin.displayName}${t("uninstall_files_gone")}`);
|
|
2741
3037
|
}
|
|
2742
3038
|
}
|
|
2743
3039
|
if (skills.length > 0) {
|
|
2744
|
-
logger.info(
|
|
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")}: ${
|
|
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
|
|
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 ${
|
|
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
|
|
2850
|
-
import { existsSync as
|
|
2851
|
-
import { join as
|
|
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(
|
|
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 ?
|
|
3156
|
+
const statusText = isInstalled ? chalk12.green(`\u2713 ${t("status_installed")}`) : chalk12.dim(`\u2014 ${t("status_not_installed")}`);
|
|
2861
3157
|
console.log();
|
|
2862
|
-
console.log(
|
|
2863
|
-
console.log(
|
|
3158
|
+
console.log(chalk12.bold(` ${plugin.displayName}`));
|
|
3159
|
+
console.log(chalk12.dim(" " + "\u2500".repeat(40)));
|
|
2864
3160
|
console.log();
|
|
2865
|
-
console.log(` ${
|
|
2866
|
-
console.log(` ${
|
|
2867
|
-
console.log(` ${
|
|
2868
|
-
console.log(` ${
|
|
2869
|
-
console.log(` ${
|
|
2870
|
-
console.log(` ${
|
|
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 =
|
|
2876
|
-
if (
|
|
2877
|
-
console.log(` ${
|
|
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 =
|
|
2880
|
-
if (
|
|
2881
|
-
const agentFiles =
|
|
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(` ${
|
|
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
|
|
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(
|
|
2902
|
-
console.log(
|
|
3197
|
+
console.log(chalk13.bold(` ${t("lang_title")}`));
|
|
3198
|
+
console.log(chalk13.dim(" " + "\u2500".repeat(40)));
|
|
2903
3199
|
console.log();
|
|
2904
|
-
console.log(` ${
|
|
3200
|
+
console.log(` ${chalk13.dim(t("lang_current") + ":")} ${config.language}`);
|
|
2905
3201
|
console.log();
|
|
2906
|
-
console.log(
|
|
2907
|
-
console.log(
|
|
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(
|
|
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(
|
|
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(
|
|
3219
|
+
console.log(chalk13.green(` \u2713 ${t("lang_set")} ${value}`));
|
|
2924
3220
|
console.log();
|
|
2925
3221
|
return;
|
|
2926
3222
|
}
|
|
2927
|
-
console.log(
|
|
2928
|
-
console.log(
|
|
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.
|
|
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
|
});
|