@cannbot-ai/install-helper 0.0.2-beta.10 → 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 CHANGED
@@ -145,251 +145,6 @@ 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
- function detectTraeVariant() {
149
- const home = homedir();
150
- if (existsSync(join(home, ".trae-cn"))) return "ide";
151
- if (existsSync(join(home, ".marscode"))) return "plugin";
152
- if (existsSync(join(home, ".traecli"))) return "cli";
153
- return "unknown";
154
- }
155
- function getConfigRoot(tool, level, base) {
156
- const home = homedir();
157
- if (level === "global") {
158
- switch (tool) {
159
- case "opencode":
160
- return join(home, ".config", "opencode");
161
- case "claude":
162
- return join(home, ".claude");
163
- case "trae": {
164
- const variant = detectTraeVariant();
165
- switch (variant) {
166
- case "plugin":
167
- return join(home, ".marscode");
168
- case "cli":
169
- return join(home, ".traecli");
170
- default:
171
- return join(home, ".trae-cn");
172
- }
173
- }
174
- case "cursor":
175
- return join(home, ".cursor");
176
- case "copilot":
177
- return join(home, ".copilot");
178
- }
179
- }
180
- const baseDir = base || process.cwd();
181
- switch (tool) {
182
- case "opencode":
183
- return join(baseDir, ".opencode");
184
- case "claude":
185
- return join(baseDir, ".claude");
186
- case "trae": {
187
- const variant = detectTraeVariant();
188
- switch (variant) {
189
- case "plugin":
190
- return join(baseDir, ".marscode");
191
- case "cli":
192
- return join(baseDir, ".traecli");
193
- default:
194
- return join(baseDir, ".trae");
195
- }
196
- }
197
- case "cursor":
198
- return join(baseDir, ".cursor");
199
- case "copilot":
200
- return join(baseDir, ".github");
201
- }
202
- }
203
- function getConfigFileName(tool) {
204
- return tool === "claude" ? "CLAUDE.md" : "AGENTS.md";
205
- }
206
- function getSkillsDir(configRoot) {
207
- return join(configRoot, "skills");
208
- }
209
- function getAgentsDir(configRoot) {
210
- return join(configRoot, "agents");
211
- }
212
- function getManifestPath(configRoot) {
213
- return join(configRoot, "cannbot-manifest.json");
214
- }
215
- function getCannbotConfigDir() {
216
- return join(homedir(), ".cannbot");
217
- }
218
- function getCannbotRepoPath() {
219
- return join(getCannbotConfigDir(), "repo");
220
- }
221
-
222
- // src/core/detector.ts
223
- async function getCommandVersion(cmd, args = ["--version"]) {
224
- try {
225
- const result = await execa(cmd, args, { timeout: 5e3 });
226
- const output = result.stdout.trim();
227
- const match = output.match(/(\d+\.\d+\.\d+)/);
228
- return match ? match[1] : output.split("\n")[0];
229
- } catch {
230
- return void 0;
231
- }
232
- }
233
- async function getCommandPath(cmd) {
234
- try {
235
- const result = await execa("which", [cmd], { timeout: 5e3 });
236
- return result.stdout.trim();
237
- } catch {
238
- return void 0;
239
- }
240
- }
241
- async function detectOpenCode() {
242
- const path = await getCommandPath("opencode");
243
- if (!path) return void 0;
244
- const version = await getCommandVersion("opencode");
245
- return { name: "opencode", version, path };
246
- }
247
- async function detectClaude() {
248
- const path = await getCommandPath("claude");
249
- if (!path) return void 0;
250
- const version = await getCommandVersion("claude");
251
- return { name: "claude", version, path };
252
- }
253
- async function detectTrae() {
254
- const home = homedir2();
255
- const variant = detectTraeVariant();
256
- let path;
257
- if (variant === "ide" && existsSync2(join2(home, ".trae-cn"))) {
258
- path = join2(home, ".trae-cn");
259
- } else if (variant === "plugin" && existsSync2(join2(home, ".marscode"))) {
260
- path = join2(home, ".marscode");
261
- } else if (variant === "cli" && existsSync2(join2(home, ".traecli"))) {
262
- path = join2(home, ".traecli");
263
- } else if (variant === "unknown") {
264
- const cmdPath = await getCommandPath("trae");
265
- if (cmdPath) path = cmdPath;
266
- }
267
- if (!path) return void 0;
268
- return { name: "trae", version: variant, path };
269
- }
270
- async function detectCursor() {
271
- const path = await getCommandPath("cursor");
272
- if (path) {
273
- const version = await getCommandVersion("cursor");
274
- return { name: "cursor", version, path };
275
- }
276
- if (process.platform === "darwin") {
277
- const appPath = "/Applications/Cursor.app";
278
- if (existsSync2(appPath)) {
279
- return { name: "cursor", path: appPath };
280
- }
281
- }
282
- return void 0;
283
- }
284
- async function detectCopilot() {
285
- const path = await getCommandPath("gh");
286
- if (!path) return void 0;
287
- try {
288
- await execa("gh", ["extension", "list"], { timeout: 5e3 });
289
- return { name: "copilot", path };
290
- } catch {
291
- return void 0;
292
- }
293
- }
294
- async function detectTools() {
295
- const detectors = [
296
- detectOpenCode,
297
- detectClaude,
298
- detectTrae,
299
- detectCursor,
300
- detectCopilot
301
- ];
302
- const results = await Promise.allSettled(detectors.map((d) => d()));
303
- const tools = [];
304
- for (const result of results) {
305
- if (result.status === "fulfilled" && result.value) {
306
- tools.push(result.value);
307
- }
308
- }
309
- return tools;
310
- }
311
- function getToolDisplayName(tool) {
312
- const names = {
313
- opencode: "OpenCode",
314
- claude: "Claude Code",
315
- trae: "Trae",
316
- cursor: "Cursor",
317
- copilot: "GitHub Copilot"
318
- };
319
- return names[tool];
320
- }
321
- function getAllTools() {
322
- return ["opencode", "claude", "trae", "cursor", "copilot"];
323
- }
324
-
325
- // src/core/manifest.ts
326
- import { existsSync as existsSync3, readFileSync } from "fs";
327
- import { join as join3 } from "path";
328
- function readManifest(configRoot) {
329
- const manifestPath = getManifestPath(configRoot);
330
- if (existsSync3(manifestPath)) {
331
- try {
332
- const content = readFileSync(manifestPath, "utf-8");
333
- return JSON.parse(content);
334
- } catch {
335
- }
336
- }
337
- return null;
338
- }
339
- function readAllManifests(configRoot) {
340
- const manifests = [];
341
- const plugins = getAllPlugins();
342
- const standardPath = getManifestPath(configRoot);
343
- if (existsSync3(standardPath)) {
344
- try {
345
- const content = readFileSync(standardPath, "utf-8");
346
- manifests.push(JSON.parse(content));
347
- } catch {
348
- }
349
- }
350
- for (const plugin of plugins) {
351
- const pluginManifestPath = join3(configRoot, `${plugin.id}-manifest.json`);
352
- if (existsSync3(pluginManifestPath)) {
353
- try {
354
- const content = readFileSync(pluginManifestPath, "utf-8");
355
- manifests.push(JSON.parse(content));
356
- } catch {
357
- }
358
- }
359
- }
360
- return manifests;
361
- }
362
- function scanInstalled() {
363
- const plugins = getAllPlugins();
364
- const installed = [];
365
- const tools = ["opencode", "claude", "trae", "cursor", "copilot"];
366
- const levels = ["project", "global"];
367
- for (const tool of tools) {
368
- for (const level of levels) {
369
- const configRoot = getConfigRoot(tool, level);
370
- const manifests = readAllManifests(configRoot);
371
- for (const manifest of manifests) {
372
- const plugin = plugins.find((p) => p.id === manifest.team);
373
- if (!plugin) continue;
374
- const alreadyAdded = installed.some(
375
- (p) => p.id === plugin.id && p.tool === tool && p.level === level
376
- );
377
- if (alreadyAdded) continue;
378
- installed.push({
379
- id: plugin.id,
380
- displayName: plugin.displayName,
381
- tool,
382
- level,
383
- skillsCount: manifest.installed_skills?.length || 0,
384
- agentsCount: manifest.installed_agents?.length || 0,
385
- installTime: manifest.install_time,
386
- configRoot
387
- });
388
- }
389
- }
390
- }
391
- return installed;
392
- }
393
148
 
