@lesliechan721/aw-plugin-core 0.1.0-beta.1
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/file-rules.d.ts +2 -0
- package/dist/file-rules.js +42 -0
- package/dist/file-rules.js.map +1 -0
- package/dist/generated/plugin-manifest-v1.d.ts +368 -0
- package/dist/generated/plugin-manifest-v1.js +3 -0
- package/dist/generated/plugin-manifest-v1.js.map +1 -0
- package/dist/hooks-contract.d.ts +189 -0
- package/dist/hooks-contract.js +967 -0
- package/dist/hooks-contract.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest-contract.d.ts +96 -0
- package/dist/manifest-contract.js +2730 -0
- package/dist/manifest-contract.js.map +1 -0
- package/dist/manifest-type-contract.d.ts +7 -0
- package/dist/manifest-type-contract.js +2 -0
- package/dist/manifest-type-contract.js.map +1 -0
- package/dist/manifest.d.ts +27 -0
- package/dist/manifest.js +59 -0
- package/dist/manifest.js.map +1 -0
- package/dist/permission-command.d.ts +3 -0
- package/dist/permission-command.js +11 -0
- package/dist/permission-command.js.map +1 -0
- package/dist/platform-entries.d.ts +13 -0
- package/dist/platform-entries.js +20 -0
- package/dist/platform-entries.js.map +1 -0
- package/dist/platform-support.d.ts +6 -0
- package/dist/platform-support.js +38 -0
- package/dist/platform-support.js.map +1 -0
- package/dist/plugin-release.d.ts +30 -0
- package/dist/plugin-release.js +187 -0
- package/dist/plugin-release.js.map +1 -0
- package/dist/plugin-script-contract.d.ts +33 -0
- package/dist/plugin-script-contract.js +599 -0
- package/dist/plugin-script-contract.js.map +1 -0
- package/dist/portable-skill-validation.d.ts +7 -0
- package/dist/portable-skill-validation.js +111 -0
- package/dist/portable-skill-validation.js.map +1 -0
- package/dist/read-json.d.ts +1 -0
- package/dist/read-json.js +5 -0
- package/dist/read-json.js.map +1 -0
- package/dist/runtime-export-source.d.ts +14 -0
- package/dist/runtime-export-source.js +73 -0
- package/dist/runtime-export-source.js.map +1 -0
- package/dist/skill-authoring.d.ts +2 -0
- package/dist/skill-authoring.js +13 -0
- package/dist/skill-authoring.js.map +1 -0
- package/dist/skill-frontmatter-capabilities.d.ts +36 -0
- package/dist/skill-frontmatter-capabilities.js +120 -0
- package/dist/skill-frontmatter-capabilities.js.map +1 -0
- package/dist/skill-frontmatter-capabilities.json +200 -0
- package/dist/slash-commands.d.ts +43 -0
- package/dist/slash-commands.js +394 -0
- package/dist/slash-commands.js.map +1 -0
- package/dist/template-engine.d.ts +2 -0
- package/dist/template-engine.js +26 -0
- package/dist/template-engine.js.map +1 -0
- package/dist/types.d.ts +428 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/workspace.d.ts +105 -0
- package/dist/workspace.js +963 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +46 -0
- package/schemas/plugin-manifest-v1.json +329 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import YAML from 'yaml';
|
|
4
|
+
import { isSkillAuthorOnlyPath } from './skill-authoring.js';
|
|
5
|
+
import { validateSkillFrontmatterCapabilities } from './skill-frontmatter-capabilities.js';
|
|
6
|
+
const SKILL_FILE_PATH = 'SKILL.md';
|
|
7
|
+
const SKILL_OWNER_MARKER = '.agent-workflows-owner.json';
|
|
8
|
+
export function validatePortableSkillName(value, fieldName = 'portable Skill name') {
|
|
9
|
+
if (value.length > 64 || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(value)) {
|
|
10
|
+
throw new Error(`Invalid ${fieldName}: expected at most 64 ASCII lowercase hyphen-case characters.`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function comparePaths(left, right) {
|
|
14
|
+
return Buffer.compare(Buffer.from(left, 'utf8'), Buffer.from(right, 'utf8'));
|
|
15
|
+
}
|
|
16
|
+
function parseFrontmatter(rawContent) {
|
|
17
|
+
const normalized = rawContent.replace(/\r\n/g, '\n');
|
|
18
|
+
if (!normalized.startsWith('---\n'))
|
|
19
|
+
throw new Error('SKILL.md 缺少 YAML frontmatter。');
|
|
20
|
+
const closingIndex = normalized.indexOf('\n---\n', 4);
|
|
21
|
+
const closingAtEof = closingIndex === -1 && normalized.endsWith('\n---');
|
|
22
|
+
if (closingIndex === -1 && !closingAtEof)
|
|
23
|
+
throw new Error('SKILL.md frontmatter 缺少结束分隔符。');
|
|
24
|
+
const yamlEndIndex = closingAtEof ? normalized.length - '\n---'.length : closingIndex;
|
|
25
|
+
let frontmatter;
|
|
26
|
+
try {
|
|
27
|
+
frontmatter = YAML.parse(normalized.slice(4, yamlEndIndex));
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
throw new Error(`SKILL.md frontmatter YAML 解析失败:${error instanceof Error ? error.message : String(error)}`);
|
|
31
|
+
}
|
|
32
|
+
if (typeof frontmatter !== 'object' || frontmatter === null || Array.isArray(frontmatter)) {
|
|
33
|
+
throw new Error('SKILL.md frontmatter 根节点必须是 object。');
|
|
34
|
+
}
|
|
35
|
+
return frontmatter;
|
|
36
|
+
}
|
|
37
|
+
async function collectFiles(rootDir) {
|
|
38
|
+
const files = {};
|
|
39
|
+
const visit = async (currentDir, parentPath) => {
|
|
40
|
+
const entries = await fs.readdir(currentDir, { withFileTypes: true });
|
|
41
|
+
for (const entry of entries.sort((left, right) => comparePaths(left.name, right.name))) {
|
|
42
|
+
const relativePath = parentPath ? `${parentPath}/${entry.name}` : entry.name;
|
|
43
|
+
if (isSkillAuthorOnlyPath(relativePath))
|
|
44
|
+
continue;
|
|
45
|
+
if (relativePath === SKILL_OWNER_MARKER) {
|
|
46
|
+
throw new Error(`Skill source tree 不能声明保留文件 ${SKILL_OWNER_MARKER}。`);
|
|
47
|
+
}
|
|
48
|
+
const absolutePath = path.join(currentDir, entry.name);
|
|
49
|
+
if (entry.isSymbolicLink())
|
|
50
|
+
throw new Error(`Skill 静态源不支持符号链接:${relativePath}`);
|
|
51
|
+
if (entry.isDirectory()) {
|
|
52
|
+
await visit(absolutePath, relativePath);
|
|
53
|
+
}
|
|
54
|
+
else if (entry.isFile()) {
|
|
55
|
+
files[relativePath] = await fs.readFile(absolutePath);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
throw new Error(`Skill 静态源只支持普通文件和目录:${relativePath}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
await visit(rootDir, '');
|
|
63
|
+
return files;
|
|
64
|
+
}
|
|
65
|
+
export async function validatePortableSkillDirectory(rootDir) {
|
|
66
|
+
const rootStats = await fs.lstat(rootDir).catch(() => null);
|
|
67
|
+
if (!rootStats || rootStats.isSymbolicLink() || !rootStats.isDirectory()) {
|
|
68
|
+
throw new Error(`Skill 根路径必须是真实目录:${rootDir}`);
|
|
69
|
+
}
|
|
70
|
+
const skillKey = path.basename(rootDir);
|
|
71
|
+
validatePortableSkillName(skillKey, 'portable Skill directory name');
|
|
72
|
+
const files = await collectFiles(rootDir);
|
|
73
|
+
const skillFile = files[SKILL_FILE_PATH];
|
|
74
|
+
if (!skillFile || skillFile.toString('utf8').trim() === '') {
|
|
75
|
+
throw new Error(`agent-skills.skill "${skillKey}" 缺少 SKILL.md 内容。`);
|
|
76
|
+
}
|
|
77
|
+
const frontmatter = parseFrontmatter(skillFile.toString('utf8'));
|
|
78
|
+
if (typeof frontmatter.name === 'string')
|
|
79
|
+
validatePortableSkillName(frontmatter.name, 'SKILL.md frontmatter.name');
|
|
80
|
+
if (typeof frontmatter.description === 'string' && frontmatter.description.length > 1024) {
|
|
81
|
+
throw new Error('Invalid SKILL.md frontmatter.description: expected at most 1024 characters.');
|
|
82
|
+
}
|
|
83
|
+
const diagnostics = validateSkillFrontmatterCapabilities(frontmatter, 'portable-agent-skills');
|
|
84
|
+
if (diagnostics.length > 0) {
|
|
85
|
+
throw new Error(`SKILL.md frontmatter 不符合 portable-agent-skills profile:${diagnostics.map((entry) => `[${entry.code}] ${entry.message}`).join('; ')}`);
|
|
86
|
+
}
|
|
87
|
+
if (frontmatter.name !== skillKey) {
|
|
88
|
+
throw new Error(`SKILL.md frontmatter 的 name 必须与 Skill 目录一致:期望 ${JSON.stringify(skillKey)}。`);
|
|
89
|
+
}
|
|
90
|
+
const readme = files['README.md'];
|
|
91
|
+
if (!readme || readme.toString('utf8').trim() === '') {
|
|
92
|
+
throw new Error(`agent-skills.skill "${skillKey}" 缺少非空 README.md。`);
|
|
93
|
+
}
|
|
94
|
+
return { skillKey, files };
|
|
95
|
+
}
|
|
96
|
+
export async function validatePortableSkillDirectoriesRoot(rootDir) {
|
|
97
|
+
const rootStats = await fs.lstat(rootDir).catch(() => null);
|
|
98
|
+
if (!rootStats || rootStats.isSymbolicLink() || !rootStats.isDirectory()) {
|
|
99
|
+
throw new Error(`Skills 根路径必须是真实目录:${rootDir}`);
|
|
100
|
+
}
|
|
101
|
+
const entries = await fs.readdir(rootDir, { withFileTypes: true });
|
|
102
|
+
const trees = [];
|
|
103
|
+
for (const entry of entries.sort((left, right) => comparePaths(left.name, right.name))) {
|
|
104
|
+
if (entry.isSymbolicLink() || !entry.isDirectory()) {
|
|
105
|
+
throw new Error(`Skills 根目录的直接子节点必须是普通目录:${entry.name}`);
|
|
106
|
+
}
|
|
107
|
+
trees.push(await validatePortableSkillDirectory(path.join(rootDir, entry.name)));
|
|
108
|
+
}
|
|
109
|
+
return trees;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=portable-skill-validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portable-skill-validation.js","sourceRoot":"","sources":["../src/portable-skill-validation.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,oCAAoC,EAAE,MAAM,qCAAqC,CAAC;AAE3F,MAAM,eAAe,GAAG,UAAU,CAAC;AACnC,MAAM,kBAAkB,GAAG,6BAA6B,CAAC;AAOzD,MAAM,UAAU,yBAAyB,CAAC,KAAa,EAAE,SAAS,GAAG,qBAAqB;IACxF,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,IAAI,CAAC,6BAA6B,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,WAAW,SAAS,+DAA+D,CAAC,CAAC;IACvG,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,KAAa;IAC/C,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;AAC/E,CAAC;AAED,SAAS,gBAAgB,CAAC,UAAkB;IAC1C,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACrD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACtF,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;IACtD,MAAM,YAAY,GAAG,YAAY,KAAK,CAAC,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACzE,IAAI,YAAY,KAAK,CAAC,CAAC,IAAI,CAAC,YAAY;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IAC3F,MAAM,YAAY,GAAG,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC;IACtF,IAAI,WAAoB,CAAC;IACzB,IAAI,CAAC;QACH,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC;IAC9D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,kCAAkC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC9G,CAAC;IACD,IAAI,OAAO,WAAW,KAAK,QAAQ,IAAI,WAAW,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QAC1F,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,WAAsC,CAAC;AAChD,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,OAAe;IACzC,MAAM,KAAK,GAA2B,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,KAAK,EAAE,UAAkB,EAAE,UAAkB,EAAiB,EAAE;QAC5E,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACtE,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YACvF,MAAM,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;YAC7E,IAAI,qBAAqB,CAAC,YAAY,CAAC;gBAAE,SAAS;YAClD,IAAI,YAAY,KAAK,kBAAkB,EAAE,CAAC;gBACxC,MAAM,IAAI,KAAK,CAAC,8BAA8B,kBAAkB,GAAG,CAAC,CAAC;YACvE,CAAC;YACD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACvD,IAAI,KAAK,CAAC,cAAc,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,YAAY,EAAE,CAAC,CAAC;YAChF,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,MAAM,KAAK,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;YAC1C,CAAC;iBAAM,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;gBAC1B,KAAK,CAAC,YAAY,CAAC,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;YACxD,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,KAAK,CAAC,uBAAuB,YAAY,EAAE,CAAC,CAAC;YACzD,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,MAAM,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACzB,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAAC,OAAe;IAClE,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAC5D,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC;QACzE,MAAM,IAAI,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACxC,yBAAyB,CAAC,QAAQ,EAAE,+BAA+B,CAAC,CAAC;IACrE,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,KAAK,CAAC,eAAe,CAAC,CAAC;IACzC,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,uBAAuB,QAAQ,mBAAmB,CAAC,CAAC;IACtE,CAAC;IACD,MAAM,WAAW,GAAG,gBAAgB,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IACjE,IAAI,OAAO,WAAW,CAAC,IAAI,KAAK,QAAQ;QAAE,yBAAyB,CAAC,WAAW,CAAC,IAAI,EAAE,2BAA2B,CAAC,CAAC;IACnH,IAAI,OAAO,WAAW,CAAC,WAAW,KAAK,QAAQ,IAAI,WAAW,CAAC,WAAW,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;QACzF,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC;IACjG,CAAC;IACD,MAAM,WAAW,GAAG,oCAAoC,CAAC,WAAW,EAAE,uBAAuB,CAAC,CAAC;IAC/F,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,0DAA0D,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzJ,CAAC;IACD,IAAI,WAAW,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,iDAAiD,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAChG,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;IAClC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,uBAAuB,QAAQ,mBAAmB,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC7B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oCAAoC,CAAC,OAAe;IACxE,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAC5D,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC;QACzE,MAAM,IAAI,KAAK,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAC;IAClD,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACnE,MAAM,KAAK,GAAwB,EAAE,CAAC;IACtC,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QACvF,IAAI,KAAK,CAAC,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACnD,MAAM,IAAI,KAAK,CAAC,2BAA2B,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3D,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,MAAM,8BAA8B,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACnF,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function readJsonFile<T>(filePath: string): Promise<T>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-json.js","sourceRoot":"","sources":["../src/read-json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAE1B,MAAM,CAAC,KAAK,UAAU,YAAY,CAAI,QAAgB;IACpD,OAAO,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAe,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare function isIgnoredPluginInputDirectory(name: string): boolean;
|
|
2
|
+
export declare function assertPluginInputTree(rootDir: string): Promise<string>;
|
|
3
|
+
export interface CanonicalRuntimeSourceIdentity {
|
|
4
|
+
rootPath: string;
|
|
5
|
+
rootRealPath: string;
|
|
6
|
+
relativePath: string;
|
|
7
|
+
sourceRealPath: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function resolveCanonicalRuntimeSourceIdentity(rootDir: string, relativePath: string, fieldName: string): Promise<CanonicalRuntimeSourceIdentity>;
|
|
10
|
+
export declare function validateRuntimeExportSource(options: {
|
|
11
|
+
pluginRoot: string;
|
|
12
|
+
name: string;
|
|
13
|
+
source: string;
|
|
14
|
+
}): Promise<CanonicalRuntimeSourceIdentity>;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
const FORBIDDEN_EXPORT_ROOTS = new Set([
|
|
4
|
+
'.release', '.tmp', 'build', 'dist', 'evals', 'node_modules', 'reports', 'skills', 'tmp',
|
|
5
|
+
]);
|
|
6
|
+
const AUTHORING_TREE_IGNORED_DIRECTORIES = new Set(['.git', 'node_modules']);
|
|
7
|
+
export function isIgnoredPluginInputDirectory(name) {
|
|
8
|
+
return AUTHORING_TREE_IGNORED_DIRECTORIES.has(name);
|
|
9
|
+
}
|
|
10
|
+
export async function assertPluginInputTree(rootDir) {
|
|
11
|
+
const rootPath = path.resolve(rootDir);
|
|
12
|
+
const rootStats = await fs.lstat(rootPath);
|
|
13
|
+
if (rootStats.isSymbolicLink() || !rootStats.isDirectory()) {
|
|
14
|
+
throw new Error('Invalid plugin input tree: plugin root must be a regular directory.');
|
|
15
|
+
}
|
|
16
|
+
const rootRealPath = await fs.realpath(rootPath);
|
|
17
|
+
const walk = async (directory, relativeRoot = '') => {
|
|
18
|
+
for (const entry of await fs.readdir(directory, { withFileTypes: true })) {
|
|
19
|
+
const relativePath = relativeRoot
|
|
20
|
+
? path.posix.join(relativeRoot, entry.name)
|
|
21
|
+
: entry.name;
|
|
22
|
+
if (entry.isDirectory() && isIgnoredPluginInputDirectory(entry.name))
|
|
23
|
+
continue;
|
|
24
|
+
if (entry.isSymbolicLink()) {
|
|
25
|
+
throw new Error(`Invalid plugin input tree: symbolic links are not supported (${relativePath}).`);
|
|
26
|
+
}
|
|
27
|
+
if (entry.isDirectory()) {
|
|
28
|
+
await walk(path.join(directory, entry.name), relativePath);
|
|
29
|
+
}
|
|
30
|
+
else if (!entry.isFile()) {
|
|
31
|
+
throw new Error(`Invalid plugin input tree: only regular files and directories are supported (${relativePath}).`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
await walk(rootRealPath);
|
|
36
|
+
return rootRealPath;
|
|
37
|
+
}
|
|
38
|
+
export async function resolveCanonicalRuntimeSourceIdentity(rootDir, relativePath, fieldName) {
|
|
39
|
+
const rootPath = path.resolve(rootDir);
|
|
40
|
+
const rootStats = await fs.lstat(rootPath);
|
|
41
|
+
if (rootStats.isSymbolicLink() || !rootStats.isDirectory()) {
|
|
42
|
+
throw new Error(`Invalid ${fieldName}: source root must be a regular directory.`);
|
|
43
|
+
}
|
|
44
|
+
const rootRealPath = await fs.realpath(rootPath);
|
|
45
|
+
const segments = relativePath.replace(/^\.\//u, '').split('/');
|
|
46
|
+
let current = rootRealPath;
|
|
47
|
+
for (const [index, segment] of segments.entries()) {
|
|
48
|
+
current = path.join(current, segment);
|
|
49
|
+
const stats = await fs.lstat(current).catch(() => undefined);
|
|
50
|
+
if (!stats)
|
|
51
|
+
throw new Error(`Invalid ${fieldName}: missing file "${relativePath}".`);
|
|
52
|
+
if (stats.isSymbolicLink()) {
|
|
53
|
+
throw new Error(`Invalid ${fieldName}: symbolic links are not supported (${relativePath}).`);
|
|
54
|
+
}
|
|
55
|
+
if (index < segments.length - 1 && !stats.isDirectory()) {
|
|
56
|
+
throw new Error(`Invalid ${fieldName}: path parent is not a directory (${relativePath}).`);
|
|
57
|
+
}
|
|
58
|
+
if (index === segments.length - 1 && !stats.isFile()) {
|
|
59
|
+
throw new Error(`Invalid ${fieldName}: expected a regular file (${relativePath}).`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return { rootPath, rootRealPath, relativePath, sourceRealPath: await fs.realpath(current) };
|
|
63
|
+
}
|
|
64
|
+
export async function validateRuntimeExportSource(options) {
|
|
65
|
+
const normalizedSource = options.source.replace(/^\.\//u, '');
|
|
66
|
+
const forbiddenSegment = normalizedSource.split('/').find((segment) => FORBIDDEN_EXPORT_ROOTS.has(segment));
|
|
67
|
+
if (forbiddenSegment) {
|
|
68
|
+
throw new Error(`Invalid buildConfig.runtimeExports export "${options.name}": source must not be below ${forbiddenSegment}/.`);
|
|
69
|
+
}
|
|
70
|
+
const fieldName = `buildConfig.runtimeExports export "${options.name}"`;
|
|
71
|
+
return resolveCanonicalRuntimeSourceIdentity(options.pluginRoot, options.source, fieldName);
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=runtime-export-source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-export-source.js","sourceRoot":"","sources":["../src/runtime-export-source.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,MAAM,UAAU,CAAC;AAE1B,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC;IACrC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK;CACzF,CAAC,CAAC;AACH,MAAM,kCAAkC,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC;AAE7E,MAAM,UAAU,6BAA6B,CAAC,IAAY;IACxD,OAAO,kCAAkC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,OAAe;IACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC3C,IAAI,SAAS,CAAC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;IACzF,CAAC;IACD,MAAM,YAAY,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,KAAK,EAAE,SAAiB,EAAE,YAAY,GAAG,EAAE,EAAiB,EAAE;QACzE,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YACzE,MAAM,YAAY,GAAG,YAAY;gBAC/B,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,IAAI,CAAC;gBAC3C,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;YACf,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,6BAA6B,CAAC,KAAK,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC/E,IAAI,KAAK,CAAC,cAAc,EAAE,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CAAC,gEAAgE,YAAY,IAAI,CAAC,CAAC;YACpG,CAAC;YACD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC,CAAC;YAC7D,CAAC;iBAAM,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CAAC,gFAAgF,YAAY,IAAI,CAAC,CAAC;YACpH,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,MAAM,IAAI,CAAC,YAAY,CAAC,CAAC;IACzB,OAAO,YAAY,CAAC;AACtB,CAAC;AASD,MAAM,CAAC,KAAK,UAAU,qCAAqC,CACzD,OAAe,EACf,YAAoB,EACpB,SAAiB;IAEjB,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC3C,IAAI,SAAS,CAAC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,WAAW,SAAS,4CAA4C,CAAC,CAAC;IACpF,CAAC;IACD,MAAM,YAAY,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/D,IAAI,OAAO,GAAG,YAAY,CAAC;IAC3B,KAAK,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;QAClD,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACtC,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC7D,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,WAAW,SAAS,mBAAmB,YAAY,IAAI,CAAC,CAAC;QACrF,IAAI,KAAK,CAAC,cAAc,EAAE,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,WAAW,SAAS,uCAAuC,YAAY,IAAI,CAAC,CAAC;QAC/F,CAAC;QACD,IAAI,KAAK,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxD,MAAM,IAAI,KAAK,CAAC,WAAW,SAAS,qCAAqC,YAAY,IAAI,CAAC,CAAC;QAC7F,CAAC;QACD,IAAI,KAAK,KAAK,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YACrD,MAAM,IAAI,KAAK,CAAC,WAAW,SAAS,8BAA8B,YAAY,IAAI,CAAC,CAAC;QACtF,CAAC;IACH,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;AAC9F,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,OAIjD;IACC,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC9D,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CACpE,sBAAsB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IACvC,IAAI,gBAAgB,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CACb,8CAA8C,OAAO,CAAC,IAAI,+BAA+B,gBAAgB,IAAI,CAC9G,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,sCAAsC,OAAO,CAAC,IAAI,GAAG,CAAC;IACxE,OAAO,qCAAqC,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAC9F,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const SKILL_AUTHOR_ONLY_DIRECTORIES = new Set(['evals', 'reports']);
|
|
2
|
+
function pathSegments(relativePath) {
|
|
3
|
+
return relativePath.split(/[\\/]/u).filter(Boolean);
|
|
4
|
+
}
|
|
5
|
+
export function isSkillAuthorOnlyPath(relativePath) {
|
|
6
|
+
const [topLevel] = pathSegments(relativePath);
|
|
7
|
+
return topLevel !== undefined && SKILL_AUTHOR_ONLY_DIRECTORIES.has(topLevel);
|
|
8
|
+
}
|
|
9
|
+
export function isSkillCollectionAuthorOnlyPath(relativePath) {
|
|
10
|
+
const [, skillTopLevel] = pathSegments(relativePath);
|
|
11
|
+
return skillTopLevel !== undefined && SKILL_AUTHOR_ONLY_DIRECTORIES.has(skillTopLevel);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=skill-authoring.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-authoring.js","sourceRoot":"","sources":["../src/skill-authoring.ts"],"names":[],"mappings":"AAAA,MAAM,6BAA6B,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;AAEpE,SAAS,YAAY,CAAC,YAAoB;IACxC,OAAO,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,YAAoB;IACxD,MAAM,CAAC,QAAQ,CAAC,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;IAC9C,OAAO,QAAQ,KAAK,SAAS,IAAI,6BAA6B,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,+BAA+B,CAAC,YAAoB;IAClE,MAAM,CAAC,EAAE,aAAa,CAAC,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;IACrD,OAAO,aAAa,KAAK,SAAS,IAAI,6BAA6B,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;AACzF,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export type SkillFrontmatterProfile = 'portable-agent-skills' | 'claude-2.1.88' | 'claude-current';
|
|
2
|
+
export type SkillFrontmatterDiagnosticCode = 'unknown-field' | 'known-field-not-supported-by-target-version' | 'known-field-requires-related-field' | 'known-field-invalid-type-value' | 'portable-profile-platform-extension';
|
|
3
|
+
type SkillFrontmatterFieldType = 'boolean' | 'boolean-or-string' | 'boolean-or-string-or-binary-number' | 'object' | 'string' | 'string-map' | 'string-or-integer' | 'string-or-string-array';
|
|
4
|
+
interface SkillFrontmatterFieldCapability {
|
|
5
|
+
owner: 'agent-skills' | 'claude';
|
|
6
|
+
type: SkillFrontmatterFieldType;
|
|
7
|
+
typeByProfile?: Partial<Record<SkillFrontmatterProfile, SkillFrontmatterFieldType>>;
|
|
8
|
+
required?: boolean;
|
|
9
|
+
profiles: SkillFrontmatterProfile[];
|
|
10
|
+
acceptedValues?: string[];
|
|
11
|
+
acceptedValuesByProfile?: Partial<Record<SkillFrontmatterProfile, string[]>>;
|
|
12
|
+
acceptedValuesCaseInsensitive?: boolean;
|
|
13
|
+
acceptedValuesCaseInsensitiveByProfile?: Partial<Record<SkillFrontmatterProfile, boolean>>;
|
|
14
|
+
requires?: Record<string, unknown>;
|
|
15
|
+
introducedVersion?: string | null;
|
|
16
|
+
verifiedAtVersion?: string;
|
|
17
|
+
}
|
|
18
|
+
interface SkillFrontmatterCapabilityRegistry {
|
|
19
|
+
schemaVersion: 1;
|
|
20
|
+
verifiedOn: string;
|
|
21
|
+
requiredSemantics: string;
|
|
22
|
+
profiles: Record<SkillFrontmatterProfile, {
|
|
23
|
+
platform: 'claude' | 'portable';
|
|
24
|
+
targetVersion: string | null;
|
|
25
|
+
description: string;
|
|
26
|
+
}>;
|
|
27
|
+
fields: Record<string, SkillFrontmatterFieldCapability>;
|
|
28
|
+
}
|
|
29
|
+
export interface SkillFrontmatterCapabilityDiagnostic {
|
|
30
|
+
code: SkillFrontmatterDiagnosticCode;
|
|
31
|
+
field: string;
|
|
32
|
+
message: string;
|
|
33
|
+
}
|
|
34
|
+
export declare function getSkillFrontmatterCapabilityRegistry(): SkillFrontmatterCapabilityRegistry;
|
|
35
|
+
export declare function validateSkillFrontmatterCapabilities(frontmatter: Record<string, unknown>, profile: SkillFrontmatterProfile): SkillFrontmatterCapabilityDiagnostic[];
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
const require = createRequire(import.meta.url);
|
|
3
|
+
const registryDocument = require('./skill-frontmatter-capabilities.json');
|
|
4
|
+
const REGISTRY = registryDocument;
|
|
5
|
+
function isRecord(value) {
|
|
6
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
function nonEmptyString(value) {
|
|
9
|
+
return typeof value === 'string' && value.trim().length > 0;
|
|
10
|
+
}
|
|
11
|
+
function isStringArray(value) {
|
|
12
|
+
return Array.isArray(value) && value.every(nonEmptyString);
|
|
13
|
+
}
|
|
14
|
+
function matchesType(value, type) {
|
|
15
|
+
switch (type) {
|
|
16
|
+
case 'boolean':
|
|
17
|
+
return typeof value === 'boolean';
|
|
18
|
+
case 'boolean-or-string':
|
|
19
|
+
return typeof value === 'boolean' || nonEmptyString(value);
|
|
20
|
+
case 'boolean-or-string-or-binary-number':
|
|
21
|
+
return typeof value === 'boolean'
|
|
22
|
+
|| nonEmptyString(value)
|
|
23
|
+
|| value === 0
|
|
24
|
+
|| value === 1;
|
|
25
|
+
case 'object':
|
|
26
|
+
return isRecord(value);
|
|
27
|
+
case 'string':
|
|
28
|
+
return nonEmptyString(value);
|
|
29
|
+
case 'string-map':
|
|
30
|
+
return isRecord(value) && Object.values(value).every((entry) => typeof entry === 'string');
|
|
31
|
+
case 'string-or-integer':
|
|
32
|
+
return nonEmptyString(value) || (typeof value === 'number' && Number.isInteger(value));
|
|
33
|
+
case 'string-or-string-array':
|
|
34
|
+
return nonEmptyString(value) || isStringArray(value);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function unsupportedFieldDiagnostic(field, capability, profile) {
|
|
38
|
+
if (profile === 'portable-agent-skills' && capability.owner !== 'agent-skills') {
|
|
39
|
+
return {
|
|
40
|
+
code: 'portable-profile-platform-extension',
|
|
41
|
+
field,
|
|
42
|
+
message: `field ${JSON.stringify(field)} is a Claude Code extension and is not portable Agent Skills frontmatter`,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const introduced = capability.introducedVersion
|
|
46
|
+
? `; documented minimum is Claude Code ${capability.introducedVersion}`
|
|
47
|
+
: '';
|
|
48
|
+
return {
|
|
49
|
+
code: 'known-field-not-supported-by-target-version',
|
|
50
|
+
field,
|
|
51
|
+
message: `field ${JSON.stringify(field)} is known but is not supported by profile ${JSON.stringify(profile)}${introduced}`,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export function getSkillFrontmatterCapabilityRegistry() {
|
|
55
|
+
return REGISTRY;
|
|
56
|
+
}
|
|
57
|
+
export function validateSkillFrontmatterCapabilities(frontmatter, profile) {
|
|
58
|
+
const diagnostics = [];
|
|
59
|
+
for (const field of Object.keys(frontmatter)) {
|
|
60
|
+
const capability = REGISTRY.fields[field];
|
|
61
|
+
if (!capability) {
|
|
62
|
+
diagnostics.push({
|
|
63
|
+
code: 'unknown-field',
|
|
64
|
+
field,
|
|
65
|
+
message: `field ${JSON.stringify(field)} is not registered for any supported Skill frontmatter profile`,
|
|
66
|
+
});
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (!capability.profiles.includes(profile)) {
|
|
70
|
+
diagnostics.push(unsupportedFieldDiagnostic(field, capability, profile));
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const expectedType = capability.typeByProfile?.[profile] ?? capability.type;
|
|
74
|
+
const value = frontmatter[field];
|
|
75
|
+
if (!matchesType(value, expectedType)) {
|
|
76
|
+
diagnostics.push({
|
|
77
|
+
code: 'known-field-invalid-type-value',
|
|
78
|
+
field,
|
|
79
|
+
message: `field ${JSON.stringify(field)} must have type ${JSON.stringify(expectedType)} in profile ${JSON.stringify(profile)}`,
|
|
80
|
+
});
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const acceptedValues = capability.acceptedValuesByProfile?.[profile]
|
|
84
|
+
?? capability.acceptedValues;
|
|
85
|
+
const acceptedValuesCaseInsensitive = capability.acceptedValuesCaseInsensitiveByProfile?.[profile]
|
|
86
|
+
?? capability.acceptedValuesCaseInsensitive
|
|
87
|
+
?? false;
|
|
88
|
+
if (typeof value === 'string' &&
|
|
89
|
+
acceptedValues &&
|
|
90
|
+
!acceptedValues.includes(acceptedValuesCaseInsensitive ? value.trim().toLowerCase() : value.trim())) {
|
|
91
|
+
diagnostics.push({
|
|
92
|
+
code: 'known-field-invalid-type-value',
|
|
93
|
+
field,
|
|
94
|
+
message: `field ${JSON.stringify(field)} must be one of ${acceptedValues.map((entry) => JSON.stringify(entry)).join(', ')}`,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
for (const [requiredField, requiredValue] of Object.entries(capability.requires ?? {})) {
|
|
98
|
+
if (frontmatter[requiredField] !== requiredValue) {
|
|
99
|
+
diagnostics.push({
|
|
100
|
+
code: 'known-field-requires-related-field',
|
|
101
|
+
field,
|
|
102
|
+
message: `field ${JSON.stringify(field)} requires ${JSON.stringify(requiredField)}=${JSON.stringify(requiredValue)}`,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
for (const [field, capability] of Object.entries(REGISTRY.fields)) {
|
|
108
|
+
if (capability.required &&
|
|
109
|
+
capability.profiles.includes(profile) &&
|
|
110
|
+
frontmatter[field] === undefined) {
|
|
111
|
+
diagnostics.push({
|
|
112
|
+
code: 'known-field-invalid-type-value',
|
|
113
|
+
field,
|
|
114
|
+
message: `required field ${JSON.stringify(field)} is missing for profile ${JSON.stringify(profile)}`,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return diagnostics;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=skill-frontmatter-capabilities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-frontmatter-capabilities.js","sourceRoot":"","sources":["../src/skill-frontmatter-capabilities.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"verifiedOn": "2026-08-12",
|
|
4
|
+
"requiredSemantics": "required is an AW authoring/package policy, not a claim that every host parser rejects omission",
|
|
5
|
+
"sources": {
|
|
6
|
+
"agentSkills": "https://agentskills.io/specification",
|
|
7
|
+
"claudeCurrent": "https://code.claude.com/docs/en/skills",
|
|
8
|
+
"claudeMinimum": "Claude Code 2.1.88 source snapshot: src/utils/frontmatterParser.ts and src/skills/loadSkillsDir.ts"
|
|
9
|
+
},
|
|
10
|
+
"profiles": {
|
|
11
|
+
"portable-agent-skills": {
|
|
12
|
+
"platform": "portable",
|
|
13
|
+
"targetVersion": null,
|
|
14
|
+
"description": "Agent Skills portable frontmatter only."
|
|
15
|
+
},
|
|
16
|
+
"claude-2.1.88": {
|
|
17
|
+
"platform": "claude",
|
|
18
|
+
"targetVersion": "2.1.88",
|
|
19
|
+
"description": "Claude Code fields verified at the AW minimum supported version."
|
|
20
|
+
},
|
|
21
|
+
"claude-current": {
|
|
22
|
+
"platform": "claude",
|
|
23
|
+
"targetVersion": "current",
|
|
24
|
+
"description": "Fields documented by current Claude Code documentation on the verification date."
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"fields": {
|
|
28
|
+
"name": {
|
|
29
|
+
"owner": "agent-skills",
|
|
30
|
+
"type": "string",
|
|
31
|
+
"required": true,
|
|
32
|
+
"profiles": ["portable-agent-skills", "claude-2.1.88", "claude-current"]
|
|
33
|
+
},
|
|
34
|
+
"description": {
|
|
35
|
+
"owner": "agent-skills",
|
|
36
|
+
"type": "string",
|
|
37
|
+
"required": true,
|
|
38
|
+
"profiles": ["portable-agent-skills", "claude-2.1.88", "claude-current"]
|
|
39
|
+
},
|
|
40
|
+
"license": {
|
|
41
|
+
"owner": "agent-skills",
|
|
42
|
+
"type": "string",
|
|
43
|
+
"profiles": ["portable-agent-skills", "claude-2.1.88", "claude-current"]
|
|
44
|
+
},
|
|
45
|
+
"compatibility": {
|
|
46
|
+
"owner": "agent-skills",
|
|
47
|
+
"type": "string",
|
|
48
|
+
"profiles": ["portable-agent-skills", "claude-2.1.88", "claude-current"]
|
|
49
|
+
},
|
|
50
|
+
"metadata": {
|
|
51
|
+
"owner": "agent-skills",
|
|
52
|
+
"type": "string-map",
|
|
53
|
+
"typeByProfile": {
|
|
54
|
+
"claude-current": "object"
|
|
55
|
+
},
|
|
56
|
+
"profiles": ["portable-agent-skills", "claude-2.1.88", "claude-current"]
|
|
57
|
+
},
|
|
58
|
+
"allowed-tools": {
|
|
59
|
+
"owner": "agent-skills",
|
|
60
|
+
"type": "string",
|
|
61
|
+
"typeByProfile": {
|
|
62
|
+
"claude-2.1.88": "string-or-string-array",
|
|
63
|
+
"claude-current": "string-or-string-array"
|
|
64
|
+
},
|
|
65
|
+
"profiles": ["portable-agent-skills", "claude-2.1.88", "claude-current"]
|
|
66
|
+
},
|
|
67
|
+
"when_to_use": {
|
|
68
|
+
"owner": "claude",
|
|
69
|
+
"type": "string",
|
|
70
|
+
"verifiedAtVersion": "2.1.88",
|
|
71
|
+
"profiles": ["claude-2.1.88", "claude-current"]
|
|
72
|
+
},
|
|
73
|
+
"argument-hint": {
|
|
74
|
+
"owner": "claude",
|
|
75
|
+
"type": "string",
|
|
76
|
+
"verifiedAtVersion": "2.1.88",
|
|
77
|
+
"profiles": ["claude-2.1.88", "claude-current"]
|
|
78
|
+
},
|
|
79
|
+
"arguments": {
|
|
80
|
+
"owner": "claude",
|
|
81
|
+
"type": "string-or-string-array",
|
|
82
|
+
"verifiedAtVersion": "2.1.88",
|
|
83
|
+
"profiles": ["claude-2.1.88", "claude-current"]
|
|
84
|
+
},
|
|
85
|
+
"version": {
|
|
86
|
+
"owner": "claude",
|
|
87
|
+
"type": "string",
|
|
88
|
+
"verifiedAtVersion": "2.1.88",
|
|
89
|
+
"profiles": ["claude-2.1.88", "claude-current"]
|
|
90
|
+
},
|
|
91
|
+
"disable-model-invocation": {
|
|
92
|
+
"owner": "claude",
|
|
93
|
+
"type": "boolean-or-string-or-binary-number",
|
|
94
|
+
"typeByProfile": {
|
|
95
|
+
"claude-2.1.88": "boolean-or-string"
|
|
96
|
+
},
|
|
97
|
+
"acceptedValuesByProfile": {
|
|
98
|
+
"claude-2.1.88": ["true", "false"],
|
|
99
|
+
"claude-current": ["true", "false", "yes", "no", "on", "off", "1", "0"]
|
|
100
|
+
},
|
|
101
|
+
"acceptedValuesCaseInsensitiveByProfile": {
|
|
102
|
+
"claude-current": true
|
|
103
|
+
},
|
|
104
|
+
"verifiedAtVersion": "2.1.88",
|
|
105
|
+
"profiles": ["claude-2.1.88", "claude-current"]
|
|
106
|
+
},
|
|
107
|
+
"user-invocable": {
|
|
108
|
+
"owner": "claude",
|
|
109
|
+
"type": "boolean-or-string-or-binary-number",
|
|
110
|
+
"typeByProfile": {
|
|
111
|
+
"claude-2.1.88": "boolean-or-string"
|
|
112
|
+
},
|
|
113
|
+
"acceptedValuesByProfile": {
|
|
114
|
+
"claude-2.1.88": ["true", "false"],
|
|
115
|
+
"claude-current": ["true", "false", "yes", "no", "on", "off", "1", "0"]
|
|
116
|
+
},
|
|
117
|
+
"acceptedValuesCaseInsensitiveByProfile": {
|
|
118
|
+
"claude-current": true
|
|
119
|
+
},
|
|
120
|
+
"verifiedAtVersion": "2.1.88",
|
|
121
|
+
"profiles": ["claude-2.1.88", "claude-current"]
|
|
122
|
+
},
|
|
123
|
+
"disallowed-tools": {
|
|
124
|
+
"owner": "claude",
|
|
125
|
+
"type": "string-or-string-array",
|
|
126
|
+
"introducedVersion": null,
|
|
127
|
+
"profiles": ["claude-current"]
|
|
128
|
+
},
|
|
129
|
+
"model": {
|
|
130
|
+
"owner": "claude",
|
|
131
|
+
"type": "string",
|
|
132
|
+
"verifiedAtVersion": "2.1.88",
|
|
133
|
+
"profiles": ["claude-2.1.88", "claude-current"]
|
|
134
|
+
},
|
|
135
|
+
"effort": {
|
|
136
|
+
"owner": "claude",
|
|
137
|
+
"type": "string",
|
|
138
|
+
"typeByProfile": {
|
|
139
|
+
"claude-2.1.88": "string-or-integer"
|
|
140
|
+
},
|
|
141
|
+
"verifiedAtVersion": "2.1.88",
|
|
142
|
+
"acceptedValuesByProfile": {
|
|
143
|
+
"claude-2.1.88": ["low", "medium", "high", "max"],
|
|
144
|
+
"claude-current": ["low", "medium", "high", "xhigh", "max"]
|
|
145
|
+
},
|
|
146
|
+
"acceptedValuesCaseInsensitive": true,
|
|
147
|
+
"profiles": ["claude-2.1.88", "claude-current"]
|
|
148
|
+
},
|
|
149
|
+
"context": {
|
|
150
|
+
"owner": "claude",
|
|
151
|
+
"type": "string",
|
|
152
|
+
"acceptedValuesByProfile": {
|
|
153
|
+
"claude-2.1.88": ["inline", "fork"],
|
|
154
|
+
"claude-current": ["fork"]
|
|
155
|
+
},
|
|
156
|
+
"verifiedAtVersion": "2.1.88",
|
|
157
|
+
"profiles": ["claude-2.1.88", "claude-current"]
|
|
158
|
+
},
|
|
159
|
+
"agent": {
|
|
160
|
+
"owner": "claude",
|
|
161
|
+
"type": "string",
|
|
162
|
+
"requires": {
|
|
163
|
+
"context": "fork"
|
|
164
|
+
},
|
|
165
|
+
"verifiedAtVersion": "2.1.88",
|
|
166
|
+
"profiles": ["claude-2.1.88", "claude-current"]
|
|
167
|
+
},
|
|
168
|
+
"background": {
|
|
169
|
+
"owner": "claude",
|
|
170
|
+
"type": "boolean-or-string-or-binary-number",
|
|
171
|
+
"acceptedValues": ["true", "false", "yes", "no", "on", "off", "1", "0"],
|
|
172
|
+
"acceptedValuesCaseInsensitive": true,
|
|
173
|
+
"requires": {
|
|
174
|
+
"context": "fork"
|
|
175
|
+
},
|
|
176
|
+
"introducedVersion": "2.1.218",
|
|
177
|
+
"profiles": ["claude-current"]
|
|
178
|
+
},
|
|
179
|
+
"hooks": {
|
|
180
|
+
"owner": "claude",
|
|
181
|
+
"type": "object",
|
|
182
|
+
"verifiedAtVersion": "2.1.88",
|
|
183
|
+
"profiles": ["claude-2.1.88", "claude-current"]
|
|
184
|
+
},
|
|
185
|
+
"paths": {
|
|
186
|
+
"owner": "claude",
|
|
187
|
+
"type": "string-or-string-array",
|
|
188
|
+
"verifiedAtVersion": "2.1.88",
|
|
189
|
+
"profiles": ["claude-2.1.88", "claude-current"]
|
|
190
|
+
},
|
|
191
|
+
"shell": {
|
|
192
|
+
"owner": "claude",
|
|
193
|
+
"type": "string",
|
|
194
|
+
"acceptedValues": ["bash", "powershell"],
|
|
195
|
+
"acceptedValuesCaseInsensitive": true,
|
|
196
|
+
"verifiedAtVersion": "2.1.88",
|
|
197
|
+
"profiles": ["claude-2.1.88", "claude-current"]
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|