@skillkit/core 1.7.5 → 1.7.7

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
@@ -17,7 +17,22 @@ var AgentType = z.enum([
17
17
  "roo",
18
18
  "trae",
19
19
  "windsurf",
20
- "universal"
20
+ "universal",
21
+ "cline",
22
+ "codebuddy",
23
+ "commandcode",
24
+ "continue",
25
+ "crush",
26
+ "factory",
27
+ "mcpjam",
28
+ "mux",
29
+ "neovate",
30
+ "openhands",
31
+ "pi",
32
+ "qoder",
33
+ "qwen",
34
+ "vercel",
35
+ "zencoder"
21
36
  ]);
22
37
  var GitProvider = z.enum(["github", "gitlab", "bitbucket", "local"]);
23
38
  var SkillFrontmatter = z.object({
@@ -233,6 +248,127 @@ var AGENT_CONFIG = {
233
248
  configFormat: "xml",
234
249
  usesFrontmatter: true,
235
250
  supportsAutoDiscovery: true
251
+ },
252
+ // Cline
253
+ cline: {
254
+ skillsDir: ".cline/skills",
255
+ configFile: "AGENTS.md",
256
+ configFormat: "xml",
257
+ usesFrontmatter: true,
258
+ supportsAutoDiscovery: true
259
+ },
260
+ // Codebuddy
261
+ codebuddy: {
262
+ skillsDir: ".codebuddy/skills",
263
+ configFile: "AGENTS.md",
264
+ configFormat: "xml",
265
+ usesFrontmatter: true,
266
+ supportsAutoDiscovery: true
267
+ },
268
+ // Commandcode
269
+ commandcode: {
270
+ skillsDir: ".commandcode/skills",
271
+ configFile: "AGENTS.md",
272
+ configFormat: "xml",
273
+ usesFrontmatter: true,
274
+ supportsAutoDiscovery: true
275
+ },
276
+ // Continue
277
+ continue: {
278
+ skillsDir: ".continue/skills",
279
+ configFile: "AGENTS.md",
280
+ globalSkillsDir: "~/.continue/skills",
281
+ configFormat: "xml",
282
+ usesFrontmatter: true,
283
+ supportsAutoDiscovery: true
284
+ },
285
+ // Crush
286
+ crush: {
287
+ skillsDir: ".crush/skills",
288
+ configFile: "AGENTS.md",
289
+ configFormat: "xml",
290
+ usesFrontmatter: true,
291
+ supportsAutoDiscovery: true
292
+ },
293
+ // Factory
294
+ factory: {
295
+ skillsDir: ".factory/skills",
296
+ configFile: "AGENTS.md",
297
+ configFormat: "xml",
298
+ usesFrontmatter: true,
299
+ supportsAutoDiscovery: true
300
+ },
301
+ // MCPJam
302
+ mcpjam: {
303
+ skillsDir: ".mcpjam/skills",
304
+ configFile: "AGENTS.md",
305
+ configFormat: "xml",
306
+ usesFrontmatter: true,
307
+ supportsAutoDiscovery: true
308
+ },
309
+ // Mux
310
+ mux: {
311
+ skillsDir: ".mux/skills",
312
+ configFile: "AGENTS.md",
313
+ configFormat: "xml",
314
+ usesFrontmatter: true,
315
+ supportsAutoDiscovery: true
316
+ },
317
+ // Neovate
318
+ neovate: {
319
+ skillsDir: ".neovate/skills",
320
+ configFile: "AGENTS.md",
321
+ configFormat: "xml",
322
+ usesFrontmatter: true,
323
+ supportsAutoDiscovery: true
324
+ },
325
+ // OpenHands
326
+ openhands: {
327
+ skillsDir: ".openhands/skills",
328
+ configFile: "AGENTS.md",
329
+ configFormat: "xml",
330
+ usesFrontmatter: true,
331
+ supportsAutoDiscovery: true
332
+ },
333
+ // Pi
334
+ pi: {
335
+ skillsDir: ".pi/skills",
336
+ configFile: "AGENTS.md",
337
+ configFormat: "xml",
338
+ usesFrontmatter: true,
339
+ supportsAutoDiscovery: true
340
+ },
341
+ // Qoder
342
+ qoder: {
343
+ skillsDir: ".qoder/skills",
344
+ configFile: "AGENTS.md",
345
+ configFormat: "xml",
346
+ usesFrontmatter: true,
347
+ supportsAutoDiscovery: true
348
+ },
349
+ // Qwen
350
+ qwen: {
351
+ skillsDir: ".qwen/skills",
352
+ configFile: "AGENTS.md",
353
+ configFormat: "xml",
354
+ usesFrontmatter: true,
355
+ supportsAutoDiscovery: true
356
+ },
357
+ // Vercel
358
+ vercel: {
359
+ skillsDir: ".vercel/skills",
360
+ configFile: "AGENTS.md",
361
+ configFormat: "xml",
362
+ usesFrontmatter: true,
363
+ supportsAutoDiscovery: true
364
+ },
365
+ // Zencoder
366
+ zencoder: {
367
+ skillsDir: ".zencoder/skills",
368
+ configFile: "AGENTS.md",
369
+ configFormat: "xml",
370
+ usesFrontmatter: true,
371
+ supportsAutoDiscovery: true
236
372
  }
237
373
  };
238
374
  function getAgentDirectoryConfig(agent) {
@@ -271,10 +407,20 @@ var SKILL_DISCOVERY_PATHS = [
271
407
  "skills/.curated",
272
408
  "skills/.experimental",
273
409
  "skills/.system",
410
+ "agents",
274
411
  ".agents/skills",
275
412
  ".agent/skills",
413
+ ".amp/skills",
414
+ ".antigravity/skills",
276
415
  ".claude/skills",
416
+ ".cline/skills",
417
+ ".clawdbot/skills",
418
+ ".codebuddy/skills",
277
419
  ".codex/skills",
420
+ ".commandcode/skills",
421
+ ".continue/skills",
422
+ ".copilot/skills",
423
+ ".crush/skills",
278
424
  ".cursor/skills",
279
425
  ".factory/skills",
280
426
  ".gemini/skills",
@@ -282,13 +428,19 @@ var SKILL_DISCOVERY_PATHS = [
282
428
  ".goose/skills",
283
429
  ".kilocode/skills",
284
430
  ".kiro/skills",
431
+ ".mcpjam/skills",
432
+ ".mux/skills",
433
+ ".neovate/skills",
285
434
  ".opencode/skills",
435
+ ".openhands/skills",
436
+ ".pi/skills",
437
+ ".qoder/skills",
438
+ ".qwen/skills",
286
439
  ".roo/skills",
287
440
  ".trae/skills",
441
+ ".vercel/skills",
288
442
  ".windsurf/skills",
289
- ".clawdbot/skills",
290
- ".antigravity/skills",
291
- ".copilot/skills"
443
+ ".zencoder/skills"
292
444
  ];
293
445
  function discoverSkillsInDir(dir) {
294
446
  const skills = [];
@@ -297,11 +449,17 @@ function discoverSkillsInDir(dir) {
297
449
  }
298
450
  const entries = readdirSync(dir, { withFileTypes: true });
299
451
  for (const entry of entries) {
300
- if (!entry.isDirectory()) continue;
301
- const skillPath = join(dir, entry.name);
302
- const skillMdPath = join(skillPath, "SKILL.md");
303
- if (existsSync(skillMdPath)) {
304
- const skill = parseSkill(skillPath);
452
+ if (entry.isDirectory()) {
453
+ const skillPath = join(dir, entry.name);
454
+ const skillMdPath = join(skillPath, "SKILL.md");
455
+ if (existsSync(skillMdPath)) {
456
+ const skill = parseSkill(skillPath);
457
+ if (skill) {
458
+ skills.push(skill);
459
+ }
460
+ }
461
+ } else if (entry.isFile() && entry.name.endsWith(".md") && entry.name !== "README.md") {
462
+ const skill = parseStandaloneSkill(join(dir, entry.name));
305
463
  if (skill) {
306
464
  skills.push(skill);
307
465
  }
@@ -309,6 +467,32 @@ function discoverSkillsInDir(dir) {
309
467
  }
310
468
  return skills;
311
469
  }
470
+ function parseStandaloneSkill(filePath, location = "project") {
471
+ if (!existsSync(filePath)) {
472
+ return null;
473
+ }
474
+ try {
475
+ const content = readFileSync(filePath, "utf-8");
476
+ const frontmatter = extractFrontmatter(content);
477
+ if (!frontmatter) {
478
+ return null;
479
+ }
480
+ const name = frontmatter.name || basename(filePath, ".md");
481
+ const description = frontmatter.description || "No description available";
482
+ if (!name || name.length === 0) {
483
+ return null;
484
+ }
485
+ return {
486
+ name,
487
+ description,
488
+ path: filePath,
489
+ location,
490
+ enabled: true
491
+ };
492
+ } catch {
493
+ return null;
494
+ }
495
+ }
312
496
  function discoverSkillsRecursive(dir, seen, maxDepth = 5, currentDepth = 0) {
313
497
  const skills = [];
314
498
  if (currentDepth >= maxDepth || !existsSync(dir)) {
@@ -320,18 +504,25 @@ function discoverSkillsRecursive(dir, seen, maxDepth = 5, currentDepth = 0) {
320
504
  if (entry.name === "node_modules" || entry.name === ".git") {
321
505
  continue;
322
506
  }
323
- if (!entry.isDirectory()) continue;
324
507
  const entryPath = join(dir, entry.name);
325
- const skillMdPath = join(entryPath, "SKILL.md");
326
- if (existsSync(skillMdPath)) {
327
- const skill = parseSkill(entryPath);
508
+ if (entry.isDirectory()) {
509
+ const skillMdPath = join(entryPath, "SKILL.md");
510
+ if (existsSync(skillMdPath)) {
511
+ const skill = parseSkill(entryPath);
512
+ if (skill && !seen.has(skill.name)) {
513
+ seen.add(skill.name);
514
+ skills.push(skill);
515
+ }
516
+ } else {
517
+ const subSkills = discoverSkillsRecursive(entryPath, seen, maxDepth, currentDepth + 1);
518
+ skills.push(...subSkills);
519
+ }
520
+ } else if (entry.isFile() && entry.name.endsWith(".md") && entry.name !== "README.md") {
521
+ const skill = parseStandaloneSkill(entryPath);
328
522
  if (skill && !seen.has(skill.name)) {
329
523
  seen.add(skill.name);
330
524
  skills.push(skill);
331
525
  }
332
- } else {
333
- const subSkills = discoverSkillsRecursive(entryPath, seen, maxDepth, currentDepth + 1);
334
- skills.push(...subSkills);
335
526
  }
336
527
  }
337
528
  } catch {
@@ -1033,7 +1224,22 @@ var AGENT_FORMAT_MAP = {
1033
1224
  "universal": "skill-md",
1034
1225
  "cursor": "cursor-mdc",
1035
1226
  "windsurf": "markdown-rules",
1036
- "github-copilot": "markdown-rules"
1227
+ "github-copilot": "markdown-rules",
1228
+ "cline": "skill-md",
1229
+ "codebuddy": "skill-md",
1230
+ "commandcode": "skill-md",
1231
+ "continue": "skill-md",
1232
+ "crush": "skill-md",
1233
+ "factory": "skill-md",
1234
+ "mcpjam": "skill-md",
1235
+ "mux": "skill-md",
1236
+ "neovate": "skill-md",
1237
+ "openhands": "skill-md",
1238
+ "pi": "skill-md",
1239
+ "qoder": "skill-md",
1240
+ "qwen": "skill-md",
1241
+ "vercel": "skill-md",
1242
+ "zencoder": "skill-md"
1037
1243
  };
1038
1244
  var TranslatableSkillFrontmatter = z2.object({
1039
1245
  name: z2.string(),
@@ -15094,6 +15300,111 @@ var AGENT_FORMATS = {
15094
15300
  directory: "commands",
15095
15301
  supportsSlashCommands: true,
15096
15302
  supportsCommandFiles: true
15303
+ },
15304
+ cline: {
15305
+ agent: "cline",
15306
+ extension: ".md",
15307
+ directory: ".cline/commands",
15308
+ supportsSlashCommands: true,
15309
+ supportsCommandFiles: true
15310
+ },
15311
+ codebuddy: {
15312
+ agent: "codebuddy",
15313
+ extension: ".md",
15314
+ directory: ".codebuddy/commands",
15315
+ supportsSlashCommands: true,
15316
+ supportsCommandFiles: true
15317
+ },
15318
+ commandcode: {
15319
+ agent: "commandcode",
15320
+ extension: ".md",
15321
+ directory: ".commandcode/commands",
15322
+ supportsSlashCommands: true,
15323
+ supportsCommandFiles: true
15324
+ },
15325
+ continue: {
15326
+ agent: "continue",
15327
+ extension: ".md",
15328
+ directory: ".continue/commands",
15329
+ supportsSlashCommands: true,
15330
+ supportsCommandFiles: true
15331
+ },
15332
+ crush: {
15333
+ agent: "crush",
15334
+ extension: ".md",
15335
+ directory: ".crush/commands",
15336
+ supportsSlashCommands: true,
15337
+ supportsCommandFiles: true
15338
+ },
15339
+ factory: {
15340
+ agent: "factory",
15341
+ extension: ".md",
15342
+ directory: ".factory/commands",
15343
+ supportsSlashCommands: true,
15344
+ supportsCommandFiles: true
15345
+ },
15346
+ mcpjam: {
15347
+ agent: "mcpjam",
15348
+ extension: ".md",
15349
+ directory: ".mcpjam/commands",
15350
+ supportsSlashCommands: true,
15351
+ supportsCommandFiles: true
15352
+ },
15353
+ mux: {
15354
+ agent: "mux",
15355
+ extension: ".md",
15356
+ directory: ".mux/commands",
15357
+ supportsSlashCommands: true,
15358
+ supportsCommandFiles: true
15359
+ },
15360
+ neovate: {
15361
+ agent: "neovate",
15362
+ extension: ".md",
15363
+ directory: ".neovate/commands",
15364
+ supportsSlashCommands: true,
15365
+ supportsCommandFiles: true
15366
+ },
15367
+ openhands: {
15368
+ agent: "openhands",
15369
+ extension: ".md",
15370
+ directory: ".openhands/commands",
15371
+ supportsSlashCommands: true,
15372
+ supportsCommandFiles: true
15373
+ },
15374
+ pi: {
15375
+ agent: "pi",
15376
+ extension: ".md",
15377
+ directory: ".pi/commands",
15378
+ supportsSlashCommands: true,
15379
+ supportsCommandFiles: true
15380
+ },
15381
+ qoder: {
15382
+ agent: "qoder",
15383
+ extension: ".md",
15384
+ directory: ".qoder/commands",
15385
+ supportsSlashCommands: true,
15386
+ supportsCommandFiles: true
15387
+ },
15388
+ qwen: {
15389
+ agent: "qwen",
15390
+ extension: ".md",
15391
+ directory: ".qwen/commands",
15392
+ supportsSlashCommands: true,
15393
+ supportsCommandFiles: true
15394
+ },
15395
+ vercel: {
15396
+ agent: "vercel",
15397
+ extension: ".md",
15398
+ directory: ".vercel/commands",
15399
+ supportsSlashCommands: true,
15400
+ supportsCommandFiles: true
15401
+ },
15402
+ zencoder: {
15403
+ agent: "zencoder",
15404
+ extension: ".md",
15405
+ directory: ".zencoder/commands",
15406
+ supportsSlashCommands: true,
15407
+ supportsCommandFiles: true
15097
15408
  }
15098
15409
  };
15099
15410
  var CommandGenerator = class {
@@ -16094,22 +16405,40 @@ var AGENT_DISCOVERY_PATHS = {
16094
16405
  "roo": [".roo/agents", ".roo/modes"],
16095
16406
  "trae": [".trae/agents", ".trae/agent"],
16096
16407
  "windsurf": [".windsurf/agents", ".windsurf/workflows"],
16097
- "universal": ["agents", ".agents"]
16408
+ "universal": ["agents", ".agents"],
16409
+ "cline": [".cline/agents"],
16410
+ "codebuddy": [".codebuddy/agents"],
16411
+ "commandcode": [".commandcode/agents"],
16412
+ "continue": [".continue/agents"],
16413
+ "crush": [".crush/agents"],
16414
+ "factory": [".factory/agents"],
16415
+ "mcpjam": [".mcpjam/agents"],
16416
+ "mux": [".mux/agents"],
16417
+ "neovate": [".neovate/agents"],
16418
+ "openhands": [".openhands/agents"],
16419
+ "pi": [".pi/agents"],
16420
+ "qoder": [".qoder/agents"],
16421
+ "qwen": [".qwen/agents"],
16422
+ "vercel": [".vercel/agents"],
16423
+ "zencoder": [".zencoder/agents"]
16098
16424
  };
16099
16425
  var ALL_AGENT_DISCOVERY_PATHS = [
16100
16426
  "agents",
16101
16427
  ".agents",
16428
+ ".amp/agents",
16429
+ ".antigravity/agents",
16102
16430
  ".claude/agents",
16431
+ ".cline/agents",
16432
+ ".clawdbot/agents",
16433
+ ".codebuddy/agents",
16434
+ ".codex/agents",
16435
+ ".commandcode/agents",
16436
+ ".continue/agents",
16437
+ ".crush/agents",
16103
16438
  ".cursor/agents",
16104
16439
  ".cursor/commands",
16105
- ".codex/agents",
16106
- ".gemini/agents",
16107
- ".opencode/agents",
16108
- ".opencode/agent",
16109
- ".antigravity/agents",
16110
- ".amp/agents",
16111
- ".clawdbot/agents",
16112
16440
  ".factory/agents",
16441
+ ".gemini/agents",
16113
16442
  ".github/agents",
16114
16443
  ".github/instructions",
16115
16444
  ".github/custom-agents",
@@ -16117,12 +16446,23 @@ var ALL_AGENT_DISCOVERY_PATHS = [
16117
16446
  ".kilocode/agents",
16118
16447
  ".kilocode/modes",
16119
16448
  ".kiro/agents",
16449
+ ".mcpjam/agents",
16450
+ ".mux/agents",
16451
+ ".neovate/agents",
16452
+ ".opencode/agents",
16453
+ ".opencode/agent",
16454
+ ".openhands/agents",
16455
+ ".pi/agents",
16456
+ ".qoder/agents",
16457
+ ".qwen/agents",
16120
16458
  ".roo/agents",
16121
16459
  ".roo/modes",
16122
16460
  ".trae/agents",
16123
16461
  ".trae/agent",
16462
+ ".vercel/agents",
16124
16463
  ".windsurf/agents",
16125
- ".windsurf/workflows"
16464
+ ".windsurf/workflows",
16465
+ ".zencoder/agents"
16126
16466
  ];
16127
16467
  var CUSTOM_AGENT_FORMAT_MAP = {
16128
16468
  "claude-code": "claude-agent",
@@ -16141,7 +16481,22 @@ var CUSTOM_AGENT_FORMAT_MAP = {
16141
16481
  "roo": "claude-agent",
16142
16482
  "trae": "claude-agent",
16143
16483
  "windsurf": "universal",
16144
- "universal": "universal"
16484
+ "universal": "universal",
16485
+ "cline": "claude-agent",
16486
+ "codebuddy": "claude-agent",
16487
+ "commandcode": "claude-agent",
16488
+ "continue": "claude-agent",
16489
+ "crush": "claude-agent",
16490
+ "factory": "claude-agent",
16491
+ "mcpjam": "claude-agent",
16492
+ "mux": "claude-agent",
16493
+ "neovate": "claude-agent",
16494
+ "openhands": "claude-agent",
16495
+ "pi": "claude-agent",
16496
+ "qoder": "claude-agent",
16497
+ "qwen": "claude-agent",
16498
+ "vercel": "claude-agent",
16499
+ "zencoder": "claude-agent"
16145
16500
  };
16146
16501
 
16147
16502
  // src/agents/parser.ts
@@ -17367,6 +17722,798 @@ function escapeXml(text) {
17367
17722
  }
17368
17723
  var getAgentSkillsDir = getSkillsDir;
17369
17724
  var getAgentConfigFile = getConfigFile;
17725
+
17726
+ // src/manifest/index.ts
17727
+ import { readFileSync as readFileSync25, writeFileSync as writeFileSync18, existsSync as existsSync33 } from "fs";
17728
+ import { join as join34, dirname as dirname12 } from "path";
17729
+ import { parse as parseYaml12, stringify as stringifyYaml9 } from "yaml";
17730
+ var MANIFEST_FILENAMES = [".skills", ".skills.yaml", ".skills.yml", "skills.yaml"];
17731
+ function findManifestPath(startDir = process.cwd()) {
17732
+ let dir = startDir;
17733
+ while (dir !== dirname12(dir)) {
17734
+ for (const filename of MANIFEST_FILENAMES) {
17735
+ const manifestPath = join34(dir, filename);
17736
+ if (existsSync33(manifestPath)) {
17737
+ return manifestPath;
17738
+ }
17739
+ }
17740
+ dir = dirname12(dir);
17741
+ }
17742
+ return null;
17743
+ }
17744
+ function loadManifest(manifestPath) {
17745
+ const path2 = manifestPath || findManifestPath();
17746
+ if (!path2 || !existsSync33(path2)) {
17747
+ return null;
17748
+ }
17749
+ try {
17750
+ const content = readFileSync25(path2, "utf-8");
17751
+ const parsed = parseYaml12(content);
17752
+ if (!parsed || typeof parsed !== "object") {
17753
+ return null;
17754
+ }
17755
+ return {
17756
+ version: parsed.version || 1,
17757
+ skills: normalizeSkills(parsed.skills || []),
17758
+ agents: parsed.agents,
17759
+ installMethod: parsed.installMethod,
17760
+ updatedAt: parsed.updatedAt
17761
+ };
17762
+ } catch {
17763
+ return null;
17764
+ }
17765
+ }
17766
+ function normalizeSkills(skills) {
17767
+ return skills.map((skill) => {
17768
+ if (typeof skill === "string") {
17769
+ const parts = skill.split("/");
17770
+ if (parts.length >= 3) {
17771
+ return {
17772
+ source: `${parts[0]}/${parts[1]}`,
17773
+ skills: [parts.slice(2).join("/")],
17774
+ enabled: true
17775
+ };
17776
+ }
17777
+ return { source: skill, enabled: true };
17778
+ }
17779
+ if (typeof skill === "object" && skill !== null) {
17780
+ const entry = skill;
17781
+ return {
17782
+ source: String(entry.source || ""),
17783
+ skills: entry.skills,
17784
+ agents: entry.agents,
17785
+ enabled: entry.enabled !== false
17786
+ };
17787
+ }
17788
+ return { source: "", enabled: false };
17789
+ }).filter((s) => s.source);
17790
+ }
17791
+ function saveManifest(manifest, manifestPath) {
17792
+ const path2 = manifestPath || join34(process.cwd(), ".skills");
17793
+ const content = stringifyYaml9({
17794
+ version: manifest.version || 1,
17795
+ skills: manifest.skills.map((s) => {
17796
+ if (!s.skills && !s.agents && s.enabled !== false) {
17797
+ return s.source;
17798
+ }
17799
+ return s;
17800
+ }),
17801
+ ...manifest.agents && { agents: manifest.agents },
17802
+ ...manifest.installMethod && { installMethod: manifest.installMethod },
17803
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
17804
+ });
17805
+ writeFileSync18(path2, content, "utf-8");
17806
+ }
17807
+ function addToManifest(source, options, manifestPath) {
17808
+ const existing = loadManifest(manifestPath) || {
17809
+ version: 1,
17810
+ skills: []
17811
+ };
17812
+ const existingIndex = existing.skills.findIndex((s) => s.source === source);
17813
+ if (existingIndex >= 0) {
17814
+ existing.skills[existingIndex] = {
17815
+ ...existing.skills[existingIndex],
17816
+ ...options,
17817
+ enabled: true
17818
+ };
17819
+ } else {
17820
+ existing.skills.push({
17821
+ source,
17822
+ ...options,
17823
+ enabled: true
17824
+ });
17825
+ }
17826
+ saveManifest(existing, manifestPath);
17827
+ return existing;
17828
+ }
17829
+ function removeFromManifest(source, manifestPath) {
17830
+ const existing = loadManifest(manifestPath);
17831
+ if (!existing) {
17832
+ return null;
17833
+ }
17834
+ existing.skills = existing.skills.filter((s) => s.source !== source);
17835
+ saveManifest(existing, manifestPath);
17836
+ return existing;
17837
+ }
17838
+ function initManifest(options, manifestPath) {
17839
+ const manifest = {
17840
+ version: 1,
17841
+ skills: [],
17842
+ ...options,
17843
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
17844
+ };
17845
+ saveManifest(manifest, manifestPath);
17846
+ return manifest;
17847
+ }
17848
+ function generateManifestFromInstalled(installedSkills) {
17849
+ const skillsBySource = /* @__PURE__ */ new Map();
17850
+ for (const skill of installedSkills) {
17851
+ if (!skill.source) continue;
17852
+ const existing = skillsBySource.get(skill.source);
17853
+ if (existing) {
17854
+ existing.skills.push(skill.name);
17855
+ if (skill.agents) {
17856
+ skill.agents.forEach((a) => existing.agents.add(a));
17857
+ }
17858
+ } else {
17859
+ skillsBySource.set(skill.source, {
17860
+ skills: [skill.name],
17861
+ agents: new Set(skill.agents || [])
17862
+ });
17863
+ }
17864
+ }
17865
+ const skills = [];
17866
+ for (const [source, data] of skillsBySource) {
17867
+ skills.push({
17868
+ source,
17869
+ skills: data.skills.length > 0 ? data.skills : void 0,
17870
+ agents: data.agents.size > 0 ? Array.from(data.agents) : void 0,
17871
+ enabled: true
17872
+ });
17873
+ }
17874
+ return {
17875
+ version: 1,
17876
+ skills,
17877
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
17878
+ };
17879
+ }
17880
+
17881
+ // src/quality/index.ts
17882
+ import { readFileSync as readFileSync26, existsSync as existsSync34 } from "fs";
17883
+ import { join as join35, basename as basename12 } from "path";
17884
+
17885
+ // src/quality/benchmark.ts
17886
+ var CATEGORY_BENCHMARKS = {
17887
+ react: {
17888
+ category: "react",
17889
+ avgScore: 78,
17890
+ topScore: 95,
17891
+ topSkills: ["react-patterns", "react-hooks-best-practices"],
17892
+ count: 150,
17893
+ distribution: { A: 15, B: 35, C: 30, D: 15, F: 5 }
17894
+ },
17895
+ typescript: {
17896
+ category: "typescript",
17897
+ avgScore: 75,
17898
+ topScore: 92,
17899
+ topSkills: ["typescript-strict", "type-safety-patterns"],
17900
+ count: 120,
17901
+ distribution: { A: 12, B: 30, C: 35, D: 18, F: 5 }
17902
+ },
17903
+ testing: {
17904
+ category: "testing",
17905
+ avgScore: 72,
17906
+ topScore: 90,
17907
+ topSkills: ["tdd-workflow", "testing-best-practices"],
17908
+ count: 80,
17909
+ distribution: { A: 10, B: 28, C: 38, D: 19, F: 5 }
17910
+ },
17911
+ git: {
17912
+ category: "git",
17913
+ avgScore: 80,
17914
+ topScore: 94,
17915
+ topSkills: ["git-workflow", "conventional-commits"],
17916
+ count: 60,
17917
+ distribution: { A: 18, B: 40, C: 28, D: 12, F: 2 }
17918
+ },
17919
+ security: {
17920
+ category: "security",
17921
+ avgScore: 76,
17922
+ topScore: 93,
17923
+ topSkills: ["security-review", "owasp-patterns"],
17924
+ count: 45,
17925
+ distribution: { A: 14, B: 32, C: 34, D: 16, F: 4 }
17926
+ },
17927
+ api: {
17928
+ category: "api",
17929
+ avgScore: 74,
17930
+ topScore: 91,
17931
+ topSkills: ["api-design", "rest-best-practices"],
17932
+ count: 55,
17933
+ distribution: { A: 11, B: 30, C: 36, D: 18, F: 5 }
17934
+ },
17935
+ general: {
17936
+ category: "general",
17937
+ avgScore: 70,
17938
+ topScore: 88,
17939
+ topSkills: ["code-review", "best-practices"],
17940
+ count: 200,
17941
+ distribution: { A: 8, B: 25, C: 40, D: 22, F: 5 }
17942
+ }
17943
+ };
17944
+ function getGrade(score) {
17945
+ if (score >= 90) return "A";
17946
+ if (score >= 80) return "B";
17947
+ if (score >= 70) return "C";
17948
+ if (score >= 60) return "D";
17949
+ return "F";
17950
+ }
17951
+ function detectCategory(skillName, tags = []) {
17952
+ const lowerName = skillName.toLowerCase();
17953
+ const lowerTags = tags.map((t) => t.toLowerCase());
17954
+ const searchTerms = [lowerName, ...lowerTags];
17955
+ const categoryKeywords = {
17956
+ react: ["react", "hooks", "jsx", "tsx", "component", "nextjs", "remix"],
17957
+ typescript: ["typescript", "type", "types", "ts", "strict"],
17958
+ testing: ["test", "testing", "tdd", "jest", "vitest", "playwright", "e2e"],
17959
+ git: ["git", "commit", "branch", "merge", "workflow", "conventional"],
17960
+ security: ["security", "auth", "owasp", "vulnerability", "safe"],
17961
+ api: ["api", "rest", "graphql", "endpoint", "http"]
17962
+ };
17963
+ for (const [category, keywords] of Object.entries(categoryKeywords)) {
17964
+ for (const term of searchTerms) {
17965
+ if (keywords.some((kw) => term.includes(kw))) {
17966
+ return category;
17967
+ }
17968
+ }
17969
+ }
17970
+ return "general";
17971
+ }
17972
+ function calculatePercentile(score, categoryStats) {
17973
+ const { distribution } = categoryStats;
17974
+ const totalSkills = distribution.A + distribution.B + distribution.C + distribution.D + distribution.F;
17975
+ let percentBelow = 0;
17976
+ if (score < 60) {
17977
+ percentBelow = score / 60 * (distribution.F / totalSkills) * 100;
17978
+ } else if (score < 70) {
17979
+ percentBelow = distribution.F / totalSkills * 100;
17980
+ percentBelow += (score - 60) / 10 * (distribution.D / totalSkills) * 100;
17981
+ } else if (score < 80) {
17982
+ percentBelow = (distribution.F + distribution.D) / totalSkills * 100;
17983
+ percentBelow += (score - 70) / 10 * (distribution.C / totalSkills) * 100;
17984
+ } else if (score < 90) {
17985
+ percentBelow = (distribution.F + distribution.D + distribution.C) / totalSkills * 100;
17986
+ percentBelow += (score - 80) / 10 * (distribution.B / totalSkills) * 100;
17987
+ } else {
17988
+ percentBelow = (distribution.F + distribution.D + distribution.C + distribution.B) / totalSkills * 100;
17989
+ percentBelow += (score - 90) / 10 * (distribution.A / totalSkills) * 100;
17990
+ }
17991
+ return Math.round(Math.min(99, Math.max(1, percentBelow)));
17992
+ }
17993
+ function generateComparisonNotes(quality, categoryStats) {
17994
+ const notes = [];
17995
+ const topScore = categoryStats.topScore;
17996
+ const avgScore = categoryStats.avgScore;
17997
+ if (quality.overall >= topScore) {
17998
+ notes.push("Your skill is among the top performers in this category");
17999
+ } else if (quality.overall >= avgScore) {
18000
+ notes.push(`Your skill is above the category average (${avgScore})`);
18001
+ } else {
18002
+ notes.push(`Your skill is ${avgScore - quality.overall} points below the category average`);
18003
+ }
18004
+ if (!quality.structure.hasExamples) {
18005
+ notes.push("Missing code examples (present in 95% of top skills)");
18006
+ }
18007
+ if (!quality.structure.hasTriggers) {
18008
+ notes.push("Missing trigger conditions (present in 80% of top skills)");
18009
+ }
18010
+ if (!quality.structure.hasBoundaries) {
18011
+ notes.push('Missing "When Not to Use" section (present in 80% of top skills)');
18012
+ }
18013
+ if (quality.specificity.vagueTermCount > 3) {
18014
+ notes.push("Trigger conditions are less specific than category average");
18015
+ }
18016
+ if (quality.clarity.lineCount > 300) {
18017
+ notes.push("Skill is longer than recommended (top skills average 150-250 lines)");
18018
+ }
18019
+ if (quality.advanced.deprecatedPatterns.length > 0) {
18020
+ notes.push("Contains deprecated patterns not found in top skills");
18021
+ }
18022
+ return notes;
18023
+ }
18024
+ function generateRecommendations(quality, categoryStats) {
18025
+ const recommendations = [];
18026
+ const gap = categoryStats.topScore - quality.overall;
18027
+ if (gap > 20) {
18028
+ recommendations.push("Consider studying top skills in this category for patterns");
18029
+ }
18030
+ if (!quality.structure.hasExamples) {
18031
+ recommendations.push(`Add ${quality.specificity.hasCodeExamples ? "more" : ""} code examples showing input/output`);
18032
+ }
18033
+ if (!quality.structure.hasTriggers) {
18034
+ recommendations.push('Add explicit trigger conditions with patterns like "Triggers when:"');
18035
+ }
18036
+ if (!quality.structure.hasBoundaries) {
18037
+ recommendations.push('Add a "Boundaries" or "Limitations" section');
18038
+ }
18039
+ if (quality.clarity.lineCount > 400) {
18040
+ recommendations.push("Split into multiple focused skills (top skills are 150-250 lines)");
18041
+ }
18042
+ if (quality.specificity.vagueTermCount > 0) {
18043
+ recommendations.push(`Replace ${quality.specificity.vagueTermCount} vague term(s) with specific instructions`);
18044
+ }
18045
+ if (quality.advanced.completeness.hasTodos) {
18046
+ recommendations.push("Complete TODO items before publishing");
18047
+ }
18048
+ return recommendations;
18049
+ }
18050
+ function benchmarkSkill(skillName, quality, tags = [], customCategoryStats) {
18051
+ const category = detectCategory(skillName, tags);
18052
+ const categoryStats = customCategoryStats || CATEGORY_BENCHMARKS[category] || CATEGORY_BENCHMARKS.general;
18053
+ const percentile = calculatePercentile(quality.overall, categoryStats);
18054
+ const comparisonNotes = generateComparisonNotes(quality, categoryStats);
18055
+ const recommendations = generateRecommendations(quality, categoryStats);
18056
+ return {
18057
+ skill: skillName,
18058
+ score: quality.overall,
18059
+ grade: getGrade(quality.overall),
18060
+ categoryAvg: categoryStats.avgScore,
18061
+ topSkillScore: categoryStats.topScore,
18062
+ percentile,
18063
+ comparisonNotes,
18064
+ recommendations
18065
+ };
18066
+ }
18067
+ function getCategoryStats(category) {
18068
+ return CATEGORY_BENCHMARKS[category] || null;
18069
+ }
18070
+ function getAllCategories() {
18071
+ return Object.keys(CATEGORY_BENCHMARKS);
18072
+ }
18073
+
18074
+ // src/quality/index.ts
18075
+ var VAGUE_TERMS = [
18076
+ "be helpful",
18077
+ "assist the user",
18078
+ "help with",
18079
+ "try to",
18080
+ "attempt to",
18081
+ "do your best",
18082
+ "as needed",
18083
+ "when appropriate",
18084
+ "if necessary",
18085
+ "general purpose",
18086
+ "various tasks",
18087
+ "many things",
18088
+ "etc.",
18089
+ "and so on",
18090
+ "stuff like that"
18091
+ ];
18092
+ var BOUNDARY_PATTERNS = [
18093
+ /never\s+(?:do|use|commit|push|delete|remove)/i,
18094
+ /always\s+(?:do|use|check|verify|ensure)/i,
18095
+ /don'?t\s+(?:do|use|commit|push|delete)/i,
18096
+ /avoid\s+(?:using|doing|committing)/i,
18097
+ /must\s+(?:not|always|never)/i,
18098
+ /forbidden/i,
18099
+ /prohibited/i,
18100
+ /required/i
18101
+ ];
18102
+ var TRIGGER_PATTERNS = [
18103
+ /when\s+to\s+use/i,
18104
+ /use\s+this\s+(?:skill|when)/i,
18105
+ /triggers?\s*(?:when|:)/i,
18106
+ /activated?\s+(?:when|by)/i,
18107
+ /applies?\s+(?:when|to)/i,
18108
+ /invoke\s+(?:when|this)/i
18109
+ ];
18110
+ var COMMAND_PATTERNS = [
18111
+ /```(?:bash|sh|shell|zsh)[\s\S]*?```/g,
18112
+ /`(?:npm|pnpm|yarn|bun|npx|git|docker|kubectl)\s+[^`]+`/g,
18113
+ /\$\s*\w+/g
18114
+ ];
18115
+ var CODE_EXAMPLE_PATTERNS = [
18116
+ /```(?:typescript|javascript|tsx|jsx|python|go|rust|java)[\s\S]*?```/g,
18117
+ /```[\s\S]{50,}?```/g
18118
+ ];
18119
+ var FILE_PATTERN_PATTERNS = [
18120
+ /\*\*\/\*\.\w+/,
18121
+ /\.\w+$/m,
18122
+ /glob[s]?\s*[:=]/i,
18123
+ /include[s]?\s*[:=]/i,
18124
+ /pattern[s]?\s*[:=]/i
18125
+ ];
18126
+ var DEPRECATED_PATTERNS = [
18127
+ { pattern: /require\s*\(['"][^'"]+['"]\)/g, message: "Uses CommonJS require() instead of ES modules" },
18128
+ { pattern: /React\.Component/g, message: "Uses class components instead of functional" },
18129
+ { pattern: /componentDidMount|componentWillUnmount|componentDidUpdate/g, message: "Uses lifecycle methods instead of hooks" },
18130
+ { pattern: /\bvar\s+\w+\s*=/g, message: "Uses var instead of const/let" },
18131
+ { pattern: /\.then\s*\([^)]*\)\.catch/g, message: "Uses .then().catch() instead of async/await" },
18132
+ { pattern: /new\s+Promise\s*\(/g, message: "Consider using async/await instead of new Promise()" }
18133
+ ];
18134
+ var SECURITY_PATTERNS = [
18135
+ { pattern: /password\s*[:=]\s*['"][^'"]+['"]/gi, message: "Potential hardcoded password" },
18136
+ { pattern: /api[_-]?key\s*[:=]\s*['"][^'"]+['"]/gi, message: "Potential hardcoded API key" },
18137
+ { pattern: /secret\s*[:=]\s*['"][^'"]+['"]/gi, message: "Potential hardcoded secret" },
18138
+ { pattern: /token\s*[:=]\s*['"][A-Za-z0-9_-]{20,}['"]/gi, message: "Potential hardcoded token" },
18139
+ { pattern: /\$\{[^}]*\}/g, message: "Template literal - ensure proper sanitization in shell commands" },
18140
+ { pattern: /eval\s*\(/g, message: "Uses eval() - potential code injection risk" },
18141
+ { pattern: /innerHTML\s*=/g, message: "Uses innerHTML - potential XSS risk" },
18142
+ { pattern: /dangerouslySetInnerHTML/g, message: "Uses dangerouslySetInnerHTML - potential XSS risk" }
18143
+ ];
18144
+ function extractFrontmatter4(content) {
18145
+ const normalizedContent = content.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
18146
+ const match = normalizedContent.match(/^---\s*\n([\s\S]*?)\n---/);
18147
+ if (!match) return null;
18148
+ const frontmatter = {};
18149
+ const lines = match[1].split("\n");
18150
+ for (const line of lines) {
18151
+ const colonIndex = line.indexOf(":");
18152
+ if (colonIndex > 0) {
18153
+ const key = line.slice(0, colonIndex).trim();
18154
+ const value = line.slice(colonIndex + 1).trim();
18155
+ frontmatter[key] = value;
18156
+ }
18157
+ }
18158
+ return Object.keys(frontmatter).length > 0 ? frontmatter : null;
18159
+ }
18160
+ function countTokens(text) {
18161
+ return Math.ceil(text.length / 4);
18162
+ }
18163
+ function countVagueTerms(content) {
18164
+ const lowerContent = content.toLowerCase();
18165
+ let count = 0;
18166
+ for (const term of VAGUE_TERMS) {
18167
+ const regex = new RegExp(term.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "gi");
18168
+ const matches = lowerContent.match(regex);
18169
+ if (matches) count += matches.length;
18170
+ }
18171
+ return count;
18172
+ }
18173
+ function hasPattern(content, patterns) {
18174
+ return patterns.some((p) => p.test(content));
18175
+ }
18176
+ function countMatches(content, patterns) {
18177
+ let count = 0;
18178
+ for (const pattern of patterns) {
18179
+ const matches = content.match(pattern);
18180
+ if (matches) count += matches.length;
18181
+ }
18182
+ return count;
18183
+ }
18184
+ function calculateAvgSentenceLength(content) {
18185
+ const contentWithoutCode = content.replace(/```[\s\S]*?```/g, "");
18186
+ const sentences = contentWithoutCode.split(/[.!?]+/).filter((s) => s.trim().length > 0);
18187
+ if (sentences.length === 0) return 0;
18188
+ const totalWords = sentences.reduce((sum, s) => sum + s.trim().split(/\s+/).length, 0);
18189
+ return Math.round(totalWords / sentences.length);
18190
+ }
18191
+ function evaluateStructure(content) {
18192
+ const frontmatter = extractFrontmatter4(content);
18193
+ const hasMetadata = frontmatter !== null && Object.keys(frontmatter).length > 0;
18194
+ const hasDescription = !!frontmatter?.description || /^#+\s*description/im.test(content);
18195
+ const hasTriggers = hasPattern(content, TRIGGER_PATTERNS);
18196
+ const hasExamples = countMatches(content, CODE_EXAMPLE_PATTERNS) > 0;
18197
+ const hasBoundaries = hasPattern(content, BOUNDARY_PATTERNS);
18198
+ const hasWhenToUse = /when\s+to\s+use|use\s+case|scenario/i.test(content);
18199
+ let score = 0;
18200
+ if (hasMetadata) score += 15;
18201
+ if (hasDescription) score += 10;
18202
+ if (hasTriggers) score += 20;
18203
+ if (hasExamples) score += 20;
18204
+ if (hasBoundaries) score += 20;
18205
+ if (hasWhenToUse) score += 15;
18206
+ return {
18207
+ score: Math.min(100, score),
18208
+ hasMetadata,
18209
+ hasDescription,
18210
+ hasTriggers,
18211
+ hasExamples,
18212
+ hasBoundaries,
18213
+ hasWhenToUse
18214
+ };
18215
+ }
18216
+ function evaluateClarity(content) {
18217
+ const lines = content.split("\n");
18218
+ const lineCount = lines.length;
18219
+ const tokenCount = countTokens(content);
18220
+ const avgSentenceLength = calculateAvgSentenceLength(content);
18221
+ const hasHeaders = /^#+\s+/m.test(content);
18222
+ let score = 100;
18223
+ if (lineCount > 500) score -= 30;
18224
+ else if (lineCount > 300) score -= 15;
18225
+ else if (lineCount > 150) score -= 5;
18226
+ if (tokenCount > 4e3) score -= 30;
18227
+ else if (tokenCount > 2e3) score -= 15;
18228
+ else if (tokenCount > 1e3) score -= 5;
18229
+ if (avgSentenceLength > 30) score -= 20;
18230
+ else if (avgSentenceLength > 20) score -= 10;
18231
+ if (!hasHeaders) score -= 15;
18232
+ return {
18233
+ score: Math.max(0, score),
18234
+ lineCount,
18235
+ tokenCount,
18236
+ avgSentenceLength,
18237
+ hasHeaders
18238
+ };
18239
+ }
18240
+ function countCodeBlocks(content) {
18241
+ const fencedBlocks = content.match(/```[\s\S]*?```/g) || [];
18242
+ return fencedBlocks.length;
18243
+ }
18244
+ function detectDeprecatedPatterns(content) {
18245
+ const codeBlocks = content.match(/```[\s\S]*?```/g) || [];
18246
+ const codeContent = codeBlocks.join("\n");
18247
+ const issues = [];
18248
+ for (const { pattern, message } of DEPRECATED_PATTERNS) {
18249
+ const regex = new RegExp(pattern.source, pattern.flags);
18250
+ if (regex.test(codeContent)) {
18251
+ issues.push(message);
18252
+ }
18253
+ }
18254
+ return [...new Set(issues)];
18255
+ }
18256
+ function detectSecurityPatterns(content) {
18257
+ const issues = [];
18258
+ for (const { pattern, message } of SECURITY_PATTERNS) {
18259
+ const regex = new RegExp(pattern.source, pattern.flags);
18260
+ if (regex.test(content)) {
18261
+ if (!message.includes("Template literal") || content.includes("bash") || content.includes("shell")) {
18262
+ issues.push(message);
18263
+ }
18264
+ }
18265
+ }
18266
+ return [...new Set(issues)];
18267
+ }
18268
+ function detectConflictingInstructions(content) {
18269
+ const issues = [];
18270
+ const lowerContent = content.toLowerCase();
18271
+ const alwaysMatches = lowerContent.match(/always\s+(?:use|do|include|add)\s+(\w+)/gi) || [];
18272
+ const neverMatches = lowerContent.match(/never\s+(?:use|do|include|add)\s+(\w+)/gi) || [];
18273
+ for (const always of alwaysMatches) {
18274
+ const term = always.replace(/always\s+(?:use|do|include|add)\s+/i, "").toLowerCase();
18275
+ for (const never of neverMatches) {
18276
+ const neverTerm = never.replace(/never\s+(?:use|do|include|add)\s+/i, "").toLowerCase();
18277
+ if (term === neverTerm) {
18278
+ issues.push(`Conflicting instructions: "always" and "never" used with "${term}"`);
18279
+ }
18280
+ }
18281
+ }
18282
+ const mustMatches = lowerContent.match(/must\s+(\w+)/gi) || [];
18283
+ const mustNotMatches = lowerContent.match(/must\s+not\s+(\w+)/gi) || [];
18284
+ for (const must of mustMatches) {
18285
+ const term = must.replace(/must\s+/i, "").toLowerCase();
18286
+ for (const mustNot of mustNotMatches) {
18287
+ const notTerm = mustNot.replace(/must\s+not\s+/i, "").toLowerCase();
18288
+ if (term === notTerm) {
18289
+ issues.push(`Conflicting instructions: "must" and "must not" used with "${term}"`);
18290
+ }
18291
+ }
18292
+ }
18293
+ return [...new Set(issues)];
18294
+ }
18295
+ function assessCompleteness(content) {
18296
+ const todoMatches = content.match(/TODO|FIXME|XXX|HACK/gi) || [];
18297
+ const todoCount = todoMatches.length;
18298
+ const headerPositions = [];
18299
+ const lines = content.split("\n");
18300
+ let inFence = false;
18301
+ let offset = 0;
18302
+ for (const line of lines) {
18303
+ if (/^```|^~~~/.test(line)) {
18304
+ inFence = !inFence;
18305
+ } else if (!inFence && /^#+\s+.+$/.test(line)) {
18306
+ headerPositions.push({ header: line, index: offset });
18307
+ }
18308
+ offset += line.length + 1;
18309
+ }
18310
+ const emptySections = [];
18311
+ for (let i = 0; i < headerPositions.length - 1; i++) {
18312
+ const current = headerPositions[i];
18313
+ const next = headerPositions[i + 1];
18314
+ const sectionContent = content.slice(current.index + current.header.length, next.index).trim();
18315
+ if (sectionContent.length < 20) {
18316
+ const sectionName = current.header.replace(/^#+\s+/, "");
18317
+ emptySections.push(sectionName);
18318
+ }
18319
+ }
18320
+ if (headerPositions.length > 0) {
18321
+ const last = headerPositions[headerPositions.length - 1];
18322
+ const tailContent = content.slice(last.index + last.header.length).trim();
18323
+ if (tailContent.length < 20) {
18324
+ const sectionName = last.header.replace(/^#+\s+/, "");
18325
+ emptySections.push(sectionName);
18326
+ }
18327
+ }
18328
+ const codeBlocks = countCodeBlocks(content);
18329
+ const exampleCoverage = Math.min(100, codeBlocks * 25);
18330
+ let score = 100;
18331
+ if (todoCount > 0) score -= Math.min(30, todoCount * 10);
18332
+ if (emptySections.length > 0) score -= Math.min(30, emptySections.length * 10);
18333
+ if (codeBlocks < 2) score -= 20;
18334
+ else if (codeBlocks < 4) score -= 10;
18335
+ return {
18336
+ score: Math.max(0, score),
18337
+ hasTodos: todoCount > 0,
18338
+ todoCount,
18339
+ emptySections,
18340
+ exampleCoverage
18341
+ };
18342
+ }
18343
+ function evaluateAdvanced(content) {
18344
+ const deprecatedPatterns = detectDeprecatedPatterns(content);
18345
+ const conflictingInstructions = detectConflictingInstructions(content);
18346
+ const securityIssues = detectSecurityPatterns(content);
18347
+ const completeness = assessCompleteness(content);
18348
+ let score = 100;
18349
+ score -= Math.min(30, deprecatedPatterns.length * 10);
18350
+ score -= Math.min(30, conflictingInstructions.length * 15);
18351
+ score -= Math.min(25, securityIssues.length * 10);
18352
+ score -= Math.round((100 - completeness.score) * 0.15);
18353
+ return {
18354
+ score: Math.max(0, score),
18355
+ deprecatedPatterns,
18356
+ conflictingInstructions,
18357
+ securityIssues,
18358
+ completeness
18359
+ };
18360
+ }
18361
+ function evaluateSpecificity(content) {
18362
+ const hasConcreteCommands = countMatches(content, COMMAND_PATTERNS) > 0;
18363
+ const hasFilePatterns = hasPattern(content, FILE_PATTERN_PATTERNS);
18364
+ const codeBlockCount = countCodeBlocks(content);
18365
+ const hasCodeExamples = codeBlockCount >= 2;
18366
+ const vagueTermCount = countVagueTerms(content);
18367
+ let score = 0;
18368
+ if (hasConcreteCommands) score += 30;
18369
+ if (hasFilePatterns) score += 25;
18370
+ if (hasCodeExamples) score += 30;
18371
+ if (vagueTermCount === 0) score += 15;
18372
+ else if (vagueTermCount <= 2) score += 10;
18373
+ else if (vagueTermCount <= 5) score += 5;
18374
+ return {
18375
+ score: Math.min(100, score),
18376
+ hasConcreteCommands,
18377
+ hasFilePatterns,
18378
+ hasCodeExamples,
18379
+ vagueTermCount
18380
+ };
18381
+ }
18382
+ function generateWarnings(structure, clarity, specificity, advanced) {
18383
+ const warnings = [];
18384
+ if (!structure.hasMetadata) {
18385
+ warnings.push("Missing frontmatter metadata");
18386
+ }
18387
+ if (!structure.hasTriggers) {
18388
+ warnings.push("No trigger conditions defined");
18389
+ }
18390
+ if (!structure.hasBoundaries) {
18391
+ warnings.push("No boundaries or constraints specified");
18392
+ }
18393
+ if (clarity.lineCount > 500) {
18394
+ warnings.push(`Skill is too long (${clarity.lineCount} lines)`);
18395
+ }
18396
+ if (clarity.tokenCount > 4e3) {
18397
+ warnings.push(`High token usage (${clarity.tokenCount} tokens)`);
18398
+ }
18399
+ if (specificity.vagueTermCount > 5) {
18400
+ warnings.push(`Contains ${specificity.vagueTermCount} vague terms`);
18401
+ }
18402
+ if (!structure.hasExamples) {
18403
+ warnings.push("No code examples provided");
18404
+ } else if (!specificity.hasCodeExamples) {
18405
+ warnings.push("Only one code example provided");
18406
+ }
18407
+ for (const issue of advanced.securityIssues) {
18408
+ warnings.push(`Security: ${issue}`);
18409
+ }
18410
+ for (const conflict of advanced.conflictingInstructions) {
18411
+ warnings.push(conflict);
18412
+ }
18413
+ if (advanced.completeness.hasTodos) {
18414
+ warnings.push(`Contains ${advanced.completeness.todoCount} TODO/FIXME comment(s)`);
18415
+ }
18416
+ if (advanced.completeness.emptySections.length > 0) {
18417
+ warnings.push(`Empty sections: ${advanced.completeness.emptySections.join(", ")}`);
18418
+ }
18419
+ return warnings;
18420
+ }
18421
+ function generateSuggestions(structure, clarity, specificity, advanced) {
18422
+ const suggestions = [];
18423
+ if (!structure.hasMetadata) {
18424
+ suggestions.push("Add YAML frontmatter with name, description, and globs");
18425
+ }
18426
+ if (!structure.hasTriggers) {
18427
+ suggestions.push('Add a "When to Use" section with specific trigger conditions');
18428
+ }
18429
+ if (!structure.hasExamples) {
18430
+ suggestions.push("Include code examples showing expected output");
18431
+ }
18432
+ if (!structure.hasBoundaries) {
18433
+ suggestions.push("Define boundaries: what the agent should never do");
18434
+ }
18435
+ if (clarity.lineCount > 300) {
18436
+ suggestions.push("Consider splitting into multiple focused skills");
18437
+ }
18438
+ if (!clarity.hasHeaders) {
18439
+ suggestions.push("Use markdown headers to organize content");
18440
+ }
18441
+ if (specificity.vagueTermCount > 0) {
18442
+ suggestions.push("Replace vague terms with specific instructions");
18443
+ }
18444
+ if (!specificity.hasConcreteCommands) {
18445
+ suggestions.push("Add concrete executable commands with flags");
18446
+ }
18447
+ if (advanced.deprecatedPatterns.length > 0) {
18448
+ suggestions.push("Update code examples to use modern patterns (ES modules, hooks, async/await)");
18449
+ }
18450
+ if (advanced.securityIssues.length > 0) {
18451
+ suggestions.push("Review and remove potential security risks from examples");
18452
+ }
18453
+ if (advanced.completeness.hasTodos) {
18454
+ suggestions.push("Complete or remove TODO/FIXME comments");
18455
+ }
18456
+ if (advanced.completeness.emptySections.length > 0) {
18457
+ suggestions.push("Add content to empty sections or remove them");
18458
+ }
18459
+ if (advanced.completeness.exampleCoverage < 50) {
18460
+ suggestions.push("Add more code examples to improve coverage");
18461
+ }
18462
+ return suggestions;
18463
+ }
18464
+ function evaluateSkillContent(content) {
18465
+ const structure = evaluateStructure(content);
18466
+ const clarity = evaluateClarity(content);
18467
+ const specificity = evaluateSpecificity(content);
18468
+ const advanced = evaluateAdvanced(content);
18469
+ const overall = Math.round(
18470
+ structure.score * 0.35 + clarity.score * 0.25 + specificity.score * 0.25 + advanced.score * 0.15
18471
+ );
18472
+ const warnings = generateWarnings(structure, clarity, specificity, advanced);
18473
+ const suggestions = generateSuggestions(structure, clarity, specificity, advanced);
18474
+ return {
18475
+ overall,
18476
+ structure,
18477
+ clarity,
18478
+ specificity,
18479
+ advanced,
18480
+ warnings,
18481
+ suggestions
18482
+ };
18483
+ }
18484
+ function evaluateSkillFile(filePath) {
18485
+ if (!existsSync34(filePath)) return null;
18486
+ try {
18487
+ const content = readFileSync26(filePath, "utf-8");
18488
+ return evaluateSkillContent(content);
18489
+ } catch {
18490
+ return null;
18491
+ }
18492
+ }
18493
+ function evaluateSkillDirectory(dirPath) {
18494
+ const skillMdPath = join35(dirPath, "SKILL.md");
18495
+ if (existsSync34(skillMdPath)) {
18496
+ return evaluateSkillFile(skillMdPath);
18497
+ }
18498
+ const mdcFiles = ["index.mdc", `${basename12(dirPath)}.mdc`];
18499
+ for (const file of mdcFiles) {
18500
+ const mdcPath = join35(dirPath, file);
18501
+ if (existsSync34(mdcPath)) {
18502
+ return evaluateSkillFile(mdcPath);
18503
+ }
18504
+ }
18505
+ return null;
18506
+ }
18507
+ function getQualityGrade(score) {
18508
+ if (score >= 90) return "A";
18509
+ if (score >= 80) return "B";
18510
+ if (score >= 70) return "C";
18511
+ if (score >= 60) return "D";
18512
+ return "F";
18513
+ }
18514
+ function isHighQuality(score) {
18515
+ return score.overall >= 80 && score.warnings.length <= 2;
18516
+ }
17370
18517
  export {
17371
18518
  AGENT_CLI_CONFIGS,
17372
18519
  AGENT_CONFIG,
@@ -17462,9 +18609,12 @@ export {
17462
18609
  WORKFLOW_EXTENSION,
17463
18610
  WindsurfTranslator,
17464
18611
  WorkflowOrchestrator,
18612
+ addToManifest,
17465
18613
  agentExists,
17466
18614
  analyzeProject,
18615
+ benchmarkSkill,
17467
18616
  buildSkillIndex,
18617
+ calculatePercentile,
17468
18618
  canTranslate,
17469
18619
  copilotTranslator,
17470
18620
  createAPIBasedCompressor,
@@ -17502,6 +18652,7 @@ export {
17502
18652
  createWorkflowOrchestrator,
17503
18653
  createWorkflowTemplate,
17504
18654
  cursorTranslator,
18655
+ detectCategory,
17505
18656
  detectProvider,
17506
18657
  detectSkillFormat,
17507
18658
  discoverAgents,
@@ -17512,6 +18663,9 @@ export {
17512
18663
  discoverSkills,
17513
18664
  dryRunExecutor,
17514
18665
  estimateTokens,
18666
+ evaluateSkillContent,
18667
+ evaluateSkillDirectory,
18668
+ evaluateSkillFile,
17515
18669
  executeWithAgent,
17516
18670
  exportBundle,
17517
18671
  extractAgentContent,
@@ -17523,9 +18677,13 @@ export {
17523
18677
  findAgent,
17524
18678
  findAllAgents,
17525
18679
  findAllSkills,
18680
+ findManifestPath,
17526
18681
  findSkill,
17527
18682
  formatSkillAsPrompt,
17528
18683
  fromCanonicalAgent,
18684
+ generateComparisonNotes,
18685
+ generateManifestFromInstalled,
18686
+ generateRecommendations,
17529
18687
  generateSkillsConfig,
17530
18688
  getAgentCLIConfig,
17531
18689
  getAgentConfigFile,
@@ -17537,16 +18695,19 @@ export {
17537
18695
  getAgentStats,
17538
18696
  getAgentTargetDirectory,
17539
18697
  getAgentsDirectory,
18698
+ getAllCategories,
17540
18699
  getAllProviders,
17541
18700
  getAllSkillsDirs,
17542
18701
  getAvailableCLIAgents,
17543
18702
  getBuiltinPacksDir,
17544
18703
  getCICDTemplate,
18704
+ getCategoryStats,
17545
18705
  getConfigFile,
17546
18706
  getConfigFormat,
17547
18707
  getExecutionStrategy,
17548
18708
  getGlobalConfigPath,
17549
18709
  getGlobalSkillsDir,
18710
+ getGrade,
17550
18711
  getIndexStatus,
17551
18712
  getInstallDir,
17552
18713
  getManualExecutionInstructions,
@@ -17554,6 +18715,7 @@ export {
17554
18715
  getMemoryStatus,
17555
18716
  getProjectConfigPath,
17556
18717
  getProvider,
18718
+ getQualityGrade,
17557
18719
  getSearchDirs,
17558
18720
  getSkillsDir,
17559
18721
  getStackTags,
@@ -17562,11 +18724,13 @@ export {
17562
18724
  globalMemoryDirectoryExists,
17563
18725
  importBundle,
17564
18726
  initContext,
18727
+ initManifest,
17565
18728
  initProject,
17566
18729
  initializeMemoryDirectory,
17567
18730
  isAgentCLIAvailable,
17568
18731
  isAgentCompatible,
17569
18732
  isGitUrl,
18733
+ isHighQuality,
17570
18734
  isIndexStale,
17571
18735
  isLocalPath,
17572
18736
  isPathInside,
@@ -17576,6 +18740,7 @@ export {
17576
18740
  loadConfig,
17577
18741
  loadContext,
17578
18742
  loadIndex,
18743
+ loadManifest,
17579
18744
  loadMetadata,
17580
18745
  loadPlugin,
17581
18746
  loadPluginsFromDirectory,
@@ -17594,9 +18759,11 @@ export {
17594
18759
  parseWorkflow,
17595
18760
  readAgentContent,
17596
18761
  readSkillContent,
18762
+ removeFromManifest,
17597
18763
  runTestSuite,
17598
18764
  saveConfig,
17599
18765
  saveIndex,
18766
+ saveManifest,
17600
18767
  saveSkillMetadata,
17601
18768
  saveWorkflow,
17602
18769
  serializeWorkflow,