@cannbot-ai/install-helper 1.1.8 → 1.1.9-beta.1

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
@@ -1,6 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  var __defProp = Object.defineProperty;
3
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
5
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
6
+ }) : x)(function(x) {
7
+ if (typeof require !== "undefined") return require.apply(this, arguments);
8
+ throw Error('Dynamic require of "' + x + '" is not supported');
9
+ });
4
10
  var __esm = (fn, res) => function __init() {
5
11
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
6
12
  };
@@ -164,7 +170,7 @@ var init_embedded_plugins = __esm({
164
170
  "ascendc-registry",
165
171
  "registry"
166
172
  ],
167
- skills: 29,
173
+ skills: 30,
168
174
  agents: 7,
169
175
  description: "\u751F\u4EA7\u7EA7 ACLNN \u6CE8\u518C\u7B97\u5B50\u5168\u6D41\u7A0B\uFF1A\u4EE3\u7801\u2192UT/ST\u2192\u4E0A\u5E93",
170
176
  version: "1.2.3",
@@ -217,6 +223,12 @@ var init_embedded_plugins = __esm({
217
223
  as: "ops-registry-invoke-workflow"
218
224
  }
219
225
  ]
226
+ },
227
+ {
228
+ dir: "plugins-official/ops-registry-invoke/skills",
229
+ skills: [
230
+ "spec-to-design"
231
+ ]
220
232
  }
221
233
  ],
