@cannbot-ai/install-helper 0.0.2-beta.1 → 0.0.2-beta.11
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 +789 -427
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/init.ts
|
|
7
|
-
import { select as
|
|
8
|
-
import
|
|
7
|
+
import { select as select4, Separator as Separator3 } from "@inquirer/prompts";
|
|
8
|
+
import chalk6 from "chalk";
|
|
9
9
|
|
|
10
10
|
// src/ui/wizard.ts
|
|
11
11
|
import { select, checkbox, Separator } from "@inquirer/prompts";
|
|
@@ -145,6 +145,309 @@ import { join as join2 } from "path";
|
|
|
145
145
|
import { homedir } from "os";
|
|
146
146
|
import { join } from "path";
|
|
147
147
|
import { existsSync } from "fs";
|
|
148
|
+
|
|
149
|
+
// src/utils/i18n.ts
|
|
150
|
+
var zh_CN = {
|
|
151
|
+
wizard_title: "CANNBot Install Helper",
|
|
152
|
+
wizard_detect: "\u6B63\u5728\u68C0\u6D4B\u5DF2\u5B89\u88C5\u7684 AI \u7F16\u7A0B\u5DE5\u5177...",
|
|
153
|
+
wizard_select_tool: "\u9009\u62E9 AI \u7F16\u7A0B\u5DE5\u5177",
|
|
154
|
+
wizard_select_level: "\u9009\u62E9\u5B89\u88C5\u4F4D\u7F6E",
|
|
155
|
+
wizard_select_plugins: "\u9009\u62E9\u8981\u5B89\u88C5\u7684\u63D2\u4EF6",
|
|
156
|
+
wizard_confirm: "\u786E\u8BA4\u5B89\u88C5",
|
|
157
|
+
wizard_detected_tool: "\u68C0\u6D4B\u5230",
|
|
158
|
+
wizard_confirm_tool: "\u4F7F\u7528",
|
|
159
|
+
wizard_last_used: "\u4E0A\u6B21\u4F7F\u7528",
|
|
160
|
+
wizard_already_installed: "\u5DF2\u5B89\u88C5",
|
|
161
|
+
install_cloning: "\u6B63\u5728\u514B\u9686 cannbot-skills \u4ED3\u5E93...",
|
|
162
|
+
install_repo_ready: "\u4ED3\u5E93\u5C31\u7EEA",
|
|
163
|
+
install_progress: "\u6B63\u5728\u5B89\u88C5",
|
|
164
|
+
install_done: "\u5B89\u88C5\u5B8C\u6210",
|
|
165
|
+
install_success: "\u6210\u529F",
|
|
166
|
+
install_failed: "\u5931\u8D25",
|
|
167
|
+
install_already_installed: "\u5DF2\u5B89\u88C5",
|
|
168
|
+
install_reinstall_confirm: "\u662F\u5426\u91CD\u65B0\u5B89\u88C5\uFF08\u8986\u76D6\uFF09",
|
|
169
|
+
install_skip: "\u8DF3\u8FC7",
|
|
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
|
+
};
|
|
287
|
+
var en_US = {
|
|
288
|
+
wizard_title: "CANNBot Install Helper",
|
|
289
|
+
wizard_detect: "Detecting installed AI coding tools...",
|
|
290
|
+
wizard_select_tool: "Select AI coding tool",
|
|
291
|
+
wizard_select_level: "Select install level",
|
|
292
|
+
wizard_select_plugins: "Select scenarios to install",
|
|
293
|
+
wizard_confirm: "Confirm installation",
|
|
294
|
+
wizard_detected_tool: "Detected",
|
|
295
|
+
wizard_confirm_tool: "Confirm using",
|
|
296
|
+
wizard_last_used: "last used",
|
|
297
|
+
wizard_already_installed: "installed",
|
|
298
|
+
install_cloning: "Cloning cannbot-skills repository...",
|
|
299
|
+
install_repo_ready: "Repository ready",
|
|
300
|
+
install_progress: "Installing",
|
|
301
|
+
install_done: "Installation complete",
|
|
302
|
+
install_success: "success",
|
|
303
|
+
install_failed: "failed",
|
|
304
|
+
install_already_installed: "already installed",
|
|
305
|
+
install_reinstall_confirm: "Reinstall (overwrite)",
|
|
306
|
+
install_skip: "skipped",
|
|
307
|
+
install_enhanced_next_steps: "Next steps",
|
|
308
|
+
install_enhanced_launch: "Launch",
|
|
309
|
+
install_enhanced_try: "Try",
|
|
310
|
+
install_enhanced_more: "More",
|
|
311
|
+
install_enhanced_check: "Check",
|
|
312
|
+
install_enhanced_docs: "Docs",
|
|
313
|
+
update_title: "Update installed Skills",
|
|
314
|
+
update_updating: "Updating",
|
|
315
|
+
update_done: "Update complete",
|
|
316
|
+
update_no_plugins: "No installed plugins",
|
|
317
|
+
doctor_title: "CANNBot Doctor",
|
|
318
|
+
doctor_tools: "AI Tools",
|
|
319
|
+
doctor_plugins: "Installed Plugins",
|
|
320
|
+
doctor_links: "Link Integrity",
|
|
321
|
+
doctor_config: "Configuration",
|
|
322
|
+
doctor_result: "Result",
|
|
323
|
+
doctor_fix_title: "Auto-fix",
|
|
324
|
+
doctor_fix_cleaning: "Cleaning broken links",
|
|
325
|
+
doctor_fix_rebuilding: "Rebuilding directories",
|
|
326
|
+
doctor_fix_done: "Fix complete",
|
|
327
|
+
info_title: "Plugin Details",
|
|
328
|
+
info_description: "Description",
|
|
329
|
+
info_skills: "Skills",
|
|
330
|
+
info_agents: "Agents",
|
|
331
|
+
info_status: "Status",
|
|
332
|
+
info_quickstart: "Quick Start",
|
|
333
|
+
info_not_found: "Plugin not found",
|
|
334
|
+
lang_title: "Language Settings",
|
|
335
|
+
lang_current: "Current language",
|
|
336
|
+
lang_set: "Language set to",
|
|
337
|
+
lang_invalid: "Invalid language, supported: zh_CN, en_US",
|
|
338
|
+
list_title: "Available Scenarios",
|
|
339
|
+
list_id: "#",
|
|
340
|
+
list_name: "Name",
|
|
341
|
+
list_status: "Status",
|
|
342
|
+
list_skills: "Skills",
|
|
343
|
+
list_agents: "Agents",
|
|
344
|
+
status_installed: "installed",
|
|
345
|
+
status_not_installed: "not installed",
|
|
346
|
+
error_tool_not_found: "No AI coding tool detected",
|
|
347
|
+
error_plugin_not_found: "Plugin not found",
|
|
348
|
+
error_repo_not_found: "Repository not found",
|
|
349
|
+
error_invalid_tool: "Unsupported AI tool: {tool}\nSupported tools: {tools}",
|
|
350
|
+
error_invalid_level: "Unsupported install level: {level}\nSupported levels: {levels}",
|
|
351
|
+
quick_start: "Launch command",
|
|
352
|
+
quick_start_hint: "Try: help me develop an Abs operator",
|
|
353
|
+
skill_select_category: "Select Skill category",
|
|
354
|
+
skill_select_items: "Select Skills to install (space to toggle, enter to confirm)",
|
|
355
|
+
skill_already_installed: "installed",
|
|
356
|
+
skill_install_progress: "Installing",
|
|
357
|
+
skill_install_done: "Skill installation complete",
|
|
358
|
+
skill_uninstall_done: "Skill uninstallation complete",
|
|
359
|
+
skill_list_title: "Available Skills",
|
|
360
|
+
wizard_select_mode: "Select installation mode",
|
|
361
|
+
wizard_mode_plugin: "Install Plugin",
|
|
362
|
+
wizard_mode_plugin_desc: "Full development workflow (Skills + Agents + config)",
|
|
363
|
+
wizard_mode_skill: "Install Skill",
|
|
364
|
+
wizard_mode_skill_desc: "Domain knowledge only, give AI specific capabilities",
|
|
365
|
+
wizard_back: "Go back",
|
|
366
|
+
wizard_cancel: "Cancel installation",
|
|
367
|
+
wizard_no_selection: "No items selected, please choose an action",
|
|
368
|
+
wizard_back_to_reselect: "Go back",
|
|
369
|
+
status_title: "Installed Plugins",
|
|
370
|
+
status_none: "No installed plugins",
|
|
371
|
+
status_hint: "Run install-helper init to start",
|
|
372
|
+
status_install_time: "Installed at",
|
|
373
|
+
install_installed_to: "Installed to",
|
|
374
|
+
install_skills_count: "Skills",
|
|
375
|
+
install_agents_count: "Agents",
|
|
376
|
+
lang_supported: "Supported languages: zh_CN, en_US",
|
|
377
|
+
lang_usage: "Usage: install-helper lang set <language>",
|
|
378
|
+
lang_specify: "Please specify language: install-helper lang set zh_CN",
|
|
379
|
+
lang_unknown_action: "Unknown action",
|
|
380
|
+
lang_supported_actions: "Supported actions: show, set",
|
|
381
|
+
info_aliases: "Aliases",
|
|
382
|
+
uninstall_not_found: "Not found",
|
|
383
|
+
uninstall_no_record: "No install record found, may not be installed or record is corrupted",
|
|
384
|
+
uninstall_no_record_hint: "For manual cleanup, delete related files in .opencode/ or .claude/ directory",
|
|
385
|
+
uninstall_in_progress: "Uninstalling",
|
|
386
|
+
uninstall_removed: "Uninstalled",
|
|
387
|
+
uninstall_files_gone: " files no longer exist, install record cleaned",
|
|
388
|
+
uninstall_skills_in_progress: "Uninstalling",
|
|
389
|
+
init_pkg_dir_warn: "Current directory appears to be the install-helper package directory",
|
|
390
|
+
init_pkg_dir_hint: "Please run this command in your project directory, not in the install-helper package directory",
|
|
391
|
+
init_pkg_dir_example: "Example: cd ~/my-project && install-helper",
|
|
392
|
+
init_cancelled: "Installation cancelled",
|
|
393
|
+
backup_detected: "Plugin already installed in current directory",
|
|
394
|
+
backup_current: "Currently installed",
|
|
395
|
+
backup_installing: "About to install",
|
|
396
|
+
backup_overwrite_warning: "Continuing will overwrite existing AGENTS.md configuration.",
|
|
397
|
+
backup_auto_create: "System will automatically create backup for future restoration.",
|
|
398
|
+
backup_overwrite: "Overwrite (auto backup)",
|
|
399
|
+
backup_cancel: "Cancel installation",
|
|
400
|
+
backup_restore_prompt: "Backup configuration detected, restore?",
|
|
401
|
+
backup_restore: "Restore",
|
|
402
|
+
backup_only_uninstall: "Uninstall only (no restore)",
|
|
403
|
+
backup_select_action: "Please select an action",
|
|
404
|
+
backup_restore_success: "Configuration restored",
|
|
405
|
+
backup_created: "Backup created",
|
|
406
|
+
loading_skills_list: "Loading Skills list...",
|
|
407
|
+
loading_skills_list_complete: "Skills list loaded",
|
|
408
|
+
loading_plugin_data: "Loading plugin data...",
|
|
409
|
+
loading_plugin_data_complete: "Plugin data loaded",
|
|
410
|
+
loading_skills_list_failed: "Failed to load Skills list, using built-in data",
|
|
411
|
+
install_no_skill_selected: "No Skill selected",
|
|
412
|
+
install_to: "Install to",
|
|
413
|
+
start_to_use: "Start {tool} to use",
|
|
414
|
+
wizard_step_1_title: "[1/4] Select AI coding tool",
|
|
415
|
+
wizard_step_2_title: "[2/4] Select installation location",
|
|
416
|
+
wizard_step_3_title: "[3/4] Select plugins to install",
|
|
417
|
+
wizard_step_4_title: "[4/4] Confirm installation",
|
|
418
|
+
wizard_step_3_skill_title: "[3/4] Select Skill category",
|
|
419
|
+
wizard_step_4_skill_title: "[4/4] Select Skills to install \u2014 {category}",
|
|
420
|
+
install_level_project: "Install to current directory (recommended, current project only)",
|
|
421
|
+
install_level_global: "Install globally (all projects)",
|
|
422
|
+
wizard_select_mode_title: "Select installation type"
|
|
423
|
+
};
|
|
424
|
+
var currentLang = "zh_CN";
|
|
425
|
+
function setLanguage(lang) {
|
|
426
|
+
currentLang = lang;
|
|
427
|
+
}
|
|
428
|
+
function t(key) {
|
|
429
|
+
return currentLang === "zh_CN" ? zh_CN[key] : en_US[key];
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// src/utils/paths.ts
|
|
433
|
+
var VALID_TOOLS = ["opencode", "claude", "trae", "cursor", "copilot"];
|
|
434
|
+
var VALID_LEVELS = ["project", "global"];
|
|
435
|
+
function validateTool(tool) {
|
|
436
|
+
if (!VALID_TOOLS.includes(tool)) {
|
|
437
|
+
throw new Error(
|
|
438
|
+
t("error_invalid_tool").replace("{tool}", tool).replace("{tools}", VALID_TOOLS.join(", "))
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
return tool;
|
|
442
|
+
}
|
|
443
|
+
function validateLevel(level) {
|
|
444
|
+
if (!VALID_LEVELS.includes(level)) {
|
|
445
|
+
throw new Error(
|
|
446
|
+
t("error_invalid_level").replace("{level}", level).replace("{levels}", VALID_LEVELS.join(", "))
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
return level;
|
|
450
|
+
}
|
|
148
451
|
function detectTraeVariant() {
|
|
149
452
|
const home = homedir();
|
|
150
453
|
if (existsSync(join(home, ".trae-cn"))) return "ide";
|
|
@@ -175,6 +478,10 @@ function getConfigRoot(tool, level, base) {
|
|
|
175
478
|
return join(home, ".cursor");
|
|
176
479
|
case "copilot":
|
|
177
480
|
return join(home, ".copilot");
|
|
481
|
+
default:
|
|
482
|
+
throw new Error(
|
|
483
|
+
t("error_invalid_tool").replace("{tool}", tool).replace("{tools}", VALID_TOOLS.join(", "))
|
|
484
|
+
);
|
|
178
485
|
}
|
|
179
486
|
}
|
|
180
487
|
const baseDir = base || process.cwd();
|
|
@@ -198,6 +505,10 @@ function getConfigRoot(tool, level, base) {
|
|
|
198
505
|
return join(baseDir, ".cursor");
|
|
199
506
|
case "copilot":
|
|
200
507
|
return join(baseDir, ".github");
|
|
508
|
+
default:
|
|
509
|
+
throw new Error(
|
|
510
|
+
t("error_invalid_tool").replace("{tool}", tool).replace("{tools}", VALID_TOOLS.join(", "))
|
|
511
|
+
);
|
|
201
512
|
}
|
|
202
513
|
}
|
|
203
514
|
function getConfigFileName(tool) {
|
|
@@ -232,7 +543,7 @@ async function getCommandVersion(cmd, args = ["--version"]) {
|
|
|
232
543
|
}
|
|
233
544
|
async function getCommandPath(cmd) {
|
|
234
545
|
try {
|
|
235
|
-
const result = await execa("
|
|
546
|
+
const result = await execa("which", [cmd], { timeout: 5e3 });
|
|
236
547
|
return result.stdout.trim();
|
|
237
548
|
} catch {
|
|
238
549
|
return void 0;
|
|
@@ -391,185 +702,6 @@ function scanInstalled() {
|
|
|
391
702
|
return installed;
|
|
392
703
|
}
|
|
393
704
|
|
|
394
|
-
// src/utils/i18n.ts
|
|
395
|
-
var zh_CN = {
|
|
396
|
-
wizard_title: "CANNBot Install Helper",
|
|
397
|
-
wizard_detect: "\u6B63\u5728\u68C0\u6D4B\u5DF2\u5B89\u88C5\u7684 AI \u7F16\u7A0B\u5DE5\u5177...",
|
|
398
|
-
wizard_select_tool: "\u9009\u62E9 AI \u7F16\u7A0B\u5DE5\u5177",
|
|
399
|
-
wizard_select_level: "\u9009\u62E9\u5B89\u88C5\u4F4D\u7F6E",
|
|
400
|
-
wizard_select_plugins: "\u9009\u62E9\u8981\u5B89\u88C5\u7684\u63D2\u4EF6",
|
|
401
|
-
wizard_confirm: "\u786E\u8BA4\u5B89\u88C5",
|
|
402
|
-
wizard_detected_tool: "\u68C0\u6D4B\u5230",
|
|
403
|
-
wizard_confirm_tool: "\u4F7F\u7528",
|
|
404
|
-
wizard_last_used: "\u4E0A\u6B21\u4F7F\u7528",
|
|
405
|
-
wizard_already_installed: "\u5DF2\u5B89\u88C5",
|
|
406
|
-
install_cloning: "\u6B63\u5728\u514B\u9686 cannbot-skills \u4ED3\u5E93...",
|
|
407
|
-
install_repo_ready: "\u4ED3\u5E93\u5C31\u7EEA",
|
|
408
|
-
install_progress: "\u6B63\u5728\u5B89\u88C5",
|
|
409
|
-
install_done: "\u5B89\u88C5\u5B8C\u6210",
|
|
410
|
-
install_success: "\u6210\u529F",
|
|
411
|
-
install_failed: "\u5931\u8D25",
|
|
412
|
-
install_already_installed: "\u5DF2\u5B89\u88C5",
|
|
413
|
-
install_reinstall_confirm: "\u662F\u5426\u91CD\u65B0\u5B89\u88C5\uFF08\u8986\u76D6\uFF09",
|
|
414
|
-
install_skip: "\u8DF3\u8FC7",
|
|
415
|
-
install_enhanced_next_steps: "\u4E0B\u4E00\u6B65",
|
|
416
|
-
install_enhanced_launch: "\u542F\u52A8",
|
|
417
|
-
install_enhanced_try: "\u8BD5\u8BD5",
|
|
418
|
-
install_enhanced_more: "\u66F4\u591A",
|
|
419
|
-
install_enhanced_check: "\u68C0\u67E5",
|
|
420
|
-
install_enhanced_docs: "\u6587\u6863",
|
|
421
|
-
update_title: "\u66F4\u65B0\u5DF2\u5B89\u88C5\u7684 Skills",
|
|
422
|
-
update_updating: "\u6B63\u5728\u66F4\u65B0",
|
|
423
|
-
update_done: "\u66F4\u65B0\u5B8C\u6210",
|
|
424
|
-
update_no_plugins: "\u6682\u65E0\u5DF2\u5B89\u88C5\u7684\u63D2\u4EF6",
|
|
425
|
-
doctor_title: "CANNBot Doctor",
|
|
426
|
-
doctor_tools: "AI \u5DE5\u5177",
|
|
427
|
-
doctor_plugins: "\u5DF2\u5B89\u88C5\u63D2\u4EF6",
|
|
428
|
-
doctor_links: "\u94FE\u63A5\u5B8C\u6574\u6027",
|
|
429
|
-
doctor_config: "\u914D\u7F6E\u6587\u4EF6",
|
|
430
|
-
doctor_result: "\u7ED3\u679C",
|
|
431
|
-
doctor_fix_title: "\u81EA\u52A8\u4FEE\u590D",
|
|
432
|
-
doctor_fix_cleaning: "\u6E05\u7406\u5931\u6548\u94FE\u63A5",
|
|
433
|
-
doctor_fix_rebuilding: "\u91CD\u5EFA\u76EE\u5F55",
|
|
434
|
-
doctor_fix_done: "\u4FEE\u590D\u5B8C\u6210",
|
|
435
|
-
info_title: "\u63D2\u4EF6\u8BE6\u60C5",
|
|
436
|
-
info_description: "\u63CF\u8FF0",
|
|
437
|
-
info_skills: "Skills",
|
|
438
|
-
info_agents: "Agents",
|
|
439
|
-
info_status: "\u72B6\u6001",
|
|
440
|
-
info_quickstart: "\u5FEB\u901F\u5F00\u59CB",
|
|
441
|
-
info_not_found: "\u672A\u627E\u5230\u63D2\u4EF6",
|
|
442
|
-
lang_title: "\u8BED\u8A00\u8BBE\u7F6E",
|
|
443
|
-
lang_current: "\u5F53\u524D\u8BED\u8A00",
|
|
444
|
-
lang_set: "\u8BED\u8A00\u5DF2\u8BBE\u7F6E\u4E3A",
|
|
445
|
-
lang_invalid: "\u65E0\u6548\u7684\u8BED\u8A00\uFF0C\u652F\u6301: zh_CN, en_US",
|
|
446
|
-
list_title: "\u53EF\u7528\u573A\u666F",
|
|
447
|
-
list_id: "\u5E8F\u53F7",
|
|
448
|
-
list_name: "\u573A\u666F\u540D",
|
|
449
|
-
list_status: "\u72B6\u6001",
|
|
450
|
-
list_skills: "Skills",
|
|
451
|
-
list_agents: "Agents",
|
|
452
|
-
status_installed: "\u5DF2\u88C5",
|
|
453
|
-
status_not_installed: "\u672A\u88C5",
|
|
454
|
-
error_tool_not_found: "\u672A\u68C0\u6D4B\u5230\u4EFB\u4F55 AI \u7F16\u7A0B\u5DE5\u5177",
|
|
455
|
-
error_plugin_not_found: "\u672A\u627E\u5230\u63D2\u4EF6",
|
|
456
|
-
error_repo_not_found: "\u4ED3\u5E93\u672A\u627E\u5230",
|
|
457
|
-
quick_start: "\u542F\u52A8\u547D\u4EE4",
|
|
458
|
-
quick_start_hint: "\u8BD5\u8BD5\u8F93\u5165: \u5E2E\u6211\u5F00\u53D1\u4E00\u4E2A Abs \u7B97\u5B50",
|
|
459
|
-
skill_select_category: "\u9009\u62E9 Skill \u7C7B\u522B",
|
|
460
|
-
skill_select_items: "\u9009\u62E9\u8981\u5B89\u88C5\u7684 Skills",
|
|
461
|
-
skill_already_installed: "\u5DF2\u5B89\u88C5",
|
|
462
|
-
skill_install_progress: "\u6B63\u5728\u5B89\u88C5",
|
|
463
|
-
skill_install_done: "Skill \u5B89\u88C5\u5B8C\u6210",
|
|
464
|
-
skill_uninstall_done: "Skill \u5378\u8F7D\u5B8C\u6210",
|
|
465
|
-
skill_list_title: "\u53EF\u7528 Skills",
|
|
466
|
-
wizard_select_mode: "\u9009\u62E9\u5B89\u88C5\u7C7B\u578B",
|
|
467
|
-
wizard_mode_plugin: "\u5B89\u88C5 Plugin",
|
|
468
|
-
wizard_mode_plugin_desc: "\u5B8C\u6574\u5F00\u53D1\u5DE5\u4F5C\u6D41\uFF08Skills + Agents + \u914D\u7F6E\u6587\u4EF6\uFF09",
|
|
469
|
-
wizard_mode_skill: "\u5B89\u88C5 Skill",
|
|
470
|
-
wizard_mode_skill_desc: "\u4EC5\u5B89\u88C5\u9886\u57DF\u77E5\u8BC6\u6280\u80FD\uFF0C\u8BA9 AI \u638C\u63E1\u7279\u5B9A\u80FD\u529B",
|
|
471
|
-
wizard_back: "\u8FD4\u56DE",
|
|
472
|
-
wizard_cancel: "\u9000\u51FA",
|
|
473
|
-
wizard_no_selection: "\u672A\u9009\u62E9\u4EFB\u4F55\u9879\uFF0C\u8BF7\u9009\u62E9\u64CD\u4F5C",
|
|
474
|
-
wizard_back_to_reselect: "\u8FD4\u56DE",
|
|
475
|
-
status_title: "\u5DF2\u5B89\u88C5\u63D2\u4EF6",
|
|
476
|
-
status_none: "\u6682\u65E0\u5DF2\u5B89\u88C5\u7684\u63D2\u4EF6",
|
|
477
|
-
status_hint: "\u8FD0\u884C install-helper init \u5F00\u59CB\u5B89\u88C5",
|
|
478
|
-
status_install_time: "\u5B89\u88C5\u65F6\u95F4"
|
|
479
|
-
};
|
|
480
|
-
var en_US = {
|
|
481
|
-
wizard_title: "CANNBot Skills Setup Wizard",
|
|
482
|
-
wizard_detect: "Detecting installed AI coding tools...",
|
|
483
|
-
wizard_select_tool: "Select AI coding tool",
|
|
484
|
-
wizard_select_level: "Select install level",
|
|
485
|
-
wizard_select_plugins: "Select scenarios to install",
|
|
486
|
-
wizard_confirm: "Confirm installation",
|
|
487
|
-
wizard_detected_tool: "Detected",
|
|
488
|
-
wizard_confirm_tool: "Confirm using",
|
|
489
|
-
wizard_last_used: "last used",
|
|
490
|
-
wizard_already_installed: "installed",
|
|
491
|
-
install_cloning: "Cloning cannbot-skills repository...",
|
|
492
|
-
install_repo_ready: "Repository ready",
|
|
493
|
-
install_progress: "Installing",
|
|
494
|
-
install_done: "Installation complete",
|
|
495
|
-
install_success: "success",
|
|
496
|
-
install_failed: "failed",
|
|
497
|
-
install_already_installed: "already installed",
|
|
498
|
-
install_reinstall_confirm: "Reinstall (overwrite)",
|
|
499
|
-
install_skip: "skipped",
|
|
500
|
-
install_enhanced_next_steps: "Next steps",
|
|
501
|
-
install_enhanced_launch: "Launch",
|
|
502
|
-
install_enhanced_try: "Try",
|
|
503
|
-
install_enhanced_more: "More",
|
|
504
|
-
install_enhanced_check: "Check",
|
|
505
|
-
install_enhanced_docs: "Docs",
|
|
506
|
-
update_title: "Update installed Skills",
|
|
507
|
-
update_updating: "Updating",
|
|
508
|
-
update_done: "Update complete",
|
|
509
|
-
update_no_plugins: "No installed plugins",
|
|
510
|
-
doctor_title: "CANNBot Doctor",
|
|
511
|
-
doctor_tools: "AI Tools",
|
|
512
|
-
doctor_plugins: "Installed Plugins",
|
|
513
|
-
doctor_links: "Link Integrity",
|
|
514
|
-
doctor_config: "Configuration",
|
|
515
|
-
doctor_result: "Result",
|
|
516
|
-
doctor_fix_title: "Auto-fix",
|
|
517
|
-
doctor_fix_cleaning: "Cleaning broken links",
|
|
518
|
-
doctor_fix_rebuilding: "Rebuilding directories",
|
|
519
|
-
doctor_fix_done: "Fix complete",
|
|
520
|
-
info_title: "Plugin Details",
|
|
521
|
-
info_description: "Description",
|
|
522
|
-
info_skills: "Skills",
|
|
523
|
-
info_agents: "Agents",
|
|
524
|
-
info_status: "Status",
|
|
525
|
-
info_quickstart: "Quick Start",
|
|
526
|
-
info_not_found: "Plugin not found",
|
|
527
|
-
lang_title: "Language Settings",
|
|
528
|
-
lang_current: "Current language",
|
|
529
|
-
lang_set: "Language set to",
|
|
530
|
-
lang_invalid: "Invalid language, supported: zh_CN, en_US",
|
|
531
|
-
list_title: "Available Scenarios",
|
|
532
|
-
list_id: "#",
|
|
533
|
-
list_name: "Name",
|
|
534
|
-
list_status: "Status",
|
|
535
|
-
list_skills: "Skills",
|
|
536
|
-
list_agents: "Agents",
|
|
537
|
-
status_installed: "installed",
|
|
538
|
-
status_not_installed: "not installed",
|
|
539
|
-
error_tool_not_found: "No AI coding tool detected",
|
|
540
|
-
error_plugin_not_found: "Plugin not found",
|
|
541
|
-
error_repo_not_found: "Repository not found",
|
|
542
|
-
quick_start: "Launch command",
|
|
543
|
-
quick_start_hint: "Try: help me develop an Abs operator",
|
|
544
|
-
skill_select_category: "Select Skill category",
|
|
545
|
-
skill_select_items: "Select Skills to install (space to toggle, enter to confirm)",
|
|
546
|
-
skill_already_installed: "installed",
|
|
547
|
-
skill_install_progress: "Installing",
|
|
548
|
-
skill_install_done: "Skill installation complete",
|
|
549
|
-
skill_uninstall_done: "Skill uninstallation complete",
|
|
550
|
-
skill_list_title: "Available Skills",
|
|
551
|
-
wizard_select_mode: "Select installation mode",
|
|
552
|
-
wizard_mode_plugin: "Install Plugin",
|
|
553
|
-
wizard_mode_plugin_desc: "Full development workflow (Skills + Agents + config)",
|
|
554
|
-
wizard_mode_skill: "Install Skill",
|
|
555
|
-
wizard_mode_skill_desc: "Domain knowledge only, give AI specific capabilities",
|
|
556
|
-
wizard_back: "Go back",
|
|
557
|
-
wizard_cancel: "Cancel installation",
|
|
558
|
-
wizard_no_selection: "No items selected, please choose an action",
|
|
559
|
-
wizard_back_to_reselect: "Go back",
|
|
560
|
-
status_title: "Installed Plugins",
|
|
561
|
-
status_none: "No installed plugins",
|
|
562
|
-
status_hint: "Run install-helper init to start",
|
|
563
|
-
status_install_time: "Installed at"
|
|
564
|
-
};
|
|
565
|
-
var currentLang = "zh_CN";
|
|
566
|
-
function setLanguage(lang) {
|
|
567
|
-
currentLang = lang;
|
|
568
|
-
}
|
|
569
|
-
function t(key) {
|
|
570
|
-
return currentLang === "zh_CN" ? zh_CN[key] : en_US[key];
|
|
571
|
-
}
|
|
572
|
-
|
|
573
705
|
// src/utils/logger.ts
|
|
574
706
|
import chalk from "chalk";
|
|
575
707
|
import ora from "ora";
|
|
@@ -624,7 +756,7 @@ function printBoxTitle(title, width = 65) {
|
|
|
624
756
|
}
|
|
625
757
|
function showOperationHints(isCheckbox = false) {
|
|
626
758
|
if (isCheckbox) {
|
|
627
|
-
console.log(` \u{1F4A1} \x1B[36m\u2191\u2193\x1B[0m \u79FB\u52A8 | \x1B[36m\u7A7A\u683C\x1B[0m \u9009
|
|
759
|
+
console.log(` \u{1F4A1} \x1B[36m\u2191\u2193\x1B[0m \u79FB\u52A8 | \x1B[36m\u7A7A\u683C\x1B[0m \u52FE\u9009 | \x1B[36m\u23CE\x1B[0m \u786E\u8BA4\uFF08\u4E0D\u9009\u6309\u56DE\u8F66\u53EF\u8FD4\u56DE\uFF09
|
|
628
760
|
`);
|
|
629
761
|
} else {
|
|
630
762
|
console.log(` \u{1F4A1} \x1B[36m\u2191\u2193\x1B[0m \u79FB\u52A8 | \x1B[36m\u23CE\x1B[0m \u786E\u8BA4
|
|
@@ -793,7 +925,7 @@ async function runWizard() {
|
|
|
793
925
|
}
|
|
794
926
|
}
|
|
795
927
|
async function stepTool(detectedTools, lastTool) {
|
|
796
|
-
printBoxTitle("
|
|
928
|
+
printBoxTitle(t("wizard_step_1_title"));
|
|
797
929
|
if (detectedTools.length === 0) {
|
|
798
930
|
logger.error(t("error_tool_not_found"));
|
|
799
931
|
const choices2 = [
|
|
@@ -868,10 +1000,10 @@ async function stepToolManual(lastTool) {
|
|
|
868
1000
|
return result;
|
|
869
1001
|
}
|
|
870
1002
|
async function stepLevel(lastLevel) {
|
|
871
|
-
printBoxTitle("
|
|
1003
|
+
printBoxTitle(t("wizard_step_2_title"));
|
|
872
1004
|
const choices = [
|
|
873
|
-
{ name:
|
|
874
|
-
{ name:
|
|
1005
|
+
{ name: `> project \u2014 ${t("install_level_project")}`, value: "project" },
|
|
1006
|
+
{ name: `> global \u2014 ${t("install_level_global")}`, value: "global" },
|
|
875
1007
|
new Separator("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
|
|
876
1008
|
{ name: "<- " + t("wizard_back"), value: BACK },
|
|
877
1009
|
{ name: "x " + t("wizard_cancel"), value: CANCEL }
|
|
@@ -889,7 +1021,7 @@ async function stepLevel(lastLevel) {
|
|
|
889
1021
|
return result;
|
|
890
1022
|
}
|
|
891
1023
|
async function stepPlugins(tool, level) {
|
|
892
|
-
printBoxTitle("
|
|
1024
|
+
printBoxTitle(t("wizard_step_3_title"));
|
|
893
1025
|
const plugins = getAllPlugins();
|
|
894
1026
|
const configRoot = getConfigRoot(tool, level);
|
|
895
1027
|
const manifests = readAllManifests(configRoot);
|
|
@@ -903,20 +1035,16 @@ async function stepPlugins(tool, level) {
|
|
|
903
1035
|
checked: false
|
|
904
1036
|
};
|
|
905
1037
|
});
|
|
906
|
-
choices.push(new Separator("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
907
|
-
choices.push({ name: "<- " + t("wizard_back"), value: BACK, checked: false });
|
|
908
|
-
choices.push({ name: "x " + t("wizard_cancel"), value: CANCEL, checked: false });
|
|
909
1038
|
showOperationHints(true);
|
|
910
1039
|
const selected = await checkbox({
|
|
911
1040
|
message: t("wizard_select_plugins"),
|
|
912
1041
|
choices,
|
|
913
1042
|
loop: false,
|
|
914
1043
|
instructions: false,
|
|
915
|
-
theme: checkboxTheme
|
|
1044
|
+
theme: checkboxTheme,
|
|
1045
|
+
pageSize: 15
|
|
916
1046
|
});
|
|
917
|
-
|
|
918
|
-
if (selected.includes(CANCEL)) return CANCEL;
|
|
919
|
-
const pluginIds = selected.filter((v) => v !== BACK && v !== CANCEL);
|
|
1047
|
+
const pluginIds = selected;
|
|
920
1048
|
if (pluginIds.length === 0) {
|
|
921
1049
|
const action = await select({
|
|
922
1050
|
message: t("wizard_no_selection"),
|
|
@@ -934,14 +1062,17 @@ async function stepPlugins(tool, level) {
|
|
|
934
1062
|
return pluginIds;
|
|
935
1063
|
}
|
|
936
1064
|
async function stepConfirm(tool, level, plugins) {
|
|
937
|
-
printBoxTitle("
|
|
1065
|
+
printBoxTitle(t("wizard_step_4_title"));
|
|
938
1066
|
const allPlugins = getAllPlugins();
|
|
939
1067
|
const selectedPlugins = plugins.map((id) => allPlugins.find((p) => p.id === id));
|
|
940
1068
|
const displayPath = getConfigRoot(tool, level);
|
|
941
|
-
|
|
1069
|
+
const toolName = getToolDisplayName(tool);
|
|
1070
|
+
const levelText = level === "project" ? "project" : "global";
|
|
1071
|
+
logger.info(`\u5373\u5C06\u5B89\u88C5 ${chalk2.bold(plugins.length)} \u4E2A\u63D2\u4EF6\u5230 ${chalk2.green(toolName)}\uFF08${chalk2.cyan(levelText)} \u7EA7\u522B\uFF09\uFF1A`);
|
|
1072
|
+
logger.info(`\u5B89\u88C5\u8DEF\u5F84: ${chalk2.cyan(displayPath)}`);
|
|
942
1073
|
for (const plugin of selectedPlugins) {
|
|
943
1074
|
if (plugin) {
|
|
944
|
-
logger.step(` \u2022 ${chalk2.bold(plugin.displayName)}
|
|
1075
|
+
logger.step(` \u2022 ${chalk2.bold(plugin.displayName)}`);
|
|
945
1076
|
}
|
|
946
1077
|
}
|
|
947
1078
|
logger.blank();
|
|
@@ -965,7 +1096,7 @@ import { execa as execa2 } from "execa";
|
|
|
965
1096
|
|
|
966
1097
|
// src/core/scanner.ts
|
|
967
1098
|
import { existsSync as existsSync5, readdirSync, readFileSync as readFileSync3, statSync, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
968
|
-
import { join as join5
|
|
1099
|
+
import { join as join5 } from "path";
|
|
969
1100
|
import { parse as parseYaml } from "yaml";
|
|
970
1101
|
var EXCLUDE_DIRS = /* @__PURE__ */ new Set([
|
|
971
1102
|
"node_modules",
|
|
@@ -1103,8 +1234,7 @@ function writeScanCache(cache) {
|
|
|
1103
1234
|
}
|
|
1104
1235
|
}
|
|
1105
1236
|
function getCachePath() {
|
|
1106
|
-
|
|
1107
|
-
return join5(homeDir, ".cannbot", "scan-cache.json");
|
|
1237
|
+
return join5(getCannbotConfigDir(), "scan-cache.json");
|
|
1108
1238
|
}
|
|
1109
1239
|
function scanDirectory(dirPath, repoPath, sourcePrefix, skills, seen) {
|
|
1110
1240
|
const selfSkillMd = join5(dirPath, "SKILL.md");
|
|
@@ -1478,8 +1608,8 @@ function createRepositoryManager(customPath) {
|
|
|
1478
1608
|
}
|
|
1479
1609
|
|
|
1480
1610
|
// src/core/installer.ts
|
|
1481
|
-
import { existsSync as
|
|
1482
|
-
import { join as
|
|
1611
|
+
import { existsSync as existsSync9 } from "fs";
|
|
1612
|
+
import { join as join9 } from "path";
|
|
1483
1613
|
import { execa as execa3 } from "execa";
|
|
1484
1614
|
|
|
1485
1615
|
// src/core/record.ts
|
|
@@ -1573,7 +1703,6 @@ function scanInstalledFiles(pluginId, displayName, tool, level, installPath, con
|
|
|
1573
1703
|
files.push(repoLinkInConfig);
|
|
1574
1704
|
}
|
|
1575
1705
|
}
|
|
1576
|
-
directories.push(configRoot);
|
|
1577
1706
|
return {
|
|
1578
1707
|
pluginId,
|
|
1579
1708
|
displayName,
|
|
@@ -1653,6 +1782,179 @@ function getInstalledSkills(tool, level, installPath) {
|
|
|
1653
1782
|
return record[tool]?.[level]?.[installPath]?.skills || [];
|
|
1654
1783
|
}
|
|
1655
1784
|
|
|
1785
|
+
// src/core/backup.ts
|
|
1786
|
+
import { existsSync as existsSync8, copyFileSync, readdirSync as readdirSync2, unlinkSync as unlinkSync2 } from "fs";
|
|
1787
|
+
import { join as join8 } from "path";
|
|
1788
|
+
function getAgentsFileName(tool) {
|
|
1789
|
+
return tool === "claude" ? "CLAUDE.md" : "AGENTS.md";
|
|
1790
|
+
}
|
|
1791
|
+
function detectCurrentPlugin(configRoot, tool) {
|
|
1792
|
+
const manifest = readManifest(configRoot);
|
|
1793
|
+
if (manifest?.team) {
|
|
1794
|
+
const plugin = findPlugin(manifest.team);
|
|
1795
|
+
if (plugin) {
|
|
1796
|
+
return {
|
|
1797
|
+
pluginId: plugin.id,
|
|
1798
|
+
pluginName: plugin.displayName
|
|
1799
|
+
};
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
const agentsFile = join8(configRoot, getAgentsFileName(tool));
|
|
1803
|
+
if (!existsSync8(agentsFile)) {
|
|
1804
|
+
return null;
|
|
1805
|
+
}
|
|
1806
|
+
const allRecords = readAllRecords();
|
|
1807
|
+
for (const record of allRecords) {
|
|
1808
|
+
if (record.configRoot === configRoot && record.tool === tool) {
|
|
1809
|
+
const plugin = findPlugin(record.pluginId);
|
|
1810
|
+
if (plugin) {
|
|
1811
|
+
return {
|
|
1812
|
+
pluginId: plugin.id,
|
|
1813
|
+
pluginName: plugin.displayName
|
|
1814
|
+
};
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
return null;
|
|
1819
|
+
}
|
|
1820
|
+
function createBackup(configRoot, tool, fromPluginId, fromPluginName) {
|
|
1821
|
+
const agentsFile = join8(configRoot, getAgentsFileName(tool));
|
|
1822
|
+
if (!existsSync8(agentsFile)) {
|
|
1823
|
+
return null;
|
|
1824
|
+
}
|
|
1825
|
+
const timestamp = formatTimestamp(/* @__PURE__ */ new Date());
|
|
1826
|
+
const backupFileName = `${getAgentsFileName(tool)}.cannbot-backup.${fromPluginId}.${timestamp}`;
|
|
1827
|
+
const backupPath = join8(configRoot, backupFileName);
|
|
1828
|
+
try {
|
|
1829
|
+
copyFileSync(agentsFile, backupPath);
|
|
1830
|
+
return {
|
|
1831
|
+
filePath: backupPath,
|
|
1832
|
+
pluginId: fromPluginId,
|
|
1833
|
+
pluginName: fromPluginName,
|
|
1834
|
+
backupTime: timestamp
|
|
1835
|
+
};
|
|
1836
|
+
} catch {
|
|
1837
|
+
return null;
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
function findBackups(configRoot) {
|
|
1841
|
+
if (!existsSync8(configRoot)) {
|
|
1842
|
+
return [];
|
|
1843
|
+
}
|
|
1844
|
+
const files = readdirSync2(configRoot);
|
|
1845
|
+
const backups = [];
|
|
1846
|
+
for (const file of files) {
|
|
1847
|
+
if (file.includes(".cannbot-backup.")) {
|
|
1848
|
+
const parts = file.split(".cannbot-backup.");
|
|
1849
|
+
if (parts.length === 2) {
|
|
1850
|
+
const pluginIdAndTime = parts[1];
|
|
1851
|
+
const lastDotIndex = pluginIdAndTime.lastIndexOf(".");
|
|
1852
|
+
if (lastDotIndex > 0) {
|
|
1853
|
+
const pluginId = pluginIdAndTime.substring(0, lastDotIndex);
|
|
1854
|
+
const timestamp = pluginIdAndTime.substring(lastDotIndex + 1);
|
|
1855
|
+
const plugin = findPlugin(pluginId);
|
|
1856
|
+
backups.push({
|
|
1857
|
+
filePath: join8(configRoot, file),
|
|
1858
|
+
pluginId,
|
|
1859
|
+
pluginName: plugin?.displayName || pluginId,
|
|
1860
|
+
backupTime: timestamp
|
|
1861
|
+
});
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
return backups.sort((a, b) => b.backupTime.localeCompare(a.backupTime));
|
|
1867
|
+
}
|
|
1868
|
+
function restoreBackup(backupPath, configRoot, tool) {
|
|
1869
|
+
try {
|
|
1870
|
+
const agentsFile = join8(configRoot, getAgentsFileName(tool));
|
|
1871
|
+
copyFileSync(backupPath, agentsFile);
|
|
1872
|
+
return true;
|
|
1873
|
+
} catch {
|
|
1874
|
+
return false;
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
function deleteBackup(backupPath) {
|
|
1878
|
+
try {
|
|
1879
|
+
if (existsSync8(backupPath)) {
|
|
1880
|
+
unlinkSync2(backupPath);
|
|
1881
|
+
return true;
|
|
1882
|
+
}
|
|
1883
|
+
return false;
|
|
1884
|
+
} catch {
|
|
1885
|
+
return false;
|
|
1886
|
+
}
|
|
1887
|
+
}
|
|
1888
|
+
function formatTimestamp(date) {
|
|
1889
|
+
const year = date.getFullYear();
|
|
1890
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
1891
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
1892
|
+
const hours = String(date.getHours()).padStart(2, "0");
|
|
1893
|
+
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
1894
|
+
const seconds = String(date.getSeconds()).padStart(2, "0");
|
|
1895
|
+
return `${year}${month}${day}-${hours}${minutes}${seconds}`;
|
|
1896
|
+
}
|
|
1897
|
+
function readAllRecords() {
|
|
1898
|
+
const records = [];
|
|
1899
|
+
const plugins = [
|
|
1900
|
+
"ops-direct-invoke",
|
|
1901
|
+
"ops-direct-invoke-flash",
|
|
1902
|
+
"ops-registry-invoke",
|
|
1903
|
+
"pypto-op-orchestrator",
|
|
1904
|
+
"triton-op-generator",
|
|
1905
|
+
"tilelang-op-orchestrator",
|
|
1906
|
+
"model-infer-optimize",
|
|
1907
|
+
"catlass-op-generator",
|
|
1908
|
+
"ops-code-reviewer",
|
|
1909
|
+
"torch-compile"
|
|
1910
|
+
];
|
|
1911
|
+
for (const pluginId of plugins) {
|
|
1912
|
+
const record = readRecord(pluginId);
|
|
1913
|
+
if (record) {
|
|
1914
|
+
records.push(record);
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
return records;
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1920
|
+
// src/ui/backup-prompts.ts
|
|
1921
|
+
import { select as select2 } from "@inquirer/prompts";
|
|
1922
|
+
import chalk3 from "chalk";
|
|
1923
|
+
async function showOverwriteWarning(currentPluginName, newPluginName) {
|
|
1924
|
+
console.log();
|
|
1925
|
+
console.log(chalk3.yellow(` \u26A0\uFE0F ${t("backup_detected")}`));
|
|
1926
|
+
console.log();
|
|
1927
|
+
console.log(` ${t("backup_current")}: ${chalk3.cyan(currentPluginName)}`);
|
|
1928
|
+
console.log(` ${t("backup_installing")}: ${chalk3.cyan(newPluginName)}`);
|
|
1929
|
+
console.log();
|
|
1930
|
+
console.log(` ${t("backup_overwrite_warning")}`);
|
|
1931
|
+
console.log(` ${t("backup_auto_create")}`);
|
|
1932
|
+
console.log();
|
|
1933
|
+
const choice = await select2({
|
|
1934
|
+
message: t("backup_select_action"),
|
|
1935
|
+
choices: [
|
|
1936
|
+
{ name: t("backup_overwrite"), value: "overwrite" },
|
|
1937
|
+
{ name: t("backup_cancel"), value: "cancel" }
|
|
1938
|
+
]
|
|
1939
|
+
});
|
|
1940
|
+
return choice;
|
|
1941
|
+
}
|
|
1942
|
+
async function showRestorePrompt(backups) {
|
|
1943
|
+
console.log();
|
|
1944
|
+
console.log(chalk3.cyan(` ${t("backup_restore_prompt")}`));
|
|
1945
|
+
console.log();
|
|
1946
|
+
const choices = backups.map((b) => ({
|
|
1947
|
+
name: `${t("backup_restore")} ${b.pluginName} (${b.backupTime})`,
|
|
1948
|
+
value: b.filePath
|
|
1949
|
+
}));
|
|
1950
|
+
choices.push({ name: t("backup_only_uninstall"), value: "none" });
|
|
1951
|
+
const choice = await select2({
|
|
1952
|
+
message: t("backup_select_action"),
|
|
1953
|
+
choices
|
|
1954
|
+
});
|
|
1955
|
+
return choice;
|
|
1956
|
+
}
|
|
1957
|
+
|
|
1656
1958
|
// src/core/installer.ts
|
|
1657
1959
|
async function installPlugin(opts) {
|
|
1658
1960
|
const plugin = getPluginById(opts.pluginId);
|
|
@@ -1666,8 +1968,8 @@ async function installPlugin(opts) {
|
|
|
1666
1968
|
warnings: []
|
|
1667
1969
|
};
|
|
1668
1970
|
}
|
|
1669
|
-
const scriptPath =
|
|
1670
|
-
if (!
|
|
1971
|
+
const scriptPath = join9(opts.repoPath, plugin.dir, plugin.script);
|
|
1972
|
+
if (!existsSync9(scriptPath)) {
|
|
1671
1973
|
return {
|
|
1672
1974
|
success: false,
|
|
1673
1975
|
pluginId: opts.pluginId,
|
|
@@ -1682,13 +1984,49 @@ async function installPlugin(opts) {
|
|
|
1682
1984
|
args.push(opts.installPath);
|
|
1683
1985
|
}
|
|
1684
1986
|
const cwd = opts.installPath || process.cwd();
|
|
1987
|
+
const configRoot = getConfigRoot(opts.tool, opts.level, opts.installPath);
|
|
1988
|
+
const agentsFile = join9(configRoot, getAgentsFileName(opts.tool));
|
|
1989
|
+
let backupInfo = null;
|
|
1990
|
+
if (existsSync9(agentsFile)) {
|
|
1991
|
+
const currentPlugin = detectCurrentPlugin(configRoot, opts.tool);
|
|
1992
|
+
if (currentPlugin && currentPlugin.pluginId !== opts.pluginId) {
|
|
1993
|
+
let choice = "overwrite";
|
|
1994
|
+
if (!opts.yes) {
|
|
1995
|
+
choice = await showOverwriteWarning(
|
|
1996
|
+
currentPlugin.pluginName,
|
|
1997
|
+
plugin.displayName
|
|
1998
|
+
);
|
|
1999
|
+
}
|
|
2000
|
+
if (choice === "cancel") {
|
|
2001
|
+
logger.info(t("backup_cancel"));
|
|
2002
|
+
return {
|
|
2003
|
+
success: false,
|
|
2004
|
+
pluginId: opts.pluginId,
|
|
2005
|
+
skillsCount: 0,
|
|
2006
|
+
agentsCount: 0,
|
|
2007
|
+
errors: [t("backup_cancel")],
|
|
2008
|
+
warnings: []
|
|
2009
|
+
};
|
|
2010
|
+
}
|
|
2011
|
+
backupInfo = createBackup(
|
|
2012
|
+
configRoot,
|
|
2013
|
+
opts.tool,
|
|
2014
|
+
currentPlugin.pluginId,
|
|
2015
|
+
currentPlugin.pluginName
|
|
2016
|
+
);
|
|
2017
|
+
if (backupInfo) {
|
|
2018
|
+
logger.success(`${t("backup_created")}: ${backupInfo.filePath}`);
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
}
|
|
1685
2022
|
try {
|
|
1686
|
-
|
|
2023
|
+
const execOptions = {
|
|
1687
2024
|
cwd,
|
|
1688
2025
|
timeout: 3e5,
|
|
1689
|
-
stdio: "pipe"
|
|
1690
|
-
|
|
1691
|
-
|
|
2026
|
+
stdio: "pipe",
|
|
2027
|
+
input: opts.yes ? "y\n" : void 0
|
|
2028
|
+
};
|
|
2029
|
+
await execa3("bash", [scriptPath, ...args], execOptions);
|
|
1692
2030
|
const manifest = readManifest(configRoot);
|
|
1693
2031
|
let skillsCount = 0;
|
|
1694
2032
|
let agentsCount = 0;
|
|
@@ -1709,6 +2047,14 @@ async function installPlugin(opts) {
|
|
|
1709
2047
|
configRoot,
|
|
1710
2048
|
manifest
|
|
1711
2049
|
);
|
|
2050
|
+
if (backupInfo) {
|
|
2051
|
+
record.backup = {
|
|
2052
|
+
filePath: backupInfo.filePath,
|
|
2053
|
+
fromPluginId: backupInfo.pluginId,
|
|
2054
|
+
fromPluginName: backupInfo.pluginName,
|
|
2055
|
+
backupTime: backupInfo.backupTime
|
|
2056
|
+
};
|
|
2057
|
+
}
|
|
1712
2058
|
writeRecord(record);
|
|
1713
2059
|
} catch {
|
|
1714
2060
|
}
|
|
@@ -1734,16 +2080,16 @@ async function installPlugin(opts) {
|
|
|
1734
2080
|
}
|
|
1735
2081
|
|
|
1736
2082
|
// src/core/skill-installer.ts
|
|
1737
|
-
import { existsSync as
|
|
1738
|
-
import { join as
|
|
1739
|
-
import { select as
|
|
1740
|
-
import
|
|
2083
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync5, symlinkSync, unlinkSync as unlinkSync3, readdirSync as readdirSync3, rmdirSync, realpathSync, lstatSync as lstatSync2 } from "fs";
|
|
2084
|
+
import { join as join10 } from "path";
|
|
2085
|
+
import { select as select3, checkbox as checkbox2, Separator as Separator2 } from "@inquirer/prompts";
|
|
2086
|
+
import chalk4 from "chalk";
|
|
1741
2087
|
import Table from "cli-table3";
|
|
1742
2088
|
async function installSkills(skillIds, tool, level, repoPath) {
|
|
1743
2089
|
const configRoot = getConfigRoot(tool, level);
|
|
1744
|
-
const skillsDir =
|
|
2090
|
+
const skillsDir = join10(configRoot, "skills");
|
|
1745
2091
|
const installPath = level === "project" ? process.cwd() : configRoot;
|
|
1746
|
-
if (!
|
|
2092
|
+
if (!existsSync10(skillsDir)) {
|
|
1747
2093
|
mkdirSync5(skillsDir, { recursive: true });
|
|
1748
2094
|
}
|
|
1749
2095
|
const results = [];
|
|
@@ -1754,15 +2100,15 @@ async function installSkills(skillIds, tool, level, repoPath) {
|
|
|
1754
2100
|
results.push({ skillId, success: false, error: "Skill not found in registry" });
|
|
1755
2101
|
continue;
|
|
1756
2102
|
}
|
|
1757
|
-
const sourcePath =
|
|
1758
|
-
const targetPath =
|
|
1759
|
-
if (!
|
|
2103
|
+
const sourcePath = join10(repoPath, skill.source, skill.id);
|
|
2104
|
+
const targetPath = join10(skillsDir, skillId);
|
|
2105
|
+
if (!existsSync10(sourcePath)) {
|
|
1760
2106
|
results.push({ skillId, success: false, error: `Source not found: ${sourcePath}` });
|
|
1761
2107
|
continue;
|
|
1762
2108
|
}
|
|
1763
2109
|
try {
|
|
1764
|
-
if (
|
|
1765
|
-
|
|
2110
|
+
if (existsSync10(targetPath) || isSymlink2(targetPath)) {
|
|
2111
|
+
unlinkSync3(targetPath);
|
|
1766
2112
|
}
|
|
1767
2113
|
symlinkSync(realpathSync(sourcePath), targetPath);
|
|
1768
2114
|
results.push({ skillId, success: true });
|
|
@@ -1778,15 +2124,15 @@ async function installSkills(skillIds, tool, level, repoPath) {
|
|
|
1778
2124
|
}
|
|
1779
2125
|
async function uninstallSkills(skillIds, tool, level) {
|
|
1780
2126
|
const configRoot = getConfigRoot(tool, level);
|
|
1781
|
-
const skillsDir =
|
|
2127
|
+
const skillsDir = join10(configRoot, "skills");
|
|
1782
2128
|
const installPath = level === "project" ? process.cwd() : configRoot;
|
|
1783
2129
|
const results = [];
|
|
1784
2130
|
const removedIds = [];
|
|
1785
2131
|
for (const skillId of skillIds) {
|
|
1786
|
-
const targetPath =
|
|
2132
|
+
const targetPath = join10(skillsDir, skillId);
|
|
1787
2133
|
try {
|
|
1788
|
-
if (
|
|
1789
|
-
|
|
2134
|
+
if (existsSync10(targetPath) || isSymlink2(targetPath)) {
|
|
2135
|
+
unlinkSync3(targetPath);
|
|
1790
2136
|
results.push({ skillId, success: true });
|
|
1791
2137
|
removedIds.push(skillId);
|
|
1792
2138
|
logger.step(` \u79FB\u9664: ${skillId}`);
|
|
@@ -1801,7 +2147,7 @@ async function uninstallSkills(skillIds, tool, level) {
|
|
|
1801
2147
|
if (removedIds.length > 0) {
|
|
1802
2148
|
removeSkillsFromRecord(removedIds, tool, level, installPath);
|
|
1803
2149
|
}
|
|
1804
|
-
if (
|
|
2150
|
+
if (existsSync10(skillsDir)) {
|
|
1805
2151
|
try {
|
|
1806
2152
|
const entries = readdirSync3(skillsDir);
|
|
1807
2153
|
if (entries.length === 0) {
|
|
@@ -1811,16 +2157,6 @@ async function uninstallSkills(skillIds, tool, level) {
|
|
|
1811
2157
|
} catch {
|
|
1812
2158
|
}
|
|
1813
2159
|
}
|
|
1814
|
-
if (existsSync9(configRoot)) {
|
|
1815
|
-
try {
|
|
1816
|
-
const entries = readdirSync3(configRoot);
|
|
1817
|
-
if (entries.length === 0) {
|
|
1818
|
-
rmdirSync(configRoot);
|
|
1819
|
-
logger.step(` \u6E05\u7406\u7A7A\u76EE\u5F55: ${configRoot.split("/").pop()}/`);
|
|
1820
|
-
}
|
|
1821
|
-
} catch {
|
|
1822
|
-
}
|
|
1823
|
-
}
|
|
1824
2160
|
return results;
|
|
1825
2161
|
}
|
|
1826
2162
|
async function interactiveSkillSelect() {
|
|
@@ -1832,7 +2168,7 @@ async function interactiveSkillSelect() {
|
|
|
1832
2168
|
while (true) {
|
|
1833
2169
|
switch (step) {
|
|
1834
2170
|
case 0: {
|
|
1835
|
-
printBoxTitle("
|
|
2171
|
+
printBoxTitle(t("wizard_step_3_skill_title"));
|
|
1836
2172
|
const categoryChoices = [
|
|
1837
2173
|
...categories.map((cat) => ({
|
|
1838
2174
|
name: `> ${cat.name} (${cat.skills.length} skills)`,
|
|
@@ -1843,11 +2179,12 @@ async function interactiveSkillSelect() {
|
|
|
1843
2179
|
{ name: "x " + t("wizard_cancel"), value: CANCEL3 }
|
|
1844
2180
|
];
|
|
1845
2181
|
showOperationHints();
|
|
1846
|
-
selectedCategoryId = await
|
|
2182
|
+
selectedCategoryId = await select3({
|
|
1847
2183
|
message: t("skill_select_category"),
|
|
1848
2184
|
choices: categoryChoices,
|
|
1849
2185
|
loop: false,
|
|
1850
|
-
theme: selectTheme
|
|
2186
|
+
theme: selectTheme,
|
|
2187
|
+
pageSize: 15
|
|
1851
2188
|
});
|
|
1852
2189
|
if (selectedCategoryId === BACK3) return "back";
|
|
1853
2190
|
if (selectedCategoryId === CANCEL3) return "cancel";
|
|
@@ -1857,7 +2194,7 @@ async function interactiveSkillSelect() {
|
|
|
1857
2194
|
case 1: {
|
|
1858
2195
|
const category = categories.find((c) => c.id === selectedCategoryId);
|
|
1859
2196
|
if (!category) return [];
|
|
1860
|
-
printBoxTitle(
|
|
2197
|
+
printBoxTitle(t("wizard_step_4_skill_title").replace("{category}", category.name));
|
|
1861
2198
|
const tools = ["opencode", "claude", "trae", "cursor", "copilot"];
|
|
1862
2199
|
const levels = ["project", "global"];
|
|
1863
2200
|
const installedSkills = [];
|
|
@@ -1877,25 +2214,18 @@ async function interactiveSkillSelect() {
|
|
|
1877
2214
|
checked: false
|
|
1878
2215
|
};
|
|
1879
2216
|
});
|
|
1880
|
-
skillChoices.push(new Separator2("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
1881
|
-
skillChoices.push({ name: "<- " + t("wizard_back"), value: BACK3, checked: false });
|
|
1882
|
-
skillChoices.push({ name: "x " + t("wizard_cancel"), value: CANCEL3, checked: false });
|
|
1883
2217
|
showOperationHints(true);
|
|
1884
2218
|
const selectedSkills = await checkbox2({
|
|
1885
2219
|
message: t("skill_select_items"),
|
|
1886
2220
|
choices: skillChoices,
|
|
1887
2221
|
loop: false,
|
|
1888
2222
|
instructions: false,
|
|
1889
|
-
theme: checkboxTheme
|
|
2223
|
+
theme: checkboxTheme,
|
|
2224
|
+
pageSize: 15
|
|
1890
2225
|
});
|
|
1891
|
-
|
|
1892
|
-
step = 0;
|
|
1893
|
-
break;
|
|
1894
|
-
}
|
|
1895
|
-
if (selectedSkills.includes(CANCEL3)) return "cancel";
|
|
1896
|
-
const skillIds = selectedSkills.filter((v) => v !== BACK3 && v !== CANCEL3);
|
|
2226
|
+
const skillIds = selectedSkills;
|
|
1897
2227
|
if (skillIds.length === 0) {
|
|
1898
|
-
const action = await
|
|
2228
|
+
const action = await select3({
|
|
1899
2229
|
message: t("wizard_no_selection"),
|
|
1900
2230
|
choices: [
|
|
1901
2231
|
new Separator2("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),
|
|
@@ -1919,11 +2249,11 @@ async function interactiveSkillSelect() {
|
|
|
1919
2249
|
function listAllSkills() {
|
|
1920
2250
|
const categories = getAllCategories();
|
|
1921
2251
|
console.log();
|
|
1922
|
-
console.log(
|
|
1923
|
-
console.log(
|
|
2252
|
+
console.log(chalk4.bold(` ${t("skill_list_title")}`));
|
|
2253
|
+
console.log(chalk4.dim(" " + "\u2500".repeat(60)));
|
|
1924
2254
|
for (const category of categories) {
|
|
1925
2255
|
console.log();
|
|
1926
|
-
console.log(
|
|
2256
|
+
console.log(chalk4.bold(` ${category.name}`) + chalk4.dim(` (${category.skills.length} skills)`));
|
|
1927
2257
|
const table = new Table({
|
|
1928
2258
|
style: { head: [], border: [] },
|
|
1929
2259
|
colWidths: [35, 45],
|
|
@@ -1931,14 +2261,14 @@ function listAllSkills() {
|
|
|
1931
2261
|
});
|
|
1932
2262
|
for (const skill of category.skills) {
|
|
1933
2263
|
table.push([
|
|
1934
|
-
|
|
2264
|
+
chalk4.cyan(skill.id),
|
|
1935
2265
|
skill.description
|
|
1936
2266
|
]);
|
|
1937
2267
|
}
|
|
1938
2268
|
console.log(table.toString());
|
|
1939
2269
|
}
|
|
1940
2270
|
console.log();
|
|
1941
|
-
console.log(
|
|
2271
|
+
console.log(chalk4.dim(` \u5171 ${getAllSkills().length} \u4E2A Skills`));
|
|
1942
2272
|
console.log();
|
|
1943
2273
|
}
|
|
1944
2274
|
function isSymlink2(path) {
|
|
@@ -1950,22 +2280,22 @@ function isSymlink2(path) {
|
|
|
1950
2280
|
}
|
|
1951
2281
|
|
|
1952
2282
|
// src/ui/display.ts
|
|
1953
|
-
import
|
|
2283
|
+
import chalk5 from "chalk";
|
|
1954
2284
|
import Table2 from "cli-table3";
|
|
1955
2285
|
function printPluginList(plugins, installed) {
|
|
1956
2286
|
const table = new Table2({
|
|
1957
2287
|
head: [
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
2288
|
+
chalk5.cyan(t("list_id")),
|
|
2289
|
+
chalk5.cyan(t("list_name")),
|
|
2290
|
+
chalk5.cyan(t("list_status")),
|
|
2291
|
+
chalk5.cyan(t("list_skills")),
|
|
2292
|
+
chalk5.cyan(t("list_agents"))
|
|
1963
2293
|
],
|
|
1964
2294
|
style: { head: [], border: [] }
|
|
1965
2295
|
});
|
|
1966
2296
|
plugins.forEach((plugin, index) => {
|
|
1967
2297
|
const isInstalled = installed.has(plugin.id);
|
|
1968
|
-
const status = isInstalled ?
|
|
2298
|
+
const status = isInstalled ? chalk5.green(`\u2713 ${t("status_installed")}`) : chalk5.dim(`\u2014`);
|
|
1969
2299
|
table.push([
|
|
1970
2300
|
String(index + 1),
|
|
1971
2301
|
plugin.displayName,
|
|
@@ -1975,7 +2305,7 @@ function printPluginList(plugins, installed) {
|
|
|
1975
2305
|
]);
|
|
1976
2306
|
});
|
|
1977
2307
|
console.log();
|
|
1978
|
-
console.log(
|
|
2308
|
+
console.log(chalk5.bold(` ${t("list_title")} (${plugins.length} \u4E2A)`));
|
|
1979
2309
|
console.log(table.toString());
|
|
1980
2310
|
console.log();
|
|
1981
2311
|
}
|
|
@@ -1984,7 +2314,7 @@ function printInstallSummary(results) {
|
|
|
1984
2314
|
const totalCount = results.length;
|
|
1985
2315
|
console.log();
|
|
1986
2316
|
console.log(
|
|
1987
|
-
|
|
2317
|
+
chalk5.bold(
|
|
1988
2318
|
` ${t("install_done")}! ${successCount}/${totalCount} ${t("install_success")}`
|
|
1989
2319
|
)
|
|
1990
2320
|
);
|
|
@@ -1992,10 +2322,10 @@ function printInstallSummary(results) {
|
|
|
1992
2322
|
for (const result of results) {
|
|
1993
2323
|
if (result.success) {
|
|
1994
2324
|
console.log(
|
|
1995
|
-
|
|
2325
|
+
chalk5.green(" \u2713") + ` ${result.displayName} (${result.skillsCount} skills, ${result.agentsCount} agents)`
|
|
1996
2326
|
);
|
|
1997
2327
|
} else {
|
|
1998
|
-
console.log(
|
|
2328
|
+
console.log(chalk5.red(" \u2717") + ` ${result.displayName}`);
|
|
1999
2329
|
}
|
|
2000
2330
|
}
|
|
2001
2331
|
console.log();
|
|
@@ -2009,21 +2339,21 @@ function printEnhancedSummary(results, tool, configRoot) {
|
|
|
2009
2339
|
}
|
|
2010
2340
|
const toolName = getToolDisplayName(tool);
|
|
2011
2341
|
const lines = [
|
|
2012
|
-
|
|
2342
|
+
chalk5.bold(` ${t("install_done")}!`),
|
|
2013
2343
|
"",
|
|
2014
|
-
` ${
|
|
2015
|
-
` ${
|
|
2344
|
+
` ${chalk5.dim(t("install_installed_to") + ":")} ${configRoot}`,
|
|
2345
|
+
` ${chalk5.dim(t("install_skills_count") + ":")} ${totalSkills} \u4E2A ${chalk5.dim("|")} ${chalk5.dim(t("install_agents_count") + ":")} ${totalAgents} \u4E2A`,
|
|
2016
2346
|
"",
|
|
2017
|
-
|
|
2018
|
-
` ${
|
|
2019
|
-
` ${
|
|
2020
|
-
` ${
|
|
2021
|
-
` ${
|
|
2347
|
+
chalk5.bold(` ${t("install_enhanced_next_steps")}:`),
|
|
2348
|
+
` ${chalk5.cyan("1.")} ${t("install_enhanced_launch")}: ${chalk5.green(toolName.toLowerCase())}`,
|
|
2349
|
+
` ${chalk5.cyan("2.")} ${t("install_enhanced_try")}: ${chalk5.green("\u5E2E\u6211\u5F00\u53D1\u4E00\u4E2A Abs \u7B97\u5B50")}`,
|
|
2350
|
+
` ${chalk5.cyan("3.")} ${t("install_enhanced_more")}: ${chalk5.green("install-helper list")}`,
|
|
2351
|
+
` ${chalk5.cyan("4.")} ${t("install_enhanced_check")}: ${chalk5.green("install-helper doctor")}`,
|
|
2022
2352
|
""
|
|
2023
2353
|
];
|
|
2024
2354
|
if (successResults.length === 1) {
|
|
2025
2355
|
lines.push(
|
|
2026
|
-
` ${
|
|
2356
|
+
` ${chalk5.dim(t("install_enhanced_docs"))}: ${chalk5.dim(`plugins-official/${successResults[0].pluginId}/quickstart.md`)}`
|
|
2027
2357
|
);
|
|
2028
2358
|
}
|
|
2029
2359
|
console.log();
|
|
@@ -2034,34 +2364,34 @@ function printEnhancedSummary(results, tool, configRoot) {
|
|
|
2034
2364
|
}
|
|
2035
2365
|
|
|
2036
2366
|
// src/commands/init.ts
|
|
2037
|
-
import { existsSync as
|
|
2038
|
-
import { join as
|
|
2367
|
+
import { existsSync as existsSync11, readFileSync as readFileSync5 } from "fs";
|
|
2368
|
+
import { join as join11 } from "path";
|
|
2039
2369
|
var BACK2 = "__back__";
|
|
2040
2370
|
var CANCEL2 = "__cancel__";
|
|
2041
2371
|
async function initCommand() {
|
|
2042
2372
|
const cwd = process.cwd();
|
|
2043
|
-
if (
|
|
2373
|
+
if (existsSync11(join11(cwd, "package.json")) && (() => {
|
|
2044
2374
|
try {
|
|
2045
|
-
const pkg = JSON.parse(readFileSync5(
|
|
2375
|
+
const pkg = JSON.parse(readFileSync5(join11(cwd, "package.json"), "utf-8"));
|
|
2046
2376
|
return pkg.name === "@cannbot-ai/install-helper";
|
|
2047
2377
|
} catch {
|
|
2048
2378
|
return false;
|
|
2049
2379
|
}
|
|
2050
2380
|
})()) {
|
|
2051
|
-
logger.warn("
|
|
2052
|
-
logger.info("
|
|
2053
|
-
logger.info("
|
|
2381
|
+
logger.warn(t("init_pkg_dir_warn"));
|
|
2382
|
+
logger.info(t("init_pkg_dir_hint"));
|
|
2383
|
+
logger.info(t("init_pkg_dir_example"));
|
|
2054
2384
|
return;
|
|
2055
2385
|
}
|
|
2056
2386
|
printBanner(t("wizard_title"));
|
|
2057
|
-
const spinner = createSpinner("
|
|
2387
|
+
const spinner = createSpinner(t("loading_skills_list"));
|
|
2058
2388
|
spinner.start();
|
|
2059
2389
|
try {
|
|
2060
2390
|
const repoManager = createRepositoryManager();
|
|
2061
2391
|
await repoManager.ensureRepoAndScan();
|
|
2062
|
-
spinner.succeed("
|
|
2392
|
+
spinner.succeed(t("loading_skills_list_complete"));
|
|
2063
2393
|
} catch {
|
|
2064
|
-
spinner.warn("
|
|
2394
|
+
spinner.warn(t("loading_skills_list_failed"));
|
|
2065
2395
|
}
|
|
2066
2396
|
let step = 0;
|
|
2067
2397
|
let mode = "plugin";
|
|
@@ -2095,7 +2425,7 @@ async function initCommand() {
|
|
|
2095
2425
|
}
|
|
2096
2426
|
}
|
|
2097
2427
|
async function selectMode() {
|
|
2098
|
-
printBoxTitle("
|
|
2428
|
+
printBoxTitle(t("wizard_select_mode_title"));
|
|
2099
2429
|
const CANCEL3 = "__cancel__";
|
|
2100
2430
|
const choices = [
|
|
2101
2431
|
{
|
|
@@ -2110,7 +2440,7 @@ async function selectMode() {
|
|
|
2110
2440
|
{ name: "x " + t("wizard_cancel"), value: CANCEL3 }
|
|
2111
2441
|
];
|
|
2112
2442
|
showOperationHints();
|
|
2113
|
-
const result = await
|
|
2443
|
+
const result = await select4({
|
|
2114
2444
|
message: t("wizard_select_mode"),
|
|
2115
2445
|
choices,
|
|
2116
2446
|
loop: false,
|
|
@@ -2123,14 +2453,14 @@ async function pluginInstallFlow() {
|
|
|
2123
2453
|
const answers = await runWizard();
|
|
2124
2454
|
if (!answers.confirmed) {
|
|
2125
2455
|
if (answers.back) return "back";
|
|
2126
|
-
logger.info("
|
|
2456
|
+
logger.info(t("init_cancelled"));
|
|
2127
2457
|
return "done";
|
|
2128
2458
|
}
|
|
2129
2459
|
const repoManager = createRepositoryManager();
|
|
2130
|
-
const spinner = createSpinner(t("
|
|
2460
|
+
const spinner = createSpinner(t("loading_plugin_data"));
|
|
2131
2461
|
spinner.start();
|
|
2132
2462
|
const repoPath = await repoManager.ensureRepo();
|
|
2133
|
-
spinner.succeed(t("
|
|
2463
|
+
spinner.succeed(t("loading_plugin_data_complete"));
|
|
2134
2464
|
const allPlugins = getAllPlugins();
|
|
2135
2465
|
const selectedPlugins = answers.plugins.map(
|
|
2136
2466
|
(id) => allPlugins.find((p) => p.id === id)
|
|
@@ -2184,7 +2514,7 @@ async function skillInstallFlow() {
|
|
|
2184
2514
|
const result = await selectToolWithDetection();
|
|
2185
2515
|
if (result === "back") return "back";
|
|
2186
2516
|
if (result === "cancel") {
|
|
2187
|
-
logger.info("
|
|
2517
|
+
logger.info(t("init_cancelled"));
|
|
2188
2518
|
return "done";
|
|
2189
2519
|
}
|
|
2190
2520
|
tool = result;
|
|
@@ -2198,7 +2528,7 @@ async function skillInstallFlow() {
|
|
|
2198
2528
|
break;
|
|
2199
2529
|
}
|
|
2200
2530
|
if (result === CANCEL2) {
|
|
2201
|
-
logger.info("
|
|
2531
|
+
logger.info(t("init_cancelled"));
|
|
2202
2532
|
return "done";
|
|
2203
2533
|
}
|
|
2204
2534
|
level = result;
|
|
@@ -2212,37 +2542,40 @@ async function skillInstallFlow() {
|
|
|
2212
2542
|
break;
|
|
2213
2543
|
}
|
|
2214
2544
|
if (selectedSkills === "cancel") {
|
|
2215
|
-
logger.info("
|
|
2545
|
+
logger.info(t("init_cancelled"));
|
|
2216
2546
|
return "done";
|
|
2217
2547
|
}
|
|
2218
2548
|
if (selectedSkills.length === 0) {
|
|
2219
|
-
logger.info("
|
|
2549
|
+
logger.info(t("install_no_skill_selected"));
|
|
2220
2550
|
return "done";
|
|
2221
2551
|
}
|
|
2222
2552
|
const repoManager = createRepositoryManager();
|
|
2223
|
-
const spinner = createSpinner(t("
|
|
2553
|
+
const spinner = createSpinner(t("loading_plugin_data"));
|
|
2224
2554
|
spinner.start();
|
|
2225
2555
|
const repoPath = await repoManager.ensureRepo();
|
|
2226
|
-
spinner.succeed(t("
|
|
2227
|
-
logger.info(`${t("skill_install_progress")} ${
|
|
2556
|
+
spinner.succeed(t("loading_plugin_data_complete"));
|
|
2557
|
+
logger.info(`${t("skill_install_progress")} ${chalk6.bold(selectedSkills.length)} \u4E2A Skills...`);
|
|
2228
2558
|
const results = await installSkills(selectedSkills, tool, level, repoPath);
|
|
2229
2559
|
let successCount = 0;
|
|
2230
2560
|
let failCount = 0;
|
|
2231
|
-
|
|
2561
|
+
const total = results.length;
|
|
2562
|
+
for (let i = 0; i < results.length; i++) {
|
|
2563
|
+
const result = results[i];
|
|
2564
|
+
const progress = `[${i + 1}/${total}]`;
|
|
2232
2565
|
if (result.success) {
|
|
2233
|
-
logger.success(`${result.skillId}`);
|
|
2566
|
+
logger.success(`${progress} ${result.skillId}`);
|
|
2234
2567
|
successCount++;
|
|
2235
2568
|
} else {
|
|
2236
|
-
logger.error(`${result.skillId}: ${result.error}`);
|
|
2569
|
+
logger.error(`${progress} ${result.skillId}: ${result.error}`);
|
|
2237
2570
|
failCount++;
|
|
2238
2571
|
}
|
|
2239
2572
|
}
|
|
2240
2573
|
const configRoot = getConfigRoot(tool, level);
|
|
2241
2574
|
logger.blank();
|
|
2242
|
-
logger.success(`${t("skill_install_done")}: ${
|
|
2575
|
+
logger.success(`${t("skill_install_done")}: ${chalk6.green(successCount + " \u6210\u529F")}, ${failCount > 0 ? chalk6.red(failCount + " \u5931\u8D25") : chalk6.dim(failCount + " \u5931\u8D25")}`);
|
|
2243
2576
|
logger.blank();
|
|
2244
|
-
logger.info(
|
|
2245
|
-
logger.info(
|
|
2577
|
+
logger.info(`${t("install_to")}: ${chalk6.cyan(configRoot + "/skills/")}`);
|
|
2578
|
+
logger.info(`${t("start_to_use").replace("{tool}", chalk6.green(tool))}`);
|
|
2246
2579
|
logger.blank();
|
|
2247
2580
|
return "done";
|
|
2248
2581
|
}
|
|
@@ -2264,32 +2597,32 @@ async function listCommand() {
|
|
|
2264
2597
|
}
|
|
2265
2598
|
|
|
2266
2599
|
// src/commands/doctor.ts
|
|
2267
|
-
import
|
|
2268
|
-
import { existsSync as
|
|
2269
|
-
import { join as
|
|
2600
|
+
import chalk7 from "chalk";
|
|
2601
|
+
import { existsSync as existsSync12, readdirSync as readdirSync4, lstatSync as lstatSync3, unlinkSync as unlinkSync4, mkdirSync as mkdirSync6 } from "fs";
|
|
2602
|
+
import { join as join12 } from "path";
|
|
2270
2603
|
async function doctorCommand(options = {}) {
|
|
2271
2604
|
console.log();
|
|
2272
|
-
console.log(
|
|
2273
|
-
console.log(
|
|
2605
|
+
console.log(chalk7.bold(` ${t("doctor_title")}`));
|
|
2606
|
+
console.log(chalk7.dim(" " + "\u2500".repeat(46)));
|
|
2274
2607
|
let errors = 0;
|
|
2275
2608
|
let warnings = 0;
|
|
2276
2609
|
let fixes = 0;
|
|
2277
2610
|
console.log();
|
|
2278
|
-
console.log(
|
|
2611
|
+
console.log(chalk7.bold(` ${t("doctor_tools")}`));
|
|
2279
2612
|
const detectedTools = await detectTools();
|
|
2280
2613
|
const allTools = getAllTools();
|
|
2281
2614
|
for (const tool of allTools) {
|
|
2282
2615
|
const detected = detectedTools.find((d) => d.name === tool);
|
|
2283
2616
|
if (detected) {
|
|
2284
2617
|
console.log(
|
|
2285
|
-
|
|
2618
|
+
chalk7.green(" \u2713") + ` ${getToolDisplayName(tool)}${detected.version ? ` v${detected.version}` : ""}`
|
|
2286
2619
|
);
|
|
2287
2620
|
} else {
|
|
2288
|
-
console.log(
|
|
2621
|
+
console.log(chalk7.dim(" \u2014") + ` ${getToolDisplayName(tool)} \u2014 \u672A\u5B89\u88C5`);
|
|
2289
2622
|
}
|
|
2290
2623
|
}
|
|
2291
2624
|
console.log();
|
|
2292
|
-
console.log(
|
|
2625
|
+
console.log(chalk7.bold(` ${t("doctor_plugins")}`));
|
|
2293
2626
|
const plugins = getAllPlugins();
|
|
2294
2627
|
const installed = scanInstalled();
|
|
2295
2628
|
const installedMap = new Map(installed.map((p) => [p.id, p]));
|
|
@@ -2297,73 +2630,73 @@ async function doctorCommand(options = {}) {
|
|
|
2297
2630
|
const inst = installedMap.get(plugin.id);
|
|
2298
2631
|
if (inst) {
|
|
2299
2632
|
console.log(
|
|
2300
|
-
|
|
2633
|
+
chalk7.green(" \u2713") + ` ${plugin.id.padEnd(30)} ${inst.skillsCount} skills, ${inst.agentsCount} agents`
|
|
2301
2634
|
);
|
|
2302
2635
|
} else {
|
|
2303
|
-
console.log(
|
|
2636
|
+
console.log(chalk7.dim(" \u2014") + ` ${plugin.id.padEnd(30)} \u2014 \u672A\u5B89\u88C5`);
|
|
2304
2637
|
}
|
|
2305
2638
|
}
|
|
2306
2639
|
console.log();
|
|
2307
|
-
console.log(
|
|
2640
|
+
console.log(chalk7.bold(` ${t("doctor_links")}`));
|
|
2308
2641
|
const primaryTool = detectedTools[0]?.name || "opencode";
|
|
2309
2642
|
const configRoot = getConfigRoot(primaryTool, "project");
|
|
2310
2643
|
const skillsDir = getSkillsDir(configRoot);
|
|
2311
2644
|
const agentsDir = getAgentsDir(configRoot);
|
|
2312
|
-
if (
|
|
2645
|
+
if (existsSync12(skillsDir)) {
|
|
2313
2646
|
const brokenLinks = checkBrokenLinks(skillsDir);
|
|
2314
2647
|
if (brokenLinks === 0) {
|
|
2315
2648
|
const count = readdirSync4(skillsDir).length;
|
|
2316
|
-
console.log(
|
|
2649
|
+
console.log(chalk7.green(" \u2713") + ` ${skillsDir} \u2014 ${count} \u4E2A\u8F6F\u94FE\u63A5\u5747\u6709\u6548`);
|
|
2317
2650
|
} else {
|
|
2318
|
-
console.log(
|
|
2651
|
+
console.log(chalk7.yellow(" \u26A0") + ` ${skillsDir} \u2014 ${brokenLinks} \u4E2A\u5931\u6548\u94FE\u63A5`);
|
|
2319
2652
|
warnings++;
|
|
2320
2653
|
if (options.fix) {
|
|
2321
2654
|
const fixed = fixBrokenLinks(skillsDir);
|
|
2322
2655
|
fixes += fixed;
|
|
2323
|
-
console.log(
|
|
2656
|
+
console.log(chalk7.green(" \u2713") + ` ${t("doctor_fix_cleaning")}: \u5DF2\u6E05\u7406 ${fixed} \u4E2A\u5931\u6548\u94FE\u63A5`);
|
|
2324
2657
|
}
|
|
2325
2658
|
}
|
|
2326
2659
|
} else {
|
|
2327
|
-
console.log(
|
|
2660
|
+
console.log(chalk7.dim(" \u2014") + ` ${skillsDir} \u2014 \u4E0D\u5B58\u5728`);
|
|
2328
2661
|
if (options.fix) {
|
|
2329
2662
|
mkdirSync6(skillsDir, { recursive: true });
|
|
2330
2663
|
fixes++;
|
|
2331
|
-
console.log(
|
|
2664
|
+
console.log(chalk7.green(" \u2713") + ` ${t("doctor_fix_rebuilding")}: \u5DF2\u521B\u5EFA ${skillsDir}`);
|
|
2332
2665
|
}
|
|
2333
2666
|
}
|
|
2334
|
-
if (
|
|
2667
|
+
if (existsSync12(agentsDir)) {
|
|
2335
2668
|
const brokenLinks = checkBrokenLinks(agentsDir);
|
|
2336
2669
|
if (brokenLinks === 0) {
|
|
2337
2670
|
const count = readdirSync4(agentsDir).length;
|
|
2338
|
-
console.log(
|
|
2671
|
+
console.log(chalk7.green(" \u2713") + ` ${agentsDir} \u2014 ${count} \u4E2A\u8F6F\u94FE\u63A5\u5747\u6709\u6548`);
|
|
2339
2672
|
} else {
|
|
2340
|
-
console.log(
|
|
2673
|
+
console.log(chalk7.yellow(" \u26A0") + ` ${agentsDir} \u2014 ${brokenLinks} \u4E2A\u5931\u6548\u94FE\u63A5`);
|
|
2341
2674
|
warnings++;
|
|
2342
2675
|
if (options.fix) {
|
|
2343
2676
|
const fixed = fixBrokenLinks(agentsDir);
|
|
2344
2677
|
fixes += fixed;
|
|
2345
|
-
console.log(
|
|
2678
|
+
console.log(chalk7.green(" \u2713") + ` ${t("doctor_fix_cleaning")}: \u5DF2\u6E05\u7406 ${fixed} \u4E2A\u5931\u6548\u94FE\u63A5`);
|
|
2346
2679
|
}
|
|
2347
2680
|
}
|
|
2348
2681
|
} else {
|
|
2349
|
-
console.log(
|
|
2682
|
+
console.log(chalk7.dim(" \u2014") + ` ${agentsDir} \u2014 \u4E0D\u5B58\u5728`);
|
|
2350
2683
|
if (options.fix) {
|
|
2351
2684
|
mkdirSync6(agentsDir, { recursive: true });
|
|
2352
2685
|
fixes++;
|
|
2353
|
-
console.log(
|
|
2686
|
+
console.log(chalk7.green(" \u2713") + ` ${t("doctor_fix_rebuilding")}: \u5DF2\u521B\u5EFA ${agentsDir}`);
|
|
2354
2687
|
}
|
|
2355
2688
|
}
|
|
2356
2689
|
console.log();
|
|
2357
|
-
console.log(
|
|
2690
|
+
console.log(chalk7.bold(` ${t("doctor_config")}`));
|
|
2358
2691
|
const configFile = getConfigFileName(primaryTool);
|
|
2359
|
-
const configPath =
|
|
2360
|
-
if (
|
|
2361
|
-
console.log(
|
|
2692
|
+
const configPath = join12(process.cwd(), configFile);
|
|
2693
|
+
if (existsSync12(configPath)) {
|
|
2694
|
+
console.log(chalk7.green(" \u2713") + ` ${configFile} \u5B58\u5728`);
|
|
2362
2695
|
} else {
|
|
2363
|
-
console.log(
|
|
2696
|
+
console.log(chalk7.dim(" \u2014") + ` ${configFile} \u4E0D\u5B58\u5728`);
|
|
2364
2697
|
}
|
|
2365
2698
|
console.log();
|
|
2366
|
-
console.log(
|
|
2699
|
+
console.log(chalk7.dim(" " + "\u2500".repeat(46)));
|
|
2367
2700
|
if (options.fix && fixes > 0) {
|
|
2368
2701
|
console.log(
|
|
2369
2702
|
` ${t("doctor_result")}: ${warnings} \u4E2A\u8B66\u544A, ${errors} \u4E2A\u9519\u8BEF, ${fixes} \u9879\u5DF2\u4FEE\u590D`
|
|
@@ -2380,11 +2713,11 @@ function checkBrokenLinks(dir) {
|
|
|
2380
2713
|
try {
|
|
2381
2714
|
const entries = readdirSync4(dir);
|
|
2382
2715
|
for (const entry of entries) {
|
|
2383
|
-
const fullPath =
|
|
2716
|
+
const fullPath = join12(dir, entry);
|
|
2384
2717
|
try {
|
|
2385
2718
|
const stats = lstatSync3(fullPath);
|
|
2386
2719
|
if (stats.isSymbolicLink()) {
|
|
2387
|
-
if (!
|
|
2720
|
+
if (!existsSync12(fullPath)) {
|
|
2388
2721
|
broken++;
|
|
2389
2722
|
}
|
|
2390
2723
|
}
|
|
@@ -2401,12 +2734,12 @@ function fixBrokenLinks(dir) {
|
|
|
2401
2734
|
try {
|
|
2402
2735
|
const entries = readdirSync4(dir);
|
|
2403
2736
|
for (const entry of entries) {
|
|
2404
|
-
const fullPath =
|
|
2737
|
+
const fullPath = join12(dir, entry);
|
|
2405
2738
|
try {
|
|
2406
2739
|
const stats = lstatSync3(fullPath);
|
|
2407
2740
|
if (stats.isSymbolicLink()) {
|
|
2408
|
-
if (!
|
|
2409
|
-
|
|
2741
|
+
if (!existsSync12(fullPath)) {
|
|
2742
|
+
unlinkSync4(fullPath);
|
|
2410
2743
|
fixed++;
|
|
2411
2744
|
}
|
|
2412
2745
|
}
|
|
@@ -2419,36 +2752,36 @@ function fixBrokenLinks(dir) {
|
|
|
2419
2752
|
}
|
|
2420
2753
|
|
|
2421
2754
|
// src/commands/status.ts
|
|
2422
|
-
import
|
|
2755
|
+
import chalk8 from "chalk";
|
|
2423
2756
|
async function statusCommand() {
|
|
2424
2757
|
const plugins = getAllPlugins();
|
|
2425
2758
|
const installed = scanInstalled();
|
|
2426
2759
|
const installedMap = new Map(installed.map((p) => [p.id, p]));
|
|
2427
2760
|
console.log();
|
|
2428
|
-
console.log(
|
|
2761
|
+
console.log(chalk8.bold(` ${t("status_title")}`));
|
|
2429
2762
|
console.log();
|
|
2430
2763
|
if (installed.length === 0) {
|
|
2431
|
-
console.log(
|
|
2432
|
-
console.log(
|
|
2764
|
+
console.log(chalk8.dim(` ${t("status_none")}`));
|
|
2765
|
+
console.log(chalk8.dim(` ${t("status_hint")}`));
|
|
2433
2766
|
console.log();
|
|
2434
2767
|
return;
|
|
2435
2768
|
}
|
|
2436
2769
|
for (const inst of installed) {
|
|
2437
2770
|
console.log(
|
|
2438
|
-
|
|
2771
|
+
chalk8.green(" \u2713") + ` ${inst.displayName}` + chalk8.dim(` (${inst.tool}, ${inst.level})`)
|
|
2439
2772
|
);
|
|
2440
2773
|
console.log(
|
|
2441
|
-
|
|
2774
|
+
chalk8.dim(` ${inst.skillsCount} skills, ${inst.agentsCount} agents`)
|
|
2442
2775
|
);
|
|
2443
|
-
console.log(
|
|
2444
|
-
console.log(
|
|
2776
|
+
console.log(chalk8.dim(` ${inst.configRoot}`));
|
|
2777
|
+
console.log(chalk8.dim(` ${t("status_install_time")}: ${inst.installTime}`));
|
|
2445
2778
|
console.log();
|
|
2446
2779
|
}
|
|
2447
2780
|
}
|
|
2448
2781
|
|
|
2449
2782
|
// src/commands/install.ts
|
|
2450
2783
|
import { confirm } from "@inquirer/prompts";
|
|
2451
|
-
import
|
|
2784
|
+
import chalk9 from "chalk";
|
|
2452
2785
|
async function installCommand(names, options) {
|
|
2453
2786
|
if (options.list) {
|
|
2454
2787
|
try {
|
|
@@ -2460,7 +2793,7 @@ async function installCommand(names, options) {
|
|
|
2460
2793
|
return;
|
|
2461
2794
|
}
|
|
2462
2795
|
if (names.length === 0) {
|
|
2463
|
-
const scanSpinner2 = createSpinner("
|
|
2796
|
+
const scanSpinner2 = createSpinner(t("loading_skills_list"));
|
|
2464
2797
|
scanSpinner2.start();
|
|
2465
2798
|
try {
|
|
2466
2799
|
const scanRepoManager = createRepositoryManager();
|
|
@@ -2471,7 +2804,7 @@ async function installCommand(names, options) {
|
|
|
2471
2804
|
}
|
|
2472
2805
|
let tool2;
|
|
2473
2806
|
if (options.tool) {
|
|
2474
|
-
tool2 = options.tool;
|
|
2807
|
+
tool2 = validateTool(options.tool);
|
|
2475
2808
|
} else {
|
|
2476
2809
|
const detected = await selectToolWithDetection();
|
|
2477
2810
|
if (detected === "back") return;
|
|
@@ -2489,42 +2822,45 @@ async function installCommand(names, options) {
|
|
|
2489
2822
|
break;
|
|
2490
2823
|
}
|
|
2491
2824
|
if (selectedSkills.length === 0) {
|
|
2492
|
-
logger.info("
|
|
2825
|
+
logger.info(t("install_no_skill_selected"));
|
|
2493
2826
|
return;
|
|
2494
2827
|
}
|
|
2495
2828
|
names = selectedSkills;
|
|
2496
2829
|
const repoManager = createRepositoryManager();
|
|
2497
|
-
const spinner = createSpinner(t("
|
|
2830
|
+
const spinner = createSpinner(t("loading_plugin_data"));
|
|
2498
2831
|
spinner.start();
|
|
2499
2832
|
const repoPath = await repoManager.ensureRepo();
|
|
2500
|
-
spinner.succeed(
|
|
2501
|
-
logger.info(`${t("skill_install_progress")} ${
|
|
2502
|
-
const level2 = options.level
|
|
2833
|
+
spinner.succeed("\u63D2\u4EF6\u6570\u636E\u52A0\u8F7D\u5B8C\u6210");
|
|
2834
|
+
logger.info(`${t("skill_install_progress")} ${chalk9.bold(names.length)} \u4E2A Skills...`);
|
|
2835
|
+
const level2 = options.level ? validateLevel(options.level) : "project";
|
|
2503
2836
|
const results = await installSkills(names, tool2, level2, repoPath);
|
|
2504
2837
|
let successCount = 0;
|
|
2505
2838
|
let failCount = 0;
|
|
2506
|
-
|
|
2839
|
+
const total = results.length;
|
|
2840
|
+
for (let i = 0; i < results.length; i++) {
|
|
2841
|
+
const result = results[i];
|
|
2842
|
+
const progress = `[${i + 1}/${total}]`;
|
|
2507
2843
|
if (result.success) {
|
|
2508
|
-
logger.success(`${result.skillId}`);
|
|
2844
|
+
logger.success(`${progress} ${result.skillId}`);
|
|
2509
2845
|
successCount++;
|
|
2510
2846
|
} else {
|
|
2511
|
-
logger.error(`${result.skillId}: ${result.error}`);
|
|
2847
|
+
logger.error(`${progress} ${result.skillId}: ${result.error}`);
|
|
2512
2848
|
failCount++;
|
|
2513
2849
|
}
|
|
2514
2850
|
}
|
|
2515
2851
|
const configRoot = getConfigRoot(tool2, level2);
|
|
2516
2852
|
logger.blank();
|
|
2517
|
-
logger.success(`${t("skill_install_done")}: ${
|
|
2853
|
+
logger.success(`${t("skill_install_done")}: ${chalk9.green(successCount + " \u6210\u529F")}, ${failCount > 0 ? chalk9.red(failCount + " \u5931\u8D25") : chalk9.dim(failCount + " \u5931\u8D25")}`);
|
|
2518
2854
|
logger.blank();
|
|
2519
|
-
logger.info(
|
|
2520
|
-
logger.info(
|
|
2855
|
+
logger.info(`${t("install_to")}: ${chalk9.cyan(configRoot + "/skills/")}`);
|
|
2856
|
+
logger.info(`${t("start_to_use").replace("{tool}", chalk9.green(tool2))}`);
|
|
2521
2857
|
logger.blank();
|
|
2522
2858
|
return;
|
|
2523
2859
|
}
|
|
2524
2860
|
}
|
|
2525
2861
|
}
|
|
2526
2862
|
}
|
|
2527
|
-
const scanSpinner = createSpinner("
|
|
2863
|
+
const scanSpinner = createSpinner(t("loading_skills_list"));
|
|
2528
2864
|
scanSpinner.start();
|
|
2529
2865
|
try {
|
|
2530
2866
|
const scanRepoManager = createRepositoryManager();
|
|
@@ -2552,18 +2888,18 @@ async function installCommand(names, options) {
|
|
|
2552
2888
|
for (const p of allPlugins) {
|
|
2553
2889
|
logger.step(` ${p.id} (${p.aliases.join(", ")})`);
|
|
2554
2890
|
}
|
|
2555
|
-
logger.info(`\u53EF\u7528 Skills: ${
|
|
2891
|
+
logger.info(`\u53EF\u7528 Skills: ${chalk9.cyan("install-helper install --list")}`);
|
|
2556
2892
|
return;
|
|
2557
2893
|
}
|
|
2558
2894
|
let tool;
|
|
2559
2895
|
if (options.tool) {
|
|
2560
|
-
tool = options.tool;
|
|
2896
|
+
tool = validateTool(options.tool);
|
|
2561
2897
|
} else {
|
|
2562
2898
|
const detected = await selectToolWithDetection();
|
|
2563
2899
|
if (detected === "back") return;
|
|
2564
2900
|
tool = detected;
|
|
2565
2901
|
}
|
|
2566
|
-
const level = options.level
|
|
2902
|
+
const level = options.level ? validateLevel(options.level) : "project";
|
|
2567
2903
|
if (plugins.length > 0) {
|
|
2568
2904
|
const configRoot = getConfigRoot(tool, level);
|
|
2569
2905
|
const manifests = readAllManifests(configRoot);
|
|
@@ -2591,16 +2927,18 @@ async function installCommand(names, options) {
|
|
|
2591
2927
|
}
|
|
2592
2928
|
if (pluginsToInstall.length > 0) {
|
|
2593
2929
|
const repoManager = createRepositoryManager();
|
|
2594
|
-
const spinner = createSpinner(t("
|
|
2930
|
+
const spinner = createSpinner(t("loading_plugin_data"));
|
|
2595
2931
|
spinner.start();
|
|
2596
2932
|
const repoPath = await repoManager.ensureRepo();
|
|
2597
|
-
spinner.succeed(t("
|
|
2933
|
+
spinner.succeed(t("loading_plugin_data_complete"));
|
|
2598
2934
|
const allPlugins = getAllPlugins();
|
|
2599
2935
|
const results = await installPlugins(
|
|
2600
2936
|
pluginsToInstall,
|
|
2601
2937
|
tool,
|
|
2602
2938
|
level,
|
|
2603
|
-
repoPath
|
|
2939
|
+
repoPath,
|
|
2940
|
+
void 0,
|
|
2941
|
+
options.yes
|
|
2604
2942
|
);
|
|
2605
2943
|
const summary = results.map((result) => {
|
|
2606
2944
|
const plugin = allPlugins.find((p) => p.id === result.pluginId);
|
|
@@ -2618,28 +2956,31 @@ async function installCommand(names, options) {
|
|
|
2618
2956
|
}
|
|
2619
2957
|
if (skills.length > 0) {
|
|
2620
2958
|
const repoManager = createRepositoryManager();
|
|
2621
|
-
const spinner = createSpinner(t("
|
|
2959
|
+
const spinner = createSpinner(t("loading_plugin_data"));
|
|
2622
2960
|
spinner.start();
|
|
2623
2961
|
const repoPath = await repoManager.ensureRepo();
|
|
2624
|
-
spinner.succeed(t("
|
|
2625
|
-
logger.info(`${t("skill_install_progress")} ${
|
|
2962
|
+
spinner.succeed(t("loading_plugin_data_complete"));
|
|
2963
|
+
logger.info(`${t("skill_install_progress")} ${chalk9.bold(skills.length)} \u4E2A Skills...`);
|
|
2626
2964
|
const results = await installSkills(skills, tool, level, repoPath);
|
|
2627
2965
|
let successCount = 0;
|
|
2628
2966
|
let failCount = 0;
|
|
2629
|
-
|
|
2967
|
+
const total = results.length;
|
|
2968
|
+
for (let i = 0; i < results.length; i++) {
|
|
2969
|
+
const result = results[i];
|
|
2970
|
+
const progress = `[${i + 1}/${total}]`;
|
|
2630
2971
|
if (result.success) {
|
|
2631
|
-
logger.success(`${result.skillId}`);
|
|
2972
|
+
logger.success(`${progress} ${result.skillId}`);
|
|
2632
2973
|
successCount++;
|
|
2633
2974
|
} else {
|
|
2634
|
-
logger.error(`${result.skillId}: ${result.error}`);
|
|
2975
|
+
logger.error(`${progress} ${result.skillId}: ${result.error}`);
|
|
2635
2976
|
failCount++;
|
|
2636
2977
|
}
|
|
2637
2978
|
}
|
|
2638
2979
|
logger.blank();
|
|
2639
|
-
logger.success(`${t("skill_install_done")}: ${
|
|
2980
|
+
logger.success(`${t("skill_install_done")}: ${chalk9.green(successCount + " \u6210\u529F")}, ${failCount > 0 ? chalk9.red(failCount + " \u5931\u8D25") : chalk9.dim(failCount + " \u5931\u8D25")}`);
|
|
2640
2981
|
logger.blank();
|
|
2641
|
-
logger.info(
|
|
2642
|
-
logger.info(
|
|
2982
|
+
logger.info(`${t("install_to")}: ${chalk9.cyan(getConfigRoot(tool, level) + "/skills/")}`);
|
|
2983
|
+
logger.info(`${t("start_to_use").replace("{tool}", chalk9.green(tool))}`);
|
|
2643
2984
|
logger.blank();
|
|
2644
2985
|
}
|
|
2645
2986
|
}
|
|
@@ -2671,11 +3012,11 @@ async function installPlugins(pluginIds, tool, level, repoPath) {
|
|
|
2671
3012
|
}
|
|
2672
3013
|
|
|
2673
3014
|
// src/commands/uninstall.ts
|
|
2674
|
-
import { existsSync as
|
|
2675
|
-
import
|
|
3015
|
+
import { existsSync as existsSync13, unlinkSync as unlinkSync5, rmdirSync as rmdirSync2, readdirSync as readdirSync5, lstatSync as lstatSync4 } from "fs";
|
|
3016
|
+
import chalk10 from "chalk";
|
|
2676
3017
|
async function uninstallCommand(names, options) {
|
|
2677
|
-
const tool = options.tool
|
|
2678
|
-
const level = options.level
|
|
3018
|
+
const tool = options.tool ? validateTool(options.tool) : "opencode";
|
|
3019
|
+
const level = options.level ? validateLevel(options.level) : "project";
|
|
2679
3020
|
const plugins = [];
|
|
2680
3021
|
const skills = [];
|
|
2681
3022
|
for (const name of names) {
|
|
@@ -2689,24 +3030,24 @@ async function uninstallCommand(names, options) {
|
|
|
2689
3030
|
skills.push(skill.id);
|
|
2690
3031
|
continue;
|
|
2691
3032
|
}
|
|
2692
|
-
logger.error(
|
|
3033
|
+
logger.error(`${t("uninstall_not_found")}: ${name}`);
|
|
2693
3034
|
}
|
|
2694
3035
|
for (const pluginId of plugins) {
|
|
2695
3036
|
const plugin = findPlugin(pluginId);
|
|
2696
3037
|
if (!plugin) continue;
|
|
2697
3038
|
const record = readRecord(plugin.id);
|
|
2698
3039
|
if (!record) {
|
|
2699
|
-
logger.warn(`${plugin.displayName}
|
|
2700
|
-
logger.info(
|
|
3040
|
+
logger.warn(`${plugin.displayName} ${t("uninstall_no_record")}`);
|
|
3041
|
+
logger.info(`${t("uninstall_no_record_hint")}`);
|
|
2701
3042
|
continue;
|
|
2702
3043
|
}
|
|
2703
|
-
logger.info(
|
|
3044
|
+
logger.info(`${t("uninstall_in_progress")} ${plugin.displayName}...`);
|
|
2704
3045
|
let removedFiles = 0;
|
|
2705
3046
|
let removedDirs = 0;
|
|
2706
3047
|
for (const filePath of record.files) {
|
|
2707
3048
|
try {
|
|
2708
|
-
if (
|
|
2709
|
-
|
|
3049
|
+
if (existsSync13(filePath) || isSymlink3(filePath)) {
|
|
3050
|
+
unlinkSync5(filePath);
|
|
2710
3051
|
const name = filePath.split("/").pop() || filePath;
|
|
2711
3052
|
logger.step(` \u79FB\u9664: ${name}`);
|
|
2712
3053
|
removedFiles++;
|
|
@@ -2714,10 +3055,14 @@ async function uninstallCommand(names, options) {
|
|
|
2714
3055
|
} catch {
|
|
2715
3056
|
}
|
|
2716
3057
|
}
|
|
3058
|
+
const configRoot = getConfigRoot(record.tool, record.level);
|
|
2717
3059
|
const sortedDirs = [...record.directories].sort((a, b) => b.length - a.length);
|
|
2718
3060
|
for (const dirPath of sortedDirs) {
|
|
2719
3061
|
try {
|
|
2720
|
-
if (
|
|
3062
|
+
if (dirPath === configRoot) {
|
|
3063
|
+
continue;
|
|
3064
|
+
}
|
|
3065
|
+
if (existsSync13(dirPath)) {
|
|
2721
3066
|
const entries = readdirSync5(dirPath);
|
|
2722
3067
|
if (entries.length === 0) {
|
|
2723
3068
|
rmdirSync2(dirPath);
|
|
@@ -2731,15 +3076,32 @@ async function uninstallCommand(names, options) {
|
|
|
2731
3076
|
}
|
|
2732
3077
|
deleteRecord(plugin.id);
|
|
2733
3078
|
removeInstalledPlugin(plugin.id);
|
|
3079
|
+
const backups = findBackups(configRoot);
|
|
3080
|
+
const otherBackups = backups.filter((b) => b.pluginId !== pluginId);
|
|
3081
|
+
if (otherBackups.length > 0) {
|
|
3082
|
+
const choice = await showRestorePrompt(otherBackups);
|
|
3083
|
+
if (choice !== "none") {
|
|
3084
|
+
const restored = restoreBackup(choice, configRoot, record.tool);
|
|
3085
|
+
if (restored) {
|
|
3086
|
+
const backupInfo = otherBackups.find((b) => b.filePath === choice);
|
|
3087
|
+
logger.success(`${t("backup_restore_success")}: ${backupInfo?.pluginName || ""}`);
|
|
3088
|
+
deleteBackup(choice);
|
|
3089
|
+
}
|
|
3090
|
+
}
|
|
3091
|
+
}
|
|
3092
|
+
const currentBackups = backups.filter((b) => b.pluginId === pluginId);
|
|
3093
|
+
for (const backup of currentBackups) {
|
|
3094
|
+
deleteBackup(backup.filePath);
|
|
3095
|
+
}
|
|
2734
3096
|
const totalRemoved = removedFiles + removedDirs;
|
|
2735
3097
|
if (totalRemoved > 0) {
|
|
2736
|
-
logger.success(
|
|
3098
|
+
logger.success(`${t("uninstall_removed")} ${plugin.displayName}\uFF08\u79FB\u9664 ${removedFiles} \u4E2A\u6587\u4EF6\uFF0C${removedDirs} \u4E2A\u76EE\u5F55\uFF09`);
|
|
2737
3099
|
} else {
|
|
2738
|
-
logger.warn(`${plugin.displayName}
|
|
3100
|
+
logger.warn(`${plugin.displayName}${t("uninstall_files_gone")}`);
|
|
2739
3101
|
}
|
|
2740
3102
|
}
|
|
2741
3103
|
if (skills.length > 0) {
|
|
2742
|
-
logger.info(
|
|
3104
|
+
logger.info(`${t("uninstall_skills_in_progress")} ${skills.length} \u4E2A Skills...`);
|
|
2743
3105
|
const results = await uninstallSkills(skills, tool, level);
|
|
2744
3106
|
let successCount = 0;
|
|
2745
3107
|
let failCount = 0;
|
|
@@ -2751,7 +3113,7 @@ async function uninstallCommand(names, options) {
|
|
|
2751
3113
|
}
|
|
2752
3114
|
}
|
|
2753
3115
|
logger.blank();
|
|
2754
|
-
logger.success(`${t("skill_uninstall_done")}: ${
|
|
3116
|
+
logger.success(`${t("skill_uninstall_done")}: ${chalk10.green(successCount + " \u6210\u529F")}, ${failCount > 0 ? chalk10.red(failCount + " \u5931\u8D25") : chalk10.dim(failCount + " \u5931\u8D25")}`);
|
|
2755
3117
|
logger.blank();
|
|
2756
3118
|
}
|
|
2757
3119
|
}
|
|
@@ -2764,17 +3126,17 @@ function isSymlink3(path) {
|
|
|
2764
3126
|
}
|
|
2765
3127
|
|
|
2766
3128
|
// src/commands/update.ts
|
|
2767
|
-
import
|
|
3129
|
+
import chalk11 from "chalk";
|
|
2768
3130
|
async function updateCommand(pluginNames, options) {
|
|
2769
3131
|
let tool;
|
|
2770
3132
|
if (options.tool) {
|
|
2771
|
-
tool = options.tool;
|
|
3133
|
+
tool = validateTool(options.tool);
|
|
2772
3134
|
} else {
|
|
2773
3135
|
const detected = await selectToolWithDetection();
|
|
2774
3136
|
if (detected === "back") return;
|
|
2775
3137
|
tool = detected;
|
|
2776
3138
|
}
|
|
2777
|
-
const level = options.level
|
|
3139
|
+
const level = options.level ? validateLevel(options.level) : "project";
|
|
2778
3140
|
let pluginsToUpdate = [];
|
|
2779
3141
|
if (pluginNames.length === 0) {
|
|
2780
3142
|
const configRoot = getConfigRoot(tool, level);
|
|
@@ -2782,7 +3144,7 @@ async function updateCommand(pluginNames, options) {
|
|
|
2782
3144
|
pluginsToUpdate = manifests.map((m) => m.team);
|
|
2783
3145
|
if (pluginsToUpdate.length === 0) {
|
|
2784
3146
|
logger.info(t("update_no_plugins"));
|
|
2785
|
-
logger.info(`\u4F7F\u7528 ${
|
|
3147
|
+
logger.info(`\u4F7F\u7528 ${chalk11.cyan("install-helper install <plugin>")} \u5B89\u88C5\u63D2\u4EF6`);
|
|
2786
3148
|
return;
|
|
2787
3149
|
}
|
|
2788
3150
|
} else {
|
|
@@ -2844,42 +3206,42 @@ async function updateCommand(pluginNames, options) {
|
|
|
2844
3206
|
}
|
|
2845
3207
|
|
|
2846
3208
|
// src/commands/info.ts
|
|
2847
|
-
import
|
|
2848
|
-
import { existsSync as
|
|
2849
|
-
import { join as
|
|
3209
|
+
import chalk12 from "chalk";
|
|
3210
|
+
import { existsSync as existsSync14, readdirSync as readdirSync6 } from "fs";
|
|
3211
|
+
import { join as join13 } from "path";
|
|
2850
3212
|
async function infoCommand(pluginName) {
|
|
2851
3213
|
const plugin = findPlugin(pluginName);
|
|
2852
3214
|
if (!plugin) {
|
|
2853
|
-
console.log(
|
|
3215
|
+
console.log(chalk12.red(` ${t("info_not_found")}: ${pluginName}`));
|
|
2854
3216
|
return;
|
|
2855
3217
|
}
|
|
2856
3218
|
const installed = scanInstalled();
|
|
2857
3219
|
const isInstalled = installed.some((p) => p.id === plugin.id);
|
|
2858
|
-
const statusText = isInstalled ?
|
|
3220
|
+
const statusText = isInstalled ? chalk12.green(`\u2713 ${t("status_installed")}`) : chalk12.dim(`\u2014 ${t("status_not_installed")}`);
|
|
2859
3221
|
console.log();
|
|
2860
|
-
console.log(
|
|
2861
|
-
console.log(
|
|
3222
|
+
console.log(chalk12.bold(` ${plugin.displayName}`));
|
|
3223
|
+
console.log(chalk12.dim(" " + "\u2500".repeat(40)));
|
|
2862
3224
|
console.log();
|
|
2863
|
-
console.log(` ${
|
|
2864
|
-
console.log(` ${
|
|
2865
|
-
console.log(` ${
|
|
2866
|
-
console.log(` ${
|
|
2867
|
-
console.log(` ${
|
|
2868
|
-
console.log(` ${
|
|
3225
|
+
console.log(` ${chalk12.dim(t("info_description") + ":")} ${plugin.description}`);
|
|
3226
|
+
console.log(` ${chalk12.dim("ID:")} ${plugin.id}`);
|
|
3227
|
+
console.log(` ${chalk12.dim(t("info_status") + ":")} ${statusText}`);
|
|
3228
|
+
console.log(` ${chalk12.dim(t("info_skills") + ":")} ${plugin.skills}`);
|
|
3229
|
+
console.log(` ${chalk12.dim(t("info_agents") + ":")} ${plugin.agents}`);
|
|
3230
|
+
console.log(` ${chalk12.dim(t("info_aliases") + ":")} ${plugin.aliases.join(", ")}`);
|
|
2869
3231
|
console.log();
|
|
2870
3232
|
try {
|
|
2871
3233
|
const repoManager = createRepositoryManager();
|
|
2872
3234
|
const repoPath = await repoManager.ensureRepo();
|
|
2873
|
-
const quickstartPath =
|
|
2874
|
-
if (
|
|
2875
|
-
console.log(` ${
|
|
3235
|
+
const quickstartPath = join13(repoPath, plugin.dir, "quickstart.md");
|
|
3236
|
+
if (existsSync14(quickstartPath)) {
|
|
3237
|
+
console.log(` ${chalk12.dim(t("info_quickstart") + ":")} ${quickstartPath}`);
|
|
2876
3238
|
}
|
|
2877
|
-
const agentsDir =
|
|
2878
|
-
if (
|
|
3239
|
+
const agentsDir = join13(repoPath, plugin.dir, "agents");
|
|
3240
|
+
if (existsSync14(agentsDir)) {
|
|
2879
3241
|
const agentFiles = readdirSync6(agentsDir).filter((f) => f.endsWith(".md"));
|
|
2880
3242
|
if (agentFiles.length > 0) {
|
|
2881
3243
|
console.log();
|
|
2882
|
-
console.log(` ${
|
|
3244
|
+
console.log(` ${chalk12.bold("Agents:")}`);
|
|
2883
3245
|
for (const agent of agentFiles) {
|
|
2884
3246
|
console.log(` \u2022 ${agent.replace(".md", "")}`);
|
|
2885
3247
|
}
|
|
@@ -2891,39 +3253,39 @@ async function infoCommand(pluginName) {
|
|
|
2891
3253
|
}
|
|
2892
3254
|
|
|
2893
3255
|
// src/commands/lang.ts
|
|
2894
|
-
import
|
|
3256
|
+
import chalk13 from "chalk";
|
|
2895
3257
|
async function langCommand(action, value) {
|
|
2896
3258
|
const config = readConfig();
|
|
2897
3259
|
if (!action || action === "show") {
|
|
2898
3260
|
console.log();
|
|
2899
|
-
console.log(
|
|
2900
|
-
console.log(
|
|
3261
|
+
console.log(chalk13.bold(` ${t("lang_title")}`));
|
|
3262
|
+
console.log(chalk13.dim(" " + "\u2500".repeat(40)));
|
|
2901
3263
|
console.log();
|
|
2902
|
-
console.log(` ${
|
|
3264
|
+
console.log(` ${chalk13.dim(t("lang_current") + ":")} ${config.language}`);
|
|
2903
3265
|
console.log();
|
|
2904
|
-
console.log(
|
|
2905
|
-
console.log(
|
|
3266
|
+
console.log(chalk13.dim(` ${t("lang_supported")}`));
|
|
3267
|
+
console.log(chalk13.dim(` ${t("lang_usage")}`));
|
|
2906
3268
|
console.log();
|
|
2907
3269
|
return;
|
|
2908
3270
|
}
|
|
2909
3271
|
if (action === "set") {
|
|
2910
3272
|
if (!value) {
|
|
2911
|
-
console.log(
|
|
3273
|
+
console.log(chalk13.red(` ${t("lang_specify")}`));
|
|
2912
3274
|
return;
|
|
2913
3275
|
}
|
|
2914
3276
|
if (value !== "zh_CN" && value !== "en_US") {
|
|
2915
|
-
console.log(
|
|
3277
|
+
console.log(chalk13.red(` ${t("lang_invalid")}`));
|
|
2916
3278
|
return;
|
|
2917
3279
|
}
|
|
2918
3280
|
updateConfig({ language: value });
|
|
2919
3281
|
setLanguage(value);
|
|
2920
3282
|
console.log();
|
|
2921
|
-
console.log(
|
|
3283
|
+
console.log(chalk13.green(` \u2713 ${t("lang_set")} ${value}`));
|
|
2922
3284
|
console.log();
|
|
2923
3285
|
return;
|
|
2924
3286
|
}
|
|
2925
|
-
console.log(
|
|
2926
|
-
console.log(
|
|
3287
|
+
console.log(chalk13.red(` ${t("lang_unknown_action")}: ${action}`));
|
|
3288
|
+
console.log(chalk13.dim(` ${t("lang_supported_actions")}`));
|
|
2927
3289
|
}
|
|
2928
3290
|
|
|
2929
3291
|
// src/cli.ts
|
|
@@ -2933,7 +3295,7 @@ function createCLI() {
|
|
|
2933
3295
|
setLanguage(config.language);
|
|
2934
3296
|
}
|
|
2935
3297
|
const program2 = new Command();
|
|
2936
|
-
program2.name("install-helper").description("Install Helper - Interactive installer for CANN operator development skills").version("0.0.2-beta.
|
|
3298
|
+
program2.name("install-helper").description("CANNBot Install Helper - Interactive installer for CANN operator development skills").version("0.0.2-beta.11");
|
|
2937
3299
|
program2.command("init", { isDefault: false }).description("Run interactive installation wizard").action(async () => {
|
|
2938
3300
|
await initCommand();
|
|
2939
3301
|
});
|