@skillkit/core 1.15.0 → 1.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +125 -8
- package/dist/index.js +1157 -8
- package/dist/index.js.map +1 -1
- package/package.json +7 -4
package/dist/index.js
CHANGED
|
@@ -3290,7 +3290,19 @@ var AgentType = z.enum([
|
|
|
3290
3290
|
"qoder",
|
|
3291
3291
|
"qwen",
|
|
3292
3292
|
"vercel",
|
|
3293
|
-
"zencoder"
|
|
3293
|
+
"zencoder",
|
|
3294
|
+
"devin",
|
|
3295
|
+
"aider",
|
|
3296
|
+
"sourcegraph-cody",
|
|
3297
|
+
"amazon-q",
|
|
3298
|
+
"augment-code",
|
|
3299
|
+
"replit-agent",
|
|
3300
|
+
"bolt",
|
|
3301
|
+
"lovable",
|
|
3302
|
+
"tabby",
|
|
3303
|
+
"tabnine",
|
|
3304
|
+
"codegpt",
|
|
3305
|
+
"playcode-agent"
|
|
3294
3306
|
]);
|
|
3295
3307
|
var GitProvider = z.enum(["github", "gitlab", "bitbucket", "local", "wellknown"]);
|
|
3296
3308
|
var SkillFrontmatter = z.object({
|
|
@@ -3627,6 +3639,107 @@ var AGENT_CONFIG = {
|
|
|
3627
3639
|
configFormat: "xml",
|
|
3628
3640
|
usesFrontmatter: true,
|
|
3629
3641
|
supportsAutoDiscovery: true
|
|
3642
|
+
},
|
|
3643
|
+
// Devin (Cognition Labs)
|
|
3644
|
+
devin: {
|
|
3645
|
+
skillsDir: ".devin/skills",
|
|
3646
|
+
configFile: "AGENTS.md",
|
|
3647
|
+
configFormat: "markdown",
|
|
3648
|
+
usesFrontmatter: true,
|
|
3649
|
+
supportsAutoDiscovery: true
|
|
3650
|
+
},
|
|
3651
|
+
// Aider
|
|
3652
|
+
aider: {
|
|
3653
|
+
skillsDir: ".aider/skills",
|
|
3654
|
+
configFile: "AGENTS.md",
|
|
3655
|
+
globalSkillsDir: "~/.aider/skills",
|
|
3656
|
+
configFormat: "markdown",
|
|
3657
|
+
usesFrontmatter: true,
|
|
3658
|
+
supportsAutoDiscovery: true
|
|
3659
|
+
},
|
|
3660
|
+
// Sourcegraph Cody
|
|
3661
|
+
"sourcegraph-cody": {
|
|
3662
|
+
skillsDir: ".cody/skills",
|
|
3663
|
+
configFile: "AGENTS.md",
|
|
3664
|
+
globalSkillsDir: "~/.cody/skills",
|
|
3665
|
+
configFormat: "markdown",
|
|
3666
|
+
usesFrontmatter: true,
|
|
3667
|
+
supportsAutoDiscovery: true
|
|
3668
|
+
},
|
|
3669
|
+
// Amazon Q Developer
|
|
3670
|
+
"amazon-q": {
|
|
3671
|
+
skillsDir: ".amazonq/skills",
|
|
3672
|
+
configFile: "AGENTS.md",
|
|
3673
|
+
globalSkillsDir: "~/.amazonq/skills",
|
|
3674
|
+
configFormat: "markdown",
|
|
3675
|
+
usesFrontmatter: true,
|
|
3676
|
+
supportsAutoDiscovery: true
|
|
3677
|
+
},
|
|
3678
|
+
// Augment Code
|
|
3679
|
+
"augment-code": {
|
|
3680
|
+
skillsDir: ".augment/skills",
|
|
3681
|
+
configFile: "AGENTS.md",
|
|
3682
|
+
configFormat: "markdown",
|
|
3683
|
+
usesFrontmatter: true,
|
|
3684
|
+
supportsAutoDiscovery: true
|
|
3685
|
+
},
|
|
3686
|
+
// Replit Agent
|
|
3687
|
+
"replit-agent": {
|
|
3688
|
+
skillsDir: ".replit/skills",
|
|
3689
|
+
configFile: "AGENTS.md",
|
|
3690
|
+
configFormat: "markdown",
|
|
3691
|
+
usesFrontmatter: true,
|
|
3692
|
+
supportsAutoDiscovery: true
|
|
3693
|
+
},
|
|
3694
|
+
// Bolt (Vercel)
|
|
3695
|
+
bolt: {
|
|
3696
|
+
skillsDir: ".bolt/skills",
|
|
3697
|
+
configFile: "AGENTS.md",
|
|
3698
|
+
configFormat: "markdown",
|
|
3699
|
+
usesFrontmatter: true,
|
|
3700
|
+
supportsAutoDiscovery: true
|
|
3701
|
+
},
|
|
3702
|
+
// Lovable
|
|
3703
|
+
lovable: {
|
|
3704
|
+
skillsDir: ".lovable/skills",
|
|
3705
|
+
configFile: "AGENTS.md",
|
|
3706
|
+
configFormat: "markdown",
|
|
3707
|
+
usesFrontmatter: true,
|
|
3708
|
+
supportsAutoDiscovery: true
|
|
3709
|
+
},
|
|
3710
|
+
// Tabby
|
|
3711
|
+
tabby: {
|
|
3712
|
+
skillsDir: ".tabby/skills",
|
|
3713
|
+
configFile: "AGENTS.md",
|
|
3714
|
+
globalSkillsDir: "~/.tabby/skills",
|
|
3715
|
+
configFormat: "markdown",
|
|
3716
|
+
usesFrontmatter: true,
|
|
3717
|
+
supportsAutoDiscovery: true
|
|
3718
|
+
},
|
|
3719
|
+
// Tabnine
|
|
3720
|
+
tabnine: {
|
|
3721
|
+
skillsDir: ".tabnine/skills",
|
|
3722
|
+
configFile: "AGENTS.md",
|
|
3723
|
+
globalSkillsDir: "~/.tabnine/skills",
|
|
3724
|
+
configFormat: "markdown",
|
|
3725
|
+
usesFrontmatter: true,
|
|
3726
|
+
supportsAutoDiscovery: true
|
|
3727
|
+
},
|
|
3728
|
+
// CodeGPT
|
|
3729
|
+
codegpt: {
|
|
3730
|
+
skillsDir: ".codegpt/skills",
|
|
3731
|
+
configFile: "AGENTS.md",
|
|
3732
|
+
configFormat: "markdown",
|
|
3733
|
+
usesFrontmatter: true,
|
|
3734
|
+
supportsAutoDiscovery: true
|
|
3735
|
+
},
|
|
3736
|
+
// PlayCode Agent
|
|
3737
|
+
"playcode-agent": {
|
|
3738
|
+
skillsDir: ".playcode/skills",
|
|
3739
|
+
configFile: "AGENTS.md",
|
|
3740
|
+
configFormat: "markdown",
|
|
3741
|
+
usesFrontmatter: true,
|
|
3742
|
+
supportsAutoDiscovery: true
|
|
3630
3743
|
}
|
|
3631
3744
|
};
|
|
3632
3745
|
function getAgentDirectoryConfig(agent) {
|
|
@@ -4442,6 +4555,16 @@ import { existsSync as existsSync7, mkdirSync as mkdirSync2, writeFileSync as wr
|
|
|
4442
4555
|
import { join as join7, basename as basename6, resolve as resolve3, sep as sep2 } from "path";
|
|
4443
4556
|
import { tmpdir as tmpdir4 } from "os";
|
|
4444
4557
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
4558
|
+
function skillNameFromUrl(url) {
|
|
4559
|
+
try {
|
|
4560
|
+
const parsed = new URL(url);
|
|
4561
|
+
const segments = parsed.pathname.split("/").filter(Boolean);
|
|
4562
|
+
return segments[segments.length - 1] || parsed.hostname.split(".")[0] || "default";
|
|
4563
|
+
} catch {
|
|
4564
|
+
return basename6(url) || "default";
|
|
4565
|
+
}
|
|
4566
|
+
}
|
|
4567
|
+
var FRONTMATTER_REGEX = /^---\s*\n[\s\S]*?name:\s*.+/;
|
|
4445
4568
|
function sanitizeSkillName(name) {
|
|
4446
4569
|
if (!name || typeof name !== "string") return null;
|
|
4447
4570
|
const base = basename6(name);
|
|
@@ -4453,6 +4576,11 @@ function sanitizeSkillName(name) {
|
|
|
4453
4576
|
}
|
|
4454
4577
|
return name;
|
|
4455
4578
|
}
|
|
4579
|
+
var MINTLIFY_PATHS = [
|
|
4580
|
+
"/.well-known/skills/default/skill.md",
|
|
4581
|
+
"/skill.md",
|
|
4582
|
+
"/.well-known/skill.md"
|
|
4583
|
+
];
|
|
4456
4584
|
var WellKnownProvider = class {
|
|
4457
4585
|
type = "wellknown";
|
|
4458
4586
|
name = "Well-Known";
|
|
@@ -4484,6 +4612,51 @@ var WellKnownProvider = class {
|
|
|
4484
4612
|
getSshUrl(_owner, _repo) {
|
|
4485
4613
|
return "";
|
|
4486
4614
|
}
|
|
4615
|
+
async discoverFromUrl(url) {
|
|
4616
|
+
const baseUrl = url.replace(/\/$/, "");
|
|
4617
|
+
const tempDir = join7(tmpdir4(), `skillkit-wellknown-${randomUUID4()}`);
|
|
4618
|
+
try {
|
|
4619
|
+
mkdirSync2(tempDir, { recursive: true });
|
|
4620
|
+
for (const mintlifyPath of MINTLIFY_PATHS) {
|
|
4621
|
+
const fullUrl = `${baseUrl}${mintlifyPath}`;
|
|
4622
|
+
try {
|
|
4623
|
+
const response = await fetch(fullUrl);
|
|
4624
|
+
if (response.ok) {
|
|
4625
|
+
const content = await response.text();
|
|
4626
|
+
if (FRONTMATTER_REGEX.test(content)) {
|
|
4627
|
+
const skillName = skillNameFromUrl(baseUrl);
|
|
4628
|
+
const safeName = sanitizeSkillName(skillName) ?? "default";
|
|
4629
|
+
const skillDir = join7(tempDir, safeName);
|
|
4630
|
+
mkdirSync2(skillDir, { recursive: true });
|
|
4631
|
+
writeFileSync2(join7(skillDir, "SKILL.md"), content);
|
|
4632
|
+
return {
|
|
4633
|
+
success: true,
|
|
4634
|
+
path: tempDir,
|
|
4635
|
+
tempRoot: tempDir,
|
|
4636
|
+
skills: [safeName],
|
|
4637
|
+
discoveredSkills: [{ name: safeName, dirName: safeName, path: skillDir }]
|
|
4638
|
+
};
|
|
4639
|
+
}
|
|
4640
|
+
}
|
|
4641
|
+
} catch {
|
|
4642
|
+
continue;
|
|
4643
|
+
}
|
|
4644
|
+
}
|
|
4645
|
+
const indexResult = await this.clone(baseUrl, "", {});
|
|
4646
|
+
if (indexResult.success) {
|
|
4647
|
+
rmSync4(tempDir, { recursive: true, force: true });
|
|
4648
|
+
return indexResult;
|
|
4649
|
+
}
|
|
4650
|
+
rmSync4(tempDir, { recursive: true, force: true });
|
|
4651
|
+
return { success: false, error: "No well-known skills found" };
|
|
4652
|
+
} catch (error) {
|
|
4653
|
+
if (existsSync7(tempDir)) {
|
|
4654
|
+
rmSync4(tempDir, { recursive: true, force: true });
|
|
4655
|
+
}
|
|
4656
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4657
|
+
return { success: false, error: `Failed to discover skills: ${message}` };
|
|
4658
|
+
}
|
|
4659
|
+
}
|
|
4487
4660
|
async clone(source, _targetDir, _options = {}) {
|
|
4488
4661
|
const tempDir = join7(tmpdir4(), `skillkit-wellknown-${randomUUID4()}`);
|
|
4489
4662
|
try {
|
|
@@ -4508,6 +4681,32 @@ var WellKnownProvider = class {
|
|
|
4508
4681
|
}
|
|
4509
4682
|
}
|
|
4510
4683
|
if (!index || !index.skills || index.skills.length === 0) {
|
|
4684
|
+
for (const mintlifyPath of MINTLIFY_PATHS) {
|
|
4685
|
+
const fullUrl = `${baseUrl}${mintlifyPath}`;
|
|
4686
|
+
try {
|
|
4687
|
+
const response = await fetch(fullUrl);
|
|
4688
|
+
if (response.ok) {
|
|
4689
|
+
const content = await response.text();
|
|
4690
|
+
if (FRONTMATTER_REGEX.test(content)) {
|
|
4691
|
+
const skillName = skillNameFromUrl(baseUrl);
|
|
4692
|
+
const safeName = sanitizeSkillName(skillName) ?? "default";
|
|
4693
|
+
const skillDir = join7(tempDir, safeName);
|
|
4694
|
+
mkdirSync2(skillDir, { recursive: true });
|
|
4695
|
+
writeFileSync2(join7(skillDir, "SKILL.md"), content);
|
|
4696
|
+
return {
|
|
4697
|
+
success: true,
|
|
4698
|
+
path: tempDir,
|
|
4699
|
+
tempRoot: tempDir,
|
|
4700
|
+
skills: [safeName],
|
|
4701
|
+
discoveredSkills: [{ name: safeName, dirName: safeName, path: skillDir }]
|
|
4702
|
+
};
|
|
4703
|
+
}
|
|
4704
|
+
}
|
|
4705
|
+
} catch {
|
|
4706
|
+
continue;
|
|
4707
|
+
}
|
|
4708
|
+
}
|
|
4709
|
+
rmSync4(tempDir, { recursive: true, force: true });
|
|
4511
4710
|
return {
|
|
4512
4711
|
success: false,
|
|
4513
4712
|
error: `No skills found at ${baseUrl}/.well-known/skills/index.json`
|
|
@@ -4692,7 +4891,19 @@ var AGENT_FORMAT_MAP = {
|
|
|
4692
4891
|
"qoder": "skill-md",
|
|
4693
4892
|
"qwen": "skill-md",
|
|
4694
4893
|
"vercel": "skill-md",
|
|
4695
|
-
"zencoder": "skill-md"
|
|
4894
|
+
"zencoder": "skill-md",
|
|
4895
|
+
"devin": "external",
|
|
4896
|
+
"aider": "skill-md",
|
|
4897
|
+
"sourcegraph-cody": "skill-md",
|
|
4898
|
+
"amazon-q": "skill-md",
|
|
4899
|
+
"augment-code": "skill-md",
|
|
4900
|
+
"replit-agent": "external",
|
|
4901
|
+
"bolt": "external",
|
|
4902
|
+
"lovable": "external",
|
|
4903
|
+
"tabby": "skill-md",
|
|
4904
|
+
"tabnine": "skill-md",
|
|
4905
|
+
"codegpt": "skill-md",
|
|
4906
|
+
"playcode-agent": "external"
|
|
4696
4907
|
};
|
|
4697
4908
|
var TranslatableSkillFrontmatter = z2.object({
|
|
4698
4909
|
name: z2.string(),
|
|
@@ -19992,6 +20203,90 @@ var AGENT_FORMATS = {
|
|
|
19992
20203
|
directory: ".zencoder/commands",
|
|
19993
20204
|
supportsSlashCommands: true,
|
|
19994
20205
|
supportsCommandFiles: true
|
|
20206
|
+
},
|
|
20207
|
+
devin: {
|
|
20208
|
+
agent: "devin",
|
|
20209
|
+
extension: ".md",
|
|
20210
|
+
directory: ".devin/commands",
|
|
20211
|
+
supportsSlashCommands: false,
|
|
20212
|
+
supportsCommandFiles: true
|
|
20213
|
+
},
|
|
20214
|
+
aider: {
|
|
20215
|
+
agent: "aider",
|
|
20216
|
+
extension: ".md",
|
|
20217
|
+
directory: ".aider/commands",
|
|
20218
|
+
supportsSlashCommands: false,
|
|
20219
|
+
supportsCommandFiles: true
|
|
20220
|
+
},
|
|
20221
|
+
"sourcegraph-cody": {
|
|
20222
|
+
agent: "sourcegraph-cody",
|
|
20223
|
+
extension: ".md",
|
|
20224
|
+
directory: ".cody/commands",
|
|
20225
|
+
supportsSlashCommands: false,
|
|
20226
|
+
supportsCommandFiles: true
|
|
20227
|
+
},
|
|
20228
|
+
"amazon-q": {
|
|
20229
|
+
agent: "amazon-q",
|
|
20230
|
+
extension: ".md",
|
|
20231
|
+
directory: ".amazonq/commands",
|
|
20232
|
+
supportsSlashCommands: false,
|
|
20233
|
+
supportsCommandFiles: true
|
|
20234
|
+
},
|
|
20235
|
+
"augment-code": {
|
|
20236
|
+
agent: "augment-code",
|
|
20237
|
+
extension: ".md",
|
|
20238
|
+
directory: ".augment/commands",
|
|
20239
|
+
supportsSlashCommands: false,
|
|
20240
|
+
supportsCommandFiles: true
|
|
20241
|
+
},
|
|
20242
|
+
"replit-agent": {
|
|
20243
|
+
agent: "replit-agent",
|
|
20244
|
+
extension: ".md",
|
|
20245
|
+
directory: ".replit/commands",
|
|
20246
|
+
supportsSlashCommands: false,
|
|
20247
|
+
supportsCommandFiles: true
|
|
20248
|
+
},
|
|
20249
|
+
bolt: {
|
|
20250
|
+
agent: "bolt",
|
|
20251
|
+
extension: ".md",
|
|
20252
|
+
directory: ".bolt/commands",
|
|
20253
|
+
supportsSlashCommands: false,
|
|
20254
|
+
supportsCommandFiles: true
|
|
20255
|
+
},
|
|
20256
|
+
lovable: {
|
|
20257
|
+
agent: "lovable",
|
|
20258
|
+
extension: ".md",
|
|
20259
|
+
directory: ".lovable/commands",
|
|
20260
|
+
supportsSlashCommands: false,
|
|
20261
|
+
supportsCommandFiles: true
|
|
20262
|
+
},
|
|
20263
|
+
tabby: {
|
|
20264
|
+
agent: "tabby",
|
|
20265
|
+
extension: ".md",
|
|
20266
|
+
directory: ".tabby/commands",
|
|
20267
|
+
supportsSlashCommands: false,
|
|
20268
|
+
supportsCommandFiles: true
|
|
20269
|
+
},
|
|
20270
|
+
tabnine: {
|
|
20271
|
+
agent: "tabnine",
|
|
20272
|
+
extension: ".md",
|
|
20273
|
+
directory: ".tabnine/commands",
|
|
20274
|
+
supportsSlashCommands: false,
|
|
20275
|
+
supportsCommandFiles: true
|
|
20276
|
+
},
|
|
20277
|
+
codegpt: {
|
|
20278
|
+
agent: "codegpt",
|
|
20279
|
+
extension: ".md",
|
|
20280
|
+
directory: ".codegpt/commands",
|
|
20281
|
+
supportsSlashCommands: false,
|
|
20282
|
+
supportsCommandFiles: true
|
|
20283
|
+
},
|
|
20284
|
+
"playcode-agent": {
|
|
20285
|
+
agent: "playcode-agent",
|
|
20286
|
+
extension: ".md",
|
|
20287
|
+
directory: ".playcode/commands",
|
|
20288
|
+
supportsSlashCommands: false,
|
|
20289
|
+
supportsCommandFiles: true
|
|
19995
20290
|
}
|
|
19996
20291
|
};
|
|
19997
20292
|
var CommandGenerator = class {
|
|
@@ -25148,7 +25443,19 @@ var AGENT_DISCOVERY_PATHS = {
|
|
|
25148
25443
|
"qoder": [".qoder/agents"],
|
|
25149
25444
|
"qwen": [".qwen/agents"],
|
|
25150
25445
|
"vercel": [".vercel/agents"],
|
|
25151
|
-
"zencoder": [".zencoder/agents"]
|
|
25446
|
+
"zencoder": [".zencoder/agents"],
|
|
25447
|
+
"devin": [".devin/agents"],
|
|
25448
|
+
"aider": [".aider/agents"],
|
|
25449
|
+
"sourcegraph-cody": [".cody/agents"],
|
|
25450
|
+
"amazon-q": [".amazonq/agents"],
|
|
25451
|
+
"augment-code": [".augment/agents"],
|
|
25452
|
+
"replit-agent": [".replit/agents"],
|
|
25453
|
+
"bolt": [".bolt/agents"],
|
|
25454
|
+
"lovable": [".lovable/agents"],
|
|
25455
|
+
"tabby": [".tabby/agents"],
|
|
25456
|
+
"tabnine": [".tabnine/agents"],
|
|
25457
|
+
"codegpt": [".codegpt/agents"],
|
|
25458
|
+
"playcode-agent": [".playcode/agents"]
|
|
25152
25459
|
};
|
|
25153
25460
|
var ALL_AGENT_DISCOVERY_PATHS = [
|
|
25154
25461
|
"agents",
|
|
@@ -25191,7 +25498,19 @@ var ALL_AGENT_DISCOVERY_PATHS = [
|
|
|
25191
25498
|
".vercel/agents",
|
|
25192
25499
|
".windsurf/agents",
|
|
25193
25500
|
".windsurf/workflows",
|
|
25194
|
-
".zencoder/agents"
|
|
25501
|
+
".zencoder/agents",
|
|
25502
|
+
".devin/agents",
|
|
25503
|
+
".aider/agents",
|
|
25504
|
+
".cody/agents",
|
|
25505
|
+
".amazonq/agents",
|
|
25506
|
+
".augment/agents",
|
|
25507
|
+
".replit/agents",
|
|
25508
|
+
".bolt/agents",
|
|
25509
|
+
".lovable/agents",
|
|
25510
|
+
".tabby/agents",
|
|
25511
|
+
".tabnine/agents",
|
|
25512
|
+
".codegpt/agents",
|
|
25513
|
+
".playcode/agents"
|
|
25195
25514
|
];
|
|
25196
25515
|
var CUSTOM_AGENT_FORMAT_MAP = {
|
|
25197
25516
|
"claude-code": "claude-agent",
|
|
@@ -25225,7 +25544,19 @@ var CUSTOM_AGENT_FORMAT_MAP = {
|
|
|
25225
25544
|
"qoder": "claude-agent",
|
|
25226
25545
|
"qwen": "claude-agent",
|
|
25227
25546
|
"vercel": "claude-agent",
|
|
25228
|
-
"zencoder": "claude-agent"
|
|
25547
|
+
"zencoder": "claude-agent",
|
|
25548
|
+
"devin": "universal",
|
|
25549
|
+
"aider": "universal",
|
|
25550
|
+
"sourcegraph-cody": "universal",
|
|
25551
|
+
"amazon-q": "universal",
|
|
25552
|
+
"augment-code": "universal",
|
|
25553
|
+
"replit-agent": "universal",
|
|
25554
|
+
"bolt": "universal",
|
|
25555
|
+
"lovable": "universal",
|
|
25556
|
+
"tabby": "universal",
|
|
25557
|
+
"tabnine": "universal",
|
|
25558
|
+
"codegpt": "universal",
|
|
25559
|
+
"playcode-agent": "universal"
|
|
25229
25560
|
};
|
|
25230
25561
|
|
|
25231
25562
|
// src/agents/parser.ts
|
|
@@ -26382,7 +26713,34 @@ function translateSkillToAll(skillPath, sourceAgent, options) {
|
|
|
26382
26713
|
"roo",
|
|
26383
26714
|
"trae",
|
|
26384
26715
|
"windsurf",
|
|
26385
|
-
"universal"
|
|
26716
|
+
"universal",
|
|
26717
|
+
"cline",
|
|
26718
|
+
"codebuddy",
|
|
26719
|
+
"commandcode",
|
|
26720
|
+
"continue",
|
|
26721
|
+
"crush",
|
|
26722
|
+
"factory",
|
|
26723
|
+
"mcpjam",
|
|
26724
|
+
"mux",
|
|
26725
|
+
"neovate",
|
|
26726
|
+
"openhands",
|
|
26727
|
+
"pi",
|
|
26728
|
+
"qoder",
|
|
26729
|
+
"qwen",
|
|
26730
|
+
"vercel",
|
|
26731
|
+
"zencoder",
|
|
26732
|
+
"devin",
|
|
26733
|
+
"aider",
|
|
26734
|
+
"sourcegraph-cody",
|
|
26735
|
+
"amazon-q",
|
|
26736
|
+
"augment-code",
|
|
26737
|
+
"replit-agent",
|
|
26738
|
+
"bolt",
|
|
26739
|
+
"lovable",
|
|
26740
|
+
"tabby",
|
|
26741
|
+
"tabnine",
|
|
26742
|
+
"codegpt",
|
|
26743
|
+
"playcode-agent"
|
|
26386
26744
|
];
|
|
26387
26745
|
for (const agent of agents) {
|
|
26388
26746
|
if (agent !== sourceAgent) {
|
|
@@ -27371,10 +27729,37 @@ function evaluateSkillFile(filePath) {
|
|
|
27371
27729
|
return null;
|
|
27372
27730
|
}
|
|
27373
27731
|
}
|
|
27732
|
+
function checkNameDirectoryMatch(content, dirPath) {
|
|
27733
|
+
const frontmatter = extractFrontmatter4(content);
|
|
27734
|
+
if (!frontmatter || typeof frontmatter.name !== "string") return null;
|
|
27735
|
+
const dirName = basename17(dirPath);
|
|
27736
|
+
if (frontmatter.name !== dirName) {
|
|
27737
|
+
return `Skill name "${frontmatter.name}" does not match directory "${dirName}"`;
|
|
27738
|
+
}
|
|
27739
|
+
return null;
|
|
27740
|
+
}
|
|
27741
|
+
function checkTokenBudget(content) {
|
|
27742
|
+
const normalizedContent = content.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
27743
|
+
const fmMatch = normalizedContent.match(/^---\s*\n[\s\S]*?\n---\s*\n?/);
|
|
27744
|
+
const body = fmMatch ? normalizedContent.slice(fmMatch[0].length) : normalizedContent;
|
|
27745
|
+
const bodyLines = body.split("\n").length;
|
|
27746
|
+
if (bodyLines > 500) {
|
|
27747
|
+
return `Body is ${bodyLines} lines (exceeds 500). Consider moving content to references/ directory`;
|
|
27748
|
+
}
|
|
27749
|
+
return null;
|
|
27750
|
+
}
|
|
27374
27751
|
function evaluateSkillDirectory(dirPath) {
|
|
27375
27752
|
const skillMdPath = join42(dirPath, "SKILL.md");
|
|
27376
27753
|
if (existsSync41(skillMdPath)) {
|
|
27377
|
-
|
|
27754
|
+
const result = evaluateSkillFile(skillMdPath);
|
|
27755
|
+
if (result) {
|
|
27756
|
+
const content = readFileSync30(skillMdPath, "utf-8");
|
|
27757
|
+
const nameWarning = checkNameDirectoryMatch(content, dirPath);
|
|
27758
|
+
if (nameWarning) result.warnings.push(nameWarning);
|
|
27759
|
+
const budgetWarning = checkTokenBudget(content);
|
|
27760
|
+
if (budgetWarning) result.warnings.push(budgetWarning);
|
|
27761
|
+
}
|
|
27762
|
+
return result;
|
|
27378
27763
|
}
|
|
27379
27764
|
const mdcFiles = ["index.mdc", `${basename17(dirPath)}.mdc`];
|
|
27380
27765
|
for (const file of mdcFiles) {
|
|
@@ -32909,7 +33294,7 @@ var SkillScanner = class {
|
|
|
32909
33294
|
|
|
32910
33295
|
// src/scanner/reporter.ts
|
|
32911
33296
|
import { basename as basename21 } from "path";
|
|
32912
|
-
var SCANNER_VERSION = true ? "1.
|
|
33297
|
+
var SCANNER_VERSION = true ? "1.17.0" : "0.0.0";
|
|
32913
33298
|
var SEVERITY_COLORS = {
|
|
32914
33299
|
["critical" /* CRITICAL */]: "\x1B[91m",
|
|
32915
33300
|
["high" /* HIGH */]: "\x1B[31m",
|
|
@@ -33180,6 +33565,764 @@ function getThreatInfo(category) {
|
|
|
33180
33565
|
function getDefaultSeverity(category) {
|
|
33181
33566
|
return THREAT_TAXONOMY[category].defaultSeverity;
|
|
33182
33567
|
}
|
|
33568
|
+
|
|
33569
|
+
// src/validation/spec-validator.ts
|
|
33570
|
+
import { readFileSync as readFileSync38, existsSync as existsSync53 } from "fs";
|
|
33571
|
+
import { join as join54, basename as basename22 } from "path";
|
|
33572
|
+
var NAME_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
33573
|
+
var SPEC_VERSION = "1.0";
|
|
33574
|
+
var SpecValidator = class {
|
|
33575
|
+
validate(skillPath, options) {
|
|
33576
|
+
const checks = [];
|
|
33577
|
+
const errors = [];
|
|
33578
|
+
const warnings = [];
|
|
33579
|
+
const skillMdPath = skillPath.endsWith(".md") ? skillPath : join54(skillPath, "SKILL.md");
|
|
33580
|
+
if (!existsSync53(skillMdPath)) {
|
|
33581
|
+
errors.push(`SKILL.md not found at ${skillMdPath}`);
|
|
33582
|
+
return { valid: false, errors, warnings, specVersion: SPEC_VERSION, checks };
|
|
33583
|
+
}
|
|
33584
|
+
const raw = readFileSync38(skillMdPath, "utf-8");
|
|
33585
|
+
const { frontmatter, body } = stripFrontmatter(raw);
|
|
33586
|
+
const hasName = typeof frontmatter.name === "string" && frontmatter.name.length > 0;
|
|
33587
|
+
checks.push({
|
|
33588
|
+
name: "name-present",
|
|
33589
|
+
passed: hasName,
|
|
33590
|
+
message: hasName ? "Name field is present" : 'Missing required "name" field in frontmatter',
|
|
33591
|
+
severity: hasName ? "info" : "error"
|
|
33592
|
+
});
|
|
33593
|
+
if (!hasName) errors.push('Missing required "name" field in frontmatter');
|
|
33594
|
+
const hasDescription = typeof frontmatter.description === "string" && frontmatter.description.length > 0;
|
|
33595
|
+
checks.push({
|
|
33596
|
+
name: "description-present",
|
|
33597
|
+
passed: hasDescription,
|
|
33598
|
+
message: hasDescription ? "Description field is present" : 'Missing required "description" field in frontmatter',
|
|
33599
|
+
severity: hasDescription ? "info" : "error"
|
|
33600
|
+
});
|
|
33601
|
+
if (!hasDescription) errors.push('Missing required "description" field in frontmatter');
|
|
33602
|
+
if (hasName) {
|
|
33603
|
+
const nameStr = frontmatter.name;
|
|
33604
|
+
const nameValid = NAME_PATTERN.test(nameStr);
|
|
33605
|
+
checks.push({
|
|
33606
|
+
name: "name-format",
|
|
33607
|
+
passed: nameValid,
|
|
33608
|
+
message: nameValid ? "Name matches required pattern" : `Name "${nameStr}" does not match pattern: lowercase alphanumeric with hyphens`,
|
|
33609
|
+
severity: nameValid ? "info" : "error"
|
|
33610
|
+
});
|
|
33611
|
+
if (!nameValid) errors.push(`Name "${nameStr}" does not match pattern: lowercase alphanumeric with hyphens`);
|
|
33612
|
+
}
|
|
33613
|
+
if (options?.strict) {
|
|
33614
|
+
if (frontmatter.version !== void 0) {
|
|
33615
|
+
warnings.push("version should be under metadata.skillkit-version");
|
|
33616
|
+
checks.push({
|
|
33617
|
+
name: "version-placement",
|
|
33618
|
+
passed: false,
|
|
33619
|
+
message: "version should be under metadata.skillkit-version",
|
|
33620
|
+
severity: "warning"
|
|
33621
|
+
});
|
|
33622
|
+
}
|
|
33623
|
+
if (frontmatter.author !== void 0) {
|
|
33624
|
+
warnings.push("author should be under metadata.skillkit-author");
|
|
33625
|
+
checks.push({
|
|
33626
|
+
name: "author-placement",
|
|
33627
|
+
passed: false,
|
|
33628
|
+
message: "author should be under metadata.skillkit-author",
|
|
33629
|
+
severity: "warning"
|
|
33630
|
+
});
|
|
33631
|
+
}
|
|
33632
|
+
if (frontmatter.tags !== void 0) {
|
|
33633
|
+
warnings.push("tags should be under metadata.skillkit-tags");
|
|
33634
|
+
checks.push({
|
|
33635
|
+
name: "tags-placement",
|
|
33636
|
+
passed: false,
|
|
33637
|
+
message: "tags should be under metadata.skillkit-tags",
|
|
33638
|
+
severity: "warning"
|
|
33639
|
+
});
|
|
33640
|
+
}
|
|
33641
|
+
if (frontmatter.agents !== void 0) {
|
|
33642
|
+
warnings.push("agents should be under metadata.skillkit-agents");
|
|
33643
|
+
checks.push({
|
|
33644
|
+
name: "agents-placement",
|
|
33645
|
+
passed: false,
|
|
33646
|
+
message: "agents should be under metadata.skillkit-agents",
|
|
33647
|
+
severity: "warning"
|
|
33648
|
+
});
|
|
33649
|
+
}
|
|
33650
|
+
if (hasName) {
|
|
33651
|
+
const skillDir = skillPath.endsWith(".md") ? join54(skillPath, "..") : skillPath;
|
|
33652
|
+
const dirName = basename22(skillDir);
|
|
33653
|
+
const nameStr = frontmatter.name;
|
|
33654
|
+
const nameMatchesDir = nameStr === dirName;
|
|
33655
|
+
checks.push({
|
|
33656
|
+
name: "name-directory-match",
|
|
33657
|
+
passed: nameMatchesDir,
|
|
33658
|
+
message: nameMatchesDir ? "Name matches directory" : `Name "${nameStr}" does not match directory "${dirName}"`,
|
|
33659
|
+
severity: nameMatchesDir ? "info" : "warning"
|
|
33660
|
+
});
|
|
33661
|
+
if (!nameMatchesDir) warnings.push(`Name "${nameStr}" does not match directory "${dirName}"`);
|
|
33662
|
+
}
|
|
33663
|
+
const bodyLines = body.split("\n").length;
|
|
33664
|
+
const bodyWithinLimit = bodyLines <= 500;
|
|
33665
|
+
checks.push({
|
|
33666
|
+
name: "body-length",
|
|
33667
|
+
passed: bodyWithinLimit,
|
|
33668
|
+
message: bodyWithinLimit ? `Body is ${bodyLines} lines` : `Body is ${bodyLines} lines (exceeds 500). Consider moving content to references/ directory`,
|
|
33669
|
+
severity: bodyWithinLimit ? "info" : "warning"
|
|
33670
|
+
});
|
|
33671
|
+
if (!bodyWithinLimit) warnings.push(`Body is ${bodyLines} lines (exceeds 500). Consider moving content to references/ directory`);
|
|
33672
|
+
}
|
|
33673
|
+
return {
|
|
33674
|
+
valid: errors.length === 0,
|
|
33675
|
+
errors,
|
|
33676
|
+
warnings,
|
|
33677
|
+
specVersion: SPEC_VERSION,
|
|
33678
|
+
checks
|
|
33679
|
+
};
|
|
33680
|
+
}
|
|
33681
|
+
};
|
|
33682
|
+
|
|
33683
|
+
// src/agents-md/generator.ts
|
|
33684
|
+
import { existsSync as existsSync54, readFileSync as readFileSync39 } from "fs";
|
|
33685
|
+
import { join as join55 } from "path";
|
|
33686
|
+
function escapeTableCell(text) {
|
|
33687
|
+
return text.replace(/\|/g, "\\|").replace(/\n/g, " ");
|
|
33688
|
+
}
|
|
33689
|
+
var MANAGED_START = "<!-- skillkit:managed:start -->";
|
|
33690
|
+
var MANAGED_END = "<!-- skillkit:managed:end -->";
|
|
33691
|
+
var AgentsMdGenerator = class {
|
|
33692
|
+
config;
|
|
33693
|
+
detector;
|
|
33694
|
+
constructor(config) {
|
|
33695
|
+
this.config = config;
|
|
33696
|
+
this.detector = new ProjectDetector(config.projectPath);
|
|
33697
|
+
}
|
|
33698
|
+
generate() {
|
|
33699
|
+
this.detector.analyze();
|
|
33700
|
+
const sections = [];
|
|
33701
|
+
sections.push({
|
|
33702
|
+
id: "project-overview",
|
|
33703
|
+
title: "Project Overview",
|
|
33704
|
+
content: this.generateProjectSection(),
|
|
33705
|
+
managed: true
|
|
33706
|
+
});
|
|
33707
|
+
sections.push({
|
|
33708
|
+
id: "technology-stack",
|
|
33709
|
+
title: "Technology Stack",
|
|
33710
|
+
content: this.generateStackSection(),
|
|
33711
|
+
managed: true
|
|
33712
|
+
});
|
|
33713
|
+
if (this.config.includeSkills !== false) {
|
|
33714
|
+
const skillsContent = this.generateSkillsSection(findAllSkills([join55(this.config.projectPath, "skills")]));
|
|
33715
|
+
if (skillsContent) {
|
|
33716
|
+
sections.push({
|
|
33717
|
+
id: "installed-skills",
|
|
33718
|
+
title: "Installed Skills",
|
|
33719
|
+
content: skillsContent,
|
|
33720
|
+
managed: true
|
|
33721
|
+
});
|
|
33722
|
+
}
|
|
33723
|
+
}
|
|
33724
|
+
if (this.config.includeBuildCommands !== false) {
|
|
33725
|
+
const buildContent = this.generateBuildSection();
|
|
33726
|
+
if (buildContent) {
|
|
33727
|
+
sections.push({
|
|
33728
|
+
id: "build-test",
|
|
33729
|
+
title: "Build & Test",
|
|
33730
|
+
content: buildContent,
|
|
33731
|
+
managed: true
|
|
33732
|
+
});
|
|
33733
|
+
}
|
|
33734
|
+
}
|
|
33735
|
+
if (this.config.includeCodeStyle !== false) {
|
|
33736
|
+
const styleContent = this.generateCodeStyleSection();
|
|
33737
|
+
if (styleContent) {
|
|
33738
|
+
sections.push({
|
|
33739
|
+
id: "code-style",
|
|
33740
|
+
title: "Code Style",
|
|
33741
|
+
content: styleContent,
|
|
33742
|
+
managed: true
|
|
33743
|
+
});
|
|
33744
|
+
}
|
|
33745
|
+
}
|
|
33746
|
+
const lines = ["# AGENTS.md", "", MANAGED_START];
|
|
33747
|
+
for (const section of sections) {
|
|
33748
|
+
lines.push(`## ${section.title}`);
|
|
33749
|
+
lines.push(section.content);
|
|
33750
|
+
lines.push("");
|
|
33751
|
+
}
|
|
33752
|
+
lines.push(MANAGED_END, "");
|
|
33753
|
+
const content = lines.join("\n");
|
|
33754
|
+
return {
|
|
33755
|
+
content,
|
|
33756
|
+
sections,
|
|
33757
|
+
path: join55(this.config.projectPath, "AGENTS.md")
|
|
33758
|
+
};
|
|
33759
|
+
}
|
|
33760
|
+
generateSkillsSection(skills) {
|
|
33761
|
+
if (skills.length === 0) {
|
|
33762
|
+
return "";
|
|
33763
|
+
}
|
|
33764
|
+
const lines = [
|
|
33765
|
+
"| Skill | Description | Tags |",
|
|
33766
|
+
"|-------|-------------|------|"
|
|
33767
|
+
];
|
|
33768
|
+
for (const skill of skills) {
|
|
33769
|
+
const name = escapeTableCell(skill.name);
|
|
33770
|
+
const desc = escapeTableCell(skill.description);
|
|
33771
|
+
lines.push(`| ${name} | ${desc} | |`);
|
|
33772
|
+
}
|
|
33773
|
+
return lines.join("\n");
|
|
33774
|
+
}
|
|
33775
|
+
generateProjectSection() {
|
|
33776
|
+
const name = this.detector.getProjectName();
|
|
33777
|
+
const description = this.detector.getProjectDescription();
|
|
33778
|
+
const projectType = this.detector.detectProjectType();
|
|
33779
|
+
const lines = [];
|
|
33780
|
+
lines.push(`- **Name**: ${name}`);
|
|
33781
|
+
if (description) {
|
|
33782
|
+
lines.push(`- **Description**: ${description}`);
|
|
33783
|
+
}
|
|
33784
|
+
lines.push(`- **Type**: ${projectType}`);
|
|
33785
|
+
return lines.join("\n");
|
|
33786
|
+
}
|
|
33787
|
+
generateBuildSection() {
|
|
33788
|
+
const packageJsonPath = join55(this.config.projectPath, "package.json");
|
|
33789
|
+
if (!existsSync54(packageJsonPath)) {
|
|
33790
|
+
return "";
|
|
33791
|
+
}
|
|
33792
|
+
try {
|
|
33793
|
+
const pkg = JSON.parse(readFileSync39(packageJsonPath, "utf-8"));
|
|
33794
|
+
const scripts = pkg.scripts;
|
|
33795
|
+
if (!scripts || Object.keys(scripts).length === 0) {
|
|
33796
|
+
return "";
|
|
33797
|
+
}
|
|
33798
|
+
const relevantScripts = ["build", "dev", "start", "test", "lint", "format", "typecheck", "check"];
|
|
33799
|
+
const lines = ["```bash"];
|
|
33800
|
+
for (const key of relevantScripts) {
|
|
33801
|
+
if (scripts[key]) {
|
|
33802
|
+
lines.push(`# ${key}`);
|
|
33803
|
+
lines.push(scripts[key]);
|
|
33804
|
+
lines.push("");
|
|
33805
|
+
}
|
|
33806
|
+
}
|
|
33807
|
+
if (lines.length === 1) {
|
|
33808
|
+
return "";
|
|
33809
|
+
}
|
|
33810
|
+
lines.push("```");
|
|
33811
|
+
return lines.join("\n");
|
|
33812
|
+
} catch {
|
|
33813
|
+
return "";
|
|
33814
|
+
}
|
|
33815
|
+
}
|
|
33816
|
+
generateCodeStyleSection() {
|
|
33817
|
+
const patterns = this.detector.detectPatterns();
|
|
33818
|
+
const lines = [];
|
|
33819
|
+
if (patterns.linting) {
|
|
33820
|
+
lines.push(`- **Linting**: ${patterns.linting}`);
|
|
33821
|
+
}
|
|
33822
|
+
if (patterns.formatting) {
|
|
33823
|
+
lines.push(`- **Formatting**: ${patterns.formatting}`);
|
|
33824
|
+
}
|
|
33825
|
+
if (patterns.testing) {
|
|
33826
|
+
lines.push(`- **Testing**: ${patterns.testing}`);
|
|
33827
|
+
}
|
|
33828
|
+
if (patterns.styling) {
|
|
33829
|
+
lines.push(`- **Styling**: ${patterns.styling}`);
|
|
33830
|
+
}
|
|
33831
|
+
return lines.length > 0 ? lines.join("\n") : "";
|
|
33832
|
+
}
|
|
33833
|
+
generateStackSection() {
|
|
33834
|
+
const stack = this.detector.analyze();
|
|
33835
|
+
const lines = [];
|
|
33836
|
+
if (stack.languages.length > 0) {
|
|
33837
|
+
lines.push(`- **Languages**: ${stack.languages.map((l) => l.version ? `${l.name} ${l.version}` : l.name).join(", ")}`);
|
|
33838
|
+
}
|
|
33839
|
+
if (stack.frameworks.length > 0) {
|
|
33840
|
+
lines.push(`- **Frameworks**: ${stack.frameworks.map((f) => f.version ? `${f.name} ${f.version}` : f.name).join(", ")}`);
|
|
33841
|
+
}
|
|
33842
|
+
if (stack.libraries.length > 0) {
|
|
33843
|
+
lines.push(`- **Libraries**: ${stack.libraries.map((l) => l.name).join(", ")}`);
|
|
33844
|
+
}
|
|
33845
|
+
if (stack.databases.length > 0) {
|
|
33846
|
+
lines.push(`- **Databases**: ${stack.databases.map((d) => d.name).join(", ")}`);
|
|
33847
|
+
}
|
|
33848
|
+
if (stack.runtime.length > 0) {
|
|
33849
|
+
lines.push(`- **Runtime**: ${stack.runtime.map((r) => r.version ? `${r.name} ${r.version}` : r.name).join(", ")}`);
|
|
33850
|
+
}
|
|
33851
|
+
return lines.length > 0 ? lines.join("\n") : "No technology stack detected.";
|
|
33852
|
+
}
|
|
33853
|
+
};
|
|
33854
|
+
|
|
33855
|
+
// src/agents-md/parser.ts
|
|
33856
|
+
var MANAGED_START2 = "<!-- skillkit:managed:start -->";
|
|
33857
|
+
var MANAGED_END2 = "<!-- skillkit:managed:end -->";
|
|
33858
|
+
var AgentsMdParser = class {
|
|
33859
|
+
parse(content) {
|
|
33860
|
+
const sections = [];
|
|
33861
|
+
const lines = content.split("\n");
|
|
33862
|
+
let inManaged = false;
|
|
33863
|
+
let currentSection = null;
|
|
33864
|
+
for (const line of lines) {
|
|
33865
|
+
if (line.trim() === MANAGED_START2) {
|
|
33866
|
+
inManaged = true;
|
|
33867
|
+
continue;
|
|
33868
|
+
}
|
|
33869
|
+
if (line.trim() === MANAGED_END2) {
|
|
33870
|
+
if (currentSection) {
|
|
33871
|
+
sections.push({
|
|
33872
|
+
id: currentSection.id,
|
|
33873
|
+
title: currentSection.title,
|
|
33874
|
+
content: currentSection.lines.join("\n").trim(),
|
|
33875
|
+
managed: currentSection.managed
|
|
33876
|
+
});
|
|
33877
|
+
currentSection = null;
|
|
33878
|
+
}
|
|
33879
|
+
inManaged = false;
|
|
33880
|
+
continue;
|
|
33881
|
+
}
|
|
33882
|
+
const headingMatch = line.match(/^##\s+(.+)$/);
|
|
33883
|
+
if (headingMatch) {
|
|
33884
|
+
if (currentSection) {
|
|
33885
|
+
sections.push({
|
|
33886
|
+
id: currentSection.id,
|
|
33887
|
+
title: currentSection.title,
|
|
33888
|
+
content: currentSection.lines.join("\n").trim(),
|
|
33889
|
+
managed: currentSection.managed
|
|
33890
|
+
});
|
|
33891
|
+
}
|
|
33892
|
+
const title = headingMatch[1];
|
|
33893
|
+
currentSection = {
|
|
33894
|
+
id: title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, ""),
|
|
33895
|
+
title,
|
|
33896
|
+
lines: [],
|
|
33897
|
+
managed: inManaged
|
|
33898
|
+
};
|
|
33899
|
+
continue;
|
|
33900
|
+
}
|
|
33901
|
+
if (currentSection) {
|
|
33902
|
+
currentSection.lines.push(line);
|
|
33903
|
+
}
|
|
33904
|
+
}
|
|
33905
|
+
if (currentSection) {
|
|
33906
|
+
sections.push({
|
|
33907
|
+
id: currentSection.id,
|
|
33908
|
+
title: currentSection.title,
|
|
33909
|
+
content: currentSection.lines.join("\n").trim(),
|
|
33910
|
+
managed: currentSection.managed
|
|
33911
|
+
});
|
|
33912
|
+
}
|
|
33913
|
+
return sections;
|
|
33914
|
+
}
|
|
33915
|
+
hasManagedSections(content) {
|
|
33916
|
+
return content.includes(MANAGED_START2) && content.includes(MANAGED_END2);
|
|
33917
|
+
}
|
|
33918
|
+
updateManagedSections(existing, newManaged) {
|
|
33919
|
+
if (!this.hasManagedSections(existing)) {
|
|
33920
|
+
return existing;
|
|
33921
|
+
}
|
|
33922
|
+
const startIdx = existing.indexOf(MANAGED_START2);
|
|
33923
|
+
const endIdx = existing.indexOf(MANAGED_END2);
|
|
33924
|
+
if (startIdx >= endIdx) {
|
|
33925
|
+
return existing;
|
|
33926
|
+
}
|
|
33927
|
+
const managedBlock = this.buildManagedBlock(newManaged);
|
|
33928
|
+
const before = existing.substring(0, startIdx);
|
|
33929
|
+
const after = existing.substring(endIdx + MANAGED_END2.length);
|
|
33930
|
+
return `${before}${managedBlock}${after}`;
|
|
33931
|
+
}
|
|
33932
|
+
buildManagedBlock(sections) {
|
|
33933
|
+
const lines = [MANAGED_START2];
|
|
33934
|
+
for (const section of sections) {
|
|
33935
|
+
lines.push(`## ${section.title}`);
|
|
33936
|
+
lines.push(section.content);
|
|
33937
|
+
lines.push("");
|
|
33938
|
+
}
|
|
33939
|
+
lines.push(MANAGED_END2);
|
|
33940
|
+
return lines.join("\n");
|
|
33941
|
+
}
|
|
33942
|
+
};
|
|
33943
|
+
|
|
33944
|
+
// src/save/extractor.ts
|
|
33945
|
+
import { existsSync as existsSync55, readFileSync as readFileSync40 } from "fs";
|
|
33946
|
+
import { basename as basename23, extname as extname7 } from "path";
|
|
33947
|
+
import TurndownService from "turndown";
|
|
33948
|
+
var LANGUAGE_MAP = {
|
|
33949
|
+
".ts": "typescript",
|
|
33950
|
+
".tsx": "typescript",
|
|
33951
|
+
".js": "javascript",
|
|
33952
|
+
".jsx": "javascript",
|
|
33953
|
+
".py": "python",
|
|
33954
|
+
".rb": "ruby",
|
|
33955
|
+
".go": "go",
|
|
33956
|
+
".rs": "rust",
|
|
33957
|
+
".java": "java",
|
|
33958
|
+
".kt": "kotlin",
|
|
33959
|
+
".swift": "swift",
|
|
33960
|
+
".c": "c",
|
|
33961
|
+
".cpp": "cpp",
|
|
33962
|
+
".cs": "csharp",
|
|
33963
|
+
".php": "php",
|
|
33964
|
+
".sh": "shell",
|
|
33965
|
+
".bash": "shell",
|
|
33966
|
+
".zsh": "shell",
|
|
33967
|
+
".yml": "yaml",
|
|
33968
|
+
".yaml": "yaml",
|
|
33969
|
+
".json": "json",
|
|
33970
|
+
".toml": "toml",
|
|
33971
|
+
".md": "markdown",
|
|
33972
|
+
".mdx": "markdown",
|
|
33973
|
+
".html": "html",
|
|
33974
|
+
".css": "css",
|
|
33975
|
+
".scss": "scss",
|
|
33976
|
+
".sql": "sql",
|
|
33977
|
+
".r": "r",
|
|
33978
|
+
".lua": "lua",
|
|
33979
|
+
".dart": "dart",
|
|
33980
|
+
".ex": "elixir",
|
|
33981
|
+
".exs": "elixir",
|
|
33982
|
+
".zig": "zig",
|
|
33983
|
+
".nim": "nim",
|
|
33984
|
+
".vue": "vue",
|
|
33985
|
+
".svelte": "svelte"
|
|
33986
|
+
};
|
|
33987
|
+
var GITHUB_URL_PATTERN = /^https?:\/\/github\.com\/([^/]+)\/([^/]+)\/blob\/([^/]+)\/(.+)$/;
|
|
33988
|
+
var GITHUB_RAW_PATTERN = /^https?:\/\/raw\.githubusercontent\.com\//;
|
|
33989
|
+
var FETCH_TIMEOUT = 3e4;
|
|
33990
|
+
var ContentExtractor = class {
|
|
33991
|
+
turndown;
|
|
33992
|
+
constructor() {
|
|
33993
|
+
this.turndown = new TurndownService({
|
|
33994
|
+
headingStyle: "atx",
|
|
33995
|
+
codeBlockStyle: "fenced"
|
|
33996
|
+
});
|
|
33997
|
+
}
|
|
33998
|
+
async extractFromUrl(url, options) {
|
|
33999
|
+
if (this.isGitHubUrl(url)) {
|
|
34000
|
+
return this.fetchGitHubContent(url, options);
|
|
34001
|
+
}
|
|
34002
|
+
const response = await fetch(url, { signal: AbortSignal.timeout(FETCH_TIMEOUT) });
|
|
34003
|
+
if (!response.ok) {
|
|
34004
|
+
throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);
|
|
34005
|
+
}
|
|
34006
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
34007
|
+
const body = await response.text();
|
|
34008
|
+
if (contentType.includes("text/html")) {
|
|
34009
|
+
const { title: title2, content } = this.htmlToMarkdown(body, url);
|
|
34010
|
+
const finalContent2 = options?.maxLength ? content.slice(0, options.maxLength) : content;
|
|
34011
|
+
return {
|
|
34012
|
+
title: options?.preferredTitle ?? title2,
|
|
34013
|
+
content: finalContent2,
|
|
34014
|
+
sourceUrl: url,
|
|
34015
|
+
tags: [],
|
|
34016
|
+
extractedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
34017
|
+
contentType: "webpage",
|
|
34018
|
+
metadata: { url }
|
|
34019
|
+
};
|
|
34020
|
+
}
|
|
34021
|
+
const title = options?.preferredTitle ?? new URL(url).pathname.split("/").pop() ?? "Untitled";
|
|
34022
|
+
const finalContent = options?.maxLength ? body.slice(0, options.maxLength) : body;
|
|
34023
|
+
return {
|
|
34024
|
+
title,
|
|
34025
|
+
content: finalContent,
|
|
34026
|
+
sourceUrl: url,
|
|
34027
|
+
tags: [],
|
|
34028
|
+
extractedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
34029
|
+
contentType: "text",
|
|
34030
|
+
metadata: { url }
|
|
34031
|
+
};
|
|
34032
|
+
}
|
|
34033
|
+
extractFromText(text, options) {
|
|
34034
|
+
const firstLine = text.split("\n")[0]?.trim() ?? "";
|
|
34035
|
+
const title = options?.preferredTitle ?? (firstLine.length > 0 && firstLine.length <= 100 ? firstLine : "Untitled");
|
|
34036
|
+
const content = options?.maxLength ? text.slice(0, options.maxLength) : text;
|
|
34037
|
+
return {
|
|
34038
|
+
title,
|
|
34039
|
+
content,
|
|
34040
|
+
tags: [],
|
|
34041
|
+
extractedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
34042
|
+
contentType: "text",
|
|
34043
|
+
metadata: {}
|
|
34044
|
+
};
|
|
34045
|
+
}
|
|
34046
|
+
extractFromFile(filePath, options) {
|
|
34047
|
+
if (!existsSync55(filePath)) {
|
|
34048
|
+
throw new Error(`File not found: ${filePath}`);
|
|
34049
|
+
}
|
|
34050
|
+
const raw = readFileSync40(filePath, "utf-8");
|
|
34051
|
+
const name = basename23(filePath);
|
|
34052
|
+
const language = this.detectLanguage(name);
|
|
34053
|
+
const isCode = language !== void 0 && language !== "markdown";
|
|
34054
|
+
const title = options?.preferredTitle ?? name;
|
|
34055
|
+
const content = options?.maxLength ? raw.slice(0, options.maxLength) : raw;
|
|
34056
|
+
return {
|
|
34057
|
+
title,
|
|
34058
|
+
content: isCode ? `\`\`\`${language}
|
|
34059
|
+
${content}
|
|
34060
|
+
\`\`\`` : content,
|
|
34061
|
+
sourcePath: filePath,
|
|
34062
|
+
tags: language ? [language] : [],
|
|
34063
|
+
extractedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
34064
|
+
contentType: isCode ? "code" : "file",
|
|
34065
|
+
language,
|
|
34066
|
+
metadata: { filename: name }
|
|
34067
|
+
};
|
|
34068
|
+
}
|
|
34069
|
+
isGitHubUrl(url) {
|
|
34070
|
+
return GITHUB_URL_PATTERN.test(url) || GITHUB_RAW_PATTERN.test(url);
|
|
34071
|
+
}
|
|
34072
|
+
async fetchGitHubContent(url, options) {
|
|
34073
|
+
let rawUrl = url;
|
|
34074
|
+
const match = url.match(GITHUB_URL_PATTERN);
|
|
34075
|
+
if (match) {
|
|
34076
|
+
const [, owner, repo, branch, path4] = match;
|
|
34077
|
+
rawUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/${path4}`;
|
|
34078
|
+
}
|
|
34079
|
+
const response = await fetch(rawUrl, { signal: AbortSignal.timeout(FETCH_TIMEOUT) });
|
|
34080
|
+
if (!response.ok) {
|
|
34081
|
+
throw new Error(`Failed to fetch GitHub content: ${response.status} ${response.statusText}`);
|
|
34082
|
+
}
|
|
34083
|
+
const body = await response.text();
|
|
34084
|
+
const filename = rawUrl.split("/").pop() ?? "file";
|
|
34085
|
+
const language = this.detectLanguage(filename);
|
|
34086
|
+
const isCode = language !== void 0 && language !== "markdown";
|
|
34087
|
+
const title = options?.preferredTitle ?? filename;
|
|
34088
|
+
const content = options?.maxLength ? body.slice(0, options.maxLength) : body;
|
|
34089
|
+
return {
|
|
34090
|
+
title,
|
|
34091
|
+
content: isCode ? `\`\`\`${language}
|
|
34092
|
+
${content}
|
|
34093
|
+
\`\`\`` : content,
|
|
34094
|
+
sourceUrl: url,
|
|
34095
|
+
tags: language ? ["github", language] : ["github"],
|
|
34096
|
+
extractedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
34097
|
+
contentType: "github",
|
|
34098
|
+
language,
|
|
34099
|
+
metadata: {
|
|
34100
|
+
url,
|
|
34101
|
+
rawUrl,
|
|
34102
|
+
filename
|
|
34103
|
+
}
|
|
34104
|
+
};
|
|
34105
|
+
}
|
|
34106
|
+
htmlToMarkdown(html, url) {
|
|
34107
|
+
const titleMatch = html.match(/<title[^>]*>([^<]+)<\/title>/i);
|
|
34108
|
+
const title = titleMatch?.[1]?.trim() ?? new URL(url).hostname;
|
|
34109
|
+
const bodyMatch = html.match(/<body[^>]*>([\s\S]*)<\/body>/i);
|
|
34110
|
+
const bodyHtml = bodyMatch?.[1] ?? html;
|
|
34111
|
+
const content = this.turndown.turndown(bodyHtml);
|
|
34112
|
+
return { title, content };
|
|
34113
|
+
}
|
|
34114
|
+
detectLanguage(filename) {
|
|
34115
|
+
const ext = extname7(filename).toLowerCase();
|
|
34116
|
+
return LANGUAGE_MAP[ext];
|
|
34117
|
+
}
|
|
34118
|
+
};
|
|
34119
|
+
|
|
34120
|
+
// src/save/tagger.ts
|
|
34121
|
+
var TECH_KEYWORDS = /* @__PURE__ */ new Set([
|
|
34122
|
+
"react",
|
|
34123
|
+
"vue",
|
|
34124
|
+
"angular",
|
|
34125
|
+
"svelte",
|
|
34126
|
+
"nextjs",
|
|
34127
|
+
"nuxt",
|
|
34128
|
+
"remix",
|
|
34129
|
+
"typescript",
|
|
34130
|
+
"javascript",
|
|
34131
|
+
"python",
|
|
34132
|
+
"rust",
|
|
34133
|
+
"go",
|
|
34134
|
+
"java",
|
|
34135
|
+
"ruby",
|
|
34136
|
+
"node",
|
|
34137
|
+
"deno",
|
|
34138
|
+
"bun",
|
|
34139
|
+
"docker",
|
|
34140
|
+
"kubernetes",
|
|
34141
|
+
"terraform",
|
|
34142
|
+
"aws",
|
|
34143
|
+
"gcp",
|
|
34144
|
+
"azure",
|
|
34145
|
+
"vercel",
|
|
34146
|
+
"netlify",
|
|
34147
|
+
"cloudflare",
|
|
34148
|
+
"graphql",
|
|
34149
|
+
"rest",
|
|
34150
|
+
"grpc",
|
|
34151
|
+
"websocket",
|
|
34152
|
+
"redis",
|
|
34153
|
+
"postgres",
|
|
34154
|
+
"mongodb",
|
|
34155
|
+
"sqlite",
|
|
34156
|
+
"mysql",
|
|
34157
|
+
"prisma",
|
|
34158
|
+
"drizzle",
|
|
34159
|
+
"tailwind",
|
|
34160
|
+
"css",
|
|
34161
|
+
"html",
|
|
34162
|
+
"sass",
|
|
34163
|
+
"webpack",
|
|
34164
|
+
"vite",
|
|
34165
|
+
"esbuild",
|
|
34166
|
+
"git",
|
|
34167
|
+
"ci",
|
|
34168
|
+
"cd",
|
|
34169
|
+
"testing",
|
|
34170
|
+
"security",
|
|
34171
|
+
"authentication",
|
|
34172
|
+
"api",
|
|
34173
|
+
"cli",
|
|
34174
|
+
"sdk",
|
|
34175
|
+
"mcp",
|
|
34176
|
+
"llm",
|
|
34177
|
+
"ai",
|
|
34178
|
+
"ml",
|
|
34179
|
+
"openai",
|
|
34180
|
+
"anthropic"
|
|
34181
|
+
]);
|
|
34182
|
+
var TAG_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
34183
|
+
var AutoTagger = class {
|
|
34184
|
+
detectTags(content) {
|
|
34185
|
+
const tagCounts = /* @__PURE__ */ new Map();
|
|
34186
|
+
this.extractFromUrl(content.sourceUrl, tagCounts);
|
|
34187
|
+
this.extractFromHeadings(content.content, tagCounts);
|
|
34188
|
+
this.extractFromCodeBlocks(content.content, tagCounts);
|
|
34189
|
+
this.extractFromKeywords(content.content, tagCounts);
|
|
34190
|
+
if (content.language) {
|
|
34191
|
+
this.addTag(content.language.toLowerCase(), tagCounts, 3);
|
|
34192
|
+
}
|
|
34193
|
+
if (content.contentType !== "text") {
|
|
34194
|
+
this.addTag(content.contentType, tagCounts, 1);
|
|
34195
|
+
}
|
|
34196
|
+
return Array.from(tagCounts.entries()).sort((a, b) => b[1] - a[1]).slice(0, 10).map(([tag]) => tag);
|
|
34197
|
+
}
|
|
34198
|
+
extractFromUrl(url, counts) {
|
|
34199
|
+
if (!url) return;
|
|
34200
|
+
try {
|
|
34201
|
+
const parsed = new URL(url);
|
|
34202
|
+
const segments = parsed.pathname.split("/").filter(Boolean).map((s) => s.toLowerCase().replace(/[^a-z0-9-]/g, ""));
|
|
34203
|
+
for (const seg of segments) {
|
|
34204
|
+
if (seg.length >= 2 && seg.length <= 30 && TAG_PATTERN.test(seg)) {
|
|
34205
|
+
this.addTag(seg, counts, 2);
|
|
34206
|
+
}
|
|
34207
|
+
}
|
|
34208
|
+
} catch {
|
|
34209
|
+
}
|
|
34210
|
+
}
|
|
34211
|
+
extractFromHeadings(content, counts) {
|
|
34212
|
+
const headingRe = /^#{1,2}\s+(.+)$/gm;
|
|
34213
|
+
let match;
|
|
34214
|
+
while ((match = headingRe.exec(content)) !== null) {
|
|
34215
|
+
const words = match[1].toLowerCase().split(/\s+/);
|
|
34216
|
+
for (const word of words) {
|
|
34217
|
+
const cleaned = word.replace(/[^a-z0-9-]/g, "");
|
|
34218
|
+
if (cleaned.length >= 2 && TAG_PATTERN.test(cleaned)) {
|
|
34219
|
+
this.addTag(cleaned, counts, 2);
|
|
34220
|
+
}
|
|
34221
|
+
}
|
|
34222
|
+
}
|
|
34223
|
+
}
|
|
34224
|
+
extractFromCodeBlocks(content, counts) {
|
|
34225
|
+
const codeBlockRe = /^```(\w+)/gm;
|
|
34226
|
+
let match;
|
|
34227
|
+
while ((match = codeBlockRe.exec(content)) !== null) {
|
|
34228
|
+
const lang = match[1].toLowerCase();
|
|
34229
|
+
if (lang.length >= 2 && TAG_PATTERN.test(lang)) {
|
|
34230
|
+
this.addTag(lang, counts, 3);
|
|
34231
|
+
}
|
|
34232
|
+
}
|
|
34233
|
+
}
|
|
34234
|
+
extractFromKeywords(content, counts) {
|
|
34235
|
+
const lower = content.toLowerCase();
|
|
34236
|
+
for (const keyword of TECH_KEYWORDS) {
|
|
34237
|
+
const re = new RegExp(`\\b${keyword}\\b`, "i");
|
|
34238
|
+
if (re.test(lower)) {
|
|
34239
|
+
this.addTag(keyword, counts, 1);
|
|
34240
|
+
}
|
|
34241
|
+
}
|
|
34242
|
+
}
|
|
34243
|
+
addTag(tag, counts, weight) {
|
|
34244
|
+
if (!TAG_PATTERN.test(tag)) return;
|
|
34245
|
+
counts.set(tag, (counts.get(tag) ?? 0) + weight);
|
|
34246
|
+
}
|
|
34247
|
+
};
|
|
34248
|
+
|
|
34249
|
+
// src/save/skill-generator.ts
|
|
34250
|
+
import { mkdirSync as mkdirSync28, writeFileSync as writeFileSync28 } from "fs";
|
|
34251
|
+
import { join as join56 } from "path";
|
|
34252
|
+
import { homedir as homedir19 } from "os";
|
|
34253
|
+
var MAX_NAME_LENGTH = 64;
|
|
34254
|
+
var SUMMARY_LINE_LIMIT = 100;
|
|
34255
|
+
var SPLIT_THRESHOLD = 500;
|
|
34256
|
+
var DESCRIPTION_MAX = 200;
|
|
34257
|
+
var SkillGenerator = class {
|
|
34258
|
+
tagger = new AutoTagger();
|
|
34259
|
+
generate(content, options = {}) {
|
|
34260
|
+
const name = options.name ? this.slugify(options.name) : this.slugify(content.title || "untitled-skill");
|
|
34261
|
+
const tags = this.tagger.detectTags(content);
|
|
34262
|
+
const description = this.makeDescription(content.content);
|
|
34263
|
+
const source = content.sourceUrl ?? content.sourcePath ?? "";
|
|
34264
|
+
const frontmatter = this.buildFrontmatter(name, description, tags, source);
|
|
34265
|
+
const lines = content.content.split("\n");
|
|
34266
|
+
const needsSplit = lines.length > SPLIT_THRESHOLD;
|
|
34267
|
+
const body = needsSplit ? lines.slice(0, SUMMARY_LINE_LIMIT).join("\n") : content.content;
|
|
34268
|
+
const skillMd = `${frontmatter}
|
|
34269
|
+
${body}
|
|
34270
|
+
`;
|
|
34271
|
+
const outputDir = options.outputDir ?? this.defaultOutputDir(name, options.global);
|
|
34272
|
+
mkdirSync28(outputDir, { recursive: true });
|
|
34273
|
+
const skillPath = join56(outputDir, "SKILL.md");
|
|
34274
|
+
writeFileSync28(skillPath, skillMd, "utf-8");
|
|
34275
|
+
if (needsSplit) {
|
|
34276
|
+
const refsDir = join56(outputDir, "references");
|
|
34277
|
+
mkdirSync28(refsDir, { recursive: true });
|
|
34278
|
+
writeFileSync28(
|
|
34279
|
+
join56(refsDir, "full-content.md"),
|
|
34280
|
+
content.content,
|
|
34281
|
+
"utf-8"
|
|
34282
|
+
);
|
|
34283
|
+
}
|
|
34284
|
+
return { skillPath, skillMd, name };
|
|
34285
|
+
}
|
|
34286
|
+
slugify(input) {
|
|
34287
|
+
const slug = input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").replace(/-{2,}/g, "-");
|
|
34288
|
+
const trimmed = slug.slice(0, MAX_NAME_LENGTH).replace(/-+$/, "");
|
|
34289
|
+
return trimmed || "untitled-skill";
|
|
34290
|
+
}
|
|
34291
|
+
makeDescription(content) {
|
|
34292
|
+
const firstLine = content.split("\n").find((l) => l.trim().length > 0) ?? "";
|
|
34293
|
+
const cleaned = firstLine.replace(/^#+\s*/, "").trim();
|
|
34294
|
+
return cleaned.length > DESCRIPTION_MAX ? cleaned.slice(0, DESCRIPTION_MAX - 3) + "..." : cleaned || "Saved skill";
|
|
34295
|
+
}
|
|
34296
|
+
buildFrontmatter(name, description, tags, source) {
|
|
34297
|
+
const yamlTags = tags.map((t) => ` - ${t}`).join("\n");
|
|
34298
|
+
const savedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
34299
|
+
const lines = [
|
|
34300
|
+
"---",
|
|
34301
|
+
`name: ${name}`,
|
|
34302
|
+
`description: ${this.yamlEscape(description)}`,
|
|
34303
|
+
tags.length > 0 ? `tags:
|
|
34304
|
+
${yamlTags}` : null,
|
|
34305
|
+
"metadata:",
|
|
34306
|
+
source ? ` source: ${source}` : null,
|
|
34307
|
+
` savedAt: ${savedAt}`,
|
|
34308
|
+
"---"
|
|
34309
|
+
].filter((l) => l !== null);
|
|
34310
|
+
return lines.join("\n") + "\n";
|
|
34311
|
+
}
|
|
34312
|
+
yamlEscape(value) {
|
|
34313
|
+
const singleLine = value.replace(/\r?\n/g, " ").trim();
|
|
34314
|
+
if (/[:#{}[\],&*?|>!%@`]/.test(singleLine) || singleLine.startsWith("'") || singleLine.startsWith('"')) {
|
|
34315
|
+
return `"${singleLine.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
34316
|
+
}
|
|
34317
|
+
return singleLine;
|
|
34318
|
+
}
|
|
34319
|
+
defaultOutputDir(name, global) {
|
|
34320
|
+
if (global) {
|
|
34321
|
+
return join56(homedir19(), ".skillkit", "skills", name);
|
|
34322
|
+
}
|
|
34323
|
+
return join56(".skillkit", "skills", name);
|
|
34324
|
+
}
|
|
34325
|
+
};
|
|
33183
34326
|
export {
|
|
33184
34327
|
AGENT_CLI_CONFIGS,
|
|
33185
34328
|
AGENT_CONFIG,
|
|
@@ -33199,8 +34342,11 @@ export {
|
|
|
33199
34342
|
AgentOptimizer,
|
|
33200
34343
|
AgentPermissionMode,
|
|
33201
34344
|
AgentType,
|
|
34345
|
+
AgentsMdGenerator,
|
|
34346
|
+
AgentsMdParser,
|
|
33202
34347
|
AnthropicProvider,
|
|
33203
34348
|
AuditLogger,
|
|
34349
|
+
AutoTagger,
|
|
33204
34350
|
BUILTIN_PIPELINES,
|
|
33205
34351
|
BaseAIProvider,
|
|
33206
34352
|
BitbucketProvider,
|
|
@@ -33221,6 +34367,7 @@ export {
|
|
|
33221
34367
|
ConnectorConfigSchema,
|
|
33222
34368
|
ConnectorMappingSchema,
|
|
33223
34369
|
ConnectorPlaceholderSchema,
|
|
34370
|
+
ContentExtractor,
|
|
33224
34371
|
ContextEngine,
|
|
33225
34372
|
ContextLoader,
|
|
33226
34373
|
ContextManager,
|
|
@@ -33325,6 +34472,7 @@ export {
|
|
|
33325
34472
|
SkillComposer,
|
|
33326
34473
|
SkillExecutionEngine,
|
|
33327
34474
|
SkillFrontmatter,
|
|
34475
|
+
SkillGenerator,
|
|
33328
34476
|
SkillInjector,
|
|
33329
34477
|
SkillLocation,
|
|
33330
34478
|
SkillMdTranslator,
|
|
@@ -33337,6 +34485,7 @@ export {
|
|
|
33337
34485
|
SkillWizard,
|
|
33338
34486
|
SkillkitConfig,
|
|
33339
34487
|
SkillsSource,
|
|
34488
|
+
SpecValidator,
|
|
33340
34489
|
StaticAnalyzer,
|
|
33341
34490
|
TAG_TO_CATEGORY,
|
|
33342
34491
|
TAG_TO_TECH,
|