@cannbot-ai/install-helper 1.0.4 → 1.0.6
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/README.md +63 -31
- package/dist/index.js +324 -150
- package/dist/index.js.map +1 -1
- package/dist/locales/en_US.json +6 -0
- package/dist/locales/zh_CN.json +6 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5,11 +5,11 @@ import { Command } from "commander";
|
|
|
5
5
|
|
|
6
6
|
// src/commands/init.ts
|
|
7
7
|
import { select as select4, Separator as Separator3 } from "@inquirer/prompts";
|
|
8
|
-
import
|
|
8
|
+
import chalk7 from "chalk";
|
|
9
9
|
|
|
10
10
|
// src/ui/wizard.ts
|
|
11
11
|
import { select, checkbox, Separator } from "@inquirer/prompts";
|
|
12
|
-
import
|
|
12
|
+
import chalk3 from "chalk";
|
|
13
13
|
|
|
14
14
|
// src/core/registry.ts
|
|
15
15
|
import { readdirSync, readFileSync } from "fs";
|
|
@@ -48,7 +48,9 @@ function loadPluginsFromYaml() {
|
|
|
48
48
|
}
|
|
49
49
|
} catch {
|
|
50
50
|
}
|
|
51
|
-
plugins.sort(
|
|
51
|
+
plugins.sort(
|
|
52
|
+
(a, b) => a.displayName < b.displayName ? -1 : a.displayName > b.displayName ? 1 : 0
|
|
53
|
+
);
|
|
52
54
|
return plugins;
|
|
53
55
|
}
|
|
54
56
|
var PLUGIN_REGISTRY = loadPluginsFromYaml();
|
|
@@ -546,16 +548,78 @@ function removeInstalledPlugin(pluginId) {
|
|
|
546
548
|
}
|
|
547
549
|
|
|
548
550
|
// src/ui/theme.ts
|
|
551
|
+
import chalk2 from "chalk";
|
|
549
552
|
var selectTheme = {
|
|
550
553
|
helpMode: "never"
|
|
551
554
|
};
|
|
555
|
+
function isCJK(code) {
|
|
556
|
+
return code >= 11904 && code <= 40959 || code >= 63744 && code <= 64255 || code >= 65072 && code <= 65103 || code >= 65280 && code <= 65519 || code >= 13312 && code <= 19903 || code >= 131072 && code <= 173791 || code >= 173824 && code <= 177983 || code >= 177984 && code <= 178207 || code >= 178208 && code <= 183983;
|
|
557
|
+
}
|
|
558
|
+
function isEmoji(code) {
|
|
559
|
+
return code >= 127744 && code <= 129791 || code >= 9728 && code <= 10175;
|
|
560
|
+
}
|
|
561
|
+
function getDisplayWidth2(str) {
|
|
562
|
+
let width = 0;
|
|
563
|
+
for (const ch of str) {
|
|
564
|
+
const code = ch.codePointAt(0);
|
|
565
|
+
if (isCJK(code) || isEmoji(code)) {
|
|
566
|
+
width += 2;
|
|
567
|
+
} else {
|
|
568
|
+
width += 1;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
return width;
|
|
572
|
+
}
|
|
573
|
+
function wrapDescription(text) {
|
|
574
|
+
const prefix = " \u{1F4A1} ";
|
|
575
|
+
const indent = " ";
|
|
576
|
+
const cols = process.stdout.columns || 120;
|
|
577
|
+
const maxLen = Math.max(20, cols - getDisplayWidth2(prefix) - 2);
|
|
578
|
+
const tokens = [];
|
|
579
|
+
let i = 0;
|
|
580
|
+
while (i < text.length) {
|
|
581
|
+
const code = text[i].codePointAt(0);
|
|
582
|
+
if (isCJK(code)) {
|
|
583
|
+
tokens.push({ text: text[i], width: 2 });
|
|
584
|
+
i++;
|
|
585
|
+
} else {
|
|
586
|
+
let j = i;
|
|
587
|
+
while (j < text.length) {
|
|
588
|
+
const c = text[j].codePointAt(0);
|
|
589
|
+
if (isCJK(c)) break;
|
|
590
|
+
j++;
|
|
591
|
+
}
|
|
592
|
+
const word = text.slice(i, j);
|
|
593
|
+
tokens.push({ text: word, width: getDisplayWidth2(word) });
|
|
594
|
+
i = j;
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
const lines = [];
|
|
598
|
+
let line = "";
|
|
599
|
+
let lineWidth = 0;
|
|
600
|
+
for (const token of tokens) {
|
|
601
|
+
if (lineWidth + token.width > maxLen && line) {
|
|
602
|
+
lines.push(line.trimEnd());
|
|
603
|
+
line = token.text;
|
|
604
|
+
lineWidth = token.width;
|
|
605
|
+
} else {
|
|
606
|
+
line += token.text;
|
|
607
|
+
lineWidth += token.width;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
if (line) lines.push(line.trimEnd());
|
|
611
|
+
return lines.map((l, i2) => chalk2.cyan(i2 === 0 ? prefix + l : indent + l)).join("\n");
|
|
612
|
+
}
|
|
552
613
|
var checkboxTheme = {
|
|
553
614
|
icon: {
|
|
554
615
|
checked: "\x1B[32m\u2611\x1B[22m",
|
|
555
616
|
unchecked: "\u2610",
|
|
556
617
|
cursor: "\u276F"
|
|
557
618
|
},
|
|
558
|
-
helpMode: "never"
|
|
619
|
+
helpMode: "never",
|
|
620
|
+
style: {
|
|
621
|
+
description: (text) => wrapDescription(text)
|
|
622
|
+
}
|
|
559
623
|
};
|
|
560
624
|
|
|
561
625
|
// src/ui/wizard.ts
|
|
@@ -630,7 +694,7 @@ async function runWizard() {
|
|
|
630
694
|
step = 2;
|
|
631
695
|
break;
|
|
632
696
|
}
|
|
633
|
-
if (result === CANCEL
|
|
697
|
+
if (result === CANCEL) {
|
|
634
698
|
return { language: config.language || "zh_CN", tool: selectedTool, level, plugins: [], confirmed: false };
|
|
635
699
|
}
|
|
636
700
|
updateConfig({ lastTool: selectedTool, lastLevel: level });
|
|
@@ -745,9 +809,10 @@ async function stepPlugins(tool, level) {
|
|
|
745
809
|
const isInstalled = installedSet.has(p.id);
|
|
746
810
|
const suffix = isInstalled ? ` [${t("wizard_already_installed")}]` : "";
|
|
747
811
|
return {
|
|
748
|
-
name: `${p.displayName}${suffix}
|
|
812
|
+
name: `${chalk3.cyan(p.displayName)}${suffix}`,
|
|
749
813
|
value: p.id,
|
|
750
|
-
checked: false
|
|
814
|
+
checked: false,
|
|
815
|
+
description: p.description
|
|
751
816
|
};
|
|
752
817
|
});
|
|
753
818
|
showOperationHints(true);
|
|
@@ -783,11 +848,11 @@ async function stepConfirm(tool, level, plugins) {
|
|
|
783
848
|
const displayPath = getConfigRoot(tool, level);
|
|
784
849
|
const toolName = getToolDisplayName(tool);
|
|
785
850
|
const levelText = level === "project" ? "project" : "global";
|
|
786
|
-
logger.info(t("wizard_confirm_install_format").replace("{count}",
|
|
787
|
-
logger.info(`${t("wizard_install_path")}: ${
|
|
851
|
+
logger.info(t("wizard_confirm_install_format").replace("{count}", chalk3.bold(String(plugins.length))).replace("{tool}", chalk3.green(toolName)).replace("{level}", chalk3.cyan(levelText)));
|
|
852
|
+
logger.info(`${t("wizard_install_path")}: ${chalk3.cyan(displayPath)}`);
|
|
788
853
|
for (const plugin of selectedPlugins) {
|
|
789
854
|
if (plugin) {
|
|
790
|
-
logger.step(` \u2022 ${
|
|
855
|
+
logger.step(` \u2022 ${chalk3.bold(plugin.displayName)}`);
|
|
791
856
|
}
|
|
792
857
|
}
|
|
793
858
|
logger.blank();
|
|
@@ -964,20 +1029,6 @@ function getCachePath() {
|
|
|
964
1029
|
return join7(getCannbotConfigDir(), "scan-cache.json");
|
|
965
1030
|
}
|
|
966
1031
|
function scanDirectory(dirPath, repoPath, sourcePrefix, skills, seen) {
|
|
967
|
-
const selfSkillMd = join7(dirPath, "SKILL.md");
|
|
968
|
-
if (existsSync5(selfSkillMd)) {
|
|
969
|
-
const frontmatter = parseFrontmatter(selfSkillMd);
|
|
970
|
-
if (frontmatter && !seen.has(frontmatter.name)) {
|
|
971
|
-
seen.add(frontmatter.name);
|
|
972
|
-
skills.push({
|
|
973
|
-
id: frontmatter.name,
|
|
974
|
-
description: frontmatter.description,
|
|
975
|
-
source: sourcePrefix,
|
|
976
|
-
filePath: selfSkillMd
|
|
977
|
-
});
|
|
978
|
-
}
|
|
979
|
-
return;
|
|
980
|
-
}
|
|
981
1032
|
for (const entry of safeReaddir(dirPath)) {
|
|
982
1033
|
const fullPath = join7(dirPath, entry);
|
|
983
1034
|
if (EXCLUDE_DIRS.has(entry)) continue;
|
|
@@ -996,7 +1047,7 @@ function scanDirectory(dirPath, repoPath, sourcePrefix, skills, seen) {
|
|
|
996
1047
|
}
|
|
997
1048
|
continue;
|
|
998
1049
|
}
|
|
999
|
-
scanDirectory(fullPath, repoPath, sourcePrefix, skills, seen);
|
|
1050
|
+
scanDirectory(fullPath, repoPath, sourcePrefix + "/" + entry, skills, seen);
|
|
1000
1051
|
}
|
|
1001
1052
|
}
|
|
1002
1053
|
function safeReaddir(dir) {
|
|
@@ -1666,13 +1717,13 @@ function readAllRecords() {
|
|
|
1666
1717
|
|
|
1667
1718
|
// src/ui/backup-prompts.ts
|
|
1668
1719
|
import { select as select2 } from "@inquirer/prompts";
|
|
1669
|
-
import
|
|
1720
|
+
import chalk4 from "chalk";
|
|
1670
1721
|
async function showOverwriteWarning(currentPluginName, newPluginName) {
|
|
1671
1722
|
console.log();
|
|
1672
|
-
console.log(
|
|
1723
|
+
console.log(chalk4.yellow(` \u26A0\uFE0F ${t("backup_detected")}`));
|
|
1673
1724
|
console.log();
|
|
1674
|
-
console.log(` ${t("backup_current")}: ${
|
|
1675
|
-
console.log(` ${t("backup_installing")}: ${
|
|
1725
|
+
console.log(` ${t("backup_current")}: ${chalk4.cyan(currentPluginName)}`);
|
|
1726
|
+
console.log(` ${t("backup_installing")}: ${chalk4.cyan(newPluginName)}`);
|
|
1676
1727
|
console.log();
|
|
1677
1728
|
console.log(` ${t("backup_overwrite_warning")}`);
|
|
1678
1729
|
console.log(` ${t("backup_auto_create")}`);
|
|
@@ -1688,7 +1739,7 @@ async function showOverwriteWarning(currentPluginName, newPluginName) {
|
|
|
1688
1739
|
}
|
|
1689
1740
|
async function showRestorePrompt(backups) {
|
|
1690
1741
|
console.log();
|
|
1691
|
-
console.log(
|
|
1742
|
+
console.log(chalk4.cyan(` ${t("backup_restore_prompt")}`));
|
|
1692
1743
|
console.log();
|
|
1693
1744
|
const choices = backups.map((b) => ({
|
|
1694
1745
|
name: `${t("backup_restore")} ${b.pluginName} (${b.backupTime})`,
|
|
@@ -1830,7 +1881,7 @@ async function installPlugin(opts) {
|
|
|
1830
1881
|
import { existsSync as existsSync10, mkdirSync as mkdirSync5, symlinkSync, unlinkSync as unlinkSync3, readdirSync as readdirSync4, rmdirSync, realpathSync, lstatSync as lstatSync2 } from "fs";
|
|
1831
1882
|
import { join as join12 } from "path";
|
|
1832
1883
|
import { select as select3, checkbox as checkbox2, Separator as Separator2 } from "@inquirer/prompts";
|
|
1833
|
-
import
|
|
1884
|
+
import chalk5 from "chalk";
|
|
1834
1885
|
import Table from "cli-table3";
|
|
1835
1886
|
async function installSkills(skillIds, tool, level, repoPath) {
|
|
1836
1887
|
const configRoot = getConfigRoot(tool, level);
|
|
@@ -1906,22 +1957,34 @@ async function uninstallSkills(skillIds, tool, level) {
|
|
|
1906
1957
|
}
|
|
1907
1958
|
return results;
|
|
1908
1959
|
}
|
|
1960
|
+
var SELECT_ALL = "__select_all__";
|
|
1961
|
+
var SELECT_ALL_CATEGORY = "__select_all_category__";
|
|
1962
|
+
var CONTINUE_SELECT = "__continue_select__";
|
|
1909
1963
|
async function interactiveSkillSelect(tool, level) {
|
|
1910
1964
|
const BACK3 = "__back__";
|
|
1911
1965
|
const CANCEL3 = "__cancel__";
|
|
1912
1966
|
const categories = getAllCategories();
|
|
1967
|
+
const allSkillIds = getAllSkills().map((s) => s.id);
|
|
1968
|
+
let accumulated = [];
|
|
1913
1969
|
let step = 0;
|
|
1914
1970
|
let selectedCategoryId = "";
|
|
1915
1971
|
while (true) {
|
|
1916
1972
|
switch (step) {
|
|
1917
1973
|
case 0: {
|
|
1918
|
-
|
|
1974
|
+
const titleSuffix = accumulated.length > 0 ? `${t("wizard_step_3_skill_title")}\uFF08${t("skill_count_format").replace("{count}", String(accumulated.length))}\uFF09` : t("wizard_step_3_skill_title");
|
|
1975
|
+
printBoxTitle(titleSuffix);
|
|
1919
1976
|
const categoryChoices = [
|
|
1977
|
+
{
|
|
1978
|
+
name: `>> ${t("skill_select_all").replace("{count}", String(allSkillIds.length))}`,
|
|
1979
|
+
value: SELECT_ALL
|
|
1980
|
+
},
|
|
1981
|
+
new Separator2("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
|
|
1920
1982
|
...categories.map((cat) => ({
|
|
1921
1983
|
name: `> ${cat.name} (${cat.skills.length} skills)`,
|
|
1922
1984
|
value: cat.id
|
|
1923
1985
|
})),
|
|
1924
1986
|
new Separator2("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
|
|
1987
|
+
...accumulated.length > 0 ? [{ name: `>> ${t("skill_confirm_install_count").replace("{count}", String(accumulated.length))}`, value: "install" }] : [],
|
|
1925
1988
|
{ name: "<- " + t("wizard_back"), value: BACK3 },
|
|
1926
1989
|
{ name: "x " + t("wizard_cancel"), value: CANCEL3 }
|
|
1927
1990
|
];
|
|
@@ -1935,6 +1998,12 @@ async function interactiveSkillSelect(tool, level) {
|
|
|
1935
1998
|
});
|
|
1936
1999
|
if (selectedCategoryId === BACK3) return "back";
|
|
1937
2000
|
if (selectedCategoryId === CANCEL3) return "cancel";
|
|
2001
|
+
if (selectedCategoryId === SELECT_ALL) {
|
|
2002
|
+
return allSkillIds;
|
|
2003
|
+
}
|
|
2004
|
+
if (selectedCategoryId === "install") {
|
|
2005
|
+
return accumulated;
|
|
2006
|
+
}
|
|
1938
2007
|
step = 1;
|
|
1939
2008
|
break;
|
|
1940
2009
|
}
|
|
@@ -1945,15 +2014,28 @@ async function interactiveSkillSelect(tool, level) {
|
|
|
1945
2014
|
const installPath = level === "project" ? process.cwd() : getConfigRoot(tool, level);
|
|
1946
2015
|
const installedSkills = getInstalledSkills(tool, level, installPath);
|
|
1947
2016
|
const installedSet = new Set(installedSkills);
|
|
1948
|
-
const
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
name:
|
|
1953
|
-
value:
|
|
1954
|
-
checked:
|
|
1955
|
-
|
|
1956
|
-
|
|
2017
|
+
const categorySkillIds = new Set(category.skills.map((s) => s.id));
|
|
2018
|
+
const accumulatedInCategory = new Set(accumulated.filter((id) => categorySkillIds.has(id)));
|
|
2019
|
+
const skillChoices = [
|
|
2020
|
+
{
|
|
2021
|
+
name: `>> ${t("skill_select_all_category")}`,
|
|
2022
|
+
value: SELECT_ALL_CATEGORY,
|
|
2023
|
+
checked: accumulatedInCategory.size === category.skills.length,
|
|
2024
|
+
description: t("skill_select_all_category")
|
|
2025
|
+
},
|
|
2026
|
+
new Separator2("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
|
|
2027
|
+
...category.skills.map((skill) => {
|
|
2028
|
+
const isInstalled = installedSet.has(skill.id);
|
|
2029
|
+
const isAccumulated = accumulatedInCategory.has(skill.id);
|
|
2030
|
+
const suffix = isInstalled ? ` [${t("skill_already_installed")}]` : isAccumulated ? " [+]" : "";
|
|
2031
|
+
return {
|
|
2032
|
+
name: `${chalk5.cyan(skill.id)}${suffix}`,
|
|
2033
|
+
value: skill.id,
|
|
2034
|
+
checked: isAccumulated,
|
|
2035
|
+
description: skill.description
|
|
2036
|
+
};
|
|
2037
|
+
})
|
|
2038
|
+
];
|
|
1957
2039
|
showOperationHints(true);
|
|
1958
2040
|
const selectedSkills = await checkbox2({
|
|
1959
2041
|
message: t("skill_select_items"),
|
|
@@ -1963,11 +2045,21 @@ async function interactiveSkillSelect(tool, level) {
|
|
|
1963
2045
|
theme: checkboxTheme,
|
|
1964
2046
|
pageSize: 15
|
|
1965
2047
|
});
|
|
1966
|
-
|
|
2048
|
+
let skillIds;
|
|
2049
|
+
if (selectedSkills.includes(SELECT_ALL_CATEGORY)) {
|
|
2050
|
+
skillIds = category.skills.map((s) => s.id);
|
|
2051
|
+
} else {
|
|
2052
|
+
skillIds = selectedSkills.filter((id) => id !== SELECT_ALL_CATEGORY);
|
|
2053
|
+
}
|
|
1967
2054
|
if (skillIds.length === 0) {
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
2055
|
+
accumulated = accumulated.filter((id) => !categorySkillIds.has(id));
|
|
2056
|
+
const action2 = await select3({
|
|
2057
|
+
message: accumulated.length > 0 ? t("skill_continue_or_install").replace("{count}", String(accumulated.length)) : t("wizard_no_selection"),
|
|
2058
|
+
choices: accumulated.length > 0 ? [
|
|
2059
|
+
{ name: ">> " + t("skill_confirm_install_count").replace("{count}", String(accumulated.length)), value: "install" },
|
|
2060
|
+
{ name: "<- " + t("wizard_back_to_reselect"), value: "back" },
|
|
2061
|
+
{ name: "x " + t("wizard_cancel"), value: "cancel" }
|
|
2062
|
+
] : [
|
|
1971
2063
|
new Separator2("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
|
|
1972
2064
|
{ name: "<- " + t("wizard_back_to_reselect"), value: "back" },
|
|
1973
2065
|
{ name: "x " + t("wizard_cancel"), value: "cancel" }
|
|
@@ -1975,13 +2067,38 @@ async function interactiveSkillSelect(tool, level) {
|
|
|
1975
2067
|
loop: false,
|
|
1976
2068
|
theme: selectTheme
|
|
1977
2069
|
});
|
|
1978
|
-
if (
|
|
2070
|
+
if (action2 === "install") return accumulated;
|
|
2071
|
+
if (action2 === "back") {
|
|
1979
2072
|
step = 0;
|
|
1980
2073
|
break;
|
|
1981
2074
|
}
|
|
1982
2075
|
return "cancel";
|
|
1983
2076
|
}
|
|
1984
|
-
|
|
2077
|
+
accumulated = accumulated.filter((id) => !categorySkillIds.has(id));
|
|
2078
|
+
for (const id of skillIds) {
|
|
2079
|
+
if (!accumulated.includes(id)) {
|
|
2080
|
+
accumulated.push(id);
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
2083
|
+
const action = await select3({
|
|
2084
|
+
message: t("skill_continue_or_install").replace("{count}", String(accumulated.length)),
|
|
2085
|
+
choices: [
|
|
2086
|
+
{ name: ">> " + t("skill_confirm_install_count").replace("{count}", String(accumulated.length)), value: "install" },
|
|
2087
|
+
{ name: "> " + t("skill_continue_select"), value: CONTINUE_SELECT },
|
|
2088
|
+
new Separator2("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
|
|
2089
|
+
{ name: "x " + t("wizard_cancel"), value: "cancel" }
|
|
2090
|
+
],
|
|
2091
|
+
loop: false,
|
|
2092
|
+
theme: selectTheme
|
|
2093
|
+
});
|
|
2094
|
+
if (action === "install") {
|
|
2095
|
+
return accumulated;
|
|
2096
|
+
}
|
|
2097
|
+
if (action === CONTINUE_SELECT) {
|
|
2098
|
+
step = 0;
|
|
2099
|
+
break;
|
|
2100
|
+
}
|
|
2101
|
+
return "cancel";
|
|
1985
2102
|
}
|
|
1986
2103
|
}
|
|
1987
2104
|
}
|
|
@@ -1989,11 +2106,11 @@ async function interactiveSkillSelect(tool, level) {
|
|
|
1989
2106
|
function listAllSkills() {
|
|
1990
2107
|
const categories = getAllCategories();
|
|
1991
2108
|
console.log();
|
|
1992
|
-
console.log(
|
|
1993
|
-
console.log(
|
|
2109
|
+
console.log(chalk5.bold(` ${t("skill_list_title")}`));
|
|
2110
|
+
console.log(chalk5.dim(" " + "\u2500".repeat(60)));
|
|
1994
2111
|
for (const category of categories) {
|
|
1995
2112
|
console.log();
|
|
1996
|
-
console.log(
|
|
2113
|
+
console.log(chalk5.bold(` ${category.name}`) + chalk5.dim(` (${category.skills.length} skills)`));
|
|
1997
2114
|
const table = new Table({
|
|
1998
2115
|
style: { head: [], border: [] },
|
|
1999
2116
|
colWidths: [35, 45],
|
|
@@ -2001,14 +2118,14 @@ function listAllSkills() {
|
|
|
2001
2118
|
});
|
|
2002
2119
|
for (const skill of category.skills) {
|
|
2003
2120
|
table.push([
|
|
2004
|
-
|
|
2121
|
+
chalk5.cyan(skill.id),
|
|
2005
2122
|
skill.description
|
|
2006
2123
|
]);
|
|
2007
2124
|
}
|
|
2008
2125
|
console.log(table.toString());
|
|
2009
2126
|
}
|
|
2010
2127
|
console.log();
|
|
2011
|
-
console.log(
|
|
2128
|
+
console.log(chalk5.dim(` ${t("skill_total_count").replace("{count}", String(getAllSkills().length))}`));
|
|
2012
2129
|
console.log();
|
|
2013
2130
|
}
|
|
2014
2131
|
function isSymlink2(path) {
|
|
@@ -2020,22 +2137,22 @@ function isSymlink2(path) {
|
|
|
2020
2137
|
}
|
|
2021
2138
|
|
|
2022
2139
|
// src/ui/display.ts
|
|
2023
|
-
import
|
|
2140
|
+
import chalk6 from "chalk";
|
|
2024
2141
|
import Table2 from "cli-table3";
|
|
2025
2142
|
function printPluginList(plugins, installed) {
|
|
2026
2143
|
const table = new Table2({
|
|
2027
2144
|
head: [
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2145
|
+
chalk6.cyan(t("list_id")),
|
|
2146
|
+
chalk6.cyan(t("list_name")),
|
|
2147
|
+
chalk6.cyan(t("list_status")),
|
|
2148
|
+
chalk6.cyan(t("list_skills")),
|
|
2149
|
+
chalk6.cyan(t("list_agents"))
|
|
2033
2150
|
],
|
|
2034
2151
|
style: { head: [], border: [] }
|
|
2035
2152
|
});
|
|
2036
2153
|
plugins.forEach((plugin, index) => {
|
|
2037
2154
|
const isInstalled = installed.has(plugin.id);
|
|
2038
|
-
const status = isInstalled ?
|
|
2155
|
+
const status = isInstalled ? chalk6.green(`\u2713 ${t("status_installed")}`) : chalk6.dim(`\u2014`);
|
|
2039
2156
|
table.push([
|
|
2040
2157
|
String(index + 1),
|
|
2041
2158
|
plugin.displayName,
|
|
@@ -2046,7 +2163,7 @@ function printPluginList(plugins, installed) {
|
|
|
2046
2163
|
});
|
|
2047
2164
|
console.log();
|
|
2048
2165
|
const countSuffix = t("count_suffix");
|
|
2049
|
-
console.log(
|
|
2166
|
+
console.log(chalk6.bold(` ${t("list_title")} (${plugins.length}${countSuffix ? " " + countSuffix : ""})`));
|
|
2050
2167
|
console.log(table.toString());
|
|
2051
2168
|
console.log();
|
|
2052
2169
|
}
|
|
@@ -2055,7 +2172,7 @@ function printInstallSummary(results) {
|
|
|
2055
2172
|
const totalCount = results.length;
|
|
2056
2173
|
console.log();
|
|
2057
2174
|
console.log(
|
|
2058
|
-
|
|
2175
|
+
chalk6.bold(
|
|
2059
2176
|
` ${t("install_done")}! ${successCount}/${totalCount} ${t("install_success")}`
|
|
2060
2177
|
)
|
|
2061
2178
|
);
|
|
@@ -2063,10 +2180,10 @@ function printInstallSummary(results) {
|
|
|
2063
2180
|
for (const result of results) {
|
|
2064
2181
|
if (result.success) {
|
|
2065
2182
|
console.log(
|
|
2066
|
-
|
|
2183
|
+
chalk6.green(" \u2713") + ` ${result.displayName} (${result.skillsCount} skills, ${result.agentsCount} agents)`
|
|
2067
2184
|
);
|
|
2068
2185
|
} else {
|
|
2069
|
-
console.log(
|
|
2186
|
+
console.log(chalk6.red(" \u2717") + ` ${result.displayName}`);
|
|
2070
2187
|
}
|
|
2071
2188
|
}
|
|
2072
2189
|
console.log();
|
|
@@ -2081,23 +2198,23 @@ function printEnhancedSummary(results, tool, configRoot) {
|
|
|
2081
2198
|
const toolName = getToolDisplayName(tool);
|
|
2082
2199
|
const countSuffix = t("count_suffix");
|
|
2083
2200
|
const lines = [
|
|
2084
|
-
|
|
2201
|
+
chalk6.bold(` ${t("install_done")}!`),
|
|
2085
2202
|
"",
|
|
2086
|
-
` ${
|
|
2087
|
-
` ${
|
|
2203
|
+
` ${chalk6.dim(t("install_installed_to") + ":")} ${configRoot}`,
|
|
2204
|
+
` ${chalk6.dim(t("install_skills_count") + ":")} ${totalSkills}${countSuffix ? " " + countSuffix : ""} ${chalk6.dim("|")} ${chalk6.dim(t("install_agents_count") + ":")} ${totalAgents}${countSuffix ? " " + countSuffix : ""}`,
|
|
2088
2205
|
"",
|
|
2089
|
-
|
|
2090
|
-
` ${
|
|
2091
|
-
` ${
|
|
2092
|
-
` ${
|
|
2093
|
-
` ${
|
|
2206
|
+
chalk6.bold(` ${t("install_enhanced_next_steps")}:`),
|
|
2207
|
+
` ${chalk6.cyan("1.")} ${t("install_enhanced_launch")}: ${chalk6.green(toolName.toLowerCase())}`,
|
|
2208
|
+
` ${chalk6.cyan("2.")} ${t("install_enhanced_try")}: ${chalk6.green(t("try_prompt"))}`,
|
|
2209
|
+
` ${chalk6.cyan("3.")} ${t("install_enhanced_more")}: ${chalk6.green("install-helper list")}`,
|
|
2210
|
+
` ${chalk6.cyan("4.")} ${t("install_enhanced_check")}: ${chalk6.green("install-helper doctor")}`,
|
|
2094
2211
|
""
|
|
2095
2212
|
];
|
|
2096
2213
|
if (successResults.length === 1) {
|
|
2097
2214
|
const plugin = findPlugin(successResults[0].pluginId);
|
|
2098
2215
|
const docsPath = plugin ? `${plugin.dir}/quickstart.md` : `${successResults[0].pluginId}/quickstart.md`;
|
|
2099
2216
|
lines.push(
|
|
2100
|
-
` ${
|
|
2217
|
+
` ${chalk6.dim(t("install_enhanced_docs"))}: ${chalk6.dim(docsPath)}`
|
|
2101
2218
|
);
|
|
2102
2219
|
}
|
|
2103
2220
|
console.log();
|
|
@@ -2298,7 +2415,7 @@ async function skillInstallFlow() {
|
|
|
2298
2415
|
spinner.start();
|
|
2299
2416
|
const repoPath = await repoManager.ensureRepo();
|
|
2300
2417
|
spinner.succeed(t("loading_plugin_data_complete"));
|
|
2301
|
-
logger.info(`${t("skill_install_progress")} ${t("skill_count_format").replace("{count}",
|
|
2418
|
+
logger.info(`${t("skill_install_progress")} ${t("skill_count_format").replace("{count}", chalk7.bold(String(selectedSkills.length)))}...`);
|
|
2302
2419
|
const results = await installSkills(selectedSkills, tool, level, repoPath);
|
|
2303
2420
|
let successCount = 0;
|
|
2304
2421
|
let failCount = 0;
|
|
@@ -2316,10 +2433,10 @@ async function skillInstallFlow() {
|
|
|
2316
2433
|
}
|
|
2317
2434
|
const configRoot = getConfigRoot(tool, level);
|
|
2318
2435
|
logger.blank();
|
|
2319
|
-
logger.success(`${t("skill_install_done")}: ${
|
|
2436
|
+
logger.success(`${t("skill_install_done")}: ${chalk7.green(t("result_success_format").replace("{count}", String(successCount)))}, ${failCount > 0 ? chalk7.red(t("result_failed_format").replace("{count}", String(failCount))) : chalk7.dim(t("result_failed_format").replace("{count}", String(failCount)))}`);
|
|
2320
2437
|
logger.blank();
|
|
2321
|
-
logger.info(`${t("install_to")}: ${
|
|
2322
|
-
logger.info(`${t("start_to_use").replace("{tool}",
|
|
2438
|
+
logger.info(`${t("install_to")}: ${chalk7.cyan(configRoot + "/skills/")}`);
|
|
2439
|
+
logger.info(`${t("start_to_use").replace("{tool}", chalk7.green(tool))}`);
|
|
2323
2440
|
logger.blank();
|
|
2324
2441
|
return "done";
|
|
2325
2442
|
}
|
|
@@ -2341,32 +2458,32 @@ async function listCommand() {
|
|
|
2341
2458
|
}
|
|
2342
2459
|
|
|
2343
2460
|
// src/commands/doctor.ts
|
|
2344
|
-
import
|
|
2461
|
+
import chalk8 from "chalk";
|
|
2345
2462
|
import { existsSync as existsSync12, readdirSync as readdirSync5, lstatSync as lstatSync3, unlinkSync as unlinkSync4, mkdirSync as mkdirSync6 } from "fs";
|
|
2346
2463
|
import { join as join14 } from "path";
|
|
2347
2464
|
async function doctorCommand(options = {}) {
|
|
2348
2465
|
console.log();
|
|
2349
|
-
console.log(
|
|
2350
|
-
console.log(
|
|
2466
|
+
console.log(chalk8.bold(` ${t("doctor_title")}`));
|
|
2467
|
+
console.log(chalk8.dim(" " + "\u2500".repeat(46)));
|
|
2351
2468
|
let errors = 0;
|
|
2352
2469
|
let warnings = 0;
|
|
2353
2470
|
let fixes = 0;
|
|
2354
2471
|
console.log();
|
|
2355
|
-
console.log(
|
|
2472
|
+
console.log(chalk8.bold(` ${t("doctor_tools")}`));
|
|
2356
2473
|
const detectedTools = await detectTools();
|
|
2357
2474
|
const allTools = getAllTools();
|
|
2358
2475
|
for (const tool of allTools) {
|
|
2359
2476
|
const detected = detectedTools.find((d) => d.name === tool);
|
|
2360
2477
|
if (detected) {
|
|
2361
2478
|
console.log(
|
|
2362
|
-
|
|
2479
|
+
chalk8.green(" \u2713") + ` ${getToolDisplayName(tool)}${detected.version ? ` v${detected.version}` : ""}`
|
|
2363
2480
|
);
|
|
2364
2481
|
} else {
|
|
2365
|
-
console.log(
|
|
2482
|
+
console.log(chalk8.dim(" \u2014") + ` ${getToolDisplayName(tool)} \u2014 ${t("doctor_not_installed")}`);
|
|
2366
2483
|
}
|
|
2367
2484
|
}
|
|
2368
2485
|
console.log();
|
|
2369
|
-
console.log(
|
|
2486
|
+
console.log(chalk8.bold(` ${t("doctor_plugins")}`));
|
|
2370
2487
|
const plugins = getAllPlugins();
|
|
2371
2488
|
const installed = scanInstalled();
|
|
2372
2489
|
const installedMap = new Map(installed.map((p) => [p.id, p]));
|
|
@@ -2374,14 +2491,14 @@ async function doctorCommand(options = {}) {
|
|
|
2374
2491
|
const inst = installedMap.get(plugin.id);
|
|
2375
2492
|
if (inst) {
|
|
2376
2493
|
console.log(
|
|
2377
|
-
|
|
2494
|
+
chalk8.green(" \u2713") + ` ${plugin.id.padEnd(30)} ${inst.skillsCount} skills, ${inst.agentsCount} agents`
|
|
2378
2495
|
);
|
|
2379
2496
|
} else {
|
|
2380
|
-
console.log(
|
|
2497
|
+
console.log(chalk8.dim(" \u2014") + ` ${plugin.id.padEnd(30)} \u2014 ${t("doctor_not_installed")}`);
|
|
2381
2498
|
}
|
|
2382
2499
|
}
|
|
2383
2500
|
console.log();
|
|
2384
|
-
console.log(
|
|
2501
|
+
console.log(chalk8.bold(` ${t("doctor_links")}`));
|
|
2385
2502
|
const primaryTool = detectedTools[0]?.name || "opencode";
|
|
2386
2503
|
const configRoot = getConfigRoot(primaryTool, "project");
|
|
2387
2504
|
const skillsDir = getSkillsDir(configRoot);
|
|
@@ -2390,57 +2507,57 @@ async function doctorCommand(options = {}) {
|
|
|
2390
2507
|
const brokenLinks = checkBrokenLinks(skillsDir);
|
|
2391
2508
|
if (brokenLinks === 0) {
|
|
2392
2509
|
const count = readdirSync5(skillsDir).length;
|
|
2393
|
-
console.log(
|
|
2510
|
+
console.log(chalk8.green(" \u2713") + ` ${skillsDir} \u2014 ${t("doctor_links_valid").replace("{count}", String(count))}`);
|
|
2394
2511
|
} else {
|
|
2395
|
-
console.log(
|
|
2512
|
+
console.log(chalk8.yellow(" \u26A0") + ` ${skillsDir} \u2014 ${t("doctor_broken_links").replace("{count}", String(brokenLinks))}`);
|
|
2396
2513
|
warnings++;
|
|
2397
2514
|
if (options.fix) {
|
|
2398
2515
|
const fixed = fixBrokenLinks(skillsDir);
|
|
2399
2516
|
fixes += fixed;
|
|
2400
|
-
console.log(
|
|
2517
|
+
console.log(chalk8.green(" \u2713") + ` ${t("doctor_fix_cleaning")}: ${t("doctor_fixed").replace("{count}", String(fixed))}`);
|
|
2401
2518
|
}
|
|
2402
2519
|
}
|
|
2403
2520
|
} else {
|
|
2404
|
-
console.log(
|
|
2521
|
+
console.log(chalk8.dim(" \u2014") + ` ${skillsDir} \u2014 ${t("doctor_not_exist")}`);
|
|
2405
2522
|
if (options.fix) {
|
|
2406
2523
|
mkdirSync6(skillsDir, { recursive: true });
|
|
2407
2524
|
fixes++;
|
|
2408
|
-
console.log(
|
|
2525
|
+
console.log(chalk8.green(" \u2713") + ` ${t("doctor_fix_rebuilding")}: ${t("doctor_created").replace("{path}", skillsDir)}`);
|
|
2409
2526
|
}
|
|
2410
2527
|
}
|
|
2411
2528
|
if (existsSync12(agentsDir)) {
|
|
2412
2529
|
const brokenLinks = checkBrokenLinks(agentsDir);
|
|
2413
2530
|
if (brokenLinks === 0) {
|
|
2414
2531
|
const count = readdirSync5(agentsDir).length;
|
|
2415
|
-
console.log(
|
|
2532
|
+
console.log(chalk8.green(" \u2713") + ` ${agentsDir} \u2014 ${t("doctor_links_valid").replace("{count}", String(count))}`);
|
|
2416
2533
|
} else {
|
|
2417
|
-
console.log(
|
|
2534
|
+
console.log(chalk8.yellow(" \u26A0") + ` ${agentsDir} \u2014 ${t("doctor_broken_links").replace("{count}", String(brokenLinks))}`);
|
|
2418
2535
|
warnings++;
|
|
2419
2536
|
if (options.fix) {
|
|
2420
2537
|
const fixed = fixBrokenLinks(agentsDir);
|
|
2421
2538
|
fixes += fixed;
|
|
2422
|
-
console.log(
|
|
2539
|
+
console.log(chalk8.green(" \u2713") + ` ${t("doctor_fix_cleaning")}: ${t("doctor_fixed").replace("{count}", String(fixed))}`);
|
|
2423
2540
|
}
|
|
2424
2541
|
}
|
|
2425
2542
|
} else {
|
|
2426
|
-
console.log(
|
|
2543
|
+
console.log(chalk8.dim(" \u2014") + ` ${agentsDir} \u2014 ${t("doctor_not_exist")}`);
|
|
2427
2544
|
if (options.fix) {
|
|
2428
2545
|
mkdirSync6(agentsDir, { recursive: true });
|
|
2429
2546
|
fixes++;
|
|
2430
|
-
console.log(
|
|
2547
|
+
console.log(chalk8.green(" \u2713") + ` ${t("doctor_fix_rebuilding")}: ${t("doctor_created").replace("{path}", agentsDir)}`);
|
|
2431
2548
|
}
|
|
2432
2549
|
}
|
|
2433
2550
|
console.log();
|
|
2434
|
-
console.log(
|
|
2551
|
+
console.log(chalk8.bold(` ${t("doctor_config")}`));
|
|
2435
2552
|
const configFile = getConfigFileName(primaryTool);
|
|
2436
2553
|
const configPath = join14(process.cwd(), configFile);
|
|
2437
2554
|
if (existsSync12(configPath)) {
|
|
2438
|
-
console.log(
|
|
2555
|
+
console.log(chalk8.green(" \u2713") + ` ${configFile} ${t("doctor_config_exists")}`);
|
|
2439
2556
|
} else {
|
|
2440
|
-
console.log(
|
|
2557
|
+
console.log(chalk8.dim(" \u2014") + ` ${configFile} ${t("doctor_config_not_exist")}`);
|
|
2441
2558
|
}
|
|
2442
2559
|
console.log();
|
|
2443
|
-
console.log(
|
|
2560
|
+
console.log(chalk8.dim(" " + "\u2500".repeat(46)));
|
|
2444
2561
|
if (options.fix && fixes > 0) {
|
|
2445
2562
|
console.log(
|
|
2446
2563
|
` ${t("doctor_result")}: ${t("doctor_result_with_fix").replace("{warnings}", String(warnings)).replace("{errors}", String(errors)).replace("{fixes}", String(fixes))}`
|
|
@@ -2496,36 +2613,36 @@ function fixBrokenLinks(dir) {
|
|
|
2496
2613
|
}
|
|
2497
2614
|
|
|
2498
2615
|
// src/commands/status.ts
|
|
2499
|
-
import
|
|
2616
|
+
import chalk9 from "chalk";
|
|
2500
2617
|
async function statusCommand() {
|
|
2501
2618
|
const plugins = getAllPlugins();
|
|
2502
2619
|
const installed = scanInstalled();
|
|
2503
2620
|
const installedMap = new Map(installed.map((p) => [p.id, p]));
|
|
2504
2621
|
console.log();
|
|
2505
|
-
console.log(
|
|
2622
|
+
console.log(chalk9.bold(` ${t("status_title")}`));
|
|
2506
2623
|
console.log();
|
|
2507
2624
|
if (installed.length === 0) {
|
|
2508
|
-
console.log(
|
|
2509
|
-
console.log(
|
|
2625
|
+
console.log(chalk9.dim(` ${t("status_none")}`));
|
|
2626
|
+
console.log(chalk9.dim(` ${t("status_hint")}`));
|
|
2510
2627
|
console.log();
|
|
2511
2628
|
return;
|
|
2512
2629
|
}
|
|
2513
2630
|
for (const inst of installed) {
|
|
2514
2631
|
console.log(
|
|
2515
|
-
|
|
2632
|
+
chalk9.green(" \u2713") + ` ${inst.displayName}` + chalk9.dim(` (${inst.tool}, ${inst.level})`)
|
|
2516
2633
|
);
|
|
2517
2634
|
console.log(
|
|
2518
|
-
|
|
2635
|
+
chalk9.dim(` ${inst.skillsCount} skills, ${inst.agentsCount} agents`)
|
|
2519
2636
|
);
|
|
2520
|
-
console.log(
|
|
2521
|
-
console.log(
|
|
2637
|
+
console.log(chalk9.dim(` ${inst.configRoot}`));
|
|
2638
|
+
console.log(chalk9.dim(` ${t("status_install_time")}: ${inst.installTime}`));
|
|
2522
2639
|
console.log();
|
|
2523
2640
|
}
|
|
2524
2641
|
}
|
|
2525
2642
|
|
|
2526
2643
|
// src/commands/install.ts
|
|
2527
2644
|
import { confirm } from "@inquirer/prompts";
|
|
2528
|
-
import
|
|
2645
|
+
import chalk10 from "chalk";
|
|
2529
2646
|
async function installCommand(names, options) {
|
|
2530
2647
|
if (options.list) {
|
|
2531
2648
|
try {
|
|
@@ -2536,6 +2653,61 @@ async function installCommand(names, options) {
|
|
|
2536
2653
|
listAllSkills();
|
|
2537
2654
|
return;
|
|
2538
2655
|
}
|
|
2656
|
+
if (options.all) {
|
|
2657
|
+
const scanSpinner2 = createSpinner(t("loading_skills_list"));
|
|
2658
|
+
scanSpinner2.start();
|
|
2659
|
+
try {
|
|
2660
|
+
const scanRepoManager = createRepositoryManager();
|
|
2661
|
+
await scanRepoManager.ensureRepoAndScan();
|
|
2662
|
+
scanSpinner2.succeed(t("loading_skills_list_complete"));
|
|
2663
|
+
} catch {
|
|
2664
|
+
scanSpinner2.warn(t("loading_skills_list_failed"));
|
|
2665
|
+
}
|
|
2666
|
+
const allSkills = getAllSkills();
|
|
2667
|
+
const skillIds = allSkills.map((s) => s.id);
|
|
2668
|
+
if (skillIds.length === 0) {
|
|
2669
|
+
logger.error(t("install_no_skill_selected"));
|
|
2670
|
+
return;
|
|
2671
|
+
}
|
|
2672
|
+
let tool2;
|
|
2673
|
+
if (options.tool) {
|
|
2674
|
+
tool2 = validateTool(options.tool);
|
|
2675
|
+
} else {
|
|
2676
|
+
const detected = await selectToolWithDetection();
|
|
2677
|
+
if (detected === "back" || detected === "cancel") return;
|
|
2678
|
+
tool2 = detected;
|
|
2679
|
+
}
|
|
2680
|
+
const level2 = options.level ? validateLevel(options.level) : "project";
|
|
2681
|
+
const repoManager = createRepositoryManager();
|
|
2682
|
+
const spinner = createSpinner(t("loading_plugin_data"));
|
|
2683
|
+
spinner.start();
|
|
2684
|
+
const repoPath = await repoManager.ensureRepo();
|
|
2685
|
+
spinner.succeed(t("loading_plugin_data_complete"));
|
|
2686
|
+
logger.info(`${t("skill_all_install_progress").replace("{count}", chalk10.bold(String(skillIds.length)))}`);
|
|
2687
|
+
const results = await installSkills(skillIds, tool2, level2, repoPath);
|
|
2688
|
+
let successCount = 0;
|
|
2689
|
+
let failCount = 0;
|
|
2690
|
+
const total = results.length;
|
|
2691
|
+
for (let i = 0; i < results.length; i++) {
|
|
2692
|
+
const result = results[i];
|
|
2693
|
+
const progress = `[${i + 1}/${total}]`;
|
|
2694
|
+
if (result.success) {
|
|
2695
|
+
logger.success(`${progress} ${result.skillId}`);
|
|
2696
|
+
successCount++;
|
|
2697
|
+
} else {
|
|
2698
|
+
logger.error(`${progress} ${result.skillId}: ${result.error}`);
|
|
2699
|
+
failCount++;
|
|
2700
|
+
}
|
|
2701
|
+
}
|
|
2702
|
+
const configRoot = getConfigRoot(tool2, level2);
|
|
2703
|
+
logger.blank();
|
|
2704
|
+
logger.success(`${t("skill_install_done")}: ${chalk10.green(t("result_success_format").replace("{count}", String(successCount)))}, ${failCount > 0 ? chalk10.red(t("result_failed_format").replace("{count}", String(failCount))) : chalk10.dim(t("result_failed_format").replace("{count}", String(failCount)))}`);
|
|
2705
|
+
logger.blank();
|
|
2706
|
+
logger.info(`${t("install_to")}: ${chalk10.cyan(configRoot + "/skills/")}`);
|
|
2707
|
+
logger.info(`${t("start_to_use").replace("{tool}", chalk10.green(tool2))}`);
|
|
2708
|
+
logger.blank();
|
|
2709
|
+
return;
|
|
2710
|
+
}
|
|
2539
2711
|
if (names.length === 0) {
|
|
2540
2712
|
const scanSpinner2 = createSpinner(t("loading_skills_list"));
|
|
2541
2713
|
scanSpinner2.start();
|
|
@@ -2577,7 +2749,7 @@ async function installCommand(names, options) {
|
|
|
2577
2749
|
spinner.start();
|
|
2578
2750
|
const repoPath = await repoManager.ensureRepo();
|
|
2579
2751
|
spinner.succeed(t("loading_plugin_data_complete"));
|
|
2580
|
-
logger.info(`${t("skill_install_progress")} ${t("skill_count_format").replace("{count}",
|
|
2752
|
+
logger.info(`${t("skill_install_progress")} ${t("skill_count_format").replace("{count}", chalk10.bold(String(names.length)))}...`);
|
|
2581
2753
|
const results = await installSkills(names, tool2, level2, repoPath);
|
|
2582
2754
|
let successCount = 0;
|
|
2583
2755
|
let failCount = 0;
|
|
@@ -2595,10 +2767,10 @@ async function installCommand(names, options) {
|
|
|
2595
2767
|
}
|
|
2596
2768
|
const configRoot = getConfigRoot(tool2, level2);
|
|
2597
2769
|
logger.blank();
|
|
2598
|
-
logger.success(`${t("skill_install_done")}: ${
|
|
2770
|
+
logger.success(`${t("skill_install_done")}: ${chalk10.green(t("result_success_format").replace("{count}", String(successCount)))}, ${failCount > 0 ? chalk10.red(t("result_failed_format").replace("{count}", String(failCount))) : chalk10.dim(t("result_failed_format").replace("{count}", String(failCount)))}`);
|
|
2599
2771
|
logger.blank();
|
|
2600
|
-
logger.info(`${t("install_to")}: ${
|
|
2601
|
-
logger.info(`${t("start_to_use").replace("{tool}",
|
|
2772
|
+
logger.info(`${t("install_to")}: ${chalk10.cyan(configRoot + "/skills/")}`);
|
|
2773
|
+
logger.info(`${t("start_to_use").replace("{tool}", chalk10.green(tool2))}`);
|
|
2602
2774
|
logger.blank();
|
|
2603
2775
|
return;
|
|
2604
2776
|
}
|
|
@@ -2633,7 +2805,7 @@ async function installCommand(names, options) {
|
|
|
2633
2805
|
for (const p of allPlugins) {
|
|
2634
2806
|
logger.step(` ${p.id} (${p.aliases.join(", ")})`);
|
|
2635
2807
|
}
|
|
2636
|
-
logger.info(`${t("available_skills")}: ${
|
|
2808
|
+
logger.info(`${t("available_skills")}: ${chalk10.cyan("install-helper install --list")}`);
|
|
2637
2809
|
return;
|
|
2638
2810
|
}
|
|
2639
2811
|
let tool;
|
|
@@ -2705,7 +2877,7 @@ async function installCommand(names, options) {
|
|
|
2705
2877
|
spinner.start();
|
|
2706
2878
|
const repoPath = await repoManager.ensureRepo();
|
|
2707
2879
|
spinner.succeed(t("loading_plugin_data_complete"));
|
|
2708
|
-
logger.info(`${t("skill_install_progress")} ${t("skill_count_format").replace("{count}",
|
|
2880
|
+
logger.info(`${t("skill_install_progress")} ${t("skill_count_format").replace("{count}", chalk10.bold(String(skills.length)))}...`);
|
|
2709
2881
|
const results = await installSkills(skills, tool, level, repoPath);
|
|
2710
2882
|
let successCount = 0;
|
|
2711
2883
|
let failCount = 0;
|
|
@@ -2722,14 +2894,14 @@ async function installCommand(names, options) {
|
|
|
2722
2894
|
}
|
|
2723
2895
|
}
|
|
2724
2896
|
logger.blank();
|
|
2725
|
-
logger.success(`${t("skill_install_done")}: ${
|
|
2897
|
+
logger.success(`${t("skill_install_done")}: ${chalk10.green(t("result_success_format").replace("{count}", String(successCount)))}, ${failCount > 0 ? chalk10.red(t("result_failed_format").replace("{count}", String(failCount))) : chalk10.dim(t("result_failed_format").replace("{count}", String(failCount)))}`);
|
|
2726
2898
|
logger.blank();
|
|
2727
|
-
logger.info(`${t("install_to")}: ${
|
|
2728
|
-
logger.info(`${t("start_to_use").replace("{tool}",
|
|
2899
|
+
logger.info(`${t("install_to")}: ${chalk10.cyan(getConfigRoot(tool, level) + "/skills/")}`);
|
|
2900
|
+
logger.info(`${t("start_to_use").replace("{tool}", chalk10.green(tool))}`);
|
|
2729
2901
|
logger.blank();
|
|
2730
2902
|
}
|
|
2731
2903
|
}
|
|
2732
|
-
async function installPlugins(pluginIds, tool, level, repoPath) {
|
|
2904
|
+
async function installPlugins(pluginIds, tool, level, repoPath, installPath, yes) {
|
|
2733
2905
|
const results = [];
|
|
2734
2906
|
const total = pluginIds.length;
|
|
2735
2907
|
for (let i = 0; i < pluginIds.length; i++) {
|
|
@@ -2741,7 +2913,9 @@ async function installPlugins(pluginIds, tool, level, repoPath) {
|
|
|
2741
2913
|
pluginId,
|
|
2742
2914
|
tool,
|
|
2743
2915
|
level,
|
|
2744
|
-
repoPath
|
|
2916
|
+
repoPath,
|
|
2917
|
+
installPath,
|
|
2918
|
+
yes
|
|
2745
2919
|
});
|
|
2746
2920
|
if (result.success) {
|
|
2747
2921
|
spinner.succeed(
|
|
@@ -2758,7 +2932,7 @@ async function installPlugins(pluginIds, tool, level, repoPath) {
|
|
|
2758
2932
|
|
|
2759
2933
|
// src/commands/uninstall.ts
|
|
2760
2934
|
import { existsSync as existsSync13, unlinkSync as unlinkSync5, rmdirSync as rmdirSync2, readdirSync as readdirSync6, lstatSync as lstatSync4 } from "fs";
|
|
2761
|
-
import
|
|
2935
|
+
import chalk11 from "chalk";
|
|
2762
2936
|
async function uninstallCommand(names, options) {
|
|
2763
2937
|
const tool = options.tool ? validateTool(options.tool) : "opencode";
|
|
2764
2938
|
const level = options.level ? validateLevel(options.level) : "project";
|
|
@@ -2858,7 +3032,7 @@ async function uninstallCommand(names, options) {
|
|
|
2858
3032
|
}
|
|
2859
3033
|
}
|
|
2860
3034
|
logger.blank();
|
|
2861
|
-
logger.success(`${t("skill_uninstall_done")}: ${
|
|
3035
|
+
logger.success(`${t("skill_uninstall_done")}: ${chalk11.green(t("result_success_format").replace("{count}", String(successCount)))}, ${failCount > 0 ? chalk11.red(t("result_failed_format").replace("{count}", String(failCount))) : chalk11.dim(t("result_failed_format").replace("{count}", String(failCount)))}`);
|
|
2862
3036
|
logger.blank();
|
|
2863
3037
|
}
|
|
2864
3038
|
}
|
|
@@ -2871,7 +3045,7 @@ function isSymlink3(path) {
|
|
|
2871
3045
|
}
|
|
2872
3046
|
|
|
2873
3047
|
// src/commands/update.ts
|
|
2874
|
-
import
|
|
3048
|
+
import chalk12 from "chalk";
|
|
2875
3049
|
async function updateCommand(pluginNames, options) {
|
|
2876
3050
|
let tool;
|
|
2877
3051
|
if (options.tool) {
|
|
@@ -2889,7 +3063,7 @@ async function updateCommand(pluginNames, options) {
|
|
|
2889
3063
|
pluginsToUpdate = manifests.map((m) => m.team);
|
|
2890
3064
|
if (pluginsToUpdate.length === 0) {
|
|
2891
3065
|
logger.info(t("update_no_plugins"));
|
|
2892
|
-
logger.info(t("update_install_hint").replace("{cmd}",
|
|
3066
|
+
logger.info(t("update_install_hint").replace("{cmd}", chalk12.cyan("install-helper install <plugin>")));
|
|
2893
3067
|
return;
|
|
2894
3068
|
}
|
|
2895
3069
|
} else {
|
|
@@ -2951,42 +3125,42 @@ async function updateCommand(pluginNames, options) {
|
|
|
2951
3125
|
}
|
|
2952
3126
|
|
|
2953
3127
|
// src/commands/info.ts
|
|
2954
|
-
import
|
|
3128
|
+
import chalk13 from "chalk";
|
|
2955
3129
|
import { existsSync as existsSync14, readdirSync as readdirSync7 } from "fs";
|
|
2956
3130
|
import { join as join15 } from "path";
|
|
2957
3131
|
async function infoCommand(pluginName) {
|
|
2958
3132
|
const plugin = findPlugin(pluginName);
|
|
2959
3133
|
if (!plugin) {
|
|
2960
|
-
console.log(
|
|
3134
|
+
console.log(chalk13.red(` ${t("info_not_found")}: ${pluginName}`));
|
|
2961
3135
|
return;
|
|
2962
3136
|
}
|
|
2963
3137
|
const installed = scanInstalled();
|
|
2964
3138
|
const isInstalled = installed.some((p) => p.id === plugin.id);
|
|
2965
|
-
const statusText = isInstalled ?
|
|
3139
|
+
const statusText = isInstalled ? chalk13.green(`\u2713 ${t("status_installed")}`) : chalk13.dim(`\u2014 ${t("status_not_installed")}`);
|
|
2966
3140
|
console.log();
|
|
2967
|
-
console.log(
|
|
2968
|
-
console.log(
|
|
3141
|
+
console.log(chalk13.bold(` ${plugin.displayName}`));
|
|
3142
|
+
console.log(chalk13.dim(" " + "\u2500".repeat(40)));
|
|
2969
3143
|
console.log();
|
|
2970
|
-
console.log(` ${
|
|
2971
|
-
console.log(` ${
|
|
2972
|
-
console.log(` ${
|
|
2973
|
-
console.log(` ${
|
|
2974
|
-
console.log(` ${
|
|
2975
|
-
console.log(` ${
|
|
3144
|
+
console.log(` ${chalk13.dim(t("info_description") + ":")} ${plugin.description}`);
|
|
3145
|
+
console.log(` ${chalk13.dim("ID:")} ${plugin.id}`);
|
|
3146
|
+
console.log(` ${chalk13.dim(t("info_status") + ":")} ${statusText}`);
|
|
3147
|
+
console.log(` ${chalk13.dim(t("info_skills") + ":")} ${plugin.skills}`);
|
|
3148
|
+
console.log(` ${chalk13.dim(t("info_agents") + ":")} ${plugin.agents}`);
|
|
3149
|
+
console.log(` ${chalk13.dim(t("info_aliases") + ":")} ${plugin.aliases.join(", ")}`);
|
|
2976
3150
|
console.log();
|
|
2977
3151
|
try {
|
|
2978
3152
|
const repoManager = createRepositoryManager();
|
|
2979
3153
|
const repoPath = await repoManager.ensureRepo();
|
|
2980
3154
|
const quickstartPath = join15(repoPath, plugin.dir, "quickstart.md");
|
|
2981
3155
|
if (existsSync14(quickstartPath)) {
|
|
2982
|
-
console.log(` ${
|
|
3156
|
+
console.log(` ${chalk13.dim(t("info_quickstart") + ":")} ${quickstartPath}`);
|
|
2983
3157
|
}
|
|
2984
3158
|
const agentsDir = join15(repoPath, plugin.dir, "agents");
|
|
2985
3159
|
if (existsSync14(agentsDir)) {
|
|
2986
3160
|
const agentFiles = readdirSync7(agentsDir).filter((f) => f.endsWith(".md"));
|
|
2987
3161
|
if (agentFiles.length > 0) {
|
|
2988
3162
|
console.log();
|
|
2989
|
-
console.log(` ${
|
|
3163
|
+
console.log(` ${chalk13.bold("Agents:")}`);
|
|
2990
3164
|
for (const agent of agentFiles) {
|
|
2991
3165
|
console.log(` \u2022 ${agent.replace(".md", "")}`);
|
|
2992
3166
|
}
|
|
@@ -2998,39 +3172,39 @@ async function infoCommand(pluginName) {
|
|
|
2998
3172
|
}
|
|
2999
3173
|
|
|
3000
3174
|
// src/commands/lang.ts
|
|
3001
|
-
import
|
|
3175
|
+
import chalk14 from "chalk";
|
|
3002
3176
|
async function langCommand(action, value) {
|
|
3003
3177
|
const config = readConfig();
|
|
3004
3178
|
if (!action || action === "show") {
|
|
3005
3179
|
console.log();
|
|
3006
|
-
console.log(
|
|
3007
|
-
console.log(
|
|
3180
|
+
console.log(chalk14.bold(` ${t("lang_title")}`));
|
|
3181
|
+
console.log(chalk14.dim(" " + "\u2500".repeat(40)));
|
|
3008
3182
|
console.log();
|
|
3009
|
-
console.log(` ${
|
|
3183
|
+
console.log(` ${chalk14.dim(t("lang_current") + ":")} ${config.language}`);
|
|
3010
3184
|
console.log();
|
|
3011
|
-
console.log(
|
|
3012
|
-
console.log(
|
|
3185
|
+
console.log(chalk14.dim(` ${t("lang_supported")}`));
|
|
3186
|
+
console.log(chalk14.dim(` ${t("lang_usage")}`));
|
|
3013
3187
|
console.log();
|
|
3014
3188
|
return;
|
|
3015
3189
|
}
|
|
3016
3190
|
if (action === "set") {
|
|
3017
3191
|
if (!value) {
|
|
3018
|
-
console.log(
|
|
3192
|
+
console.log(chalk14.red(` ${t("lang_specify")}`));
|
|
3019
3193
|
return;
|
|
3020
3194
|
}
|
|
3021
3195
|
if (value !== "zh_CN" && value !== "en_US") {
|
|
3022
|
-
console.log(
|
|
3196
|
+
console.log(chalk14.red(` ${t("lang_invalid")}`));
|
|
3023
3197
|
return;
|
|
3024
3198
|
}
|
|
3025
3199
|
updateConfig({ language: value });
|
|
3026
3200
|
setLanguage(value);
|
|
3027
3201
|
console.log();
|
|
3028
|
-
console.log(
|
|
3202
|
+
console.log(chalk14.green(` \u2713 ${t("lang_set")} ${value}`));
|
|
3029
3203
|
console.log();
|
|
3030
3204
|
return;
|
|
3031
3205
|
}
|
|
3032
|
-
console.log(
|
|
3033
|
-
console.log(
|
|
3206
|
+
console.log(chalk14.red(` ${t("lang_unknown_action")}: ${action}`));
|
|
3207
|
+
console.log(chalk14.dim(` ${t("lang_supported_actions")}`));
|
|
3034
3208
|
}
|
|
3035
3209
|
|
|
3036
3210
|
// src/cli.ts
|
|
@@ -3040,7 +3214,7 @@ function createCLI() {
|
|
|
3040
3214
|
setLanguage(config.language);
|
|
3041
3215
|
}
|
|
3042
3216
|
const program2 = new Command();
|
|
3043
|
-
program2.name("install-helper").description("CANNBot Install Helper - Interactive installer for CANN operator development skills").version("1.0.
|
|
3217
|
+
program2.name("install-helper").description("CANNBot Install Helper - Interactive installer for CANN operator development skills").version("1.0.6");
|
|
3044
3218
|
program2.command("init", { isDefault: false }).description("Run interactive installation wizard").action(async () => {
|
|
3045
3219
|
await initCommand();
|
|
3046
3220
|
});
|
|
@@ -3053,7 +3227,7 @@ function createCLI() {
|
|
|
3053
3227
|
program2.command("status").description("Show installed plugins").action(async () => {
|
|
3054
3228
|
await statusCommand();
|
|
3055
3229
|
});
|
|
3056
|
-
program2.command("install [names...]").description("Install plugins or skills (auto-detects type)").option("-t, --tool <tool>", "AI tool (opencode, claude, trae, cursor, copilot)").option("-l, --level <level>", "Install level (project, global)", "project").option("-y, --yes", "Skip confirmation prompts").option("--list", "List all available skills by category").action(async (names, options) => {
|
|
3230
|
+
program2.command("install [names...]").description("Install plugins or skills (auto-detects type)").option("-t, --tool <tool>", "AI tool (opencode, claude, trae, cursor, copilot)").option("-l, --level <level>", "Install level (project, global)", "project").option("-y, --yes", "Skip confirmation prompts").option("-a, --all", "Install ALL available skills").option("--list", "List all available skills by category").action(async (names, options) => {
|
|
3057
3231
|
await installCommand(names, options);
|
|
3058
3232
|
});
|
|
3059
3233
|
program2.command("uninstall <names...>").description("Uninstall plugins or skills (auto-detects type)").option("-t, --tool <tool>", "AI tool (opencode, claude, trae, cursor, copilot)").option("-l, --level <level>", "Install level (project, global)", "project").action(async (names, options) => {
|