@cannbot-ai/install-helper 0.0.2-beta.6 → 0.0.2-beta.8
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 +497 -194
- 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,49 @@ 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
|
+
let choice = "overwrite";
|
|
1930
|
+
if (!opts.yes) {
|
|
1931
|
+
choice = await showOverwriteWarning(
|
|
1932
|
+
currentPlugin.pluginName,
|
|
1933
|
+
plugin.displayName
|
|
1934
|
+
);
|
|
1935
|
+
}
|
|
1936
|
+
if (choice === "cancel") {
|
|
1937
|
+
logger.info(t("backup_cancel"));
|
|
1938
|
+
return {
|
|
1939
|
+
success: false,
|
|
1940
|
+
pluginId: opts.pluginId,
|
|
1941
|
+
skillsCount: 0,
|
|
1942
|
+
agentsCount: 0,
|
|
1943
|
+
errors: [t("backup_cancel")],
|
|
1944
|
+
warnings: []
|
|
1945
|
+
};
|
|
1946
|
+
}
|
|
1947
|
+
backupInfo = createBackup(
|
|
1948
|
+
configRoot,
|
|
1949
|
+
opts.tool,
|
|
1950
|
+
currentPlugin.pluginId,
|
|
1951
|
+
currentPlugin.pluginName
|
|
1952
|
+
);
|
|
1953
|
+
if (backupInfo) {
|
|
1954
|
+
logger.success(`${t("backup_created")}: ${backupInfo.filePath}`);
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1690
1958
|
try {
|
|
1691
|
-
|
|
1959
|
+
const execOptions = {
|
|
1692
1960
|
cwd,
|
|
1693
1961
|
timeout: 3e5,
|
|
1694
|
-
stdio: "pipe"
|
|
1695
|
-
|
|
1696
|
-
|
|
1962
|
+
stdio: "pipe",
|
|
1963
|
+
input: opts.yes ? "y\n" : void 0
|
|
1964
|
+
};
|
|
1965
|
+
await execa3("bash", [scriptPath, ...args], execOptions);
|
|
1697
1966
|
const manifest = readManifest(configRoot);
|
|
1698
1967
|
let skillsCount = 0;
|
|
1699
1968
|
let agentsCount = 0;
|
|
@@ -1714,6 +1983,14 @@ async function installPlugin(opts) {
|
|
|
1714
1983
|
configRoot,
|
|
1715
1984
|
manifest
|
|
1716
1985
|
);
|
|
1986
|
+
if (backupInfo) {
|
|
1987
|
+
record.backup = {
|
|
1988
|
+
filePath: backupInfo.filePath,
|
|
1989
|
+
fromPluginId: backupInfo.pluginId,
|
|
1990
|
+
fromPluginName: backupInfo.pluginName,
|
|
1991
|
+
backupTime: backupInfo.backupTime
|
|
1992
|
+
};
|
|
1993
|
+
}
|
|
1717
1994
|
writeRecord(record);
|
|
1718
1995
|
} catch {
|
|
1719
1996
|
}
|
|
@@ -1739,16 +2016,16 @@ async function installPlugin(opts) {
|
|
|
1739
2016
|
}
|
|
1740
2017
|
|
|
1741
2018
|
// src/core/skill-installer.ts
|
|
1742
|
-
import { existsSync as
|
|
1743
|
-
import { join as
|
|
1744
|
-
import { select as
|
|
1745
|
-
import
|
|
2019
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync5, symlinkSync, unlinkSync as unlinkSync3, readdirSync as readdirSync4, rmdirSync, realpathSync, lstatSync as lstatSync2 } from "fs";
|
|
2020
|
+
import { join as join10 } from "path";
|
|
2021
|
+
import { select as select3, checkbox as checkbox2, Separator as Separator2 } from "@inquirer/prompts";
|
|
2022
|
+
import chalk4 from "chalk";
|
|
1746
2023
|
import Table from "cli-table3";
|
|
1747
2024
|
async function installSkills(skillIds, tool, level, repoPath) {
|
|
1748
2025
|
const configRoot = getConfigRoot(tool, level);
|
|
1749
|
-
const skillsDir =
|
|
2026
|
+
const skillsDir = join10(configRoot, "skills");
|
|
1750
2027
|
const installPath = level === "project" ? process.cwd() : configRoot;
|
|
1751
|
-
if (!
|
|
2028
|
+
if (!existsSync10(skillsDir)) {
|
|
1752
2029
|
mkdirSync5(skillsDir, { recursive: true });
|
|
1753
2030
|
}
|
|
1754
2031
|
const results = [];
|
|
@@ -1759,15 +2036,15 @@ async function installSkills(skillIds, tool, level, repoPath) {
|
|
|
1759
2036
|
results.push({ skillId, success: false, error: "Skill not found in registry" });
|
|
1760
2037
|
continue;
|
|
1761
2038
|
}
|
|
1762
|
-
const sourcePath =
|
|
1763
|
-
const targetPath =
|
|
1764
|
-
if (!
|
|
2039
|
+
const sourcePath = join10(repoPath, skill.source, skill.id);
|
|
2040
|
+
const targetPath = join10(skillsDir, skillId);
|
|
2041
|
+
if (!existsSync10(sourcePath)) {
|
|
1765
2042
|
results.push({ skillId, success: false, error: `Source not found: ${sourcePath}` });
|
|
1766
2043
|
continue;
|
|
1767
2044
|
}
|
|
1768
2045
|
try {
|
|
1769
|
-
if (
|
|
1770
|
-
|
|
2046
|
+
if (existsSync10(targetPath) || isSymlink2(targetPath)) {
|
|
2047
|
+
unlinkSync3(targetPath);
|
|
1771
2048
|
}
|
|
1772
2049
|
symlinkSync(realpathSync(sourcePath), targetPath);
|
|
1773
2050
|
results.push({ skillId, success: true });
|
|
@@ -1783,15 +2060,15 @@ async function installSkills(skillIds, tool, level, repoPath) {
|
|
|
1783
2060
|
}
|
|
1784
2061
|
async function uninstallSkills(skillIds, tool, level) {
|
|
1785
2062
|
const configRoot = getConfigRoot(tool, level);
|
|
1786
|
-
const skillsDir =
|
|
2063
|
+
const skillsDir = join10(configRoot, "skills");
|
|
1787
2064
|
const installPath = level === "project" ? process.cwd() : configRoot;
|
|
1788
2065
|
const results = [];
|
|
1789
2066
|
const removedIds = [];
|
|
1790
2067
|
for (const skillId of skillIds) {
|
|
1791
|
-
const targetPath =
|
|
2068
|
+
const targetPath = join10(skillsDir, skillId);
|
|
1792
2069
|
try {
|
|
1793
|
-
if (
|
|
1794
|
-
|
|
2070
|
+
if (existsSync10(targetPath) || isSymlink2(targetPath)) {
|
|
2071
|
+
unlinkSync3(targetPath);
|
|
1795
2072
|
results.push({ skillId, success: true });
|
|
1796
2073
|
removedIds.push(skillId);
|
|
1797
2074
|
logger.step(` \u79FB\u9664: ${skillId}`);
|
|
@@ -1806,9 +2083,9 @@ async function uninstallSkills(skillIds, tool, level) {
|
|
|
1806
2083
|
if (removedIds.length > 0) {
|
|
1807
2084
|
removeSkillsFromRecord(removedIds, tool, level, installPath);
|
|
1808
2085
|
}
|
|
1809
|
-
if (
|
|
2086
|
+
if (existsSync10(skillsDir)) {
|
|
1810
2087
|
try {
|
|
1811
|
-
const entries =
|
|
2088
|
+
const entries = readdirSync4(skillsDir);
|
|
1812
2089
|
if (entries.length === 0) {
|
|
1813
2090
|
rmdirSync(skillsDir);
|
|
1814
2091
|
logger.step(` \u6E05\u7406\u7A7A\u76EE\u5F55: skills/`);
|
|
@@ -1816,9 +2093,9 @@ async function uninstallSkills(skillIds, tool, level) {
|
|
|
1816
2093
|
} catch {
|
|
1817
2094
|
}
|
|
1818
2095
|
}
|
|
1819
|
-
if (
|
|
2096
|
+
if (existsSync10(configRoot)) {
|
|
1820
2097
|
try {
|
|
1821
|
-
const entries =
|
|
2098
|
+
const entries = readdirSync4(configRoot);
|
|
1822
2099
|
if (entries.length === 0) {
|
|
1823
2100
|
rmdirSync(configRoot);
|
|
1824
2101
|
logger.step(` \u6E05\u7406\u7A7A\u76EE\u5F55: ${configRoot.split("/").pop()}/`);
|
|
@@ -1848,7 +2125,7 @@ async function interactiveSkillSelect() {
|
|
|
1848
2125
|
{ name: "x " + t("wizard_cancel"), value: CANCEL3 }
|
|
1849
2126
|
];
|
|
1850
2127
|
showOperationHints();
|
|
1851
|
-
selectedCategoryId = await
|
|
2128
|
+
selectedCategoryId = await select3({
|
|
1852
2129
|
message: t("skill_select_category"),
|
|
1853
2130
|
choices: categoryChoices,
|
|
1854
2131
|
loop: false,
|
|
@@ -1894,7 +2171,7 @@ async function interactiveSkillSelect() {
|
|
|
1894
2171
|
});
|
|
1895
2172
|
const skillIds = selectedSkills;
|
|
1896
2173
|
if (skillIds.length === 0) {
|
|
1897
|
-
const action = await
|
|
2174
|
+
const action = await select3({
|
|
1898
2175
|
message: t("wizard_no_selection"),
|
|
1899
2176
|
choices: [
|
|
1900
2177
|
new Separator2("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
|
|
@@ -1918,11 +2195,11 @@ async function interactiveSkillSelect() {
|
|
|
1918
2195
|
function listAllSkills() {
|
|
1919
2196
|
const categories = getAllCategories();
|
|
1920
2197
|
console.log();
|
|
1921
|
-
console.log(
|
|
1922
|
-
console.log(
|
|
2198
|
+
console.log(chalk4.bold(` ${t("skill_list_title")}`));
|
|
2199
|
+
console.log(chalk4.dim(" " + "\u2500".repeat(60)));
|
|
1923
2200
|
for (const category of categories) {
|
|
1924
2201
|
console.log();
|
|
1925
|
-
console.log(
|
|
2202
|
+
console.log(chalk4.bold(` ${category.name}`) + chalk4.dim(` (${category.skills.length} skills)`));
|
|
1926
2203
|
const table = new Table({
|
|
1927
2204
|
style: { head: [], border: [] },
|
|
1928
2205
|
colWidths: [35, 45],
|
|
@@ -1930,14 +2207,14 @@ function listAllSkills() {
|
|
|
1930
2207
|
});
|
|
1931
2208
|
for (const skill of category.skills) {
|
|
1932
2209
|
table.push([
|
|
1933
|
-
|
|
2210
|
+
chalk4.cyan(skill.id),
|
|
1934
2211
|
skill.description
|
|
1935
2212
|
]);
|
|
1936
2213
|
}
|
|
1937
2214
|
console.log(table.toString());
|
|
1938
2215
|
}
|
|
1939
2216
|
console.log();
|
|
1940
|
-
console.log(
|
|
2217
|
+
console.log(chalk4.dim(` \u5171 ${getAllSkills().length} \u4E2A Skills`));
|
|
1941
2218
|
console.log();
|
|
1942
2219
|
}
|
|
1943
2220
|
function isSymlink2(path) {
|
|
@@ -1949,22 +2226,22 @@ function isSymlink2(path) {
|
|
|
1949
2226
|
}
|
|
1950
2227
|
|
|
1951
2228
|
// src/ui/display.ts
|
|
1952
|
-
import
|
|
2229
|
+
import chalk5 from "chalk";
|
|
1953
2230
|
import Table2 from "cli-table3";
|
|
1954
2231
|
function printPluginList(plugins, installed) {
|
|
1955
2232
|
const table = new Table2({
|
|
1956
2233
|
head: [
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
2234
|
+
chalk5.cyan(t("list_id")),
|
|
2235
|
+
chalk5.cyan(t("list_name")),
|
|
2236
|
+
chalk5.cyan(t("list_status")),
|
|
2237
|
+
chalk5.cyan(t("list_skills")),
|
|
2238
|
+
chalk5.cyan(t("list_agents"))
|
|
1962
2239
|
],
|
|
1963
2240
|
style: { head: [], border: [] }
|
|
1964
2241
|
});
|
|
1965
2242
|
plugins.forEach((plugin, index) => {
|
|
1966
2243
|
const isInstalled = installed.has(plugin.id);
|
|
1967
|
-
const status = isInstalled ?
|
|
2244
|
+
const status = isInstalled ? chalk5.green(`\u2713 ${t("status_installed")}`) : chalk5.dim(`\u2014`);
|
|
1968
2245
|
table.push([
|
|
1969
2246
|
String(index + 1),
|
|
1970
2247
|
plugin.displayName,
|
|
@@ -1974,7 +2251,7 @@ function printPluginList(plugins, installed) {
|
|
|
1974
2251
|
]);
|
|
1975
2252
|
});
|
|
1976
2253
|
console.log();
|
|
1977
|
-
console.log(
|
|
2254
|
+
console.log(chalk5.bold(` ${t("list_title")} (${plugins.length} \u4E2A)`));
|
|
1978
2255
|
console.log(table.toString());
|
|
1979
2256
|
console.log();
|
|
1980
2257
|
}
|
|
@@ -1983,7 +2260,7 @@ function printInstallSummary(results) {
|
|
|
1983
2260
|
const totalCount = results.length;
|
|
1984
2261
|
console.log();
|
|
1985
2262
|
console.log(
|
|
1986
|
-
|
|
2263
|
+
chalk5.bold(
|
|
1987
2264
|
` ${t("install_done")}! ${successCount}/${totalCount} ${t("install_success")}`
|
|
1988
2265
|
)
|
|
1989
2266
|
);
|
|
@@ -1991,10 +2268,10 @@ function printInstallSummary(results) {
|
|
|
1991
2268
|
for (const result of results) {
|
|
1992
2269
|
if (result.success) {
|
|
1993
2270
|
console.log(
|
|
1994
|
-
|
|
2271
|
+
chalk5.green(" \u2713") + ` ${result.displayName} (${result.skillsCount} skills, ${result.agentsCount} agents)`
|
|
1995
2272
|
);
|
|
1996
2273
|
} else {
|
|
1997
|
-
console.log(
|
|
2274
|
+
console.log(chalk5.red(" \u2717") + ` ${result.displayName}`);
|
|
1998
2275
|
}
|
|
1999
2276
|
}
|
|
2000
2277
|
console.log();
|
|
@@ -2008,21 +2285,21 @@ function printEnhancedSummary(results, tool, configRoot) {
|
|
|
2008
2285
|
}
|
|
2009
2286
|
const toolName = getToolDisplayName(tool);
|
|
2010
2287
|
const lines = [
|
|
2011
|
-
|
|
2288
|
+
chalk5.bold(` ${t("install_done")}!`),
|
|
2012
2289
|
"",
|
|
2013
|
-
` ${
|
|
2014
|
-
` ${
|
|
2290
|
+
` ${chalk5.dim(t("install_installed_to") + ":")} ${configRoot}`,
|
|
2291
|
+
` ${chalk5.dim(t("install_skills_count") + ":")} ${totalSkills} \u4E2A ${chalk5.dim("|")} ${chalk5.dim(t("install_agents_count") + ":")} ${totalAgents} \u4E2A`,
|
|
2015
2292
|
"",
|
|
2016
|
-
|
|
2017
|
-
` ${
|
|
2018
|
-
` ${
|
|
2019
|
-
` ${
|
|
2020
|
-
` ${
|
|
2293
|
+
chalk5.bold(` ${t("install_enhanced_next_steps")}:`),
|
|
2294
|
+
` ${chalk5.cyan("1.")} ${t("install_enhanced_launch")}: ${chalk5.green(toolName.toLowerCase())}`,
|
|
2295
|
+
` ${chalk5.cyan("2.")} ${t("install_enhanced_try")}: ${chalk5.green("\u5E2E\u6211\u5F00\u53D1\u4E00\u4E2A Abs \u7B97\u5B50")}`,
|
|
2296
|
+
` ${chalk5.cyan("3.")} ${t("install_enhanced_more")}: ${chalk5.green("install-helper list")}`,
|
|
2297
|
+
` ${chalk5.cyan("4.")} ${t("install_enhanced_check")}: ${chalk5.green("install-helper doctor")}`,
|
|
2021
2298
|
""
|
|
2022
2299
|
];
|
|
2023
2300
|
if (successResults.length === 1) {
|
|
2024
2301
|
lines.push(
|
|
2025
|
-
` ${
|
|
2302
|
+
` ${chalk5.dim(t("install_enhanced_docs"))}: ${chalk5.dim(`plugins-official/${successResults[0].pluginId}/quickstart.md`)}`
|
|
2026
2303
|
);
|
|
2027
2304
|
}
|
|
2028
2305
|
console.log();
|
|
@@ -2033,23 +2310,23 @@ function printEnhancedSummary(results, tool, configRoot) {
|
|
|
2033
2310
|
}
|
|
2034
2311
|
|
|
2035
2312
|
// src/commands/init.ts
|
|
2036
|
-
import { existsSync as
|
|
2037
|
-
import { join as
|
|
2313
|
+
import { existsSync as existsSync11, readFileSync as readFileSync5 } from "fs";
|
|
2314
|
+
import { join as join11 } from "path";
|
|
2038
2315
|
var BACK2 = "__back__";
|
|
2039
2316
|
var CANCEL2 = "__cancel__";
|
|
2040
2317
|
async function initCommand() {
|
|
2041
2318
|
const cwd = process.cwd();
|
|
2042
|
-
if (
|
|
2319
|
+
if (existsSync11(join11(cwd, "package.json")) && (() => {
|
|
2043
2320
|
try {
|
|
2044
|
-
const pkg = JSON.parse(readFileSync5(
|
|
2321
|
+
const pkg = JSON.parse(readFileSync5(join11(cwd, "package.json"), "utf-8"));
|
|
2045
2322
|
return pkg.name === "@cannbot-ai/install-helper";
|
|
2046
2323
|
} catch {
|
|
2047
2324
|
return false;
|
|
2048
2325
|
}
|
|
2049
2326
|
})()) {
|
|
2050
|
-
logger.warn("
|
|
2051
|
-
logger.info("
|
|
2052
|
-
logger.info("
|
|
2327
|
+
logger.warn(t("init_pkg_dir_warn"));
|
|
2328
|
+
logger.info(t("init_pkg_dir_hint"));
|
|
2329
|
+
logger.info(t("init_pkg_dir_example"));
|
|
2053
2330
|
return;
|
|
2054
2331
|
}
|
|
2055
2332
|
printBanner(t("wizard_title"));
|
|
@@ -2109,7 +2386,7 @@ async function selectMode() {
|
|
|
2109
2386
|
{ name: "x " + t("wizard_cancel"), value: CANCEL3 }
|
|
2110
2387
|
];
|
|
2111
2388
|
showOperationHints();
|
|
2112
|
-
const result = await
|
|
2389
|
+
const result = await select4({
|
|
2113
2390
|
message: t("wizard_select_mode"),
|
|
2114
2391
|
choices,
|
|
2115
2392
|
loop: false,
|
|
@@ -2122,7 +2399,7 @@ async function pluginInstallFlow() {
|
|
|
2122
2399
|
const answers = await runWizard();
|
|
2123
2400
|
if (!answers.confirmed) {
|
|
2124
2401
|
if (answers.back) return "back";
|
|
2125
|
-
logger.info("
|
|
2402
|
+
logger.info(t("init_cancelled"));
|
|
2126
2403
|
return "done";
|
|
2127
2404
|
}
|
|
2128
2405
|
const repoManager = createRepositoryManager();
|
|
@@ -2183,7 +2460,7 @@ async function skillInstallFlow() {
|
|
|
2183
2460
|
const result = await selectToolWithDetection();
|
|
2184
2461
|
if (result === "back") return "back";
|
|
2185
2462
|
if (result === "cancel") {
|
|
2186
|
-
logger.info("
|
|
2463
|
+
logger.info(t("init_cancelled"));
|
|
2187
2464
|
return "done";
|
|
2188
2465
|
}
|
|
2189
2466
|
tool = result;
|
|
@@ -2197,7 +2474,7 @@ async function skillInstallFlow() {
|
|
|
2197
2474
|
break;
|
|
2198
2475
|
}
|
|
2199
2476
|
if (result === CANCEL2) {
|
|
2200
|
-
logger.info("
|
|
2477
|
+
logger.info(t("init_cancelled"));
|
|
2201
2478
|
return "done";
|
|
2202
2479
|
}
|
|
2203
2480
|
level = result;
|
|
@@ -2211,7 +2488,7 @@ async function skillInstallFlow() {
|
|
|
2211
2488
|
break;
|
|
2212
2489
|
}
|
|
2213
2490
|
if (selectedSkills === "cancel") {
|
|
2214
|
-
logger.info("
|
|
2491
|
+
logger.info(t("init_cancelled"));
|
|
2215
2492
|
return "done";
|
|
2216
2493
|
}
|
|
2217
2494
|
if (selectedSkills.length === 0) {
|
|
@@ -2223,7 +2500,7 @@ async function skillInstallFlow() {
|
|
|
2223
2500
|
spinner.start();
|
|
2224
2501
|
const repoPath = await repoManager.ensureRepo();
|
|
2225
2502
|
spinner.succeed("\u63D2\u4EF6\u6570\u636E\u52A0\u8F7D\u5B8C\u6210");
|
|
2226
|
-
logger.info(`${t("skill_install_progress")} ${
|
|
2503
|
+
logger.info(`${t("skill_install_progress")} ${chalk6.bold(selectedSkills.length)} \u4E2A Skills...`);
|
|
2227
2504
|
const results = await installSkills(selectedSkills, tool, level, repoPath);
|
|
2228
2505
|
let successCount = 0;
|
|
2229
2506
|
let failCount = 0;
|
|
@@ -2241,10 +2518,10 @@ async function skillInstallFlow() {
|
|
|
2241
2518
|
}
|
|
2242
2519
|
const configRoot = getConfigRoot(tool, level);
|
|
2243
2520
|
logger.blank();
|
|
2244
|
-
logger.success(`${t("skill_install_done")}: ${
|
|
2521
|
+
logger.success(`${t("skill_install_done")}: ${chalk6.green(successCount + " \u6210\u529F")}, ${failCount > 0 ? chalk6.red(failCount + " \u5931\u8D25") : chalk6.dim(failCount + " \u5931\u8D25")}`);
|
|
2245
2522
|
logger.blank();
|
|
2246
|
-
logger.info(`\u5B89\u88C5\u5230: ${
|
|
2247
|
-
logger.info(`\u542F\u52A8 ${
|
|
2523
|
+
logger.info(`\u5B89\u88C5\u5230: ${chalk6.cyan(configRoot + "/skills/")}`);
|
|
2524
|
+
logger.info(`\u542F\u52A8 ${chalk6.green(tool)} \u5373\u53EF\u4F7F\u7528`);
|
|
2248
2525
|
logger.blank();
|
|
2249
2526
|
return "done";
|
|
2250
2527
|
}
|
|
@@ -2266,32 +2543,32 @@ async function listCommand() {
|
|
|
2266
2543
|
}
|
|
2267
2544
|
|
|
2268
2545
|
// src/commands/doctor.ts
|
|
2269
|
-
import
|
|
2270
|
-
import { existsSync as
|
|
2271
|
-
import { join as
|
|
2546
|
+
import chalk7 from "chalk";
|
|
2547
|
+
import { existsSync as existsSync12, readdirSync as readdirSync5, lstatSync as lstatSync3, unlinkSync as unlinkSync4, mkdirSync as mkdirSync6 } from "fs";
|
|
2548
|
+
import { join as join12 } from "path";
|
|
2272
2549
|
async function doctorCommand(options = {}) {
|
|
2273
2550
|
console.log();
|
|
2274
|
-
console.log(
|
|
2275
|
-
console.log(
|
|
2551
|
+
console.log(chalk7.bold(` ${t("doctor_title")}`));
|
|
2552
|
+
console.log(chalk7.dim(" " + "\u2500".repeat(46)));
|
|
2276
2553
|
let errors = 0;
|
|
2277
2554
|
let warnings = 0;
|
|
2278
2555
|
let fixes = 0;
|
|
2279
2556
|
console.log();
|
|
2280
|
-
console.log(
|
|
2557
|
+
console.log(chalk7.bold(` ${t("doctor_tools")}`));
|
|
2281
2558
|
const detectedTools = await detectTools();
|
|
2282
2559
|
const allTools = getAllTools();
|
|
2283
2560
|
for (const tool of allTools) {
|
|
2284
2561
|
const detected = detectedTools.find((d) => d.name === tool);
|
|
2285
2562
|
if (detected) {
|
|
2286
2563
|
console.log(
|
|
2287
|
-
|
|
2564
|
+
chalk7.green(" \u2713") + ` ${getToolDisplayName(tool)}${detected.version ? ` v${detected.version}` : ""}`
|
|
2288
2565
|
);
|
|
2289
2566
|
} else {
|
|
2290
|
-
console.log(
|
|
2567
|
+
console.log(chalk7.dim(" \u2014") + ` ${getToolDisplayName(tool)} \u2014 \u672A\u5B89\u88C5`);
|
|
2291
2568
|
}
|
|
2292
2569
|
}
|
|
2293
2570
|
console.log();
|
|
2294
|
-
console.log(
|
|
2571
|
+
console.log(chalk7.bold(` ${t("doctor_plugins")}`));
|
|
2295
2572
|
const plugins = getAllPlugins();
|
|
2296
2573
|
const installed = scanInstalled();
|
|
2297
2574
|
const installedMap = new Map(installed.map((p) => [p.id, p]));
|
|
@@ -2299,73 +2576,73 @@ async function doctorCommand(options = {}) {
|
|
|
2299
2576
|
const inst = installedMap.get(plugin.id);
|
|
2300
2577
|
if (inst) {
|
|
2301
2578
|
console.log(
|
|
2302
|
-
|
|
2579
|
+
chalk7.green(" \u2713") + ` ${plugin.id.padEnd(30)} ${inst.skillsCount} skills, ${inst.agentsCount} agents`
|
|
2303
2580
|
);
|
|
2304
2581
|
} else {
|
|
2305
|
-
console.log(
|
|
2582
|
+
console.log(chalk7.dim(" \u2014") + ` ${plugin.id.padEnd(30)} \u2014 \u672A\u5B89\u88C5`);
|
|
2306
2583
|
}
|
|
2307
2584
|
}
|
|
2308
2585
|
console.log();
|
|
2309
|
-
console.log(
|
|
2586
|
+
console.log(chalk7.bold(` ${t("doctor_links")}`));
|
|
2310
2587
|
const primaryTool = detectedTools[0]?.name || "opencode";
|
|
2311
2588
|
const configRoot = getConfigRoot(primaryTool, "project");
|
|
2312
2589
|
const skillsDir = getSkillsDir(configRoot);
|
|
2313
2590
|
const agentsDir = getAgentsDir(configRoot);
|
|
2314
|
-
if (
|
|
2591
|
+
if (existsSync12(skillsDir)) {
|
|
2315
2592
|
const brokenLinks = checkBrokenLinks(skillsDir);
|
|
2316
2593
|
if (brokenLinks === 0) {
|
|
2317
|
-
const count =
|
|
2318
|
-
console.log(
|
|
2594
|
+
const count = readdirSync5(skillsDir).length;
|
|
2595
|
+
console.log(chalk7.green(" \u2713") + ` ${skillsDir} \u2014 ${count} \u4E2A\u8F6F\u94FE\u63A5\u5747\u6709\u6548`);
|
|
2319
2596
|
} else {
|
|
2320
|
-
console.log(
|
|
2597
|
+
console.log(chalk7.yellow(" \u26A0") + ` ${skillsDir} \u2014 ${brokenLinks} \u4E2A\u5931\u6548\u94FE\u63A5`);
|
|
2321
2598
|
warnings++;
|
|
2322
2599
|
if (options.fix) {
|
|
2323
2600
|
const fixed = fixBrokenLinks(skillsDir);
|
|
2324
2601
|
fixes += fixed;
|
|
2325
|
-
console.log(
|
|
2602
|
+
console.log(chalk7.green(" \u2713") + ` ${t("doctor_fix_cleaning")}: \u5DF2\u6E05\u7406 ${fixed} \u4E2A\u5931\u6548\u94FE\u63A5`);
|
|
2326
2603
|
}
|
|
2327
2604
|
}
|
|
2328
2605
|
} else {
|
|
2329
|
-
console.log(
|
|
2606
|
+
console.log(chalk7.dim(" \u2014") + ` ${skillsDir} \u2014 \u4E0D\u5B58\u5728`);
|
|
2330
2607
|
if (options.fix) {
|
|
2331
2608
|
mkdirSync6(skillsDir, { recursive: true });
|
|
2332
2609
|
fixes++;
|
|
2333
|
-
console.log(
|
|
2610
|
+
console.log(chalk7.green(" \u2713") + ` ${t("doctor_fix_rebuilding")}: \u5DF2\u521B\u5EFA ${skillsDir}`);
|
|
2334
2611
|
}
|
|
2335
2612
|
}
|
|
2336
|
-
if (
|
|
2613
|
+
if (existsSync12(agentsDir)) {
|
|
2337
2614
|
const brokenLinks = checkBrokenLinks(agentsDir);
|
|
2338
2615
|
if (brokenLinks === 0) {
|
|
2339
|
-
const count =
|
|
2340
|
-
console.log(
|
|
2616
|
+
const count = readdirSync5(agentsDir).length;
|
|
2617
|
+
console.log(chalk7.green(" \u2713") + ` ${agentsDir} \u2014 ${count} \u4E2A\u8F6F\u94FE\u63A5\u5747\u6709\u6548`);
|
|
2341
2618
|
} else {
|
|
2342
|
-
console.log(
|
|
2619
|
+
console.log(chalk7.yellow(" \u26A0") + ` ${agentsDir} \u2014 ${brokenLinks} \u4E2A\u5931\u6548\u94FE\u63A5`);
|
|
2343
2620
|
warnings++;
|
|
2344
2621
|
if (options.fix) {
|
|
2345
2622
|
const fixed = fixBrokenLinks(agentsDir);
|
|
2346
2623
|
fixes += fixed;
|
|
2347
|
-
console.log(
|
|
2624
|
+
console.log(chalk7.green(" \u2713") + ` ${t("doctor_fix_cleaning")}: \u5DF2\u6E05\u7406 ${fixed} \u4E2A\u5931\u6548\u94FE\u63A5`);
|
|
2348
2625
|
}
|
|
2349
2626
|
}
|
|
2350
2627
|
} else {
|
|
2351
|
-
console.log(
|
|
2628
|
+
console.log(chalk7.dim(" \u2014") + ` ${agentsDir} \u2014 \u4E0D\u5B58\u5728`);
|
|
2352
2629
|
if (options.fix) {
|
|
2353
2630
|
mkdirSync6(agentsDir, { recursive: true });
|
|
2354
2631
|
fixes++;
|
|
2355
|
-
console.log(
|
|
2632
|
+
console.log(chalk7.green(" \u2713") + ` ${t("doctor_fix_rebuilding")}: \u5DF2\u521B\u5EFA ${agentsDir}`);
|
|
2356
2633
|
}
|
|
2357
2634
|
}
|
|
2358
2635
|
console.log();
|
|
2359
|
-
console.log(
|
|
2636
|
+
console.log(chalk7.bold(` ${t("doctor_config")}`));
|
|
2360
2637
|
const configFile = getConfigFileName(primaryTool);
|
|
2361
|
-
const configPath =
|
|
2362
|
-
if (
|
|
2363
|
-
console.log(
|
|
2638
|
+
const configPath = join12(process.cwd(), configFile);
|
|
2639
|
+
if (existsSync12(configPath)) {
|
|
2640
|
+
console.log(chalk7.green(" \u2713") + ` ${configFile} \u5B58\u5728`);
|
|
2364
2641
|
} else {
|
|
2365
|
-
console.log(
|
|
2642
|
+
console.log(chalk7.dim(" \u2014") + ` ${configFile} \u4E0D\u5B58\u5728`);
|
|
2366
2643
|
}
|
|
2367
2644
|
console.log();
|
|
2368
|
-
console.log(
|
|
2645
|
+
console.log(chalk7.dim(" " + "\u2500".repeat(46)));
|
|
2369
2646
|
if (options.fix && fixes > 0) {
|
|
2370
2647
|
console.log(
|
|
2371
2648
|
` ${t("doctor_result")}: ${warnings} \u4E2A\u8B66\u544A, ${errors} \u4E2A\u9519\u8BEF, ${fixes} \u9879\u5DF2\u4FEE\u590D`
|
|
@@ -2380,13 +2657,13 @@ async function doctorCommand(options = {}) {
|
|
|
2380
2657
|
function checkBrokenLinks(dir) {
|
|
2381
2658
|
let broken = 0;
|
|
2382
2659
|
try {
|
|
2383
|
-
const entries =
|
|
2660
|
+
const entries = readdirSync5(dir);
|
|
2384
2661
|
for (const entry of entries) {
|
|
2385
|
-
const fullPath =
|
|
2662
|
+
const fullPath = join12(dir, entry);
|
|
2386
2663
|
try {
|
|
2387
2664
|
const stats = lstatSync3(fullPath);
|
|
2388
2665
|
if (stats.isSymbolicLink()) {
|
|
2389
|
-
if (!
|
|
2666
|
+
if (!existsSync12(fullPath)) {
|
|
2390
2667
|
broken++;
|
|
2391
2668
|
}
|
|
2392
2669
|
}
|
|
@@ -2401,14 +2678,14 @@ function checkBrokenLinks(dir) {
|
|
|
2401
2678
|
function fixBrokenLinks(dir) {
|
|
2402
2679
|
let fixed = 0;
|
|
2403
2680
|
try {
|
|
2404
|
-
const entries =
|
|
2681
|
+
const entries = readdirSync5(dir);
|
|
2405
2682
|
for (const entry of entries) {
|
|
2406
|
-
const fullPath =
|
|
2683
|
+
const fullPath = join12(dir, entry);
|
|
2407
2684
|
try {
|
|
2408
2685
|
const stats = lstatSync3(fullPath);
|
|
2409
2686
|
if (stats.isSymbolicLink()) {
|
|
2410
|
-
if (!
|
|
2411
|
-
|
|
2687
|
+
if (!existsSync12(fullPath)) {
|
|
2688
|
+
unlinkSync4(fullPath);
|
|
2412
2689
|
fixed++;
|
|
2413
2690
|
}
|
|
2414
2691
|
}
|
|
@@ -2421,36 +2698,36 @@ function fixBrokenLinks(dir) {
|
|
|
2421
2698
|
}
|
|
2422
2699
|
|
|
2423
2700
|
// src/commands/status.ts
|
|
2424
|
-
import
|
|
2701
|
+
import chalk8 from "chalk";
|
|
2425
2702
|
async function statusCommand() {
|
|
2426
2703
|
const plugins = getAllPlugins();
|
|
2427
2704
|
const installed = scanInstalled();
|
|
2428
2705
|
const installedMap = new Map(installed.map((p) => [p.id, p]));
|
|
2429
2706
|
console.log();
|
|
2430
|
-
console.log(
|
|
2707
|
+
console.log(chalk8.bold(` ${t("status_title")}`));
|
|
2431
2708
|
console.log();
|
|
2432
2709
|
if (installed.length === 0) {
|
|
2433
|
-
console.log(
|
|
2434
|
-
console.log(
|
|
2710
|
+
console.log(chalk8.dim(` ${t("status_none")}`));
|
|
2711
|
+
console.log(chalk8.dim(` ${t("status_hint")}`));
|
|
2435
2712
|
console.log();
|
|
2436
2713
|
return;
|
|
2437
2714
|
}
|
|
2438
2715
|
for (const inst of installed) {
|
|
2439
2716
|
console.log(
|
|
2440
|
-
|
|
2717
|
+
chalk8.green(" \u2713") + ` ${inst.displayName}` + chalk8.dim(` (${inst.tool}, ${inst.level})`)
|
|
2441
2718
|
);
|
|
2442
2719
|
console.log(
|
|
2443
|
-
|
|
2720
|
+
chalk8.dim(` ${inst.skillsCount} skills, ${inst.agentsCount} agents`)
|
|
2444
2721
|
);
|
|
2445
|
-
console.log(
|
|
2446
|
-
console.log(
|
|
2722
|
+
console.log(chalk8.dim(` ${inst.configRoot}`));
|
|
2723
|
+
console.log(chalk8.dim(` ${t("status_install_time")}: ${inst.installTime}`));
|
|
2447
2724
|
console.log();
|
|
2448
2725
|
}
|
|
2449
2726
|
}
|
|
2450
2727
|
|
|
2451
2728
|
// src/commands/install.ts
|
|
2452
2729
|
import { confirm } from "@inquirer/prompts";
|
|
2453
|
-
import
|
|
2730
|
+
import chalk9 from "chalk";
|
|
2454
2731
|
async function installCommand(names, options) {
|
|
2455
2732
|
if (options.list) {
|
|
2456
2733
|
try {
|
|
@@ -2496,30 +2773,33 @@ async function installCommand(names, options) {
|
|
|
2496
2773
|
}
|
|
2497
2774
|
names = selectedSkills;
|
|
2498
2775
|
const repoManager = createRepositoryManager();
|
|
2499
|
-
const spinner = createSpinner(
|
|
2776
|
+
const spinner = createSpinner("\u6B63\u5728\u52A0\u8F7D\u63D2\u4EF6\u6570\u636E...");
|
|
2500
2777
|
spinner.start();
|
|
2501
2778
|
const repoPath = await repoManager.ensureRepo();
|
|
2502
|
-
spinner.succeed(
|
|
2503
|
-
logger.info(`${t("skill_install_progress")} ${
|
|
2779
|
+
spinner.succeed("\u63D2\u4EF6\u6570\u636E\u52A0\u8F7D\u5B8C\u6210");
|
|
2780
|
+
logger.info(`${t("skill_install_progress")} ${chalk9.bold(names.length)} \u4E2A Skills...`);
|
|
2504
2781
|
const level2 = options.level || "project";
|
|
2505
2782
|
const results = await installSkills(names, tool2, level2, repoPath);
|
|
2506
2783
|
let successCount = 0;
|
|
2507
2784
|
let failCount = 0;
|
|
2508
|
-
|
|
2785
|
+
const total = results.length;
|
|
2786
|
+
for (let i = 0; i < results.length; i++) {
|
|
2787
|
+
const result = results[i];
|
|
2788
|
+
const progress = `[${i + 1}/${total}]`;
|
|
2509
2789
|
if (result.success) {
|
|
2510
|
-
logger.success(`${result.skillId}`);
|
|
2790
|
+
logger.success(`${progress} ${result.skillId}`);
|
|
2511
2791
|
successCount++;
|
|
2512
2792
|
} else {
|
|
2513
|
-
logger.error(`${result.skillId}: ${result.error}`);
|
|
2793
|
+
logger.error(`${progress} ${result.skillId}: ${result.error}`);
|
|
2514
2794
|
failCount++;
|
|
2515
2795
|
}
|
|
2516
2796
|
}
|
|
2517
2797
|
const configRoot = getConfigRoot(tool2, level2);
|
|
2518
2798
|
logger.blank();
|
|
2519
|
-
logger.success(`${t("skill_install_done")}: ${
|
|
2799
|
+
logger.success(`${t("skill_install_done")}: ${chalk9.green(successCount + " \u6210\u529F")}, ${failCount > 0 ? chalk9.red(failCount + " \u5931\u8D25") : chalk9.dim(failCount + " \u5931\u8D25")}`);
|
|
2520
2800
|
logger.blank();
|
|
2521
|
-
logger.info(`\u5B89\u88C5\u5230: ${
|
|
2522
|
-
logger.info(`\u542F\u52A8 ${
|
|
2801
|
+
logger.info(`\u5B89\u88C5\u5230: ${chalk9.cyan(configRoot + "/skills/")}`);
|
|
2802
|
+
logger.info(`\u542F\u52A8 ${chalk9.green(tool2)} \u5373\u53EF\u4F7F\u7528`);
|
|
2523
2803
|
logger.blank();
|
|
2524
2804
|
return;
|
|
2525
2805
|
}
|
|
@@ -2554,7 +2834,7 @@ async function installCommand(names, options) {
|
|
|
2554
2834
|
for (const p of allPlugins) {
|
|
2555
2835
|
logger.step(` ${p.id} (${p.aliases.join(", ")})`);
|
|
2556
2836
|
}
|
|
2557
|
-
logger.info(`\u53EF\u7528 Skills: ${
|
|
2837
|
+
logger.info(`\u53EF\u7528 Skills: ${chalk9.cyan("install-helper install --list")}`);
|
|
2558
2838
|
return;
|
|
2559
2839
|
}
|
|
2560
2840
|
let tool;
|
|
@@ -2593,16 +2873,18 @@ async function installCommand(names, options) {
|
|
|
2593
2873
|
}
|
|
2594
2874
|
if (pluginsToInstall.length > 0) {
|
|
2595
2875
|
const repoManager = createRepositoryManager();
|
|
2596
|
-
const spinner = createSpinner(
|
|
2876
|
+
const spinner = createSpinner("\u6B63\u5728\u52A0\u8F7D\u63D2\u4EF6\u6570\u636E...");
|
|
2597
2877
|
spinner.start();
|
|
2598
2878
|
const repoPath = await repoManager.ensureRepo();
|
|
2599
|
-
spinner.succeed(
|
|
2879
|
+
spinner.succeed("\u63D2\u4EF6\u6570\u636E\u52A0\u8F7D\u5B8C\u6210");
|
|
2600
2880
|
const allPlugins = getAllPlugins();
|
|
2601
2881
|
const results = await installPlugins(
|
|
2602
2882
|
pluginsToInstall,
|
|
2603
2883
|
tool,
|
|
2604
2884
|
level,
|
|
2605
|
-
repoPath
|
|
2885
|
+
repoPath,
|
|
2886
|
+
void 0,
|
|
2887
|
+
options.yes
|
|
2606
2888
|
);
|
|
2607
2889
|
const summary = results.map((result) => {
|
|
2608
2890
|
const plugin = allPlugins.find((p) => p.id === result.pluginId);
|
|
@@ -2620,28 +2902,31 @@ async function installCommand(names, options) {
|
|
|
2620
2902
|
}
|
|
2621
2903
|
if (skills.length > 0) {
|
|
2622
2904
|
const repoManager = createRepositoryManager();
|
|
2623
|
-
const spinner = createSpinner(
|
|
2905
|
+
const spinner = createSpinner("\u6B63\u5728\u52A0\u8F7D\u63D2\u4EF6\u6570\u636E...");
|
|
2624
2906
|
spinner.start();
|
|
2625
2907
|
const repoPath = await repoManager.ensureRepo();
|
|
2626
|
-
spinner.succeed(
|
|
2627
|
-
logger.info(`${t("skill_install_progress")} ${
|
|
2908
|
+
spinner.succeed("\u63D2\u4EF6\u6570\u636E\u52A0\u8F7D\u5B8C\u6210");
|
|
2909
|
+
logger.info(`${t("skill_install_progress")} ${chalk9.bold(skills.length)} \u4E2A Skills...`);
|
|
2628
2910
|
const results = await installSkills(skills, tool, level, repoPath);
|
|
2629
2911
|
let successCount = 0;
|
|
2630
2912
|
let failCount = 0;
|
|
2631
|
-
|
|
2913
|
+
const total = results.length;
|
|
2914
|
+
for (let i = 0; i < results.length; i++) {
|
|
2915
|
+
const result = results[i];
|
|
2916
|
+
const progress = `[${i + 1}/${total}]`;
|
|
2632
2917
|
if (result.success) {
|
|
2633
|
-
logger.success(`${result.skillId}`);
|
|
2918
|
+
logger.success(`${progress} ${result.skillId}`);
|
|
2634
2919
|
successCount++;
|
|
2635
2920
|
} else {
|
|
2636
|
-
logger.error(`${result.skillId}: ${result.error}`);
|
|
2921
|
+
logger.error(`${progress} ${result.skillId}: ${result.error}`);
|
|
2637
2922
|
failCount++;
|
|
2638
2923
|
}
|
|
2639
2924
|
}
|
|
2640
2925
|
logger.blank();
|
|
2641
|
-
logger.success(`${t("skill_install_done")}: ${
|
|
2926
|
+
logger.success(`${t("skill_install_done")}: ${chalk9.green(successCount + " \u6210\u529F")}, ${failCount > 0 ? chalk9.red(failCount + " \u5931\u8D25") : chalk9.dim(failCount + " \u5931\u8D25")}`);
|
|
2642
2927
|
logger.blank();
|
|
2643
|
-
logger.info(`\u5B89\u88C5\u5230: ${
|
|
2644
|
-
logger.info(`\u542F\u52A8 ${
|
|
2928
|
+
logger.info(`\u5B89\u88C5\u5230: ${chalk9.cyan(getConfigRoot(tool, level) + "/skills/")}`);
|
|
2929
|
+
logger.info(`\u542F\u52A8 ${chalk9.green(tool)} \u5373\u53EF\u4F7F\u7528`);
|
|
2645
2930
|
logger.blank();
|
|
2646
2931
|
}
|
|
2647
2932
|
}
|
|
@@ -2673,8 +2958,8 @@ async function installPlugins(pluginIds, tool, level, repoPath) {
|
|
|
2673
2958
|
}
|
|
2674
2959
|
|
|
2675
2960
|
// src/commands/uninstall.ts
|
|
2676
|
-
import { existsSync as
|
|
2677
|
-
import
|
|
2961
|
+
import { existsSync as existsSync13, unlinkSync as unlinkSync5, rmdirSync as rmdirSync2, readdirSync as readdirSync6, lstatSync as lstatSync4 } from "fs";
|
|
2962
|
+
import chalk10 from "chalk";
|
|
2678
2963
|
async function uninstallCommand(names, options) {
|
|
2679
2964
|
const tool = options.tool || "opencode";
|
|
2680
2965
|
const level = options.level || "project";
|
|
@@ -2691,24 +2976,24 @@ async function uninstallCommand(names, options) {
|
|
|
2691
2976
|
skills.push(skill.id);
|
|
2692
2977
|
continue;
|
|
2693
2978
|
}
|
|
2694
|
-
logger.error(
|
|
2979
|
+
logger.error(`${t("uninstall_not_found")}: ${name}`);
|
|
2695
2980
|
}
|
|
2696
2981
|
for (const pluginId of plugins) {
|
|
2697
2982
|
const plugin = findPlugin(pluginId);
|
|
2698
2983
|
if (!plugin) continue;
|
|
2699
2984
|
const record = readRecord(plugin.id);
|
|
2700
2985
|
if (!record) {
|
|
2701
|
-
logger.warn(`${plugin.displayName}
|
|
2702
|
-
logger.info(
|
|
2986
|
+
logger.warn(`${plugin.displayName} ${t("uninstall_no_record")}`);
|
|
2987
|
+
logger.info(`${t("uninstall_no_record_hint")}`);
|
|
2703
2988
|
continue;
|
|
2704
2989
|
}
|
|
2705
|
-
logger.info(
|
|
2990
|
+
logger.info(`${t("uninstall_in_progress")} ${plugin.displayName}...`);
|
|
2706
2991
|
let removedFiles = 0;
|
|
2707
2992
|
let removedDirs = 0;
|
|
2708
2993
|
for (const filePath of record.files) {
|
|
2709
2994
|
try {
|
|
2710
|
-
if (
|
|
2711
|
-
|
|
2995
|
+
if (existsSync13(filePath) || isSymlink3(filePath)) {
|
|
2996
|
+
unlinkSync5(filePath);
|
|
2712
2997
|
const name = filePath.split("/").pop() || filePath;
|
|
2713
2998
|
logger.step(` \u79FB\u9664: ${name}`);
|
|
2714
2999
|
removedFiles++;
|
|
@@ -2719,8 +3004,8 @@ async function uninstallCommand(names, options) {
|
|
|
2719
3004
|
const sortedDirs = [...record.directories].sort((a, b) => b.length - a.length);
|
|
2720
3005
|
for (const dirPath of sortedDirs) {
|
|
2721
3006
|
try {
|
|
2722
|
-
if (
|
|
2723
|
-
const entries =
|
|
3007
|
+
if (existsSync13(dirPath)) {
|
|
3008
|
+
const entries = readdirSync6(dirPath);
|
|
2724
3009
|
if (entries.length === 0) {
|
|
2725
3010
|
rmdirSync2(dirPath);
|
|
2726
3011
|
const name = dirPath.split("/").pop() || dirPath;
|
|
@@ -2733,15 +3018,33 @@ async function uninstallCommand(names, options) {
|
|
|
2733
3018
|
}
|
|
2734
3019
|
deleteRecord(plugin.id);
|
|
2735
3020
|
removeInstalledPlugin(plugin.id);
|
|
3021
|
+
const configRoot = getConfigRoot(record.tool, record.level);
|
|
3022
|
+
const backups = findBackups(configRoot);
|
|
3023
|
+
const otherBackups = backups.filter((b) => b.pluginId !== pluginId);
|
|
3024
|
+
if (otherBackups.length > 0) {
|
|
3025
|
+
const choice = await showRestorePrompt(otherBackups);
|
|
3026
|
+
if (choice !== "none") {
|
|
3027
|
+
const restored = restoreBackup(choice, configRoot, record.tool);
|
|
3028
|
+
if (restored) {
|
|
3029
|
+
const backupInfo = otherBackups.find((b) => b.filePath === choice);
|
|
3030
|
+
logger.success(`${t("backup_restore_success")}: ${backupInfo?.pluginName || ""}`);
|
|
3031
|
+
deleteBackup(choice);
|
|
3032
|
+
}
|
|
3033
|
+
}
|
|
3034
|
+
}
|
|
3035
|
+
const currentBackups = backups.filter((b) => b.pluginId === pluginId);
|
|
3036
|
+
for (const backup of currentBackups) {
|
|
3037
|
+
deleteBackup(backup.filePath);
|
|
3038
|
+
}
|
|
2736
3039
|
const totalRemoved = removedFiles + removedDirs;
|
|
2737
3040
|
if (totalRemoved > 0) {
|
|
2738
|
-
logger.success(
|
|
3041
|
+
logger.success(`${t("uninstall_removed")} ${plugin.displayName}\uFF08\u79FB\u9664 ${removedFiles} \u4E2A\u6587\u4EF6\uFF0C${removedDirs} \u4E2A\u76EE\u5F55\uFF09`);
|
|
2739
3042
|
} else {
|
|
2740
|
-
logger.warn(`${plugin.displayName}
|
|
3043
|
+
logger.warn(`${plugin.displayName}${t("uninstall_files_gone")}`);
|
|
2741
3044
|
}
|
|
2742
3045
|
}
|
|
2743
3046
|
if (skills.length > 0) {
|
|
2744
|
-
logger.info(
|
|
3047
|
+
logger.info(`${t("uninstall_skills_in_progress")} ${skills.length} \u4E2A Skills...`);
|
|
2745
3048
|
const results = await uninstallSkills(skills, tool, level);
|
|
2746
3049
|
let successCount = 0;
|
|
2747
3050
|
let failCount = 0;
|
|
@@ -2753,7 +3056,7 @@ async function uninstallCommand(names, options) {
|
|
|
2753
3056
|
}
|
|
2754
3057
|
}
|
|
2755
3058
|
logger.blank();
|
|
2756
|
-
logger.success(`${t("skill_uninstall_done")}: ${
|
|
3059
|
+
logger.success(`${t("skill_uninstall_done")}: ${chalk10.green(successCount + " \u6210\u529F")}, ${failCount > 0 ? chalk10.red(failCount + " \u5931\u8D25") : chalk10.dim(failCount + " \u5931\u8D25")}`);
|
|
2757
3060
|
logger.blank();
|
|
2758
3061
|
}
|
|
2759
3062
|
}
|
|
@@ -2766,7 +3069,7 @@ function isSymlink3(path) {
|
|
|
2766
3069
|
}
|
|
2767
3070
|
|
|
2768
3071
|
// src/commands/update.ts
|
|
2769
|
-
import
|
|
3072
|
+
import chalk11 from "chalk";
|
|
2770
3073
|
async function updateCommand(pluginNames, options) {
|
|
2771
3074
|
let tool;
|
|
2772
3075
|
if (options.tool) {
|
|
@@ -2784,7 +3087,7 @@ async function updateCommand(pluginNames, options) {
|
|
|
2784
3087
|
pluginsToUpdate = manifests.map((m) => m.team);
|
|
2785
3088
|
if (pluginsToUpdate.length === 0) {
|
|
2786
3089
|
logger.info(t("update_no_plugins"));
|
|
2787
|
-
logger.info(`\u4F7F\u7528 ${
|
|
3090
|
+
logger.info(`\u4F7F\u7528 ${chalk11.cyan("install-helper install <plugin>")} \u5B89\u88C5\u63D2\u4EF6`);
|
|
2788
3091
|
return;
|
|
2789
3092
|
}
|
|
2790
3093
|
} else {
|
|
@@ -2846,42 +3149,42 @@ async function updateCommand(pluginNames, options) {
|
|
|
2846
3149
|
}
|
|
2847
3150
|
|
|
2848
3151
|
// src/commands/info.ts
|
|
2849
|
-
import
|
|
2850
|
-
import { existsSync as
|
|
2851
|
-
import { join as
|
|
3152
|
+
import chalk12 from "chalk";
|
|
3153
|
+
import { existsSync as existsSync14, readdirSync as readdirSync7 } from "fs";
|
|
3154
|
+
import { join as join13 } from "path";
|
|
2852
3155
|
async function infoCommand(pluginName) {
|
|
2853
3156
|
const plugin = findPlugin(pluginName);
|
|
2854
3157
|
if (!plugin) {
|
|
2855
|
-
console.log(
|
|
3158
|
+
console.log(chalk12.red(` ${t("info_not_found")}: ${pluginName}`));
|
|
2856
3159
|
return;
|
|
2857
3160
|
}
|
|
2858
3161
|
const installed = scanInstalled();
|
|
2859
3162
|
const isInstalled = installed.some((p) => p.id === plugin.id);
|
|
2860
|
-
const statusText = isInstalled ?
|
|
3163
|
+
const statusText = isInstalled ? chalk12.green(`\u2713 ${t("status_installed")}`) : chalk12.dim(`\u2014 ${t("status_not_installed")}`);
|
|
2861
3164
|
console.log();
|
|
2862
|
-
console.log(
|
|
2863
|
-
console.log(
|
|
3165
|
+
console.log(chalk12.bold(` ${plugin.displayName}`));
|
|
3166
|
+
console.log(chalk12.dim(" " + "\u2500".repeat(40)));
|
|
2864
3167
|
console.log();
|
|
2865
|
-
console.log(` ${
|
|
2866
|
-
console.log(` ${
|
|
2867
|
-
console.log(` ${
|
|
2868
|
-
console.log(` ${
|
|
2869
|
-
console.log(` ${
|
|
2870
|
-
console.log(` ${
|
|
3168
|
+
console.log(` ${chalk12.dim(t("info_description") + ":")} ${plugin.description}`);
|
|
3169
|
+
console.log(` ${chalk12.dim("ID:")} ${plugin.id}`);
|
|
3170
|
+
console.log(` ${chalk12.dim(t("info_status") + ":")} ${statusText}`);
|
|
3171
|
+
console.log(` ${chalk12.dim(t("info_skills") + ":")} ${plugin.skills}`);
|
|
3172
|
+
console.log(` ${chalk12.dim(t("info_agents") + ":")} ${plugin.agents}`);
|
|
3173
|
+
console.log(` ${chalk12.dim(t("info_aliases") + ":")} ${plugin.aliases.join(", ")}`);
|
|
2871
3174
|
console.log();
|
|
2872
3175
|
try {
|
|
2873
3176
|
const repoManager = createRepositoryManager();
|
|
2874
3177
|
const repoPath = await repoManager.ensureRepo();
|
|
2875
|
-
const quickstartPath =
|
|
2876
|
-
if (
|
|
2877
|
-
console.log(` ${
|
|
3178
|
+
const quickstartPath = join13(repoPath, plugin.dir, "quickstart.md");
|
|
3179
|
+
if (existsSync14(quickstartPath)) {
|
|
3180
|
+
console.log(` ${chalk12.dim(t("info_quickstart") + ":")} ${quickstartPath}`);
|
|
2878
3181
|
}
|
|
2879
|
-
const agentsDir =
|
|
2880
|
-
if (
|
|
2881
|
-
const agentFiles =
|
|
3182
|
+
const agentsDir = join13(repoPath, plugin.dir, "agents");
|
|
3183
|
+
if (existsSync14(agentsDir)) {
|
|
3184
|
+
const agentFiles = readdirSync7(agentsDir).filter((f) => f.endsWith(".md"));
|
|
2882
3185
|
if (agentFiles.length > 0) {
|
|
2883
3186
|
console.log();
|
|
2884
|
-
console.log(` ${
|
|
3187
|
+
console.log(` ${chalk12.bold("Agents:")}`);
|
|
2885
3188
|
for (const agent of agentFiles) {
|
|
2886
3189
|
console.log(` \u2022 ${agent.replace(".md", "")}`);
|
|
2887
3190
|
}
|
|
@@ -2893,39 +3196,39 @@ async function infoCommand(pluginName) {
|
|
|
2893
3196
|
}
|
|
2894
3197
|
|
|
2895
3198
|
// src/commands/lang.ts
|
|
2896
|
-
import
|
|
3199
|
+
import chalk13 from "chalk";
|
|
2897
3200
|
async function langCommand(action, value) {
|
|
2898
3201
|
const config = readConfig();
|
|
2899
3202
|
if (!action || action === "show") {
|
|
2900
3203
|
console.log();
|
|
2901
|
-
console.log(
|
|
2902
|
-
console.log(
|
|
3204
|
+
console.log(chalk13.bold(` ${t("lang_title")}`));
|
|
3205
|
+
console.log(chalk13.dim(" " + "\u2500".repeat(40)));
|
|
2903
3206
|
console.log();
|
|
2904
|
-
console.log(` ${
|
|
3207
|
+
console.log(` ${chalk13.dim(t("lang_current") + ":")} ${config.language}`);
|
|
2905
3208
|
console.log();
|
|
2906
|
-
console.log(
|
|
2907
|
-
console.log(
|
|
3209
|
+
console.log(chalk13.dim(` ${t("lang_supported")}`));
|
|
3210
|
+
console.log(chalk13.dim(` ${t("lang_usage")}`));
|
|
2908
3211
|
console.log();
|
|
2909
3212
|
return;
|
|
2910
3213
|
}
|
|
2911
3214
|
if (action === "set") {
|
|
2912
3215
|
if (!value) {
|
|
2913
|
-
console.log(
|
|
3216
|
+
console.log(chalk13.red(` ${t("lang_specify")}`));
|
|
2914
3217
|
return;
|
|
2915
3218
|
}
|
|
2916
3219
|
if (value !== "zh_CN" && value !== "en_US") {
|
|
2917
|
-
console.log(
|
|
3220
|
+
console.log(chalk13.red(` ${t("lang_invalid")}`));
|
|
2918
3221
|
return;
|
|
2919
3222
|
}
|
|
2920
3223
|
updateConfig({ language: value });
|
|
2921
3224
|
setLanguage(value);
|
|
2922
3225
|
console.log();
|
|
2923
|
-
console.log(
|
|
3226
|
+
console.log(chalk13.green(` \u2713 ${t("lang_set")} ${value}`));
|
|
2924
3227
|
console.log();
|
|
2925
3228
|
return;
|
|
2926
3229
|
}
|
|
2927
|
-
console.log(
|
|
2928
|
-
console.log(
|
|
3230
|
+
console.log(chalk13.red(` ${t("lang_unknown_action")}: ${action}`));
|
|
3231
|
+
console.log(chalk13.dim(` ${t("lang_supported_actions")}`));
|
|
2929
3232
|
}
|
|
2930
3233
|
|
|
2931
3234
|
// src/cli.ts
|
|
@@ -2935,7 +3238,7 @@ function createCLI() {
|
|
|
2935
3238
|
setLanguage(config.language);
|
|
2936
3239
|
}
|
|
2937
3240
|
const program2 = new Command();
|
|
2938
|
-
program2.name("install-helper").description("Install Helper - Interactive installer for CANN operator development skills").version("0.0.2-beta.
|
|
3241
|
+
program2.name("install-helper").description("CANNBot Install Helper - Interactive installer for CANN operator development skills").version("0.0.2-beta.8");
|
|
2939
3242
|
program2.command("init", { isDefault: false }).description("Run interactive installation wizard").action(async () => {
|
|
2940
3243
|
await initCommand();
|
|
2941
3244
|
});
|