@codemcp/agentskills-core 1.3.1 → 1.4.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 +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/skill-frontmatter.schema.json +175 -0
- package/dist/types.d.ts +1 -13
- package/dist/types.d.ts.map +1 -1
- package/dist/validator.d.ts +0 -24
- package/dist/validator.d.ts.map +1 -1
- package/dist/validator.js +15 -354
- package/dist/validator.js.map +1 -1
- package/package.json +2 -1
- package/dist/__tests__/validator.test.d.ts +0 -2
- package/dist/__tests__/validator.test.d.ts.map +0 -1
- package/dist/__tests__/validator.test.js +0 -660
- package/dist/__tests__/validator.test.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { Skill, SkillMetadata, ParseResult, ParseSuccess, ParseFailure, ParseError, ParseErrorCode, ValidationResult, ValidationError, ValidationWarning,
|
|
1
|
+
export type { Skill, SkillMetadata, ParseResult, ParseSuccess, ParseFailure, ParseError, ParseErrorCode, ValidationResult, ValidationError, ValidationWarning, LoadResult, RegistryState, InstallResult, InstallSuccess, InstallFailure, InstallAllResult, InstallError, InstallErrorCode, SkillManifest, SkillLockFile, SkillLockEntry, PackageConfig, McpClientType, McpConfig, McpServerConfig, McpServerDependency, McpParameterSpec, McpDependencyCheckResult, McpDependencyInfo, ParameterValues } from "./types.js";
|
|
2
2
|
export { parseSkill, parseSkillContent } from "./parser.js";
|
|
3
3
|
export { validateSkill } from "./validator.js";
|
|
4
4
|
export { SkillRegistry } from "./registry.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,KAAK,EACL,aAAa,EACb,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,KAAK,EACL,aAAa,EACb,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,cAAc,EACd,aAAa,EACb,aAAa,EACb,SAAS,EACT,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,wBAAwB,EACxB,iBAAiB,EACjB,eAAe,EAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAkCA,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://mrsimpson.github.io/agentskills-mcp/skill-frontmatter-schema.json",
|
|
4
|
+
"title": "Agent Skill Frontmatter",
|
|
5
|
+
"description": "YAML frontmatter schema for Agent Skills (SKILL.md files). See https://mrsimpson.github.io/agentskills-mcp/reference/skill-format for full documentation.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["name", "description"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"name": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "Unique skill identifier. Lowercase letters, numbers, and hyphens only. No leading/trailing/consecutive hyphens.",
|
|
13
|
+
"minLength": 1,
|
|
14
|
+
"maxLength": 64,
|
|
15
|
+
"allOf": [
|
|
16
|
+
{ "pattern": "^[a-z0-9]([a-z0-9-]*[a-z0-9])?$" },
|
|
17
|
+
{ "not": { "pattern": "--" } }
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"description": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "Short summary of the skill shown in tool descriptions.",
|
|
23
|
+
"minLength": 1,
|
|
24
|
+
"maxLength": 1024
|
|
25
|
+
},
|
|
26
|
+
"license": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"description": "SPDX license identifier (e.g. MIT, Apache-2.0). Recommended for published skills."
|
|
29
|
+
},
|
|
30
|
+
"compatibility": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"description": "Agent compatibility string.",
|
|
33
|
+
"maxLength": 500
|
|
34
|
+
},
|
|
35
|
+
"metadata": {
|
|
36
|
+
"type": "object",
|
|
37
|
+
"description": "Arbitrary key-value metadata.",
|
|
38
|
+
"additionalProperties": true
|
|
39
|
+
},
|
|
40
|
+
"allowedTools": {
|
|
41
|
+
"type": "array",
|
|
42
|
+
"description": "Tools this skill is permitted to use.",
|
|
43
|
+
"items": {
|
|
44
|
+
"type": "string"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"disableModelInvocation": {
|
|
48
|
+
"type": "boolean",
|
|
49
|
+
"description": "If true, the skill is excluded from the use_skill tool enum and cannot be invoked via MCP."
|
|
50
|
+
},
|
|
51
|
+
"userInvocable": {
|
|
52
|
+
"type": "boolean",
|
|
53
|
+
"description": "If true, the skill is designed for direct user invocation (e.g. via /skill-name)."
|
|
54
|
+
},
|
|
55
|
+
"argumentHint": {
|
|
56
|
+
"type": "string",
|
|
57
|
+
"description": "Hint shown to users about expected arguments, e.g. \"<pr-url>\" or \"<target> [options]\"."
|
|
58
|
+
},
|
|
59
|
+
"context": {
|
|
60
|
+
"type": "string",
|
|
61
|
+
"description": "Execution context hint for the agent."
|
|
62
|
+
},
|
|
63
|
+
"agent": {
|
|
64
|
+
"type": "string",
|
|
65
|
+
"description": "Target agent identifier this skill is optimized for."
|
|
66
|
+
},
|
|
67
|
+
"model": {
|
|
68
|
+
"type": "string",
|
|
69
|
+
"description": "Preferred model for executing this skill."
|
|
70
|
+
},
|
|
71
|
+
"hooks": {
|
|
72
|
+
"type": "object",
|
|
73
|
+
"description": "Lifecycle hook definitions keyed by hook name.",
|
|
74
|
+
"additionalProperties": {
|
|
75
|
+
"type": "string"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"requiresMcpServers": {
|
|
79
|
+
"type": "array",
|
|
80
|
+
"description": "MCP servers that must be configured for this skill to work. Used by 'agentskills install --agent' for validation and auto-configuration.",
|
|
81
|
+
"items": {
|
|
82
|
+
"$ref": "#/$defs/McpServerDependency"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"$defs": {
|
|
87
|
+
"McpServerDependency": {
|
|
88
|
+
"type": "object",
|
|
89
|
+
"description": "An MCP server that this skill depends on.",
|
|
90
|
+
"required": ["name", "description", "command"],
|
|
91
|
+
"additionalProperties": false,
|
|
92
|
+
"properties": {
|
|
93
|
+
"name": {
|
|
94
|
+
"type": "string",
|
|
95
|
+
"description": "Server identifier. Lowercase letters, numbers, and hyphens. Must start and end with alphanumeric.",
|
|
96
|
+
"allOf": [
|
|
97
|
+
{ "pattern": "^[a-z0-9][a-z0-9-]*[a-z0-9]$" },
|
|
98
|
+
{ "not": { "pattern": "--" } }
|
|
99
|
+
]
|
|
100
|
+
},
|
|
101
|
+
"package": {
|
|
102
|
+
"type": "string",
|
|
103
|
+
"description": "npm package name used for auto-installation (e.g. \"@modelcontextprotocol/server-filesystem\")."
|
|
104
|
+
},
|
|
105
|
+
"description": {
|
|
106
|
+
"type": "string",
|
|
107
|
+
"description": "Why this MCP server is needed by the skill."
|
|
108
|
+
},
|
|
109
|
+
"command": {
|
|
110
|
+
"type": "string",
|
|
111
|
+
"description": "Executable to run (e.g. \"npx\", \"node\", \"/usr/local/bin/my-server\")."
|
|
112
|
+
},
|
|
113
|
+
"args": {
|
|
114
|
+
"type": "array",
|
|
115
|
+
"description": "Arguments passed to the command. May contain {{PARAM_NAME}} placeholders resolved at install time.",
|
|
116
|
+
"items": {
|
|
117
|
+
"type": "string"
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
"env": {
|
|
121
|
+
"type": "object",
|
|
122
|
+
"description": "Environment variables to set when running the server.",
|
|
123
|
+
"additionalProperties": {
|
|
124
|
+
"type": "string"
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"cwd": {
|
|
128
|
+
"type": "string",
|
|
129
|
+
"description": "Working directory for the server process."
|
|
130
|
+
},
|
|
131
|
+
"parameters": {
|
|
132
|
+
"type": "object",
|
|
133
|
+
"description": "Parameter definitions for {{PARAM}} placeholders used in args or env.",
|
|
134
|
+
"propertyNames": {
|
|
135
|
+
"allOf": [
|
|
136
|
+
{ "pattern": "^[a-z0-9][a-z0-9-]*[a-z0-9]$" },
|
|
137
|
+
{ "not": { "pattern": "--" } }
|
|
138
|
+
]
|
|
139
|
+
},
|
|
140
|
+
"additionalProperties": {
|
|
141
|
+
"$ref": "#/$defs/McpParameterSpec"
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
"McpParameterSpec": {
|
|
147
|
+
"type": "object",
|
|
148
|
+
"description": "Definition of a parameter placeholder used in an MCP server dependency.",
|
|
149
|
+
"required": ["description", "required"],
|
|
150
|
+
"additionalProperties": false,
|
|
151
|
+
"properties": {
|
|
152
|
+
"description": {
|
|
153
|
+
"type": "string",
|
|
154
|
+
"description": "What this parameter configures."
|
|
155
|
+
},
|
|
156
|
+
"required": {
|
|
157
|
+
"type": "boolean",
|
|
158
|
+
"description": "Whether the user must supply this parameter."
|
|
159
|
+
},
|
|
160
|
+
"sensitive": {
|
|
161
|
+
"type": "boolean",
|
|
162
|
+
"description": "If true, treat as a secret or credential (mask in output, do not log)."
|
|
163
|
+
},
|
|
164
|
+
"default": {
|
|
165
|
+
"type": "string",
|
|
166
|
+
"description": "Default value used when the parameter is not supplied."
|
|
167
|
+
},
|
|
168
|
+
"example": {
|
|
169
|
+
"type": "string",
|
|
170
|
+
"description": "Example value shown to guide users."
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -60,29 +60,17 @@ export interface ParseFailure {
|
|
|
60
60
|
* Result of parsing a skill (discriminated union)
|
|
61
61
|
*/
|
|
62
62
|
export type ParseResult = ParseSuccess | ParseFailure;
|
|
63
|
-
/**
|
|
64
|
-
* Error codes for validation failures
|
|
65
|
-
*/
|
|
66
|
-
export type ValidationErrorCode = "MISSING_FIELD" | "INVALID_NAME_LENGTH" | "INVALID_NAME_FORMAT" | "INVALID_DESCRIPTION_LENGTH" | "INVALID_COMPATIBILITY_LENGTH" | "INVALID_FIELD_TYPE";
|
|
67
|
-
/**
|
|
68
|
-
* Warning codes for non-blocking validation issues
|
|
69
|
-
*/
|
|
70
|
-
export type ValidationWarningCode = "MISSING_RECOMMENDED_FIELD" | "SHORT_DESCRIPTION" | "LONG_CONTENT";
|
|
71
63
|
/**
|
|
72
64
|
* Validation error information
|
|
73
65
|
*/
|
|
74
66
|
export interface ValidationError {
|
|
75
|
-
code: ValidationErrorCode;
|
|
76
67
|
message: string;
|
|
77
|
-
field?: string;
|
|
78
68
|
}
|
|
79
69
|
/**
|
|
80
|
-
* Validation warning information
|
|
70
|
+
* Validation warning information (reserved for future use)
|
|
81
71
|
*/
|
|
82
72
|
export interface ValidationWarning {
|
|
83
|
-
code: ValidationWarningCode;
|
|
84
73
|
message: string;
|
|
85
|
-
field?: string;
|
|
86
74
|
}
|
|
87
75
|
/**
|
|
88
76
|
* Result of validating a skill
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,WAAW,aAAa;IAE5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IAGpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAGxB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAG/B,kBAAkB,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,WAAW,KAAK;IACpB,QAAQ,EAAE,aAAa,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,YAAY,GACZ,qBAAqB,GACrB,cAAc,GACd,wBAAwB,GACxB,gBAAgB,GAChB,iBAAiB,CAAC;AAEtB;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,IAAI,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE,UAAU,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,YAAY,CAAC;AAEtD;;GAEG;AACH,MAAM,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/validator.d.ts
CHANGED
|
@@ -1,27 +1,3 @@
|
|
|
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
1
|
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
2
|
export declare function validateSkill(skill: Skill): ValidationResult;
|
|
27
3
|
//# sourceMappingURL=validator.d.ts.map
|
package/dist/validator.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAW1D,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,gBAAgB,CAW5D"}
|
package/dist/validator.js
CHANGED
|
@@ -1,359 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
*/
|
|
1
|
+
import Ajv from "ajv";
|
|
2
|
+
import schema from "./skill-frontmatter.schema.json" with { type: "json" };
|
|
3
|
+
// AJV v8 lacks an exports field, so moduleResolution:NodeNext sees the full CJS
|
|
4
|
+
// module namespace rather than the default export — cast once at construction.
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
|
+
const ajv = new Ajv({ validateSchema: false });
|
|
7
|
+
const validateFrontmatter = ajv.compile(schema);
|
|
25
8
|
export function validateSkill(skill) {
|
|
26
|
-
const
|
|
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
|
-
// Validate requiresMcpServers - optional field
|
|
160
|
-
if (skill.metadata.requiresMcpServers !== undefined) {
|
|
161
|
-
const mcpServers = skill.metadata.requiresMcpServers;
|
|
162
|
-
// Must be an array
|
|
163
|
-
if (!Array.isArray(mcpServers)) {
|
|
164
|
-
errors.push({
|
|
165
|
-
code: "INVALID_FIELD_TYPE",
|
|
166
|
-
field: "requiresMcpServers",
|
|
167
|
-
message: "RequiresMcpServers must be an array"
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
else {
|
|
171
|
-
// Validate each server in the array
|
|
172
|
-
mcpServers.forEach((server, index) => {
|
|
173
|
-
const serverPrefix = `requiresMcpServers[${index}]`;
|
|
174
|
-
// Check if server is an object
|
|
175
|
-
if (!server || typeof server !== "object" || Array.isArray(server)) {
|
|
176
|
-
errors.push({
|
|
177
|
-
code: "INVALID_FIELD_TYPE",
|
|
178
|
-
field: serverPrefix,
|
|
179
|
-
message: `Server at index ${index} must be an object`
|
|
180
|
-
});
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
// Validate required fields: name, command, description
|
|
184
|
-
if (!server.name) {
|
|
185
|
-
errors.push({
|
|
186
|
-
code: "MISSING_FIELD",
|
|
187
|
-
field: `${serverPrefix}.name`,
|
|
188
|
-
message: "Server name is required"
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
else if (typeof server.name === "string") {
|
|
192
|
-
// Validate server name format (lowercase-hyphens, no leading/trailing/consecutive hyphens)
|
|
193
|
-
const hasConsecutiveHyphens = server.name.includes("--");
|
|
194
|
-
const serverNamePattern = /^[a-z0-9][a-z0-9-]*[a-z0-9]$/;
|
|
195
|
-
if (hasConsecutiveHyphens || !serverNamePattern.test(server.name)) {
|
|
196
|
-
errors.push({
|
|
197
|
-
code: "INVALID_NAME_FORMAT",
|
|
198
|
-
field: `${serverPrefix}.name`,
|
|
199
|
-
message: "Server name must contain only lowercase letters, numbers, and hyphens; must start and end with alphanumeric; no consecutive hyphens"
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
if (!server.command) {
|
|
204
|
-
errors.push({
|
|
205
|
-
code: "MISSING_FIELD",
|
|
206
|
-
field: `${serverPrefix}.command`,
|
|
207
|
-
message: "Server command is required"
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
if (!server.description) {
|
|
211
|
-
errors.push({
|
|
212
|
-
code: "MISSING_FIELD",
|
|
213
|
-
field: `${serverPrefix}.description`,
|
|
214
|
-
message: "Server description is required"
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
// Validate optional fields
|
|
218
|
-
if (server.args !== undefined) {
|
|
219
|
-
if (!Array.isArray(server.args)) {
|
|
220
|
-
errors.push({
|
|
221
|
-
code: "INVALID_FIELD_TYPE",
|
|
222
|
-
field: `${serverPrefix}.args`,
|
|
223
|
-
message: "Server args must be an array"
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
if (server.env !== undefined) {
|
|
228
|
-
if (!server.env ||
|
|
229
|
-
typeof server.env !== "object" ||
|
|
230
|
-
Array.isArray(server.env)) {
|
|
231
|
-
errors.push({
|
|
232
|
-
code: "INVALID_FIELD_TYPE",
|
|
233
|
-
field: `${serverPrefix}.env`,
|
|
234
|
-
message: "Server env must be an object"
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
if (server.parameters !== undefined) {
|
|
239
|
-
if (!server.parameters ||
|
|
240
|
-
typeof server.parameters !== "object" ||
|
|
241
|
-
Array.isArray(server.parameters)) {
|
|
242
|
-
errors.push({
|
|
243
|
-
code: "INVALID_FIELD_TYPE",
|
|
244
|
-
field: `${serverPrefix}.parameters`,
|
|
245
|
-
message: "Server parameters must be an object"
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
else {
|
|
249
|
-
// Validate each parameter
|
|
250
|
-
Object.entries(server.parameters).forEach(([paramName, paramSpec]) => {
|
|
251
|
-
const paramPrefix = `${serverPrefix}.parameters.${paramName}`;
|
|
252
|
-
// Validate parameter name format (lowercase-hyphens, no consecutive hyphens)
|
|
253
|
-
const hasConsecutiveHyphens = paramName.includes("--");
|
|
254
|
-
const paramNamePattern = /^[a-z0-9][a-z0-9-]*[a-z0-9]$/;
|
|
255
|
-
if (hasConsecutiveHyphens ||
|
|
256
|
-
!paramNamePattern.test(paramName)) {
|
|
257
|
-
errors.push({
|
|
258
|
-
code: "INVALID_NAME_FORMAT",
|
|
259
|
-
field: paramPrefix,
|
|
260
|
-
message: "Parameter name must contain only lowercase letters, numbers, and hyphens; must start and end with alphanumeric; no consecutive hyphens"
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
// Validate parameter spec
|
|
264
|
-
if (!paramSpec || typeof paramSpec !== "object") {
|
|
265
|
-
errors.push({
|
|
266
|
-
code: "INVALID_FIELD_TYPE",
|
|
267
|
-
field: paramPrefix,
|
|
268
|
-
message: "Parameter spec must be an object"
|
|
269
|
-
});
|
|
270
|
-
return;
|
|
271
|
-
}
|
|
272
|
-
// Required fields: description, required
|
|
273
|
-
if (paramSpec.description === undefined) {
|
|
274
|
-
errors.push({
|
|
275
|
-
code: "MISSING_FIELD",
|
|
276
|
-
field: `${paramPrefix}.description`,
|
|
277
|
-
message: "Parameter description is required"
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
if (paramSpec.required === undefined) {
|
|
281
|
-
errors.push({
|
|
282
|
-
code: "MISSING_FIELD",
|
|
283
|
-
field: `${paramPrefix}.required`,
|
|
284
|
-
message: "Parameter required field is required"
|
|
285
|
-
});
|
|
286
|
-
}
|
|
287
|
-
// Validate optional fields
|
|
288
|
-
if (paramSpec.default !== undefined &&
|
|
289
|
-
typeof paramSpec.default !== "string") {
|
|
290
|
-
errors.push({
|
|
291
|
-
code: "INVALID_FIELD_TYPE",
|
|
292
|
-
field: `${paramPrefix}.default`,
|
|
293
|
-
message: "Parameter default must be a string"
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
if (paramSpec.example !== undefined &&
|
|
297
|
-
typeof paramSpec.example !== "string") {
|
|
298
|
-
errors.push({
|
|
299
|
-
code: "INVALID_FIELD_TYPE",
|
|
300
|
-
field: `${paramPrefix}.example`,
|
|
301
|
-
message: "Parameter example must be a string"
|
|
302
|
-
});
|
|
303
|
-
}
|
|
304
|
-
if (paramSpec.sensitive !== undefined &&
|
|
305
|
-
typeof paramSpec.sensitive !== "boolean") {
|
|
306
|
-
errors.push({
|
|
307
|
-
code: "INVALID_FIELD_TYPE",
|
|
308
|
-
field: `${paramPrefix}.sensitive`,
|
|
309
|
-
message: "Parameter sensitive must be a boolean"
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
// Check for additional properties
|
|
313
|
-
const allowedKeys = [
|
|
314
|
-
"description",
|
|
315
|
-
"required",
|
|
316
|
-
"default",
|
|
317
|
-
"example",
|
|
318
|
-
"sensitive"
|
|
319
|
-
];
|
|
320
|
-
const extraKeys = Object.keys(paramSpec).filter((key) => !allowedKeys.includes(key));
|
|
321
|
-
if (extraKeys.length > 0) {
|
|
322
|
-
errors.push({
|
|
323
|
-
code: "INVALID_FIELD_TYPE",
|
|
324
|
-
field: paramPrefix,
|
|
325
|
-
message: `Parameter has unexpected fields: ${extraKeys.join(", ")}`
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
});
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
// Check for additional properties on server
|
|
332
|
-
const allowedServerKeys = [
|
|
333
|
-
"name",
|
|
334
|
-
"package",
|
|
335
|
-
"description",
|
|
336
|
-
"command",
|
|
337
|
-
"args",
|
|
338
|
-
"env",
|
|
339
|
-
"cwd",
|
|
340
|
-
"parameters"
|
|
341
|
-
];
|
|
342
|
-
const extraServerKeys = Object.keys(server).filter((key) => !allowedServerKeys.includes(key));
|
|
343
|
-
if (extraServerKeys.length > 0) {
|
|
344
|
-
errors.push({
|
|
345
|
-
code: "INVALID_FIELD_TYPE",
|
|
346
|
-
field: serverPrefix,
|
|
347
|
-
message: `Server has unexpected fields: ${extraServerKeys.join(", ")}`
|
|
348
|
-
});
|
|
349
|
-
}
|
|
350
|
-
});
|
|
351
|
-
}
|
|
352
|
-
}
|
|
9
|
+
const valid = validateFrontmatter(skill.metadata);
|
|
353
10
|
return {
|
|
354
|
-
valid
|
|
355
|
-
errors
|
|
356
|
-
|
|
11
|
+
valid,
|
|
12
|
+
errors: valid
|
|
13
|
+
? []
|
|
14
|
+
: (validateFrontmatter.errors ?? []).map((e) => ({
|
|
15
|
+
message: e.message ?? "Validation error"
|
|
16
|
+
})),
|
|
17
|
+
warnings: []
|
|
357
18
|
};
|
|
358
19
|
}
|
|
359
20
|
//# sourceMappingURL=validator.js.map
|