@skillkit/core 1.7.6 → 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.d.ts +97 -8
- package/dist/index.js +1032 -27
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
-
".
|
|
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 (
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
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
|
-
|
|
326
|
-
|
|
327
|
-
|
|
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
|
|
@@ -17522,6 +17877,643 @@ function generateManifestFromInstalled(installedSkills) {
|
|
|
17522
17877
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
17523
17878
|
};
|
|
17524
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
|
+
}
|
|
17525
18517
|
export {
|
|
17526
18518
|
AGENT_CLI_CONFIGS,
|
|
17527
18519
|
AGENT_CONFIG,
|
|
@@ -17620,7 +18612,9 @@ export {
|
|
|
17620
18612
|
addToManifest,
|
|
17621
18613
|
agentExists,
|
|
17622
18614
|
analyzeProject,
|
|
18615
|
+
benchmarkSkill,
|
|
17623
18616
|
buildSkillIndex,
|
|
18617
|
+
calculatePercentile,
|
|
17624
18618
|
canTranslate,
|
|
17625
18619
|
copilotTranslator,
|
|
17626
18620
|
createAPIBasedCompressor,
|
|
@@ -17658,6 +18652,7 @@ export {
|
|
|
17658
18652
|
createWorkflowOrchestrator,
|
|
17659
18653
|
createWorkflowTemplate,
|
|
17660
18654
|
cursorTranslator,
|
|
18655
|
+
detectCategory,
|
|
17661
18656
|
detectProvider,
|
|
17662
18657
|
detectSkillFormat,
|
|
17663
18658
|
discoverAgents,
|
|
@@ -17668,6 +18663,9 @@ export {
|
|
|
17668
18663
|
discoverSkills,
|
|
17669
18664
|
dryRunExecutor,
|
|
17670
18665
|
estimateTokens,
|
|
18666
|
+
evaluateSkillContent,
|
|
18667
|
+
evaluateSkillDirectory,
|
|
18668
|
+
evaluateSkillFile,
|
|
17671
18669
|
executeWithAgent,
|
|
17672
18670
|
exportBundle,
|
|
17673
18671
|
extractAgentContent,
|
|
@@ -17683,7 +18681,9 @@ export {
|
|
|
17683
18681
|
findSkill,
|
|
17684
18682
|
formatSkillAsPrompt,
|
|
17685
18683
|
fromCanonicalAgent,
|
|
18684
|
+
generateComparisonNotes,
|
|
17686
18685
|
generateManifestFromInstalled,
|
|
18686
|
+
generateRecommendations,
|
|
17687
18687
|
generateSkillsConfig,
|
|
17688
18688
|
getAgentCLIConfig,
|
|
17689
18689
|
getAgentConfigFile,
|
|
@@ -17695,16 +18695,19 @@ export {
|
|
|
17695
18695
|
getAgentStats,
|
|
17696
18696
|
getAgentTargetDirectory,
|
|
17697
18697
|
getAgentsDirectory,
|
|
18698
|
+
getAllCategories,
|
|
17698
18699
|
getAllProviders,
|
|
17699
18700
|
getAllSkillsDirs,
|
|
17700
18701
|
getAvailableCLIAgents,
|
|
17701
18702
|
getBuiltinPacksDir,
|
|
17702
18703
|
getCICDTemplate,
|
|
18704
|
+
getCategoryStats,
|
|
17703
18705
|
getConfigFile,
|
|
17704
18706
|
getConfigFormat,
|
|
17705
18707
|
getExecutionStrategy,
|
|
17706
18708
|
getGlobalConfigPath,
|
|
17707
18709
|
getGlobalSkillsDir,
|
|
18710
|
+
getGrade,
|
|
17708
18711
|
getIndexStatus,
|
|
17709
18712
|
getInstallDir,
|
|
17710
18713
|
getManualExecutionInstructions,
|
|
@@ -17712,6 +18715,7 @@ export {
|
|
|
17712
18715
|
getMemoryStatus,
|
|
17713
18716
|
getProjectConfigPath,
|
|
17714
18717
|
getProvider,
|
|
18718
|
+
getQualityGrade,
|
|
17715
18719
|
getSearchDirs,
|
|
17716
18720
|
getSkillsDir,
|
|
17717
18721
|
getStackTags,
|
|
@@ -17726,6 +18730,7 @@ export {
|
|
|
17726
18730
|
isAgentCLIAvailable,
|
|
17727
18731
|
isAgentCompatible,
|
|
17728
18732
|
isGitUrl,
|
|
18733
|
+
isHighQuality,
|
|
17729
18734
|
isIndexStale,
|
|
17730
18735
|
isLocalPath,
|
|
17731
18736
|
isPathInside,
|