@cannbot-ai/install-helper 0.0.2-beta.1 → 0.0.2-beta.10
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 +573 -243
- 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";
|
|
@@ -232,7 +232,7 @@ async function getCommandVersion(cmd, args = ["--version"]) {
|
|
|
232
232
|
}
|
|
233
233
|
async function getCommandPath(cmd) {
|
|
234
234
|
try {
|
|
235
|
-
const result = await execa("
|
|
235
|
+
const result = await execa("which", [cmd], { timeout: 5e3 });
|
|
236
236
|
return result.stdout.trim();
|
|
237
237
|
} catch {
|
|
238
238
|
return void 0;
|
|
@@ -475,10 +475,60 @@ var zh_CN = {
|
|
|
475
475
|
status_title: "\u5DF2\u5B89\u88C5\u63D2\u4EF6",
|
|
476
476
|
status_none: "\u6682\u65E0\u5DF2\u5B89\u88C5\u7684\u63D2\u4EF6",
|
|
477
477
|
status_hint: "\u8FD0\u884C install-helper init \u5F00\u59CB\u5B89\u88C5",
|
|
478
|
-
status_install_time: "\u5B89\u88C5\u65F6\u95F4"
|
|
478
|
+
status_install_time: "\u5B89\u88C5\u65F6\u95F4",
|
|
479
|
+
install_installed_to: "\u5B89\u88C5\u5230",
|
|
480
|
+
install_skills_count: "Skills",
|
|
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",
|
|
512
|
+
loading_skills_list: "\u6B63\u5728\u52A0\u8F7D Skills \u5217\u8868...",
|
|
513
|
+
loading_skills_list_complete: "Skills \u5217\u8868\u52A0\u8F7D\u5B8C\u6210",
|
|
514
|
+
loading_plugin_data: "\u6B63\u5728\u52A0\u8F7D\u63D2\u4EF6\u6570\u636E...",
|
|
515
|
+
loading_plugin_data_complete: "\u63D2\u4EF6\u6570\u636E\u52A0\u8F7D\u5B8C\u6210",
|
|
516
|
+
loading_skills_list_failed: "Skills \u5217\u8868\u52A0\u8F7D\u5931\u8D25\uFF0C\u5C06\u4F7F\u7528\u5185\u7F6E\u6570\u636E",
|
|
517
|
+
install_no_skill_selected: "\u672A\u9009\u62E9\u4EFB\u4F55 Skill",
|
|
518
|
+
install_to: "\u5B89\u88C5\u5230",
|
|
519
|
+
start_to_use: "\u542F\u52A8 {tool} \u5373\u53EF\u4F7F\u7528",
|
|
520
|
+
wizard_step_1_title: "[1/4] \u9009\u62E9 AI \u7F16\u7A0B\u5DE5\u5177",
|
|
521
|
+
wizard_step_2_title: "[2/4] \u9009\u62E9\u5B89\u88C5\u4F4D\u7F6E",
|
|
522
|
+
wizard_step_3_title: "[3/4] \u9009\u62E9\u8981\u5B89\u88C5\u7684\u63D2\u4EF6",
|
|
523
|
+
wizard_step_4_title: "[4/4] \u786E\u8BA4\u5B89\u88C5",
|
|
524
|
+
wizard_step_3_skill_title: "[3/4] \u9009\u62E9 Skill \u7C7B\u522B",
|
|
525
|
+
wizard_step_4_skill_title: "[4/4] \u9009\u62E9\u8981\u5B89\u88C5\u7684 Skills \u2014 {category}",
|
|
526
|
+
install_level_project: "\u5B89\u88C5\u5230\u5F53\u524D\u76EE\u5F55\uFF08\u63A8\u8350\uFF0C\u4EC5\u5F53\u524D\u9879\u76EE\u53EF\u7528\uFF09",
|
|
527
|
+
install_level_global: "\u5B89\u88C5\u5230\u5168\u5C40\uFF08\u6240\u6709\u9879\u76EE\u5171\u4EAB\uFF09",
|
|
528
|
+
wizard_select_mode_title: "\u9009\u62E9\u5B89\u88C5\u7C7B\u578B"
|
|
479
529
|
};
|
|
480
530
|
var en_US = {
|
|
481
|
-
wizard_title: "CANNBot
|
|
531
|
+
wizard_title: "CANNBot Install Helper",
|
|
482
532
|
wizard_detect: "Detecting installed AI coding tools...",
|
|
483
533
|
wizard_select_tool: "Select AI coding tool",
|
|
484
534
|
wizard_select_level: "Select install level",
|
|
@@ -560,7 +610,57 @@ var en_US = {
|
|
|
560
610
|
status_title: "Installed Plugins",
|
|
561
611
|
status_none: "No installed plugins",
|
|
562
612
|
status_hint: "Run install-helper init to start",
|
|
563
|
-
status_install_time: "Installed at"
|
|
613
|
+
status_install_time: "Installed at",
|
|
614
|
+
install_installed_to: "Installed to",
|
|
615
|
+
install_skills_count: "Skills",
|
|
616
|
+
install_agents_count: "Agents",
|
|
617
|
+
lang_supported: "Supported languages: zh_CN, en_US",
|
|
618
|
+
lang_usage: "Usage: install-helper lang set <language>",
|
|
619
|
+
lang_specify: "Please specify language: install-helper lang set zh_CN",
|
|
620
|
+
lang_unknown_action: "Unknown action",
|
|
621
|
+
lang_supported_actions: "Supported actions: show, set",
|
|
622
|
+
info_aliases: "Aliases",
|
|
623
|
+
uninstall_not_found: "Not found",
|
|
624
|
+
uninstall_no_record: "No install record found, may not be installed or record is corrupted",
|
|
625
|
+
uninstall_no_record_hint: "For manual cleanup, delete related files in .opencode/ or .claude/ directory",
|
|
626
|
+
uninstall_in_progress: "Uninstalling",
|
|
627
|
+
uninstall_removed: "Uninstalled",
|
|
628
|
+
uninstall_files_gone: " files no longer exist, install record cleaned",
|
|
629
|
+
uninstall_skills_in_progress: "Uninstalling",
|
|
630
|
+
init_pkg_dir_warn: "Current directory appears to be the install-helper package directory",
|
|
631
|
+
init_pkg_dir_hint: "Please run this command in your project directory, not in the install-helper package directory",
|
|
632
|
+
init_pkg_dir_example: "Example: cd ~/my-project && install-helper",
|
|
633
|
+
init_cancelled: "Installation cancelled",
|
|
634
|
+
backup_detected: "Plugin already installed in current directory",
|
|
635
|
+
backup_current: "Currently installed",
|
|
636
|
+
backup_installing: "About to install",
|
|
637
|
+
backup_overwrite_warning: "Continuing will overwrite existing AGENTS.md configuration.",
|
|
638
|
+
backup_auto_create: "System will automatically create backup for future restoration.",
|
|
639
|
+
backup_overwrite: "Overwrite (auto backup)",
|
|
640
|
+
backup_cancel: "Cancel installation",
|
|
641
|
+
backup_restore_prompt: "Backup configuration detected, restore?",
|
|
642
|
+
backup_restore: "Restore",
|
|
643
|
+
backup_only_uninstall: "Uninstall only (no restore)",
|
|
644
|
+
backup_select_action: "Please select an action",
|
|
645
|
+
backup_restore_success: "Configuration restored",
|
|
646
|
+
backup_created: "Backup created",
|
|
647
|
+
loading_skills_list: "Loading Skills list...",
|
|
648
|
+
loading_skills_list_complete: "Skills list loaded",
|
|
649
|
+
loading_plugin_data: "Loading plugin data...",
|
|
650
|
+
loading_plugin_data_complete: "Plugin data loaded",
|
|
651
|
+
loading_skills_list_failed: "Failed to load Skills list, using built-in data",
|
|
652
|
+
install_no_skill_selected: "No Skill selected",
|
|
653
|
+
install_to: "Install to",
|
|
654
|
+
start_to_use: "Start {tool} to use",
|
|
655
|
+
wizard_step_1_title: "[1/4] Select AI coding tool",
|
|
656
|
+
wizard_step_2_title: "[2/4] Select installation location",
|
|
657
|
+
wizard_step_3_title: "[3/4] Select plugins to install",
|
|
658
|
+
wizard_step_4_title: "[4/4] Confirm installation",
|
|
659
|
+
wizard_step_3_skill_title: "[3/4] Select Skill category",
|
|
660
|
+
wizard_step_4_skill_title: "[4/4] Select Skills to install \u2014 {category}",
|
|
661
|
+
install_level_project: "Install to current directory (recommended, current project only)",
|
|
662
|
+
install_level_global: "Install globally (all projects)",
|
|
663
|
+
wizard_select_mode_title: "Select installation type"
|
|
564
664
|
};
|
|
565
665
|
var currentLang = "zh_CN";
|
|
566
666
|
function setLanguage(lang) {
|
|
@@ -624,7 +724,7 @@ function printBoxTitle(title, width = 65) {
|
|
|
624
724
|
}
|
|
625
725
|
function showOperationHints(isCheckbox = false) {
|
|
626
726
|
if (isCheckbox) {
|
|
627
|
-
console.log(` \u{1F4A1} \x1B[36m\u2191\u2193\x1B[0m \u79FB\u52A8 | \x1B[36m\u7A7A\u683C\x1B[0m \u9009
|
|
727
|
+
console.log(` \u{1F4A1} \x1B[36m\u2191\u2193\x1B[0m \u79FB\u52A8 | \x1B[36m\u7A7A\u683C\x1B[0m \u52FE\u9009 | \x1B[36m\u23CE\x1B[0m \u786E\u8BA4\uFF08\u4E0D\u9009\u6309\u56DE\u8F66\u53EF\u8FD4\u56DE\uFF09
|
|
628
728
|
`);
|
|
629
729
|
} else {
|
|
630
730
|
console.log(` \u{1F4A1} \x1B[36m\u2191\u2193\x1B[0m \u79FB\u52A8 | \x1B[36m\u23CE\x1B[0m \u786E\u8BA4
|
|
@@ -793,7 +893,7 @@ async function runWizard() {
|
|
|
793
893
|
}
|
|
794
894
|
}
|
|
795
895
|
async function stepTool(detectedTools, lastTool) {
|
|
796
|
-
printBoxTitle("
|
|
896
|
+
printBoxTitle(t("wizard_step_1_title"));
|
|
797
897
|
if (detectedTools.length === 0) {
|
|
798
898
|
logger.error(t("error_tool_not_found"));
|
|
799
899
|
const choices2 = [
|
|
@@ -868,10 +968,10 @@ async function stepToolManual(lastTool) {
|
|
|
868
968
|
return result;
|
|
869
969
|
}
|
|
870
970
|
async function stepLevel(lastLevel) {
|
|
871
|
-
printBoxTitle("
|
|
971
|
+
printBoxTitle(t("wizard_step_2_title"));
|
|
872
972
|
const choices = [
|
|
873
|
-
{ name:
|
|
874
|
-
{ name:
|
|
973
|
+
{ name: `> project \u2014 ${t("install_level_project")}`, value: "project" },
|
|
974
|
+
{ name: `> global \u2014 ${t("install_level_global")}`, value: "global" },
|
|
875
975
|
new Separator("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
|
|
876
976
|
{ name: "<- " + t("wizard_back"), value: BACK },
|
|
877
977
|
{ name: "x " + t("wizard_cancel"), value: CANCEL }
|
|
@@ -889,7 +989,7 @@ async function stepLevel(lastLevel) {
|
|
|
889
989
|
return result;
|
|
890
990
|
}
|
|
891
991
|
async function stepPlugins(tool, level) {
|
|
892
|
-
printBoxTitle("
|
|
992
|
+
printBoxTitle(t("wizard_step_3_title"));
|
|
893
993
|
const plugins = getAllPlugins();
|
|
894
994
|
const configRoot = getConfigRoot(tool, level);
|
|
895
995
|
const manifests = readAllManifests(configRoot);
|
|
@@ -903,20 +1003,16 @@ async function stepPlugins(tool, level) {
|
|
|
903
1003
|
checked: false
|
|
904
1004
|
};
|
|
905
1005
|
});
|
|
906
|
-
choices.push(new Separator("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
907
|
-
choices.push({ name: "<- " + t("wizard_back"), value: BACK, checked: false });
|
|
908
|
-
choices.push({ name: "x " + t("wizard_cancel"), value: CANCEL, checked: false });
|
|
909
1006
|
showOperationHints(true);
|
|
910
1007
|
const selected = await checkbox({
|
|
911
1008
|
message: t("wizard_select_plugins"),
|
|
912
1009
|
choices,
|
|
913
1010
|
loop: false,
|
|
914
1011
|
instructions: false,
|
|
915
|
-
theme: checkboxTheme
|
|
1012
|
+
theme: checkboxTheme,
|
|
1013
|
+
pageSize: 15
|
|
916
1014
|
});
|
|
917
|
-
|
|
918
|
-
if (selected.includes(CANCEL)) return CANCEL;
|
|
919
|
-
const pluginIds = selected.filter((v) => v !== BACK && v !== CANCEL);
|
|
1015
|
+
const pluginIds = selected;
|
|
920
1016
|
if (pluginIds.length === 0) {
|
|
921
1017
|
const action = await select({
|
|
922
1018
|
message: t("wizard_no_selection"),
|
|
@@ -934,14 +1030,17 @@ async function stepPlugins(tool, level) {
|
|
|
934
1030
|
return pluginIds;
|
|
935
1031
|
}
|
|
936
1032
|
async function stepConfirm(tool, level, plugins) {
|
|
937
|
-
printBoxTitle("
|
|
1033
|
+
printBoxTitle(t("wizard_step_4_title"));
|
|
938
1034
|
const allPlugins = getAllPlugins();
|
|
939
1035
|
const selectedPlugins = plugins.map((id) => allPlugins.find((p) => p.id === id));
|
|
940
1036
|
const displayPath = getConfigRoot(tool, level);
|
|
941
|
-
|
|
1037
|
+
const toolName = getToolDisplayName(tool);
|
|
1038
|
+
const levelText = level === "project" ? "project" : "global";
|
|
1039
|
+
logger.info(`\u5373\u5C06\u5B89\u88C5 ${chalk2.bold(plugins.length)} \u4E2A\u63D2\u4EF6\u5230 ${chalk2.green(toolName)}\uFF08${chalk2.cyan(levelText)} \u7EA7\u522B\uFF09\uFF1A`);
|
|
1040
|
+
logger.info(`\u5B89\u88C5\u8DEF\u5F84: ${chalk2.cyan(displayPath)}`);
|
|
942
1041
|
for (const plugin of selectedPlugins) {
|
|
943
1042
|
if (plugin) {
|
|
944
|
-
logger.step(` \u2022 ${chalk2.bold(plugin.displayName)}
|
|
1043
|
+
logger.step(` \u2022 ${chalk2.bold(plugin.displayName)}`);
|
|
945
1044
|
}
|
|
946
1045
|
}
|
|
947
1046
|
logger.blank();
|
|
@@ -965,7 +1064,7 @@ import { execa as execa2 } from "execa";
|
|
|
965
1064
|
|
|
966
1065
|
// src/core/scanner.ts
|
|
967
1066
|
import { existsSync as existsSync5, readdirSync, readFileSync as readFileSync3, statSync, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
968
|
-
import { join as join5
|
|
1067
|
+
import { join as join5 } from "path";
|
|
969
1068
|
import { parse as parseYaml } from "yaml";
|
|
970
1069
|
var EXCLUDE_DIRS = /* @__PURE__ */ new Set([
|
|
971
1070
|
"node_modules",
|
|
@@ -1103,8 +1202,7 @@ function writeScanCache(cache) {
|
|
|
1103
1202
|
}
|
|
1104
1203
|
}
|
|
1105
1204
|
function getCachePath() {
|
|
1106
|
-
|
|
1107
|
-
return join5(homeDir, ".cannbot", "scan-cache.json");
|
|
1205
|
+
return join5(getCannbotConfigDir(), "scan-cache.json");
|
|
1108
1206
|
}
|
|
1109
1207
|
function scanDirectory(dirPath, repoPath, sourcePrefix, skills, seen) {
|
|
1110
1208
|
const selfSkillMd = join5(dirPath, "SKILL.md");
|
|
@@ -1478,8 +1576,8 @@ function createRepositoryManager(customPath) {
|
|
|
1478
1576
|
}
|
|
1479
1577
|
|
|
1480
1578
|
// src/core/installer.ts
|
|
1481
|
-
import { existsSync as
|
|
1482
|
-
import { join as
|
|
1579
|
+
import { existsSync as existsSync9 } from "fs";
|
|
1580
|
+
import { join as join9 } from "path";
|
|
1483
1581
|
import { execa as execa3 } from "execa";
|
|
1484
1582
|
|
|
1485
1583
|
// src/core/record.ts
|
|
@@ -1573,7 +1671,6 @@ function scanInstalledFiles(pluginId, displayName, tool, level, installPath, con
|
|
|
1573
1671
|
files.push(repoLinkInConfig);
|
|
1574
1672
|
}
|
|
1575
1673
|
}
|
|
1576
|
-
directories.push(configRoot);
|
|
1577
1674
|
return {
|
|
1578
1675
|
pluginId,
|
|
1579
1676
|
displayName,
|
|
@@ -1653,6 +1750,179 @@ function getInstalledSkills(tool, level, installPath) {
|
|
|
1653
1750
|
return record[tool]?.[level]?.[installPath]?.skills || [];
|
|
1654
1751
|
}
|
|
1655
1752
|
|
|
1753
|
+
// src/core/backup.ts
|
|
1754
|
+
import { existsSync as existsSync8, copyFileSync, readdirSync as readdirSync2, unlinkSync as unlinkSync2 } from "fs";
|
|
1755
|
+
import { join as join8 } from "path";
|
|
1756
|
+
function getAgentsFileName(tool) {
|
|
1757
|
+
return tool === "claude" ? "CLAUDE.md" : "AGENTS.md";
|
|
1758
|
+
}
|
|
1759
|
+
function detectCurrentPlugin(configRoot, tool) {
|
|
1760
|
+
const manifest = readManifest(configRoot);
|
|
1761
|
+
if (manifest?.team) {
|
|
1762
|
+
const plugin = findPlugin(manifest.team);
|
|
1763
|
+
if (plugin) {
|
|
1764
|
+
return {
|
|
1765
|
+
pluginId: plugin.id,
|
|
1766
|
+
pluginName: plugin.displayName
|
|
1767
|
+
};
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
const agentsFile = join8(configRoot, getAgentsFileName(tool));
|
|
1771
|
+
if (!existsSync8(agentsFile)) {
|
|
1772
|
+
return null;
|
|
1773
|
+
}
|
|
1774
|
+
const allRecords = readAllRecords();
|
|
1775
|
+
for (const record of allRecords) {
|
|
1776
|
+
if (record.configRoot === configRoot && record.tool === tool) {
|
|
1777
|
+
const plugin = findPlugin(record.pluginId);
|
|
1778
|
+
if (plugin) {
|
|
1779
|
+
return {
|
|
1780
|
+
pluginId: plugin.id,
|
|
1781
|
+
pluginName: plugin.displayName
|
|
1782
|
+
};
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
return null;
|
|
1787
|
+
}
|
|
1788
|
+
function createBackup(configRoot, tool, fromPluginId, fromPluginName) {
|
|
1789
|
+
const agentsFile = join8(configRoot, getAgentsFileName(tool));
|
|
1790
|
+
if (!existsSync8(agentsFile)) {
|
|
1791
|
+
return null;
|
|
1792
|
+
}
|
|
1793
|
+
const timestamp = formatTimestamp(/* @__PURE__ */ new Date());
|
|
1794
|
+
const backupFileName = `${getAgentsFileName(tool)}.cannbot-backup.${fromPluginId}.${timestamp}`;
|
|
1795
|
+
const backupPath = join8(configRoot, backupFileName);
|
|
1796
|
+
try {
|
|
1797
|
+
copyFileSync(agentsFile, backupPath);
|
|
1798
|
+
return {
|
|
1799
|
+
filePath: backupPath,
|
|
1800
|
+
pluginId: fromPluginId,
|
|
1801
|
+
pluginName: fromPluginName,
|
|
1802
|
+
backupTime: timestamp
|
|
1803
|
+
};
|
|
1804
|
+
} catch {
|
|
1805
|
+
return null;
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1808
|
+
function findBackups(configRoot) {
|
|
1809
|
+
if (!existsSync8(configRoot)) {
|
|
1810
|
+
return [];
|
|
1811
|
+
}
|
|
1812
|
+
const files = readdirSync2(configRoot);
|
|
1813
|
+
const backups = [];
|
|
1814
|
+
for (const file of files) {
|
|
1815
|
+
if (file.includes(".cannbot-backup.")) {
|
|
1816
|
+
const parts = file.split(".cannbot-backup.");
|
|
1817
|
+
if (parts.length === 2) {
|
|
1818
|
+
const pluginIdAndTime = parts[1];
|
|
1819
|
+
const lastDotIndex = pluginIdAndTime.lastIndexOf(".");
|
|
1820
|
+
if (lastDotIndex > 0) {
|
|
1821
|
+
const pluginId = pluginIdAndTime.substring(0, lastDotIndex);
|
|
1822
|
+
const timestamp = pluginIdAndTime.substring(lastDotIndex + 1);
|
|
1823
|
+
const plugin = findPlugin(pluginId);
|
|
1824
|
+
backups.push({
|
|
1825
|
+
filePath: join8(configRoot, file),
|
|
1826
|
+
pluginId,
|
|
1827
|
+
pluginName: plugin?.displayName || pluginId,
|
|
1828
|
+
backupTime: timestamp
|
|
1829
|
+
});
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
return backups.sort((a, b) => b.backupTime.localeCompare(a.backupTime));
|
|
1835
|
+
}
|
|
1836
|
+
function restoreBackup(backupPath, configRoot, tool) {
|
|
1837
|
+
try {
|
|
1838
|
+
const agentsFile = join8(configRoot, getAgentsFileName(tool));
|
|
1839
|
+
copyFileSync(backupPath, agentsFile);
|
|
1840
|
+
return true;
|
|
1841
|
+
} catch {
|
|
1842
|
+
return false;
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
function deleteBackup(backupPath) {
|
|
1846
|
+
try {
|
|
1847
|
+
if (existsSync8(backupPath)) {
|
|
1848
|
+
unlinkSync2(backupPath);
|
|
1849
|
+
return true;
|
|
1850
|
+
}
|
|
1851
|
+
return false;
|
|
1852
|
+
} catch {
|
|
1853
|
+
return false;
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
function formatTimestamp(date) {
|
|
1857
|
+
const year = date.getFullYear();
|
|
1858
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
1859
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
1860
|
+
const hours = String(date.getHours()).padStart(2, "0");
|
|
1861
|
+
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
1862
|
+
const seconds = String(date.getSeconds()).padStart(2, "0");
|
|
1863
|
+
return `${year}${month}${day}-${hours}${minutes}${seconds}`;
|
|
1864
|
+
}
|
|
1865
|
+
function readAllRecords() {
|
|
1866
|
+
const records = [];
|
|
1867
|
+
const plugins = [
|
|
1868
|
+
"ops-direct-invoke",
|
|
1869
|
+
"ops-direct-invoke-flash",
|
|
1870
|
+
"ops-registry-invoke",
|
|
1871
|
+
"pypto-op-orchestrator",
|
|
1872
|
+
"triton-op-generator",
|
|
1873
|
+
"tilelang-op-orchestrator",
|
|
1874
|
+
"model-infer-optimize",
|
|
1875
|
+
"catlass-op-generator",
|
|
1876
|
+
"ops-code-reviewer",
|
|
1877
|
+
"torch-compile"
|
|
1878
|
+
];
|
|
1879
|
+
for (const pluginId of plugins) {
|
|
1880
|
+
const record = readRecord(pluginId);
|
|
1881
|
+
if (record) {
|
|
1882
|
+
records.push(record);
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
return records;
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1888
|
+
// src/ui/backup-prompts.ts
|
|
1889
|
+
import { select as select2 } from "@inquirer/prompts";
|
|
1890
|
+
import chalk3 from "chalk";
|
|
1891
|
+
async function showOverwriteWarning(currentPluginName, newPluginName) {
|
|
1892
|
+
console.log();
|
|
1893
|
+
console.log(chalk3.yellow(` \u26A0\uFE0F ${t("backup_detected")}`));
|
|
1894
|
+
console.log();
|
|
1895
|
+
console.log(` ${t("backup_current")}: ${chalk3.cyan(currentPluginName)}`);
|
|
1896
|
+
console.log(` ${t("backup_installing")}: ${chalk3.cyan(newPluginName)}`);
|
|
1897
|
+
console.log();
|
|
1898
|
+
console.log(` ${t("backup_overwrite_warning")}`);
|
|
1899
|
+
console.log(` ${t("backup_auto_create")}`);
|
|
1900
|
+
console.log();
|
|
1901
|
+
const choice = await select2({
|
|
1902
|
+
message: t("backup_select_action"),
|
|
1903
|
+
choices: [
|
|
1904
|
+
{ name: t("backup_overwrite"), value: "overwrite" },
|
|
1905
|
+
{ name: t("backup_cancel"), value: "cancel" }
|
|
1906
|
+
]
|
|
1907
|
+
});
|
|
1908
|
+
return choice;
|
|
1909
|
+
}
|
|
1910
|
+
async function showRestorePrompt(backups) {
|
|
1911
|
+
console.log();
|
|
1912
|
+
console.log(chalk3.cyan(` ${t("backup_restore_prompt")}`));
|
|
1913
|
+
console.log();
|
|
1914
|
+
const choices = backups.map((b) => ({
|
|
1915
|
+
name: `${t("backup_restore")} ${b.pluginName} (${b.backupTime})`,
|
|
1916
|
+
value: b.filePath
|
|
1917
|
+
}));
|
|
1918
|
+
choices.push({ name: t("backup_only_uninstall"), value: "none" });
|
|
1919
|
+
const choice = await select2({
|
|
1920
|
+
message: t("backup_select_action"),
|
|
1921
|
+
choices
|
|
1922
|
+
});
|
|
1923
|
+
return choice;
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1656
1926
|
// src/core/installer.ts
|
|
1657
1927
|
async function installPlugin(opts) {
|
|
1658
1928
|
const plugin = getPluginById(opts.pluginId);
|
|
@@ -1666,8 +1936,8 @@ async function installPlugin(opts) {
|
|
|
1666
1936
|
warnings: []
|
|
1667
1937
|
};
|
|
1668
1938
|
}
|
|
1669
|
-
const scriptPath =
|
|
1670
|
-
if (!
|
|
1939
|
+
const scriptPath = join9(opts.repoPath, plugin.dir, plugin.script);
|
|
1940
|
+
if (!existsSync9(scriptPath)) {
|
|
1671
1941
|
return {
|
|
1672
1942
|
success: false,
|
|
1673
1943
|
pluginId: opts.pluginId,
|
|
@@ -1682,13 +1952,49 @@ async function installPlugin(opts) {
|
|
|
1682
1952
|
args.push(opts.installPath);
|
|
1683
1953
|
}
|
|
1684
1954
|
const cwd = opts.installPath || process.cwd();
|
|
1955
|
+
const configRoot = getConfigRoot(opts.tool, opts.level, opts.installPath);
|
|
1956
|
+
const agentsFile = join9(configRoot, getAgentsFileName(opts.tool));
|
|
1957
|
+
let backupInfo = null;
|
|
1958
|
+
if (existsSync9(agentsFile)) {
|
|
1959
|
+
const currentPlugin = detectCurrentPlugin(configRoot, opts.tool);
|
|
1960
|
+
if (currentPlugin && currentPlugin.pluginId !== opts.pluginId) {
|
|
1961
|
+
let choice = "overwrite";
|
|
1962
|
+
if (!opts.yes) {
|
|
1963
|
+
choice = await showOverwriteWarning(
|
|
1964
|
+
currentPlugin.pluginName,
|
|
1965
|
+
plugin.displayName
|
|
1966
|
+
);
|
|
1967
|
+
}
|
|
1968
|
+
if (choice === "cancel") {
|
|
1969
|
+
logger.info(t("backup_cancel"));
|
|
1970
|
+
return {
|
|
1971
|
+
success: false,
|
|
1972
|
+
pluginId: opts.pluginId,
|
|
1973
|
+
skillsCount: 0,
|
|
1974
|
+
agentsCount: 0,
|
|
1975
|
+
errors: [t("backup_cancel")],
|
|
1976
|
+
warnings: []
|
|
1977
|
+
};
|
|
1978
|
+
}
|
|
1979
|
+
backupInfo = createBackup(
|
|
1980
|
+
configRoot,
|
|
1981
|
+
opts.tool,
|
|
1982
|
+
currentPlugin.pluginId,
|
|
1983
|
+
currentPlugin.pluginName
|
|
1984
|
+
);
|
|
1985
|
+
if (backupInfo) {
|
|
1986
|
+
logger.success(`${t("backup_created")}: ${backupInfo.filePath}`);
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
}
|
|
1685
1990
|
try {
|
|
1686
|
-
|
|
1991
|
+
const execOptions = {
|
|
1687
1992
|
cwd,
|
|
1688
1993
|
timeout: 3e5,
|
|
1689
|
-
stdio: "pipe"
|
|
1690
|
-
|
|
1691
|
-
|
|
1994
|
+
stdio: "pipe",
|
|
1995
|
+
input: opts.yes ? "y\n" : void 0
|
|
1996
|
+
};
|
|
1997
|
+
await execa3("bash", [scriptPath, ...args], execOptions);
|
|
1692
1998
|
const manifest = readManifest(configRoot);
|
|
1693
1999
|
let skillsCount = 0;
|
|
1694
2000
|
let agentsCount = 0;
|
|
@@ -1709,6 +2015,14 @@ async function installPlugin(opts) {
|
|
|
1709
2015
|
configRoot,
|
|
1710
2016
|
manifest
|
|
1711
2017
|
);
|
|
2018
|
+
if (backupInfo) {
|
|
2019
|
+
record.backup = {
|
|
2020
|
+
filePath: backupInfo.filePath,
|
|
2021
|
+
fromPluginId: backupInfo.pluginId,
|
|
2022
|
+
fromPluginName: backupInfo.pluginName,
|
|
2023
|
+
backupTime: backupInfo.backupTime
|
|
2024
|
+
};
|
|
2025
|
+
}
|
|
1712
2026
|
writeRecord(record);
|
|
1713
2027
|
} catch {
|
|
1714
2028
|
}
|
|
@@ -1734,16 +2048,16 @@ async function installPlugin(opts) {
|
|
|
1734
2048
|
}
|
|
1735
2049
|
|
|
1736
2050
|
// src/core/skill-installer.ts
|
|
1737
|
-
import { existsSync as
|
|
1738
|
-
import { join as
|
|
1739
|
-
import { select as
|
|
1740
|
-
import
|
|
2051
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync5, symlinkSync, unlinkSync as unlinkSync3, readdirSync as readdirSync3, rmdirSync, realpathSync, lstatSync as lstatSync2 } from "fs";
|
|
2052
|
+
import { join as join10 } from "path";
|
|
2053
|
+
import { select as select3, checkbox as checkbox2, Separator as Separator2 } from "@inquirer/prompts";
|
|
2054
|
+
import chalk4 from "chalk";
|
|
1741
2055
|
import Table from "cli-table3";
|
|
1742
2056
|
async function installSkills(skillIds, tool, level, repoPath) {
|
|
1743
2057
|
const configRoot = getConfigRoot(tool, level);
|
|
1744
|
-
const skillsDir =
|
|
2058
|
+
const skillsDir = join10(configRoot, "skills");
|
|
1745
2059
|
const installPath = level === "project" ? process.cwd() : configRoot;
|
|
1746
|
-
if (!
|
|
2060
|
+
if (!existsSync10(skillsDir)) {
|
|
1747
2061
|
mkdirSync5(skillsDir, { recursive: true });
|
|
1748
2062
|
}
|
|
1749
2063
|
const results = [];
|
|
@@ -1754,15 +2068,15 @@ async function installSkills(skillIds, tool, level, repoPath) {
|
|
|
1754
2068
|
results.push({ skillId, success: false, error: "Skill not found in registry" });
|
|
1755
2069
|
continue;
|
|
1756
2070
|
}
|
|
1757
|
-
const sourcePath =
|
|
1758
|
-
const targetPath =
|
|
1759
|
-
if (!
|
|
2071
|
+
const sourcePath = join10(repoPath, skill.source, skill.id);
|
|
2072
|
+
const targetPath = join10(skillsDir, skillId);
|
|
2073
|
+
if (!existsSync10(sourcePath)) {
|
|
1760
2074
|
results.push({ skillId, success: false, error: `Source not found: ${sourcePath}` });
|
|
1761
2075
|
continue;
|
|
1762
2076
|
}
|
|
1763
2077
|
try {
|
|
1764
|
-
if (
|
|
1765
|
-
|
|
2078
|
+
if (existsSync10(targetPath) || isSymlink2(targetPath)) {
|
|
2079
|
+
unlinkSync3(targetPath);
|
|
1766
2080
|
}
|
|
1767
2081
|
symlinkSync(realpathSync(sourcePath), targetPath);
|
|
1768
2082
|
results.push({ skillId, success: true });
|
|
@@ -1778,15 +2092,15 @@ async function installSkills(skillIds, tool, level, repoPath) {
|
|
|
1778
2092
|
}
|
|
1779
2093
|
async function uninstallSkills(skillIds, tool, level) {
|
|
1780
2094
|
const configRoot = getConfigRoot(tool, level);
|
|
1781
|
-
const skillsDir =
|
|
2095
|
+
const skillsDir = join10(configRoot, "skills");
|
|
1782
2096
|
const installPath = level === "project" ? process.cwd() : configRoot;
|
|
1783
2097
|
const results = [];
|
|
1784
2098
|
const removedIds = [];
|
|
1785
2099
|
for (const skillId of skillIds) {
|
|
1786
|
-
const targetPath =
|
|
2100
|
+
const targetPath = join10(skillsDir, skillId);
|
|
1787
2101
|
try {
|
|
1788
|
-
if (
|
|
1789
|
-
|
|
2102
|
+
if (existsSync10(targetPath) || isSymlink2(targetPath)) {
|
|
2103
|
+
unlinkSync3(targetPath);
|
|
1790
2104
|
results.push({ skillId, success: true });
|
|
1791
2105
|
removedIds.push(skillId);
|
|
1792
2106
|
logger.step(` \u79FB\u9664: ${skillId}`);
|
|
@@ -1801,7 +2115,7 @@ async function uninstallSkills(skillIds, tool, level) {
|
|
|
1801
2115
|
if (removedIds.length > 0) {
|
|
1802
2116
|
removeSkillsFromRecord(removedIds, tool, level, installPath);
|
|
1803
2117
|
}
|
|
1804
|
-
if (
|
|
2118
|
+
if (existsSync10(skillsDir)) {
|
|
1805
2119
|
try {
|
|
1806
2120
|
const entries = readdirSync3(skillsDir);
|
|
1807
2121
|
if (entries.length === 0) {
|
|
@@ -1811,16 +2125,6 @@ async function uninstallSkills(skillIds, tool, level) {
|
|
|
1811
2125
|
} catch {
|
|
1812
2126
|
}
|
|
1813
2127
|
}
|
|
1814
|
-
if (existsSync9(configRoot)) {
|
|
1815
|
-
try {
|
|
1816
|
-
const entries = readdirSync3(configRoot);
|
|
1817
|
-
if (entries.length === 0) {
|
|
1818
|
-
rmdirSync(configRoot);
|
|
1819
|
-
logger.step(` \u6E05\u7406\u7A7A\u76EE\u5F55: ${configRoot.split("/").pop()}/`);
|
|
1820
|
-
}
|
|
1821
|
-
} catch {
|
|
1822
|
-
}
|
|
1823
|
-
}
|
|
1824
2128
|
return results;
|
|
1825
2129
|
}
|
|
1826
2130
|
async function interactiveSkillSelect() {
|
|
@@ -1832,7 +2136,7 @@ async function interactiveSkillSelect() {
|
|
|
1832
2136
|
while (true) {
|
|
1833
2137
|
switch (step) {
|
|
1834
2138
|
case 0: {
|
|
1835
|
-
printBoxTitle("
|
|
2139
|
+
printBoxTitle(t("wizard_step_3_skill_title"));
|
|
1836
2140
|
const categoryChoices = [
|
|
1837
2141
|
...categories.map((cat) => ({
|
|
1838
2142
|
name: `> ${cat.name} (${cat.skills.length} skills)`,
|
|
@@ -1843,11 +2147,12 @@ async function interactiveSkillSelect() {
|
|
|
1843
2147
|
{ name: "x " + t("wizard_cancel"), value: CANCEL3 }
|
|
1844
2148
|
];
|
|
1845
2149
|
showOperationHints();
|
|
1846
|
-
selectedCategoryId = await
|
|
2150
|
+
selectedCategoryId = await select3({
|
|
1847
2151
|
message: t("skill_select_category"),
|
|
1848
2152
|
choices: categoryChoices,
|
|
1849
2153
|
loop: false,
|
|
1850
|
-
theme: selectTheme
|
|
2154
|
+
theme: selectTheme,
|
|
2155
|
+
pageSize: 15
|
|
1851
2156
|
});
|
|
1852
2157
|
if (selectedCategoryId === BACK3) return "back";
|
|
1853
2158
|
if (selectedCategoryId === CANCEL3) return "cancel";
|
|
@@ -1857,7 +2162,7 @@ async function interactiveSkillSelect() {
|
|
|
1857
2162
|
case 1: {
|
|
1858
2163
|
const category = categories.find((c) => c.id === selectedCategoryId);
|
|
1859
2164
|
if (!category) return [];
|
|
1860
|
-
printBoxTitle(
|
|
2165
|
+
printBoxTitle(t("wizard_step_4_skill_title").replace("{category}", category.name));
|
|
1861
2166
|
const tools = ["opencode", "claude", "trae", "cursor", "copilot"];
|
|
1862
2167
|
const levels = ["project", "global"];
|
|
1863
2168
|
const installedSkills = [];
|
|
@@ -1877,25 +2182,18 @@ async function interactiveSkillSelect() {
|
|
|
1877
2182
|
checked: false
|
|
1878
2183
|
};
|
|
1879
2184
|
});
|
|
1880
|
-
skillChoices.push(new Separator2("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
1881
|
-
skillChoices.push({ name: "<- " + t("wizard_back"), value: BACK3, checked: false });
|
|
1882
|
-
skillChoices.push({ name: "x " + t("wizard_cancel"), value: CANCEL3, checked: false });
|
|
1883
2185
|
showOperationHints(true);
|
|
1884
2186
|
const selectedSkills = await checkbox2({
|
|
1885
2187
|
message: t("skill_select_items"),
|
|
1886
2188
|
choices: skillChoices,
|
|
1887
2189
|
loop: false,
|
|
1888
2190
|
instructions: false,
|
|
1889
|
-
theme: checkboxTheme
|
|
2191
|
+
theme: checkboxTheme,
|
|
2192
|
+
pageSize: 15
|
|
1890
2193
|
});
|
|
1891
|
-
|
|
1892
|
-
step = 0;
|
|
1893
|
-
break;
|
|
1894
|
-
}
|
|
1895
|
-
if (selectedSkills.includes(CANCEL3)) return "cancel";
|
|
1896
|
-
const skillIds = selectedSkills.filter((v) => v !== BACK3 && v !== CANCEL3);
|
|
2194
|
+
const skillIds = selectedSkills;
|
|
1897
2195
|
if (skillIds.length === 0) {
|
|
1898
|
-
const action = await
|
|
2196
|
+
const action = await select3({
|
|
1899
2197
|
message: t("wizard_no_selection"),
|
|
1900
2198
|
choices: [
|
|
1901
2199
|
new Separator2("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
|
|
@@ -1919,11 +2217,11 @@ async function interactiveSkillSelect() {
|
|
|
1919
2217
|
function listAllSkills() {
|
|
1920
2218
|
const categories = getAllCategories();
|
|
1921
2219
|
console.log();
|
|
1922
|
-
console.log(
|
|
1923
|
-
console.log(
|
|
2220
|
+
console.log(chalk4.bold(` ${t("skill_list_title")}`));
|
|
2221
|
+
console.log(chalk4.dim(" " + "\u2500".repeat(60)));
|
|
1924
2222
|
for (const category of categories) {
|
|
1925
2223
|
console.log();
|
|
1926
|
-
console.log(
|
|
2224
|
+
console.log(chalk4.bold(` ${category.name}`) + chalk4.dim(` (${category.skills.length} skills)`));
|
|
1927
2225
|
const table = new Table({
|
|
1928
2226
|
style: { head: [], border: [] },
|
|
1929
2227
|
colWidths: [35, 45],
|
|
@@ -1931,14 +2229,14 @@ function listAllSkills() {
|
|
|
1931
2229
|
});
|
|
1932
2230
|
for (const skill of category.skills) {
|
|
1933
2231
|
table.push([
|
|
1934
|
-
|
|
2232
|
+
chalk4.cyan(skill.id),
|
|
1935
2233
|
skill.description
|
|
1936
2234
|
]);
|
|
1937
2235
|
}
|
|
1938
2236
|
console.log(table.toString());
|
|
1939
2237
|
}
|
|
1940
2238
|
console.log();
|
|
1941
|
-
console.log(
|
|
2239
|
+
console.log(chalk4.dim(` \u5171 ${getAllSkills().length} \u4E2A Skills`));
|
|
1942
2240
|
console.log();
|
|
1943
2241
|
}
|
|
1944
2242
|
function isSymlink2(path) {
|
|
@@ -1950,22 +2248,22 @@ function isSymlink2(path) {
|
|
|
1950
2248
|
}
|
|
1951
2249
|
|
|
1952
2250
|
// src/ui/display.ts
|
|
1953
|
-
import
|
|
2251
|
+
import chalk5 from "chalk";
|
|
1954
2252
|
import Table2 from "cli-table3";
|
|
1955
2253
|
function printPluginList(plugins, installed) {
|
|
1956
2254
|
const table = new Table2({
|
|
1957
2255
|
head: [
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
2256
|
+
chalk5.cyan(t("list_id")),
|
|
2257
|
+
chalk5.cyan(t("list_name")),
|
|
2258
|
+
chalk5.cyan(t("list_status")),
|
|
2259
|
+
chalk5.cyan(t("list_skills")),
|
|
2260
|
+
chalk5.cyan(t("list_agents"))
|
|
1963
2261
|
],
|
|
1964
2262
|
style: { head: [], border: [] }
|
|
1965
2263
|
});
|
|
1966
2264
|
plugins.forEach((plugin, index) => {
|
|
1967
2265
|
const isInstalled = installed.has(plugin.id);
|
|
1968
|
-
const status = isInstalled ?
|
|
2266
|
+
const status = isInstalled ? chalk5.green(`\u2713 ${t("status_installed")}`) : chalk5.dim(`\u2014`);
|
|
1969
2267
|
table.push([
|
|
1970
2268
|
String(index + 1),
|
|
1971
2269
|
plugin.displayName,
|
|
@@ -1975,7 +2273,7 @@ function printPluginList(plugins, installed) {
|
|
|
1975
2273
|
]);
|
|
1976
2274
|
});
|
|
1977
2275
|
console.log();
|
|
1978
|
-
console.log(
|
|
2276
|
+
console.log(chalk5.bold(` ${t("list_title")} (${plugins.length} \u4E2A)`));
|
|
1979
2277
|
console.log(table.toString());
|
|
1980
2278
|
console.log();
|
|
1981
2279
|
}
|
|
@@ -1984,7 +2282,7 @@ function printInstallSummary(results) {
|
|
|
1984
2282
|
const totalCount = results.length;
|
|
1985
2283
|
console.log();
|
|
1986
2284
|
console.log(
|
|
1987
|
-
|
|
2285
|
+
chalk5.bold(
|
|
1988
2286
|
` ${t("install_done")}! ${successCount}/${totalCount} ${t("install_success")}`
|
|
1989
2287
|
)
|
|
1990
2288
|
);
|
|
@@ -1992,10 +2290,10 @@ function printInstallSummary(results) {
|
|
|
1992
2290
|
for (const result of results) {
|
|
1993
2291
|
if (result.success) {
|
|
1994
2292
|
console.log(
|
|
1995
|
-
|
|
2293
|
+
chalk5.green(" \u2713") + ` ${result.displayName} (${result.skillsCount} skills, ${result.agentsCount} agents)`
|
|
1996
2294
|
);
|
|
1997
2295
|
} else {
|
|
1998
|
-
console.log(
|
|
2296
|
+
console.log(chalk5.red(" \u2717") + ` ${result.displayName}`);
|
|
1999
2297
|
}
|
|
2000
2298
|
}
|
|
2001
2299
|
console.log();
|
|
@@ -2009,21 +2307,21 @@ function printEnhancedSummary(results, tool, configRoot) {
|
|
|
2009
2307
|
}
|
|
2010
2308
|
const toolName = getToolDisplayName(tool);
|
|
2011
2309
|
const lines = [
|
|
2012
|
-
|
|
2310
|
+
chalk5.bold(` ${t("install_done")}!`),
|
|
2013
2311
|
"",
|
|
2014
|
-
` ${
|
|
2015
|
-
` ${
|
|
2312
|
+
` ${chalk5.dim(t("install_installed_to") + ":")} ${configRoot}`,
|
|
2313
|
+
` ${chalk5.dim(t("install_skills_count") + ":")} ${totalSkills} \u4E2A ${chalk5.dim("|")} ${chalk5.dim(t("install_agents_count") + ":")} ${totalAgents} \u4E2A`,
|
|
2016
2314
|
"",
|
|
2017
|
-
|
|
2018
|
-
` ${
|
|
2019
|
-
` ${
|
|
2020
|
-
` ${
|
|
2021
|
-
` ${
|
|
2315
|
+
chalk5.bold(` ${t("install_enhanced_next_steps")}:`),
|
|
2316
|
+
` ${chalk5.cyan("1.")} ${t("install_enhanced_launch")}: ${chalk5.green(toolName.toLowerCase())}`,
|
|
2317
|
+
` ${chalk5.cyan("2.")} ${t("install_enhanced_try")}: ${chalk5.green("\u5E2E\u6211\u5F00\u53D1\u4E00\u4E2A Abs \u7B97\u5B50")}`,
|
|
2318
|
+
` ${chalk5.cyan("3.")} ${t("install_enhanced_more")}: ${chalk5.green("install-helper list")}`,
|
|
2319
|
+
` ${chalk5.cyan("4.")} ${t("install_enhanced_check")}: ${chalk5.green("install-helper doctor")}`,
|
|
2022
2320
|
""
|
|
2023
2321
|
];
|
|
2024
2322
|
if (successResults.length === 1) {
|
|
2025
2323
|
lines.push(
|
|
2026
|
-
` ${
|
|
2324
|
+
` ${chalk5.dim(t("install_enhanced_docs"))}: ${chalk5.dim(`plugins-official/${successResults[0].pluginId}/quickstart.md`)}`
|
|
2027
2325
|
);
|
|
2028
2326
|
}
|
|
2029
2327
|
console.log();
|
|
@@ -2034,34 +2332,34 @@ function printEnhancedSummary(results, tool, configRoot) {
|
|
|
2034
2332
|
}
|
|
2035
2333
|
|
|
2036
2334
|
// src/commands/init.ts
|
|
2037
|
-
import { existsSync as
|
|
2038
|
-
import { join as
|
|
2335
|
+
import { existsSync as existsSync11, readFileSync as readFileSync5 } from "fs";
|
|
2336
|
+
import { join as join11 } from "path";
|
|
2039
2337
|
var BACK2 = "__back__";
|
|
2040
2338
|
var CANCEL2 = "__cancel__";
|
|
2041
2339
|
async function initCommand() {
|
|
2042
2340
|
const cwd = process.cwd();
|
|
2043
|
-
if (
|
|
2341
|
+
if (existsSync11(join11(cwd, "package.json")) && (() => {
|
|
2044
2342
|
try {
|
|
2045
|
-
const pkg = JSON.parse(readFileSync5(
|
|
2343
|
+
const pkg = JSON.parse(readFileSync5(join11(cwd, "package.json"), "utf-8"));
|
|
2046
2344
|
return pkg.name === "@cannbot-ai/install-helper";
|
|
2047
2345
|
} catch {
|
|
2048
2346
|
return false;
|
|
2049
2347
|
}
|
|
2050
2348
|
})()) {
|
|
2051
|
-
logger.warn("
|
|
2052
|
-
logger.info("
|
|
2053
|
-
logger.info("
|
|
2349
|
+
logger.warn(t("init_pkg_dir_warn"));
|
|
2350
|
+
logger.info(t("init_pkg_dir_hint"));
|
|
2351
|
+
logger.info(t("init_pkg_dir_example"));
|
|
2054
2352
|
return;
|
|
2055
2353
|
}
|
|
2056
2354
|
printBanner(t("wizard_title"));
|
|
2057
|
-
const spinner = createSpinner("
|
|
2355
|
+
const spinner = createSpinner(t("loading_skills_list"));
|
|
2058
2356
|
spinner.start();
|
|
2059
2357
|
try {
|
|
2060
2358
|
const repoManager = createRepositoryManager();
|
|
2061
2359
|
await repoManager.ensureRepoAndScan();
|
|
2062
|
-
spinner.succeed("
|
|
2360
|
+
spinner.succeed(t("loading_skills_list_complete"));
|
|
2063
2361
|
} catch {
|
|
2064
|
-
spinner.warn("
|
|
2362
|
+
spinner.warn(t("loading_skills_list_failed"));
|
|
2065
2363
|
}
|
|
2066
2364
|
let step = 0;
|
|
2067
2365
|
let mode = "plugin";
|
|
@@ -2095,7 +2393,7 @@ async function initCommand() {
|
|
|
2095
2393
|
}
|
|
2096
2394
|
}
|
|
2097
2395
|
async function selectMode() {
|
|
2098
|
-
printBoxTitle("
|
|
2396
|
+
printBoxTitle(t("wizard_select_mode_title"));
|
|
2099
2397
|
const CANCEL3 = "__cancel__";
|
|
2100
2398
|
const choices = [
|
|
2101
2399
|
{
|
|
@@ -2110,7 +2408,7 @@ async function selectMode() {
|
|
|
2110
2408
|
{ name: "x " + t("wizard_cancel"), value: CANCEL3 }
|
|
2111
2409
|
];
|
|
2112
2410
|
showOperationHints();
|
|
2113
|
-
const result = await
|
|
2411
|
+
const result = await select4({
|
|
2114
2412
|
message: t("wizard_select_mode"),
|
|
2115
2413
|
choices,
|
|
2116
2414
|
loop: false,
|
|
@@ -2123,14 +2421,14 @@ async function pluginInstallFlow() {
|
|
|
2123
2421
|
const answers = await runWizard();
|
|
2124
2422
|
if (!answers.confirmed) {
|
|
2125
2423
|
if (answers.back) return "back";
|
|
2126
|
-
logger.info("
|
|
2424
|
+
logger.info(t("init_cancelled"));
|
|
2127
2425
|
return "done";
|
|
2128
2426
|
}
|
|
2129
2427
|
const repoManager = createRepositoryManager();
|
|
2130
|
-
const spinner = createSpinner(t("
|
|
2428
|
+
const spinner = createSpinner(t("loading_plugin_data"));
|
|
2131
2429
|
spinner.start();
|
|
2132
2430
|
const repoPath = await repoManager.ensureRepo();
|
|
2133
|
-
spinner.succeed(t("
|
|
2431
|
+
spinner.succeed(t("loading_plugin_data_complete"));
|
|
2134
2432
|
const allPlugins = getAllPlugins();
|
|
2135
2433
|
const selectedPlugins = answers.plugins.map(
|
|
2136
2434
|
(id) => allPlugins.find((p) => p.id === id)
|
|
@@ -2184,7 +2482,7 @@ async function skillInstallFlow() {
|
|
|
2184
2482
|
const result = await selectToolWithDetection();
|
|
2185
2483
|
if (result === "back") return "back";
|
|
2186
2484
|
if (result === "cancel") {
|
|
2187
|
-
logger.info("
|
|
2485
|
+
logger.info(t("init_cancelled"));
|
|
2188
2486
|
return "done";
|
|
2189
2487
|
}
|
|
2190
2488
|
tool = result;
|
|
@@ -2198,7 +2496,7 @@ async function skillInstallFlow() {
|
|
|
2198
2496
|
break;
|
|
2199
2497
|
}
|
|
2200
2498
|
if (result === CANCEL2) {
|
|
2201
|
-
logger.info("
|
|
2499
|
+
logger.info(t("init_cancelled"));
|
|
2202
2500
|
return "done";
|
|
2203
2501
|
}
|
|
2204
2502
|
level = result;
|
|
@@ -2212,37 +2510,40 @@ async function skillInstallFlow() {
|
|
|
2212
2510
|
break;
|
|
2213
2511
|
}
|
|
2214
2512
|
if (selectedSkills === "cancel") {
|
|
2215
|
-
logger.info("
|
|
2513
|
+
logger.info(t("init_cancelled"));
|
|
2216
2514
|
return "done";
|
|
2217
2515
|
}
|
|
2218
2516
|
if (selectedSkills.length === 0) {
|
|
2219
|
-
logger.info("
|
|
2517
|
+
logger.info(t("install_no_skill_selected"));
|
|
2220
2518
|
return "done";
|
|
2221
2519
|
}
|
|
2222
2520
|
const repoManager = createRepositoryManager();
|
|
2223
|
-
const spinner = createSpinner(t("
|
|
2521
|
+
const spinner = createSpinner(t("loading_plugin_data"));
|
|
2224
2522
|
spinner.start();
|
|
2225
2523
|
const repoPath = await repoManager.ensureRepo();
|
|
2226
|
-
spinner.succeed(t("
|
|
2227
|
-
logger.info(`${t("skill_install_progress")} ${
|
|
2524
|
+
spinner.succeed(t("loading_plugin_data_complete"));
|
|
2525
|
+
logger.info(`${t("skill_install_progress")} ${chalk6.bold(selectedSkills.length)} \u4E2A Skills...`);
|
|
2228
2526
|
const results = await installSkills(selectedSkills, tool, level, repoPath);
|
|
2229
2527
|
let successCount = 0;
|
|
2230
2528
|
let failCount = 0;
|
|
2231
|
-
|
|
2529
|
+
const total = results.length;
|
|
2530
|
+
for (let i = 0; i < results.length; i++) {
|
|
2531
|
+
const result = results[i];
|
|
2532
|
+
const progress = `[${i + 1}/${total}]`;
|
|
2232
2533
|
if (result.success) {
|
|
2233
|
-
logger.success(`${result.skillId}`);
|
|
2534
|
+
logger.success(`${progress} ${result.skillId}`);
|
|
2234
2535
|
successCount++;
|
|
2235
2536
|
} else {
|
|
2236
|
-
logger.error(`${result.skillId}: ${result.error}`);
|
|
2537
|
+
logger.error(`${progress} ${result.skillId}: ${result.error}`);
|
|
2237
2538
|
failCount++;
|
|
2238
2539
|
}
|
|
2239
2540
|
}
|
|
2240
2541
|
const configRoot = getConfigRoot(tool, level);
|
|
2241
2542
|
logger.blank();
|
|
2242
|
-
logger.success(`${t("skill_install_done")}: ${
|
|
2543
|
+
logger.success(`${t("skill_install_done")}: ${chalk6.green(successCount + " \u6210\u529F")}, ${failCount > 0 ? chalk6.red(failCount + " \u5931\u8D25") : chalk6.dim(failCount + " \u5931\u8D25")}`);
|
|
2243
2544
|
logger.blank();
|
|
2244
|
-
logger.info(
|
|
2245
|
-
logger.info(
|
|
2545
|
+
logger.info(`${t("install_to")}: ${chalk6.cyan(configRoot + "/skills/")}`);
|
|
2546
|
+
logger.info(`${t("start_to_use").replace("{tool}", chalk6.green(tool))}`);
|
|
2246
2547
|
logger.blank();
|
|
2247
2548
|
return "done";
|
|
2248
2549
|
}
|
|
@@ -2264,32 +2565,32 @@ async function listCommand() {
|
|
|
2264
2565
|
}
|
|
2265
2566
|
|
|
2266
2567
|
// src/commands/doctor.ts
|
|
2267
|
-
import
|
|
2268
|
-
import { existsSync as
|
|
2269
|
-
import { join as
|
|
2568
|
+
import chalk7 from "chalk";
|
|
2569
|
+
import { existsSync as existsSync12, readdirSync as readdirSync4, lstatSync as lstatSync3, unlinkSync as unlinkSync4, mkdirSync as mkdirSync6 } from "fs";
|
|
2570
|
+
import { join as join12 } from "path";
|
|
2270
2571
|
async function doctorCommand(options = {}) {
|
|
2271
2572
|
console.log();
|
|
2272
|
-
console.log(
|
|
2273
|
-
console.log(
|
|
2573
|
+
console.log(chalk7.bold(` ${t("doctor_title")}`));
|
|
2574
|
+
console.log(chalk7.dim(" " + "\u2500".repeat(46)));
|
|
2274
2575
|
let errors = 0;
|
|
2275
2576
|
let warnings = 0;
|
|
2276
2577
|
let fixes = 0;
|
|
2277
2578
|
console.log();
|
|
2278
|
-
console.log(
|
|
2579
|
+
console.log(chalk7.bold(` ${t("doctor_tools")}`));
|
|
2279
2580
|
const detectedTools = await detectTools();
|
|
2280
2581
|
const allTools = getAllTools();
|
|
2281
2582
|
for (const tool of allTools) {
|
|
2282
2583
|
const detected = detectedTools.find((d) => d.name === tool);
|
|
2283
2584
|
if (detected) {
|
|
2284
2585
|
console.log(
|
|
2285
|
-
|
|
2586
|
+
chalk7.green(" \u2713") + ` ${getToolDisplayName(tool)}${detected.version ? ` v${detected.version}` : ""}`
|
|
2286
2587
|
);
|
|
2287
2588
|
} else {
|
|
2288
|
-
console.log(
|
|
2589
|
+
console.log(chalk7.dim(" \u2014") + ` ${getToolDisplayName(tool)} \u2014 \u672A\u5B89\u88C5`);
|
|
2289
2590
|
}
|
|
2290
2591
|
}
|
|
2291
2592
|
console.log();
|
|
2292
|
-
console.log(
|
|
2593
|
+
console.log(chalk7.bold(` ${t("doctor_plugins")}`));
|
|
2293
2594
|
const plugins = getAllPlugins();
|
|
2294
2595
|
const installed = scanInstalled();
|
|
2295
2596
|
const installedMap = new Map(installed.map((p) => [p.id, p]));
|
|
@@ -2297,73 +2598,73 @@ async function doctorCommand(options = {}) {
|
|
|
2297
2598
|
const inst = installedMap.get(plugin.id);
|
|
2298
2599
|
if (inst) {
|
|
2299
2600
|
console.log(
|
|
2300
|
-
|
|
2601
|
+
chalk7.green(" \u2713") + ` ${plugin.id.padEnd(30)} ${inst.skillsCount} skills, ${inst.agentsCount} agents`
|
|
2301
2602
|
);
|
|
2302
2603
|
} else {
|
|
2303
|
-
console.log(
|
|
2604
|
+
console.log(chalk7.dim(" \u2014") + ` ${plugin.id.padEnd(30)} \u2014 \u672A\u5B89\u88C5`);
|
|
2304
2605
|
}
|
|
2305
2606
|
}
|
|
2306
2607
|
console.log();
|
|
2307
|
-
console.log(
|
|
2608
|
+
console.log(chalk7.bold(` ${t("doctor_links")}`));
|
|
2308
2609
|
const primaryTool = detectedTools[0]?.name || "opencode";
|
|
2309
2610
|
const configRoot = getConfigRoot(primaryTool, "project");
|
|
2310
2611
|
const skillsDir = getSkillsDir(configRoot);
|
|
2311
2612
|
const agentsDir = getAgentsDir(configRoot);
|
|
2312
|
-
if (
|
|
2613
|
+
if (existsSync12(skillsDir)) {
|
|
2313
2614
|
const brokenLinks = checkBrokenLinks(skillsDir);
|
|
2314
2615
|
if (brokenLinks === 0) {
|
|
2315
2616
|
const count = readdirSync4(skillsDir).length;
|
|
2316
|
-
console.log(
|
|
2617
|
+
console.log(chalk7.green(" \u2713") + ` ${skillsDir} \u2014 ${count} \u4E2A\u8F6F\u94FE\u63A5\u5747\u6709\u6548`);
|
|
2317
2618
|
} else {
|
|
2318
|
-
console.log(
|
|
2619
|
+
console.log(chalk7.yellow(" \u26A0") + ` ${skillsDir} \u2014 ${brokenLinks} \u4E2A\u5931\u6548\u94FE\u63A5`);
|
|
2319
2620
|
warnings++;
|
|
2320
2621
|
if (options.fix) {
|
|
2321
2622
|
const fixed = fixBrokenLinks(skillsDir);
|
|
2322
2623
|
fixes += fixed;
|
|
2323
|
-
console.log(
|
|
2624
|
+
console.log(chalk7.green(" \u2713") + ` ${t("doctor_fix_cleaning")}: \u5DF2\u6E05\u7406 ${fixed} \u4E2A\u5931\u6548\u94FE\u63A5`);
|
|
2324
2625
|
}
|
|
2325
2626
|
}
|
|
2326
2627
|
} else {
|
|
2327
|
-
console.log(
|
|
2628
|
+
console.log(chalk7.dim(" \u2014") + ` ${skillsDir} \u2014 \u4E0D\u5B58\u5728`);
|
|
2328
2629
|
if (options.fix) {
|
|
2329
2630
|
mkdirSync6(skillsDir, { recursive: true });
|
|
2330
2631
|
fixes++;
|
|
2331
|
-
console.log(
|
|
2632
|
+
console.log(chalk7.green(" \u2713") + ` ${t("doctor_fix_rebuilding")}: \u5DF2\u521B\u5EFA ${skillsDir}`);
|
|
2332
2633
|
}
|
|
2333
2634
|
}
|
|
2334
|
-
if (
|
|
2635
|
+
if (existsSync12(agentsDir)) {
|
|
2335
2636
|
const brokenLinks = checkBrokenLinks(agentsDir);
|
|
2336
2637
|
if (brokenLinks === 0) {
|
|
2337
2638
|
const count = readdirSync4(agentsDir).length;
|
|
2338
|
-
console.log(
|
|
2639
|
+
console.log(chalk7.green(" \u2713") + ` ${agentsDir} \u2014 ${count} \u4E2A\u8F6F\u94FE\u63A5\u5747\u6709\u6548`);
|
|
2339
2640
|
} else {
|
|
2340
|
-
console.log(
|
|
2641
|
+
console.log(chalk7.yellow(" \u26A0") + ` ${agentsDir} \u2014 ${brokenLinks} \u4E2A\u5931\u6548\u94FE\u63A5`);
|
|
2341
2642
|
warnings++;
|
|
2342
2643
|
if (options.fix) {
|
|
2343
2644
|
const fixed = fixBrokenLinks(agentsDir);
|
|
2344
2645
|
fixes += fixed;
|
|
2345
|
-
console.log(
|
|
2646
|
+
console.log(chalk7.green(" \u2713") + ` ${t("doctor_fix_cleaning")}: \u5DF2\u6E05\u7406 ${fixed} \u4E2A\u5931\u6548\u94FE\u63A5`);
|
|
2346
2647
|
}
|
|
2347
2648
|
}
|
|
2348
2649
|
} else {
|
|
2349
|
-
console.log(
|
|
2650
|
+
console.log(chalk7.dim(" \u2014") + ` ${agentsDir} \u2014 \u4E0D\u5B58\u5728`);
|
|
2350
2651
|
if (options.fix) {
|
|
2351
2652
|
mkdirSync6(agentsDir, { recursive: true });
|
|
2352
2653
|
fixes++;
|
|
2353
|
-
console.log(
|
|
2654
|
+
console.log(chalk7.green(" \u2713") + ` ${t("doctor_fix_rebuilding")}: \u5DF2\u521B\u5EFA ${agentsDir}`);
|
|
2354
2655
|
}
|
|
2355
2656
|
}
|
|
2356
2657
|
console.log();
|
|
2357
|
-
console.log(
|
|
2658
|
+
console.log(chalk7.bold(` ${t("doctor_config")}`));
|
|
2358
2659
|
const configFile = getConfigFileName(primaryTool);
|
|
2359
|
-
const configPath =
|
|
2360
|
-
if (
|
|
2361
|
-
console.log(
|
|
2660
|
+
const configPath = join12(process.cwd(), configFile);
|
|
2661
|
+
if (existsSync12(configPath)) {
|
|
2662
|
+
console.log(chalk7.green(" \u2713") + ` ${configFile} \u5B58\u5728`);
|
|
2362
2663
|
} else {
|
|
2363
|
-
console.log(
|
|
2664
|
+
console.log(chalk7.dim(" \u2014") + ` ${configFile} \u4E0D\u5B58\u5728`);
|
|
2364
2665
|
}
|
|
2365
2666
|
console.log();
|
|
2366
|
-
console.log(
|
|
2667
|
+
console.log(chalk7.dim(" " + "\u2500".repeat(46)));
|
|
2367
2668
|
if (options.fix && fixes > 0) {
|
|
2368
2669
|
console.log(
|
|
2369
2670
|
` ${t("doctor_result")}: ${warnings} \u4E2A\u8B66\u544A, ${errors} \u4E2A\u9519\u8BEF, ${fixes} \u9879\u5DF2\u4FEE\u590D`
|
|
@@ -2380,11 +2681,11 @@ function checkBrokenLinks(dir) {
|
|
|
2380
2681
|
try {
|
|
2381
2682
|
const entries = readdirSync4(dir);
|
|
2382
2683
|
for (const entry of entries) {
|
|
2383
|
-
const fullPath =
|
|
2684
|
+
const fullPath = join12(dir, entry);
|
|
2384
2685
|
try {
|
|
2385
2686
|
const stats = lstatSync3(fullPath);
|
|
2386
2687
|
if (stats.isSymbolicLink()) {
|
|
2387
|
-
if (!
|
|
2688
|
+
if (!existsSync12(fullPath)) {
|
|
2388
2689
|
broken++;
|
|
2389
2690
|
}
|
|
2390
2691
|
}
|
|
@@ -2401,12 +2702,12 @@ function fixBrokenLinks(dir) {
|
|
|
2401
2702
|
try {
|
|
2402
2703
|
const entries = readdirSync4(dir);
|
|
2403
2704
|
for (const entry of entries) {
|
|
2404
|
-
const fullPath =
|
|
2705
|
+
const fullPath = join12(dir, entry);
|
|
2405
2706
|
try {
|
|
2406
2707
|
const stats = lstatSync3(fullPath);
|
|
2407
2708
|
if (stats.isSymbolicLink()) {
|
|
2408
|
-
if (!
|
|
2409
|
-
|
|
2709
|
+
if (!existsSync12(fullPath)) {
|
|
2710
|
+
unlinkSync4(fullPath);
|
|
2410
2711
|
fixed++;
|
|
2411
2712
|
}
|
|
2412
2713
|
}
|
|
@@ -2419,36 +2720,36 @@ function fixBrokenLinks(dir) {
|
|
|
2419
2720
|
}
|
|
2420
2721
|
|
|
2421
2722
|
// src/commands/status.ts
|
|
2422
|
-
import
|
|
2723
|
+
import chalk8 from "chalk";
|
|
2423
2724
|
async function statusCommand() {
|
|
2424
2725
|
const plugins = getAllPlugins();
|
|
2425
2726
|
const installed = scanInstalled();
|
|
2426
2727
|
const installedMap = new Map(installed.map((p) => [p.id, p]));
|
|
2427
2728
|
console.log();
|
|
2428
|
-
console.log(
|
|
2729
|
+
console.log(chalk8.bold(` ${t("status_title")}`));
|
|
2429
2730
|
console.log();
|
|
2430
2731
|
if (installed.length === 0) {
|
|
2431
|
-
console.log(
|
|
2432
|
-
console.log(
|
|
2732
|
+
console.log(chalk8.dim(` ${t("status_none")}`));
|
|
2733
|
+
console.log(chalk8.dim(` ${t("status_hint")}`));
|
|
2433
2734
|
console.log();
|
|
2434
2735
|
return;
|
|
2435
2736
|
}
|
|
2436
2737
|
for (const inst of installed) {
|
|
2437
2738
|
console.log(
|
|
2438
|
-
|
|
2739
|
+
chalk8.green(" \u2713") + ` ${inst.displayName}` + chalk8.dim(` (${inst.tool}, ${inst.level})`)
|
|
2439
2740
|
);
|
|
2440
2741
|
console.log(
|
|
2441
|
-
|
|
2742
|
+
chalk8.dim(` ${inst.skillsCount} skills, ${inst.agentsCount} agents`)
|
|
2442
2743
|
);
|
|
2443
|
-
console.log(
|
|
2444
|
-
console.log(
|
|
2744
|
+
console.log(chalk8.dim(` ${inst.configRoot}`));
|
|
2745
|
+
console.log(chalk8.dim(` ${t("status_install_time")}: ${inst.installTime}`));
|
|
2445
2746
|
console.log();
|
|
2446
2747
|
}
|
|
2447
2748
|
}
|
|
2448
2749
|
|
|
2449
2750
|
// src/commands/install.ts
|
|
2450
2751
|
import { confirm } from "@inquirer/prompts";
|
|
2451
|
-
import
|
|
2752
|
+
import chalk9 from "chalk";
|
|
2452
2753
|
async function installCommand(names, options) {
|
|
2453
2754
|
if (options.list) {
|
|
2454
2755
|
try {
|
|
@@ -2460,7 +2761,7 @@ async function installCommand(names, options) {
|
|
|
2460
2761
|
return;
|
|
2461
2762
|
}
|
|
2462
2763
|
if (names.length === 0) {
|
|
2463
|
-
const scanSpinner2 = createSpinner("
|
|
2764
|
+
const scanSpinner2 = createSpinner(t("loading_skills_list"));
|
|
2464
2765
|
scanSpinner2.start();
|
|
2465
2766
|
try {
|
|
2466
2767
|
const scanRepoManager = createRepositoryManager();
|
|
@@ -2489,42 +2790,45 @@ async function installCommand(names, options) {
|
|
|
2489
2790
|
break;
|
|
2490
2791
|
}
|
|
2491
2792
|
if (selectedSkills.length === 0) {
|
|
2492
|
-
logger.info("
|
|
2793
|
+
logger.info(t("install_no_skill_selected"));
|
|
2493
2794
|
return;
|
|
2494
2795
|
}
|
|
2495
2796
|
names = selectedSkills;
|
|
2496
2797
|
const repoManager = createRepositoryManager();
|
|
2497
|
-
const spinner = createSpinner(t("
|
|
2798
|
+
const spinner = createSpinner(t("loading_plugin_data"));
|
|
2498
2799
|
spinner.start();
|
|
2499
2800
|
const repoPath = await repoManager.ensureRepo();
|
|
2500
|
-
spinner.succeed(
|
|
2501
|
-
logger.info(`${t("skill_install_progress")} ${
|
|
2801
|
+
spinner.succeed("\u63D2\u4EF6\u6570\u636E\u52A0\u8F7D\u5B8C\u6210");
|
|
2802
|
+
logger.info(`${t("skill_install_progress")} ${chalk9.bold(names.length)} \u4E2A Skills...`);
|
|
2502
2803
|
const level2 = options.level || "project";
|
|
2503
2804
|
const results = await installSkills(names, tool2, level2, repoPath);
|
|
2504
2805
|
let successCount = 0;
|
|
2505
2806
|
let failCount = 0;
|
|
2506
|
-
|
|
2807
|
+
const total = results.length;
|
|
2808
|
+
for (let i = 0; i < results.length; i++) {
|
|
2809
|
+
const result = results[i];
|
|
2810
|
+
const progress = `[${i + 1}/${total}]`;
|
|
2507
2811
|
if (result.success) {
|
|
2508
|
-
logger.success(`${result.skillId}`);
|
|
2812
|
+
logger.success(`${progress} ${result.skillId}`);
|
|
2509
2813
|
successCount++;
|
|
2510
2814
|
} else {
|
|
2511
|
-
logger.error(`${result.skillId}: ${result.error}`);
|
|
2815
|
+
logger.error(`${progress} ${result.skillId}: ${result.error}`);
|
|
2512
2816
|
failCount++;
|
|
2513
2817
|
}
|
|
2514
2818
|
}
|
|
2515
2819
|
const configRoot = getConfigRoot(tool2, level2);
|
|
2516
2820
|
logger.blank();
|
|
2517
|
-
logger.success(`${t("skill_install_done")}: ${
|
|
2821
|
+
logger.success(`${t("skill_install_done")}: ${chalk9.green(successCount + " \u6210\u529F")}, ${failCount > 0 ? chalk9.red(failCount + " \u5931\u8D25") : chalk9.dim(failCount + " \u5931\u8D25")}`);
|
|
2518
2822
|
logger.blank();
|
|
2519
|
-
logger.info(
|
|
2520
|
-
logger.info(
|
|
2823
|
+
logger.info(`${t("install_to")}: ${chalk9.cyan(configRoot + "/skills/")}`);
|
|
2824
|
+
logger.info(`${t("start_to_use").replace("{tool}", chalk9.green(tool2))}`);
|
|
2521
2825
|
logger.blank();
|
|
2522
2826
|
return;
|
|
2523
2827
|
}
|
|
2524
2828
|
}
|
|
2525
2829
|
}
|
|
2526
2830
|
}
|
|
2527
|
-
const scanSpinner = createSpinner("
|
|
2831
|
+
const scanSpinner = createSpinner(t("loading_skills_list"));
|
|
2528
2832
|
scanSpinner.start();
|
|
2529
2833
|
try {
|
|
2530
2834
|
const scanRepoManager = createRepositoryManager();
|
|
@@ -2552,7 +2856,7 @@ async function installCommand(names, options) {
|
|
|
2552
2856
|
for (const p of allPlugins) {
|
|
2553
2857
|
logger.step(` ${p.id} (${p.aliases.join(", ")})`);
|
|
2554
2858
|
}
|
|
2555
|
-
logger.info(`\u53EF\u7528 Skills: ${
|
|
2859
|
+
logger.info(`\u53EF\u7528 Skills: ${chalk9.cyan("install-helper install --list")}`);
|
|
2556
2860
|
return;
|
|
2557
2861
|
}
|
|
2558
2862
|
let tool;
|
|
@@ -2591,16 +2895,18 @@ async function installCommand(names, options) {
|
|
|
2591
2895
|
}
|
|
2592
2896
|
if (pluginsToInstall.length > 0) {
|
|
2593
2897
|
const repoManager = createRepositoryManager();
|
|
2594
|
-
const spinner = createSpinner(t("
|
|
2898
|
+
const spinner = createSpinner(t("loading_plugin_data"));
|
|
2595
2899
|
spinner.start();
|
|
2596
2900
|
const repoPath = await repoManager.ensureRepo();
|
|
2597
|
-
spinner.succeed(t("
|
|
2901
|
+
spinner.succeed(t("loading_plugin_data_complete"));
|
|
2598
2902
|
const allPlugins = getAllPlugins();
|
|
2599
2903
|
const results = await installPlugins(
|
|
2600
2904
|
pluginsToInstall,
|
|
2601
2905
|
tool,
|
|
2602
2906
|
level,
|
|
2603
|
-
repoPath
|
|
2907
|
+
repoPath,
|
|
2908
|
+
void 0,
|
|
2909
|
+
options.yes
|
|
2604
2910
|
);
|
|
2605
2911
|
const summary = results.map((result) => {
|
|
2606
2912
|
const plugin = allPlugins.find((p) => p.id === result.pluginId);
|
|
@@ -2618,28 +2924,31 @@ async function installCommand(names, options) {
|
|
|
2618
2924
|
}
|
|
2619
2925
|
if (skills.length > 0) {
|
|
2620
2926
|
const repoManager = createRepositoryManager();
|
|
2621
|
-
const spinner = createSpinner(t("
|
|
2927
|
+
const spinner = createSpinner(t("loading_plugin_data"));
|
|
2622
2928
|
spinner.start();
|
|
2623
2929
|
const repoPath = await repoManager.ensureRepo();
|
|
2624
|
-
spinner.succeed(t("
|
|
2625
|
-
logger.info(`${t("skill_install_progress")} ${
|
|
2930
|
+
spinner.succeed(t("loading_plugin_data_complete"));
|
|
2931
|
+
logger.info(`${t("skill_install_progress")} ${chalk9.bold(skills.length)} \u4E2A Skills...`);
|
|
2626
2932
|
const results = await installSkills(skills, tool, level, repoPath);
|
|
2627
2933
|
let successCount = 0;
|
|
2628
2934
|
let failCount = 0;
|
|
2629
|
-
|
|
2935
|
+
const total = results.length;
|
|
2936
|
+
for (let i = 0; i < results.length; i++) {
|
|
2937
|
+
const result = results[i];
|
|
2938
|
+
const progress = `[${i + 1}/${total}]`;
|
|
2630
2939
|
if (result.success) {
|
|
2631
|
-
logger.success(`${result.skillId}`);
|
|
2940
|
+
logger.success(`${progress} ${result.skillId}`);
|
|
2632
2941
|
successCount++;
|
|
2633
2942
|
} else {
|
|
2634
|
-
logger.error(`${result.skillId}: ${result.error}`);
|
|
2943
|
+
logger.error(`${progress} ${result.skillId}: ${result.error}`);
|
|
2635
2944
|
failCount++;
|
|
2636
2945
|
}
|
|
2637
2946
|
}
|
|
2638
2947
|
logger.blank();
|
|
2639
|
-
logger.success(`${t("skill_install_done")}: ${
|
|
2948
|
+
logger.success(`${t("skill_install_done")}: ${chalk9.green(successCount + " \u6210\u529F")}, ${failCount > 0 ? chalk9.red(failCount + " \u5931\u8D25") : chalk9.dim(failCount + " \u5931\u8D25")}`);
|
|
2640
2949
|
logger.blank();
|
|
2641
|
-
logger.info(
|
|
2642
|
-
logger.info(
|
|
2950
|
+
logger.info(`${t("install_to")}: ${chalk9.cyan(getConfigRoot(tool, level) + "/skills/")}`);
|
|
2951
|
+
logger.info(`${t("start_to_use").replace("{tool}", chalk9.green(tool))}`);
|
|
2643
2952
|
logger.blank();
|
|
2644
2953
|
}
|
|
2645
2954
|
}
|
|
@@ -2671,8 +2980,8 @@ async function installPlugins(pluginIds, tool, level, repoPath) {
|
|
|
2671
2980
|
}
|
|
2672
2981
|
|
|
2673
2982
|
// src/commands/uninstall.ts
|
|
2674
|
-
import { existsSync as
|
|
2675
|
-
import
|
|
2983
|
+
import { existsSync as existsSync13, unlinkSync as unlinkSync5, rmdirSync as rmdirSync2, readdirSync as readdirSync5, lstatSync as lstatSync4 } from "fs";
|
|
2984
|
+
import chalk10 from "chalk";
|
|
2676
2985
|
async function uninstallCommand(names, options) {
|
|
2677
2986
|
const tool = options.tool || "opencode";
|
|
2678
2987
|
const level = options.level || "project";
|
|
@@ -2689,24 +2998,24 @@ async function uninstallCommand(names, options) {
|
|
|
2689
2998
|
skills.push(skill.id);
|
|
2690
2999
|
continue;
|
|
2691
3000
|
}
|
|
2692
|
-
logger.error(
|
|
3001
|
+
logger.error(`${t("uninstall_not_found")}: ${name}`);
|
|
2693
3002
|
}
|
|
2694
3003
|
for (const pluginId of plugins) {
|
|
2695
3004
|
const plugin = findPlugin(pluginId);
|
|
2696
3005
|
if (!plugin) continue;
|
|
2697
3006
|
const record = readRecord(plugin.id);
|
|
2698
3007
|
if (!record) {
|
|
2699
|
-
logger.warn(`${plugin.displayName}
|
|
2700
|
-
logger.info(
|
|
3008
|
+
logger.warn(`${plugin.displayName} ${t("uninstall_no_record")}`);
|
|
3009
|
+
logger.info(`${t("uninstall_no_record_hint")}`);
|
|
2701
3010
|
continue;
|
|
2702
3011
|
}
|
|
2703
|
-
logger.info(
|
|
3012
|
+
logger.info(`${t("uninstall_in_progress")} ${plugin.displayName}...`);
|
|
2704
3013
|
let removedFiles = 0;
|
|
2705
3014
|
let removedDirs = 0;
|
|
2706
3015
|
for (const filePath of record.files) {
|
|
2707
3016
|
try {
|
|
2708
|
-
if (
|
|
2709
|
-
|
|
3017
|
+
if (existsSync13(filePath) || isSymlink3(filePath)) {
|
|
3018
|
+
unlinkSync5(filePath);
|
|
2710
3019
|
const name = filePath.split("/").pop() || filePath;
|
|
2711
3020
|
logger.step(` \u79FB\u9664: ${name}`);
|
|
2712
3021
|
removedFiles++;
|
|
@@ -2714,10 +3023,14 @@ async function uninstallCommand(names, options) {
|
|
|
2714
3023
|
} catch {
|
|
2715
3024
|
}
|
|
2716
3025
|
}
|
|
3026
|
+
const configRoot = getConfigRoot(record.tool, record.level);
|
|
2717
3027
|
const sortedDirs = [...record.directories].sort((a, b) => b.length - a.length);
|
|
2718
3028
|
for (const dirPath of sortedDirs) {
|
|
2719
3029
|
try {
|
|
2720
|
-
if (
|
|
3030
|
+
if (dirPath === configRoot) {
|
|
3031
|
+
continue;
|
|
3032
|
+
}
|
|
3033
|
+
if (existsSync13(dirPath)) {
|
|
2721
3034
|
const entries = readdirSync5(dirPath);
|
|
2722
3035
|
if (entries.length === 0) {
|
|
2723
3036
|
rmdirSync2(dirPath);
|
|
@@ -2731,15 +3044,32 @@ async function uninstallCommand(names, options) {
|
|
|
2731
3044
|
}
|
|
2732
3045
|
deleteRecord(plugin.id);
|
|
2733
3046
|
removeInstalledPlugin(plugin.id);
|
|
3047
|
+
const backups = findBackups(configRoot);
|
|
3048
|
+
const otherBackups = backups.filter((b) => b.pluginId !== pluginId);
|
|
3049
|
+
if (otherBackups.length > 0) {
|
|
3050
|
+
const choice = await showRestorePrompt(otherBackups);
|
|
3051
|
+
if (choice !== "none") {
|
|
3052
|
+
const restored = restoreBackup(choice, configRoot, record.tool);
|
|
3053
|
+
if (restored) {
|
|
3054
|
+
const backupInfo = otherBackups.find((b) => b.filePath === choice);
|
|
3055
|
+
logger.success(`${t("backup_restore_success")}: ${backupInfo?.pluginName || ""}`);
|
|
3056
|
+
deleteBackup(choice);
|
|
3057
|
+
}
|
|
3058
|
+
}
|
|
3059
|
+
}
|
|
3060
|
+
const currentBackups = backups.filter((b) => b.pluginId === pluginId);
|
|
3061
|
+
for (const backup of currentBackups) {
|
|
3062
|
+
deleteBackup(backup.filePath);
|
|
3063
|
+
}
|
|
2734
3064
|
const totalRemoved = removedFiles + removedDirs;
|
|
2735
3065
|
if (totalRemoved > 0) {
|
|
2736
|
-
logger.success(
|
|
3066
|
+
logger.success(`${t("uninstall_removed")} ${plugin.displayName}\uFF08\u79FB\u9664 ${removedFiles} \u4E2A\u6587\u4EF6\uFF0C${removedDirs} \u4E2A\u76EE\u5F55\uFF09`);
|
|
2737
3067
|
} else {
|
|
2738
|
-
logger.warn(`${plugin.displayName}
|
|
3068
|
+
logger.warn(`${plugin.displayName}${t("uninstall_files_gone")}`);
|
|
2739
3069
|
}
|
|
2740
3070
|
}
|
|
2741
3071
|
if (skills.length > 0) {
|
|
2742
|
-
logger.info(
|
|
3072
|
+
logger.info(`${t("uninstall_skills_in_progress")} ${skills.length} \u4E2A Skills...`);
|
|
2743
3073
|
const results = await uninstallSkills(skills, tool, level);
|
|
2744
3074
|
let successCount = 0;
|
|
2745
3075
|
let failCount = 0;
|
|
@@ -2751,7 +3081,7 @@ async function uninstallCommand(names, options) {
|
|
|
2751
3081
|
}
|
|
2752
3082
|
}
|
|
2753
3083
|
logger.blank();
|
|
2754
|
-
logger.success(`${t("skill_uninstall_done")}: ${
|
|
3084
|
+
logger.success(`${t("skill_uninstall_done")}: ${chalk10.green(successCount + " \u6210\u529F")}, ${failCount > 0 ? chalk10.red(failCount + " \u5931\u8D25") : chalk10.dim(failCount + " \u5931\u8D25")}`);
|
|
2755
3085
|
logger.blank();
|
|
2756
3086
|
}
|
|
2757
3087
|
}
|
|
@@ -2764,7 +3094,7 @@ function isSymlink3(path) {
|
|
|
2764
3094
|
}
|
|
2765
3095
|
|
|
2766
3096
|
// src/commands/update.ts
|
|
2767
|
-
import
|
|
3097
|
+
import chalk11 from "chalk";
|
|
2768
3098
|
async function updateCommand(pluginNames, options) {
|
|
2769
3099
|
let tool;
|
|
2770
3100
|
if (options.tool) {
|
|
@@ -2782,7 +3112,7 @@ async function updateCommand(pluginNames, options) {
|
|
|
2782
3112
|
pluginsToUpdate = manifests.map((m) => m.team);
|
|
2783
3113
|
if (pluginsToUpdate.length === 0) {
|
|
2784
3114
|
logger.info(t("update_no_plugins"));
|
|
2785
|
-
logger.info(`\u4F7F\u7528 ${
|
|
3115
|
+
logger.info(`\u4F7F\u7528 ${chalk11.cyan("install-helper install <plugin>")} \u5B89\u88C5\u63D2\u4EF6`);
|
|
2786
3116
|
return;
|
|
2787
3117
|
}
|
|
2788
3118
|
} else {
|
|
@@ -2844,42 +3174,42 @@ async function updateCommand(pluginNames, options) {
|
|
|
2844
3174
|
}
|
|
2845
3175
|
|
|
2846
3176
|
// src/commands/info.ts
|
|
2847
|
-
import
|
|
2848
|
-
import { existsSync as
|
|
2849
|
-
import { join as
|
|
3177
|
+
import chalk12 from "chalk";
|
|
3178
|
+
import { existsSync as existsSync14, readdirSync as readdirSync6 } from "fs";
|
|
3179
|
+
import { join as join13 } from "path";
|
|
2850
3180
|
async function infoCommand(pluginName) {
|
|
2851
3181
|
const plugin = findPlugin(pluginName);
|
|
2852
3182
|
if (!plugin) {
|
|
2853
|
-
console.log(
|
|
3183
|
+
console.log(chalk12.red(` ${t("info_not_found")}: ${pluginName}`));
|
|
2854
3184
|
return;
|
|
2855
3185
|
}
|
|
2856
3186
|
const installed = scanInstalled();
|
|
2857
3187
|
const isInstalled = installed.some((p) => p.id === plugin.id);
|
|
2858
|
-
const statusText = isInstalled ?
|
|
3188
|
+
const statusText = isInstalled ? chalk12.green(`\u2713 ${t("status_installed")}`) : chalk12.dim(`\u2014 ${t("status_not_installed")}`);
|
|
2859
3189
|
console.log();
|
|
2860
|
-
console.log(
|
|
2861
|
-
console.log(
|
|
3190
|
+
console.log(chalk12.bold(` ${plugin.displayName}`));
|
|
3191
|
+
console.log(chalk12.dim(" " + "\u2500".repeat(40)));
|
|
2862
3192
|
console.log();
|
|
2863
|
-
console.log(` ${
|
|
2864
|
-
console.log(` ${
|
|
2865
|
-
console.log(` ${
|
|
2866
|
-
console.log(` ${
|
|
2867
|
-
console.log(` ${
|
|
2868
|
-
console.log(` ${
|
|
3193
|
+
console.log(` ${chalk12.dim(t("info_description") + ":")} ${plugin.description}`);
|
|
3194
|
+
console.log(` ${chalk12.dim("ID:")} ${plugin.id}`);
|
|
3195
|
+
console.log(` ${chalk12.dim(t("info_status") + ":")} ${statusText}`);
|
|
3196
|
+
console.log(` ${chalk12.dim(t("info_skills") + ":")} ${plugin.skills}`);
|
|
3197
|
+
console.log(` ${chalk12.dim(t("info_agents") + ":")} ${plugin.agents}`);
|
|
3198
|
+
console.log(` ${chalk12.dim(t("info_aliases") + ":")} ${plugin.aliases.join(", ")}`);
|
|
2869
3199
|
console.log();
|
|
2870
3200
|
try {
|
|
2871
3201
|
const repoManager = createRepositoryManager();
|
|
2872
3202
|
const repoPath = await repoManager.ensureRepo();
|
|
2873
|
-
const quickstartPath =
|
|
2874
|
-
if (
|
|
2875
|
-
console.log(` ${
|
|
3203
|
+
const quickstartPath = join13(repoPath, plugin.dir, "quickstart.md");
|
|
3204
|
+
if (existsSync14(quickstartPath)) {
|
|
3205
|
+
console.log(` ${chalk12.dim(t("info_quickstart") + ":")} ${quickstartPath}`);
|
|
2876
3206
|
}
|
|
2877
|
-
const agentsDir =
|
|
2878
|
-
if (
|
|
3207
|
+
const agentsDir = join13(repoPath, plugin.dir, "agents");
|
|
3208
|
+
if (existsSync14(agentsDir)) {
|
|
2879
3209
|
const agentFiles = readdirSync6(agentsDir).filter((f) => f.endsWith(".md"));
|
|
2880
3210
|
if (agentFiles.length > 0) {
|
|
2881
3211
|
console.log();
|
|
2882
|
-
console.log(` ${
|
|
3212
|
+
console.log(` ${chalk12.bold("Agents:")}`);
|
|
2883
3213
|
for (const agent of agentFiles) {
|
|
2884
3214
|
console.log(` \u2022 ${agent.replace(".md", "")}`);
|
|
2885
3215
|
}
|
|
@@ -2891,39 +3221,39 @@ async function infoCommand(pluginName) {
|
|
|
2891
3221
|
}
|
|
2892
3222
|
|
|
2893
3223
|
// src/commands/lang.ts
|
|
2894
|
-
import
|
|
3224
|
+
import chalk13 from "chalk";
|
|
2895
3225
|
async function langCommand(action, value) {
|
|
2896
3226
|
const config = readConfig();
|
|
2897
3227
|
if (!action || action === "show") {
|
|
2898
3228
|
console.log();
|
|
2899
|
-
console.log(
|
|
2900
|
-
console.log(
|
|
3229
|
+
console.log(chalk13.bold(` ${t("lang_title")}`));
|
|
3230
|
+
console.log(chalk13.dim(" " + "\u2500".repeat(40)));
|
|
2901
3231
|
console.log();
|
|
2902
|
-
console.log(` ${
|
|
3232
|
+
console.log(` ${chalk13.dim(t("lang_current") + ":")} ${config.language}`);
|
|
2903
3233
|
console.log();
|
|
2904
|
-
console.log(
|
|
2905
|
-
console.log(
|
|
3234
|
+
console.log(chalk13.dim(` ${t("lang_supported")}`));
|
|
3235
|
+
console.log(chalk13.dim(` ${t("lang_usage")}`));
|
|
2906
3236
|
console.log();
|
|
2907
3237
|
return;
|
|
2908
3238
|
}
|
|
2909
3239
|
if (action === "set") {
|
|
2910
3240
|
if (!value) {
|
|
2911
|
-
console.log(
|
|
3241
|
+
console.log(chalk13.red(` ${t("lang_specify")}`));
|
|
2912
3242
|
return;
|
|
2913
3243
|
}
|
|
2914
3244
|
if (value !== "zh_CN" && value !== "en_US") {
|
|
2915
|
-
console.log(
|
|
3245
|
+
console.log(chalk13.red(` ${t("lang_invalid")}`));
|
|
2916
3246
|
return;
|
|
2917
3247
|
}
|
|
2918
3248
|
updateConfig({ language: value });
|
|
2919
3249
|
setLanguage(value);
|
|
2920
3250
|
console.log();
|
|
2921
|
-
console.log(
|
|
3251
|
+
console.log(chalk13.green(` \u2713 ${t("lang_set")} ${value}`));
|
|
2922
3252
|
console.log();
|
|
2923
3253
|
return;
|
|
2924
3254
|
}
|
|
2925
|
-
console.log(
|
|
2926
|
-
console.log(
|
|
3255
|
+
console.log(chalk13.red(` ${t("lang_unknown_action")}: ${action}`));
|
|
3256
|
+
console.log(chalk13.dim(` ${t("lang_supported_actions")}`));
|
|
2927
3257
|
}
|
|
2928
3258
|
|
|
2929
3259
|
// src/cli.ts
|
|
@@ -2933,7 +3263,7 @@ function createCLI() {
|
|
|
2933
3263
|
setLanguage(config.language);
|
|
2934
3264
|
}
|
|
2935
3265
|
const program2 = new Command();
|
|
2936
|
-
program2.name("install-helper").description("Install Helper - Interactive installer for CANN operator development skills").version("0.0.2-beta.
|
|
3266
|
+
program2.name("install-helper").description("CANNBot Install Helper - Interactive installer for CANN operator development skills").version("0.0.2-beta.10");
|
|
2937
3267
|
program2.command("init", { isDefault: false }).description("Run interactive installation wizard").action(async () => {
|
|
2938
3268
|
await initCommand();
|
|
2939
3269
|
});
|