@cannbot-ai/install-helper 0.0.2-beta.34 → 0.0.2-beta.35
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 +176 -211
- package/dist/index.js.map +1 -1
- package/dist/locales/en_US.json +8 -9
- package/dist/locales/zh_CN.json +8 -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(
|
|
@@ -431,7 +504,7 @@ function getToolDisplayName(tool) {
|
|
|
431
504
|
return names[tool];
|
|
432
505
|
}
|
|
433
506
|
function getAllTools() {
|
|
434
|
-
return
|
|
507
|
+
return VALID_TOOLS;
|
|
435
508
|
}
|
|
436
509
|
|
|
437
510
|
// src/core/manifest.ts
|
|
@@ -474,7 +547,7 @@ function readAllManifests(configRoot) {
|
|
|
474
547
|
function scanInstalled() {
|
|
475
548
|
const plugins = getAllPlugins();
|
|
476
549
|
const installed = [];
|
|
477
|
-
const tools =
|
|
550
|
+
const tools = VALID_TOOLS;
|
|
478
551
|
const levels = ["project", "global"];
|
|
479
552
|
for (const tool of tools) {
|
|
480
553
|
for (const level of levels) {
|
|
@@ -535,7 +608,6 @@ function verifyPluginFilesExist(configRoot, manifest, tool, level) {
|
|
|
535
608
|
// src/utils/config.ts
|
|
536
609
|
import { existsSync as existsSync6, mkdirSync, readFileSync as readFileSync4 } from "fs";
|
|
537
610
|
import { join as join6 } from "path";
|
|
538
|
-
import { homedir as homedir3 } from "os";
|
|
539
611
|
import { parse, stringify } from "yaml";
|
|
540
612
|
|
|
541
613
|
// src/utils/fs.ts
|
|
@@ -559,7 +631,7 @@ function atomicWriteFileSync(filePath, data, encoding = "utf-8") {
|
|
|
559
631
|
|
|
560
632
|
// src/utils/config.ts
|
|
561
633
|
function getConfigDir() {
|
|
562
|
-
return
|
|
634
|
+
return getCannbotConfigDir();
|
|
563
635
|
}
|
|
564
636
|
function getConfigPath() {
|
|
565
637
|
return join6(getConfigDir(), "config.yaml");
|
|
@@ -620,84 +692,11 @@ function removeInstalledPlugin(pluginId) {
|
|
|
620
692
|
writeConfig(config);
|
|
621
693
|
}
|
|
622
694
|
|
|
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
|
|
695
|
+
// src/utils/constants.ts
|
|
699
696
|
var BACK = "__back__";
|
|
700
697
|
var CANCEL = "__cancel__";
|
|
698
|
+
|
|
699
|
+
// src/ui/wizard.ts
|
|
701
700
|
async function selectToolWithDetection() {
|
|
702
701
|
const config = readConfig();
|
|
703
702
|
logger.blank();
|
|
@@ -781,7 +780,7 @@ async function stepTool(detectedTools, lastTool) {
|
|
|
781
780
|
if (detectedTools.length === 0) {
|
|
782
781
|
logger.error(t("error_tool_not_found"));
|
|
783
782
|
const choices2 = [
|
|
784
|
-
...
|
|
783
|
+
...VALID_TOOLS.map((tool) => ({
|
|
785
784
|
name: `> ${getToolDisplayName(tool)}`,
|
|
786
785
|
value: tool
|
|
787
786
|
})),
|
|
@@ -950,7 +949,7 @@ import { execa as execa2 } from "execa";
|
|
|
950
949
|
import { parse as parseYaml3 } from "yaml";
|
|
951
950
|
|
|
952
951
|
// src/core/scanner.ts
|
|
953
|
-
import { existsSync as existsSync7, readdirSync as readdirSync2, readFileSync as readFileSync5,
|
|
952
|
+
import { existsSync as existsSync7, readdirSync as readdirSync2, readFileSync as readFileSync5, mkdirSync as mkdirSync2 } from "fs";
|
|
954
953
|
import { join as join7, dirname as dirname4 } from "path";
|
|
955
954
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
956
955
|
import { parse as parseYaml2 } from "yaml";
|
|
@@ -1007,7 +1006,7 @@ function scanSkills(repoPath) {
|
|
|
1007
1006
|
if (!existsSync7(pluginParent)) continue;
|
|
1008
1007
|
for (const plugin of safeReaddir(pluginParent)) {
|
|
1009
1008
|
const pluginPath = join7(pluginParent, plugin);
|
|
1010
|
-
if (!
|
|
1009
|
+
if (!isDirectory(pluginPath)) continue;
|
|
1011
1010
|
const skillsDir = join7(pluginPath, "skills");
|
|
1012
1011
|
if (existsSync7(skillsDir)) {
|
|
1013
1012
|
scanDirectory(skillsDir, repoPath, `${pluginDir}/${plugin}/skills`, skills, seen);
|
|
@@ -1123,7 +1122,7 @@ function scanDirectory(dirPath, repoPath, sourcePrefix, skills, seen) {
|
|
|
1123
1122
|
for (const entry of safeReaddir(dirPath)) {
|
|
1124
1123
|
const fullPath = join7(dirPath, entry);
|
|
1125
1124
|
if (EXCLUDE_DIRS.has(entry)) continue;
|
|
1126
|
-
if (!
|
|
1125
|
+
if (!isDirectory(fullPath)) continue;
|
|
1127
1126
|
const skillMd = join7(fullPath, "SKILL.md");
|
|
1128
1127
|
if (existsSync7(skillMd)) {
|
|
1129
1128
|
const frontmatter = parseFrontmatter(skillMd);
|
|
@@ -1148,29 +1147,22 @@ function safeReaddir(dir) {
|
|
|
1148
1147
|
return [];
|
|
1149
1148
|
}
|
|
1150
1149
|
}
|
|
1151
|
-
function isDirectory2(path) {
|
|
1152
|
-
try {
|
|
1153
|
-
return statSync2(path).isDirectory();
|
|
1154
|
-
} catch {
|
|
1155
|
-
return false;
|
|
1156
|
-
}
|
|
1157
|
-
}
|
|
1158
1150
|
|
|
1159
1151
|
// src/core/skill-registry.ts
|
|
1160
1152
|
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" }
|
|
1153
|
+
{ id: "knowledge", name: "\u77E5\u8BC6\u4E0E\u53C2\u8003", nameEn: "Knowledge & Reference" },
|
|
1154
|
+
{ id: "env-tools", name: "\u73AF\u5883\u4E0E\u5DE5\u5177", nameEn: "Environment & Tools" },
|
|
1155
|
+
{ id: "debug", name: "\u8C03\u8BD5\u4E0E\u8BCA\u65AD", nameEn: "Debug & Diagnostics" },
|
|
1156
|
+
{ id: "testing", name: "\u6D4B\u8BD5\u4E0E\u8D28\u91CF", nameEn: "Testing & Quality" },
|
|
1157
|
+
{ id: "ascendc", name: "AscendC \u5F00\u53D1", nameEn: "AscendC Development" },
|
|
1158
|
+
{ id: "pypto", name: "PyPTO \u5F00\u53D1", nameEn: "PyPTO Development" },
|
|
1159
|
+
{ id: "tilelang", name: "TileLang \u5F00\u53D1", nameEn: "TileLang Development" },
|
|
1160
|
+
{ id: "triton", name: "Triton \u5F00\u53D1", nameEn: "Triton Development" },
|
|
1161
|
+
{ id: "model", name: "\u6A21\u578B\u63A8\u7406\u4F18\u5316", nameEn: "Model Inference Optimization" },
|
|
1162
|
+
{ id: "runtime", name: "Runtime \u8FC1\u79FB", nameEn: "Runtime Migration" },
|
|
1163
|
+
{ id: "graph", name: "\u56FE\u6A21\u5F0F", nameEn: "Graph Mode" },
|
|
1164
|
+
{ id: "platform", name: "\u5E73\u53F0\u5DE5\u5177", nameEn: "Platform Tools" },
|
|
1165
|
+
{ id: "other", name: "\u5176\u4ED6 Skills", nameEn: "Other Skills" }
|
|
1174
1166
|
];
|
|
1175
1167
|
var dynamicSkills = [];
|
|
1176
1168
|
var initialized = false;
|
|
@@ -1380,9 +1372,10 @@ function getAllSkills() {
|
|
|
1380
1372
|
}
|
|
1381
1373
|
function getAllCategories() {
|
|
1382
1374
|
const skills = getActiveSkills();
|
|
1375
|
+
const isEn = t("list_name") === "Name";
|
|
1383
1376
|
return CATEGORY_DEFS.map((def) => ({
|
|
1384
1377
|
id: def.id,
|
|
1385
|
-
name: def.name,
|
|
1378
|
+
name: isEn ? def.nameEn : def.name,
|
|
1386
1379
|
skills: skills.filter((s) => {
|
|
1387
1380
|
const catId = CATEGORY_MAP[s.id];
|
|
1388
1381
|
if (catId) return catId === def.id;
|
|
@@ -1510,7 +1503,7 @@ import { join as join11 } from "path";
|
|
|
1510
1503
|
import { execa as execa3 } from "execa";
|
|
1511
1504
|
|
|
1512
1505
|
// src/core/record.ts
|
|
1513
|
-
import { existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync7,
|
|
1506
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync7, unlinkSync as unlinkSync2 } from "fs";
|
|
1514
1507
|
import { join as join9 } from "path";
|
|
1515
1508
|
function getInstallsDir() {
|
|
1516
1509
|
return join9(getCannbotConfigDir(), "installs");
|
|
@@ -1613,13 +1606,6 @@ function scanInstalledFiles(pluginId, displayName, tool, level, installPath, con
|
|
|
1613
1606
|
directories
|
|
1614
1607
|
};
|
|
1615
1608
|
}
|
|
1616
|
-
function isSymlink(path) {
|
|
1617
|
-
try {
|
|
1618
|
-
return lstatSync(path).isSymbolicLink();
|
|
1619
|
-
} catch {
|
|
1620
|
-
return false;
|
|
1621
|
-
}
|
|
1622
|
-
}
|
|
1623
1609
|
function getSkillRecordPath() {
|
|
1624
1610
|
return join9(getInstallsDir(), "skills.json");
|
|
1625
1611
|
}
|
|
@@ -1690,9 +1676,6 @@ function getInstalledSkills(tool, level, installPath) {
|
|
|
1690
1676
|
// src/core/backup.ts
|
|
1691
1677
|
import { existsSync as existsSync10, copyFileSync, readdirSync as readdirSync3, unlinkSync as unlinkSync3 } from "fs";
|
|
1692
1678
|
import { join as join10 } from "path";
|
|
1693
|
-
function getAgentsFileName(tool) {
|
|
1694
|
-
return tool === "claude" ? "CLAUDE.md" : "AGENTS.md";
|
|
1695
|
-
}
|
|
1696
1679
|
function detectCurrentPlugin(configRoot, tool) {
|
|
1697
1680
|
const manifest = readManifest(configRoot);
|
|
1698
1681
|
if (manifest?.team) {
|
|
@@ -1801,20 +1784,9 @@ function formatTimestamp(date) {
|
|
|
1801
1784
|
}
|
|
1802
1785
|
function readAllRecords() {
|
|
1803
1786
|
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);
|
|
1787
|
+
const plugins = getAllPlugins();
|
|
1788
|
+
for (const plugin of plugins) {
|
|
1789
|
+
const record = readRecord(plugin.id);
|
|
1818
1790
|
if (record) {
|
|
1819
1791
|
records.push(record);
|
|
1820
1792
|
}
|
|
@@ -1869,7 +1841,7 @@ async function installPlugin(opts) {
|
|
|
1869
1841
|
pluginId: opts.pluginId,
|
|
1870
1842
|
skillsCount: 0,
|
|
1871
1843
|
agentsCount: 0,
|
|
1872
|
-
errors: [
|
|
1844
|
+
errors: [t("error_plugin_not_found") + ": " + opts.pluginId],
|
|
1873
1845
|
warnings: []
|
|
1874
1846
|
};
|
|
1875
1847
|
}
|
|
@@ -1880,7 +1852,7 @@ async function installPlugin(opts) {
|
|
|
1880
1852
|
pluginId: opts.pluginId,
|
|
1881
1853
|
skillsCount: 0,
|
|
1882
1854
|
agentsCount: 0,
|
|
1883
|
-
errors: [
|
|
1855
|
+
errors: [t("error_script_not_found").replace("{path}", scriptPath)],
|
|
1884
1856
|
warnings: []
|
|
1885
1857
|
};
|
|
1886
1858
|
}
|
|
@@ -1890,7 +1862,7 @@ async function installPlugin(opts) {
|
|
|
1890
1862
|
}
|
|
1891
1863
|
const cwd = opts.installPath || process.cwd();
|
|
1892
1864
|
const configRoot = getConfigRoot(opts.tool, opts.level, opts.installPath);
|
|
1893
|
-
const agentsFile = join11(configRoot,
|
|
1865
|
+
const agentsFile = join11(configRoot, getAgentsFileName2(opts.tool));
|
|
1894
1866
|
let backupInfo = null;
|
|
1895
1867
|
if (existsSync11(agentsFile)) {
|
|
1896
1868
|
const currentPlugin = detectCurrentPlugin(configRoot, opts.tool);
|
|
@@ -1982,7 +1954,7 @@ async function installPlugin(opts) {
|
|
|
1982
1954
|
warnings: []
|
|
1983
1955
|
};
|
|
1984
1956
|
} catch (error) {
|
|
1985
|
-
const errorMessage = error instanceof Error ? error.message : "
|
|
1957
|
+
const errorMessage = error instanceof Error ? error.message : t("error_unknown");
|
|
1986
1958
|
return {
|
|
1987
1959
|
success: false,
|
|
1988
1960
|
pluginId: opts.pluginId,
|
|
@@ -1995,7 +1967,7 @@ async function installPlugin(opts) {
|
|
|
1995
1967
|
}
|
|
1996
1968
|
|
|
1997
1969
|
// src/core/skill-installer.ts
|
|
1998
|
-
import { existsSync as existsSync12, mkdirSync as mkdirSync5, symlinkSync, unlinkSync as unlinkSync4, readdirSync as readdirSync4, rmdirSync, realpathSync
|
|
1970
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync5, symlinkSync, unlinkSync as unlinkSync4, readdirSync as readdirSync4, rmdirSync, realpathSync } from "fs";
|
|
1999
1971
|
import { join as join12, dirname as dirname6 } from "path";
|
|
2000
1972
|
import { select as select3, checkbox as checkbox2, Separator as Separator2 } from "@inquirer/prompts";
|
|
2001
1973
|
import chalk5 from "chalk";
|
|
@@ -2012,25 +1984,25 @@ async function installSkills(skillIds, tool, level, repoPath) {
|
|
|
2012
1984
|
for (const skillId of skillIds) {
|
|
2013
1985
|
const skill = findSkill(skillId);
|
|
2014
1986
|
if (!skill) {
|
|
2015
|
-
results.push({ skillId, success: false, error: "
|
|
1987
|
+
results.push({ skillId, success: false, error: t("error_skill_not_found") });
|
|
2016
1988
|
continue;
|
|
2017
1989
|
}
|
|
2018
1990
|
const sourcePath = resolveSkillSourcePath(skill, repoPath);
|
|
2019
1991
|
const targetPath = join12(skillsDir, skillId);
|
|
2020
1992
|
if (!existsSync12(sourcePath)) {
|
|
2021
|
-
results.push({ skillId, success: false, error:
|
|
1993
|
+
results.push({ skillId, success: false, error: t("error_source_not_found").replace("{path}", sourcePath) });
|
|
2022
1994
|
continue;
|
|
2023
1995
|
}
|
|
2024
1996
|
try {
|
|
2025
1997
|
const resolvedSource = realpathSync(sourcePath);
|
|
2026
|
-
if (existsSync12(targetPath) ||
|
|
1998
|
+
if (existsSync12(targetPath) || isSymlink(targetPath)) {
|
|
2027
1999
|
unlinkSync4(targetPath);
|
|
2028
2000
|
}
|
|
2029
2001
|
symlinkSync(resolvedSource, targetPath);
|
|
2030
2002
|
results.push({ skillId, success: true });
|
|
2031
2003
|
installedIds.push(skillId);
|
|
2032
2004
|
} catch (error) {
|
|
2033
|
-
results.push({ skillId, success: false, error: error instanceof Error ? error.message : "
|
|
2005
|
+
results.push({ skillId, success: false, error: error instanceof Error ? error.message : t("error_unknown") });
|
|
2034
2006
|
}
|
|
2035
2007
|
}
|
|
2036
2008
|
if (installedIds.length > 0) {
|
|
@@ -2047,17 +2019,17 @@ async function uninstallSkills(skillIds, tool, level) {
|
|
|
2047
2019
|
for (const skillId of skillIds) {
|
|
2048
2020
|
const targetPath = join12(skillsDir, skillId);
|
|
2049
2021
|
try {
|
|
2050
|
-
if (existsSync12(targetPath) ||
|
|
2022
|
+
if (existsSync12(targetPath) || isSymlink(targetPath)) {
|
|
2051
2023
|
unlinkSync4(targetPath);
|
|
2052
2024
|
results.push({ skillId, success: true });
|
|
2053
2025
|
removedIds.push(skillId);
|
|
2054
2026
|
logger.step(` ${t("uninstall_remove_label")}: ${skillId}`);
|
|
2055
2027
|
} else {
|
|
2056
|
-
results.push({ skillId, success: false, error: "
|
|
2028
|
+
results.push({ skillId, success: false, error: t("error_not_installed") });
|
|
2057
2029
|
logger.warn(`${skillId} ${t("uninstall_skill_not_installed")}`);
|
|
2058
2030
|
}
|
|
2059
2031
|
} catch (error) {
|
|
2060
|
-
results.push({ skillId, success: false, error: error instanceof Error ? error.message : "
|
|
2032
|
+
results.push({ skillId, success: false, error: error instanceof Error ? error.message : t("error_unknown") });
|
|
2061
2033
|
}
|
|
2062
2034
|
}
|
|
2063
2035
|
if (removedIds.length > 0) {
|
|
@@ -2079,8 +2051,6 @@ var SELECT_ALL = "__select_all__";
|
|
|
2079
2051
|
var SELECT_ALL_CATEGORY = "__select_all_category__";
|
|
2080
2052
|
var CONTINUE_SELECT = "__continue_select__";
|
|
2081
2053
|
async function interactiveSkillSelect(tool, level) {
|
|
2082
|
-
const BACK3 = "__back__";
|
|
2083
|
-
const CANCEL3 = "__cancel__";
|
|
2084
2054
|
const categories = getAllCategories();
|
|
2085
2055
|
const allSkillIds = getAllSkills().map((s) => s.id);
|
|
2086
2056
|
let accumulated = [];
|
|
@@ -2103,8 +2073,8 @@ async function interactiveSkillSelect(tool, level) {
|
|
|
2103
2073
|
})),
|
|
2104
2074
|
new Separator2("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
|
|
2105
2075
|
...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:
|
|
2076
|
+
{ name: "<- " + t("wizard_back"), value: BACK },
|
|
2077
|
+
{ name: "x " + t("wizard_cancel"), value: CANCEL }
|
|
2108
2078
|
];
|
|
2109
2079
|
showOperationHints();
|
|
2110
2080
|
selectedCategoryId = await select3({
|
|
@@ -2114,8 +2084,8 @@ async function interactiveSkillSelect(tool, level) {
|
|
|
2114
2084
|
theme: selectTheme,
|
|
2115
2085
|
pageSize: 15
|
|
2116
2086
|
});
|
|
2117
|
-
if (selectedCategoryId ===
|
|
2118
|
-
if (selectedCategoryId ===
|
|
2087
|
+
if (selectedCategoryId === BACK) return "back";
|
|
2088
|
+
if (selectedCategoryId === CANCEL) return "cancel";
|
|
2119
2089
|
if (selectedCategoryId === SELECT_ALL) {
|
|
2120
2090
|
return allSkillIds;
|
|
2121
2091
|
}
|
|
@@ -2255,13 +2225,6 @@ function resolveSkillSourcePath(skill, repoPath) {
|
|
|
2255
2225
|
}
|
|
2256
2226
|
return join12(repoPath, skill.source, skill.id);
|
|
2257
2227
|
}
|
|
2258
|
-
function isSymlink2(path) {
|
|
2259
|
-
try {
|
|
2260
|
-
return lstatSync2(path).isSymbolicLink();
|
|
2261
|
-
} catch {
|
|
2262
|
-
return false;
|
|
2263
|
-
}
|
|
2264
|
-
}
|
|
2265
2228
|
|
|
2266
2229
|
// src/ui/display.ts
|
|
2267
2230
|
import chalk6 from "chalk";
|
|
@@ -2354,8 +2317,6 @@ function printEnhancedSummary(results, tool, configRoot) {
|
|
|
2354
2317
|
// src/commands/init.ts
|
|
2355
2318
|
import { existsSync as existsSync13, readFileSync as readFileSync8 } from "fs";
|
|
2356
2319
|
import { join as join13 } from "path";
|
|
2357
|
-
var BACK2 = "__back__";
|
|
2358
|
-
var CANCEL2 = "__cancel__";
|
|
2359
2320
|
async function initCommand() {
|
|
2360
2321
|
const cwd = process.cwd();
|
|
2361
2322
|
if (existsSync13(join13(cwd, "package.json")) && (() => {
|
|
@@ -2414,7 +2375,6 @@ async function initCommand() {
|
|
|
2414
2375
|
}
|
|
2415
2376
|
async function selectMode() {
|
|
2416
2377
|
printBoxTitle(t("wizard_select_mode_title"));
|
|
2417
|
-
const CANCEL3 = "__cancel__";
|
|
2418
2378
|
const choices = [
|
|
2419
2379
|
{
|
|
2420
2380
|
name: `> ${t("wizard_mode_plugin")} \u2014 ${t("wizard_mode_plugin_desc")}`,
|
|
@@ -2425,7 +2385,7 @@ async function selectMode() {
|
|
|
2425
2385
|
value: "skill"
|
|
2426
2386
|
},
|
|
2427
2387
|
new Separator3("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
|
|
2428
|
-
{ name: "x " + t("wizard_cancel"), value:
|
|
2388
|
+
{ name: "x " + t("wizard_cancel"), value: CANCEL }
|
|
2429
2389
|
];
|
|
2430
2390
|
showOperationHints();
|
|
2431
2391
|
const result = await select4({
|
|
@@ -2434,7 +2394,7 @@ async function selectMode() {
|
|
|
2434
2394
|
loop: false,
|
|
2435
2395
|
theme: selectTheme
|
|
2436
2396
|
});
|
|
2437
|
-
if (result ===
|
|
2397
|
+
if (result === CANCEL) return null;
|
|
2438
2398
|
return result;
|
|
2439
2399
|
}
|
|
2440
2400
|
async function pluginInstallFlow() {
|
|
@@ -2511,11 +2471,11 @@ async function skillInstallFlow() {
|
|
|
2511
2471
|
}
|
|
2512
2472
|
case 1: {
|
|
2513
2473
|
const result = await stepLevel();
|
|
2514
|
-
if (result ===
|
|
2474
|
+
if (result === BACK) {
|
|
2515
2475
|
step = 0;
|
|
2516
2476
|
break;
|
|
2517
2477
|
}
|
|
2518
|
-
if (result ===
|
|
2478
|
+
if (result === CANCEL) {
|
|
2519
2479
|
logger.info(t("init_cancelled"));
|
|
2520
2480
|
return "done";
|
|
2521
2481
|
}
|
|
@@ -2586,13 +2546,12 @@ async function listCommand() {
|
|
|
2586
2546
|
|
|
2587
2547
|
// src/commands/doctor.ts
|
|
2588
2548
|
import chalk8 from "chalk";
|
|
2589
|
-
import { existsSync as existsSync14, readdirSync as readdirSync5, lstatSync as
|
|
2549
|
+
import { existsSync as existsSync14, readdirSync as readdirSync5, lstatSync as lstatSync2, unlinkSync as unlinkSync5, mkdirSync as mkdirSync6 } from "fs";
|
|
2590
2550
|
import { join as join14 } from "path";
|
|
2591
2551
|
async function doctorCommand(options = {}) {
|
|
2592
2552
|
console.log();
|
|
2593
2553
|
console.log(chalk8.bold(` ${t("doctor_title")}`));
|
|
2594
2554
|
console.log(chalk8.dim(" " + "\u2500".repeat(46)));
|
|
2595
|
-
let errors = 0;
|
|
2596
2555
|
let warnings = 0;
|
|
2597
2556
|
let fixes = 0;
|
|
2598
2557
|
console.log();
|
|
@@ -2687,11 +2646,11 @@ async function doctorCommand(options = {}) {
|
|
|
2687
2646
|
console.log(chalk8.dim(" " + "\u2500".repeat(46)));
|
|
2688
2647
|
if (options.fix && fixes > 0) {
|
|
2689
2648
|
console.log(
|
|
2690
|
-
` ${t("doctor_result")}: ${t("doctor_result_with_fix").replace("{warnings}", String(warnings)).replace("{
|
|
2649
|
+
` ${t("doctor_result")}: ${t("doctor_result_with_fix").replace("{warnings}", String(warnings)).replace("{fixes}", String(fixes))}`
|
|
2691
2650
|
);
|
|
2692
2651
|
} else {
|
|
2693
2652
|
console.log(
|
|
2694
|
-
` ${t("doctor_result")}: ${t("doctor_result_without_fix").replace("{warnings}", String(warnings))
|
|
2653
|
+
` ${t("doctor_result")}: ${t("doctor_result_without_fix").replace("{warnings}", String(warnings))}`
|
|
2695
2654
|
);
|
|
2696
2655
|
}
|
|
2697
2656
|
console.log();
|
|
@@ -2703,7 +2662,7 @@ function checkBrokenLinks(dir) {
|
|
|
2703
2662
|
for (const entry of entries) {
|
|
2704
2663
|
const fullPath = join14(dir, entry);
|
|
2705
2664
|
try {
|
|
2706
|
-
const stats =
|
|
2665
|
+
const stats = lstatSync2(fullPath);
|
|
2707
2666
|
if (stats.isSymbolicLink()) {
|
|
2708
2667
|
if (!existsSync14(fullPath)) {
|
|
2709
2668
|
broken++;
|
|
@@ -2724,7 +2683,7 @@ function fixBrokenLinks(dir) {
|
|
|
2724
2683
|
for (const entry of entries) {
|
|
2725
2684
|
const fullPath = join14(dir, entry);
|
|
2726
2685
|
try {
|
|
2727
|
-
const stats =
|
|
2686
|
+
const stats = lstatSync2(fullPath);
|
|
2728
2687
|
if (stats.isSymbolicLink()) {
|
|
2729
2688
|
if (!existsSync14(fullPath)) {
|
|
2730
2689
|
unlinkSync5(fullPath);
|
|
@@ -2742,7 +2701,6 @@ function fixBrokenLinks(dir) {
|
|
|
2742
2701
|
// src/commands/status.ts
|
|
2743
2702
|
import chalk9 from "chalk";
|
|
2744
2703
|
async function statusCommand() {
|
|
2745
|
-
const plugins = getAllPlugins();
|
|
2746
2704
|
const installed = scanInstalled();
|
|
2747
2705
|
const installedMap = new Map(installed.map((p) => [p.id, p]));
|
|
2748
2706
|
console.log();
|
|
@@ -3073,7 +3031,7 @@ async function installPlugins(pluginIds, tool, level, repoPath, installPath, yes
|
|
|
3073
3031
|
}
|
|
3074
3032
|
|
|
3075
3033
|
// src/commands/uninstall.ts
|
|
3076
|
-
import { existsSync as existsSync15, unlinkSync as unlinkSync6, rmdirSync as rmdirSync2, readdirSync as readdirSync6
|
|
3034
|
+
import { existsSync as existsSync15, unlinkSync as unlinkSync6, rmdirSync as rmdirSync2, readdirSync as readdirSync6 } from "fs";
|
|
3077
3035
|
import { resolve } from "path";
|
|
3078
3036
|
import chalk11 from "chalk";
|
|
3079
3037
|
async function uninstallCommand(names, options) {
|
|
@@ -3115,7 +3073,7 @@ async function uninstallCommand(names, options) {
|
|
|
3115
3073
|
for (const filePath of record.files) {
|
|
3116
3074
|
if (!isSafePath(filePath)) continue;
|
|
3117
3075
|
try {
|
|
3118
|
-
if (existsSync15(filePath) ||
|
|
3076
|
+
if (existsSync15(filePath) || isSymlink(filePath)) {
|
|
3119
3077
|
unlinkSync6(filePath);
|
|
3120
3078
|
const name = filePath.split("/").pop() || filePath;
|
|
3121
3079
|
logger.step(` ${t("uninstall_remove_label")}: ${name}`);
|
|
@@ -3163,7 +3121,7 @@ async function uninstallCommand(names, options) {
|
|
|
3163
3121
|
}
|
|
3164
3122
|
const totalRemoved = removedFiles + removedDirs;
|
|
3165
3123
|
if (totalRemoved > 0) {
|
|
3166
|
-
logger.success(
|
|
3124
|
+
logger.success(t("uninstall_summary_format").replace("{name}", plugin.displayName).replace("{files}", String(removedFiles)).replace("{dirs}", String(removedDirs)));
|
|
3167
3125
|
} else {
|
|
3168
3126
|
logger.warn(`${plugin.displayName}${t("uninstall_files_gone")}`);
|
|
3169
3127
|
}
|
|
@@ -3185,13 +3143,6 @@ async function uninstallCommand(names, options) {
|
|
|
3185
3143
|
logger.blank();
|
|
3186
3144
|
}
|
|
3187
3145
|
}
|
|
3188
|
-
function isSymlink3(path) {
|
|
3189
|
-
try {
|
|
3190
|
-
return lstatSync4(path).isSymbolicLink();
|
|
3191
|
-
} catch {
|
|
3192
|
-
return false;
|
|
3193
|
-
}
|
|
3194
|
-
}
|
|
3195
3146
|
|
|
3196
3147
|
// src/commands/update.ts
|
|
3197
3148
|
import chalk12 from "chalk";
|
|
@@ -3360,13 +3311,27 @@ async function langCommand(action, value) {
|
|
|
3360
3311
|
}
|
|
3361
3312
|
|
|
3362
3313
|
// src/cli.ts
|
|
3314
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
3315
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
3316
|
+
import { dirname as dirname7, join as join16 } from "path";
|
|
3317
|
+
function readVersion() {
|
|
3318
|
+
try {
|
|
3319
|
+
const __filename5 = fileURLToPath5(import.meta.url);
|
|
3320
|
+
const __dirname5 = dirname7(__filename5);
|
|
3321
|
+
const pkgPath = join16(__dirname5, "..", "package.json");
|
|
3322
|
+
const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
|
|
3323
|
+
return pkg.version || "0.0.0";
|
|
3324
|
+
} catch {
|
|
3325
|
+
return "0.0.0";
|
|
3326
|
+
}
|
|
3327
|
+
}
|
|
3363
3328
|
function createCLI() {
|
|
3364
3329
|
const config = readConfig();
|
|
3365
3330
|
if (config.language) {
|
|
3366
3331
|
setLanguage(config.language);
|
|
3367
3332
|
}
|
|
3368
3333
|
const program2 = new Command();
|
|
3369
|
-
program2.name("install-helper").description("CANNBot Install Helper - Interactive installer for CANN operator development skills").version(
|
|
3334
|
+
program2.name("install-helper").description("CANNBot Install Helper - Interactive installer for CANN operator development skills").version(readVersion());
|
|
3370
3335
|
program2.command("init", { isDefault: false }).description("Run interactive installation wizard").action(async () => {
|
|
3371
3336
|
await initCommand();
|
|
3372
3337
|
});
|