@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 +489 -212
- 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) {
|
|
@@ -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
|
-
|
|
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
|
|
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
|
|
1496
|
-
import { join as
|
|
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 =
|
|
1684
|
-
if (!
|
|
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
|
|
1752
|
-
import { join as
|
|
1753
|
-
import { select as
|
|
1754
|
-
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";
|
|
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 =
|
|
2021
|
+
const skillsDir = join10(configRoot, "skills");
|
|
1759
2022
|
const installPath = level === "project" ? process.cwd() : configRoot;
|
|
1760
|
-
if (!
|
|
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 =
|
|
1772
|
-
const targetPath =
|
|
1773
|
-
if (!
|
|
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 (
|
|
1779
|
-
|
|
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 =
|
|
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 =
|
|
2063
|
+
const targetPath = join10(skillsDir, skillId);
|
|
1801
2064
|
try {
|
|
1802
|
-
if (
|
|
1803
|
-
|
|
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 (
|
|
2081
|
+
if (existsSync10(skillsDir)) {
|
|
1819
2082
|
try {
|
|
1820
|
-
const entries =
|
|
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 (
|
|
2091
|
+
if (existsSync10(configRoot)) {
|
|
1829
2092
|
try {
|
|
1830
|
-
const entries =
|
|
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
|
|
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
|
-
|
|
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
|
|
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(
|
|
1941
|
-
console.log(
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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
|
|
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
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
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 ?
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
2266
|
+
chalk5.green(" \u2713") + ` ${result.displayName} (${result.skillsCount} skills, ${result.agentsCount} agents)`
|
|
2014
2267
|
);
|
|
2015
2268
|
} else {
|
|
2016
|
-
console.log(
|
|
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
|
-
|
|
2283
|
+
chalk5.bold(` ${t("install_done")}!`),
|
|
2031
2284
|
"",
|
|
2032
|
-
` ${
|
|
2033
|
-
` ${
|
|
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
|
-
|
|
2036
|
-
` ${
|
|
2037
|
-
` ${
|
|
2038
|
-
` ${
|
|
2039
|
-
` ${
|
|
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
|
-
` ${
|
|
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
|
|
2056
|
-
import { join as
|
|
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 (
|
|
2314
|
+
if (existsSync11(join11(cwd, "package.json")) && (() => {
|
|
2062
2315
|
try {
|
|
2063
|
-
const pkg = JSON.parse(readFileSync5(
|
|
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("
|
|
2070
|
-
logger.info("
|
|
2071
|
-
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"));
|
|
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
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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")} ${
|
|
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")}: ${
|
|
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: ${
|
|
2266
|
-
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`);
|
|
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
|
|
2289
|
-
import { existsSync as
|
|
2290
|
-
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";
|
|
2291
2544
|
async function doctorCommand(options = {}) {
|
|
2292
2545
|
console.log();
|
|
2293
|
-
console.log(
|
|
2294
|
-
console.log(
|
|
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(
|
|
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
|
-
|
|
2559
|
+
chalk7.green(" \u2713") + ` ${getToolDisplayName(tool)}${detected.version ? ` v${detected.version}` : ""}`
|
|
2307
2560
|
);
|
|
2308
2561
|
} else {
|
|
2309
|
-
console.log(
|
|
2562
|
+
console.log(chalk7.dim(" \u2014") + ` ${getToolDisplayName(tool)} \u2014 \u672A\u5B89\u88C5`);
|
|
2310
2563
|
}
|
|
2311
2564
|
}
|
|
2312
2565
|
console.log();
|
|
2313
|
-
console.log(
|
|
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
|
-
|
|
2574
|
+
chalk7.green(" \u2713") + ` ${plugin.id.padEnd(30)} ${inst.skillsCount} skills, ${inst.agentsCount} agents`
|
|
2322
2575
|
);
|
|
2323
2576
|
} else {
|
|
2324
|
-
console.log(
|
|
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(
|
|
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 (
|
|
2586
|
+
if (existsSync12(skillsDir)) {
|
|
2334
2587
|
const brokenLinks = checkBrokenLinks(skillsDir);
|
|
2335
2588
|
if (brokenLinks === 0) {
|
|
2336
|
-
const count =
|
|
2337
|
-
console.log(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
2605
|
+
console.log(chalk7.green(" \u2713") + ` ${t("doctor_fix_rebuilding")}: \u5DF2\u521B\u5EFA ${skillsDir}`);
|
|
2353
2606
|
}
|
|
2354
2607
|
}
|
|
2355
|
-
if (
|
|
2608
|
+
if (existsSync12(agentsDir)) {
|
|
2356
2609
|
const brokenLinks = checkBrokenLinks(agentsDir);
|
|
2357
2610
|
if (brokenLinks === 0) {
|
|
2358
|
-
const count =
|
|
2359
|
-
console.log(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
2631
|
+
console.log(chalk7.bold(` ${t("doctor_config")}`));
|
|
2379
2632
|
const configFile = getConfigFileName(primaryTool);
|
|
2380
|
-
const configPath =
|
|
2381
|
-
if (
|
|
2382
|
-
console.log(
|
|
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(
|
|
2637
|
+
console.log(chalk7.dim(" \u2014") + ` ${configFile} \u4E0D\u5B58\u5728`);
|
|
2385
2638
|
}
|
|
2386
2639
|
console.log();
|
|
2387
|
-
console.log(
|
|
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 =
|
|
2655
|
+
const entries = readdirSync5(dir);
|
|
2403
2656
|
for (const entry of entries) {
|
|
2404
|
-
const fullPath =
|
|
2657
|
+
const fullPath = join12(dir, entry);
|
|
2405
2658
|
try {
|
|
2406
2659
|
const stats = lstatSync3(fullPath);
|
|
2407
2660
|
if (stats.isSymbolicLink()) {
|
|
2408
|
-
if (!
|
|
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 =
|
|
2676
|
+
const entries = readdirSync5(dir);
|
|
2424
2677
|
for (const entry of entries) {
|
|
2425
|
-
const fullPath =
|
|
2678
|
+
const fullPath = join12(dir, entry);
|
|
2426
2679
|
try {
|
|
2427
2680
|
const stats = lstatSync3(fullPath);
|
|
2428
2681
|
if (stats.isSymbolicLink()) {
|
|
2429
|
-
if (!
|
|
2430
|
-
|
|
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
|
|
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(
|
|
2702
|
+
console.log(chalk8.bold(` ${t("status_title")}`));
|
|
2450
2703
|
console.log();
|
|
2451
2704
|
if (installed.length === 0) {
|
|
2452
|
-
console.log(
|
|
2453
|
-
console.log(
|
|
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
|
-
|
|
2712
|
+
chalk8.green(" \u2713") + ` ${inst.displayName}` + chalk8.dim(` (${inst.tool}, ${inst.level})`)
|
|
2460
2713
|
);
|
|
2461
2714
|
console.log(
|
|
2462
|
-
|
|
2715
|
+
chalk8.dim(` ${inst.skillsCount} skills, ${inst.agentsCount} agents`)
|
|
2463
2716
|
);
|
|
2464
|
-
console.log(
|
|
2465
|
-
console.log(
|
|
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
|
|
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(
|
|
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(
|
|
2522
|
-
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...`);
|
|
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
|
-
|
|
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")}: ${
|
|
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: ${
|
|
2541
|
-
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`);
|
|
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: ${
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
2646
|
-
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...`);
|
|
2647
2903
|
const results = await installSkills(skills, tool, level, repoPath);
|
|
2648
2904
|
let successCount = 0;
|
|
2649
2905
|
let failCount = 0;
|
|
2650
|
-
|
|
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")}: ${
|
|
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: ${
|
|
2663
|
-
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`);
|
|
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
|
|
2696
|
-
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";
|
|
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(
|
|
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}
|
|
2721
|
-
logger.info(
|
|
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(
|
|
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 (
|
|
2730
|
-
|
|
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 (
|
|
2742
|
-
const entries =
|
|
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(
|
|
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}
|
|
3036
|
+
logger.warn(`${plugin.displayName}${t("uninstall_files_gone")}`);
|
|
2760
3037
|
}
|
|
2761
3038
|
}
|
|
2762
3039
|
if (skills.length > 0) {
|
|
2763
|
-
logger.info(
|
|
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")}: ${
|
|
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
|
|
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 ${
|
|
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
|
|
2869
|
-
import { existsSync as
|
|
2870
|
-
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";
|
|
2871
3148
|
async function infoCommand(pluginName) {
|
|
2872
3149
|
const plugin = findPlugin(pluginName);
|
|
2873
3150
|
if (!plugin) {
|
|
2874
|
-
console.log(
|
|
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 ?
|
|
3156
|
+
const statusText = isInstalled ? chalk12.green(`\u2713 ${t("status_installed")}`) : chalk12.dim(`\u2014 ${t("status_not_installed")}`);
|
|
2880
3157
|
console.log();
|
|
2881
|
-
console.log(
|
|
2882
|
-
console.log(
|
|
3158
|
+
console.log(chalk12.bold(` ${plugin.displayName}`));
|
|
3159
|
+
console.log(chalk12.dim(" " + "\u2500".repeat(40)));
|
|
2883
3160
|
console.log();
|
|
2884
|
-
console.log(` ${
|
|
2885
|
-
console.log(` ${
|
|
2886
|
-
console.log(` ${
|
|
2887
|
-
console.log(` ${
|
|
2888
|
-
console.log(` ${
|
|
2889
|
-
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(", ")}`);
|
|
2890
3167
|
console.log();
|
|
2891
3168
|
try {
|
|
2892
3169
|
const repoManager = createRepositoryManager();
|
|
2893
3170
|
const repoPath = await repoManager.ensureRepo();
|
|
2894
|
-
const quickstartPath =
|
|
2895
|
-
if (
|
|
2896
|
-
console.log(` ${
|
|
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 =
|
|
2899
|
-
if (
|
|
2900
|
-
const agentFiles =
|
|
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(` ${
|
|
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
|
|
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(
|
|
2921
|
-
console.log(
|
|
3197
|
+
console.log(chalk13.bold(` ${t("lang_title")}`));
|
|
3198
|
+
console.log(chalk13.dim(" " + "\u2500".repeat(40)));
|
|
2922
3199
|
console.log();
|
|
2923
|
-
console.log(` ${
|
|
3200
|
+
console.log(` ${chalk13.dim(t("lang_current") + ":")} ${config.language}`);
|
|
2924
3201
|
console.log();
|
|
2925
|
-
console.log(
|
|
2926
|
-
console.log(
|
|
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(
|
|
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(
|
|
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(
|
|
3219
|
+
console.log(chalk13.green(` \u2713 ${t("lang_set")} ${value}`));
|
|
2943
3220
|
console.log();
|
|
2944
3221
|
return;
|
|
2945
3222
|
}
|
|
2946
|
-
console.log(
|
|
2947
|
-
console.log(
|
|
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.
|
|
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
|
});
|