@cannbot-ai/install-helper 0.0.2-beta.34 → 0.0.2-beta.36
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 +188 -217
- package/dist/index.js.map +1 -1
- package/dist/locales/en_US.json +9 -9
- package/dist/locales/zh_CN.json +9 -9
- package/dist/plugins.d/ops-direct-invoke.yml +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12,13 +12,13 @@ import { select, checkbox, Separator } from "@inquirer/prompts";
|
|
|
12
12
|
import chalk3 from "chalk";
|
|
13
13
|
|
|
14
14
|
// src/core/registry.ts
|
|
15
|
-
import { readdirSync, readFileSync as readFileSync2, existsSync
|
|
15
|
+
import { readdirSync, readFileSync as readFileSync2, existsSync } from "fs";
|
|
16
16
|
import { join as join2, dirname as dirname2 } from "path";
|
|
17
17
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
18
18
|
import { parse as parseYaml } from "yaml";
|
|
19
19
|
|
|
20
20
|
// src/utils/logger.ts
|
|
21
|
-
import
|
|
21
|
+
import chalk2 from "chalk";
|
|
22
22
|
import ora from "ora";
|
|
23
23
|
|
|
24
24
|
// src/utils/i18n.ts
|
|
@@ -52,20 +52,95 @@ function t(key) {
|
|
|
52
52
|
return messages[key] !== void 0 ? messages[key] : key;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
// src/ui/theme.ts
|
|
56
|
+
import chalk from "chalk";
|
|
57
|
+
var selectTheme = {
|
|
58
|
+
helpMode: "never"
|
|
59
|
+
};
|
|
60
|
+
function isCJK(code) {
|
|
61
|
+
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;
|
|
62
|
+
}
|
|
63
|
+
function isEmoji(code) {
|
|
64
|
+
return code >= 127744 && code <= 129791 || code >= 9728 && code <= 10175;
|
|
65
|
+
}
|
|
66
|
+
function getDisplayWidth(str) {
|
|
67
|
+
let width = 0;
|
|
68
|
+
for (const ch of str) {
|
|
69
|
+
const code = ch.codePointAt(0);
|
|
70
|
+
if (isCJK(code) || isEmoji(code)) {
|
|
71
|
+
width += 2;
|
|
72
|
+
} else {
|
|
73
|
+
width += 1;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return width;
|
|
77
|
+
}
|
|
78
|
+
function wrapDescription(text) {
|
|
79
|
+
const prefix = " \u{1F4A1} ";
|
|
80
|
+
const indent = " ";
|
|
81
|
+
const cols = process.stdout.columns || 120;
|
|
82
|
+
const maxLen = Math.max(20, cols - getDisplayWidth(prefix) - 2);
|
|
83
|
+
const tokens = [];
|
|
84
|
+
let i = 0;
|
|
85
|
+
while (i < text.length) {
|
|
86
|
+
const code = text[i].codePointAt(0);
|
|
87
|
+
if (isCJK(code)) {
|
|
88
|
+
tokens.push({ text: text[i], width: 2 });
|
|
89
|
+
i++;
|
|
90
|
+
} else {
|
|
91
|
+
let j = i;
|
|
92
|
+
while (j < text.length) {
|
|
93
|
+
const c = text[j].codePointAt(0);
|
|
94
|
+
if (isCJK(c)) break;
|
|
95
|
+
j++;
|
|
96
|
+
}
|
|
97
|
+
const word = text.slice(i, j);
|
|
98
|
+
tokens.push({ text: word, width: getDisplayWidth(word) });
|
|
99
|
+
i = j;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const lines = [];
|
|
103
|
+
let line = "";
|
|
104
|
+
let lineWidth = 0;
|
|
105
|
+
for (const token of tokens) {
|
|
106
|
+
if (lineWidth + token.width > maxLen && line) {
|
|
107
|
+
lines.push(line.trimEnd());
|
|
108
|
+
line = token.text;
|
|
109
|
+
lineWidth = token.width;
|
|
110
|
+
} else {
|
|
111
|
+
line += token.text;
|
|
112
|
+
lineWidth += token.width;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (line) lines.push(line.trimEnd());
|
|
116
|
+
return lines.map((l, i2) => chalk.cyan(i2 === 0 ? prefix + l : indent + l)).join("\n");
|
|
117
|
+
}
|
|
118
|
+
var checkboxTheme = {
|
|
119
|
+
icon: {
|
|
120
|
+
checked: "\x1B[32m\u2611\x1B[22m",
|
|
121
|
+
unchecked: "\u2610",
|
|
122
|
+
cursor: "\u276F"
|
|
123
|
+
},
|
|
124
|
+
helpMode: "never",
|
|
125
|
+
style: {
|
|
126
|
+
description: (text) => wrapDescription(text)
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
55
130
|
// src/utils/logger.ts
|
|
56
131
|
var logger = {
|
|
57
|
-
success: (msg) => console.log(
|
|
58
|
-
error: (msg) => console.log(
|
|
59
|
-
warn: (msg) => console.log(
|
|
60
|
-
info: (msg) => console.log(
|
|
61
|
-
step: (msg) => console.log(
|
|
132
|
+
success: (msg) => console.log(chalk2.green("\u2713") + " " + msg),
|
|
133
|
+
error: (msg) => console.log(chalk2.red("\u2717") + " " + msg),
|
|
134
|
+
warn: (msg) => console.log(chalk2.yellow("\u26A0") + " " + msg),
|
|
135
|
+
info: (msg) => console.log(chalk2.cyan("\u2192") + " " + msg),
|
|
136
|
+
step: (msg) => console.log(chalk2.dim(msg)),
|
|
62
137
|
blank: () => console.log()
|
|
63
138
|
};
|
|
64
139
|
function createSpinner(text) {
|
|
65
140
|
return ora({ text, color: "cyan" });
|
|
66
141
|
}
|
|
67
142
|
function printBanner(subtitle) {
|
|
68
|
-
console.log(
|
|
143
|
+
console.log(chalk2.cyan(`
|
|
69
144
|
____ _ _ _ _ _ ____ _
|
|
70
145
|
/ ___| / \\ | \\ | | \\ | | __ ) ___ | |_
|
|
71
146
|
| | / _ \\ | \\| | \\| | _ \\ / _ \\| __|
|
|
@@ -73,22 +148,10 @@ function printBanner(subtitle) {
|
|
|
73
148
|
\\____/_/ \\_\\_| \\_|_| \\_|____/ \\___/ \\__|
|
|
74
149
|
`));
|
|
75
150
|
if (subtitle) {
|
|
76
|
-
console.log(
|
|
151
|
+
console.log(chalk2.bold(` ${subtitle}`));
|
|
77
152
|
console.log();
|
|
78
153
|
}
|
|
79
154
|
}
|
|
80
|
-
function getDisplayWidth(str) {
|
|
81
|
-
let width = 0;
|
|
82
|
-
for (const ch of str) {
|
|
83
|
-
const code = ch.codePointAt(0);
|
|
84
|
-
if (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) {
|
|
85
|
-
width += 2;
|
|
86
|
-
} else {
|
|
87
|
-
width += 1;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
return width;
|
|
91
|
-
}
|
|
92
155
|
function printBoxTitle(title, width = 65) {
|
|
93
156
|
const border = "\u2550".repeat(width);
|
|
94
157
|
const displayWidth = getDisplayWidth(title);
|
|
@@ -97,9 +160,9 @@ function printBoxTitle(title, width = 65) {
|
|
|
97
160
|
const rightPadding = totalPadding - leftPadding;
|
|
98
161
|
const paddedTitle = " ".repeat(Math.max(0, leftPadding)) + title + " ".repeat(Math.max(0, rightPadding));
|
|
99
162
|
console.log();
|
|
100
|
-
console.log(
|
|
101
|
-
console.log(
|
|
102
|
-
console.log(
|
|
163
|
+
console.log(chalk2.cyan.bold(` \u2554${border}\u2557`));
|
|
164
|
+
console.log(chalk2.cyan.bold(` \u2551`) + chalk2.cyan.bold(paddedTitle) + chalk2.cyan.bold(`\u2551`));
|
|
165
|
+
console.log(chalk2.cyan.bold(` \u255A${border}\u255D`));
|
|
103
166
|
console.log();
|
|
104
167
|
}
|
|
105
168
|
function showOperationHints(isCheckbox = false) {
|
|
@@ -112,6 +175,23 @@ function showOperationHints(isCheckbox = false) {
|
|
|
112
175
|
}
|
|
113
176
|
}
|
|
114
177
|
|
|
178
|
+
// src/utils/fs-helpers.ts
|
|
179
|
+
import { lstatSync, statSync } from "fs";
|
|
180
|
+
function isSymlink(path) {
|
|
181
|
+
try {
|
|
182
|
+
return lstatSync(path).isSymbolicLink();
|
|
183
|
+
} catch {
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
function isDirectory(path) {
|
|
188
|
+
try {
|
|
189
|
+
return statSync(path).isDirectory();
|
|
190
|
+
} catch {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
115
195
|
// src/core/registry.ts
|
|
116
196
|
var __filename2 = fileURLToPath2(import.meta.url);
|
|
117
197
|
var __dirname2 = dirname2(__filename2);
|
|
@@ -193,13 +273,6 @@ function mergeDynamicPlugins(repoPath) {
|
|
|
193
273
|
);
|
|
194
274
|
}
|
|
195
275
|
}
|
|
196
|
-
function isDirectory(path) {
|
|
197
|
-
try {
|
|
198
|
-
return statSync(path).isDirectory();
|
|
199
|
-
} catch {
|
|
200
|
-
return false;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
276
|
function findPlugin(query) {
|
|
204
277
|
const normalized = query.toLowerCase().trim();
|
|
205
278
|
const exactMatch = PLUGIN_REGISTRY.find(
|
|
@@ -344,8 +417,9 @@ async function getCommandVersion(cmd, args = ["--version"]) {
|
|
|
344
417
|
}
|
|
345
418
|
async function getCommandPath(cmd) {
|
|
346
419
|
try {
|
|
347
|
-
const
|
|
348
|
-
|
|
420
|
+
const whichCmd = process.platform === "win32" ? "where" : "which";
|
|
421
|
+
const result = await execa(whichCmd, [cmd], { timeout: 5e3 });
|
|
422
|
+
return result.stdout.trim().split("\n")[0];
|
|
349
423
|
} catch {
|
|
350
424
|
return void 0;
|
|
351
425
|
}
|
|
@@ -431,7 +505,7 @@ function getToolDisplayName(tool) {
|
|
|
431
505
|
return names[tool];
|
|
432
506
|
}
|
|
433
507
|
function getAllTools() {
|
|
434
|
-
return
|
|
508
|
+
return VALID_TOOLS;
|
|
435
509
|
}
|
|
436
510
|
|
|
437
511
|
// src/core/manifest.ts
|
|
@@ -474,7 +548,7 @@ function readAllManifests(configRoot) {
|
|
|
474
548
|
function scanInstalled() {
|
|
475
549
|
const plugins = getAllPlugins();
|
|
476
550
|
const installed = [];
|
|
477
|
-
const tools =
|
|
551
|
+
const tools = VALID_TOOLS;
|
|
478
552
|
const levels = ["project", "global"];
|
|
479
553
|
for (const tool of tools) {
|
|
480
554
|
for (const level of levels) {
|
|
@@ -535,7 +609,6 @@ function verifyPluginFilesExist(configRoot, manifest, tool, level) {
|
|
|
535
609
|
// src/utils/config.ts
|
|
536
610
|
import { existsSync as existsSync6, mkdirSync, readFileSync as readFileSync4 } from "fs";
|
|
537
611
|
import { join as join6 } from "path";
|
|
538
|
-
import { homedir as homedir3 } from "os";
|
|
539
612
|
import { parse, stringify } from "yaml";
|
|
540
613
|
|
|
541
614
|
// src/utils/fs.ts
|
|
@@ -559,7 +632,7 @@ function atomicWriteFileSync(filePath, data, encoding = "utf-8") {
|
|
|
559
632
|
|
|
560
633
|
// src/utils/config.ts
|
|
561
634
|
function getConfigDir() {
|
|
562
|
-
return
|
|
635
|
+
return getCannbotConfigDir();
|
|
563
636
|
}
|
|
564
637
|
function getConfigPath() {
|
|
565
638
|
return join6(getConfigDir(), "config.yaml");
|
|
@@ -620,84 +693,11 @@ function removeInstalledPlugin(pluginId) {
|
|
|
620
693
|
writeConfig(config);
|
|
621
694
|
}
|
|
622
695
|
|
|
623
|
-
// src/
|
|
624
|
-
import chalk2 from "chalk";
|
|
625
|
-
var selectTheme = {
|
|
626
|
-
helpMode: "never"
|
|
627
|
-
};
|
|
628
|
-
function isCJK(code) {
|
|
629
|
-
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;
|
|
630
|
-
}
|
|
631
|
-
function isEmoji(code) {
|
|
632
|
-
return code >= 127744 && code <= 129791 || code >= 9728 && code <= 10175;
|
|
633
|
-
}
|
|
634
|
-
function getDisplayWidth2(str) {
|
|
635
|
-
let width = 0;
|
|
636
|
-
for (const ch of str) {
|
|
637
|
-
const code = ch.codePointAt(0);
|
|
638
|
-
if (isCJK(code) || isEmoji(code)) {
|
|
639
|
-
width += 2;
|
|
640
|
-
} else {
|
|
641
|
-
width += 1;
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
return width;
|
|
645
|
-
}
|
|
646
|
-
function wrapDescription(text) {
|
|
647
|
-
const prefix = " \u{1F4A1} ";
|
|
648
|
-
const indent = " ";
|
|
649
|
-
const cols = process.stdout.columns || 120;
|
|
650
|
-
const maxLen = Math.max(20, cols - getDisplayWidth2(prefix) - 2);
|
|
651
|
-
const tokens = [];
|
|
652
|
-
let i = 0;
|
|
653
|
-
while (i < text.length) {
|
|
654
|
-
const code = text[i].codePointAt(0);
|
|
655
|
-
if (isCJK(code)) {
|
|
656
|
-
tokens.push({ text: text[i], width: 2 });
|
|
657
|
-
i++;
|
|
658
|
-
} else {
|
|
659
|
-
let j = i;
|
|
660
|
-
while (j < text.length) {
|
|
661
|
-
const c = text[j].codePointAt(0);
|
|
662
|
-
if (isCJK(c)) break;
|
|
663
|
-
j++;
|
|
664
|
-
}
|
|
665
|
-
const word = text.slice(i, j);
|
|
666
|
-
tokens.push({ text: word, width: getDisplayWidth2(word) });
|
|
667
|
-
i = j;
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
const lines = [];
|
|
671
|
-
let line = "";
|
|
672
|
-
let lineWidth = 0;
|
|
673
|
-
for (const token of tokens) {
|
|
674
|
-
if (lineWidth + token.width > maxLen && line) {
|
|
675
|
-
lines.push(line.trimEnd());
|
|
676
|
-
line = token.text;
|
|
677
|
-
lineWidth = token.width;
|
|
678
|
-
} else {
|
|
679
|
-
line += token.text;
|
|
680
|
-
lineWidth += token.width;
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
if (line) lines.push(line.trimEnd());
|
|
684
|
-
return lines.map((l, i2) => chalk2.cyan(i2 === 0 ? prefix + l : indent + l)).join("\n");
|
|
685
|
-
}
|
|
686
|
-
var checkboxTheme = {
|
|
687
|
-
icon: {
|
|
688
|
-
checked: "\x1B[32m\u2611\x1B[22m",
|
|
689
|
-
unchecked: "\u2610",
|
|
690
|
-
cursor: "\u276F"
|
|
691
|
-
},
|
|
692
|
-
helpMode: "never",
|
|
693
|
-
style: {
|
|
694
|
-
description: (text) => wrapDescription(text)
|
|
695
|
-
}
|
|
696
|
-
};
|
|
697
|
-
|
|
698
|
-
// src/ui/wizard.ts
|
|
696
|
+
// src/utils/constants.ts
|
|
699
697
|
var BACK = "__back__";
|
|
700
698
|
var CANCEL = "__cancel__";
|
|
699
|
+
|
|
700
|
+
// src/ui/wizard.ts
|
|
701
701
|
async function selectToolWithDetection() {
|
|
702
702
|
const config = readConfig();
|
|
703
703
|
logger.blank();
|
|
@@ -781,7 +781,7 @@ async function stepTool(detectedTools, lastTool) {
|
|
|
781
781
|
if (detectedTools.length === 0) {
|
|
782
782
|
logger.error(t("error_tool_not_found"));
|
|
783
783
|
const choices2 = [
|
|
784
|
-
...
|
|
784
|
+
...VALID_TOOLS.map((tool) => ({
|
|
785
785
|
name: `> ${getToolDisplayName(tool)}`,
|
|
786
786
|
value: tool
|
|
787
787
|
})),
|
|
@@ -950,7 +950,7 @@ import { execa as execa2 } from "execa";
|
|
|
950
950
|
import { parse as parseYaml3 } from "yaml";
|
|
951
951
|
|
|
952
952
|
// src/core/scanner.ts
|
|
953
|
-
import { existsSync as existsSync7, readdirSync as readdirSync2, readFileSync as readFileSync5,
|
|
953
|
+
import { existsSync as existsSync7, readdirSync as readdirSync2, readFileSync as readFileSync5, mkdirSync as mkdirSync2 } from "fs";
|
|
954
954
|
import { join as join7, dirname as dirname4 } from "path";
|
|
955
955
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
956
956
|
import { parse as parseYaml2 } from "yaml";
|
|
@@ -1007,7 +1007,7 @@ function scanSkills(repoPath) {
|
|
|
1007
1007
|
if (!existsSync7(pluginParent)) continue;
|
|
1008
1008
|
for (const plugin of safeReaddir(pluginParent)) {
|
|
1009
1009
|
const pluginPath = join7(pluginParent, plugin);
|
|
1010
|
-
if (!
|
|
1010
|
+
if (!isDirectory(pluginPath)) continue;
|
|
1011
1011
|
const skillsDir = join7(pluginPath, "skills");
|
|
1012
1012
|
if (existsSync7(skillsDir)) {
|
|
1013
1013
|
scanDirectory(skillsDir, repoPath, `${pluginDir}/${plugin}/skills`, skills, seen);
|
|
@@ -1123,7 +1123,7 @@ function scanDirectory(dirPath, repoPath, sourcePrefix, skills, seen) {
|
|
|
1123
1123
|
for (const entry of safeReaddir(dirPath)) {
|
|
1124
1124
|
const fullPath = join7(dirPath, entry);
|
|
1125
1125
|
if (EXCLUDE_DIRS.has(entry)) continue;
|
|
1126
|
-
if (!
|
|
1126
|
+
if (!isDirectory(fullPath)) continue;
|
|
1127
1127
|
const skillMd = join7(fullPath, "SKILL.md");
|
|
1128
1128
|
if (existsSync7(skillMd)) {
|
|
1129
1129
|
const frontmatter = parseFrontmatter(skillMd);
|
|
@@ -1148,29 +1148,22 @@ function safeReaddir(dir) {
|
|
|
1148
1148
|
return [];
|
|
1149
1149
|
}
|
|
1150
1150
|
}
|
|
1151
|
-
function isDirectory2(path) {
|
|
1152
|
-
try {
|
|
1153
|
-
return statSync2(path).isDirectory();
|
|
1154
|
-
} catch {
|
|
1155
|
-
return false;
|
|
1156
|
-
}
|
|
1157
|
-
}
|
|
1158
1151
|
|
|
1159
1152
|
// src/core/skill-registry.ts
|
|
1160
1153
|
var CATEGORY_DEFS = [
|
|
1161
|
-
{ id: "knowledge", name: "\u77E5\u8BC6\u4E0E\u53C2\u8003" },
|
|
1162
|
-
{ id: "env-tools", name: "\u73AF\u5883\u4E0E\u5DE5\u5177" },
|
|
1163
|
-
{ id: "debug", name: "\u8C03\u8BD5\u4E0E\u8BCA\u65AD" },
|
|
1164
|
-
{ id: "testing", name: "\u6D4B\u8BD5\u4E0E\u8D28\u91CF" },
|
|
1165
|
-
{ id: "ascendc", name: "AscendC \u5F00\u53D1" },
|
|
1166
|
-
{ id: "pypto", name: "PyPTO \u5F00\u53D1" },
|
|
1167
|
-
{ id: "tilelang", name: "TileLang \u5F00\u53D1" },
|
|
1168
|
-
{ id: "triton", name: "Triton \u5F00\u53D1" },
|
|
1169
|
-
{ id: "model", name: "\u6A21\u578B\u63A8\u7406\u4F18\u5316" },
|
|
1170
|
-
{ id: "runtime", name: "Runtime \u8FC1\u79FB" },
|
|
1171
|
-
{ id: "graph", name: "\u56FE\u6A21\u5F0F" },
|
|
1172
|
-
{ id: "platform", name: "\u5E73\u53F0\u5DE5\u5177" },
|
|
1173
|
-
{ id: "other", name: "\u5176\u4ED6 Skills" }
|
|
1154
|
+
{ id: "knowledge", name: "\u77E5\u8BC6\u4E0E\u53C2\u8003", nameEn: "Knowledge & Reference" },
|
|
1155
|
+
{ id: "env-tools", name: "\u73AF\u5883\u4E0E\u5DE5\u5177", nameEn: "Environment & Tools" },
|
|
1156
|
+
{ id: "debug", name: "\u8C03\u8BD5\u4E0E\u8BCA\u65AD", nameEn: "Debug & Diagnostics" },
|
|
1157
|
+
{ id: "testing", name: "\u6D4B\u8BD5\u4E0E\u8D28\u91CF", nameEn: "Testing & Quality" },
|
|
1158
|
+
{ id: "ascendc", name: "AscendC \u5F00\u53D1", nameEn: "AscendC Development" },
|
|
1159
|
+
{ id: "pypto", name: "PyPTO \u5F00\u53D1", nameEn: "PyPTO Development" },
|
|
1160
|
+
{ id: "tilelang", name: "TileLang \u5F00\u53D1", nameEn: "TileLang Development" },
|
|
1161
|
+
{ id: "triton", name: "Triton \u5F00\u53D1", nameEn: "Triton Development" },
|
|
1162
|
+
{ id: "model", name: "\u6A21\u578B\u63A8\u7406\u4F18\u5316", nameEn: "Model Inference Optimization" },
|
|
1163
|
+
{ id: "runtime", name: "Runtime \u8FC1\u79FB", nameEn: "Runtime Migration" },
|
|
1164
|
+
{ id: "graph", name: "\u56FE\u6A21\u5F0F", nameEn: "Graph Mode" },
|
|
1165
|
+
{ id: "platform", name: "\u5E73\u53F0\u5DE5\u5177", nameEn: "Platform Tools" },
|
|
1166
|
+
{ id: "other", name: "\u5176\u4ED6 Skills", nameEn: "Other Skills" }
|
|
1174
1167
|
];
|
|
1175
1168
|
var dynamicSkills = [];
|
|
1176
1169
|
var initialized = false;
|
|
@@ -1380,9 +1373,10 @@ function getAllSkills() {
|
|
|
1380
1373
|
}
|
|
1381
1374
|
function getAllCategories() {
|
|
1382
1375
|
const skills = getActiveSkills();
|
|
1376
|
+
const isEn = t("list_name") === "Name";
|
|
1383
1377
|
return CATEGORY_DEFS.map((def) => ({
|
|
1384
1378
|
id: def.id,
|
|
1385
|
-
name: def.name,
|
|
1379
|
+
name: isEn ? def.nameEn : def.name,
|
|
1386
1380
|
skills: skills.filter((s) => {
|
|
1387
1381
|
const catId = CATEGORY_MAP[s.id];
|
|
1388
1382
|
if (catId) return catId === def.id;
|
|
@@ -1510,7 +1504,7 @@ import { join as join11 } from "path";
|
|
|
1510
1504
|
import { execa as execa3 } from "execa";
|
|
1511
1505
|
|
|
1512
1506
|
// src/core/record.ts
|
|
1513
|
-
import { existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync7,
|
|
1507
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync7, unlinkSync as unlinkSync2 } from "fs";
|
|
1514
1508
|
import { join as join9 } from "path";
|
|
1515
1509
|
function getInstallsDir() {
|
|
1516
1510
|
return join9(getCannbotConfigDir(), "installs");
|
|
@@ -1613,13 +1607,6 @@ function scanInstalledFiles(pluginId, displayName, tool, level, installPath, con
|
|
|
1613
1607
|
directories
|
|
1614
1608
|
};
|
|
1615
1609
|
}
|
|
1616
|
-
function isSymlink(path) {
|
|
1617
|
-
try {
|
|
1618
|
-
return lstatSync(path).isSymbolicLink();
|
|
1619
|
-
} catch {
|
|
1620
|
-
return false;
|
|
1621
|
-
}
|
|
1622
|
-
}
|
|
1623
1610
|
function getSkillRecordPath() {
|
|
1624
1611
|
return join9(getInstallsDir(), "skills.json");
|
|
1625
1612
|
}
|
|
@@ -1690,9 +1677,6 @@ function getInstalledSkills(tool, level, installPath) {
|
|
|
1690
1677
|
// src/core/backup.ts
|
|
1691
1678
|
import { existsSync as existsSync10, copyFileSync, readdirSync as readdirSync3, unlinkSync as unlinkSync3 } from "fs";
|
|
1692
1679
|
import { join as join10 } from "path";
|
|
1693
|
-
function getAgentsFileName(tool) {
|
|
1694
|
-
return tool === "claude" ? "CLAUDE.md" : "AGENTS.md";
|
|
1695
|
-
}
|
|
1696
1680
|
function detectCurrentPlugin(configRoot, tool) {
|
|
1697
1681
|
const manifest = readManifest(configRoot);
|
|
1698
1682
|
if (manifest?.team) {
|
|
@@ -1801,20 +1785,9 @@ function formatTimestamp(date) {
|
|
|
1801
1785
|
}
|
|
1802
1786
|
function readAllRecords() {
|
|
1803
1787
|
const records = [];
|
|
1804
|
-
const plugins =
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
"ops-registry-invoke",
|
|
1808
|
-
"pypto-op-orchestrator",
|
|
1809
|
-
"triton-op-generator",
|
|
1810
|
-
"tilelang-op-orchestrator",
|
|
1811
|
-
"model-infer-optimize",
|
|
1812
|
-
"catlass-op-generator",
|
|
1813
|
-
"ops-code-reviewer",
|
|
1814
|
-
"torch-compile"
|
|
1815
|
-
];
|
|
1816
|
-
for (const pluginId of plugins) {
|
|
1817
|
-
const record = readRecord(pluginId);
|
|
1788
|
+
const plugins = getAllPlugins();
|
|
1789
|
+
for (const plugin of plugins) {
|
|
1790
|
+
const record = readRecord(plugin.id);
|
|
1818
1791
|
if (record) {
|
|
1819
1792
|
records.push(record);
|
|
1820
1793
|
}
|
|
@@ -1869,7 +1842,7 @@ async function installPlugin(opts) {
|
|
|
1869
1842
|
pluginId: opts.pluginId,
|
|
1870
1843
|
skillsCount: 0,
|
|
1871
1844
|
agentsCount: 0,
|
|
1872
|
-
errors: [
|
|
1845
|
+
errors: [t("error_plugin_not_found") + ": " + opts.pluginId],
|
|
1873
1846
|
warnings: []
|
|
1874
1847
|
};
|
|
1875
1848
|
}
|
|
@@ -1880,7 +1853,7 @@ async function installPlugin(opts) {
|
|
|
1880
1853
|
pluginId: opts.pluginId,
|
|
1881
1854
|
skillsCount: 0,
|
|
1882
1855
|
agentsCount: 0,
|
|
1883
|
-
errors: [
|
|
1856
|
+
errors: [t("error_script_not_found").replace("{path}", scriptPath)],
|
|
1884
1857
|
warnings: []
|
|
1885
1858
|
};
|
|
1886
1859
|
}
|
|
@@ -1890,7 +1863,7 @@ async function installPlugin(opts) {
|
|
|
1890
1863
|
}
|
|
1891
1864
|
const cwd = opts.installPath || process.cwd();
|
|
1892
1865
|
const configRoot = getConfigRoot(opts.tool, opts.level, opts.installPath);
|
|
1893
|
-
const agentsFile = join11(configRoot,
|
|
1866
|
+
const agentsFile = join11(configRoot, getAgentsFileName2(opts.tool));
|
|
1894
1867
|
let backupInfo = null;
|
|
1895
1868
|
if (existsSync11(agentsFile)) {
|
|
1896
1869
|
const currentPlugin = detectCurrentPlugin(configRoot, opts.tool);
|
|
@@ -1934,13 +1907,14 @@ async function installPlugin(opts) {
|
|
|
1934
1907
|
}
|
|
1935
1908
|
}
|
|
1936
1909
|
try {
|
|
1910
|
+
const shell = process.platform === "win32" ? "sh" : "bash";
|
|
1937
1911
|
const execOptions = {
|
|
1938
1912
|
cwd,
|
|
1939
1913
|
timeout: 3e5,
|
|
1940
1914
|
stdio: "pipe",
|
|
1941
1915
|
input: opts.yes ? "y\n" : void 0
|
|
1942
1916
|
};
|
|
1943
|
-
await execa3(
|
|
1917
|
+
await execa3(shell, [scriptPath, ...args], execOptions);
|
|
1944
1918
|
const manifest = readManifest(configRoot);
|
|
1945
1919
|
let skillsCount = 0;
|
|
1946
1920
|
let agentsCount = 0;
|
|
@@ -1982,7 +1956,7 @@ async function installPlugin(opts) {
|
|
|
1982
1956
|
warnings: []
|
|
1983
1957
|
};
|
|
1984
1958
|
} catch (error) {
|
|
1985
|
-
const errorMessage = error instanceof Error ? error.message : "
|
|
1959
|
+
const errorMessage = error instanceof Error ? error.message : t("error_unknown");
|
|
1986
1960
|
return {
|
|
1987
1961
|
success: false,
|
|
1988
1962
|
pluginId: opts.pluginId,
|
|
@@ -1995,7 +1969,7 @@ async function installPlugin(opts) {
|
|
|
1995
1969
|
}
|
|
1996
1970
|
|
|
1997
1971
|
// src/core/skill-installer.ts
|
|
1998
|
-
import { existsSync as existsSync12, mkdirSync as mkdirSync5, symlinkSync, unlinkSync as unlinkSync4, readdirSync as readdirSync4, rmdirSync, realpathSync
|
|
1972
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync5, symlinkSync, unlinkSync as unlinkSync4, readdirSync as readdirSync4, rmdirSync, realpathSync } from "fs";
|
|
1999
1973
|
import { join as join12, dirname as dirname6 } from "path";
|
|
2000
1974
|
import { select as select3, checkbox as checkbox2, Separator as Separator2 } from "@inquirer/prompts";
|
|
2001
1975
|
import chalk5 from "chalk";
|
|
@@ -2012,25 +1986,29 @@ async function installSkills(skillIds, tool, level, repoPath) {
|
|
|
2012
1986
|
for (const skillId of skillIds) {
|
|
2013
1987
|
const skill = findSkill(skillId);
|
|
2014
1988
|
if (!skill) {
|
|
2015
|
-
results.push({ skillId, success: false, error: "
|
|
1989
|
+
results.push({ skillId, success: false, error: t("error_skill_not_found") });
|
|
2016
1990
|
continue;
|
|
2017
1991
|
}
|
|
2018
1992
|
const sourcePath = resolveSkillSourcePath(skill, repoPath);
|
|
2019
1993
|
const targetPath = join12(skillsDir, skillId);
|
|
2020
1994
|
if (!existsSync12(sourcePath)) {
|
|
2021
|
-
results.push({ skillId, success: false, error:
|
|
1995
|
+
results.push({ skillId, success: false, error: t("error_source_not_found").replace("{path}", sourcePath) });
|
|
2022
1996
|
continue;
|
|
2023
1997
|
}
|
|
2024
1998
|
try {
|
|
2025
1999
|
const resolvedSource = realpathSync(sourcePath);
|
|
2026
|
-
if (existsSync12(targetPath) ||
|
|
2000
|
+
if (existsSync12(targetPath) || isSymlink(targetPath)) {
|
|
2027
2001
|
unlinkSync4(targetPath);
|
|
2028
2002
|
}
|
|
2029
2003
|
symlinkSync(resolvedSource, targetPath);
|
|
2030
2004
|
results.push({ skillId, success: true });
|
|
2031
2005
|
installedIds.push(skillId);
|
|
2032
2006
|
} catch (error) {
|
|
2033
|
-
|
|
2007
|
+
let msg = error instanceof Error ? error.message : t("error_unknown");
|
|
2008
|
+
if (process.platform === "win32" && msg.includes("EPERM")) {
|
|
2009
|
+
msg = t("error_symlink_windows");
|
|
2010
|
+
}
|
|
2011
|
+
results.push({ skillId, success: false, error: msg });
|
|
2034
2012
|
}
|
|
2035
2013
|
}
|
|
2036
2014
|
if (installedIds.length > 0) {
|
|
@@ -2047,17 +2025,17 @@ async function uninstallSkills(skillIds, tool, level) {
|
|
|
2047
2025
|
for (const skillId of skillIds) {
|
|
2048
2026
|
const targetPath = join12(skillsDir, skillId);
|
|
2049
2027
|
try {
|
|
2050
|
-
if (existsSync12(targetPath) ||
|
|
2028
|
+
if (existsSync12(targetPath) || isSymlink(targetPath)) {
|
|
2051
2029
|
unlinkSync4(targetPath);
|
|
2052
2030
|
results.push({ skillId, success: true });
|
|
2053
2031
|
removedIds.push(skillId);
|
|
2054
2032
|
logger.step(` ${t("uninstall_remove_label")}: ${skillId}`);
|
|
2055
2033
|
} else {
|
|
2056
|
-
results.push({ skillId, success: false, error: "
|
|
2034
|
+
results.push({ skillId, success: false, error: t("error_not_installed") });
|
|
2057
2035
|
logger.warn(`${skillId} ${t("uninstall_skill_not_installed")}`);
|
|
2058
2036
|
}
|
|
2059
2037
|
} catch (error) {
|
|
2060
|
-
results.push({ skillId, success: false, error: error instanceof Error ? error.message : "
|
|
2038
|
+
results.push({ skillId, success: false, error: error instanceof Error ? error.message : t("error_unknown") });
|
|
2061
2039
|
}
|
|
2062
2040
|
}
|
|
2063
2041
|
if (removedIds.length > 0) {
|
|
@@ -2079,8 +2057,6 @@ var SELECT_ALL = "__select_all__";
|
|
|
2079
2057
|
var SELECT_ALL_CATEGORY = "__select_all_category__";
|
|
2080
2058
|
var CONTINUE_SELECT = "__continue_select__";
|
|
2081
2059
|
async function interactiveSkillSelect(tool, level) {
|
|
2082
|
-
const BACK3 = "__back__";
|
|
2083
|
-
const CANCEL3 = "__cancel__";
|
|
2084
2060
|
const categories = getAllCategories();
|
|
2085
2061
|
const allSkillIds = getAllSkills().map((s) => s.id);
|
|
2086
2062
|
let accumulated = [];
|
|
@@ -2103,8 +2079,8 @@ async function interactiveSkillSelect(tool, level) {
|
|
|
2103
2079
|
})),
|
|
2104
2080
|
new Separator2("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
|
|
2105
2081
|
...accumulated.length > 0 ? [{ name: `>> ${t("skill_confirm_install_count").replace("{count}", String(accumulated.length))}`, value: "install" }] : [],
|
|
2106
|
-
{ name: "<- " + t("wizard_back"), value:
|
|
2107
|
-
{ name: "x " + t("wizard_cancel"), value:
|
|
2082
|
+
{ name: "<- " + t("wizard_back"), value: BACK },
|
|
2083
|
+
{ name: "x " + t("wizard_cancel"), value: CANCEL }
|
|
2108
2084
|
];
|
|
2109
2085
|
showOperationHints();
|
|
2110
2086
|
selectedCategoryId = await select3({
|
|
@@ -2114,8 +2090,8 @@ async function interactiveSkillSelect(tool, level) {
|
|
|
2114
2090
|
theme: selectTheme,
|
|
2115
2091
|
pageSize: 15
|
|
2116
2092
|
});
|
|
2117
|
-
if (selectedCategoryId ===
|
|
2118
|
-
if (selectedCategoryId ===
|
|
2093
|
+
if (selectedCategoryId === BACK) return "back";
|
|
2094
|
+
if (selectedCategoryId === CANCEL) return "cancel";
|
|
2119
2095
|
if (selectedCategoryId === SELECT_ALL) {
|
|
2120
2096
|
return allSkillIds;
|
|
2121
2097
|
}
|
|
@@ -2255,13 +2231,6 @@ function resolveSkillSourcePath(skill, repoPath) {
|
|
|
2255
2231
|
}
|
|
2256
2232
|
return join12(repoPath, skill.source, skill.id);
|
|
2257
2233
|
}
|
|
2258
|
-
function isSymlink2(path) {
|
|
2259
|
-
try {
|
|
2260
|
-
return lstatSync2(path).isSymbolicLink();
|
|
2261
|
-
} catch {
|
|
2262
|
-
return false;
|
|
2263
|
-
}
|
|
2264
|
-
}
|
|
2265
2234
|
|
|
2266
2235
|
// src/ui/display.ts
|
|
2267
2236
|
import chalk6 from "chalk";
|
|
@@ -2354,8 +2323,6 @@ function printEnhancedSummary(results, tool, configRoot) {
|
|
|
2354
2323
|
// src/commands/init.ts
|
|
2355
2324
|
import { existsSync as existsSync13, readFileSync as readFileSync8 } from "fs";
|
|
2356
2325
|
import { join as join13 } from "path";
|
|
2357
|
-
var BACK2 = "__back__";
|
|
2358
|
-
var CANCEL2 = "__cancel__";
|
|
2359
2326
|
async function initCommand() {
|
|
2360
2327
|
const cwd = process.cwd();
|
|
2361
2328
|
if (existsSync13(join13(cwd, "package.json")) && (() => {
|
|
@@ -2414,7 +2381,6 @@ async function initCommand() {
|
|
|
2414
2381
|
}
|
|
2415
2382
|
async function selectMode() {
|
|
2416
2383
|
printBoxTitle(t("wizard_select_mode_title"));
|
|
2417
|
-
const CANCEL3 = "__cancel__";
|
|
2418
2384
|
const choices = [
|
|
2419
2385
|
{
|
|
2420
2386
|
name: `> ${t("wizard_mode_plugin")} \u2014 ${t("wizard_mode_plugin_desc")}`,
|
|
@@ -2425,7 +2391,7 @@ async function selectMode() {
|
|
|
2425
2391
|
value: "skill"
|
|
2426
2392
|
},
|
|
2427
2393
|
new Separator3("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
|
|
2428
|
-
{ name: "x " + t("wizard_cancel"), value:
|
|
2394
|
+
{ name: "x " + t("wizard_cancel"), value: CANCEL }
|
|
2429
2395
|
];
|
|
2430
2396
|
showOperationHints();
|
|
2431
2397
|
const result = await select4({
|
|
@@ -2434,7 +2400,7 @@ async function selectMode() {
|
|
|
2434
2400
|
loop: false,
|
|
2435
2401
|
theme: selectTheme
|
|
2436
2402
|
});
|
|
2437
|
-
if (result ===
|
|
2403
|
+
if (result === CANCEL) return null;
|
|
2438
2404
|
return result;
|
|
2439
2405
|
}
|
|
2440
2406
|
async function pluginInstallFlow() {
|
|
@@ -2511,11 +2477,11 @@ async function skillInstallFlow() {
|
|
|
2511
2477
|
}
|
|
2512
2478
|
case 1: {
|
|
2513
2479
|
const result = await stepLevel();
|
|
2514
|
-
if (result ===
|
|
2480
|
+
if (result === BACK) {
|
|
2515
2481
|
step = 0;
|
|
2516
2482
|
break;
|
|
2517
2483
|
}
|
|
2518
|
-
if (result ===
|
|
2484
|
+
if (result === CANCEL) {
|
|
2519
2485
|
logger.info(t("init_cancelled"));
|
|
2520
2486
|
return "done";
|
|
2521
2487
|
}
|
|
@@ -2586,13 +2552,12 @@ async function listCommand() {
|
|
|
2586
2552
|
|
|
2587
2553
|
// src/commands/doctor.ts
|
|
2588
2554
|
import chalk8 from "chalk";
|
|
2589
|
-
import { existsSync as existsSync14, readdirSync as readdirSync5, lstatSync as
|
|
2555
|
+
import { existsSync as existsSync14, readdirSync as readdirSync5, lstatSync as lstatSync2, unlinkSync as unlinkSync5, mkdirSync as mkdirSync6 } from "fs";
|
|
2590
2556
|
import { join as join14 } from "path";
|
|
2591
2557
|
async function doctorCommand(options = {}) {
|
|
2592
2558
|
console.log();
|
|
2593
2559
|
console.log(chalk8.bold(` ${t("doctor_title")}`));
|
|
2594
2560
|
console.log(chalk8.dim(" " + "\u2500".repeat(46)));
|
|
2595
|
-
let errors = 0;
|
|
2596
2561
|
let warnings = 0;
|
|
2597
2562
|
let fixes = 0;
|
|
2598
2563
|
console.log();
|
|
@@ -2687,11 +2652,11 @@ async function doctorCommand(options = {}) {
|
|
|
2687
2652
|
console.log(chalk8.dim(" " + "\u2500".repeat(46)));
|
|
2688
2653
|
if (options.fix && fixes > 0) {
|
|
2689
2654
|
console.log(
|
|
2690
|
-
` ${t("doctor_result")}: ${t("doctor_result_with_fix").replace("{warnings}", String(warnings)).replace("{
|
|
2655
|
+
` ${t("doctor_result")}: ${t("doctor_result_with_fix").replace("{warnings}", String(warnings)).replace("{fixes}", String(fixes))}`
|
|
2691
2656
|
);
|
|
2692
2657
|
} else {
|
|
2693
2658
|
console.log(
|
|
2694
|
-
` ${t("doctor_result")}: ${t("doctor_result_without_fix").replace("{warnings}", String(warnings))
|
|
2659
|
+
` ${t("doctor_result")}: ${t("doctor_result_without_fix").replace("{warnings}", String(warnings))}`
|
|
2695
2660
|
);
|
|
2696
2661
|
}
|
|
2697
2662
|
console.log();
|
|
@@ -2703,7 +2668,7 @@ function checkBrokenLinks(dir) {
|
|
|
2703
2668
|
for (const entry of entries) {
|
|
2704
2669
|
const fullPath = join14(dir, entry);
|
|
2705
2670
|
try {
|
|
2706
|
-
const stats =
|
|
2671
|
+
const stats = lstatSync2(fullPath);
|
|
2707
2672
|
if (stats.isSymbolicLink()) {
|
|
2708
2673
|
if (!existsSync14(fullPath)) {
|
|
2709
2674
|
broken++;
|
|
@@ -2724,7 +2689,7 @@ function fixBrokenLinks(dir) {
|
|
|
2724
2689
|
for (const entry of entries) {
|
|
2725
2690
|
const fullPath = join14(dir, entry);
|
|
2726
2691
|
try {
|
|
2727
|
-
const stats =
|
|
2692
|
+
const stats = lstatSync2(fullPath);
|
|
2728
2693
|
if (stats.isSymbolicLink()) {
|
|
2729
2694
|
if (!existsSync14(fullPath)) {
|
|
2730
2695
|
unlinkSync5(fullPath);
|
|
@@ -2742,7 +2707,6 @@ function fixBrokenLinks(dir) {
|
|
|
2742
2707
|
// src/commands/status.ts
|
|
2743
2708
|
import chalk9 from "chalk";
|
|
2744
2709
|
async function statusCommand() {
|
|
2745
|
-
const plugins = getAllPlugins();
|
|
2746
2710
|
const installed = scanInstalled();
|
|
2747
2711
|
const installedMap = new Map(installed.map((p) => [p.id, p]));
|
|
2748
2712
|
console.log();
|
|
@@ -3073,8 +3037,8 @@ async function installPlugins(pluginIds, tool, level, repoPath, installPath, yes
|
|
|
3073
3037
|
}
|
|
3074
3038
|
|
|
3075
3039
|
// src/commands/uninstall.ts
|
|
3076
|
-
import { existsSync as existsSync15, unlinkSync as unlinkSync6, rmdirSync as rmdirSync2, readdirSync as readdirSync6
|
|
3077
|
-
import { resolve } from "path";
|
|
3040
|
+
import { existsSync as existsSync15, unlinkSync as unlinkSync6, rmdirSync as rmdirSync2, readdirSync as readdirSync6 } from "fs";
|
|
3041
|
+
import { resolve, basename } from "path";
|
|
3078
3042
|
import chalk11 from "chalk";
|
|
3079
3043
|
async function uninstallCommand(names, options) {
|
|
3080
3044
|
const tool = options.tool ? validateTool(options.tool) : "opencode";
|
|
@@ -3115,9 +3079,9 @@ async function uninstallCommand(names, options) {
|
|
|
3115
3079
|
for (const filePath of record.files) {
|
|
3116
3080
|
if (!isSafePath(filePath)) continue;
|
|
3117
3081
|
try {
|
|
3118
|
-
if (existsSync15(filePath) ||
|
|
3082
|
+
if (existsSync15(filePath) || isSymlink(filePath)) {
|
|
3119
3083
|
unlinkSync6(filePath);
|
|
3120
|
-
const name = filePath
|
|
3084
|
+
const name = basename(filePath);
|
|
3121
3085
|
logger.step(` ${t("uninstall_remove_label")}: ${name}`);
|
|
3122
3086
|
removedFiles++;
|
|
3123
3087
|
}
|
|
@@ -3134,7 +3098,7 @@ async function uninstallCommand(names, options) {
|
|
|
3134
3098
|
const entries = readdirSync6(dirPath);
|
|
3135
3099
|
if (entries.length === 0) {
|
|
3136
3100
|
rmdirSync2(dirPath);
|
|
3137
|
-
const name = dirPath
|
|
3101
|
+
const name = basename(dirPath);
|
|
3138
3102
|
logger.step(` ${t("uninstall_clean_empty_dir")}: ${name}/`);
|
|
3139
3103
|
removedDirs++;
|
|
3140
3104
|
}
|
|
@@ -3163,7 +3127,7 @@ async function uninstallCommand(names, options) {
|
|
|
3163
3127
|
}
|
|
3164
3128
|
const totalRemoved = removedFiles + removedDirs;
|
|
3165
3129
|
if (totalRemoved > 0) {
|
|
3166
|
-
logger.success(
|
|
3130
|
+
logger.success(t("uninstall_summary_format").replace("{name}", plugin.displayName).replace("{files}", String(removedFiles)).replace("{dirs}", String(removedDirs)));
|
|
3167
3131
|
} else {
|
|
3168
3132
|
logger.warn(`${plugin.displayName}${t("uninstall_files_gone")}`);
|
|
3169
3133
|
}
|
|
@@ -3185,13 +3149,6 @@ async function uninstallCommand(names, options) {
|
|
|
3185
3149
|
logger.blank();
|
|
3186
3150
|
}
|
|
3187
3151
|
}
|
|
3188
|
-
function isSymlink3(path) {
|
|
3189
|
-
try {
|
|
3190
|
-
return lstatSync4(path).isSymbolicLink();
|
|
3191
|
-
} catch {
|
|
3192
|
-
return false;
|
|
3193
|
-
}
|
|
3194
|
-
}
|
|
3195
3152
|
|
|
3196
3153
|
// src/commands/update.ts
|
|
3197
3154
|
import chalk12 from "chalk";
|
|
@@ -3360,13 +3317,27 @@ async function langCommand(action, value) {
|
|
|
3360
3317
|
}
|
|
3361
3318
|
|
|
3362
3319
|
// src/cli.ts
|
|
3320
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
3321
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
3322
|
+
import { dirname as dirname7, join as join16 } from "path";
|
|
3323
|
+
function readVersion() {
|
|
3324
|
+
try {
|
|
3325
|
+
const __filename5 = fileURLToPath5(import.meta.url);
|
|
3326
|
+
const __dirname5 = dirname7(__filename5);
|
|
3327
|
+
const pkgPath = join16(__dirname5, "..", "package.json");
|
|
3328
|
+
const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
|
|
3329
|
+
return pkg.version || "0.0.0";
|
|
3330
|
+
} catch {
|
|
3331
|
+
return "0.0.0";
|
|
3332
|
+
}
|
|
3333
|
+
}
|
|
3363
3334
|
function createCLI() {
|
|
3364
3335
|
const config = readConfig();
|
|
3365
3336
|
if (config.language) {
|
|
3366
3337
|
setLanguage(config.language);
|
|
3367
3338
|
}
|
|
3368
3339
|
const program2 = new Command();
|
|
3369
|
-
program2.name("install-helper").description("CANNBot Install Helper - Interactive installer for CANN operator development skills").version(
|
|
3340
|
+
program2.name("install-helper").description("CANNBot Install Helper - Interactive installer for CANN operator development skills").version(readVersion());
|
|
3370
3341
|
program2.command("init", { isDefault: false }).description("Run interactive installation wizard").action(async () => {
|
|
3371
3342
|
await initCommand();
|
|
3372
3343
|
});
|