ccski 1.1.0 → 2.1.0
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/LICENSE +21 -0
- package/README.md +51 -92
- package/dist/chunk-B7onSSqq.mjs +34 -0
- package/dist/cli.mjs +1648 -3551
- package/dist/cli.mjs.map +1 -1
- package/dist/create-prompt-CkW5qmPT.mjs +3107 -0
- package/dist/create-prompt-CkW5qmPT.mjs.map +1 -0
- package/dist/esm-X74pBEPN.mjs +47 -0
- package/dist/esm-X74pBEPN.mjs.map +1 -0
- package/dist/index.d.mts +132 -56
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/{registry-DtGaEhsM.mjs → registry-DNMfmLqa.mjs} +388 -142
- package/dist/registry-DNMfmLqa.mjs.map +1 -0
- package/package.json +18 -4
- package/dist/registry-DtGaEhsM.mjs.map +0 -1
|
@@ -1,41 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as __require, r as __toESM, t as __commonJS } from "./chunk-B7onSSqq.mjs";
|
|
2
2
|
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
3
3
|
import { TextDecoder } from "node:util";
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
|
-
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
5
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
6
6
|
import * as tty from "tty";
|
|
7
|
+
import debug from "debug";
|
|
7
8
|
|
|
8
|
-
//#region rolldown:runtime
|
|
9
|
-
var __create = Object.create;
|
|
10
|
-
var __defProp = Object.defineProperty;
|
|
11
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
14
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
15
|
-
var __commonJS = (cb, mod) => function() {
|
|
16
|
-
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
17
|
-
};
|
|
18
|
-
var __copyProps = (to, from, except, desc) => {
|
|
19
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
-
for (var keys = __getOwnPropNames(from), i$1 = 0, n = keys.length, key; i$1 < n; i$1++) {
|
|
21
|
-
key = keys[i$1];
|
|
22
|
-
if (!__hasOwnProp.call(to, key) && key !== except) {
|
|
23
|
-
__defProp(to, key, {
|
|
24
|
-
get: ((k) => from[k]).bind(null, key),
|
|
25
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return to;
|
|
31
|
-
};
|
|
32
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
33
|
-
value: mod,
|
|
34
|
-
enumerable: true
|
|
35
|
-
}) : target, mod));
|
|
36
|
-
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
37
|
-
|
|
38
|
-
//#endregion
|
|
39
9
|
//#region src/types/errors.ts
|
|
40
10
|
/**
|
|
41
11
|
* Base error class for ccski errors
|
|
@@ -62,8 +32,8 @@ var SkillNotFoundError = class extends CcskiError {
|
|
|
62
32
|
* Error thrown when a skill name is ambiguous
|
|
63
33
|
*/
|
|
64
34
|
var AmbiguousSkillNameError = class extends CcskiError {
|
|
65
|
-
constructor(skillName, matches) {
|
|
66
|
-
super(`Skill name '${skillName}' is ambiguous. Multiple skills found: ${matches.join(", ")}
|
|
35
|
+
constructor(skillName, matches, suggestions = []) {
|
|
36
|
+
super(`Skill name '${skillName}' is ambiguous. Multiple skills found: ${matches.join(", ")}`, suggestions.length ? suggestions : matches);
|
|
67
37
|
this.skillName = skillName;
|
|
68
38
|
this.matches = matches;
|
|
69
39
|
this.name = "AmbiguousSkillNameError";
|
|
@@ -3687,15 +3657,20 @@ const PluginEntrySchema = objectType({
|
|
|
3687
3657
|
lastUpdated: stringType(),
|
|
3688
3658
|
installPath: stringType(),
|
|
3689
3659
|
gitCommitSha: stringType(),
|
|
3690
|
-
isLocal: booleanType()
|
|
3691
|
-
|
|
3660
|
+
isLocal: booleanType(),
|
|
3661
|
+
scope: stringType().optional()
|
|
3662
|
+
}).passthrough();
|
|
3692
3663
|
/**
|
|
3693
3664
|
* Schema for installed_plugins.json
|
|
3694
3665
|
*/
|
|
3695
3666
|
const InstalledPluginsSchema = objectType({
|
|
3696
3667
|
version: numberType(),
|
|
3697
|
-
plugins: recordType(stringType(), PluginEntrySchema)
|
|
3668
|
+
plugins: recordType(stringType(), unionType([PluginEntrySchema, arrayType(PluginEntrySchema)]))
|
|
3698
3669
|
});
|
|
3670
|
+
/**
|
|
3671
|
+
* Schema for Claude settings.json (subset we care about)
|
|
3672
|
+
*/
|
|
3673
|
+
const ClaudeSettingsSchema = objectType({ enabledPlugins: recordType(stringType(), booleanType()).optional() }).passthrough();
|
|
3699
3674
|
|
|
3700
3675
|
//#endregion
|
|
3701
3676
|
//#region node_modules/.pnpm/kind-of@6.0.3/node_modules/kind-of/index.js
|
|
@@ -11699,9 +11674,9 @@ var require_excerpt = /* @__PURE__ */ __commonJS({ "node_modules/.pnpm/gray-matt
|
|
|
11699
11674
|
const opts = defaults$2(options);
|
|
11700
11675
|
if (file.data == null) file.data = {};
|
|
11701
11676
|
if (typeof opts.excerpt === "function") return opts.excerpt(file, opts);
|
|
11702
|
-
const sep = file.data.excerpt_separator || opts.excerpt_separator;
|
|
11703
|
-
if (sep == null && (opts.excerpt === false || opts.excerpt == null)) return file;
|
|
11704
|
-
const delimiter = typeof opts.excerpt === "string" ? opts.excerpt : sep || opts.delimiters[0];
|
|
11677
|
+
const sep$1 = file.data.excerpt_separator || opts.excerpt_separator;
|
|
11678
|
+
if (sep$1 == null && (opts.excerpt === false || opts.excerpt == null)) return file;
|
|
11679
|
+
const delimiter = typeof opts.excerpt === "string" ? opts.excerpt : sep$1 || opts.delimiters[0];
|
|
11705
11680
|
const idx = file.content.indexOf(delimiter);
|
|
11706
11681
|
if (idx !== -1) file.excerpt = file.content.slice(0, idx);
|
|
11707
11682
|
return file;
|
|
@@ -12323,9 +12298,37 @@ function error(text) {
|
|
|
12323
12298
|
function warn(text) {
|
|
12324
12299
|
return tone.warning(text);
|
|
12325
12300
|
}
|
|
12301
|
+
function info(text) {
|
|
12302
|
+
return tone.info(text);
|
|
12303
|
+
}
|
|
12326
12304
|
function heading(text) {
|
|
12327
12305
|
return tone.underline(tone.bold(tone.accent(text)));
|
|
12328
12306
|
}
|
|
12307
|
+
const SUPERSCRIPT_DIGITS = [
|
|
12308
|
+
"⁰",
|
|
12309
|
+
"¹",
|
|
12310
|
+
"²",
|
|
12311
|
+
"³",
|
|
12312
|
+
"⁴",
|
|
12313
|
+
"⁵",
|
|
12314
|
+
"⁶",
|
|
12315
|
+
"⁷",
|
|
12316
|
+
"⁸",
|
|
12317
|
+
"⁹"
|
|
12318
|
+
];
|
|
12319
|
+
function toSuperscript(num) {
|
|
12320
|
+
return num.toString().split("").map((d) => SUPERSCRIPT_DIGITS[parseInt(d, 10)] ?? d).join("");
|
|
12321
|
+
}
|
|
12322
|
+
/**
|
|
12323
|
+
* Create a duplicate badge with superscript number.
|
|
12324
|
+
* isPrimary: the chosen skill in auto mode (shows just the number)
|
|
12325
|
+
* !isPrimary: the duplicate that was filtered out (shows [dup] + number)
|
|
12326
|
+
*/
|
|
12327
|
+
function duplicateBadge(groupIndex, isPrimary) {
|
|
12328
|
+
const sup = toSuperscript(groupIndex);
|
|
12329
|
+
if (isPrimary) return tone.accent(sup);
|
|
12330
|
+
return tone.accent(`[dup]${sup}`);
|
|
12331
|
+
}
|
|
12329
12332
|
function escapeRegExp$1(value) {
|
|
12330
12333
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
12331
12334
|
}
|
|
@@ -12375,15 +12378,34 @@ function displayWidth(value) {
|
|
|
12375
12378
|
|
|
12376
12379
|
//#endregion
|
|
12377
12380
|
//#region src/core/discovery.ts
|
|
12378
|
-
|
|
12379
|
-
|
|
12380
|
-
|
|
12381
|
-
|
|
12382
|
-
|
|
12383
|
-
|
|
12384
|
-
|
|
12385
|
-
|
|
12386
|
-
|
|
12381
|
+
function getDefaultSkillDirectories(userDir) {
|
|
12382
|
+
return [
|
|
12383
|
+
{
|
|
12384
|
+
path: ".agent/skills",
|
|
12385
|
+
provider: "claude"
|
|
12386
|
+
},
|
|
12387
|
+
{
|
|
12388
|
+
path: ".claude/skills",
|
|
12389
|
+
provider: "claude"
|
|
12390
|
+
},
|
|
12391
|
+
{
|
|
12392
|
+
path: join(userDir, ".agent/skills"),
|
|
12393
|
+
provider: "claude"
|
|
12394
|
+
},
|
|
12395
|
+
{
|
|
12396
|
+
path: join(userDir, ".claude/skills"),
|
|
12397
|
+
provider: "claude"
|
|
12398
|
+
},
|
|
12399
|
+
{
|
|
12400
|
+
path: ".codex/skills",
|
|
12401
|
+
provider: "codex"
|
|
12402
|
+
},
|
|
12403
|
+
{
|
|
12404
|
+
path: join(userDir, ".codex/skills"),
|
|
12405
|
+
provider: "codex"
|
|
12406
|
+
}
|
|
12407
|
+
];
|
|
12408
|
+
}
|
|
12387
12409
|
/**
|
|
12388
12410
|
* Check if a directory has bundled resources
|
|
12389
12411
|
*/
|
|
@@ -12397,12 +12419,12 @@ function checkBundledResources(skillDir) {
|
|
|
12397
12419
|
/**
|
|
12398
12420
|
* Determine skill location type based on directory path
|
|
12399
12421
|
*/
|
|
12400
|
-
function determineLocation(dirPath) {
|
|
12422
|
+
function determineLocation(dirPath, userDir) {
|
|
12401
12423
|
const normalizedPath = resolve(dirPath);
|
|
12402
12424
|
const cwd = process.cwd();
|
|
12403
|
-
const home =
|
|
12404
|
-
if (normalizedPath.startsWith(join(cwd, ".agent")) || normalizedPath.startsWith(join(cwd, ".claude"))) return "project";
|
|
12405
|
-
if (normalizedPath.startsWith(join(home, ".agent")) || normalizedPath.startsWith(join(home, ".claude"))) return "user";
|
|
12425
|
+
const home = userDir;
|
|
12426
|
+
if (normalizedPath.startsWith(join(cwd, ".agent")) || normalizedPath.startsWith(join(cwd, ".claude")) || normalizedPath.startsWith(join(cwd, ".codex"))) return "project";
|
|
12427
|
+
if (normalizedPath.startsWith(join(home, ".agent")) || normalizedPath.startsWith(join(home, ".claude")) || normalizedPath.startsWith(join(home, ".codex"))) return "user";
|
|
12406
12428
|
return "user";
|
|
12407
12429
|
}
|
|
12408
12430
|
function collectSkillDirectories(root, recursive, diagnostics, accumulator, includeDisabled) {
|
|
@@ -12428,7 +12450,7 @@ function collectSkillDirectories(root, recursive, diagnostics, accumulator, incl
|
|
|
12428
12450
|
/**
|
|
12429
12451
|
* Scan a single skill directory and return found skills
|
|
12430
12452
|
*/
|
|
12431
|
-
function scanSkillDirectory(dirPath, { location, recursive = true, diagnostics, includeDisabled = false }) {
|
|
12453
|
+
function scanSkillDirectory(dirPath, { location, recursive = true, diagnostics, includeDisabled = false }, provider, userDir = homedir(), scope) {
|
|
12432
12454
|
const skills = [];
|
|
12433
12455
|
const skillDirectories = /* @__PURE__ */ new Set();
|
|
12434
12456
|
collectSkillDirectories(dirPath, recursive, diagnostics, skillDirectories, includeDisabled);
|
|
@@ -12450,16 +12472,20 @@ function scanSkillDirectory(dirPath, { location, recursive = true, diagnostics,
|
|
|
12450
12472
|
if (candidates.length === 0) continue;
|
|
12451
12473
|
for (const candidate of candidates) try {
|
|
12452
12474
|
const parsed = parseSkillFile(candidate.path);
|
|
12475
|
+
const baseName = parsed.frontmatter.name;
|
|
12476
|
+
const scopedName = scope && !baseName.includes(":") ? `${scope}:${baseName}` : baseName;
|
|
12453
12477
|
const resources = checkBundledResources(skillDir);
|
|
12454
|
-
const skillLocation = location ?? determineLocation(skillDir);
|
|
12478
|
+
const skillLocation = location ?? determineLocation(skillDir, userDir);
|
|
12455
12479
|
skills.push({
|
|
12456
|
-
name:
|
|
12480
|
+
name: scopedName,
|
|
12457
12481
|
description: parsed.frontmatter.description,
|
|
12482
|
+
provider,
|
|
12458
12483
|
location: skillLocation,
|
|
12459
12484
|
path: skillDir,
|
|
12460
12485
|
disabled: candidate.disabled,
|
|
12461
12486
|
...resources
|
|
12462
12487
|
});
|
|
12488
|
+
diagnostics.byProvider[provider] = (diagnostics.byProvider[provider] ?? 0) + 1;
|
|
12463
12489
|
} catch (error$1) {
|
|
12464
12490
|
console.warn(colors.yellow(`Warning: Failed to parse ${candidate.path}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`));
|
|
12465
12491
|
diagnostics.warnings.push(`Failed to parse ${candidate.path}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`);
|
|
@@ -12474,26 +12500,46 @@ function discoverSkills(options = {}) {
|
|
|
12474
12500
|
const diagnostics = {
|
|
12475
12501
|
scannedDirectories: [],
|
|
12476
12502
|
warnings: [],
|
|
12477
|
-
conflicts: []
|
|
12503
|
+
conflicts: [],
|
|
12504
|
+
byProvider: {
|
|
12505
|
+
claude: 0,
|
|
12506
|
+
codex: 0,
|
|
12507
|
+
file: 0
|
|
12508
|
+
}
|
|
12478
12509
|
};
|
|
12510
|
+
const userDir = options.userDir ? resolve(options.userDir) : homedir();
|
|
12479
12511
|
const directories = [];
|
|
12480
|
-
if (options.customDirs?.length)
|
|
12481
|
-
|
|
12482
|
-
|
|
12483
|
-
|
|
12484
|
-
|
|
12512
|
+
if (options.customDirs?.length) for (const entry of options.customDirs) {
|
|
12513
|
+
const provider = options.customProvider ?? "file";
|
|
12514
|
+
if (typeof entry === "string") directories.push({
|
|
12515
|
+
path: entry,
|
|
12516
|
+
provider,
|
|
12517
|
+
scope: provider === "file" ? "other" : void 0
|
|
12518
|
+
});
|
|
12519
|
+
else directories.push({
|
|
12520
|
+
path: entry.path,
|
|
12521
|
+
provider,
|
|
12522
|
+
scope: entry.scope ?? (provider === "file" ? "other" : void 0)
|
|
12523
|
+
});
|
|
12524
|
+
}
|
|
12525
|
+
if (options.scanDefaultDirs !== false) directories.push(...getDefaultSkillDirectories(userDir));
|
|
12526
|
+
const skills = [];
|
|
12527
|
+
const firstPathByName = /* @__PURE__ */ new Map();
|
|
12528
|
+
for (const entry of directories) {
|
|
12529
|
+
const { path: dir, provider, scope } = entry;
|
|
12530
|
+
const skillsFromDir = scanSkillDirectory(dir.startsWith("/") ? dir : resolve(process.cwd(), dir), {
|
|
12485
12531
|
diagnostics,
|
|
12486
12532
|
recursive: true,
|
|
12487
12533
|
includeDisabled: options.includeDisabled === true
|
|
12488
|
-
});
|
|
12489
|
-
for (const skill of
|
|
12490
|
-
|
|
12491
|
-
|
|
12492
|
-
|
|
12534
|
+
}, provider, userDir, scope);
|
|
12535
|
+
for (const skill of skillsFromDir) {
|
|
12536
|
+
if (firstPathByName.has(skill.name)) diagnostics.conflicts.push(`Duplicate skill '${skill.name}' found at ${skill.path} (first seen at ${firstPathByName.get(skill.name)})`);
|
|
12537
|
+
else firstPathByName.set(skill.name, skill.path);
|
|
12538
|
+
skills.push(skill);
|
|
12493
12539
|
}
|
|
12494
12540
|
}
|
|
12495
12541
|
return {
|
|
12496
|
-
skills
|
|
12542
|
+
skills,
|
|
12497
12543
|
diagnostics
|
|
12498
12544
|
};
|
|
12499
12545
|
}
|
|
@@ -12511,15 +12557,52 @@ function loadSkill(metadata) {
|
|
|
12511
12557
|
|
|
12512
12558
|
//#endregion
|
|
12513
12559
|
//#region src/core/plugins.ts
|
|
12514
|
-
|
|
12515
|
-
|
|
12560
|
+
function defaultPluginsFile(userDir) {
|
|
12561
|
+
return join(userDir, ".claude/plugins/installed_plugins.json");
|
|
12562
|
+
}
|
|
12563
|
+
function defaultPluginsRoot(userDir) {
|
|
12564
|
+
return join(userDir, ".claude/plugins");
|
|
12565
|
+
}
|
|
12566
|
+
function defaultSettingsFile(userDir) {
|
|
12567
|
+
return join(userDir, ".claude/settings.json");
|
|
12568
|
+
}
|
|
12516
12569
|
function resolveInstallPath(rawPath, pluginsRoot) {
|
|
12517
12570
|
return isAbsolute(rawPath) ? rawPath : join(pluginsRoot, rawPath);
|
|
12518
12571
|
}
|
|
12572
|
+
function normalizePluginEntries(entry) {
|
|
12573
|
+
return Array.isArray(entry) ? entry : [entry];
|
|
12574
|
+
}
|
|
12575
|
+
function loadClaudeSettings(settingsFile, diagnostics) {
|
|
12576
|
+
if (!existsSync(settingsFile)) {
|
|
12577
|
+
diagnostics?.warnings.push(`Settings file not found at ${settingsFile}`);
|
|
12578
|
+
return null;
|
|
12579
|
+
}
|
|
12580
|
+
try {
|
|
12581
|
+
const content = readFileSync(settingsFile, "utf-8");
|
|
12582
|
+
const json = JSON.parse(content);
|
|
12583
|
+
const validation = ClaudeSettingsSchema.safeParse(json);
|
|
12584
|
+
if (!validation.success) {
|
|
12585
|
+
console.warn(colors.yellow(`Warning: Invalid settings.json format:`), validation.error);
|
|
12586
|
+
diagnostics?.warnings.push("Invalid settings.json format");
|
|
12587
|
+
return null;
|
|
12588
|
+
}
|
|
12589
|
+
return validation.data;
|
|
12590
|
+
} catch (error$1) {
|
|
12591
|
+
console.warn(colors.yellow(`Warning: Failed to load settings.json:`), error$1);
|
|
12592
|
+
diagnostics?.warnings.push(`Failed to load settings.json: ${error$1 instanceof Error ? error$1.message : String(error$1)}`);
|
|
12593
|
+
return null;
|
|
12594
|
+
}
|
|
12595
|
+
}
|
|
12596
|
+
function resolveEnabledPlugins(settings) {
|
|
12597
|
+
const enabledPlugins = settings?.enabledPlugins;
|
|
12598
|
+
if (!enabledPlugins) return null;
|
|
12599
|
+
const enabled = Object.entries(enabledPlugins).filter(([, isEnabled]) => isEnabled).map(([pluginKey]) => pluginKey);
|
|
12600
|
+
return new Set(enabled);
|
|
12601
|
+
}
|
|
12519
12602
|
/**
|
|
12520
12603
|
* Parse installed_plugins.json
|
|
12521
12604
|
*/
|
|
12522
|
-
function loadInstalledPlugins(pluginsFile
|
|
12605
|
+
function loadInstalledPlugins(pluginsFile, diagnostics) {
|
|
12523
12606
|
if (!existsSync(pluginsFile)) {
|
|
12524
12607
|
console.info(`[ccski] No plugin marketplace skills found at ${pluginsFile}`);
|
|
12525
12608
|
diagnostics?.warnings.push(`Plugins file not found at ${pluginsFile}`);
|
|
@@ -12564,31 +12647,104 @@ function findSkillFiles(dir, diagnostics) {
|
|
|
12564
12647
|
* Discover skills from installed plugins
|
|
12565
12648
|
*/
|
|
12566
12649
|
function discoverPluginSkills(options = {}) {
|
|
12650
|
+
const log = debug("ccski:plugins");
|
|
12567
12651
|
const diagnostics = {
|
|
12568
12652
|
scannedPlugins: [],
|
|
12569
12653
|
warnings: []
|
|
12570
12654
|
};
|
|
12571
|
-
const
|
|
12655
|
+
const userDir = options.userDir ? resolve(options.userDir) : homedir();
|
|
12656
|
+
const pluginsFile = options.pluginsFile ?? defaultPluginsFile(userDir);
|
|
12572
12657
|
diagnostics.scannedPlugins.push(pluginsFile);
|
|
12573
|
-
const
|
|
12574
|
-
if (!plugins) return {
|
|
12575
|
-
skills: [],
|
|
12576
|
-
diagnostics
|
|
12577
|
-
};
|
|
12658
|
+
const settingsFile = options.settingsFile ?? defaultSettingsFile(userDir);
|
|
12578
12659
|
const skills = [];
|
|
12579
|
-
const
|
|
12580
|
-
|
|
12660
|
+
const seenPaths = /* @__PURE__ */ new Set();
|
|
12661
|
+
const pluginsRoot = options.pluginsRoot ?? defaultPluginsRoot(userDir);
|
|
12662
|
+
let missingOrEmpty = false;
|
|
12663
|
+
const plugins = loadInstalledPlugins(pluginsFile, diagnostics);
|
|
12664
|
+
const enabledPlugins = resolveEnabledPlugins(loadClaudeSettings(settingsFile, diagnostics));
|
|
12665
|
+
log("plugins file=%s loaded=%s", pluginsFile, Boolean(plugins));
|
|
12666
|
+
log("settings file=%s enabledPlugins=%s", settingsFile, enabledPlugins?.size ?? "all");
|
|
12667
|
+
if (plugins) for (const [pluginKey, plugin] of Object.entries(plugins.plugins)) {
|
|
12668
|
+
if (enabledPlugins && !enabledPlugins.has(pluginKey)) {
|
|
12669
|
+
log("plugin %s disabled by settings", pluginKey);
|
|
12670
|
+
continue;
|
|
12671
|
+
}
|
|
12581
12672
|
const [pluginName, marketplace] = pluginKey.split("@");
|
|
12582
12673
|
if (!pluginName || !marketplace) continue;
|
|
12583
|
-
const
|
|
12584
|
-
const
|
|
12585
|
-
|
|
12674
|
+
const entries = normalizePluginEntries(plugin);
|
|
12675
|
+
for (const entry of entries) {
|
|
12676
|
+
const installPath = resolveInstallPath(entry.installPath, pluginsRoot);
|
|
12677
|
+
const skillFiles = findSkillFiles(installPath, diagnostics);
|
|
12678
|
+
if (!skillFiles.length) {
|
|
12679
|
+
if (!existsSync(installPath)) {
|
|
12680
|
+
diagnostics.warnings.push(`Plugin install path not found: ${installPath}`);
|
|
12681
|
+
log("missing installPath: %s", installPath);
|
|
12682
|
+
} else {
|
|
12683
|
+
diagnostics.warnings.push(`No skills found in plugin install path: ${installPath}`);
|
|
12684
|
+
log("empty installPath: %s", installPath);
|
|
12685
|
+
}
|
|
12686
|
+
missingOrEmpty = true;
|
|
12687
|
+
}
|
|
12688
|
+
diagnostics.scannedPlugins.push(installPath);
|
|
12689
|
+
log("scanned manifest plugin=%s skills=%d", pluginName, skillFiles.length);
|
|
12690
|
+
for (const skillFile of skillFiles) try {
|
|
12691
|
+
const parsed = parseSkillFile(skillFile);
|
|
12692
|
+
const skillDir = dirname(skillFile);
|
|
12693
|
+
if (seenPaths.has(skillDir)) continue;
|
|
12694
|
+
const skillName = parsed.frontmatter.name;
|
|
12695
|
+
const namespaced = skillName.includes(":") ? skillName : pluginName === skillName ? skillName : `${pluginName}:${skillName}`;
|
|
12696
|
+
skills.push({
|
|
12697
|
+
name: namespaced,
|
|
12698
|
+
description: parsed.frontmatter.description,
|
|
12699
|
+
provider: "claude",
|
|
12700
|
+
location: "plugin",
|
|
12701
|
+
path: skillDir,
|
|
12702
|
+
hasReferences: existsSync(join(skillDir, "references")),
|
|
12703
|
+
hasScripts: existsSync(join(skillDir, "scripts")),
|
|
12704
|
+
hasAssets: existsSync(join(skillDir, "assets")),
|
|
12705
|
+
pluginInfo: {
|
|
12706
|
+
pluginName,
|
|
12707
|
+
marketplace,
|
|
12708
|
+
version: entry.version
|
|
12709
|
+
}
|
|
12710
|
+
});
|
|
12711
|
+
seenPaths.add(skillDir);
|
|
12712
|
+
} catch (error$1) {
|
|
12713
|
+
console.warn(colors.yellow(`Warning: Failed to parse plugin skill ${skillFile}:`), error$1);
|
|
12714
|
+
diagnostics.warnings.push(`Failed to parse plugin skill ${skillFile}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`);
|
|
12715
|
+
}
|
|
12716
|
+
}
|
|
12717
|
+
}
|
|
12718
|
+
if (!(process.env.CCSKI_CLAUDE_PLUGINS_FALLBACK === "true")) {
|
|
12719
|
+
log("fallback scan skipped (CCSKI_CLAUDE_PLUGINS_FALLBACK!=true)");
|
|
12720
|
+
return {
|
|
12721
|
+
skills,
|
|
12722
|
+
diagnostics
|
|
12723
|
+
};
|
|
12724
|
+
}
|
|
12725
|
+
if (enabledPlugins) {
|
|
12726
|
+
log("fallback scan skipped (enabledPlugins present)");
|
|
12727
|
+
return {
|
|
12728
|
+
skills,
|
|
12729
|
+
diagnostics
|
|
12730
|
+
};
|
|
12731
|
+
}
|
|
12732
|
+
if (!plugins || skills.length === 0 || missingOrEmpty) {
|
|
12733
|
+
const fallbackRoot = join(pluginsRoot, "skills");
|
|
12734
|
+
diagnostics.scannedPlugins.push(fallbackRoot);
|
|
12735
|
+
log("running fallback scan at %s", fallbackRoot);
|
|
12736
|
+
const skillFiles = findSkillFiles(fallbackRoot, diagnostics);
|
|
12586
12737
|
for (const skillFile of skillFiles) try {
|
|
12587
12738
|
const parsed = parseSkillFile(skillFile);
|
|
12588
12739
|
const skillDir = dirname(skillFile);
|
|
12740
|
+
if (seenPaths.has(skillDir)) continue;
|
|
12741
|
+
const pluginName = relative(fallbackRoot, skillDir).split(sep).filter(Boolean)[0] ?? "local";
|
|
12742
|
+
const skillName = parsed.frontmatter.name;
|
|
12743
|
+
const namespaced = skillName.includes(":") ? skillName : pluginName === skillName ? skillName : `${pluginName}:${skillName}`;
|
|
12589
12744
|
skills.push({
|
|
12590
|
-
name:
|
|
12745
|
+
name: namespaced,
|
|
12591
12746
|
description: parsed.frontmatter.description,
|
|
12747
|
+
provider: "claude",
|
|
12592
12748
|
location: "plugin",
|
|
12593
12749
|
path: skillDir,
|
|
12594
12750
|
hasReferences: existsSync(join(skillDir, "references")),
|
|
@@ -12596,10 +12752,12 @@ function discoverPluginSkills(options = {}) {
|
|
|
12596
12752
|
hasAssets: existsSync(join(skillDir, "assets")),
|
|
12597
12753
|
pluginInfo: {
|
|
12598
12754
|
pluginName,
|
|
12599
|
-
marketplace,
|
|
12600
|
-
version:
|
|
12755
|
+
marketplace: "local",
|
|
12756
|
+
version: "unknown"
|
|
12601
12757
|
}
|
|
12602
12758
|
});
|
|
12759
|
+
seenPaths.add(skillDir);
|
|
12760
|
+
log("fallback skill added %s (%s)", namespaced, skillDir);
|
|
12603
12761
|
} catch (error$1) {
|
|
12604
12762
|
console.warn(colors.yellow(`Warning: Failed to parse plugin skill ${skillFile}:`), error$1);
|
|
12605
12763
|
diagnostics.warnings.push(`Failed to parse plugin skill ${skillFile}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`);
|
|
@@ -12657,8 +12815,8 @@ var require_uFuzzy = /* @__PURE__ */ __commonJS({ "node_modules/.pnpm/@leeoniya+
|
|
|
12657
12815
|
toUpper: (str) => str.toLocaleUpperCase(),
|
|
12658
12816
|
toLower: (str) => str.toLocaleLowerCase(),
|
|
12659
12817
|
compare: null,
|
|
12660
|
-
sort: (info, haystack, needle, compare = cmp) => {
|
|
12661
|
-
let { idx, chars, terms, interLft2, interLft1, start, intraIns, interIns, cases } = info;
|
|
12818
|
+
sort: (info$1, haystack, needle, compare = cmp) => {
|
|
12819
|
+
let { idx, chars, terms, interLft2, interLft1, start, intraIns, interIns, cases } = info$1;
|
|
12662
12820
|
return idx.map((v, i$1) => i$1).sort((ia, ib) => chars[ib] - chars[ia] || intraIns[ia] - intraIns[ib] || terms[ib] + interLft2[ib] + .5 * interLft1[ib] - (terms[ia] + interLft2[ia] + .5 * interLft1[ia]) || interIns[ia] - interIns[ib] || start[ia] - start[ib] || cases[ib] - cases[ia] || compare(haystack[idx[ia]], haystack[idx[ib]]));
|
|
12663
12821
|
}
|
|
12664
12822
|
};
|
|
@@ -12806,7 +12964,7 @@ var require_uFuzzy = /* @__PURE__ */ __commonJS({ "node_modules/.pnpm/@leeoniya+
|
|
|
12806
12964
|
let withIntraBound = !!_intraBound;
|
|
12807
12965
|
let interBound = new RegExp(_interBound, uFlag);
|
|
12808
12966
|
let intraBound = new RegExp(_intraBound, uFlag);
|
|
12809
|
-
const info = (idxs, haystack, needle) => {
|
|
12967
|
+
const info$1 = (idxs, haystack, needle) => {
|
|
12810
12968
|
let [query, parts, contrs] = prepQuery(needle, 1);
|
|
12811
12969
|
let partsCased = split(needle, true);
|
|
12812
12970
|
let [queryR] = prepQuery(needle, 2);
|
|
@@ -12823,7 +12981,7 @@ var require_uFuzzy = /* @__PURE__ */ __commonJS({ "node_modules/.pnpm/@leeoniya+
|
|
|
12823
12981
|
}
|
|
12824
12982
|
let len = idxs.length;
|
|
12825
12983
|
let field = Array(len).fill(0);
|
|
12826
|
-
let info$
|
|
12984
|
+
let info$2 = {
|
|
12827
12985
|
idx: Array(len),
|
|
12828
12986
|
start: field.slice(),
|
|
12829
12987
|
chars: field.slice(),
|
|
@@ -12958,17 +13116,17 @@ var require_uFuzzy = /* @__PURE__ */ __commonJS({ "node_modules/.pnpm/@leeoniya+
|
|
|
12958
13116
|
if (j < partsLen - 1) idxAcc += groupLen + m[k + 1].length;
|
|
12959
13117
|
}
|
|
12960
13118
|
if (!disc) {
|
|
12961
|
-
info$
|
|
12962
|
-
info$
|
|
12963
|
-
info$
|
|
12964
|
-
info$
|
|
12965
|
-
info$
|
|
12966
|
-
info$
|
|
12967
|
-
info$
|
|
12968
|
-
info$
|
|
12969
|
-
info$
|
|
12970
|
-
info$
|
|
12971
|
-
info$
|
|
13119
|
+
info$2.idx[ii] = idxs[i$1];
|
|
13120
|
+
info$2.interLft2[ii] = lft2;
|
|
13121
|
+
info$2.interLft1[ii] = lft1;
|
|
13122
|
+
info$2.interRgt2[ii] = rgt2;
|
|
13123
|
+
info$2.interRgt1[ii] = rgt1;
|
|
13124
|
+
info$2.chars[ii] = chars;
|
|
13125
|
+
info$2.terms[ii] = terms;
|
|
13126
|
+
info$2.cases[ii] = cases;
|
|
13127
|
+
info$2.interIns[ii] = inter;
|
|
13128
|
+
info$2.intraIns[ii] = intra;
|
|
13129
|
+
info$2.start[ii] = start;
|
|
12972
13130
|
let m$1 = mhstr.match(queryR);
|
|
12973
13131
|
let idxAcc$1 = m$1.index + m$1[1].length;
|
|
12974
13132
|
let refLen = refine.length;
|
|
@@ -12995,7 +13153,7 @@ var require_uFuzzy = /* @__PURE__ */ __commonJS({ "node_modules/.pnpm/@leeoniya+
|
|
|
12995
13153
|
}
|
|
12996
13154
|
}
|
|
12997
13155
|
idxAcc$1 = m$1.index + m$1[1].length;
|
|
12998
|
-
let ranges = info$
|
|
13156
|
+
let ranges = info$2.ranges[ii] = [];
|
|
12999
13157
|
let from = idxAcc$1;
|
|
13000
13158
|
let to = idxAcc$1;
|
|
13001
13159
|
for (let i$2 = 2; i$2 < m$1.length; i$2++) {
|
|
@@ -13011,8 +13169,8 @@ var require_uFuzzy = /* @__PURE__ */ __commonJS({ "node_modules/.pnpm/@leeoniya+
|
|
|
13011
13169
|
ii++;
|
|
13012
13170
|
}
|
|
13013
13171
|
}
|
|
13014
|
-
if (ii < idxs.length) for (let k in info$
|
|
13015
|
-
return info$
|
|
13172
|
+
if (ii < idxs.length) for (let k in info$2) info$2[k] = info$2[k].slice(0, ii);
|
|
13173
|
+
return info$2;
|
|
13016
13174
|
};
|
|
13017
13175
|
const refineMatch = (m, k, idxInNext, termLen) => {
|
|
13018
13176
|
let prepend = m[k] + m[k + 1].slice(0, idxInNext);
|
|
@@ -13093,7 +13251,7 @@ var require_uFuzzy = /* @__PURE__ */ __commonJS({ "node_modules/.pnpm/@leeoniya+
|
|
|
13093
13251
|
let idxs = matches[ni];
|
|
13094
13252
|
if (idxs == null || idxs.length == 0) continue;
|
|
13095
13253
|
let needle$1 = needles[ni];
|
|
13096
|
-
let _info = info(idxs, haystack, needle$1);
|
|
13254
|
+
let _info = info$1(idxs, haystack, needle$1);
|
|
13097
13255
|
let order = opts.sort(_info, haystack, needle$1, compare);
|
|
13098
13256
|
if (ni > 0) for (let i$1 = 0; i$1 < order.length; i$1++) order[i$1] += retOrder.length;
|
|
13099
13257
|
for (let k in _info) retInfo[k] = (retInfo[k] ?? []).concat(_info[k]);
|
|
@@ -13112,7 +13270,7 @@ var require_uFuzzy = /* @__PURE__ */ __commonJS({ "node_modules/.pnpm/@leeoniya+
|
|
|
13112
13270
|
},
|
|
13113
13271
|
split,
|
|
13114
13272
|
filter,
|
|
13115
|
-
info,
|
|
13273
|
+
info: info$1,
|
|
13116
13274
|
sort: opts.sort
|
|
13117
13275
|
};
|
|
13118
13276
|
}
|
|
@@ -13217,18 +13375,85 @@ function containsCaseInsensitive(haystack, needle) {
|
|
|
13217
13375
|
return haystack.toLowerCase().includes(needle.toLowerCase());
|
|
13218
13376
|
}
|
|
13219
13377
|
|
|
13378
|
+
//#endregion
|
|
13379
|
+
//#region src/utils/skill-id.ts
|
|
13380
|
+
function stripPluginPrefix(name, pluginName) {
|
|
13381
|
+
const prefix = `${pluginName}:`;
|
|
13382
|
+
return name.startsWith(prefix) ? name.slice(prefix.length) : name;
|
|
13383
|
+
}
|
|
13384
|
+
const defaultFormatOptions = {
|
|
13385
|
+
includeProvider: true,
|
|
13386
|
+
color: true
|
|
13387
|
+
};
|
|
13388
|
+
/**
|
|
13389
|
+
* Build a copy/paste friendly skill id that includes provider and plugin (when present).
|
|
13390
|
+
* Format: provider:@plugin:name or provider:name
|
|
13391
|
+
*/
|
|
13392
|
+
function formatSkillId(skill, opts) {
|
|
13393
|
+
const { includeProvider } = {
|
|
13394
|
+
...defaultFormatOptions,
|
|
13395
|
+
...opts
|
|
13396
|
+
};
|
|
13397
|
+
if (skill.pluginInfo) {
|
|
13398
|
+
const base = stripPluginPrefix(skill.name, skill.pluginInfo.pluginName);
|
|
13399
|
+
const id = `@${skill.pluginInfo.pluginName}:${base}`;
|
|
13400
|
+
return includeProvider ? `${skill.provider}:${id}` : id;
|
|
13401
|
+
}
|
|
13402
|
+
return includeProvider ? `${skill.provider}:${skill.name}` : skill.name;
|
|
13403
|
+
}
|
|
13404
|
+
/**
|
|
13405
|
+
* Return a set of aliases (lowercased) that should match user input, including plugin-qualified variants.
|
|
13406
|
+
*/
|
|
13407
|
+
function skillAliases(skill) {
|
|
13408
|
+
const aliases = /* @__PURE__ */ new Set();
|
|
13409
|
+
aliases.add(skill.name.toLowerCase());
|
|
13410
|
+
const short = skill.name.toLowerCase().split(":").pop() ?? skill.name.toLowerCase();
|
|
13411
|
+
aliases.add(short);
|
|
13412
|
+
if (skill.pluginInfo) {
|
|
13413
|
+
const plugin = skill.pluginInfo.pluginName.toLowerCase();
|
|
13414
|
+
const base = stripPluginPrefix(skill.name.toLowerCase(), plugin);
|
|
13415
|
+
aliases.add(`${plugin}:${base}`);
|
|
13416
|
+
aliases.add(`@${plugin}:${base}`);
|
|
13417
|
+
aliases.add(`${skill.provider}:${plugin}:${base}`);
|
|
13418
|
+
aliases.add(`${skill.provider}:@${plugin}:${base}`);
|
|
13419
|
+
}
|
|
13420
|
+
return Array.from(aliases);
|
|
13421
|
+
}
|
|
13422
|
+
/**
|
|
13423
|
+
* Render a human-friendly label with colors, highlighting provider/plugin/name components.
|
|
13424
|
+
* Default includes provider to stay copy/pasteable; set includeProvider=false when a provider badge already exists.
|
|
13425
|
+
*/
|
|
13426
|
+
function formatSkillLabel(skill, opts) {
|
|
13427
|
+
const { includeProvider, color, providerColor } = {
|
|
13428
|
+
...defaultFormatOptions,
|
|
13429
|
+
...opts
|
|
13430
|
+
};
|
|
13431
|
+
const useColor = color !== false;
|
|
13432
|
+
const providerPart = includeProvider ? `${skill.provider}:` : "";
|
|
13433
|
+
const pluginPart = skill.pluginInfo ? `@${skill.pluginInfo.pluginName}:` : "";
|
|
13434
|
+
const baseName = skill.pluginInfo ? stripPluginPrefix(skill.name, skill.pluginInfo.pluginName) : skill.name;
|
|
13435
|
+
if (!useColor) return `${providerPart}${pluginPart}${baseName}`;
|
|
13436
|
+
const defaultProviderColor = skill.provider === "claude" ? colors.green : skill.provider === "codex" ? colors.cyan : dim;
|
|
13437
|
+
const green$1 = (providerColor ?? defaultProviderColor)(providerPart.replace(/:$/, ""));
|
|
13438
|
+
const blue$1 = colors.blue(baseName);
|
|
13439
|
+
const pluginColored = pluginPart ? dim(pluginPart) : "";
|
|
13440
|
+
return `${includeProvider ? `${green$1}:` : ""}${pluginColored}${blue$1}`;
|
|
13441
|
+
}
|
|
13442
|
+
|
|
13220
13443
|
//#endregion
|
|
13221
13444
|
//#region src/core/registry.ts
|
|
13222
13445
|
/**
|
|
13223
13446
|
* Skill registry for managing discovered skills
|
|
13224
13447
|
*/
|
|
13225
13448
|
var SkillRegistry = class {
|
|
13226
|
-
skills =
|
|
13449
|
+
skills = [];
|
|
13227
13450
|
diagnostics = {
|
|
13228
13451
|
directoriesScanned: [],
|
|
13229
13452
|
pluginSources: [],
|
|
13230
13453
|
warnings: [],
|
|
13231
|
-
conflicts: []
|
|
13454
|
+
conflicts: [],
|
|
13455
|
+
byProvider: {},
|
|
13456
|
+
byLocation: {}
|
|
13232
13457
|
};
|
|
13233
13458
|
constructor(options = {}) {
|
|
13234
13459
|
this.options = options;
|
|
@@ -13238,56 +13463,75 @@ var SkillRegistry = class {
|
|
|
13238
13463
|
* Refresh the skill registry by rescanning directories
|
|
13239
13464
|
*/
|
|
13240
13465
|
refresh() {
|
|
13241
|
-
this.skills
|
|
13466
|
+
this.skills = [];
|
|
13242
13467
|
this.diagnostics = {
|
|
13243
13468
|
directoriesScanned: [],
|
|
13244
13469
|
pluginSources: [],
|
|
13245
13470
|
warnings: [],
|
|
13246
|
-
conflicts: []
|
|
13471
|
+
conflicts: [],
|
|
13472
|
+
byProvider: {},
|
|
13473
|
+
byLocation: {}
|
|
13247
13474
|
};
|
|
13248
13475
|
const discovered = discoverSkills(this.options);
|
|
13249
13476
|
this.diagnostics.directoriesScanned.push(...discovered.diagnostics.scannedDirectories);
|
|
13250
13477
|
this.diagnostics.warnings.push(...discovered.diagnostics.warnings);
|
|
13251
13478
|
this.diagnostics.conflicts.push(...discovered.diagnostics.conflicts);
|
|
13252
|
-
for (const skill of discovered.skills)
|
|
13479
|
+
for (const skill of discovered.skills) {
|
|
13480
|
+
this.skills.push(skill);
|
|
13481
|
+
this.diagnostics.byProvider[skill.provider] = (this.diagnostics.byProvider[skill.provider] ?? 0) + 1;
|
|
13482
|
+
this.diagnostics.byLocation[skill.location] = (this.diagnostics.byLocation[skill.location] ?? 0) + 1;
|
|
13483
|
+
}
|
|
13253
13484
|
if (!this.options.skipPlugins) {
|
|
13254
13485
|
const pluginOptions = {};
|
|
13255
13486
|
if (this.options.pluginsFile) pluginOptions.pluginsFile = this.options.pluginsFile;
|
|
13256
13487
|
if (this.options.pluginsRoot) pluginOptions.pluginsRoot = this.options.pluginsRoot;
|
|
13488
|
+
if (this.options.userDir) pluginOptions.userDir = this.options.userDir;
|
|
13257
13489
|
const pluginSkills = discoverPluginSkills(pluginOptions);
|
|
13258
13490
|
this.diagnostics.pluginSources.push(...pluginSkills.diagnostics.scannedPlugins);
|
|
13259
13491
|
this.diagnostics.warnings.push(...pluginSkills.diagnostics.warnings);
|
|
13260
|
-
for (const skill of pluginSkills.skills)
|
|
13261
|
-
|
|
13492
|
+
for (const skill of pluginSkills.skills) {
|
|
13493
|
+
if (this.skills.some((existing) => existing.name.toLowerCase() === skill.name.toLowerCase() && existing.location !== "plugin")) this.diagnostics.conflicts.push(`Duplicate skill ${skill.name} from plugin at ${skill.path}; keeping for filter-stage resolution.`);
|
|
13494
|
+
this.skills.push(skill);
|
|
13495
|
+
this.diagnostics.byProvider[skill.provider] = (this.diagnostics.byProvider[skill.provider] ?? 0) + 1;
|
|
13496
|
+
this.diagnostics.byLocation[skill.location] = (this.diagnostics.byLocation[skill.location] ?? 0) + 1;
|
|
13497
|
+
}
|
|
13262
13498
|
}
|
|
13263
13499
|
}
|
|
13264
13500
|
/**
|
|
13265
13501
|
* Get all skills
|
|
13266
13502
|
*/
|
|
13267
13503
|
getAll() {
|
|
13268
|
-
return
|
|
13504
|
+
return [...this.skills];
|
|
13269
13505
|
}
|
|
13270
13506
|
/**
|
|
13271
13507
|
* Find a skill by name (case-insensitive, supports full and short names)
|
|
13272
13508
|
*/
|
|
13273
13509
|
find(name) {
|
|
13274
13510
|
const normalizedName = name.toLowerCase();
|
|
13275
|
-
|
|
13276
|
-
|
|
13277
|
-
|
|
13278
|
-
|
|
13511
|
+
const [maybeProvider, rest] = normalizedName.includes(":") ? (() => {
|
|
13512
|
+
const parts = normalizedName.split(":");
|
|
13513
|
+
if (parts.length > 1 && [
|
|
13514
|
+
"claude",
|
|
13515
|
+
"codex",
|
|
13516
|
+
"file"
|
|
13517
|
+
].includes(parts[0])) return [parts.shift(), parts.join(":")];
|
|
13518
|
+
return [void 0, normalizedName];
|
|
13519
|
+
})() : [void 0, normalizedName];
|
|
13520
|
+
const targetProvider = maybeProvider;
|
|
13521
|
+
const targetName = rest;
|
|
13522
|
+
const candidates = this.skills.filter((skill) => {
|
|
13523
|
+
const skillName = skill.name.toLowerCase();
|
|
13524
|
+
const shortName = skillName.split(":").pop();
|
|
13525
|
+
const matchesName = skillName === targetName || shortName === targetName;
|
|
13526
|
+
const matchesProvider = targetProvider ? skill.provider === targetProvider : true;
|
|
13527
|
+
return matchesName && matchesProvider;
|
|
13279
13528
|
});
|
|
13280
|
-
if (
|
|
13281
|
-
|
|
13282
|
-
|
|
13283
|
-
|
|
13284
|
-
|
|
13285
|
-
|
|
13286
|
-
const tierMatches = shortMatches.filter((skill) => skill.location === tier);
|
|
13287
|
-
if (tierMatches.length === 1) return tierMatches[0];
|
|
13288
|
-
if (tierMatches.length > 1) throw new AmbiguousSkillNameError(name, tierMatches.map((s) => s.name));
|
|
13289
|
-
}
|
|
13290
|
-
throw new SkillNotFoundError(name, this.getSuggestions(name));
|
|
13529
|
+
if (candidates.length === 1) return candidates[0];
|
|
13530
|
+
if (candidates.length > 1) {
|
|
13531
|
+
const suggestions = candidates.map((s) => this.formatNameWithProvider(s));
|
|
13532
|
+
throw new AmbiguousSkillNameError(name, candidates.map((s) => s.name), suggestions);
|
|
13533
|
+
}
|
|
13534
|
+
throw new SkillNotFoundError(name, this.getSuggestions(name, targetProvider));
|
|
13291
13535
|
}
|
|
13292
13536
|
/**
|
|
13293
13537
|
* Check if a skill exists
|
|
@@ -13309,27 +13553,29 @@ var SkillRegistry = class {
|
|
|
13309
13553
|
/**
|
|
13310
13554
|
* Get suggestions for similar skill names (fuzzy matching)
|
|
13311
13555
|
*/
|
|
13312
|
-
getSuggestions(query, limit = 3) {
|
|
13313
|
-
const
|
|
13314
|
-
return rankStrings(
|
|
13556
|
+
getSuggestions(query, provider, limit = 3) {
|
|
13557
|
+
const pool = this.skills.filter((s) => provider ? s.provider === provider : true).map((s) => this.formatNameWithProvider(s));
|
|
13558
|
+
return rankStrings(pool, query).slice(0, limit).map((index) => pool[index]);
|
|
13559
|
+
}
|
|
13560
|
+
formatNameWithProvider(skill) {
|
|
13561
|
+
return formatSkillId(skill);
|
|
13315
13562
|
}
|
|
13316
13563
|
/**
|
|
13317
13564
|
* Get diagnostic information
|
|
13318
13565
|
*/
|
|
13319
13566
|
getDiagnostics() {
|
|
13320
|
-
const byLocation = {};
|
|
13321
|
-
for (const skill of this.skills.values()) byLocation[skill.location] = (byLocation[skill.location] ?? 0) + 1;
|
|
13322
13567
|
return {
|
|
13323
|
-
totalSkills: this.skills.
|
|
13324
|
-
byLocation,
|
|
13325
|
-
|
|
13326
|
-
|
|
13327
|
-
|
|
13328
|
-
|
|
13568
|
+
totalSkills: this.skills.length,
|
|
13569
|
+
byLocation: { ...this.diagnostics.byLocation },
|
|
13570
|
+
byProvider: { ...this.diagnostics.byProvider },
|
|
13571
|
+
directoriesScanned: [...this.diagnostics.directoriesScanned],
|
|
13572
|
+
pluginSources: [...this.diagnostics.pluginSources],
|
|
13573
|
+
warnings: [...this.diagnostics.warnings],
|
|
13574
|
+
conflicts: [...this.diagnostics.conflicts]
|
|
13329
13575
|
};
|
|
13330
13576
|
}
|
|
13331
13577
|
};
|
|
13332
13578
|
|
|
13333
13579
|
//#endregion
|
|
13334
|
-
export {
|
|
13335
|
-
//# sourceMappingURL=registry-
|
|
13580
|
+
export { SkillFrontmatterSchema as A, optionalType as B, warn as C, ClaudeSettingsSchema as D, validateSkillFile as E, enumType as F, AmbiguousSkillNameError as G, stringType as H, intersectionType as I, SkillNotFoundError as J, CcskiError as K, literalType as L, booleanType as M, custom as N, InstalledPluginsSchema as O, discriminatedUnionType as P, numberType as R, tone as S, parseSkillFile as T, unionType as U, recordType as V, unknownType as W, ValidationError as Y, highlight$1 as _, containsCaseInsensitive as a, setColorEnabled as b, getDefaultSkillDirectories as c, colors as d, dim as f, heading as g, formatBytes as h, skillAliases as i, arrayType as j, PluginEntrySchema as k, loadSkill as l, error as m, formatSkillId as n, rankStrings as o, duplicateBadge as p, ParseError as q, formatSkillLabel as r, discoverSkills as s, SkillRegistry as t, scanSkillDirectory as u, info as v, wrap as w, success as x, renderList as y, objectType as z };
|
|
13581
|
+
//# sourceMappingURL=registry-DNMfmLqa.mjs.map
|