@cannbot-ai/install-helper 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/config/repository.yaml +25 -0
- package/dist/index.js +237 -585
- package/dist/index.js.map +1 -1
- package/dist/locales/en_US.json +168 -0
- package/dist/locales/zh_CN.json +168 -0
- package/dist/plugins.d/_defaults.yml +4 -0
- package/dist/plugins.d/catlass-op-generator.yml +7 -0
- package/dist/plugins.d/model-infer-optimize.yml +7 -0
- package/dist/plugins.d/ops-code-reviewer.yml +7 -0
- package/dist/plugins.d/ops-direct-invoke-flash.yml +7 -0
- package/dist/plugins.d/ops-direct-invoke.yml +7 -0
- package/dist/plugins.d/ops-registry-invoke.yml +7 -0
- package/dist/plugins.d/pypto-op-orchestrator.yml +7 -0
- package/dist/plugins.d/tilelang-op-orchestrator.yml +7 -0
- package/dist/plugins.d/torch-compile.yml +7 -0
- package/dist/plugins.d/triton-op-generator.yml +8 -0
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -12,108 +12,46 @@ import { select, checkbox, Separator } from "@inquirer/prompts";
|
|
|
12
12
|
import chalk2 from "chalk";
|
|
13
13
|
|
|
14
14
|
// src/core/registry.ts
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
dir: "plugins-official/ops-direct-invoke-flash",
|
|
29
|
-
displayName: "AscendC Kernel \u4ECE\u96F6\u6784\u5EFA",
|
|
30
|
-
script: "init.sh",
|
|
31
|
-
aliases: ["flash", "kernel-flash"],
|
|
32
|
-
skills: 1,
|
|
33
|
-
agents: 1,
|
|
34
|
-
description: "Ascend C / Ascend950 Reg API \u6838\u51FD\u6570\u4ECE\u96F6\u6784\u5EFA"
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
id: "ops-registry-invoke",
|
|
38
|
-
dir: "plugins-official/ops-registry-invoke",
|
|
39
|
-
displayName: "AscendC \u7B97\u5B50\u6CE8\u518C\u8C03\u7528",
|
|
40
|
-
script: "init.sh",
|
|
41
|
-
aliases: ["ops-registry", "ascendc-registry", "registry"],
|
|
42
|
-
skills: 12,
|
|
43
|
-
agents: 4,
|
|
44
|
-
description: "Ascend C \u7B97\u5B50\u6CE8\u518C\u8C03\u7528\u5F00\u53D1\u6D41\u7A0B"
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
id: "pypto-op-orchestrator",
|
|
48
|
-
dir: "plugins-official/pypto-op-orchestrator",
|
|
49
|
-
displayName: "PyPTO \u7B97\u5B50",
|
|
50
|
-
script: "init.sh",
|
|
51
|
-
aliases: ["pypto", "pytorch"],
|
|
52
|
-
skills: 8,
|
|
53
|
-
agents: 3,
|
|
54
|
-
description: "PyPTO \u7B97\u5B50\u7AEF\u5230\u7AEF\u5F00\u53D1\u7F16\u6392"
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
id: "triton-op-generator",
|
|
58
|
-
dir: "plugins-official/triton-op-generator",
|
|
59
|
-
displayName: "Triton \u7B97\u5B50\u751F\u6210",
|
|
60
|
-
script: "install.sh",
|
|
61
|
-
aliases: ["triton"],
|
|
62
|
-
skills: 6,
|
|
63
|
-
agents: 0,
|
|
64
|
-
description: "Triton-Ascend \u7B97\u5B50\u4EE3\u7801\u751F\u6210\u4E0E\u4F18\u5316"
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
id: "tilelang-op-orchestrator",
|
|
68
|
-
dir: "plugins-official/tilelang-op-orchestrator",
|
|
69
|
-
displayName: "TileLang \u7B97\u5B50",
|
|
70
|
-
script: "init.sh",
|
|
71
|
-
aliases: ["tilelang"],
|
|
72
|
-
skills: 9,
|
|
73
|
-
agents: 3,
|
|
74
|
-
description: "TileLang \u7B97\u5B50\u5F00\u53D1\u6D41\u7A0B"
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
id: "model-infer-optimize",
|
|
78
|
-
dir: "plugins-official/model-infer-optimize",
|
|
79
|
-
displayName: "NPU \u63A8\u7406\u4F18\u5316",
|
|
80
|
-
script: "init.sh",
|
|
81
|
-
aliases: ["model-infer", "infer", "inference"],
|
|
82
|
-
skills: 11,
|
|
83
|
-
agents: 3,
|
|
84
|
-
description: "NPU \u6A21\u578B\u63A8\u7406\u7AEF\u5230\u7AEF\u4F18\u5316"
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
id: "catlass-op-generator",
|
|
88
|
-
dir: "plugins-official/catlass-op-generator",
|
|
89
|
-
displayName: "Catlass \u7B97\u5B50\u76F4\u8C03",
|
|
90
|
-
script: "init.sh",
|
|
91
|
-
aliases: ["catlass"],
|
|
92
|
-
skills: 10,
|
|
93
|
-
agents: 3,
|
|
94
|
-
description: "Catlass \u7B97\u5B50\u76F4\u8C03\u5F00\u53D1"
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
id: "ops-code-reviewer",
|
|
98
|
-
dir: "plugins-official/ops-code-reviewer",
|
|
99
|
-
displayName: "\u4EE3\u7801\u68C0\u89C6",
|
|
100
|
-
script: "init.sh",
|
|
101
|
-
aliases: ["code-review", "reviewer", "review"],
|
|
102
|
-
skills: 5,
|
|
103
|
-
agents: 1,
|
|
104
|
-
description: "\u4EE3\u7801\u68C0\u89C6\u4E0E\u89C4\u8303\u68C0\u67E5"
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
id: "torch-compile",
|
|
108
|
-
dir: "plugins-official/torch-compile",
|
|
109
|
-
displayName: "torch.compile \u56FE\u6A21\u5F0F",
|
|
110
|
-
script: "init.sh",
|
|
111
|
-
aliases: ["torch", "compile", "graph"],
|
|
112
|
-
skills: 6,
|
|
113
|
-
agents: 1,
|
|
114
|
-
description: "PyTorch torch.compile \u56FE\u6A21\u5F0F\u9002\u914D"
|
|
15
|
+
import { readdirSync, readFileSync } from "fs";
|
|
16
|
+
import { join, dirname } from "path";
|
|
17
|
+
import { fileURLToPath } from "url";
|
|
18
|
+
import { parse as parseYaml } from "yaml";
|
|
19
|
+
var __filename = fileURLToPath(import.meta.url);
|
|
20
|
+
var __dirname = dirname(__filename);
|
|
21
|
+
function loadPluginsFromYaml() {
|
|
22
|
+
const pluginsDir = join(__dirname, "plugins.d");
|
|
23
|
+
const defaultsPath = join(pluginsDir, "_defaults.yml");
|
|
24
|
+
let defaults = {};
|
|
25
|
+
try {
|
|
26
|
+
defaults = parseYaml(readFileSync(defaultsPath, "utf-8")) || {};
|
|
27
|
+
} catch {
|
|
115
28
|
}
|
|
116
|
-
];
|
|
29
|
+
const plugins = [];
|
|
30
|
+
try {
|
|
31
|
+
for (const file of readdirSync(pluginsDir)) {
|
|
32
|
+
if (file.startsWith("_") || !file.endsWith(".yml")) continue;
|
|
33
|
+
try {
|
|
34
|
+
const content = parseYaml(readFileSync(join(pluginsDir, file), "utf-8"));
|
|
35
|
+
if (!content || !content.id) continue;
|
|
36
|
+
plugins.push({
|
|
37
|
+
id: content.id,
|
|
38
|
+
dir: content.dir,
|
|
39
|
+
displayName: content.displayName || content.id,
|
|
40
|
+
script: content.script || defaults.script || "init.sh",
|
|
41
|
+
aliases: content.aliases || [],
|
|
42
|
+
skills: content.skills ?? defaults.skills ?? 0,
|
|
43
|
+
agents: content.agents ?? defaults.agents ?? 0,
|
|
44
|
+
description: content.description || ""
|
|
45
|
+
});
|
|
46
|
+
} catch {
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
} catch {
|
|
50
|
+
}
|
|
51
|
+
plugins.sort((a, b) => a.displayName < b.displayName ? -1 : a.displayName > b.displayName ? 1 : 0);
|
|
52
|
+
return plugins;
|
|
53
|
+
}
|
|
54
|
+
var PLUGIN_REGISTRY = loadPluginsFromYaml();
|
|
117
55
|
function findPlugin(query) {
|
|
118
56
|
const normalized = query.toLowerCase().trim();
|
|
119
57
|
const exactMatch = PLUGIN_REGISTRY.find(
|
|
@@ -139,356 +77,42 @@ function getPluginById(id) {
|
|
|
139
77
|
import { execa } from "execa";
|
|
140
78
|
import { existsSync as existsSync2 } from "fs";
|
|
141
79
|
import { homedir as homedir2 } from "os";
|
|
142
|
-
import { join as
|
|
80
|
+
import { join as join4 } from "path";
|
|
143
81
|
|
|
144
82
|
// src/utils/paths.ts
|
|
145
83
|
import { homedir } from "os";
|
|
146
|
-
import { join } from "path";
|
|
84
|
+
import { join as join3 } from "path";
|
|
147
85
|
import { existsSync } from "fs";
|
|
148
86
|
|
|
149
87
|
// src/utils/i18n.ts
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
install_enhanced_next_steps: "\u4E0B\u4E00\u6B65",
|
|
171
|
-
install_enhanced_launch: "\u542F\u52A8",
|
|
172
|
-
install_enhanced_try: "\u8BD5\u8BD5",
|
|
173
|
-
install_enhanced_more: "\u66F4\u591A",
|
|
174
|
-
install_enhanced_check: "\u68C0\u67E5",
|
|
175
|
-
install_enhanced_docs: "\u6587\u6863",
|
|
176
|
-
update_title: "\u66F4\u65B0\u5DF2\u5B89\u88C5\u7684 Skills",
|
|
177
|
-
update_updating: "\u6B63\u5728\u66F4\u65B0",
|
|
178
|
-
update_done: "\u66F4\u65B0\u5B8C\u6210",
|
|
179
|
-
update_no_plugins: "\u6682\u65E0\u5DF2\u5B89\u88C5\u7684\u63D2\u4EF6",
|
|
180
|
-
doctor_title: "CANNBot Doctor",
|
|
181
|
-
doctor_tools: "AI \u5DE5\u5177",
|
|
182
|
-
doctor_plugins: "\u5DF2\u5B89\u88C5\u63D2\u4EF6",
|
|
183
|
-
doctor_links: "\u94FE\u63A5\u5B8C\u6574\u6027",
|
|
184
|
-
doctor_config: "\u914D\u7F6E\u6587\u4EF6",
|
|
185
|
-
doctor_result: "\u7ED3\u679C",
|
|
186
|
-
doctor_fix_title: "\u81EA\u52A8\u4FEE\u590D",
|
|
187
|
-
doctor_fix_cleaning: "\u6E05\u7406\u5931\u6548\u94FE\u63A5",
|
|
188
|
-
doctor_fix_rebuilding: "\u91CD\u5EFA\u76EE\u5F55",
|
|
189
|
-
doctor_fix_done: "\u4FEE\u590D\u5B8C\u6210",
|
|
190
|
-
info_title: "\u63D2\u4EF6\u8BE6\u60C5",
|
|
191
|
-
info_description: "\u63CF\u8FF0",
|
|
192
|
-
info_skills: "Skills",
|
|
193
|
-
info_agents: "Agents",
|
|
194
|
-
info_status: "\u72B6\u6001",
|
|
195
|
-
info_quickstart: "\u5FEB\u901F\u5F00\u59CB",
|
|
196
|
-
info_not_found: "\u672A\u627E\u5230\u63D2\u4EF6",
|
|
197
|
-
lang_title: "\u8BED\u8A00\u8BBE\u7F6E",
|
|
198
|
-
lang_current: "\u5F53\u524D\u8BED\u8A00",
|
|
199
|
-
lang_set: "\u8BED\u8A00\u5DF2\u8BBE\u7F6E\u4E3A",
|
|
200
|
-
lang_invalid: "\u65E0\u6548\u7684\u8BED\u8A00\uFF0C\u652F\u6301: zh_CN, en_US",
|
|
201
|
-
list_title: "\u53EF\u7528\u573A\u666F",
|
|
202
|
-
list_id: "\u5E8F\u53F7",
|
|
203
|
-
list_name: "\u573A\u666F\u540D",
|
|
204
|
-
list_status: "\u72B6\u6001",
|
|
205
|
-
list_skills: "Skills",
|
|
206
|
-
list_agents: "Agents",
|
|
207
|
-
status_installed: "\u5DF2\u88C5",
|
|
208
|
-
status_not_installed: "\u672A\u88C5",
|
|
209
|
-
error_tool_not_found: "\u672A\u68C0\u6D4B\u5230\u4EFB\u4F55 AI \u7F16\u7A0B\u5DE5\u5177",
|
|
210
|
-
error_plugin_not_found: "\u672A\u627E\u5230\u63D2\u4EF6",
|
|
211
|
-
error_repo_not_found: "\u4ED3\u5E93\u672A\u627E\u5230",
|
|
212
|
-
error_invalid_tool: "\u6682\u4E0D\u652F\u6301\u7684 AI \u5DE5\u5177: {tool}\n\u652F\u6301\u7684\u5DE5\u5177: {tools}",
|
|
213
|
-
error_invalid_level: "\u6682\u4E0D\u652F\u6301\u7684\u5B89\u88C5\u7EA7\u522B: {level}\n\u652F\u6301\u7684\u7EA7\u522B: {levels}",
|
|
214
|
-
quick_start: "\u542F\u52A8\u547D\u4EE4",
|
|
215
|
-
quick_start_hint: "\u8BD5\u8BD5\u8F93\u5165: \u5E2E\u6211\u5F00\u53D1\u4E00\u4E2A Abs \u7B97\u5B50",
|
|
216
|
-
skill_select_category: "\u9009\u62E9 Skill \u7C7B\u522B",
|
|
217
|
-
skill_select_items: "\u9009\u62E9\u8981\u5B89\u88C5\u7684 Skills",
|
|
218
|
-
skill_already_installed: "\u5DF2\u5B89\u88C5",
|
|
219
|
-
skill_install_progress: "\u6B63\u5728\u5B89\u88C5",
|
|
220
|
-
skill_install_done: "Skill \u5B89\u88C5\u5B8C\u6210",
|
|
221
|
-
skill_uninstall_done: "Skill \u5378\u8F7D\u5B8C\u6210",
|
|
222
|
-
skill_list_title: "\u53EF\u7528 Skills",
|
|
223
|
-
wizard_select_mode: "\u9009\u62E9\u5B89\u88C5\u7C7B\u578B",
|
|
224
|
-
wizard_mode_plugin: "\u5B89\u88C5 Plugin",
|
|
225
|
-
wizard_mode_plugin_desc: "\u5B8C\u6574\u5F00\u53D1\u5DE5\u4F5C\u6D41\uFF08Skills + Agents + \u914D\u7F6E\u6587\u4EF6\uFF09",
|
|
226
|
-
wizard_mode_skill: "\u5B89\u88C5 Skill",
|
|
227
|
-
wizard_mode_skill_desc: "\u4EC5\u5B89\u88C5\u9886\u57DF\u77E5\u8BC6\u6280\u80FD\uFF0C\u8BA9 AI \u638C\u63E1\u7279\u5B9A\u80FD\u529B",
|
|
228
|
-
wizard_back: "\u8FD4\u56DE",
|
|
229
|
-
wizard_cancel: "\u9000\u51FA",
|
|
230
|
-
wizard_no_selection: "\u672A\u9009\u62E9\u4EFB\u4F55\u9879\uFF0C\u8BF7\u9009\u62E9\u64CD\u4F5C",
|
|
231
|
-
wizard_back_to_reselect: "\u8FD4\u56DE",
|
|
232
|
-
status_title: "\u5DF2\u5B89\u88C5\u63D2\u4EF6",
|
|
233
|
-
status_none: "\u6682\u65E0\u5DF2\u5B89\u88C5\u7684\u63D2\u4EF6",
|
|
234
|
-
status_hint: "\u8FD0\u884C install-helper init \u5F00\u59CB\u5B89\u88C5",
|
|
235
|
-
status_install_time: "\u5B89\u88C5\u65F6\u95F4",
|
|
236
|
-
install_installed_to: "\u5B89\u88C5\u5230",
|
|
237
|
-
install_skills_count: "Skills",
|
|
238
|
-
install_agents_count: "Agents",
|
|
239
|
-
lang_supported: "\u652F\u6301\u7684\u8BED\u8A00: zh_CN, en_US",
|
|
240
|
-
lang_usage: "\u7528\u6CD5: install-helper lang set <language>",
|
|
241
|
-
lang_specify: "\u8BF7\u6307\u5B9A\u8BED\u8A00: install-helper lang set zh_CN",
|
|
242
|
-
lang_unknown_action: "\u672A\u77E5\u64CD\u4F5C",
|
|
243
|
-
lang_supported_actions: "\u652F\u6301\u7684\u64CD\u4F5C: show, set",
|
|
244
|
-
info_aliases: "\u522B\u540D",
|
|
245
|
-
uninstall_not_found: "\u672A\u627E\u5230",
|
|
246
|
-
uninstall_no_record: "\u672A\u627E\u5230\u5B89\u88C5\u8BB0\u5F55\uFF0C\u53EF\u80FD\u672A\u5B89\u88C5\u6216\u5B89\u88C5\u8BB0\u5F55\u5DF2\u635F\u574F",
|
|
247
|
-
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",
|
|
248
|
-
uninstall_in_progress: "\u6B63\u5728\u5378\u8F7D",
|
|
249
|
-
uninstall_removed: "\u5DF2\u5378\u8F7D",
|
|
250
|
-
uninstall_files_gone: "\u7684\u6587\u4EF6\u5DF2\u4E0D\u5B58\u5728\uFF0C\u5DF2\u6E05\u7406\u5B89\u88C5\u8BB0\u5F55",
|
|
251
|
-
uninstall_skills_in_progress: "\u6B63\u5728\u5378\u8F7D",
|
|
252
|
-
init_pkg_dir_warn: "\u5F53\u524D\u76EE\u5F55\u770B\u8D77\u6765\u662F install-helper \u5305\u76EE\u5F55",
|
|
253
|
-
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",
|
|
254
|
-
init_pkg_dir_example: "\u793A\u4F8B\uFF1Acd ~/my-project && install-helper",
|
|
255
|
-
init_cancelled: "\u5DF2\u53D6\u6D88\u5B89\u88C5",
|
|
256
|
-
backup_detected: "\u68C0\u6D4B\u5230\u5F53\u524D\u76EE\u5F55\u5DF2\u5B89\u88C5\u63D2\u4EF6",
|
|
257
|
-
backup_current: "\u5F53\u524D\u5B89\u88C5",
|
|
258
|
-
backup_installing: "\u5373\u5C06\u5B89\u88C5",
|
|
259
|
-
backup_overwrite_warning: "\u7EE7\u7EED\u5B89\u88C5\u5C06\u8986\u76D6\u73B0\u6709\u7684 AGENTS.md \u914D\u7F6E\u6587\u4EF6\u3002",
|
|
260
|
-
backup_auto_create: "\u7CFB\u7EDF\u4F1A\u81EA\u52A8\u521B\u5EFA\u5907\u4EFD\uFF0C\u4EE5\u4FBF\u540E\u7EED\u6062\u590D\u3002",
|
|
261
|
-
backup_overwrite: "\u8986\u76D6\u5B89\u88C5\uFF08\u81EA\u52A8\u5907\u4EFD\uFF09",
|
|
262
|
-
backup_cancel: "\u53D6\u6D88\u5B89\u88C5",
|
|
263
|
-
backup_restore_prompt: "\u68C0\u6D4B\u5230\u5907\u4EFD\u914D\u7F6E\uFF0C\u662F\u5426\u6062\u590D\uFF1F",
|
|
264
|
-
backup_restore: "\u6062\u590D",
|
|
265
|
-
backup_only_uninstall: "\u4EC5\u5378\u8F7D\uFF08\u4E0D\u6062\u590D\uFF09",
|
|
266
|
-
backup_select_action: "\u8BF7\u9009\u62E9\u64CD\u4F5C",
|
|
267
|
-
backup_restore_success: "\u5DF2\u6062\u590D\u914D\u7F6E",
|
|
268
|
-
backup_created: "\u5DF2\u521B\u5EFA\u5907\u4EFD",
|
|
269
|
-
loading_skills_list: "\u6B63\u5728\u52A0\u8F7D Skills \u5217\u8868...",
|
|
270
|
-
loading_skills_list_complete: "Skills \u5217\u8868\u52A0\u8F7D\u5B8C\u6210",
|
|
271
|
-
loading_plugin_data: "\u6B63\u5728\u52A0\u8F7D\u63D2\u4EF6\u6570\u636E...",
|
|
272
|
-
loading_plugin_data_complete: "\u63D2\u4EF6\u6570\u636E\u52A0\u8F7D\u5B8C\u6210",
|
|
273
|
-
loading_skills_list_failed: "Skills \u5217\u8868\u52A0\u8F7D\u5931\u8D25\uFF0C\u5C06\u4F7F\u7528\u5185\u7F6E\u6570\u636E",
|
|
274
|
-
install_no_skill_selected: "\u672A\u9009\u62E9\u4EFB\u4F55 Skill",
|
|
275
|
-
install_to: "\u5B89\u88C5\u5230",
|
|
276
|
-
start_to_use: "\u542F\u52A8 {tool} \u5373\u53EF\u4F7F\u7528",
|
|
277
|
-
wizard_step_1_title: "[1/4] \u9009\u62E9 AI \u7F16\u7A0B\u5DE5\u5177",
|
|
278
|
-
wizard_step_2_title: "[2/4] \u9009\u62E9\u5B89\u88C5\u4F4D\u7F6E",
|
|
279
|
-
wizard_step_3_title: "[3/4] \u9009\u62E9\u8981\u5B89\u88C5\u7684\u63D2\u4EF6",
|
|
280
|
-
wizard_step_4_title: "[4/4] \u786E\u8BA4\u5B89\u88C5",
|
|
281
|
-
wizard_step_3_skill_title: "[3/4] \u9009\u62E9 Skill \u7C7B\u522B",
|
|
282
|
-
wizard_step_4_skill_title: "[4/4] \u9009\u62E9\u8981\u5B89\u88C5\u7684 Skills \u2014 {category}",
|
|
283
|
-
install_level_project: "\u5B89\u88C5\u5230\u5F53\u524D\u76EE\u5F55\uFF08\u63A8\u8350\uFF0C\u4EC5\u5F53\u524D\u9879\u76EE\u53EF\u7528\uFF09",
|
|
284
|
-
install_level_global: "\u5B89\u88C5\u5230\u5168\u5C40\uFF08\u6240\u6709\u9879\u76EE\u5171\u4EAB\uFF09",
|
|
285
|
-
wizard_select_mode_title: "\u9009\u62E9\u5B89\u88C5\u7C7B\u578B",
|
|
286
|
-
skill_count_format: "{count} \u4E2A Skills",
|
|
287
|
-
result_success_format: "{count} \u6210\u529F",
|
|
288
|
-
result_failed_format: "{count} \u5931\u8D25",
|
|
289
|
-
uninstall_remove_label: "\u79FB\u9664",
|
|
290
|
-
uninstall_remove_file_format: "\u79FB\u9664 {count} \u4E2A\u6587\u4EF6",
|
|
291
|
-
uninstall_remove_dir_format: "{count} \u4E2A\u76EE\u5F55",
|
|
292
|
-
uninstall_clean_empty_dir: "\u6E05\u7406\u7A7A\u76EE\u5F55",
|
|
293
|
-
uninstall_skill_not_installed: "\u672A\u5B89\u88C5",
|
|
294
|
-
available_plugins: "\u53EF\u7528\u63D2\u4EF6",
|
|
295
|
-
available_skills: "\u53EF\u7528 Skills",
|
|
296
|
-
skill_total_count: "\u5171 {count} \u4E2A Skills",
|
|
297
|
-
wizard_confirm_install_format: "\u5373\u5C06\u5B89\u88C5 {count} \u4E2A\u63D2\u4EF6\u5230 {tool}\uFF08{level} \u7EA7\u522B\uFF09\uFF1A",
|
|
298
|
-
wizard_install_path: "\u5B89\u88C5\u8DEF\u5F84",
|
|
299
|
-
update_install_hint: "\u4F7F\u7528 {cmd} \u5B89\u88C5\u63D2\u4EF6",
|
|
300
|
-
hint_select_move: "\u79FB\u52A8",
|
|
301
|
-
hint_select_space: "\u7A7A\u683C",
|
|
302
|
-
hint_select_check: "\u52FE\u9009",
|
|
303
|
-
hint_select_confirm: "\u786E\u8BA4",
|
|
304
|
-
hint_checkbox_suffix: "\u4E0D\u9009\u6309\u56DE\u8F66\u53EF\u8FD4\u56DE",
|
|
305
|
-
doctor_not_installed: "\u672A\u5B89\u88C5",
|
|
306
|
-
doctor_links_valid: "{count} \u4E2A\u8F6F\u94FE\u63A5\u5747\u6709\u6548",
|
|
307
|
-
doctor_broken_links: "{count} \u4E2A\u5931\u6548\u94FE\u63A5",
|
|
308
|
-
doctor_fixed: "\u5DF2\u6E05\u7406 {count} \u4E2A\u5931\u6548\u94FE\u63A5",
|
|
309
|
-
doctor_not_exist: "\u4E0D\u5B58\u5728",
|
|
310
|
-
doctor_created: "\u5DF2\u521B\u5EFA {path}",
|
|
311
|
-
doctor_config_exists: "\u5B58\u5728",
|
|
312
|
-
doctor_config_not_exist: "\u4E0D\u5B58\u5728",
|
|
313
|
-
doctor_result_with_fix: "{warnings} \u4E2A\u8B66\u544A, {errors} \u4E2A\u9519\u8BEF, {fixes} \u9879\u5DF2\u4FEE\u590D",
|
|
314
|
-
doctor_result_without_fix: "{warnings} \u4E2A\u8B66\u544A, {errors} \u4E2A\u9519\u8BEF",
|
|
315
|
-
count_suffix: "\u4E2A",
|
|
316
|
-
try_prompt: "\u5E2E\u6211\u5F00\u53D1\u4E00\u4E2A Abs \u7B97\u5B50"
|
|
317
|
-
};
|
|
318
|
-
var en_US = {
|
|
319
|
-
wizard_title: "CANNBot Install Helper",
|
|
320
|
-
wizard_detect: "Detecting installed AI coding tools...",
|
|
321
|
-
wizard_select_tool: "Select AI coding tool",
|
|
322
|
-
wizard_select_level: "Select install level",
|
|
323
|
-
wizard_select_plugins: "Select scenarios to install",
|
|
324
|
-
wizard_confirm: "Confirm installation",
|
|
325
|
-
wizard_detected_tool: "Detected",
|
|
326
|
-
wizard_confirm_tool: "Confirm using",
|
|
327
|
-
wizard_last_used: "last used",
|
|
328
|
-
wizard_already_installed: "installed",
|
|
329
|
-
install_cloning: "Cloning cannbot-skills repository...",
|
|
330
|
-
install_repo_ready: "Repository ready",
|
|
331
|
-
install_progress: "Installing",
|
|
332
|
-
install_done: "Installation complete",
|
|
333
|
-
install_success: "success",
|
|
334
|
-
install_failed: "failed",
|
|
335
|
-
install_already_installed: "already installed",
|
|
336
|
-
install_reinstall_confirm: "Reinstall (overwrite)",
|
|
337
|
-
install_skip: "skipped",
|
|
338
|
-
install_enhanced_next_steps: "Next steps",
|
|
339
|
-
install_enhanced_launch: "Launch",
|
|
340
|
-
install_enhanced_try: "Try",
|
|
341
|
-
install_enhanced_more: "More",
|
|
342
|
-
install_enhanced_check: "Check",
|
|
343
|
-
install_enhanced_docs: "Docs",
|
|
344
|
-
update_title: "Update installed Skills",
|
|
345
|
-
update_updating: "Updating",
|
|
346
|
-
update_done: "Update complete",
|
|
347
|
-
update_no_plugins: "No installed plugins",
|
|
348
|
-
doctor_title: "CANNBot Doctor",
|
|
349
|
-
doctor_tools: "AI Tools",
|
|
350
|
-
doctor_plugins: "Installed Plugins",
|
|
351
|
-
doctor_links: "Link Integrity",
|
|
352
|
-
doctor_config: "Configuration",
|
|
353
|
-
doctor_result: "Result",
|
|
354
|
-
doctor_fix_title: "Auto-fix",
|
|
355
|
-
doctor_fix_cleaning: "Cleaning broken links",
|
|
356
|
-
doctor_fix_rebuilding: "Rebuilding directories",
|
|
357
|
-
doctor_fix_done: "Fix complete",
|
|
358
|
-
info_title: "Plugin Details",
|
|
359
|
-
info_description: "Description",
|
|
360
|
-
info_skills: "Skills",
|
|
361
|
-
info_agents: "Agents",
|
|
362
|
-
info_status: "Status",
|
|
363
|
-
info_quickstart: "Quick Start",
|
|
364
|
-
info_not_found: "Plugin not found",
|
|
365
|
-
lang_title: "Language Settings",
|
|
366
|
-
lang_current: "Current language",
|
|
367
|
-
lang_set: "Language set to",
|
|
368
|
-
lang_invalid: "Invalid language, supported: zh_CN, en_US",
|
|
369
|
-
list_title: "Available Scenarios",
|
|
370
|
-
list_id: "#",
|
|
371
|
-
list_name: "Name",
|
|
372
|
-
list_status: "Status",
|
|
373
|
-
list_skills: "Skills",
|
|
374
|
-
list_agents: "Agents",
|
|
375
|
-
status_installed: "installed",
|
|
376
|
-
status_not_installed: "not installed",
|
|
377
|
-
error_tool_not_found: "No AI coding tool detected",
|
|
378
|
-
error_plugin_not_found: "Plugin not found",
|
|
379
|
-
error_repo_not_found: "Repository not found",
|
|
380
|
-
error_invalid_tool: "Unsupported AI tool: {tool}\nSupported tools: {tools}",
|
|
381
|
-
error_invalid_level: "Unsupported install level: {level}\nSupported levels: {levels}",
|
|
382
|
-
quick_start: "Launch command",
|
|
383
|
-
quick_start_hint: "Try: help me develop an Abs operator",
|
|
384
|
-
skill_select_category: "Select Skill category",
|
|
385
|
-
skill_select_items: "Select Skills to install (space to toggle, enter to confirm)",
|
|
386
|
-
skill_already_installed: "installed",
|
|
387
|
-
skill_install_progress: "Installing",
|
|
388
|
-
skill_install_done: "Skill installation complete",
|
|
389
|
-
skill_uninstall_done: "Skill uninstallation complete",
|
|
390
|
-
skill_list_title: "Available Skills",
|
|
391
|
-
wizard_select_mode: "Select installation mode",
|
|
392
|
-
wizard_mode_plugin: "Install Plugin",
|
|
393
|
-
wizard_mode_plugin_desc: "Full development workflow (Skills + Agents + config)",
|
|
394
|
-
wizard_mode_skill: "Install Skill",
|
|
395
|
-
wizard_mode_skill_desc: "Domain knowledge only, give AI specific capabilities",
|
|
396
|
-
wizard_back: "Go back",
|
|
397
|
-
wizard_cancel: "Cancel installation",
|
|
398
|
-
wizard_no_selection: "No items selected, please choose an action",
|
|
399
|
-
wizard_back_to_reselect: "Go back",
|
|
400
|
-
status_title: "Installed Plugins",
|
|
401
|
-
status_none: "No installed plugins",
|
|
402
|
-
status_hint: "Run install-helper init to start",
|
|
403
|
-
status_install_time: "Installed at",
|
|
404
|
-
install_installed_to: "Installed to",
|
|
405
|
-
install_skills_count: "Skills",
|
|
406
|
-
install_agents_count: "Agents",
|
|
407
|
-
lang_supported: "Supported languages: zh_CN, en_US",
|
|
408
|
-
lang_usage: "Usage: install-helper lang set <language>",
|
|
409
|
-
lang_specify: "Please specify language: install-helper lang set zh_CN",
|
|
410
|
-
lang_unknown_action: "Unknown action",
|
|
411
|
-
lang_supported_actions: "Supported actions: show, set",
|
|
412
|
-
info_aliases: "Aliases",
|
|
413
|
-
uninstall_not_found: "Not found",
|
|
414
|
-
uninstall_no_record: "No install record found, may not be installed or record is corrupted",
|
|
415
|
-
uninstall_no_record_hint: "For manual cleanup, delete related files in .opencode/ or .claude/ directory",
|
|
416
|
-
uninstall_in_progress: "Uninstalling",
|
|
417
|
-
uninstall_removed: "Uninstalled",
|
|
418
|
-
uninstall_files_gone: " files no longer exist, install record cleaned",
|
|
419
|
-
uninstall_skills_in_progress: "Uninstalling",
|
|
420
|
-
init_pkg_dir_warn: "Current directory appears to be the install-helper package directory",
|
|
421
|
-
init_pkg_dir_hint: "Please run this command in your project directory, not in the install-helper package directory",
|
|
422
|
-
init_pkg_dir_example: "Example: cd ~/my-project && install-helper",
|
|
423
|
-
init_cancelled: "Installation cancelled",
|
|
424
|
-
backup_detected: "Plugin already installed in current directory",
|
|
425
|
-
backup_current: "Currently installed",
|
|
426
|
-
backup_installing: "About to install",
|
|
427
|
-
backup_overwrite_warning: "Continuing will overwrite existing AGENTS.md configuration.",
|
|
428
|
-
backup_auto_create: "System will automatically create backup for future restoration.",
|
|
429
|
-
backup_overwrite: "Overwrite (auto backup)",
|
|
430
|
-
backup_cancel: "Cancel installation",
|
|
431
|
-
backup_restore_prompt: "Backup configuration detected, restore?",
|
|
432
|
-
backup_restore: "Restore",
|
|
433
|
-
backup_only_uninstall: "Uninstall only (no restore)",
|
|
434
|
-
backup_select_action: "Please select an action",
|
|
435
|
-
backup_restore_success: "Configuration restored",
|
|
436
|
-
backup_created: "Backup created",
|
|
437
|
-
loading_skills_list: "Loading Skills list...",
|
|
438
|
-
loading_skills_list_complete: "Skills list loaded",
|
|
439
|
-
loading_plugin_data: "Loading plugin data...",
|
|
440
|
-
loading_plugin_data_complete: "Plugin data loaded",
|
|
441
|
-
loading_skills_list_failed: "Failed to load Skills list, using built-in data",
|
|
442
|
-
install_no_skill_selected: "No Skill selected",
|
|
443
|
-
install_to: "Install to",
|
|
444
|
-
start_to_use: "Start {tool} to use",
|
|
445
|
-
wizard_step_1_title: "[1/4] Select AI coding tool",
|
|
446
|
-
wizard_step_2_title: "[2/4] Select installation location",
|
|
447
|
-
wizard_step_3_title: "[3/4] Select plugins to install",
|
|
448
|
-
wizard_step_4_title: "[4/4] Confirm installation",
|
|
449
|
-
wizard_step_3_skill_title: "[3/4] Select Skill category",
|
|
450
|
-
wizard_step_4_skill_title: "[4/4] Select Skills to install \u2014 {category}",
|
|
451
|
-
install_level_project: "Install to current directory (recommended, current project only)",
|
|
452
|
-
install_level_global: "Install globally (all projects)",
|
|
453
|
-
wizard_select_mode_title: "Select installation type",
|
|
454
|
-
skill_count_format: "{count} Skills",
|
|
455
|
-
result_success_format: "{count} succeeded",
|
|
456
|
-
result_failed_format: "{count} failed",
|
|
457
|
-
uninstall_remove_label: "Removed",
|
|
458
|
-
uninstall_remove_file_format: "Removed {count} files",
|
|
459
|
-
uninstall_remove_dir_format: "{count} directories",
|
|
460
|
-
uninstall_clean_empty_dir: "Cleaned empty directory",
|
|
461
|
-
uninstall_skill_not_installed: "Not installed",
|
|
462
|
-
available_plugins: "Available plugins",
|
|
463
|
-
available_skills: "Available Skills",
|
|
464
|
-
skill_total_count: "Total {count} Skills",
|
|
465
|
-
wizard_confirm_install_format: "About to install {count} plugins to {tool} ({level} level):",
|
|
466
|
-
wizard_install_path: "Install path",
|
|
467
|
-
update_install_hint: "Use {cmd} to install plugins",
|
|
468
|
-
hint_select_move: "Navigate",
|
|
469
|
-
hint_select_space: "Space",
|
|
470
|
-
hint_select_check: "Toggle",
|
|
471
|
-
hint_select_confirm: "Confirm",
|
|
472
|
-
hint_checkbox_suffix: "Press enter without selection to go back",
|
|
473
|
-
doctor_not_installed: "Not installed",
|
|
474
|
-
doctor_links_valid: "{count} symlinks all valid",
|
|
475
|
-
doctor_broken_links: "{count} broken links",
|
|
476
|
-
doctor_fixed: "Cleaned {count} broken links",
|
|
477
|
-
doctor_not_exist: "Does not exist",
|
|
478
|
-
doctor_created: "Created {path}",
|
|
479
|
-
doctor_config_exists: "Exists",
|
|
480
|
-
doctor_config_not_exist: "Does not exist",
|
|
481
|
-
doctor_result_with_fix: "{warnings} warnings, {errors} errors, {fixes} fixed",
|
|
482
|
-
doctor_result_without_fix: "{warnings} warnings, {errors} errors",
|
|
483
|
-
count_suffix: "",
|
|
484
|
-
try_prompt: "help me develop an Abs operator"
|
|
485
|
-
};
|
|
88
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
89
|
+
import { join as join2, dirname as dirname2 } from "path";
|
|
90
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
91
|
+
var __filename2 = fileURLToPath2(import.meta.url);
|
|
92
|
+
var __dirname2 = dirname2(__filename2);
|
|
93
|
+
function loadLocale(locale) {
|
|
94
|
+
const localePath = join2(__dirname2, "locales", `${locale}.json`);
|
|
95
|
+
try {
|
|
96
|
+
const content = readFileSync2(localePath, "utf-8");
|
|
97
|
+
return JSON.parse(content);
|
|
98
|
+
} catch {
|
|
99
|
+
const fallbackPath = join2(__dirname2, "locales", "zh_CN.json");
|
|
100
|
+
try {
|
|
101
|
+
const content = readFileSync2(fallbackPath, "utf-8");
|
|
102
|
+
return JSON.parse(content);
|
|
103
|
+
} catch {
|
|
104
|
+
return {};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
486
108
|
var currentLang = "zh_CN";
|
|
109
|
+
var messages = loadLocale("zh_CN");
|
|
487
110
|
function setLanguage(lang) {
|
|
488
111
|
currentLang = lang;
|
|
112
|
+
messages = loadLocale(lang);
|
|
489
113
|
}
|
|
490
114
|
function t(key) {
|
|
491
|
-
return
|
|
115
|
+
return messages[key] !== void 0 ? messages[key] : key;
|
|
492
116
|
}
|
|
493
117
|
|
|
494
118
|
// src/utils/paths.ts
|
|
@@ -512,9 +136,9 @@ function validateLevel(level) {
|
|
|
512
136
|
}
|
|
513
137
|
function detectTraeVariant() {
|
|
514
138
|
const home = homedir();
|
|
515
|
-
if (existsSync(
|
|
516
|
-
if (existsSync(
|
|
517
|
-
if (existsSync(
|
|
139
|
+
if (existsSync(join3(home, ".trae-cn"))) return "ide";
|
|
140
|
+
if (existsSync(join3(home, ".marscode"))) return "plugin";
|
|
141
|
+
if (existsSync(join3(home, ".traecli"))) return "cli";
|
|
518
142
|
return "unknown";
|
|
519
143
|
}
|
|
520
144
|
function getConfigRoot(tool, level, base) {
|
|
@@ -522,24 +146,24 @@ function getConfigRoot(tool, level, base) {
|
|
|
522
146
|
if (level === "global") {
|
|
523
147
|
switch (tool) {
|
|
524
148
|
case "opencode":
|
|
525
|
-
return
|
|
149
|
+
return join3(home, ".config", "opencode");
|
|
526
150
|
case "claude":
|
|
527
|
-
return
|
|
151
|
+
return join3(home, ".claude");
|
|
528
152
|
case "trae": {
|
|
529
153
|
const variant = detectTraeVariant();
|
|
530
154
|
switch (variant) {
|
|
531
155
|
case "plugin":
|
|
532
|
-
return
|
|
156
|
+
return join3(home, ".marscode");
|
|
533
157
|
case "cli":
|
|
534
|
-
return
|
|
158
|
+
return join3(home, ".traecli");
|
|
535
159
|
default:
|
|
536
|
-
return
|
|
160
|
+
return join3(home, ".trae-cn");
|
|
537
161
|
}
|
|
538
162
|
}
|
|
539
163
|
case "cursor":
|
|
540
|
-
return
|
|
164
|
+
return join3(home, ".cursor");
|
|
541
165
|
case "copilot":
|
|
542
|
-
return
|
|
166
|
+
return join3(home, ".copilot");
|
|
543
167
|
default:
|
|
544
168
|
throw new Error(
|
|
545
169
|
t("error_invalid_tool").replace("{tool}", tool).replace("{tools}", VALID_TOOLS.join(", "))
|
|
@@ -549,24 +173,24 @@ function getConfigRoot(tool, level, base) {
|
|
|
549
173
|
const baseDir = base || process.cwd();
|
|
550
174
|
switch (tool) {
|
|
551
175
|
case "opencode":
|
|
552
|
-
return
|
|
176
|
+
return join3(baseDir, ".opencode");
|
|
553
177
|
case "claude":
|
|
554
|
-
return
|
|
178
|
+
return join3(baseDir, ".claude");
|
|
555
179
|
case "trae": {
|
|
556
180
|
const variant = detectTraeVariant();
|
|
557
181
|
switch (variant) {
|
|
558
182
|
case "plugin":
|
|
559
|
-
return
|
|
183
|
+
return join3(baseDir, ".marscode");
|
|
560
184
|
case "cli":
|
|
561
|
-
return
|
|
185
|
+
return join3(baseDir, ".traecli");
|
|
562
186
|
default:
|
|
563
|
-
return
|
|
187
|
+
return join3(baseDir, ".trae");
|
|
564
188
|
}
|
|
565
189
|
}
|
|
566
190
|
case "cursor":
|
|
567
|
-
return
|
|
191
|
+
return join3(baseDir, ".cursor");
|
|
568
192
|
case "copilot":
|
|
569
|
-
return
|
|
193
|
+
return join3(baseDir, ".github");
|
|
570
194
|
default:
|
|
571
195
|
throw new Error(
|
|
572
196
|
t("error_invalid_tool").replace("{tool}", tool).replace("{tools}", VALID_TOOLS.join(", "))
|
|
@@ -577,19 +201,19 @@ function getConfigFileName(tool) {
|
|
|
577
201
|
return tool === "claude" ? "CLAUDE.md" : "AGENTS.md";
|
|
578
202
|
}
|
|
579
203
|
function getSkillsDir(configRoot) {
|
|
580
|
-
return
|
|
204
|
+
return join3(configRoot, "skills");
|
|
581
205
|
}
|
|
582
206
|
function getAgentsDir(configRoot) {
|
|
583
|
-
return
|
|
207
|
+
return join3(configRoot, "agents");
|
|
584
208
|
}
|
|
585
209
|
function getManifestPath(configRoot) {
|
|
586
|
-
return
|
|
210
|
+
return join3(configRoot, "cannbot-manifest.json");
|
|
587
211
|
}
|
|
588
212
|
function getCannbotConfigDir() {
|
|
589
|
-
return
|
|
213
|
+
return join3(homedir(), ".cannbot");
|
|
590
214
|
}
|
|
591
215
|
function getCannbotRepoPath() {
|
|
592
|
-
return
|
|
216
|
+
return join3(getCannbotConfigDir(), "repo");
|
|
593
217
|
}
|
|
594
218
|
|
|
595
219
|
// src/core/detector.ts
|
|
@@ -627,12 +251,12 @@ async function detectTrae() {
|
|
|
627
251
|
const home = homedir2();
|
|
628
252
|
const variant = detectTraeVariant();
|
|
629
253
|
let path;
|
|
630
|
-
if (variant === "ide" && existsSync2(
|
|
631
|
-
path =
|
|
632
|
-
} else if (variant === "plugin" && existsSync2(
|
|
633
|
-
path =
|
|
634
|
-
} else if (variant === "cli" && existsSync2(
|
|
635
|
-
path =
|
|
254
|
+
if (variant === "ide" && existsSync2(join4(home, ".trae-cn"))) {
|
|
255
|
+
path = join4(home, ".trae-cn");
|
|
256
|
+
} else if (variant === "plugin" && existsSync2(join4(home, ".marscode"))) {
|
|
257
|
+
path = join4(home, ".marscode");
|
|
258
|
+
} else if (variant === "cli" && existsSync2(join4(home, ".traecli"))) {
|
|
259
|
+
path = join4(home, ".traecli");
|
|
636
260
|
} else if (variant === "unknown") {
|
|
637
261
|
const cmdPath = await getCommandPath("trae");
|
|
638
262
|
if (cmdPath) path = cmdPath;
|
|
@@ -696,13 +320,13 @@ function getAllTools() {
|
|
|
696
320
|
}
|
|
697
321
|
|
|
698
322
|
// src/core/manifest.ts
|
|
699
|
-
import { existsSync as existsSync3, readFileSync } from "fs";
|
|
700
|
-
import { join as
|
|
323
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
324
|
+
import { join as join5 } from "path";
|
|
701
325
|
function readManifest(configRoot) {
|
|
702
326
|
const manifestPath = getManifestPath(configRoot);
|
|
703
327
|
if (existsSync3(manifestPath)) {
|
|
704
328
|
try {
|
|
705
|
-
const content =
|
|
329
|
+
const content = readFileSync3(manifestPath, "utf-8");
|
|
706
330
|
return JSON.parse(content);
|
|
707
331
|
} catch {
|
|
708
332
|
}
|
|
@@ -715,16 +339,16 @@ function readAllManifests(configRoot) {
|
|
|
715
339
|
const standardPath = getManifestPath(configRoot);
|
|
716
340
|
if (existsSync3(standardPath)) {
|
|
717
341
|
try {
|
|
718
|
-
const content =
|
|
342
|
+
const content = readFileSync3(standardPath, "utf-8");
|
|
719
343
|
manifests.push(JSON.parse(content));
|
|
720
344
|
} catch {
|
|
721
345
|
}
|
|
722
346
|
}
|
|
723
347
|
for (const plugin of plugins) {
|
|
724
|
-
const pluginManifestPath =
|
|
348
|
+
const pluginManifestPath = join5(configRoot, `${plugin.id}-manifest.json`);
|
|
725
349
|
if (existsSync3(pluginManifestPath)) {
|
|
726
350
|
try {
|
|
727
|
-
const content =
|
|
351
|
+
const content = readFileSync3(pluginManifestPath, "utf-8");
|
|
728
352
|
manifests.push(JSON.parse(content));
|
|
729
353
|
} catch {
|
|
730
354
|
}
|
|
@@ -767,27 +391,27 @@ function scanInstalled() {
|
|
|
767
391
|
return installed;
|
|
768
392
|
}
|
|
769
393
|
function verifyPluginFilesExist(configRoot, manifest, tool, level) {
|
|
770
|
-
const skillsDir =
|
|
771
|
-
const agentsDir =
|
|
394
|
+
const skillsDir = join5(configRoot, "skills");
|
|
395
|
+
const agentsDir = join5(configRoot, "agents");
|
|
772
396
|
if (manifest.installed_skills && manifest.installed_skills.length > 0) {
|
|
773
397
|
const hasAnySkill = manifest.installed_skills.some((skillId) => {
|
|
774
|
-
const skillPath =
|
|
398
|
+
const skillPath = join5(skillsDir, skillId);
|
|
775
399
|
return existsSync3(skillPath);
|
|
776
400
|
});
|
|
777
401
|
if (!hasAnySkill) return false;
|
|
778
402
|
}
|
|
779
403
|
if (manifest.installed_agents && manifest.installed_agents.length > 0) {
|
|
780
404
|
const hasAnyAgent = manifest.installed_agents.some((agentId) => {
|
|
781
|
-
const agentPath =
|
|
405
|
+
const agentPath = join5(agentsDir, agentId);
|
|
782
406
|
return existsSync3(agentPath);
|
|
783
407
|
});
|
|
784
408
|
if (!hasAnyAgent) return false;
|
|
785
409
|
}
|
|
786
410
|
let agentsMdPath;
|
|
787
411
|
if (tool === "opencode" && level === "project") {
|
|
788
|
-
agentsMdPath =
|
|
412
|
+
agentsMdPath = join5(configRoot, "..", "AGENTS.md");
|
|
789
413
|
} else {
|
|
790
|
-
agentsMdPath =
|
|
414
|
+
agentsMdPath = join5(configRoot, "AGENTS.md");
|
|
791
415
|
}
|
|
792
416
|
if (!existsSync3(agentsMdPath)) return false;
|
|
793
417
|
return true;
|
|
@@ -856,15 +480,15 @@ function showOperationHints(isCheckbox = false) {
|
|
|
856
480
|
}
|
|
857
481
|
|
|
858
482
|
// src/utils/config.ts
|
|
859
|
-
import { existsSync as existsSync4, mkdirSync, readFileSync as
|
|
860
|
-
import { join as
|
|
483
|
+
import { existsSync as existsSync4, mkdirSync, readFileSync as readFileSync4, writeFileSync } from "fs";
|
|
484
|
+
import { join as join6 } from "path";
|
|
861
485
|
import { homedir as homedir3 } from "os";
|
|
862
486
|
import { parse, stringify } from "yaml";
|
|
863
487
|
function getConfigDir() {
|
|
864
|
-
return
|
|
488
|
+
return join6(homedir3(), ".cannbot");
|
|
865
489
|
}
|
|
866
490
|
function getConfigPath() {
|
|
867
|
-
return
|
|
491
|
+
return join6(getConfigDir(), "config.yaml");
|
|
868
492
|
}
|
|
869
493
|
function readConfig() {
|
|
870
494
|
const configPath = getConfigPath();
|
|
@@ -875,7 +499,7 @@ function readConfig() {
|
|
|
875
499
|
};
|
|
876
500
|
}
|
|
877
501
|
try {
|
|
878
|
-
const content =
|
|
502
|
+
const content = readFileSync4(configPath, "utf-8");
|
|
879
503
|
const parsed = parse(content);
|
|
880
504
|
return {
|
|
881
505
|
language: parsed.language || "zh_CN",
|
|
@@ -1181,14 +805,19 @@ async function stepConfirm(tool, level, plugins) {
|
|
|
1181
805
|
}
|
|
1182
806
|
|
|
1183
807
|
// src/core/repository.ts
|
|
1184
|
-
import { existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
|
|
1185
|
-
import { join as
|
|
808
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync6 } from "fs";
|
|
809
|
+
import { join as join8, dirname as dirname4 } from "path";
|
|
810
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
1186
811
|
import { execa as execa2 } from "execa";
|
|
812
|
+
import { parse as parseYaml3 } from "yaml";
|
|
1187
813
|
|
|
1188
814
|
// src/core/scanner.ts
|
|
1189
|
-
import { existsSync as existsSync5, readdirSync, readFileSync as
|
|
1190
|
-
import { join as
|
|
1191
|
-
import {
|
|
815
|
+
import { existsSync as existsSync5, readdirSync as readdirSync2, readFileSync as readFileSync5, statSync, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
816
|
+
import { join as join7, dirname as dirname3 } from "path";
|
|
817
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
818
|
+
import { parse as parseYaml2 } from "yaml";
|
|
819
|
+
var __filename3 = fileURLToPath3(import.meta.url);
|
|
820
|
+
var __dirname3 = dirname3(__filename3);
|
|
1192
821
|
var EXCLUDE_DIRS = /* @__PURE__ */ new Set([
|
|
1193
822
|
"node_modules",
|
|
1194
823
|
".git",
|
|
@@ -1209,36 +838,43 @@ var EXCLUDE_DIRS = /* @__PURE__ */ new Set([
|
|
|
1209
838
|
"docs",
|
|
1210
839
|
"scripts"
|
|
1211
840
|
]);
|
|
1212
|
-
|
|
1213
|
-
"
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
]
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
]
|
|
841
|
+
function loadScanConfig() {
|
|
842
|
+
const configPath = join7(__dirname3, "config", "repository.yaml");
|
|
843
|
+
try {
|
|
844
|
+
const config = parseYaml2(readFileSync5(configPath, "utf-8"));
|
|
845
|
+
return {
|
|
846
|
+
skillDirs: config.scanDirs || ["ops", "model", "graph", "infra", "ops-lab"],
|
|
847
|
+
pluginDirs: config.pluginDirs || ["plugins-official", "plugins-community"]
|
|
848
|
+
};
|
|
849
|
+
} catch {
|
|
850
|
+
return {
|
|
851
|
+
skillDirs: ["ops", "model", "graph", "infra", "ops-lab"],
|
|
852
|
+
pluginDirs: ["plugins-official", "plugins-community"]
|
|
853
|
+
};
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
var scanConfig = loadScanConfig();
|
|
857
|
+
var SKILL_SCAN_DIRS = scanConfig.skillDirs;
|
|
858
|
+
var PLUGIN_SCAN_DIRS = scanConfig.pluginDirs;
|
|
1223
859
|
function scanSkills(repoPath) {
|
|
1224
860
|
const skills = [];
|
|
1225
861
|
const seen = /* @__PURE__ */ new Set();
|
|
1226
862
|
for (const dir of SKILL_SCAN_DIRS) {
|
|
1227
|
-
const fullPath =
|
|
863
|
+
const fullPath = join7(repoPath, dir);
|
|
1228
864
|
if (!existsSync5(fullPath)) continue;
|
|
1229
865
|
scanDirectory(fullPath, repoPath, dir, skills, seen);
|
|
1230
866
|
}
|
|
1231
867
|
for (const pluginDir of PLUGIN_SCAN_DIRS) {
|
|
1232
|
-
const pluginParent =
|
|
868
|
+
const pluginParent = join7(repoPath, pluginDir);
|
|
1233
869
|
if (!existsSync5(pluginParent)) continue;
|
|
1234
870
|
for (const plugin of safeReaddir(pluginParent)) {
|
|
1235
|
-
const pluginPath =
|
|
871
|
+
const pluginPath = join7(pluginParent, plugin);
|
|
1236
872
|
if (!isDirectory(pluginPath)) continue;
|
|
1237
|
-
const skillsDir =
|
|
873
|
+
const skillsDir = join7(pluginPath, "skills");
|
|
1238
874
|
if (existsSync5(skillsDir)) {
|
|
1239
875
|
scanDirectory(skillsDir, repoPath, `${pluginDir}/${plugin}/skills`, skills, seen);
|
|
1240
876
|
}
|
|
1241
|
-
const skillDir =
|
|
877
|
+
const skillDir = join7(pluginPath, "skill");
|
|
1242
878
|
if (existsSync5(skillDir)) {
|
|
1243
879
|
scanDirectory(skillDir, repoPath, `${pluginDir}/${plugin}/skill`, skills, seen);
|
|
1244
880
|
}
|
|
@@ -1248,7 +884,7 @@ function scanSkills(repoPath) {
|
|
|
1248
884
|
}
|
|
1249
885
|
function parseFrontmatter(filePath) {
|
|
1250
886
|
try {
|
|
1251
|
-
const content =
|
|
887
|
+
const content = readFileSync5(filePath, "utf-8");
|
|
1252
888
|
const lines = content.split("\n");
|
|
1253
889
|
if (lines.length < 3) return null;
|
|
1254
890
|
if (lines[0].trim() !== "---") return null;
|
|
@@ -1261,7 +897,7 @@ function parseFrontmatter(filePath) {
|
|
|
1261
897
|
}
|
|
1262
898
|
if (endIndex === -1) return null;
|
|
1263
899
|
const yamlBlock = lines.slice(1, endIndex).map((l) => l.replace(/\r$/, "")).join("\n");
|
|
1264
|
-
const parsed =
|
|
900
|
+
const parsed = parseYaml2(yamlBlock);
|
|
1265
901
|
if (!parsed || typeof parsed !== "object") return null;
|
|
1266
902
|
if (!parsed.name || typeof parsed.name !== "string") return null;
|
|
1267
903
|
return {
|
|
@@ -1274,17 +910,17 @@ function parseFrontmatter(filePath) {
|
|
|
1274
910
|
}
|
|
1275
911
|
function getCurrentCommit(repoPath) {
|
|
1276
912
|
try {
|
|
1277
|
-
const headFile =
|
|
913
|
+
const headFile = join7(repoPath, ".git", "HEAD");
|
|
1278
914
|
if (!existsSync5(headFile)) return "unknown";
|
|
1279
|
-
const headContent =
|
|
915
|
+
const headContent = readFileSync5(headFile, "utf-8").trim();
|
|
1280
916
|
if (headContent.startsWith("ref: ")) {
|
|
1281
|
-
const refPath =
|
|
917
|
+
const refPath = join7(repoPath, ".git", headContent.slice(5));
|
|
1282
918
|
if (existsSync5(refPath)) {
|
|
1283
|
-
return
|
|
919
|
+
return readFileSync5(refPath, "utf-8").trim();
|
|
1284
920
|
}
|
|
1285
|
-
const packedRefsPath =
|
|
921
|
+
const packedRefsPath = join7(repoPath, ".git", "packed-refs");
|
|
1286
922
|
if (existsSync5(packedRefsPath)) {
|
|
1287
|
-
const packedRefs =
|
|
923
|
+
const packedRefs = readFileSync5(packedRefsPath, "utf-8");
|
|
1288
924
|
const refName = headContent.slice(5);
|
|
1289
925
|
const lines = packedRefs.split("\n");
|
|
1290
926
|
for (const line of lines) {
|
|
@@ -1303,7 +939,7 @@ function readScanCache() {
|
|
|
1303
939
|
try {
|
|
1304
940
|
const cachePath = getCachePath();
|
|
1305
941
|
if (!existsSync5(cachePath)) return null;
|
|
1306
|
-
const content =
|
|
942
|
+
const content = readFileSync5(cachePath, "utf-8");
|
|
1307
943
|
const cache = JSON.parse(content);
|
|
1308
944
|
if (!cache.skills || !cache.timestamp) return null;
|
|
1309
945
|
const age = Date.now() - cache.timestamp;
|
|
@@ -1316,7 +952,7 @@ function readScanCache() {
|
|
|
1316
952
|
function writeScanCache(cache) {
|
|
1317
953
|
try {
|
|
1318
954
|
const cachePath = getCachePath();
|
|
1319
|
-
const cacheDir =
|
|
955
|
+
const cacheDir = dirname3(cachePath);
|
|
1320
956
|
if (!existsSync5(cacheDir)) {
|
|
1321
957
|
mkdirSync2(cacheDir, { recursive: true });
|
|
1322
958
|
}
|
|
@@ -1325,10 +961,10 @@ function writeScanCache(cache) {
|
|
|
1325
961
|
}
|
|
1326
962
|
}
|
|
1327
963
|
function getCachePath() {
|
|
1328
|
-
return
|
|
964
|
+
return join7(getCannbotConfigDir(), "scan-cache.json");
|
|
1329
965
|
}
|
|
1330
966
|
function scanDirectory(dirPath, repoPath, sourcePrefix, skills, seen) {
|
|
1331
|
-
const selfSkillMd =
|
|
967
|
+
const selfSkillMd = join7(dirPath, "SKILL.md");
|
|
1332
968
|
if (existsSync5(selfSkillMd)) {
|
|
1333
969
|
const frontmatter = parseFrontmatter(selfSkillMd);
|
|
1334
970
|
if (frontmatter && !seen.has(frontmatter.name)) {
|
|
@@ -1343,10 +979,10 @@ function scanDirectory(dirPath, repoPath, sourcePrefix, skills, seen) {
|
|
|
1343
979
|
return;
|
|
1344
980
|
}
|
|
1345
981
|
for (const entry of safeReaddir(dirPath)) {
|
|
1346
|
-
const fullPath =
|
|
982
|
+
const fullPath = join7(dirPath, entry);
|
|
1347
983
|
if (EXCLUDE_DIRS.has(entry)) continue;
|
|
1348
984
|
if (!isDirectory(fullPath)) continue;
|
|
1349
|
-
const skillMd =
|
|
985
|
+
const skillMd = join7(fullPath, "SKILL.md");
|
|
1350
986
|
if (existsSync5(skillMd)) {
|
|
1351
987
|
const frontmatter = parseFrontmatter(skillMd);
|
|
1352
988
|
if (frontmatter && !seen.has(frontmatter.name)) {
|
|
@@ -1365,7 +1001,7 @@ function scanDirectory(dirPath, repoPath, sourcePrefix, skills, seen) {
|
|
|
1365
1001
|
}
|
|
1366
1002
|
function safeReaddir(dir) {
|
|
1367
1003
|
try {
|
|
1368
|
-
return
|
|
1004
|
+
return readdirSync2(dir);
|
|
1369
1005
|
} catch {
|
|
1370
1006
|
return [];
|
|
1371
1007
|
}
|
|
@@ -1605,7 +1241,21 @@ function getAllCategories() {
|
|
|
1605
1241
|
}
|
|
1606
1242
|
|
|
1607
1243
|
// src/core/repository.ts
|
|
1608
|
-
var
|
|
1244
|
+
var __filename4 = fileURLToPath4(import.meta.url);
|
|
1245
|
+
var __dirname4 = dirname4(__filename4);
|
|
1246
|
+
function loadRepoUrl() {
|
|
1247
|
+
if (process.env.CANNBOT_REPO_URL) {
|
|
1248
|
+
return process.env.CANNBOT_REPO_URL;
|
|
1249
|
+
}
|
|
1250
|
+
const configPath = join8(__dirname4, "config", "repository.yaml");
|
|
1251
|
+
try {
|
|
1252
|
+
const config = parseYaml3(readFileSync6(configPath, "utf-8"));
|
|
1253
|
+
return config.repository?.url || "https://gitcode.com/cann/cannbot-skills.git";
|
|
1254
|
+
} catch {
|
|
1255
|
+
return "https://gitcode.com/cann/cannbot-skills.git";
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
var REPO_URL = loadRepoUrl();
|
|
1609
1259
|
var RepositoryManager = class {
|
|
1610
1260
|
repoPath;
|
|
1611
1261
|
constructor(customPath) {
|
|
@@ -1663,8 +1313,8 @@ var RepositoryManager = class {
|
|
|
1663
1313
|
}
|
|
1664
1314
|
isValidRepo(path) {
|
|
1665
1315
|
if (!existsSync6(path)) return false;
|
|
1666
|
-
const gitDir =
|
|
1667
|
-
const pluginsDir =
|
|
1316
|
+
const gitDir = join8(path, ".git");
|
|
1317
|
+
const pluginsDir = join8(path, "plugins-official");
|
|
1668
1318
|
return existsSync6(gitDir) && existsSync6(pluginsDir);
|
|
1669
1319
|
}
|
|
1670
1320
|
async cloneRepo() {
|
|
@@ -1700,17 +1350,17 @@ function createRepositoryManager(customPath) {
|
|
|
1700
1350
|
|
|
1701
1351
|
// src/core/installer.ts
|
|
1702
1352
|
import { existsSync as existsSync9 } from "fs";
|
|
1703
|
-
import { join as
|
|
1353
|
+
import { join as join11 } from "path";
|
|
1704
1354
|
import { execa as execa3 } from "execa";
|
|
1705
1355
|
|
|
1706
1356
|
// src/core/record.ts
|
|
1707
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as
|
|
1708
|
-
import { join as
|
|
1357
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync4, lstatSync, unlinkSync } from "fs";
|
|
1358
|
+
import { join as join9 } from "path";
|
|
1709
1359
|
function getInstallsDir() {
|
|
1710
|
-
return
|
|
1360
|
+
return join9(getCannbotConfigDir(), "installs");
|
|
1711
1361
|
}
|
|
1712
1362
|
function getRecordPath(pluginId) {
|
|
1713
|
-
return
|
|
1363
|
+
return join9(getInstallsDir(), `${pluginId}.json`);
|
|
1714
1364
|
}
|
|
1715
1365
|
function readRecord(pluginId) {
|
|
1716
1366
|
const recordPath = getRecordPath(pluginId);
|
|
@@ -1718,7 +1368,7 @@ function readRecord(pluginId) {
|
|
|
1718
1368
|
return null;
|
|
1719
1369
|
}
|
|
1720
1370
|
try {
|
|
1721
|
-
const content =
|
|
1371
|
+
const content = readFileSync7(recordPath, "utf-8");
|
|
1722
1372
|
return JSON.parse(content);
|
|
1723
1373
|
} catch {
|
|
1724
1374
|
return null;
|
|
@@ -1742,22 +1392,22 @@ function scanInstalledFiles(pluginId, displayName, tool, level, installPath, con
|
|
|
1742
1392
|
const files = [];
|
|
1743
1393
|
const directories = [];
|
|
1744
1394
|
if (manifest) {
|
|
1745
|
-
const skillsDir =
|
|
1395
|
+
const skillsDir = join9(configRoot, "skills");
|
|
1746
1396
|
if (existsSync7(skillsDir)) {
|
|
1747
1397
|
directories.push(skillsDir);
|
|
1748
1398
|
for (const skillName of manifest.installed_skills || []) {
|
|
1749
|
-
const skillPath =
|
|
1399
|
+
const skillPath = join9(skillsDir, skillName);
|
|
1750
1400
|
if (existsSync7(skillPath) || isSymlink(skillPath)) {
|
|
1751
1401
|
files.push(skillPath);
|
|
1752
1402
|
}
|
|
1753
1403
|
}
|
|
1754
1404
|
}
|
|
1755
|
-
const agentsDir =
|
|
1405
|
+
const agentsDir = join9(configRoot, "agents");
|
|
1756
1406
|
if (existsSync7(agentsDir)) {
|
|
1757
1407
|
directories.push(agentsDir);
|
|
1758
1408
|
for (const agentName of manifest.installed_agents || []) {
|
|
1759
|
-
const agentPath =
|
|
1760
|
-
const agentPathMd =
|
|
1409
|
+
const agentPath = join9(agentsDir, agentName);
|
|
1410
|
+
const agentPathMd = join9(agentsDir, agentName + ".md");
|
|
1761
1411
|
if (existsSync7(agentPath) || isSymlink(agentPath)) {
|
|
1762
1412
|
files.push(agentPath);
|
|
1763
1413
|
} else if (existsSync7(agentPathMd) || isSymlink(agentPathMd)) {
|
|
@@ -1766,30 +1416,30 @@ function scanInstalledFiles(pluginId, displayName, tool, level, installPath, con
|
|
|
1766
1416
|
}
|
|
1767
1417
|
}
|
|
1768
1418
|
}
|
|
1769
|
-
const workflowsLink =
|
|
1419
|
+
const workflowsLink = join9(configRoot, "workflows");
|
|
1770
1420
|
if (isSymlink(workflowsLink)) {
|
|
1771
1421
|
files.push(workflowsLink);
|
|
1772
1422
|
}
|
|
1773
|
-
const manifestPath =
|
|
1423
|
+
const manifestPath = join9(configRoot, "cannbot-manifest.json");
|
|
1774
1424
|
if (existsSync7(manifestPath)) {
|
|
1775
1425
|
files.push(manifestPath);
|
|
1776
1426
|
}
|
|
1777
|
-
const pluginManifestPath =
|
|
1427
|
+
const pluginManifestPath = join9(configRoot, `${pluginId}-manifest.json`);
|
|
1778
1428
|
if (existsSync7(pluginManifestPath)) {
|
|
1779
1429
|
files.push(pluginManifestPath);
|
|
1780
1430
|
}
|
|
1781
1431
|
const configFileName = tool === "claude" ? "CLAUDE.md" : "AGENTS.md";
|
|
1782
|
-
const configFilePath = level === "project" ?
|
|
1432
|
+
const configFilePath = level === "project" ? join9(installPath, configFileName) : join9(configRoot, configFileName);
|
|
1783
1433
|
if (existsSync7(configFilePath)) {
|
|
1784
1434
|
files.push(configFilePath);
|
|
1785
1435
|
}
|
|
1786
1436
|
const repoLinks = ["asc-devkit", "pypto", "tilelang-ascend", "cann-recipes-infer", "cann-samples"];
|
|
1787
1437
|
for (const repoName of repoLinks) {
|
|
1788
|
-
const repoLinkPath =
|
|
1438
|
+
const repoLinkPath = join9(installPath, repoName);
|
|
1789
1439
|
if (isSymlink(repoLinkPath)) {
|
|
1790
1440
|
files.push(repoLinkPath);
|
|
1791
1441
|
}
|
|
1792
|
-
const repoLinkInConfig =
|
|
1442
|
+
const repoLinkInConfig = join9(configRoot, repoName);
|
|
1793
1443
|
if (isSymlink(repoLinkInConfig)) {
|
|
1794
1444
|
files.push(repoLinkInConfig);
|
|
1795
1445
|
}
|
|
@@ -1814,7 +1464,7 @@ function isSymlink(path) {
|
|
|
1814
1464
|
}
|
|
1815
1465
|
}
|
|
1816
1466
|
function getSkillRecordPath() {
|
|
1817
|
-
return
|
|
1467
|
+
return join9(getInstallsDir(), "skills.json");
|
|
1818
1468
|
}
|
|
1819
1469
|
function readSkillRecord() {
|
|
1820
1470
|
const recordPath = getSkillRecordPath();
|
|
@@ -1822,7 +1472,7 @@ function readSkillRecord() {
|
|
|
1822
1472
|
return {};
|
|
1823
1473
|
}
|
|
1824
1474
|
try {
|
|
1825
|
-
const content =
|
|
1475
|
+
const content = readFileSync7(recordPath, "utf-8");
|
|
1826
1476
|
return JSON.parse(content);
|
|
1827
1477
|
} catch {
|
|
1828
1478
|
return {};
|
|
@@ -1872,16 +1522,16 @@ function getInstalledSkills(tool, level, installPath) {
|
|
|
1872
1522
|
const record = readSkillRecord();
|
|
1873
1523
|
const recordedSkills = record[tool]?.[level]?.[installPath]?.skills || [];
|
|
1874
1524
|
const configRoot = getConfigRoot(tool, level);
|
|
1875
|
-
const skillsDir =
|
|
1525
|
+
const skillsDir = join9(configRoot, "skills");
|
|
1876
1526
|
return recordedSkills.filter((skillId) => {
|
|
1877
|
-
const skillPath =
|
|
1527
|
+
const skillPath = join9(skillsDir, skillId);
|
|
1878
1528
|
return existsSync7(skillPath) || isSymlink(skillPath);
|
|
1879
1529
|
});
|
|
1880
1530
|
}
|
|
1881
1531
|
|
|
1882
1532
|
// src/core/backup.ts
|
|
1883
|
-
import { existsSync as existsSync8, copyFileSync, readdirSync as
|
|
1884
|
-
import { join as
|
|
1533
|
+
import { existsSync as existsSync8, copyFileSync, readdirSync as readdirSync3, unlinkSync as unlinkSync2 } from "fs";
|
|
1534
|
+
import { join as join10 } from "path";
|
|
1885
1535
|
function getAgentsFileName(tool) {
|
|
1886
1536
|
return tool === "claude" ? "CLAUDE.md" : "AGENTS.md";
|
|
1887
1537
|
}
|
|
@@ -1896,7 +1546,7 @@ function detectCurrentPlugin(configRoot, tool) {
|
|
|
1896
1546
|
};
|
|
1897
1547
|
}
|
|
1898
1548
|
}
|
|
1899
|
-
const agentsFile =
|
|
1549
|
+
const agentsFile = join10(configRoot, getAgentsFileName(tool));
|
|
1900
1550
|
if (!existsSync8(agentsFile)) {
|
|
1901
1551
|
return null;
|
|
1902
1552
|
}
|
|
@@ -1915,13 +1565,13 @@ function detectCurrentPlugin(configRoot, tool) {
|
|
|
1915
1565
|
return null;
|
|
1916
1566
|
}
|
|
1917
1567
|
function createBackup(configRoot, tool, fromPluginId, fromPluginName) {
|
|
1918
|
-
const agentsFile =
|
|
1568
|
+
const agentsFile = join10(configRoot, getAgentsFileName(tool));
|
|
1919
1569
|
if (!existsSync8(agentsFile)) {
|
|
1920
1570
|
return null;
|
|
1921
1571
|
}
|
|
1922
1572
|
const timestamp = formatTimestamp(/* @__PURE__ */ new Date());
|
|
1923
1573
|
const backupFileName = `${getAgentsFileName(tool)}.cannbot-backup.${fromPluginId}.${timestamp}`;
|
|
1924
|
-
const backupPath =
|
|
1574
|
+
const backupPath = join10(configRoot, backupFileName);
|
|
1925
1575
|
try {
|
|
1926
1576
|
copyFileSync(agentsFile, backupPath);
|
|
1927
1577
|
return {
|
|
@@ -1938,7 +1588,7 @@ function findBackups(configRoot) {
|
|
|
1938
1588
|
if (!existsSync8(configRoot)) {
|
|
1939
1589
|
return [];
|
|
1940
1590
|
}
|
|
1941
|
-
const files =
|
|
1591
|
+
const files = readdirSync3(configRoot);
|
|
1942
1592
|
const backups = [];
|
|
1943
1593
|
for (const file of files) {
|
|
1944
1594
|
if (file.includes(".cannbot-backup.")) {
|
|
@@ -1951,7 +1601,7 @@ function findBackups(configRoot) {
|
|
|
1951
1601
|
const timestamp = pluginIdAndTime.substring(lastDotIndex + 1);
|
|
1952
1602
|
const plugin = findPlugin(pluginId);
|
|
1953
1603
|
backups.push({
|
|
1954
|
-
filePath:
|
|
1604
|
+
filePath: join10(configRoot, file),
|
|
1955
1605
|
pluginId,
|
|
1956
1606
|
pluginName: plugin?.displayName || pluginId,
|
|
1957
1607
|
backupTime: timestamp
|
|
@@ -1964,7 +1614,7 @@ function findBackups(configRoot) {
|
|
|
1964
1614
|
}
|
|
1965
1615
|
function restoreBackup(backupPath, configRoot, tool) {
|
|
1966
1616
|
try {
|
|
1967
|
-
const agentsFile =
|
|
1617
|
+
const agentsFile = join10(configRoot, getAgentsFileName(tool));
|
|
1968
1618
|
copyFileSync(backupPath, agentsFile);
|
|
1969
1619
|
return true;
|
|
1970
1620
|
} catch {
|
|
@@ -2065,7 +1715,7 @@ async function installPlugin(opts) {
|
|
|
2065
1715
|
warnings: []
|
|
2066
1716
|
};
|
|
2067
1717
|
}
|
|
2068
|
-
const scriptPath =
|
|
1718
|
+
const scriptPath = join11(opts.repoPath, plugin.dir, plugin.script);
|
|
2069
1719
|
if (!existsSync9(scriptPath)) {
|
|
2070
1720
|
return {
|
|
2071
1721
|
success: false,
|
|
@@ -2082,7 +1732,7 @@ async function installPlugin(opts) {
|
|
|
2082
1732
|
}
|
|
2083
1733
|
const cwd = opts.installPath || process.cwd();
|
|
2084
1734
|
const configRoot = getConfigRoot(opts.tool, opts.level, opts.installPath);
|
|
2085
|
-
const agentsFile =
|
|
1735
|
+
const agentsFile = join11(configRoot, getAgentsFileName(opts.tool));
|
|
2086
1736
|
let backupInfo = null;
|
|
2087
1737
|
if (existsSync9(agentsFile)) {
|
|
2088
1738
|
const currentPlugin = detectCurrentPlugin(configRoot, opts.tool);
|
|
@@ -2177,14 +1827,14 @@ async function installPlugin(opts) {
|
|
|
2177
1827
|
}
|
|
2178
1828
|
|
|
2179
1829
|
// src/core/skill-installer.ts
|
|
2180
|
-
import { existsSync as existsSync10, mkdirSync as mkdirSync5, symlinkSync, unlinkSync as unlinkSync3, readdirSync as
|
|
2181
|
-
import { join as
|
|
1830
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync5, symlinkSync, unlinkSync as unlinkSync3, readdirSync as readdirSync4, rmdirSync, realpathSync, lstatSync as lstatSync2 } from "fs";
|
|
1831
|
+
import { join as join12 } from "path";
|
|
2182
1832
|
import { select as select3, checkbox as checkbox2, Separator as Separator2 } from "@inquirer/prompts";
|
|
2183
1833
|
import chalk4 from "chalk";
|
|
2184
1834
|
import Table from "cli-table3";
|
|
2185
1835
|
async function installSkills(skillIds, tool, level, repoPath) {
|
|
2186
1836
|
const configRoot = getConfigRoot(tool, level);
|
|
2187
|
-
const skillsDir =
|
|
1837
|
+
const skillsDir = join12(configRoot, "skills");
|
|
2188
1838
|
const installPath = level === "project" ? process.cwd() : configRoot;
|
|
2189
1839
|
if (!existsSync10(skillsDir)) {
|
|
2190
1840
|
mkdirSync5(skillsDir, { recursive: true });
|
|
@@ -2197,8 +1847,8 @@ async function installSkills(skillIds, tool, level, repoPath) {
|
|
|
2197
1847
|
results.push({ skillId, success: false, error: "Skill not found in registry" });
|
|
2198
1848
|
continue;
|
|
2199
1849
|
}
|
|
2200
|
-
const sourcePath =
|
|
2201
|
-
const targetPath =
|
|
1850
|
+
const sourcePath = join12(repoPath, skill.source, skill.id);
|
|
1851
|
+
const targetPath = join12(skillsDir, skillId);
|
|
2202
1852
|
if (!existsSync10(sourcePath)) {
|
|
2203
1853
|
results.push({ skillId, success: false, error: `Source not found: ${sourcePath}` });
|
|
2204
1854
|
continue;
|
|
@@ -2221,12 +1871,12 @@ async function installSkills(skillIds, tool, level, repoPath) {
|
|
|
2221
1871
|
}
|
|
2222
1872
|
async function uninstallSkills(skillIds, tool, level) {
|
|
2223
1873
|
const configRoot = getConfigRoot(tool, level);
|
|
2224
|
-
const skillsDir =
|
|
1874
|
+
const skillsDir = join12(configRoot, "skills");
|
|
2225
1875
|
const installPath = level === "project" ? process.cwd() : configRoot;
|
|
2226
1876
|
const results = [];
|
|
2227
1877
|
const removedIds = [];
|
|
2228
1878
|
for (const skillId of skillIds) {
|
|
2229
|
-
const targetPath =
|
|
1879
|
+
const targetPath = join12(skillsDir, skillId);
|
|
2230
1880
|
try {
|
|
2231
1881
|
if (existsSync10(targetPath) || isSymlink2(targetPath)) {
|
|
2232
1882
|
unlinkSync3(targetPath);
|
|
@@ -2246,7 +1896,7 @@ async function uninstallSkills(skillIds, tool, level) {
|
|
|
2246
1896
|
}
|
|
2247
1897
|
if (existsSync10(skillsDir)) {
|
|
2248
1898
|
try {
|
|
2249
|
-
const entries =
|
|
1899
|
+
const entries = readdirSync4(skillsDir);
|
|
2250
1900
|
if (entries.length === 0) {
|
|
2251
1901
|
rmdirSync(skillsDir);
|
|
2252
1902
|
logger.step(` ${t("uninstall_clean_empty_dir")}: skills/`);
|
|
@@ -2444,8 +2094,10 @@ function printEnhancedSummary(results, tool, configRoot) {
|
|
|
2444
2094
|
""
|
|
2445
2095
|
];
|
|
2446
2096
|
if (successResults.length === 1) {
|
|
2097
|
+
const plugin = findPlugin(successResults[0].pluginId);
|
|
2098
|
+
const docsPath = plugin ? `${plugin.dir}/quickstart.md` : `${successResults[0].pluginId}/quickstart.md`;
|
|
2447
2099
|
lines.push(
|
|
2448
|
-
` ${chalk5.dim(t("install_enhanced_docs"))}: ${chalk5.dim(
|
|
2100
|
+
` ${chalk5.dim(t("install_enhanced_docs"))}: ${chalk5.dim(docsPath)}`
|
|
2449
2101
|
);
|
|
2450
2102
|
}
|
|
2451
2103
|
console.log();
|
|
@@ -2456,15 +2108,15 @@ function printEnhancedSummary(results, tool, configRoot) {
|
|
|
2456
2108
|
}
|
|
2457
2109
|
|
|
2458
2110
|
// src/commands/init.ts
|
|
2459
|
-
import { existsSync as existsSync11, readFileSync as
|
|
2460
|
-
import { join as
|
|
2111
|
+
import { existsSync as existsSync11, readFileSync as readFileSync8 } from "fs";
|
|
2112
|
+
import { join as join13 } from "path";
|
|
2461
2113
|
var BACK2 = "__back__";
|
|
2462
2114
|
var CANCEL2 = "__cancel__";
|
|
2463
2115
|
async function initCommand() {
|
|
2464
2116
|
const cwd = process.cwd();
|
|
2465
|
-
if (existsSync11(
|
|
2117
|
+
if (existsSync11(join13(cwd, "package.json")) && (() => {
|
|
2466
2118
|
try {
|
|
2467
|
-
const pkg = JSON.parse(
|
|
2119
|
+
const pkg = JSON.parse(readFileSync8(join13(cwd, "package.json"), "utf-8"));
|
|
2468
2120
|
return pkg.name === "@cannbot-ai/install-helper";
|
|
2469
2121
|
} catch {
|
|
2470
2122
|
return false;
|
|
@@ -2690,8 +2342,8 @@ async function listCommand() {
|
|
|
2690
2342
|
|
|
2691
2343
|
// src/commands/doctor.ts
|
|
2692
2344
|
import chalk7 from "chalk";
|
|
2693
|
-
import { existsSync as existsSync12, readdirSync as
|
|
2694
|
-
import { join as
|
|
2345
|
+
import { existsSync as existsSync12, readdirSync as readdirSync5, lstatSync as lstatSync3, unlinkSync as unlinkSync4, mkdirSync as mkdirSync6 } from "fs";
|
|
2346
|
+
import { join as join14 } from "path";
|
|
2695
2347
|
async function doctorCommand(options = {}) {
|
|
2696
2348
|
console.log();
|
|
2697
2349
|
console.log(chalk7.bold(` ${t("doctor_title")}`));
|
|
@@ -2737,7 +2389,7 @@ async function doctorCommand(options = {}) {
|
|
|
2737
2389
|
if (existsSync12(skillsDir)) {
|
|
2738
2390
|
const brokenLinks = checkBrokenLinks(skillsDir);
|
|
2739
2391
|
if (brokenLinks === 0) {
|
|
2740
|
-
const count =
|
|
2392
|
+
const count = readdirSync5(skillsDir).length;
|
|
2741
2393
|
console.log(chalk7.green(" \u2713") + ` ${skillsDir} \u2014 ${t("doctor_links_valid").replace("{count}", String(count))}`);
|
|
2742
2394
|
} else {
|
|
2743
2395
|
console.log(chalk7.yellow(" \u26A0") + ` ${skillsDir} \u2014 ${t("doctor_broken_links").replace("{count}", String(brokenLinks))}`);
|
|
@@ -2759,7 +2411,7 @@ async function doctorCommand(options = {}) {
|
|
|
2759
2411
|
if (existsSync12(agentsDir)) {
|
|
2760
2412
|
const brokenLinks = checkBrokenLinks(agentsDir);
|
|
2761
2413
|
if (brokenLinks === 0) {
|
|
2762
|
-
const count =
|
|
2414
|
+
const count = readdirSync5(agentsDir).length;
|
|
2763
2415
|
console.log(chalk7.green(" \u2713") + ` ${agentsDir} \u2014 ${t("doctor_links_valid").replace("{count}", String(count))}`);
|
|
2764
2416
|
} else {
|
|
2765
2417
|
console.log(chalk7.yellow(" \u26A0") + ` ${agentsDir} \u2014 ${t("doctor_broken_links").replace("{count}", String(brokenLinks))}`);
|
|
@@ -2781,7 +2433,7 @@ async function doctorCommand(options = {}) {
|
|
|
2781
2433
|
console.log();
|
|
2782
2434
|
console.log(chalk7.bold(` ${t("doctor_config")}`));
|
|
2783
2435
|
const configFile = getConfigFileName(primaryTool);
|
|
2784
|
-
const configPath =
|
|
2436
|
+
const configPath = join14(process.cwd(), configFile);
|
|
2785
2437
|
if (existsSync12(configPath)) {
|
|
2786
2438
|
console.log(chalk7.green(" \u2713") + ` ${configFile} ${t("doctor_config_exists")}`);
|
|
2787
2439
|
} else {
|
|
@@ -2803,9 +2455,9 @@ async function doctorCommand(options = {}) {
|
|
|
2803
2455
|
function checkBrokenLinks(dir) {
|
|
2804
2456
|
let broken = 0;
|
|
2805
2457
|
try {
|
|
2806
|
-
const entries =
|
|
2458
|
+
const entries = readdirSync5(dir);
|
|
2807
2459
|
for (const entry of entries) {
|
|
2808
|
-
const fullPath =
|
|
2460
|
+
const fullPath = join14(dir, entry);
|
|
2809
2461
|
try {
|
|
2810
2462
|
const stats = lstatSync3(fullPath);
|
|
2811
2463
|
if (stats.isSymbolicLink()) {
|
|
@@ -2824,9 +2476,9 @@ function checkBrokenLinks(dir) {
|
|
|
2824
2476
|
function fixBrokenLinks(dir) {
|
|
2825
2477
|
let fixed = 0;
|
|
2826
2478
|
try {
|
|
2827
|
-
const entries =
|
|
2479
|
+
const entries = readdirSync5(dir);
|
|
2828
2480
|
for (const entry of entries) {
|
|
2829
|
-
const fullPath =
|
|
2481
|
+
const fullPath = join14(dir, entry);
|
|
2830
2482
|
try {
|
|
2831
2483
|
const stats = lstatSync3(fullPath);
|
|
2832
2484
|
if (stats.isSymbolicLink()) {
|
|
@@ -3105,7 +2757,7 @@ async function installPlugins(pluginIds, tool, level, repoPath) {
|
|
|
3105
2757
|
}
|
|
3106
2758
|
|
|
3107
2759
|
// src/commands/uninstall.ts
|
|
3108
|
-
import { existsSync as existsSync13, unlinkSync as unlinkSync5, rmdirSync as rmdirSync2, readdirSync as
|
|
2760
|
+
import { existsSync as existsSync13, unlinkSync as unlinkSync5, rmdirSync as rmdirSync2, readdirSync as readdirSync6, lstatSync as lstatSync4 } from "fs";
|
|
3109
2761
|
import chalk10 from "chalk";
|
|
3110
2762
|
async function uninstallCommand(names, options) {
|
|
3111
2763
|
const tool = options.tool ? validateTool(options.tool) : "opencode";
|
|
@@ -3156,7 +2808,7 @@ async function uninstallCommand(names, options) {
|
|
|
3156
2808
|
continue;
|
|
3157
2809
|
}
|
|
3158
2810
|
if (existsSync13(dirPath)) {
|
|
3159
|
-
const entries =
|
|
2811
|
+
const entries = readdirSync6(dirPath);
|
|
3160
2812
|
if (entries.length === 0) {
|
|
3161
2813
|
rmdirSync2(dirPath);
|
|
3162
2814
|
const name = dirPath.split("/").pop() || dirPath;
|
|
@@ -3300,8 +2952,8 @@ async function updateCommand(pluginNames, options) {
|
|
|
3300
2952
|
|
|
3301
2953
|
// src/commands/info.ts
|
|
3302
2954
|
import chalk12 from "chalk";
|
|
3303
|
-
import { existsSync as existsSync14, readdirSync as
|
|
3304
|
-
import { join as
|
|
2955
|
+
import { existsSync as existsSync14, readdirSync as readdirSync7 } from "fs";
|
|
2956
|
+
import { join as join15 } from "path";
|
|
3305
2957
|
async function infoCommand(pluginName) {
|
|
3306
2958
|
const plugin = findPlugin(pluginName);
|
|
3307
2959
|
if (!plugin) {
|
|
@@ -3325,13 +2977,13 @@ async function infoCommand(pluginName) {
|
|
|
3325
2977
|
try {
|
|
3326
2978
|
const repoManager = createRepositoryManager();
|
|
3327
2979
|
const repoPath = await repoManager.ensureRepo();
|
|
3328
|
-
const quickstartPath =
|
|
2980
|
+
const quickstartPath = join15(repoPath, plugin.dir, "quickstart.md");
|
|
3329
2981
|
if (existsSync14(quickstartPath)) {
|
|
3330
2982
|
console.log(` ${chalk12.dim(t("info_quickstart") + ":")} ${quickstartPath}`);
|
|
3331
2983
|
}
|
|
3332
|
-
const agentsDir =
|
|
2984
|
+
const agentsDir = join15(repoPath, plugin.dir, "agents");
|
|
3333
2985
|
if (existsSync14(agentsDir)) {
|
|
3334
|
-
const agentFiles =
|
|
2986
|
+
const agentFiles = readdirSync7(agentsDir).filter((f) => f.endsWith(".md"));
|
|
3335
2987
|
if (agentFiles.length > 0) {
|
|
3336
2988
|
console.log();
|
|
3337
2989
|
console.log(` ${chalk12.bold("Agents:")}`);
|
|
@@ -3388,7 +3040,7 @@ function createCLI() {
|
|
|
3388
3040
|
setLanguage(config.language);
|
|
3389
3041
|
}
|
|
3390
3042
|
const program2 = new Command();
|
|
3391
|
-
program2.name("install-helper").description("CANNBot Install Helper - Interactive installer for CANN operator development skills").version("1.0.
|
|
3043
|
+
program2.name("install-helper").description("CANNBot Install Helper - Interactive installer for CANN operator development skills").version("1.0.4");
|
|
3392
3044
|
program2.command("init", { isDefault: false }).description("Run interactive installation wizard").action(async () => {
|
|
3393
3045
|
await initCommand();
|
|
3394
3046
|
});
|