@codemcp/agentskills-core 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +19 -0
- package/dist/__tests__/package-config.test.d.ts +2 -0
- package/dist/__tests__/package-config.test.d.ts.map +1 -0
- package/dist/__tests__/package-config.test.js +251 -0
- package/dist/__tests__/package-config.test.js.map +1 -0
- package/dist/__tests__/parser.test.d.ts +2 -0
- package/dist/__tests__/parser.test.d.ts.map +1 -0
- package/dist/__tests__/parser.test.js +613 -0
- package/dist/__tests__/parser.test.js.map +1 -0
- package/dist/__tests__/registry.test.d.ts +2 -0
- package/dist/__tests__/registry.test.d.ts.map +1 -0
- package/dist/__tests__/registry.test.js +415 -0
- package/dist/__tests__/registry.test.js.map +1 -0
- package/dist/__tests__/skill-installer.test.d.ts +2 -0
- package/dist/__tests__/skill-installer.test.d.ts.map +1 -0
- package/dist/__tests__/skill-installer.test.js +229 -0
- package/dist/__tests__/skill-installer.test.js.map +1 -0
- package/dist/__tests__/validator.test.d.ts +2 -0
- package/dist/__tests__/validator.test.d.ts.map +1 -0
- package/dist/__tests__/validator.test.js +284 -0
- package/dist/__tests__/validator.test.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/installer.d.ts +89 -0
- package/dist/installer.d.ts.map +1 -0
- package/dist/installer.js +469 -0
- package/dist/installer.js.map +1 -0
- package/dist/package-config.d.ts +52 -0
- package/dist/package-config.d.ts.map +1 -0
- package/dist/package-config.js +267 -0
- package/dist/package-config.js.map +1 -0
- package/dist/parser.d.ts +59 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +154 -0
- package/dist/parser.js.map +1 -0
- package/dist/registry.d.ts +72 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +180 -0
- package/dist/registry.js.map +1 -0
- package/dist/types.d.ts +202 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/validator.d.ts +27 -0
- package/dist/validator.d.ts.map +1 -0
- package/dist/validator.js +165 -0
- package/dist/validator.js.map +1 -0
- package/package.json +56 -0
package/dist/registry.js
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SkillRegistry Component
|
|
3
|
+
*
|
|
4
|
+
* Responsibility: In-memory skill storage with Map-based O(1) lookups.
|
|
5
|
+
* Load skills from a single directory with strict fail-fast behavior.
|
|
6
|
+
*
|
|
7
|
+
* Expected structure: <skillsDir>/<skill-name>/SKILL.md (exactly 2 levels deep)
|
|
8
|
+
* Throws errors on any misconfiguration (no partial failures).
|
|
9
|
+
*/
|
|
10
|
+
import { promises as fs } from "fs";
|
|
11
|
+
import { join, basename } from "path";
|
|
12
|
+
import { parseSkill } from "./parser.js";
|
|
13
|
+
import { validateSkill } from "./validator.js";
|
|
14
|
+
/**
|
|
15
|
+
* In-memory registry for managing agent skills
|
|
16
|
+
*
|
|
17
|
+
* Features:
|
|
18
|
+
* - O(1) skill lookups using Map
|
|
19
|
+
* - Load skills from single directory (strict fail-fast)
|
|
20
|
+
* - Expected structure: <skillsDir>/<skill-name>/SKILL.md
|
|
21
|
+
* - Validates directory name matches skill name
|
|
22
|
+
* - Immutable skill objects
|
|
23
|
+
*/
|
|
24
|
+
export class SkillRegistry {
|
|
25
|
+
skills = new Map();
|
|
26
|
+
skillsDir = "";
|
|
27
|
+
lastLoaded;
|
|
28
|
+
/**
|
|
29
|
+
* Load skills from a single directory with strict error handling
|
|
30
|
+
*
|
|
31
|
+
* Expected structure: <skillsDir>/<skill-name>/SKILL.md (exactly 2 levels deep)
|
|
32
|
+
* - Throws on any error (fail fast)
|
|
33
|
+
* - Ignores hidden directories (.git/, etc.)
|
|
34
|
+
* - Ignores non-directory files
|
|
35
|
+
* - Validates directory name matches skill name in SKILL.md
|
|
36
|
+
*
|
|
37
|
+
* @param skillsDir - Directory containing skill subdirectories
|
|
38
|
+
* @returns Load result with count, directory, and timestamp
|
|
39
|
+
* @throws Error if directory doesn't exist, isn't a directory, or any skill is invalid
|
|
40
|
+
*/
|
|
41
|
+
async loadSkills(skillsDir) {
|
|
42
|
+
// Clear existing skills
|
|
43
|
+
this.skills.clear();
|
|
44
|
+
this.skillsDir = "";
|
|
45
|
+
// 1. Check if skillsDir exists
|
|
46
|
+
let stat;
|
|
47
|
+
try {
|
|
48
|
+
stat = await fs.stat(skillsDir);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
throw new Error(`Skills directory does not exist: ${skillsDir}`);
|
|
52
|
+
}
|
|
53
|
+
// 2. Check if it's a directory
|
|
54
|
+
if (!stat.isDirectory()) {
|
|
55
|
+
throw new Error(`Skills directory is not a directory: ${skillsDir}`);
|
|
56
|
+
}
|
|
57
|
+
// 3. Read immediate subdirectories (depth 1 only)
|
|
58
|
+
const entries = await fs.readdir(skillsDir, { withFileTypes: true });
|
|
59
|
+
let loadedCount = 0;
|
|
60
|
+
// 4. Process each subdirectory
|
|
61
|
+
for (const entry of entries) {
|
|
62
|
+
// Skip non-directories
|
|
63
|
+
if (!entry.isDirectory()) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
// Skip hidden directories
|
|
67
|
+
if (entry.name.startsWith(".")) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const skillDir = join(skillsDir, entry.name);
|
|
71
|
+
const skillPath = join(skillDir, "SKILL.md");
|
|
72
|
+
// Check for SKILL.md
|
|
73
|
+
let skillStat;
|
|
74
|
+
try {
|
|
75
|
+
skillStat = await fs.stat(skillPath);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
throw new Error(`Missing SKILL.md in: ${skillDir}`);
|
|
79
|
+
}
|
|
80
|
+
// Verify SKILL.md is a file
|
|
81
|
+
if (!skillStat.isFile()) {
|
|
82
|
+
throw new Error(`Missing SKILL.md in: ${skillDir}`);
|
|
83
|
+
}
|
|
84
|
+
// Parse SKILL.md
|
|
85
|
+
const parseResult = await parseSkill(skillPath);
|
|
86
|
+
if (!parseResult.success) {
|
|
87
|
+
throw new Error(`Failed to parse SKILL.md in ${skillDir}: ${parseResult.error.message}`);
|
|
88
|
+
}
|
|
89
|
+
const { skill } = parseResult;
|
|
90
|
+
// Validate the skill
|
|
91
|
+
const validationResult = validateSkill(skill);
|
|
92
|
+
if (!validationResult.valid) {
|
|
93
|
+
const errorMessages = validationResult.errors
|
|
94
|
+
.map((e) => e.message)
|
|
95
|
+
.join(", ");
|
|
96
|
+
throw new Error(`Validation failed for ${skillDir}: ${errorMessages}`);
|
|
97
|
+
}
|
|
98
|
+
// Verify directory name matches skill name
|
|
99
|
+
const dirName = basename(skillDir);
|
|
100
|
+
if (skill.metadata.name !== dirName) {
|
|
101
|
+
throw new Error(`Directory name '${dirName}' does not match skill name '${skill.metadata.name}' in ${skillPath}`);
|
|
102
|
+
}
|
|
103
|
+
// Store the skill
|
|
104
|
+
this.skills.set(skill.metadata.name, { skill, sourcePath: skillPath });
|
|
105
|
+
loadedCount++;
|
|
106
|
+
}
|
|
107
|
+
// Update state
|
|
108
|
+
this.skillsDir = skillsDir;
|
|
109
|
+
this.lastLoaded = new Date();
|
|
110
|
+
return {
|
|
111
|
+
loaded: loadedCount,
|
|
112
|
+
skillsDir: skillsDir,
|
|
113
|
+
timestamp: this.lastLoaded
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Get a skill by name
|
|
118
|
+
*
|
|
119
|
+
* @param name - The skill name
|
|
120
|
+
* @returns The skill or undefined if not found
|
|
121
|
+
*/
|
|
122
|
+
getSkill(name) {
|
|
123
|
+
const entry = this.skills.get(name);
|
|
124
|
+
if (!entry) {
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
// Return a deep copy to maintain immutability
|
|
128
|
+
return {
|
|
129
|
+
metadata: { ...entry.skill.metadata },
|
|
130
|
+
body: entry.skill.body
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Get all loaded skills
|
|
135
|
+
*
|
|
136
|
+
* @returns Array of all skills
|
|
137
|
+
*/
|
|
138
|
+
getAllSkills() {
|
|
139
|
+
return Array.from(this.skills.values()).map((entry) => ({
|
|
140
|
+
metadata: { ...entry.skill.metadata },
|
|
141
|
+
body: entry.skill.body
|
|
142
|
+
}));
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Get skill metadata without body content
|
|
146
|
+
*
|
|
147
|
+
* @param name - The skill name
|
|
148
|
+
* @returns The skill metadata or undefined if not found
|
|
149
|
+
*/
|
|
150
|
+
getSkillMetadata(name) {
|
|
151
|
+
const entry = this.skills.get(name);
|
|
152
|
+
if (!entry) {
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
return { ...entry.skill.metadata };
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Get all skill metadata without body content
|
|
159
|
+
*
|
|
160
|
+
* @returns Array of all skill metadata
|
|
161
|
+
*/
|
|
162
|
+
getAllMetadata() {
|
|
163
|
+
return Array.from(this.skills.values()).map((entry) => ({
|
|
164
|
+
...entry.skill.metadata
|
|
165
|
+
}));
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Get current registry state
|
|
169
|
+
*
|
|
170
|
+
* @returns Current state with counts and source info
|
|
171
|
+
*/
|
|
172
|
+
getState() {
|
|
173
|
+
return {
|
|
174
|
+
skillCount: this.skills.size,
|
|
175
|
+
skillsDir: this.skillsDir,
|
|
176
|
+
lastLoaded: this.lastLoaded
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for Agent Skills Parser
|
|
3
|
+
*
|
|
4
|
+
* These types define the structure of parsed Agent Skills following
|
|
5
|
+
* the Agent Skills standard and Claude Code extensions.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Metadata extracted from skill YAML frontmatter
|
|
9
|
+
*/
|
|
10
|
+
export interface SkillMetadata {
|
|
11
|
+
name: string;
|
|
12
|
+
description: string;
|
|
13
|
+
license?: string;
|
|
14
|
+
compatibility?: string;
|
|
15
|
+
metadata?: Record<string, unknown>;
|
|
16
|
+
allowedTools?: string[];
|
|
17
|
+
disableModelInvocation?: boolean;
|
|
18
|
+
userInvocable?: boolean;
|
|
19
|
+
argumentHint?: string;
|
|
20
|
+
context?: string;
|
|
21
|
+
agent?: string;
|
|
22
|
+
model?: string;
|
|
23
|
+
hooks?: Record<string, string>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Parsed skill with metadata and body content
|
|
27
|
+
*/
|
|
28
|
+
export interface Skill {
|
|
29
|
+
metadata: SkillMetadata;
|
|
30
|
+
body: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Error codes for parsing failures
|
|
34
|
+
*/
|
|
35
|
+
export type ParseErrorCode = "EMPTY_FILE" | "MISSING_FRONTMATTER" | "INVALID_YAML" | "MISSING_REQUIRED_FIELD" | "FILE_NOT_FOUND" | "FILE_READ_ERROR";
|
|
36
|
+
/**
|
|
37
|
+
* Error information for parsing failures
|
|
38
|
+
*/
|
|
39
|
+
export interface ParseError {
|
|
40
|
+
code: ParseErrorCode;
|
|
41
|
+
message: string;
|
|
42
|
+
field?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Successful parse result
|
|
46
|
+
*/
|
|
47
|
+
export interface ParseSuccess {
|
|
48
|
+
success: true;
|
|
49
|
+
skill: Skill;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Failed parse result
|
|
53
|
+
*/
|
|
54
|
+
export interface ParseFailure {
|
|
55
|
+
success: false;
|
|
56
|
+
error: ParseError;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Result of parsing a skill (discriminated union)
|
|
60
|
+
*/
|
|
61
|
+
export type ParseResult = ParseSuccess | ParseFailure;
|
|
62
|
+
/**
|
|
63
|
+
* Error codes for validation failures
|
|
64
|
+
*/
|
|
65
|
+
export type ValidationErrorCode = "MISSING_FIELD" | "INVALID_NAME_LENGTH" | "INVALID_NAME_FORMAT" | "INVALID_DESCRIPTION_LENGTH" | "INVALID_COMPATIBILITY_LENGTH" | "INVALID_FIELD_TYPE";
|
|
66
|
+
/**
|
|
67
|
+
* Warning codes for non-blocking validation issues
|
|
68
|
+
*/
|
|
69
|
+
export type ValidationWarningCode = "MISSING_RECOMMENDED_FIELD" | "SHORT_DESCRIPTION" | "LONG_CONTENT";
|
|
70
|
+
/**
|
|
71
|
+
* Validation error information
|
|
72
|
+
*/
|
|
73
|
+
export interface ValidationError {
|
|
74
|
+
code: ValidationErrorCode;
|
|
75
|
+
message: string;
|
|
76
|
+
field?: string;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Validation warning information
|
|
80
|
+
*/
|
|
81
|
+
export interface ValidationWarning {
|
|
82
|
+
code: ValidationWarningCode;
|
|
83
|
+
message: string;
|
|
84
|
+
field?: string;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Result of validating a skill
|
|
88
|
+
*/
|
|
89
|
+
export interface ValidationResult {
|
|
90
|
+
valid: boolean;
|
|
91
|
+
errors: ValidationError[];
|
|
92
|
+
warnings: ValidationWarning[];
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Result of loading skills into registry
|
|
96
|
+
*
|
|
97
|
+
* Note: Loading is strict - any error throws exception.
|
|
98
|
+
* No partial failures allowed (fail fast on misconfiguration).
|
|
99
|
+
*/
|
|
100
|
+
export interface LoadResult {
|
|
101
|
+
loaded: number;
|
|
102
|
+
skillsDir: string;
|
|
103
|
+
timestamp: Date;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Current state of the registry
|
|
107
|
+
*/
|
|
108
|
+
export interface RegistryState {
|
|
109
|
+
skillCount: number;
|
|
110
|
+
skillsDir: string;
|
|
111
|
+
lastLoaded?: Date;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Error codes for installation failures
|
|
115
|
+
*/
|
|
116
|
+
export type InstallErrorCode = "INVALID_SPEC" | "INSTALL_FAILED" | "NETWORK_ERROR" | "MISSING_SKILL_MD" | "INVALID_SKILL_FORMAT" | "PERMISSION_ERROR";
|
|
117
|
+
/**
|
|
118
|
+
* Error information for installation failures
|
|
119
|
+
*/
|
|
120
|
+
export interface InstallError {
|
|
121
|
+
code: InstallErrorCode;
|
|
122
|
+
message: string;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Skill manifest extracted from installed package
|
|
126
|
+
*/
|
|
127
|
+
export interface SkillManifest {
|
|
128
|
+
name: string;
|
|
129
|
+
description: string;
|
|
130
|
+
license?: string;
|
|
131
|
+
compatibility?: string;
|
|
132
|
+
packageName?: string;
|
|
133
|
+
version?: string;
|
|
134
|
+
metadata?: Record<string, unknown>;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Successful installation result
|
|
138
|
+
*/
|
|
139
|
+
export interface InstallSuccess {
|
|
140
|
+
success: true;
|
|
141
|
+
name: string;
|
|
142
|
+
spec: string;
|
|
143
|
+
resolvedVersion: string;
|
|
144
|
+
integrity: string;
|
|
145
|
+
installPath: string;
|
|
146
|
+
manifest?: SkillManifest;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Failed installation result
|
|
150
|
+
*/
|
|
151
|
+
export interface InstallFailure {
|
|
152
|
+
success: false;
|
|
153
|
+
name?: string;
|
|
154
|
+
spec?: string;
|
|
155
|
+
error?: InstallError;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Result of installing a single skill (discriminated union)
|
|
159
|
+
*/
|
|
160
|
+
export type InstallResult = InstallSuccess | InstallFailure;
|
|
161
|
+
/**
|
|
162
|
+
* Result of installing multiple skills
|
|
163
|
+
*/
|
|
164
|
+
export interface InstallAllResult {
|
|
165
|
+
success: boolean;
|
|
166
|
+
installed: Set<string>;
|
|
167
|
+
failed: Set<string>;
|
|
168
|
+
results: Record<string, InstallResult>;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Lock file entry for a single skill
|
|
172
|
+
*/
|
|
173
|
+
export interface SkillLockEntry {
|
|
174
|
+
spec: string;
|
|
175
|
+
resolvedVersion: string;
|
|
176
|
+
integrity: string;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Lock file structure for reproducible installations
|
|
180
|
+
*/
|
|
181
|
+
export interface SkillLockFile {
|
|
182
|
+
version: string;
|
|
183
|
+
generated: string;
|
|
184
|
+
skills: Record<string, SkillLockEntry>;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Package configuration for agent skills
|
|
188
|
+
*/
|
|
189
|
+
export interface PackageConfig {
|
|
190
|
+
skills: Record<string, string>;
|
|
191
|
+
config: {
|
|
192
|
+
skillsDirectory: string;
|
|
193
|
+
autoDiscover: string[];
|
|
194
|
+
maxSkillSize: number;
|
|
195
|
+
logLevel: "error" | "warn" | "info" | "debug";
|
|
196
|
+
};
|
|
197
|
+
source: {
|
|
198
|
+
type: "file" | "defaults";
|
|
199
|
+
path?: string;
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill Validator
|
|
3
|
+
*
|
|
4
|
+
* Validates Agent Skills format against specification.
|
|
5
|
+
* This is a stub implementation - tests define the expected behavior.
|
|
6
|
+
*
|
|
7
|
+
* Implementation to be completed following TDD approach.
|
|
8
|
+
*/
|
|
9
|
+
import type { Skill, ValidationResult } from "./types.js";
|
|
10
|
+
/**
|
|
11
|
+
* Validate a skill against Agent Skills specification
|
|
12
|
+
*
|
|
13
|
+
* Validates:
|
|
14
|
+
* - Required fields: name (1-64 chars, lowercase-hyphens), description (1-1024 chars)
|
|
15
|
+
* - Optional fields: license, compatibility (1-500 chars), metadata, allowedTools
|
|
16
|
+
* - Name format: lowercase letters, numbers, hyphens only, no leading/trailing/consecutive hyphens
|
|
17
|
+
*
|
|
18
|
+
* Returns ValidationResult with:
|
|
19
|
+
* - valid: boolean indicating if skill passes validation
|
|
20
|
+
* - errors: array of blocking validation errors
|
|
21
|
+
* - warnings: array of non-blocking issues
|
|
22
|
+
*
|
|
23
|
+
* @param skill - The skill to validate
|
|
24
|
+
* @returns ValidationResult with validation status, errors, and warnings
|
|
25
|
+
*/
|
|
26
|
+
export declare function validateSkill(skill: Skill): ValidationResult;
|
|
27
|
+
//# sourceMappingURL=validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE1D;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,gBAAgB,CA8J5D"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill Validator
|
|
3
|
+
*
|
|
4
|
+
* Validates Agent Skills format against specification.
|
|
5
|
+
* This is a stub implementation - tests define the expected behavior.
|
|
6
|
+
*
|
|
7
|
+
* Implementation to be completed following TDD approach.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Validate a skill against Agent Skills specification
|
|
11
|
+
*
|
|
12
|
+
* Validates:
|
|
13
|
+
* - Required fields: name (1-64 chars, lowercase-hyphens), description (1-1024 chars)
|
|
14
|
+
* - Optional fields: license, compatibility (1-500 chars), metadata, allowedTools
|
|
15
|
+
* - Name format: lowercase letters, numbers, hyphens only, no leading/trailing/consecutive hyphens
|
|
16
|
+
*
|
|
17
|
+
* Returns ValidationResult with:
|
|
18
|
+
* - valid: boolean indicating if skill passes validation
|
|
19
|
+
* - errors: array of blocking validation errors
|
|
20
|
+
* - warnings: array of non-blocking issues
|
|
21
|
+
*
|
|
22
|
+
* @param skill - The skill to validate
|
|
23
|
+
* @returns ValidationResult with validation status, errors, and warnings
|
|
24
|
+
*/
|
|
25
|
+
export function validateSkill(skill) {
|
|
26
|
+
const errors = [];
|
|
27
|
+
const warnings = [];
|
|
28
|
+
// Extract metadata for validation
|
|
29
|
+
const { name, description, compatibility, metadata, allowedTools, license } = skill.metadata;
|
|
30
|
+
// Validate name - required field
|
|
31
|
+
if (name === undefined || name === null) {
|
|
32
|
+
errors.push({
|
|
33
|
+
code: "MISSING_FIELD",
|
|
34
|
+
field: "name",
|
|
35
|
+
message: "Field 'name' is required"
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
const trimmedName = name.trim();
|
|
40
|
+
// Check name length (after trimming)
|
|
41
|
+
if (trimmedName.length < 1 || trimmedName.length > 64) {
|
|
42
|
+
errors.push({
|
|
43
|
+
code: "INVALID_NAME_LENGTH",
|
|
44
|
+
field: "name",
|
|
45
|
+
message: "Name must be between 1 and 64 characters"
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
// Check name format if not empty
|
|
49
|
+
if (trimmedName.length > 0) {
|
|
50
|
+
// Check for leading hyphen
|
|
51
|
+
if (trimmedName.startsWith("-")) {
|
|
52
|
+
errors.push({
|
|
53
|
+
code: "INVALID_NAME_FORMAT",
|
|
54
|
+
field: "name",
|
|
55
|
+
message: "Name must not start with a leading hyphen"
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
// Check for trailing hyphen
|
|
59
|
+
if (trimmedName.endsWith("-")) {
|
|
60
|
+
errors.push({
|
|
61
|
+
code: "INVALID_NAME_FORMAT",
|
|
62
|
+
field: "name",
|
|
63
|
+
message: "Name must not end with a trailing hyphen"
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
// Check for consecutive hyphens
|
|
67
|
+
if (trimmedName.includes("--")) {
|
|
68
|
+
errors.push({
|
|
69
|
+
code: "INVALID_NAME_FORMAT",
|
|
70
|
+
field: "name",
|
|
71
|
+
message: "Name must not contain consecutive hyphens"
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
// Check for valid characters (lowercase letters, numbers, hyphens only)
|
|
75
|
+
const validNamePattern = /^[a-z0-9-]+$/;
|
|
76
|
+
if (!validNamePattern.test(trimmedName)) {
|
|
77
|
+
errors.push({
|
|
78
|
+
code: "INVALID_NAME_FORMAT",
|
|
79
|
+
field: "name",
|
|
80
|
+
message: "Name must contain only lowercase letters, numbers, and hyphens"
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Validate description - required field
|
|
86
|
+
if (description === undefined || description === null) {
|
|
87
|
+
errors.push({
|
|
88
|
+
code: "MISSING_FIELD",
|
|
89
|
+
field: "description",
|
|
90
|
+
message: "Field 'description' is required"
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
const trimmedDescription = description.trim();
|
|
95
|
+
// Check description length (after trimming)
|
|
96
|
+
if (trimmedDescription.length < 1 || trimmedDescription.length > 1024) {
|
|
97
|
+
errors.push({
|
|
98
|
+
code: "INVALID_DESCRIPTION_LENGTH",
|
|
99
|
+
field: "description",
|
|
100
|
+
message: "Description must be between 1 and 1024 characters"
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
// Warning: short description
|
|
104
|
+
if (trimmedDescription.length > 0 && trimmedDescription.length < 50) {
|
|
105
|
+
warnings.push({
|
|
106
|
+
code: "SHORT_DESCRIPTION",
|
|
107
|
+
field: "description",
|
|
108
|
+
message: "Description should be at least 50 characters for clarity"
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Validate compatibility - optional field
|
|
113
|
+
if (compatibility !== undefined) {
|
|
114
|
+
if (compatibility.length > 500) {
|
|
115
|
+
errors.push({
|
|
116
|
+
code: "INVALID_COMPATIBILITY_LENGTH",
|
|
117
|
+
field: "compatibility",
|
|
118
|
+
message: "Compatibility must not exceed 500 characters"
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Validate metadata - optional field, must be object if present
|
|
123
|
+
if (metadata !== undefined) {
|
|
124
|
+
if (metadata === null ||
|
|
125
|
+
Array.isArray(metadata) ||
|
|
126
|
+
typeof metadata !== "object") {
|
|
127
|
+
errors.push({
|
|
128
|
+
code: "INVALID_FIELD_TYPE",
|
|
129
|
+
field: "metadata",
|
|
130
|
+
message: "Metadata must be an object"
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// Validate allowedTools - optional field, must be array if present
|
|
135
|
+
if (allowedTools !== undefined) {
|
|
136
|
+
if (allowedTools === null || !Array.isArray(allowedTools)) {
|
|
137
|
+
errors.push({
|
|
138
|
+
code: "INVALID_FIELD_TYPE",
|
|
139
|
+
field: "allowedTools",
|
|
140
|
+
message: "AllowedTools must be an array"
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// Warning: missing license (recommended field)
|
|
145
|
+
if (license === undefined) {
|
|
146
|
+
warnings.push({
|
|
147
|
+
code: "MISSING_RECOMMENDED_FIELD",
|
|
148
|
+
field: "license",
|
|
149
|
+
message: "License field is recommended for skills"
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
// Warning: long body content (> 20000 chars ≈ 5000 tokens)
|
|
153
|
+
if (skill.body && skill.body.length > 20000) {
|
|
154
|
+
warnings.push({
|
|
155
|
+
code: "LONG_CONTENT",
|
|
156
|
+
message: "Body content exceeds 5000 tokens estimate, which may impact performance"
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
valid: errors.length === 0,
|
|
161
|
+
errors,
|
|
162
|
+
warnings
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@codemcp/agentskills-core",
|
|
3
|
+
"version": "0.0.4",
|
|
4
|
+
"description": "Core functionality for Agent Skills parsing, validation, and discovery",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"gray-matter": "4.0.3",
|
|
19
|
+
"js-yaml": "^4.1.0",
|
|
20
|
+
"pacote": "21.3.1"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/js-yaml": "^4.0.9",
|
|
24
|
+
"@types/node": "^22.10.7",
|
|
25
|
+
"@types/pacote": "11.1.8",
|
|
26
|
+
"@typescript-eslint/eslint-plugin": "^8.21.0",
|
|
27
|
+
"@typescript-eslint/parser": "^8.21.0",
|
|
28
|
+
"eslint": "^9.18.0",
|
|
29
|
+
"eslint-config-prettier": "^10.0.1",
|
|
30
|
+
"prettier": "^3.4.2",
|
|
31
|
+
"rimraf": "^6.0.1",
|
|
32
|
+
"typescript": "^5.7.3",
|
|
33
|
+
"typescript-eslint": "8.21.0",
|
|
34
|
+
"vitest": "^3.0.3"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"agentskills",
|
|
38
|
+
"skills",
|
|
39
|
+
"parser",
|
|
40
|
+
"validator"
|
|
41
|
+
],
|
|
42
|
+
"author": "Oliver Jägle <github@beimir.net>",
|
|
43
|
+
"license": "MIT",
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "tsc -p tsconfig.build.json",
|
|
46
|
+
"dev": "tsc -p tsconfig.build.json --watch",
|
|
47
|
+
"clean:build": "rimraf dist",
|
|
48
|
+
"lint": "eslint .",
|
|
49
|
+
"lint:fix": "eslint . --fix",
|
|
50
|
+
"format": "prettier --check .",
|
|
51
|
+
"format:fix": "prettier --write .",
|
|
52
|
+
"test": "vitest run",
|
|
53
|
+
"test:watch": "vitest",
|
|
54
|
+
"typecheck": "tsc --noEmit"
|
|
55
|
+
}
|
|
56
|
+
}
|