394
149
  // src/utils/i18n.ts
395
150
  var zh_CN = {
@@ -454,6 +209,8 @@ var zh_CN = {
454
209
  error_tool_not_found: "\u672A\u68C0\u6D4B\u5230\u4EFB\u4F55 AI \u7F16\u7A0B\u5DE5\u5177",
455
210
  error_plugin_not_found: "\u672A\u627E\u5230\u63D2\u4EF6",
456
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}",
457
214
  quick_start: "\u542F\u52A8\u547D\u4EE4",
458
215
  quick_start_hint: "\u8BD5\u8BD5\u8F93\u5165: \u5E2E\u6211\u5F00\u53D1\u4E00\u4E2A Abs \u7B97\u5B50",
459
216
  skill_select_category: "\u9009\u62E9 Skill \u7C7B\u522B",
@@ -589,6 +346,8 @@ var en_US = {
589
346
  error_tool_not_found: "No AI coding tool detected",
590
347
  error_plugin_not_found: "Plugin not found",
591
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}",
592
351
  quick_start: "Launch command",
593
352
  quick_start_hint: "Try: help me develop an Abs operator",
594
353
  skill_select_category: "Select Skill category",
@@ -670,6 +429,279 @@ function t(key) {
670
429
  return currentLang === "zh_CN" ? zh_CN[key] : en_US[key];
671
430
  }
672
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
+ }
451
+ function detectTraeVariant() {
452
+ const home = homedir();
453
+ if (existsSync(join(home, ".trae-cn"))) return "ide";
454
+ if (existsSync(join(home, ".marscode"))) return "plugin";
455
+ if (existsSync(join(home, ".traecli"))) return "cli";
456
+ return "unknown";
457
+ }
458
+ function getConfigRoot(tool, level, base) {
459
+ const home = homedir();
460
+ if (level === "global") {
461
+ switch (tool) {
462
+ case "opencode":
463
+ return join(home, ".config", "opencode");
464
+ case "claude":
465
+ return join(home, ".claude");
466
+ case "trae": {
467
+ const variant = detectTraeVariant();
468
+ switch (variant) {
469
+ case "plugin":
470
+ return join(home, ".marscode");
471
+ case "cli":
472
+ return join(home, ".traecli");
473
+ default:
474
+ return join(home, ".trae-cn");
475
+ }
476
+ }
477
+ case "cursor":
478
+ return join(home, ".cursor");
479
+ case "copilot":
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
+ );
485
+ }
486
+ }
487
+ const baseDir = base || process.cwd();
488
+ switch (tool) {
489
+ case "opencode":
490
+ return join(baseDir, ".opencode");
491
+ case "claude":
492
+ return join(baseDir, ".claude");
493
+ case "trae": {
494
+ const variant = detectTraeVariant();
495
+ switch (variant) {
496
+ case "plugin":
497
+ return join(baseDir, ".marscode");
498
+ case "cli":
499
+ return join(baseDir, ".traecli");
500
+ default:
501
+ return join(baseDir, ".trae");
502
+ }
503
+ }
504
+ case "cursor":
505
+ return join(baseDir, ".cursor");
506
+ case "copilot":
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
+ );
512
+ }
513
+ }
514
+ function getConfigFileName(tool) {
515
+ return tool === "claude" ? "CLAUDE.md" : "AGENTS.md";
516
+ }
517
+ function getSkillsDir(configRoot) {
518
+ return join(configRoot, "skills");
519
+ }
520
+ function getAgentsDir(configRoot) {
521
+ return join(configRoot, "agents");
522
+ }
523
+ function getManifestPath(configRoot) {
524
+ return join(configRoot, "cannbot-manifest.json");
525
+ }
526
+ function getCannbotConfigDir() {
527
+ return join(homedir(), ".cannbot");
528
+ }
529
+ function getCannbotRepoPath() {
530
+ return join(getCannbotConfigDir(), "repo");
531
+ }
532
+
533
+ // src/core/detector.ts
534
+ async function getCommandVersion(cmd, args = ["--version"]) {
535
+ try {
536
+ const result = await execa(cmd, args, { timeout: 5e3 });
537
+ const output = result.stdout.trim();
538
+ const match = output.match(/(\d+\.\d+\.\d+)/);
539
+ return match ? match[1] : output.split("\n")[0];
540
+ } catch {
541
+ return void 0;
542
+ }
543
+ }
544
+ async function getCommandPath(cmd) {
545
+ try {
546
+ const result = await execa("which", [cmd], { timeout: 5e3 });
547
+ return result.stdout.trim();
548
+ } catch {
549
+ return void 0;
550
+ }
551
+ }
552
+ async function detectOpenCode() {
553
+ const path = await getCommandPath("opencode");
554
+ if (!path) return void 0;
555
+ const version = await getCommandVersion("opencode");
556
+ return { name: "opencode", version, path };
557
+ }
558
+ async function detectClaude() {
559
+ const path = await getCommandPath("claude");
560
+ if (!path) return void 0;
561
+ const version = await getCommandVersion("claude");
562
+ return { name: "claude", version, path };
563
+ }
564
+ async function detectTrae() {
565
+ const home = homedir2();
566
+ const variant = detectTraeVariant();
567
+ let path;
568
+ if (variant === "ide" && existsSync2(join2(home, ".trae-cn"))) {
569
+ path = join2(home, ".trae-cn");
570
+ } else if (variant === "plugin" && existsSync2(join2(home, ".marscode"))) {
571
+ path = join2(home, ".marscode");
572
+ } else if (variant === "cli" && existsSync2(join2(home, ".traecli"))) {
573
+ path = join2(home, ".traecli");
574
+ } else if (variant === "unknown") {
575
+ const cmdPath = await getCommandPath("trae");
576
+ if (cmdPath) path = cmdPath;
577
+ }
578
+ if (!path) return void 0;
579
+ return { name: "trae", version: variant, path };
580
+ }
581
+ async function detectCursor() {
582
+ const path = await getCommandPath("cursor");
583
+ if (path) {
584
+ const version = await getCommandVersion("cursor");
585
+ return { name: "cursor", version, path };
586
+ }
587
+ if (process.platform === "darwin") {
588
+ const appPath = "/Applications/Cursor.app";
589
+ if (existsSync2(appPath)) {
590
+ return { name: "cursor", path: appPath };
591
+ }
592
+ }
593
+ return void 0;
594
+ }
595
+ async function detectCopilot() {
596
+ const path = await getCommandPath("gh");
597
+ if (!path) return void 0;
598
+ try {
599
+ await execa("gh", ["extension", "list"], { timeout: 5e3 });
600
+ return { name: "copilot", path };
601
+ } catch {
602
+ return void 0;
603
+ }
604
+ }
605
+ async function detectTools() {
606
+ const detectors = [
607
+ detectOpenCode,
608
+ detectClaude,
609
+ detectTrae,
610
+ detectCursor,
611
+ detectCopilot
612
+ ];
613
+ const results = await Promise.allSettled(detectors.map((d) => d()));
614
+ const tools = [];
615
+ for (const result of results) {
616
+ if (result.status === "fulfilled" && result.value) {
617
+ tools.push(result.value);
618
+ }
619
+ }
620
+ return tools;
621
+ }
622
+ function getToolDisplayName(tool) {
623
+ const names = {
624
+ opencode: "OpenCode",
625
+ claude: "Claude Code",
626
+ trae: "Trae",
627
+ cursor: "Cursor",
628
+ copilot: "GitHub Copilot"
629
+ };
630
+ return names[tool];
631
+ }
632
+ function getAllTools() {
633
+ return ["opencode", "claude", "trae", "cursor", "copilot"];
634
+ }
635
+
636
+ // src/core/manifest.ts
637
+ import { existsSync as existsSync3, readFileSync } from "fs";
638
+ import { join as join3 } from "path";
639
+ function readManifest(configRoot) {
640
+ const manifestPath = getManifestPath(configRoot);
641
+ if (existsSync3(manifestPath)) {
642
+ try {
643
+ const content = readFileSync(manifestPath, "utf-8");
644
+ return JSON.parse(content);
645
+ } catch {
646
+ }
647
+ }
648
+ return null;
649
+ }
650
+ function readAllManifests(configRoot) {
651
+ const manifests = [];
652
+ const plugins = getAllPlugins();
653
+ const standardPath = getManifestPath(configRoot);
654
+ if (existsSync3(standardPath)) {
655
+ try {
656
+ const content = readFileSync(standardPath, "utf-8");
657
+ manifests.push(JSON.parse(content));
658
+ } catch {
659
+ }
660
+ }
661
+ for (const plugin of plugins) {
662
+ const pluginManifestPath = join3(configRoot, `${plugin.id}-manifest.json`);
663
+ if (existsSync3(pluginManifestPath)) {
664
+ try {
665
+ const content = readFileSync(pluginManifestPath, "utf-8");
666
+ manifests.push(JSON.parse(content));
667
+ } catch {
668
+ }
669
+ }
670
+ }
671
+ return manifests;
672
+ }
673
+ function scanInstalled() {
674
+ const plugins = getAllPlugins();
675
+ const installed = [];
676
+ const tools = ["opencode", "claude", "trae", "cursor", "copilot"];
677
+ const levels = ["project", "global"];
678
+ for (const tool of tools) {
679
+ for (const level of levels) {
680
+ const configRoot = getConfigRoot(tool, level);
681
+ const manifests = readAllManifests(configRoot);
682
+ for (const manifest of manifests) {
683
+ const plugin = plugins.find((p) => p.id === manifest.team);
684
+ if (!plugin) continue;
685
+ const alreadyAdded = installed.some(
686
+ (p) => p.id === plugin.id && p.tool === tool && p.level === level
687
+ );
688
+ if (alreadyAdded) continue;
689
+ installed.push({
690
+ id: plugin.id,
691
+ displayName: plugin.displayName,
692
+ tool,
693
+ level,
694
+ skillsCount: manifest.installed_skills?.length || 0,
695
+ agentsCount: manifest.installed_agents?.length || 0,
696
+ installTime: manifest.install_time,
697
+ configRoot
698
+ });
699
+ }
700
+ }
701
+ }
702
+ return installed;
703
+ }
704
+
673
705
  // src/utils/logger.ts
