asterscanner 1.0.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/README.md +242 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/patterns.d.ts +18 -0
- package/dist/patterns.d.ts.map +1 -0
- package/dist/patterns.js +314 -0
- package/dist/patterns.js.map +1 -0
- package/dist/scanner.d.ts +46 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +160 -0
- package/dist/scanner.js.map +1 -0
- package/dist/scoring.d.ts +30 -0
- package/dist/scoring.d.ts.map +1 -0
- package/dist/scoring.js +62 -0
- package/dist/scoring.js.map +1 -0
- package/dist/skill-schema.d.ts +456 -0
- package/dist/skill-schema.d.ts.map +1 -0
- package/dist/skill-schema.js +531 -0
- package/dist/skill-schema.js.map +1 -0
- package/dist/skill-tester.d.ts +119 -0
- package/dist/skill-tester.d.ts.map +1 -0
- package/dist/skill-tester.js +334 -0
- package/dist/skill-tester.js.map +1 -0
- package/dist/types.d.ts +93 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill Schema Types
|
|
3
|
+
*
|
|
4
|
+
* This schema aligns with the official Agent Skills specification.
|
|
5
|
+
* See: https://agentskills.io/specification
|
|
6
|
+
*
|
|
7
|
+
* Key principles:
|
|
8
|
+
* - Skills are DIRECTORIES, not single files
|
|
9
|
+
* - Only `name` and `description` are required per spec
|
|
10
|
+
* - Optional fields: license, compatibility, metadata, allowed-tools
|
|
11
|
+
* - Skills can include executable scripts
|
|
12
|
+
* - Progressive disclosure: content loads in stages
|
|
13
|
+
*/
|
|
14
|
+
// Regex that enforces: lowercase alphanumeric, single hyphens only, no leading/trailing hyphens
|
|
15
|
+
const NAME_REGEX = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
16
|
+
/**
|
|
17
|
+
* Validate name according to official Agent Skills specification
|
|
18
|
+
* @param name - The skill name to validate
|
|
19
|
+
* @param directoryName - Optional parent directory name to check against
|
|
20
|
+
*/
|
|
21
|
+
export function validateAnthropicName(name, directoryName) {
|
|
22
|
+
if (!name) {
|
|
23
|
+
return { valid: false, error: "Name is required" };
|
|
24
|
+
}
|
|
25
|
+
if (name.length > 64) {
|
|
26
|
+
return { valid: false, error: "Name must be 64 characters or less" };
|
|
27
|
+
}
|
|
28
|
+
if (!NAME_REGEX.test(name)) {
|
|
29
|
+
return {
|
|
30
|
+
valid: false,
|
|
31
|
+
error: "Name must be lowercase alphanumeric with single hyphens (no leading/trailing/consecutive hyphens)",
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
// ask-specific: block reserved words
|
|
35
|
+
// These are reserved to prevent impersonation of official entities
|
|
36
|
+
const RESERVED_WORDS = [
|
|
37
|
+
// AI companies (prevent impersonation)
|
|
38
|
+
"anthropic",
|
|
39
|
+
"claude",
|
|
40
|
+
"openai",
|
|
41
|
+
"chatgpt",
|
|
42
|
+
"google",
|
|
43
|
+
"gemini",
|
|
44
|
+
"microsoft",
|
|
45
|
+
"copilot",
|
|
46
|
+
"github",
|
|
47
|
+
"vercel",
|
|
48
|
+
"aws",
|
|
49
|
+
"amazon",
|
|
50
|
+
// Platform reserved words
|
|
51
|
+
"admin",
|
|
52
|
+
"system",
|
|
53
|
+
"official",
|
|
54
|
+
"verified",
|
|
55
|
+
"askskills",
|
|
56
|
+
"agentskills",
|
|
57
|
+
// Security-sensitive
|
|
58
|
+
"root",
|
|
59
|
+
"sudo",
|
|
60
|
+
"shell",
|
|
61
|
+
];
|
|
62
|
+
for (const reserved of RESERVED_WORDS) {
|
|
63
|
+
if (name.includes(reserved)) {
|
|
64
|
+
return {
|
|
65
|
+
valid: false,
|
|
66
|
+
error: `Name cannot contain "${reserved}" - this word is reserved to prevent impersonation (ask registry rule)`,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// ask-specific: block XML tags
|
|
71
|
+
if (/<[^>]+>/.test(name)) {
|
|
72
|
+
return { valid: false, error: "Name cannot contain XML tags (ask registry rule)" };
|
|
73
|
+
}
|
|
74
|
+
// Validate directory name match if provided
|
|
75
|
+
if (directoryName && name !== directoryName) {
|
|
76
|
+
return {
|
|
77
|
+
valid: false,
|
|
78
|
+
error: `Name "${name}" must match parent directory name "${directoryName}"`,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return { valid: true };
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Validate compatibility field per spec (max 500 chars)
|
|
85
|
+
*/
|
|
86
|
+
export function validateCompatibility(compatibility) {
|
|
87
|
+
if (compatibility && compatibility.length > 500) {
|
|
88
|
+
return { valid: false, error: "Compatibility must be 500 characters or less" };
|
|
89
|
+
}
|
|
90
|
+
return { valid: true };
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Validate description according to Anthropic's constraints
|
|
94
|
+
*/
|
|
95
|
+
export function validateAnthropicDescription(description) {
|
|
96
|
+
if (!description || description.trim().length === 0) {
|
|
97
|
+
return { valid: false, error: "Description is required and must be non-empty" };
|
|
98
|
+
}
|
|
99
|
+
if (description.length > 1024) {
|
|
100
|
+
return { valid: false, error: "Description must be 1024 characters or less" };
|
|
101
|
+
}
|
|
102
|
+
if (/<[^>]+>/.test(description)) {
|
|
103
|
+
return { valid: false, error: "Description cannot contain XML tags" };
|
|
104
|
+
}
|
|
105
|
+
return { valid: true };
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Validate a skill manifest
|
|
109
|
+
*
|
|
110
|
+
* Per Anthropic spec, only `name` and `description` are required.
|
|
111
|
+
* All other fields are ask extensions and are optional.
|
|
112
|
+
*/
|
|
113
|
+
export function validateManifest(manifest) {
|
|
114
|
+
const errors = [];
|
|
115
|
+
const warnings = [];
|
|
116
|
+
let anthropicCompatible = true;
|
|
117
|
+
// Anthropic required fields
|
|
118
|
+
const nameValidation = validateAnthropicName(manifest.name || "");
|
|
119
|
+
if (!nameValidation.valid) {
|
|
120
|
+
errors.push(nameValidation.error);
|
|
121
|
+
anthropicCompatible = false;
|
|
122
|
+
}
|
|
123
|
+
const descValidation = validateAnthropicDescription(manifest.description || "");
|
|
124
|
+
if (!descValidation.valid) {
|
|
125
|
+
errors.push(descValidation.error);
|
|
126
|
+
anthropicCompatible = false;
|
|
127
|
+
}
|
|
128
|
+
// Check for ask extensions
|
|
129
|
+
const hasAskExtensions = !!(manifest.version ||
|
|
130
|
+
manifest.author ||
|
|
131
|
+
manifest.keywords?.length ||
|
|
132
|
+
manifest.categories?.length ||
|
|
133
|
+
manifest.contract ||
|
|
134
|
+
manifest.capabilities?.length ||
|
|
135
|
+
manifest.tests ||
|
|
136
|
+
manifest.execution ||
|
|
137
|
+
manifest.pricing);
|
|
138
|
+
// Warnings for missing recommended fields (not errors!)
|
|
139
|
+
if (!manifest.version) {
|
|
140
|
+
warnings.push("Consider adding 'version' for better skill management (ask extension)");
|
|
141
|
+
}
|
|
142
|
+
if (manifest.description && manifest.description.length < 50) {
|
|
143
|
+
warnings.push("Description is short. Consider describing both WHAT the skill does and WHEN to use it.");
|
|
144
|
+
}
|
|
145
|
+
// Contract validation (optional but if present, should be valid)
|
|
146
|
+
if (manifest.contract) {
|
|
147
|
+
if (manifest.contract.inputs) {
|
|
148
|
+
for (const input of manifest.contract.inputs) {
|
|
149
|
+
if (!input.name)
|
|
150
|
+
errors.push("Contract input missing name");
|
|
151
|
+
if (!input.type)
|
|
152
|
+
errors.push(`Contract input ${input.name} missing type`);
|
|
153
|
+
if (!input.description)
|
|
154
|
+
warnings.push(`Contract input ${input.name} missing description`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (manifest.contract.outputs) {
|
|
158
|
+
for (const output of manifest.contract.outputs) {
|
|
159
|
+
if (!output.name)
|
|
160
|
+
errors.push("Contract output missing name");
|
|
161
|
+
if (!output.type)
|
|
162
|
+
errors.push(`Contract output ${output.name} missing type`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// Capability validation (optional)
|
|
167
|
+
if (manifest.capabilities) {
|
|
168
|
+
const validCapabilities = new Set([
|
|
169
|
+
"file:read",
|
|
170
|
+
"file:write",
|
|
171
|
+
"file:delete",
|
|
172
|
+
"file:execute",
|
|
173
|
+
"network:http",
|
|
174
|
+
"network:https",
|
|
175
|
+
"network:websocket",
|
|
176
|
+
"shell:execute",
|
|
177
|
+
"shell:background",
|
|
178
|
+
"process:spawn",
|
|
179
|
+
"database:read",
|
|
180
|
+
"database:write",
|
|
181
|
+
"secrets:read",
|
|
182
|
+
"env:read",
|
|
183
|
+
"api:external",
|
|
184
|
+
"oauth:required",
|
|
185
|
+
"ui:browser",
|
|
186
|
+
"ui:terminal",
|
|
187
|
+
"gpu:required",
|
|
188
|
+
"elevated:required",
|
|
189
|
+
]);
|
|
190
|
+
for (const cap of manifest.capabilities) {
|
|
191
|
+
if (!validCapabilities.has(cap.capability)) {
|
|
192
|
+
errors.push(`Unknown capability: ${cap.capability}`);
|
|
193
|
+
}
|
|
194
|
+
if (!cap.reason) {
|
|
195
|
+
warnings.push(`Capability ${cap.capability} missing reason`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// Test validation (optional)
|
|
200
|
+
if (manifest.tests?.tests) {
|
|
201
|
+
for (const test of manifest.tests.tests) {
|
|
202
|
+
if (!test.name)
|
|
203
|
+
errors.push("Test case missing name");
|
|
204
|
+
if (!test.input)
|
|
205
|
+
errors.push(`Test ${test.name} missing input`);
|
|
206
|
+
if (!test.expect)
|
|
207
|
+
errors.push(`Test ${test.name} missing expect`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// Version format validation (optional field, but if present should be valid)
|
|
211
|
+
if (manifest.version && !/^\d+\.\d+\.\d+(-[\w.]+)?$/.test(manifest.version)) {
|
|
212
|
+
warnings.push("Invalid version format. Recommend using semver (e.g., 1.0.0)");
|
|
213
|
+
}
|
|
214
|
+
// Execution validation (ask protected-capability extension; omit => local).
|
|
215
|
+
if (manifest.execution) {
|
|
216
|
+
const { mode, runtime, handler, endpoint, transport } = manifest.execution;
|
|
217
|
+
if (mode !== "local" && mode !== "remote") {
|
|
218
|
+
errors.push(`Invalid execution.mode '${mode}' (expected 'local' or 'remote')`);
|
|
219
|
+
}
|
|
220
|
+
if (mode === "remote") {
|
|
221
|
+
if (runtime !== "hosted-function" && runtime !== "endpoint") {
|
|
222
|
+
errors.push("Remote execution requires runtime 'hosted-function' or 'endpoint'");
|
|
223
|
+
}
|
|
224
|
+
if (runtime === "hosted-function" && !handler) {
|
|
225
|
+
errors.push("Remote hosted-function execution requires a 'handler'");
|
|
226
|
+
}
|
|
227
|
+
if (runtime === "endpoint" && !endpoint) {
|
|
228
|
+
errors.push("Remote endpoint execution requires an 'endpoint' URL");
|
|
229
|
+
}
|
|
230
|
+
if (transport !== "mcp" && transport !== "cli") {
|
|
231
|
+
errors.push("Remote execution requires transport 'mcp' or 'cli'");
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// Pricing validation (omit => free).
|
|
236
|
+
if (manifest.pricing) {
|
|
237
|
+
const { model, priceUsd } = manifest.pricing;
|
|
238
|
+
if (model !== "free" && model !== "paid") {
|
|
239
|
+
errors.push(`Invalid pricing.model '${model}' (expected 'free' or 'paid')`);
|
|
240
|
+
}
|
|
241
|
+
if (model === "paid" && !(typeof priceUsd === "number" && priceUsd > 0)) {
|
|
242
|
+
errors.push("Paid pricing requires a positive 'priceUsd' (cents)");
|
|
243
|
+
}
|
|
244
|
+
// Paid + remote is the defensible quadrant; paid + local is license/honor-
|
|
245
|
+
// enforced only (leaky) — allowed, but warn.
|
|
246
|
+
if (model === "paid" && (!manifest.execution || manifest.execution.mode === "local")) {
|
|
247
|
+
warnings.push("Paid local skills are license/honor-enforced only (the leaky quadrant). Use remote execution for strong source protection.");
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return {
|
|
251
|
+
valid: errors.length === 0,
|
|
252
|
+
errors,
|
|
253
|
+
warnings,
|
|
254
|
+
anthropicCompatible,
|
|
255
|
+
hasAskExtensions,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Validate only the Anthropic-required fields
|
|
260
|
+
* Use this for quick validation when importing external skills
|
|
261
|
+
*/
|
|
262
|
+
export function validateAnthropicCompatibility(name, description) {
|
|
263
|
+
const errors = [];
|
|
264
|
+
const nameResult = validateAnthropicName(name);
|
|
265
|
+
if (!nameResult.valid)
|
|
266
|
+
errors.push(nameResult.error);
|
|
267
|
+
const descResult = validateAnthropicDescription(description);
|
|
268
|
+
if (!descResult.valid)
|
|
269
|
+
errors.push(descResult.error);
|
|
270
|
+
return { valid: errors.length === 0, errors };
|
|
271
|
+
}
|
|
272
|
+
// ============================================================================
|
|
273
|
+
// PARSING
|
|
274
|
+
// ============================================================================
|
|
275
|
+
/**
|
|
276
|
+
* Parse SKILL.md frontmatter into manifest
|
|
277
|
+
*/
|
|
278
|
+
export function parseSkillFrontmatter(content) {
|
|
279
|
+
const errors = [];
|
|
280
|
+
let manifest = {};
|
|
281
|
+
let body = content;
|
|
282
|
+
// Check for YAML frontmatter
|
|
283
|
+
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
284
|
+
if (frontmatterMatch) {
|
|
285
|
+
const [, yaml, rest] = frontmatterMatch;
|
|
286
|
+
body = rest;
|
|
287
|
+
try {
|
|
288
|
+
// Simple YAML parsing (for production, use a proper YAML parser)
|
|
289
|
+
const lines = yaml.split("\n");
|
|
290
|
+
const stack = [
|
|
291
|
+
{ obj: manifest, indent: -1 },
|
|
292
|
+
];
|
|
293
|
+
for (const line of lines) {
|
|
294
|
+
if (!line.trim() || line.trim().startsWith("#"))
|
|
295
|
+
continue;
|
|
296
|
+
const match = line.match(/^(\s*)(\w+):\s*(.*)$/);
|
|
297
|
+
if (match) {
|
|
298
|
+
const [, indent, key, value] = match;
|
|
299
|
+
const indentLevel = indent.length;
|
|
300
|
+
// Pop stack to correct level
|
|
301
|
+
while (stack.length > 1 && stack[stack.length - 1].indent >= indentLevel) {
|
|
302
|
+
stack.pop();
|
|
303
|
+
}
|
|
304
|
+
const current = stack[stack.length - 1].obj;
|
|
305
|
+
if (value) {
|
|
306
|
+
// Simple value
|
|
307
|
+
current[key] = value.replace(/^["']|["']$/g, "");
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
// Nested object or array
|
|
311
|
+
current[key] = {};
|
|
312
|
+
stack.push({ obj: current[key], indent: indentLevel });
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
catch (e) {
|
|
318
|
+
errors.push(`Failed to parse frontmatter: ${e}`);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
errors.push("SKILL.md must have YAML frontmatter (---\\n...\\n---)");
|
|
323
|
+
}
|
|
324
|
+
return { manifest, body, errors };
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Parse a skill directory into a SkillDirectory structure
|
|
328
|
+
*/
|
|
329
|
+
export function parseSkillDirectory(files) {
|
|
330
|
+
const errors = [];
|
|
331
|
+
// Find SKILL.md
|
|
332
|
+
const skillMdFile = files.find((f) => f.path === "SKILL.md" || f.path.endsWith("/SKILL.md"));
|
|
333
|
+
if (!skillMdFile) {
|
|
334
|
+
return { skill: null, errors: ["Missing required SKILL.md file"] };
|
|
335
|
+
}
|
|
336
|
+
// Parse SKILL.md
|
|
337
|
+
const { manifest, body, errors: parseErrors } = parseSkillFrontmatter(skillMdFile.content);
|
|
338
|
+
errors.push(...parseErrors);
|
|
339
|
+
// Validate required fields
|
|
340
|
+
if (!manifest.name || !manifest.description) {
|
|
341
|
+
errors.push("SKILL.md must have 'name' and 'description' in frontmatter");
|
|
342
|
+
return { skill: null, errors };
|
|
343
|
+
}
|
|
344
|
+
// Find skill.json (ask extensions)
|
|
345
|
+
const skillJsonFile = files.find((f) => f.path === "skill.json" || f.path.endsWith("/skill.json"));
|
|
346
|
+
let skillJson;
|
|
347
|
+
if (skillJsonFile) {
|
|
348
|
+
try {
|
|
349
|
+
skillJson = JSON.parse(skillJsonFile.content);
|
|
350
|
+
}
|
|
351
|
+
catch (e) {
|
|
352
|
+
errors.push(`Failed to parse skill.json: ${e}`);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
// Categorize files per agentskills.io directory structure:
|
|
356
|
+
// - scripts/ -> executable code
|
|
357
|
+
// - references/ -> additional documentation
|
|
358
|
+
// - assets/ -> static resources
|
|
359
|
+
const skillFiles = [];
|
|
360
|
+
const scripts = [];
|
|
361
|
+
const references = [];
|
|
362
|
+
const assets = [];
|
|
363
|
+
for (const file of files) {
|
|
364
|
+
if (file.path === "SKILL.md" || file.path === "skill.json")
|
|
365
|
+
continue;
|
|
366
|
+
const skillFile = {
|
|
367
|
+
path: file.path,
|
|
368
|
+
content: file.content,
|
|
369
|
+
type: "resource",
|
|
370
|
+
};
|
|
371
|
+
// scripts/ directory - executable code
|
|
372
|
+
if (file.path.startsWith("scripts/") || file.path.includes("/scripts/")) {
|
|
373
|
+
skillFile.type = "script";
|
|
374
|
+
skillFile.executable =
|
|
375
|
+
file.path.endsWith(".py") ||
|
|
376
|
+
file.path.endsWith(".sh") ||
|
|
377
|
+
file.path.endsWith(".js") ||
|
|
378
|
+
file.path.endsWith(".ts");
|
|
379
|
+
scripts.push(skillFile);
|
|
380
|
+
}
|
|
381
|
+
// references/ directory - additional documentation (per spec)
|
|
382
|
+
else if (file.path.startsWith("references/") || file.path.includes("/references/")) {
|
|
383
|
+
skillFile.type = "markdown";
|
|
384
|
+
references.push(skillFile);
|
|
385
|
+
}
|
|
386
|
+
// assets/ directory - static resources (per spec)
|
|
387
|
+
else if (file.path.startsWith("assets/") || file.path.includes("/assets/")) {
|
|
388
|
+
skillFile.type = "resource";
|
|
389
|
+
assets.push(skillFile);
|
|
390
|
+
}
|
|
391
|
+
// Markdown files not in specific directories
|
|
392
|
+
else if (file.path.endsWith(".md")) {
|
|
393
|
+
skillFile.type = "markdown";
|
|
394
|
+
references.push(skillFile);
|
|
395
|
+
}
|
|
396
|
+
// Config files
|
|
397
|
+
else if (file.path.endsWith(".json") ||
|
|
398
|
+
file.path.endsWith(".yaml") ||
|
|
399
|
+
file.path.endsWith(".yml")) {
|
|
400
|
+
skillFile.type = "config";
|
|
401
|
+
assets.push(skillFile);
|
|
402
|
+
}
|
|
403
|
+
// Everything else is an asset
|
|
404
|
+
else {
|
|
405
|
+
assets.push(skillFile);
|
|
406
|
+
}
|
|
407
|
+
skillFiles.push(skillFile);
|
|
408
|
+
}
|
|
409
|
+
return {
|
|
410
|
+
skill: {
|
|
411
|
+
skillMd: skillMdFile.content,
|
|
412
|
+
metadata: manifest,
|
|
413
|
+
instructions: body,
|
|
414
|
+
skillJson,
|
|
415
|
+
files: skillFiles,
|
|
416
|
+
scripts: scripts.length > 0 ? scripts : undefined,
|
|
417
|
+
references: references.length > 0 ? references : undefined,
|
|
418
|
+
assets: assets.length > 0 ? assets : undefined,
|
|
419
|
+
},
|
|
420
|
+
errors,
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
// ============================================================================
|
|
424
|
+
// TYPE GUARDS
|
|
425
|
+
// ============================================================================
|
|
426
|
+
export function isValidParameterType(type) {
|
|
427
|
+
return [
|
|
428
|
+
"string",
|
|
429
|
+
"number",
|
|
430
|
+
"boolean",
|
|
431
|
+
"array",
|
|
432
|
+
"object",
|
|
433
|
+
"file",
|
|
434
|
+
"url",
|
|
435
|
+
"code",
|
|
436
|
+
"markdown",
|
|
437
|
+
"json",
|
|
438
|
+
"any",
|
|
439
|
+
].includes(type);
|
|
440
|
+
}
|
|
441
|
+
export function isValidCapability(cap) {
|
|
442
|
+
return [
|
|
443
|
+
"file:read",
|
|
444
|
+
"file:write",
|
|
445
|
+
"file:delete",
|
|
446
|
+
"file:execute",
|
|
447
|
+
"network:http",
|
|
448
|
+
"network:https",
|
|
449
|
+
"network:websocket",
|
|
450
|
+
"shell:execute",
|
|
451
|
+
"shell:background",
|
|
452
|
+
"process:spawn",
|
|
453
|
+
"database:read",
|
|
454
|
+
"database:write",
|
|
455
|
+
"secrets:read",
|
|
456
|
+
"env:read",
|
|
457
|
+
"api:external",
|
|
458
|
+
"oauth:required",
|
|
459
|
+
"ui:browser",
|
|
460
|
+
"ui:terminal",
|
|
461
|
+
"gpu:required",
|
|
462
|
+
"elevated:required",
|
|
463
|
+
].includes(cap);
|
|
464
|
+
}
|
|
465
|
+
export function isAnthropicCompatible(manifest) {
|
|
466
|
+
const nameValid = validateAnthropicName(manifest.name || "").valid;
|
|
467
|
+
const descValid = validateAnthropicDescription(manifest.description || "").valid;
|
|
468
|
+
return nameValid && descValid;
|
|
469
|
+
}
|
|
470
|
+
// ============================================================================
|
|
471
|
+
// CONVERSION UTILITIES
|
|
472
|
+
// ============================================================================
|
|
473
|
+
/**
|
|
474
|
+
* Convert a legacy single-file skill to directory structure
|
|
475
|
+
*/
|
|
476
|
+
export function convertLegacySkill(legacyContent, skillName) {
|
|
477
|
+
const errors = [];
|
|
478
|
+
const files = [];
|
|
479
|
+
// Parse the legacy file
|
|
480
|
+
const { manifest, body, errors: parseErrors } = parseSkillFrontmatter(legacyContent);
|
|
481
|
+
errors.push(...parseErrors);
|
|
482
|
+
if (!manifest.name || !manifest.description) {
|
|
483
|
+
errors.push("Legacy skill must have name and description");
|
|
484
|
+
return { files: [], errors };
|
|
485
|
+
}
|
|
486
|
+
// Create Anthropic-compatible SKILL.md (only name + description)
|
|
487
|
+
const anthropicFrontmatter = `---
|
|
488
|
+
name: ${manifest.name.replace(/^@[\w-]+\//, "")}
|
|
489
|
+
description: ${manifest.description}
|
|
490
|
+
---
|
|
491
|
+
`;
|
|
492
|
+
files.push({
|
|
493
|
+
path: `${skillName}/SKILL.md`,
|
|
494
|
+
content: anthropicFrontmatter + body,
|
|
495
|
+
});
|
|
496
|
+
// Create skill.json with ask extensions
|
|
497
|
+
const askExtensions = {};
|
|
498
|
+
if (manifest.version)
|
|
499
|
+
askExtensions.version = manifest.version;
|
|
500
|
+
if (manifest.author)
|
|
501
|
+
askExtensions.author = manifest.author;
|
|
502
|
+
if (manifest.license)
|
|
503
|
+
askExtensions.license = manifest.license;
|
|
504
|
+
if (manifest.keywords)
|
|
505
|
+
askExtensions.keywords = manifest.keywords;
|
|
506
|
+
if (manifest.categories)
|
|
507
|
+
askExtensions.categories = manifest.categories;
|
|
508
|
+
if (manifest.contract)
|
|
509
|
+
askExtensions.contract = manifest.contract;
|
|
510
|
+
if (manifest.capabilities)
|
|
511
|
+
askExtensions.capabilities = manifest.capabilities;
|
|
512
|
+
if (manifest.tests)
|
|
513
|
+
askExtensions.tests = manifest.tests;
|
|
514
|
+
if (Object.keys(askExtensions).length > 0) {
|
|
515
|
+
files.push({
|
|
516
|
+
path: `${skillName}/skill.json`,
|
|
517
|
+
content: JSON.stringify(askExtensions, null, 2),
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
return { files, errors };
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Merge skill.json extensions into manifest
|
|
524
|
+
*/
|
|
525
|
+
export function mergeExtensions(metadata, extensions) {
|
|
526
|
+
return {
|
|
527
|
+
...metadata,
|
|
528
|
+
...extensions,
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
//# sourceMappingURL=skill-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-schema.js","sourceRoot":"","sources":["../src/skill-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill Testing Framework
|
|
3
|
+
*
|
|
4
|
+
* Validates skill behavior against defined test cases.
|
|
5
|
+
* Can run in dry-run mode (validation only) or execution mode.
|
|
6
|
+
*/
|
|
7
|
+
import type { SkillTestCase, SkillManifest, SkillCapability } from "./skill-schema.js";
|
|
8
|
+
export interface TestResult {
|
|
9
|
+
name: string;
|
|
10
|
+
passed: boolean;
|
|
11
|
+
duration: number;
|
|
12
|
+
error?: string;
|
|
13
|
+
details?: {
|
|
14
|
+
expectedOutput?: Record<string, unknown>;
|
|
15
|
+
actualOutput?: Record<string, unknown>;
|
|
16
|
+
mismatchedFields?: string[];
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export interface TestSuiteResult {
|
|
20
|
+
total: number;
|
|
21
|
+
passed: number;
|
|
22
|
+
failed: number;
|
|
23
|
+
skipped: number;
|
|
24
|
+
duration: number;
|
|
25
|
+
results: TestResult[];
|
|
26
|
+
coverage: {
|
|
27
|
+
inputsCovered: string[];
|
|
28
|
+
outputsCovered: string[];
|
|
29
|
+
capabilitiesCovered: string[];
|
|
30
|
+
uncoveredInputs: string[];
|
|
31
|
+
uncoveredOutputs: string[];
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export interface TestRunnerOptions {
|
|
35
|
+
/**
|
|
36
|
+
* Run tests in dry-run mode (validation only, no execution)
|
|
37
|
+
*/
|
|
38
|
+
dryRun?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Timeout per test in milliseconds
|
|
41
|
+
*/
|
|
42
|
+
timeout?: number;
|
|
43
|
+
/**
|
|
44
|
+
* Only run tests matching this pattern
|
|
45
|
+
*/
|
|
46
|
+
filter?: string;
|
|
47
|
+
/**
|
|
48
|
+
* Stop on first failure
|
|
49
|
+
*/
|
|
50
|
+
bail?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Verbose output
|
|
53
|
+
*/
|
|
54
|
+
verbose?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Custom executor for running test cases
|
|
57
|
+
* If not provided, tests run in validation-only mode
|
|
58
|
+
*/
|
|
59
|
+
executor?: TestExecutor;
|
|
60
|
+
}
|
|
61
|
+
export type TestExecutor = (test: SkillTestCase, manifest: SkillManifest) => Promise<{
|
|
62
|
+
output: Record<string, unknown>;
|
|
63
|
+
success: boolean;
|
|
64
|
+
error?: string;
|
|
65
|
+
capabilitiesUsed?: SkillCapability[];
|
|
66
|
+
}>;
|
|
67
|
+
export declare class SkillTestRunner {
|
|
68
|
+
private options;
|
|
69
|
+
constructor(options?: TestRunnerOptions);
|
|
70
|
+
/**
|
|
71
|
+
* Run all tests in a skill's test suite
|
|
72
|
+
*/
|
|
73
|
+
run(manifest: SkillManifest, skillContent: string): Promise<TestSuiteResult>;
|
|
74
|
+
/**
|
|
75
|
+
* Run a single test case
|
|
76
|
+
*/
|
|
77
|
+
private runTest;
|
|
78
|
+
/**
|
|
79
|
+
* Validate test structure (dry-run mode)
|
|
80
|
+
*/
|
|
81
|
+
private validateTestStructure;
|
|
82
|
+
/**
|
|
83
|
+
* Filter tests based on options
|
|
84
|
+
*/
|
|
85
|
+
private filterTests;
|
|
86
|
+
/**
|
|
87
|
+
* Validate inputs against contract
|
|
88
|
+
*/
|
|
89
|
+
private validateInputs;
|
|
90
|
+
/**
|
|
91
|
+
* Match actual output against expected
|
|
92
|
+
*/
|
|
93
|
+
private matchOutput;
|
|
94
|
+
/**
|
|
95
|
+
* Deep equality check
|
|
96
|
+
*/
|
|
97
|
+
private deepEqual;
|
|
98
|
+
/**
|
|
99
|
+
* Create a timeout promise
|
|
100
|
+
*/
|
|
101
|
+
private timeout;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Run tests for a skill (validation only)
|
|
105
|
+
*/
|
|
106
|
+
export declare function validateTests(manifest: SkillManifest, skillContent: string, options?: TestRunnerOptions): Promise<TestSuiteResult>;
|
|
107
|
+
/**
|
|
108
|
+
* Calculate test coverage percentage
|
|
109
|
+
*/
|
|
110
|
+
export declare function calculateCoverage(result: TestSuiteResult): {
|
|
111
|
+
inputCoverage: number;
|
|
112
|
+
outputCoverage: number;
|
|
113
|
+
overallCoverage: number;
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* Format test results for display
|
|
117
|
+
*/
|
|
118
|
+
export declare function formatTestResults(result: TestSuiteResult): string;
|
|
119
|
+
//# sourceMappingURL=skill-tester.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-tester.d.ts","sourceRoot":"","sources":["../src/skill-tester.ts"],"names":[],"mappings":"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"}
|