222
234
  installAgents: [
@@ -2444,8 +2456,8 @@ init_registry();
2444
2456
 
2445
2457
  // src/core/metadata-sync.ts
2446
2458
  init_registry();
2447
- import { existsSync as existsSync9, readFileSync as readFileSync5, statSync as statSync2 } from "fs";
2448
- import { join as join8 } from "path";
2459
+ import { existsSync as existsSync9, readFileSync as readFileSync5, statSync as statSync2, readdirSync as readdirSync3 } from "fs";
2460
+ import { join as join8, sep } from "path";
2449
2461
  function readPluginJson(pluginDir) {
2450
2462
  const pjPath = join8(pluginDir, ".claude-plugin", "plugin.json");
2451
2463
  try {
@@ -2465,13 +2477,33 @@ function parseIncludedSkills(pluginDir) {
2465
2477
  return [];
2466
2478
  }
2467
2479
  }
2468
- function findSkillSourceDir(skillName, repoRoot, scanDirs) {
2480
+ function parseAllSkills(pluginDir) {
2481
+ const initPath = join8(pluginDir, "init.sh");
2482
+ try {
2483
+ const text = readFileSync5(initPath, "utf-8");
2484
+ const m = text.match(/ALL_SKILLS="([^"]*)"/);
2485
+ if (!m) return [];
2486
+ const val = m[1];
2487
+ if (val.includes("$(") || val.includes("${")) return [];
2488
+ return val.split(/\s+/).filter(Boolean);
2489
+ } catch {
2490
+ return [];
2491
+ }
2492
+ }
2493
+ function findSkillSourceDir(skillName, repoRoot, scanDirs, pluginDir) {
2469
2494
  for (const dir of scanDirs) {
2470
2495
  const candidate = join8(repoRoot, dir, skillName);
2471
2496
  if (existsSync9(candidate) && statSync2(candidate).isDirectory()) {
2472
2497
  return dir;
2473
2498
  }
2474
2499
  }
2500
+ if (pluginDir) {
2501
+ const localCandidate = join8(pluginDir, "skills", skillName);
2502
+ if (existsSync9(localCandidate) && statSync2(localCandidate).isDirectory()) {
2503
+ const relPluginDir = pluginDir.replace(repoRoot + sep, "").replace(repoRoot + "/", "");
2504
+ return `${relPluginDir}/skills`;
2505
+ }
2506
+ }
2475
2507
  return null;
2476
2508
  }
2477
2509
  function collectDeclaredSkillNames(installSkills2) {
@@ -2489,7 +2521,60 @@ function collectDeclaredSkillNames(installSkills2) {
2489
2521
  }
2490
2522
  function resolveAgentsFromPluginJson(pj) {
2491
2523
  if (!pj || !Array.isArray(pj.agents)) return [];
2492
- return pj.agents.map((a) => a.replace(/^\.\/agents\//, "").replace(/\.md$/, "")).filter(Boolean);
2524
+ return pj.agents.filter((a) => a.startsWith("./agents/")).map((a) => a.replace(/^\.\/agents\//, "").replace(/\.md$/, "")).filter(Boolean);
2525
+ }
2526
+ function parseIncludedAgentPattern(initShPath) {
2527
+ try {
2528
+ const text = readFileSync5(initShPath, "utf-8");
2529
+ const m = text.match(/INCLUDED_AGENT_PATTERN="([^"]*)"/);
2530
+ if (!m) return null;
2531
+ return m[1].trim() || null;
2532
+ } catch {
2533
+ return null;
2534
+ }
2535
+ }
2536
+ function simpleGlobToRegExp(pattern) {
2537
+ let re = "^";
2538
+ for (let i = 0; i < pattern.length; i++) {
2539
+ const c = pattern[i];
2540
+ if (c === "*") re += ".*";
2541
+ else if (c === "?") re += ".";
2542
+ else re += c.replace(/[.+^${}()|[\]\\]/g, "\\$&");
2543
+ }
2544
+ return new RegExp(re + "$");
2545
+ }
2546
+ function matchAgentsByPattern(agentsDir, pattern) {
2547
+ const filePattern = pattern.endsWith(".md") ? pattern : pattern + ".md";
2548
+ try {
2549
+ const fsSync = __require("fs");
2550
+ if (typeof fsSync.globSync === "function") {
2551
+ return fsSync.globSync(filePattern, { cwd: agentsDir }).map((f) => f.replace(/\.md$/, "").replace(/\\/g, "/"));
2552
+ }
2553
+ } catch {
2554
+ }
2555
+ if (filePattern.includes("@(") || filePattern.includes("+(") || filePattern.includes("!(")) {
2556
+ return [];
2557
+ }
2558
+ try {
2559
+ const re = simpleGlobToRegExp(filePattern);
2560
+ return readdirSync3(agentsDir).filter((f) => f.endsWith(".md") && re.test(f)).map((f) => f.replace(/\.md$/, ""));
2561
+ } catch {
2562
+ return [];
2563
+ }
2564
+ }
2565
+ function discoverAgents(pluginDir, pj, initShPath, fallbackAgents) {
2566
+ const fromPj = resolveAgentsFromPluginJson(pj);
2567
+ if (fromPj.length > 0) return fromPj;
2568
+ if (pj && Array.isArray(pj.agents) && pj.agents.length === 0) return [];
2569
+ const pattern = parseIncludedAgentPattern(initShPath);
2570
+ if (pattern) {
2571
+ const agentsDir = join8(pluginDir, "agents");
2572
+ if (existsSync9(agentsDir)) {
2573
+ const fromPattern = matchAgentsByPattern(agentsDir, pattern);
2574
+ if (fromPattern.length > 0) return fromPattern;
2575
+ }
2576
+ }
2577
+ return fallbackAgents || [];
2493
2578
  }
2494
2579
  function countSkills(installSkills2) {
2495
2580
  if (!installSkills2) return 0;
@@ -2500,12 +2585,15 @@ function countSkills(installSkills2) {
2500
2585
  function mergeInitSkills(existing, pluginDir, repoRoot, scanDirs) {
2501
2586
  const base = existing || [];
2502
2587
  const seen = collectDeclaredSkillNames(base);
2503
- const initSkills = parseIncludedSkills(pluginDir);
2588
+ let initSkills = parseIncludedSkills(pluginDir);
2589
+ if (initSkills.length === 0) {
2590
+ initSkills = parseAllSkills(pluginDir);
2591
+ }
2504
2592
  if (initSkills.length === 0) return base;
2505
2593
  const merged = base.map((s) => ({ ...s, skills: [...s.skills] }));
2506
2594
  for (const skill of initSkills) {
2507
2595
  if (seen.has(skill)) continue;
2508
- const srcDir = findSkillSourceDir(skill, repoRoot, scanDirs);
2596
+ const srcDir = findSkillSourceDir(skill, repoRoot, scanDirs, pluginDir);
2509
2597
  if (!srcDir) continue;
2510
2598
  let bucket = merged.find((b) => b.dir === srcDir);
2511
2599
  if (!bucket) {
@@ -2532,7 +2620,8 @@ function enrichPluginMetadata(repoPath) {
2532
2620
  if (pj && pj.name && plugin.displayName === plugin.id) {
2533
2621
  plugin.displayName = pj.name;
2534
2622
  }
2535
- plugin.installAgents = resolveAgentsFromPluginJson(pj);
2623
+ const initShPath = join8(pluginDir, "init.sh");
2624
+ plugin.installAgents = discoverAgents(pluginDir, pj, initShPath, plugin.installAgents);
2536
2625
  const merged = mergeInitSkills(plugin.installSkills, pluginDir, repoPath, scanDirs);
2537
2626
  plugin.installSkills = merged;
2538
2627
  plugin.skills = countSkills(merged);
@@ -2676,7 +2765,7 @@ init_fs();
2676
2765
  init_fs_helpers();
2677
2766
  init_logger();
2678
2767
  init_i18n();
2679
- import { existsSync as existsSync11, mkdirSync as mkdirSync4, readFileSync as readFileSync7, unlinkSync as unlinkSync3, readdirSync as readdirSync3 } from "fs";
2768
+ import { existsSync as existsSync11, mkdirSync as mkdirSync4, readFileSync as readFileSync7, unlinkSync as unlinkSync3, readdirSync as readdirSync4 } from "fs";
2680
2769
  import { join as join10 } from "path";
2681
2770
  function getInstallsDir() {
2682
2771
  return join10(getCannbotConfigDir(), "installs");
@@ -2876,7 +2965,7 @@ function getInstalledSkills(tool, level, installPath, allowFsScan = true) {
2876
2965
  const fromFs = [];
2877
2966
  if (existsSync11(skillsDir)) {
2878
2967
  try {
2879
- const entries = readdirSync3(skillsDir);
2968
+ const entries = readdirSync4(skillsDir);
2880
2969
  for (const entry of entries) {
2881
2970
  if (entry === "." || entry === "..") continue;
2882
2971
  const entryPath = join10(skillsDir, entry);
@@ -2906,7 +2995,7 @@ function getLastBatchSkills(tool, level, installPath) {
2906
2995
 
2907
2996
  // src/core/backup.ts
2908
2997
  init_manifest();
2909
- import { existsSync as existsSync12, copyFileSync, readdirSync as readdirSync4, unlinkSync as unlinkSync4 } from "fs";
2998
+ import { existsSync as existsSync12, copyFileSync, readdirSync as readdirSync5, unlinkSync as unlinkSync4 } from "fs";
2910
2999
  import { join as join11 } from "path";
2911
3000
  init_registry();
2912
3001
  init_paths();
@@ -2971,7 +3060,7 @@ function findBackups(configRoot) {
2971
3060
  if (!existsSync12(configRoot)) {
2972
3061
  return [];
2973
3062
  }
2974
- const files = readdirSync4(configRoot);
3063
+ const files = readdirSync5(configRoot);
2975
3064
  const backups = [];
2976
3065
  for (const file of files) {
2977
3066
  if (file.includes(".cannbot-backup.")) {
@@ -3168,7 +3257,6 @@ async function installExternalRepos(repos, repoPath, configRoot, installPath, le
3168
3257
  await execa3("git", ["pull", "--quiet"], { cwd: targetDir, timeout: 12e4 });
3169
3258
  } catch {
3170
3259
  logger.warn(t("external_repo_update_failed").replace("{dir}", repo.dir));
3171
- continue;
3172
3260
  }
3173
3261
  } else if (!existsSync13(targetDir)) {
3174
3262
  const args = ["clone"];
@@ -3569,7 +3657,7 @@ init_fs_helpers();
3569
3657
  init_constants();
3570
3658
  init_logger();
3571
3659
  init_i18n();
3572
- import { existsSync as existsSync15, mkdirSync as mkdirSync6, symlinkSync as symlinkSync2, readdirSync as readdirSync5, rmSync as rmSync4, realpathSync as realpathSync2, readlinkSync as readlinkSync2, cpSync as cpSync2 } from "fs";
3660
+ import { existsSync as existsSync15, mkdirSync as mkdirSync6, symlinkSync as symlinkSync2, readdirSync as readdirSync6, rmSync as rmSync4, realpathSync as realpathSync2, readlinkSync as readlinkSync2, cpSync as cpSync2 } from "fs";
3573
3661
  import { join as join14, dirname as dirname5, isAbsolute } from "path";
3574
3662
  import { select as select3, checkbox, Separator as Separator2 } from "@inquirer/prompts";
3575
3663
  import chalk5 from "chalk";
@@ -3669,7 +3757,7 @@ async function uninstallSkills(skillIds, tool, level) {
3669
3757
  }
3670
3758
  if (existsSync15(skillsDir)) {
3671
3759
  try {
3672
- const entries = readdirSync5(skillsDir);
3760
+ const entries = readdirSync6(skillsDir);
3673
3761
  if (entries.length === 0) {
3674
3762
  rmSync4(skillsDir, { recursive: true });
3675
3763
  logger.step(` ${t("uninstall_clean_empty_dir")}: skills/`);
@@ -4432,7 +4520,7 @@ init_manifest();
4432
4520
  init_paths();
4433
4521
  init_i18n();
4434
4522
  import chalk8 from "chalk";
4435
- import { existsSync as existsSync17, readdirSync as readdirSync6, lstatSync as lstatSync2, unlinkSync as unlinkSync5, mkdirSync as mkdirSync7 } from "fs";
4523
+ import { existsSync as existsSync17, readdirSync as readdirSync7, lstatSync as lstatSync2, unlinkSync as unlinkSync5, mkdirSync as mkdirSync7 } from "fs";
4436
4524
  import { join as join16 } from "path";
4437
4525
  async function doctorCommand(options = {}) {
4438
4526
  console.log();
@@ -4491,7 +4579,7 @@ async function doctorCommand(options = {}) {
4491
4579
  if (existsSync17(skillsDir)) {
4492
4580
  const brokenLinks = checkBrokenLinks(skillsDir);
4493
4581
  if (brokenLinks === 0) {
4494
- const count = readdirSync6(skillsDir).length;
4582
+ const count = readdirSync7(skillsDir).length;
4495
4583
  console.log(chalk8.green(" \u2713") + ` ${skillsDir} \u2014 ${t("doctor_links_valid").replace("{count}", String(count))}`);
4496
4584
  } else {
4497
4585
  console.log(chalk8.yellow(" \u26A0") + ` ${skillsDir} \u2014 ${t("doctor_broken_links").replace("{count}", String(brokenLinks))}`);
@@ -4513,7 +4601,7 @@ async function doctorCommand(options = {}) {
4513
4601
  if (existsSync17(agentsDir)) {
4514
4602
  const brokenLinks = checkBrokenLinks(agentsDir);
4515
4603
  if (brokenLinks === 0) {
4516
- const count = readdirSync6(agentsDir).length;
4604
+ const count = readdirSync7(agentsDir).length;
4517
4605
  console.log(chalk8.green(" \u2713") + ` ${agentsDir} \u2014 ${t("doctor_links_valid").replace("{count}", String(count))}`);
4518
4606
  } else {
4519
4607
  console.log(chalk8.yellow(" \u26A0") + ` ${agentsDir} \u2014 ${t("doctor_broken_links").replace("{count}", String(brokenLinks))}`);
@@ -4560,7 +4648,7 @@ async function doctorCommand(options = {}) {
4560
4648
  function checkBrokenLinks(dir) {
4561
4649
  let broken = 0;
4562
4650
  try {
4563
- const entries = readdirSync6(dir);
4651
+ const entries = readdirSync7(dir);
4564
4652
  for (const entry of entries) {
4565
4653
  const fullPath = join16(dir, entry);
4566
4654
  try {
@@ -4581,7 +4669,7 @@ function checkBrokenLinks(dir) {
4581
4669
  function fixBrokenLinks(dir) {
4582
4670
  let fixed = 0;
4583
4671
  try {
4584
- const entries = readdirSync6(dir);
4672
+ const entries = readdirSync7(dir);
4585
4673
  for (const entry of entries) {
4586
4674
  const fullPath = join16(dir, entry);
4587
4675
  try {
@@ -4968,8 +5056,8 @@ async function installPlugins(pluginIds, tool, level, repoPath, installPath, yes
4968
5056
 
4969
5057
  // src/commands/uninstall.ts
4970
5058
  init_registry();
4971
- import { existsSync as existsSync18, unlinkSync as unlinkSync6, rmdirSync, readdirSync as readdirSync7, readFileSync as readFileSync9 } from "fs";
4972
- import { resolve, basename as basename3, sep, join as join18 } from "path";
5059
+ import { existsSync as existsSync18, unlinkSync as unlinkSync6, rmdirSync, readdirSync as readdirSync8, readFileSync as readFileSync9 } from "fs";
5060
+ import { resolve, basename as basename3, sep as sep2, join as join18 } from "path";
4973
5061
  import chalk11 from "chalk";
4974
5062
  import { select as select5, checkbox as checkbox2, Separator as Separator4, confirm as confirm3 } from "@inquirer/prompts";
4975
5063
  init_config();
@@ -5290,7 +5378,7 @@ async function uninstallPluginById(pluginId, batchMode) {
5290
5378
  const allowedBases = [resolve(configRoot), resolve(record.installPath)];
5291
5379
  const isSafePath = (p) => {
5292
5380
  const resolved = resolve(p);
5293
- return allowedBases.some((base) => resolved === base || resolved.startsWith(base + sep));
5381
+ return allowedBases.some((base) => resolved === base || resolved.startsWith(base + sep2));
5294
5382
  };
5295
5383
  let removedFiles = 0;
5296
5384
  let removedDirs = 0;
@@ -5321,7 +5409,7 @@ async function uninstallPluginById(pluginId, batchMode) {
5321
5409
  continue;
5322
5410
  }
5323
5411
  if (existsSync18(dirPath)) {
5324
- const entries = readdirSync7(dirPath);
5412
+ const entries = readdirSync8(dirPath);
5325
5413
  if (entries.length === 0) {
5326
5414
  rmdirSync(dirPath);
5327
5415
  const name = basename3(dirPath);
@@ -5482,7 +5570,7 @@ async function updateCommand(pluginNames, options) {
5482
5570
  // src/commands/info.ts
5483
5571
  init_registry();
5484
5572
  import chalk13 from "chalk";
5485
- import { existsSync as existsSync19, readdirSync as readdirSync8 } from "fs";
5573
+ import { existsSync as existsSync19, readdirSync as readdirSync9 } from "fs";
5486
5574
  import { join as join19 } from "path";
5487
5575
  init_manifest();
5488
5576
  init_i18n();
@@ -5516,7 +5604,7 @@ async function infoCommand(pluginName) {
5516
5604
  }
5517
5605
  const agentsDir = join19(repoPath, plugin.dir, "agents");
5518
5606
  if (existsSync19(agentsDir)) {
5519
- const agentFiles = readdirSync8(agentsDir).filter((f) => f.endsWith(".md"));
5607
+ const agentFiles = readdirSync9(agentsDir).filter((f) => f.endsWith(".md"));
5520
5608
  if (agentFiles.length > 0) {
5521
5609
  console.log();
5522
5610
  console.log(` ${chalk13.bold("Agents:")}`);