674
706
  import chalk from "chalk";
675
707
  import ora from "ora";
@@ -2772,7 +2804,7 @@ async function installCommand(names, options) {
2772
2804
  }
2773
2805
  let tool2;
2774
2806
  if (options.tool) {
2775
- tool2 = options.tool;
2807
+ tool2 = validateTool(options.tool);
2776
2808
  } else {
2777
2809
  const detected = await selectToolWithDetection();
2778
2810
  if (detected === "back") return;
@@ -2800,7 +2832,7 @@ async function installCommand(names, options) {
2800
2832
  const repoPath = await repoManager.ensureRepo();
2801
2833
  spinner.succeed("\u63D2\u4EF6\u6570\u636E\u52A0\u8F7D\u5B8C\u6210");
2802
2834
  logger.info(`${t("skill_install_progress")} ${chalk9.bold(names.length)} \u4E2A Skills...`);
2803
- const level2 = options.level || "project";
2835
+ const level2 = options.level ? validateLevel(options.level) : "project";
2804
2836
  const results = await installSkills(names, tool2, level2, repoPath);
2805
2837
  let successCount = 0;
2806
2838
  let failCount = 0;
@@ -2861,13 +2893,13 @@ async function installCommand(names, options) {
2861
2893
  }
2862
2894
  let tool;
2863
2895
  if (options.tool) {
2864
- tool = options.tool;
2896
+ tool = validateTool(options.tool);
2865
2897
  } else {
2866
2898
  const detected = await selectToolWithDetection();
2867
2899
  if (detected === "back") return;
2868
2900
  tool = detected;
2869
2901
  }
2870
- const level = options.level || "project";
2902
+ const level = options.level ? validateLevel(options.level) : "project";
2871
2903
  if (plugins.length > 0) {
2872
2904
  const configRoot = getConfigRoot(tool, level);
2873
2905
  const manifests = readAllManifests(configRoot);
@@ -2983,8 +3015,8 @@ async function installPlugins(pluginIds, tool, level, repoPath) {
2983
3015
  import { existsSync as existsSync13, unlinkSync as unlinkSync5, rmdirSync as rmdirSync2, readdirSync as readdirSync5, lstatSync as lstatSync4 } from "fs";
2984
3016
  import chalk10 from "chalk";
2985
3017
  async function uninstallCommand(names, options) {
2986
- const tool = options.tool || "opencode";
2987
- const level = options.level || "project";
3018
+ const tool = options.tool ? validateTool(options.tool) : "opencode";
3019
+ const level = options.level ? validateLevel(options.level) : "project";
2988
3020
  const plugins = [];
2989
3021
  const skills = [];
2990
3022
  for (const name of names) {
@@ -3098,13 +3130,13 @@ import chalk11 from "chalk";
3098
3130
  async function updateCommand(pluginNames, options) {
3099
3131
  let tool;
3100
3132
  if (options.tool) {
3101
- tool = options.tool;
3133
+ tool = validateTool(options.tool);
3102
3134
  } else {
3103
3135
  const detected = await selectToolWithDetection();
3104
3136
  if (detected === "back") return;
3105
3137
  tool = detected;
3106
3138
  }
3107
- const level = options.level || "project";
3139
+ const level = options.level ? validateLevel(options.level) : "project";
3108
3140
  let pluginsToUpdate = [];
3109
3141
  if (pluginNames.length === 0) {
3110
3142
  const configRoot = getConfigRoot(tool, level);
@@ -3263,7 +3295,7 @@ function createCLI() {
3263
3295
  setLanguage(config.language);
3264
3296
  }
3265
3297
  const program2 = new Command();
3266
- program2.name("install-helper").description("CANNBot Install Helper - Interactive installer for CANN operator development skills").version("0.0.2-beta.10");
3298
+ program2.name("install-helper").description("CANNBot Install Helper - Interactive installer for CANN operator development skills").version("0.0.2-beta.11");
3267
3299
  program2.command("init", { isDefault: false }).description("Run interactive installation wizard").action(async () => {
3268
3300
  await initCommand();
3269
3301
  });