agentic-skill-mill 1.0.3
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 +135 -0
- package/dist/cache/cache-manager.d.ts +27 -0
- package/dist/cache/cache-manager.d.ts.map +1 -0
- package/dist/cache/cache-manager.js +139 -0
- package/dist/cache/cache-manager.js.map +1 -0
- package/dist/cli/commands/check-exports.d.ts +6 -0
- package/dist/cli/commands/check-exports.d.ts.map +1 -0
- package/dist/cli/commands/check-exports.js +7 -0
- package/dist/cli/commands/check-exports.js.map +1 -0
- package/dist/cli/commands/list-project.d.ts +6 -0
- package/dist/cli/commands/list-project.d.ts.map +1 -0
- package/dist/cli/commands/list-project.js +7 -0
- package/dist/cli/commands/list-project.js.map +1 -0
- package/dist/cli/commands/scaffold.d.ts +6 -0
- package/dist/cli/commands/scaffold.d.ts.map +1 -0
- package/dist/cli/commands/scaffold.js +11 -0
- package/dist/cli/commands/scaffold.js.map +1 -0
- package/dist/cli/commands/validate-manifest.d.ts +6 -0
- package/dist/cli/commands/validate-manifest.d.ts.map +1 -0
- package/dist/cli/commands/validate-manifest.js +7 -0
- package/dist/cli/commands/validate-manifest.js.map +1 -0
- package/dist/cli/commands/validate-skill.d.ts +6 -0
- package/dist/cli/commands/validate-skill.d.ts.map +1 -0
- package/dist/cli/commands/validate-skill.js +8 -0
- package/dist/cli/commands/validate-skill.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +268 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/output-formatter.d.ts +6 -0
- package/dist/cli/output-formatter.d.ts.map +1 -0
- package/dist/cli/output-formatter.js +19 -0
- package/dist/cli/output-formatter.js.map +1 -0
- package/dist/core/check-exports.d.ts +21 -0
- package/dist/core/check-exports.d.ts.map +1 -0
- package/dist/core/check-exports.js +67 -0
- package/dist/core/check-exports.js.map +1 -0
- package/dist/core/list-project.d.ts +31 -0
- package/dist/core/list-project.d.ts.map +1 -0
- package/dist/core/list-project.js +118 -0
- package/dist/core/list-project.js.map +1 -0
- package/dist/core/scaffold.d.ts +24 -0
- package/dist/core/scaffold.d.ts.map +1 -0
- package/dist/core/scaffold.js +168 -0
- package/dist/core/scaffold.js.map +1 -0
- package/dist/core/validate-manifest.d.ts +21 -0
- package/dist/core/validate-manifest.d.ts.map +1 -0
- package/dist/core/validate-manifest.js +151 -0
- package/dist/core/validate-manifest.js.map +1 -0
- package/dist/core/validate-skill.d.ts +24 -0
- package/dist/core/validate-skill.d.ts.map +1 -0
- package/dist/core/validate-skill.js +149 -0
- package/dist/core/validate-skill.js.map +1 -0
- package/dist/errors/types.d.ts +19 -0
- package/dist/errors/types.d.ts.map +1 -0
- package/dist/errors/types.js +40 -0
- package/dist/errors/types.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/package.json +56 -0
- package/skill/build/compile.mjs +385 -0
- package/skill/build/manifest.json +29 -0
- package/skill/fragments/meta/architecture-overview.md +37 -0
- package/skill/fragments/meta/cli-command-pattern.md +83 -0
- package/skill/fragments/meta/core-module-pattern.md +38 -0
- package/skill/fragments/meta/fragment-composition.md +40 -0
- package/skill/fragments/meta/rename-workflow.md +51 -0
- package/skill/fragments/meta/research-to-code.md +44 -0
- package/skill/skills/agentic-skill-mill/agentic-skill-mill.md +133 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { AppError } from '../errors/types.js';
|
|
4
|
+
export async function scaffold(options) {
|
|
5
|
+
const { kind, name, cwd } = options;
|
|
6
|
+
const warnings = [];
|
|
7
|
+
// Validate name
|
|
8
|
+
if (name !== name.toLowerCase()) {
|
|
9
|
+
throw new AppError(`Name must be lowercase: "${name}"`, 'VALIDATION_ERROR');
|
|
10
|
+
}
|
|
11
|
+
if (/\s/.test(name)) {
|
|
12
|
+
throw new AppError(`Name must not contain spaces: "${name}"`, 'VALIDATION_ERROR');
|
|
13
|
+
}
|
|
14
|
+
if (!/^[a-z][a-z0-9-]*$/.test(name)) {
|
|
15
|
+
throw new AppError(`Name must be lowercase kebab-case: "${name}"`, 'VALIDATION_ERROR');
|
|
16
|
+
}
|
|
17
|
+
switch (kind) {
|
|
18
|
+
case 'command':
|
|
19
|
+
return scaffoldCommand(name, cwd, warnings);
|
|
20
|
+
case 'skill':
|
|
21
|
+
return scaffoldSkill(name, cwd, options.description, warnings);
|
|
22
|
+
case 'fragment':
|
|
23
|
+
return scaffoldFragment(name, cwd, options.category ?? 'domain', warnings);
|
|
24
|
+
default:
|
|
25
|
+
throw new AppError(`Unknown scaffold kind: "${kind}"`, 'VALIDATION_ERROR');
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function toPascalCase(kebab) {
|
|
29
|
+
return kebab.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join('');
|
|
30
|
+
}
|
|
31
|
+
function toCamelCase(kebab) {
|
|
32
|
+
const pascal = toPascalCase(kebab);
|
|
33
|
+
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
|
34
|
+
}
|
|
35
|
+
async function scaffoldCommand(name, cwd, warnings) {
|
|
36
|
+
const pascal = toPascalCase(name);
|
|
37
|
+
const camel = toCamelCase(name);
|
|
38
|
+
const coreContent = `export interface ${pascal}Options {
|
|
39
|
+
cwd: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface ${pascal}Result {
|
|
43
|
+
warnings: string[];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export async function ${camel}(options: ${pascal}Options): Promise<${pascal}Result> {
|
|
47
|
+
const warnings: string[] = [];
|
|
48
|
+
|
|
49
|
+
// TODO: implement domain logic
|
|
50
|
+
|
|
51
|
+
return { warnings };
|
|
52
|
+
}
|
|
53
|
+
`;
|
|
54
|
+
const commandContent = `import { ${camel}, type ${pascal}Options, type ${pascal}Result } from '../../core/${name}.js';
|
|
55
|
+
|
|
56
|
+
export interface ${pascal}CommandOptions extends ${pascal}Options {
|
|
57
|
+
json: boolean;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export async function ${camel}Command(
|
|
61
|
+
options: ${pascal}CommandOptions,
|
|
62
|
+
): Promise<${pascal}Result> {
|
|
63
|
+
return ${camel}({
|
|
64
|
+
cwd: options.cwd,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
`;
|
|
68
|
+
// Check for existing files
|
|
69
|
+
const corePath = path.join(cwd, 'src', 'core', `${name}.ts`);
|
|
70
|
+
const cmdPath = path.join(cwd, 'src', 'cli', 'commands', `${name}.ts`);
|
|
71
|
+
try {
|
|
72
|
+
await fs.access(corePath);
|
|
73
|
+
warnings.push(`Core module already exists: src/core/${name}.ts`);
|
|
74
|
+
}
|
|
75
|
+
catch { /* does not exist, good */ }
|
|
76
|
+
try {
|
|
77
|
+
await fs.access(cmdPath);
|
|
78
|
+
warnings.push(`Command wrapper already exists: src/cli/commands/${name}.ts`);
|
|
79
|
+
}
|
|
80
|
+
catch { /* does not exist, good */ }
|
|
81
|
+
return {
|
|
82
|
+
kind: 'command',
|
|
83
|
+
name,
|
|
84
|
+
files: [
|
|
85
|
+
{ path: `src/core/${name}.ts`, content: coreContent, action: 'create' },
|
|
86
|
+
{ path: `src/cli/commands/${name}.ts`, content: commandContent, action: 'create' },
|
|
87
|
+
],
|
|
88
|
+
instructions: [
|
|
89
|
+
`Wire the command into src/cli/index.ts`,
|
|
90
|
+
`Export the public API from src/index.ts`,
|
|
91
|
+
`Run: npm run build && node dist/cli/index.js ${name} --help`,
|
|
92
|
+
],
|
|
93
|
+
warnings,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
async function scaffoldSkill(name, cwd, description, warnings) {
|
|
97
|
+
const desc = description ?? `Skill description for ${name}. Update this.`;
|
|
98
|
+
const skillContent = `---
|
|
99
|
+
name: ${name}
|
|
100
|
+
description: "${desc}"
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
# ${toPascalCase(name).replace(/([A-Z])/g, ' $1').trim()}
|
|
104
|
+
|
|
105
|
+
${desc}
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Section Name
|
|
110
|
+
|
|
111
|
+
Direct content here, or use fragment includes:
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Another Section
|
|
116
|
+
|
|
117
|
+
More content.
|
|
118
|
+
`;
|
|
119
|
+
const skillDir = path.join(cwd, 'skill', 'skills', name);
|
|
120
|
+
try {
|
|
121
|
+
await fs.access(skillDir);
|
|
122
|
+
warnings.push(`Skill directory already exists: skill/skills/${name}/`);
|
|
123
|
+
}
|
|
124
|
+
catch { /* does not exist, good */ }
|
|
125
|
+
return {
|
|
126
|
+
kind: 'skill',
|
|
127
|
+
name,
|
|
128
|
+
files: [
|
|
129
|
+
{ path: `skill/skills/${name}/${name}.md`, content: skillContent, action: 'create' },
|
|
130
|
+
],
|
|
131
|
+
instructions: [
|
|
132
|
+
`Add skill entry to skill/build/manifest.json`,
|
|
133
|
+
`Add "${name}" to the SKILLS array in install.sh`,
|
|
134
|
+
`Run: npm run compile`,
|
|
135
|
+
],
|
|
136
|
+
warnings,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
async function scaffoldFragment(name, cwd, category, warnings) {
|
|
140
|
+
const validCategories = ['common', 'domain', 'meta'];
|
|
141
|
+
if (!validCategories.includes(category)) {
|
|
142
|
+
warnings.push(`Category "${category}" is non-standard. Conventional categories: ${validCategories.join(', ')}`);
|
|
143
|
+
}
|
|
144
|
+
const fragmentContent = `### ${toPascalCase(name).replace(/([A-Z])/g, ' $1').trim()}
|
|
145
|
+
|
|
146
|
+
Content for the ${name} fragment. Replace this with actual knowledge.
|
|
147
|
+
`;
|
|
148
|
+
const fragPath = path.join(cwd, 'skill', 'fragments', category, `${name}.md`);
|
|
149
|
+
try {
|
|
150
|
+
await fs.access(fragPath);
|
|
151
|
+
warnings.push(`Fragment already exists: skill/fragments/${category}/${name}.md`);
|
|
152
|
+
}
|
|
153
|
+
catch { /* does not exist, good */ }
|
|
154
|
+
return {
|
|
155
|
+
kind: 'fragment',
|
|
156
|
+
name,
|
|
157
|
+
files: [
|
|
158
|
+
{ path: `skill/fragments/${category}/${name}.md`, content: fragmentContent, action: 'create' },
|
|
159
|
+
],
|
|
160
|
+
instructions: [
|
|
161
|
+
`Include in a skill source with: {{include:${category}/${name}.md}}`,
|
|
162
|
+
`Declare in manifest.json under the skill's "fragments" array`,
|
|
163
|
+
`Run: npm run compile`,
|
|
164
|
+
],
|
|
165
|
+
warnings,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=scaffold.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/core/scaffold.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface ValidateManifestOptions {
|
|
2
|
+
manifestPath: string;
|
|
3
|
+
}
|
|
4
|
+
export interface ManifestIssue {
|
|
5
|
+
severity: 'error' | 'warning';
|
|
6
|
+
rule: string;
|
|
7
|
+
message: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ValidateManifestResult {
|
|
10
|
+
manifestPath: string;
|
|
11
|
+
valid: boolean;
|
|
12
|
+
issues: ManifestIssue[];
|
|
13
|
+
stats: {
|
|
14
|
+
skills: number;
|
|
15
|
+
fragments: number;
|
|
16
|
+
targets: number;
|
|
17
|
+
};
|
|
18
|
+
warnings: string[];
|
|
19
|
+
}
|
|
20
|
+
export declare function validateManifest(options: ValidateManifestOptions): Promise<ValidateManifestResult>;
|
|
21
|
+
//# sourceMappingURL=validate-manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-manifest.d.ts","sourceRoot":"","sources":["../../src/core/validate-manifest.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,KAAK,EAAE;QACL,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAsBD,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAmJxG"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { ConfigError, NotFoundError } from '../errors/types.js';
|
|
4
|
+
const KNOWN_TARGETS = [
|
|
5
|
+
'claude', 'cursor-rules', 'cursor-skills',
|
|
6
|
+
'windsurf-rules', 'windsurf-skills', 'opencode', 'codex',
|
|
7
|
+
];
|
|
8
|
+
export async function validateManifest(options) {
|
|
9
|
+
const { manifestPath } = options;
|
|
10
|
+
const issues = [];
|
|
11
|
+
const warnings = [];
|
|
12
|
+
let raw;
|
|
13
|
+
try {
|
|
14
|
+
raw = await fs.readFile(manifestPath, 'utf-8');
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
throw new NotFoundError('manifest', manifestPath, 'File does not exist or is not readable');
|
|
18
|
+
}
|
|
19
|
+
let manifest;
|
|
20
|
+
try {
|
|
21
|
+
manifest = JSON.parse(raw);
|
|
22
|
+
}
|
|
23
|
+
catch (e) {
|
|
24
|
+
throw new ConfigError('Invalid JSON', manifestPath, e instanceof Error ? e : undefined);
|
|
25
|
+
}
|
|
26
|
+
// Required top-level keys
|
|
27
|
+
if (!manifest.targets || !Array.isArray(manifest.targets)) {
|
|
28
|
+
issues.push({ severity: 'error', rule: 'missing-targets', message: 'Missing or invalid "targets" array' });
|
|
29
|
+
}
|
|
30
|
+
if (!manifest.skills || typeof manifest.skills !== 'object') {
|
|
31
|
+
issues.push({ severity: 'error', rule: 'missing-skills', message: 'Missing or invalid "skills" object' });
|
|
32
|
+
}
|
|
33
|
+
if (!manifest.naming_rules || typeof manifest.naming_rules !== 'object') {
|
|
34
|
+
issues.push({ severity: 'warning', rule: 'missing-naming-rules', message: 'Missing "naming_rules" object' });
|
|
35
|
+
}
|
|
36
|
+
if (issues.some(i => i.rule === 'missing-skills')) {
|
|
37
|
+
return {
|
|
38
|
+
manifestPath,
|
|
39
|
+
valid: false,
|
|
40
|
+
issues,
|
|
41
|
+
stats: { skills: 0, fragments: 0, targets: 0 },
|
|
42
|
+
warnings,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
// Validate targets
|
|
46
|
+
for (const target of manifest.targets ?? []) {
|
|
47
|
+
if (!KNOWN_TARGETS.includes(target)) {
|
|
48
|
+
issues.push({
|
|
49
|
+
severity: 'warning',
|
|
50
|
+
rule: 'unknown-target',
|
|
51
|
+
message: `Unknown target "${target}". Known: ${KNOWN_TARGETS.join(', ')}`,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const skillRoot = path.dirname(path.dirname(manifestPath));
|
|
56
|
+
const fragmentsDir = path.join(skillRoot, 'fragments');
|
|
57
|
+
const allFragments = new Set();
|
|
58
|
+
// Validate each skill
|
|
59
|
+
for (const [skillName, skillDef] of Object.entries(manifest.skills)) {
|
|
60
|
+
// Naming validation
|
|
61
|
+
if (skillName !== skillName.toLowerCase()) {
|
|
62
|
+
issues.push({ severity: 'error', rule: 'name-case', message: `Skill name not lowercase: "${skillName}"` });
|
|
63
|
+
}
|
|
64
|
+
if (/\s/.test(skillName)) {
|
|
65
|
+
issues.push({ severity: 'error', rule: 'name-spaces', message: `Skill name contains spaces: "${skillName}"` });
|
|
66
|
+
}
|
|
67
|
+
if (manifest.naming_rules?.forbidden_suffixes) {
|
|
68
|
+
for (const suffix of manifest.naming_rules.forbidden_suffixes) {
|
|
69
|
+
if (skillName.endsWith(`-${suffix}`) || skillName === suffix) {
|
|
70
|
+
issues.push({ severity: 'error', rule: 'name-forbidden-suffix', message: `Skill "${skillName}" uses forbidden suffix "${suffix}"` });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Source file exists
|
|
75
|
+
if (!skillDef.source) {
|
|
76
|
+
issues.push({ severity: 'error', rule: 'missing-source', message: `Skill "${skillName}" has no "source" field` });
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
const sourcePath = path.join(skillRoot, skillDef.source);
|
|
80
|
+
try {
|
|
81
|
+
await fs.access(sourcePath);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
issues.push({ severity: 'error', rule: 'source-not-found', message: `Source file not found: ${skillDef.source}` });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Fragments exist
|
|
88
|
+
if (!Array.isArray(skillDef.fragments)) {
|
|
89
|
+
issues.push({ severity: 'warning', rule: 'missing-fragments-array', message: `Skill "${skillName}" has no "fragments" array` });
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
for (const frag of skillDef.fragments) {
|
|
93
|
+
allFragments.add(frag);
|
|
94
|
+
const fragPath = path.join(fragmentsDir, frag);
|
|
95
|
+
try {
|
|
96
|
+
await fs.access(fragPath);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
issues.push({ severity: 'error', rule: 'fragment-not-found', message: `Fragment not found: ${frag} (declared in "${skillName}")` });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Cross-validate: check source includes match declared fragments
|
|
104
|
+
if (skillDef.source) {
|
|
105
|
+
const sourcePath = path.join(skillRoot, skillDef.source);
|
|
106
|
+
try {
|
|
107
|
+
const source = await fs.readFile(sourcePath, 'utf-8');
|
|
108
|
+
const includePattern = /\{\{include:([^}]+)\}\}/g;
|
|
109
|
+
const actualIncludes = new Set();
|
|
110
|
+
let match;
|
|
111
|
+
while ((match = includePattern.exec(source)) !== null) {
|
|
112
|
+
actualIncludes.add(match[1].trim());
|
|
113
|
+
}
|
|
114
|
+
const declared = new Set(skillDef.fragments ?? []);
|
|
115
|
+
for (const inc of actualIncludes) {
|
|
116
|
+
if (!declared.has(inc)) {
|
|
117
|
+
issues.push({
|
|
118
|
+
severity: 'error',
|
|
119
|
+
rule: 'undeclared-include',
|
|
120
|
+
message: `Undeclared fragment in "${skillName}": ${inc} (in source but not in manifest)`,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
for (const dec of declared) {
|
|
125
|
+
if (!actualIncludes.has(dec)) {
|
|
126
|
+
issues.push({
|
|
127
|
+
severity: 'warning',
|
|
128
|
+
rule: 'unused-declared-fragment',
|
|
129
|
+
message: `Unused declared fragment in "${skillName}": ${dec} (in manifest but not in source)`,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// Source not readable; already reported above
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
manifestPath,
|
|
141
|
+
valid: issues.filter(i => i.severity === 'error').length === 0,
|
|
142
|
+
issues,
|
|
143
|
+
stats: {
|
|
144
|
+
skills: Object.keys(manifest.skills).length,
|
|
145
|
+
fragments: allFragments.size,
|
|
146
|
+
targets: (manifest.targets ?? []).length,
|
|
147
|
+
},
|
|
148
|
+
warnings,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=validate-manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-manifest.js","sourceRoot":"","sources":["../../src/core/validate-manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface ValidateSkillOptions {
|
|
2
|
+
skillPath: string;
|
|
3
|
+
fragmentsDir?: string;
|
|
4
|
+
}
|
|
5
|
+
export interface SkillIssue {
|
|
6
|
+
severity: 'error' | 'warning';
|
|
7
|
+
line: number;
|
|
8
|
+
rule: string;
|
|
9
|
+
message: string;
|
|
10
|
+
}
|
|
11
|
+
export interface ValidateSkillResult {
|
|
12
|
+
skillPath: string;
|
|
13
|
+
valid: boolean;
|
|
14
|
+
issues: SkillIssue[];
|
|
15
|
+
stats: {
|
|
16
|
+
includes: number;
|
|
17
|
+
sections: number;
|
|
18
|
+
wordCount: number;
|
|
19
|
+
};
|
|
20
|
+
frontmatter: Record<string, string>;
|
|
21
|
+
warnings: string[];
|
|
22
|
+
}
|
|
23
|
+
export declare function validateSkill(options: ValidateSkillOptions): Promise<ValidateSkillResult>;
|
|
24
|
+
//# sourceMappingURL=validate-skill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-skill.d.ts","sourceRoot":"","sources":["../../src/core/validate-skill.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,KAAK,EAAE;QACL,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA0I/F"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { NotFoundError } from '../errors/types.js';
|
|
4
|
+
export async function validateSkill(options) {
|
|
5
|
+
const { skillPath } = options;
|
|
6
|
+
const issues = [];
|
|
7
|
+
const warnings = [];
|
|
8
|
+
let content;
|
|
9
|
+
try {
|
|
10
|
+
content = await fs.readFile(skillPath, 'utf-8');
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
throw new NotFoundError('skill source', skillPath);
|
|
14
|
+
}
|
|
15
|
+
const lines = content.split('\n');
|
|
16
|
+
// Parse frontmatter
|
|
17
|
+
const frontmatter = {};
|
|
18
|
+
let bodyStart = 0;
|
|
19
|
+
if (lines[0] === '---') {
|
|
20
|
+
const endIdx = lines.indexOf('---', 1);
|
|
21
|
+
if (endIdx === -1) {
|
|
22
|
+
issues.push({ severity: 'error', line: 1, rule: 'frontmatter-unclosed', message: 'Frontmatter block is never closed' });
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
bodyStart = endIdx + 1;
|
|
26
|
+
for (let i = 1; i < endIdx; i++) {
|
|
27
|
+
const colonIdx = lines[i].indexOf(':');
|
|
28
|
+
if (colonIdx === -1)
|
|
29
|
+
continue;
|
|
30
|
+
const key = lines[i].slice(0, colonIdx).trim();
|
|
31
|
+
let val = lines[i].slice(colonIdx + 1).trim();
|
|
32
|
+
if ((val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'"))) {
|
|
33
|
+
val = val.slice(1, -1);
|
|
34
|
+
}
|
|
35
|
+
frontmatter[key] = val;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
issues.push({ severity: 'error', line: 1, rule: 'missing-frontmatter', message: 'Skill source must start with YAML frontmatter (---)' });
|
|
41
|
+
}
|
|
42
|
+
// Required frontmatter fields
|
|
43
|
+
if (!frontmatter.name) {
|
|
44
|
+
issues.push({ severity: 'error', line: 1, rule: 'missing-name', message: 'Frontmatter missing required "name" field' });
|
|
45
|
+
}
|
|
46
|
+
if (!frontmatter.description) {
|
|
47
|
+
issues.push({ severity: 'error', line: 1, rule: 'missing-description', message: 'Frontmatter missing required "description" field' });
|
|
48
|
+
}
|
|
49
|
+
// Name should be lowercase kebab-case
|
|
50
|
+
if (frontmatter.name && frontmatter.name !== frontmatter.name.toLowerCase()) {
|
|
51
|
+
issues.push({ severity: 'error', line: 1, rule: 'name-case', message: `Skill name must be lowercase: "${frontmatter.name}"` });
|
|
52
|
+
}
|
|
53
|
+
if (frontmatter.name && /\s/.test(frontmatter.name)) {
|
|
54
|
+
issues.push({ severity: 'error', line: 1, rule: 'name-spaces', message: `Skill name must not contain spaces: "${frontmatter.name}"` });
|
|
55
|
+
}
|
|
56
|
+
// Check body has an H1
|
|
57
|
+
const bodyLines = lines.slice(bodyStart);
|
|
58
|
+
const h1Line = bodyLines.findIndex(l => /^# /.test(l));
|
|
59
|
+
if (h1Line === -1) {
|
|
60
|
+
issues.push({ severity: 'warning', line: bodyStart + 1, rule: 'missing-h1', message: 'Skill body has no H1 heading' });
|
|
61
|
+
}
|
|
62
|
+
// Count sections (H2 headings)
|
|
63
|
+
let sections = 0;
|
|
64
|
+
for (let i = 0; i < bodyLines.length; i++) {
|
|
65
|
+
if (/^## /.test(bodyLines[i])) {
|
|
66
|
+
sections++;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (sections === 0) {
|
|
70
|
+
issues.push({ severity: 'warning', line: bodyStart + 1, rule: 'no-sections', message: 'Skill body has no ## sections' });
|
|
71
|
+
}
|
|
72
|
+
// Collect and validate includes
|
|
73
|
+
const includePattern = /\{\{include:([^}]+)\}\}/g;
|
|
74
|
+
let match;
|
|
75
|
+
const includes = [];
|
|
76
|
+
for (let i = 0; i < lines.length; i++) {
|
|
77
|
+
includePattern.lastIndex = 0;
|
|
78
|
+
while ((match = includePattern.exec(lines[i])) !== null) {
|
|
79
|
+
includes.push({ path: match[1].trim(), line: i + 1 });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Validate fragment files exist if fragmentsDir provided
|
|
83
|
+
// Default: walk up from skill path to find the fragments dir.
|
|
84
|
+
// Skills live at skill/skills/<name>/<name>.md, fragments at skill/fragments/
|
|
85
|
+
const fragmentsDir = options.fragmentsDir ?? findFragmentsDir(skillPath);
|
|
86
|
+
for (const inc of includes) {
|
|
87
|
+
const fragPath = path.join(fragmentsDir, inc.path);
|
|
88
|
+
try {
|
|
89
|
+
await fs.access(fragPath);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
issues.push({
|
|
93
|
+
severity: 'error',
|
|
94
|
+
line: inc.line,
|
|
95
|
+
rule: 'fragment-not-found',
|
|
96
|
+
message: `Fragment file not found: ${inc.path}`,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Check for duplicate includes
|
|
101
|
+
const seen = new Map();
|
|
102
|
+
for (const inc of includes) {
|
|
103
|
+
const prev = seen.get(inc.path);
|
|
104
|
+
if (prev !== undefined) {
|
|
105
|
+
issues.push({
|
|
106
|
+
severity: 'warning',
|
|
107
|
+
line: inc.line,
|
|
108
|
+
rule: 'duplicate-include',
|
|
109
|
+
message: `Duplicate include: ${inc.path} (first at line ${prev})`,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
seen.set(inc.path, inc.line);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Word count of the body (excluding frontmatter and include markers)
|
|
117
|
+
const bodyText = bodyLines.join(' ')
|
|
118
|
+
.replace(/\{\{include:[^}]+\}\}/g, '')
|
|
119
|
+
.replace(/[#*`\-|]/g, ' ');
|
|
120
|
+
const wordCount = bodyText.split(/\s+/).filter(w => w.length > 0).length;
|
|
121
|
+
return {
|
|
122
|
+
skillPath,
|
|
123
|
+
valid: issues.filter(i => i.severity === 'error').length === 0,
|
|
124
|
+
issues,
|
|
125
|
+
stats: {
|
|
126
|
+
includes: includes.length,
|
|
127
|
+
sections,
|
|
128
|
+
wordCount,
|
|
129
|
+
},
|
|
130
|
+
frontmatter,
|
|
131
|
+
warnings,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function findFragmentsDir(skillPath) {
|
|
135
|
+
const resolved = path.resolve(skillPath);
|
|
136
|
+
// Walk up from the skill file to find a directory named "skill" that has a "fragments" child
|
|
137
|
+
let dir = path.dirname(resolved);
|
|
138
|
+
for (let i = 0; i < 6; i++) {
|
|
139
|
+
const candidate = path.join(dir, 'fragments');
|
|
140
|
+
const parentName = path.basename(dir);
|
|
141
|
+
if (parentName === 'skill') {
|
|
142
|
+
return candidate;
|
|
143
|
+
}
|
|
144
|
+
dir = path.dirname(dir);
|
|
145
|
+
}
|
|
146
|
+
// Fallback: two levels up from skill file
|
|
147
|
+
return path.join(path.dirname(path.dirname(resolved)), 'fragments');
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=validate-skill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-skill.js","sourceRoot":"","sources":["../../src/core/validate-skill.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare class AppError extends Error {
|
|
2
|
+
code: string;
|
|
3
|
+
context?: Record<string, unknown> | undefined;
|
|
4
|
+
constructor(message: string, code?: string, context?: Record<string, unknown> | undefined);
|
|
5
|
+
toJSON(): Record<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
export declare class NotFoundError extends AppError {
|
|
8
|
+
constructor(entity: string, identifier: string, context?: string);
|
|
9
|
+
}
|
|
10
|
+
export declare class CommandError extends AppError {
|
|
11
|
+
constructor(command: string, exitCode: number, stderr?: string);
|
|
12
|
+
}
|
|
13
|
+
export declare class CacheError extends AppError {
|
|
14
|
+
constructor(message: string, operation: 'read' | 'write' | 'clear', cause?: Error);
|
|
15
|
+
}
|
|
16
|
+
export declare class ConfigError extends AppError {
|
|
17
|
+
constructor(message: string, filePath?: string, cause?: Error);
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/errors/types.ts"],"names":[],"mappings":"AAAA,qBAAa,QAAS,SAAQ,KAAK;IAGxB,IAAI,EAAE,MAAM;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;gBAFxC,OAAO,EAAE,MAAM,EACR,IAAI,GAAE,MAAwB,EAC9B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YAAA;IAO1C,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAQlC;AAED,qBAAa,aAAc,SAAQ,QAAQ;gBAC7B,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;CAOjE;AAED,qBAAa,YAAa,SAAQ,QAAQ;gBAEtC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,MAAM;CAQlB;AAED,qBAAa,UAAW,SAAQ,QAAQ;gBAEpC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,EACrC,KAAK,CAAC,EAAE,KAAK;CAQhB;AAED,qBAAa,WAAY,SAAQ,QAAQ;gBAErC,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE,KAAK;CAQhB"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export class AppError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
context;
|
|
4
|
+
constructor(message, code = 'UNKNOWN_ERROR', context) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.code = code;
|
|
7
|
+
this.context = context;
|
|
8
|
+
this.name = this.constructor.name;
|
|
9
|
+
Error.captureStackTrace(this, this.constructor);
|
|
10
|
+
}
|
|
11
|
+
toJSON() {
|
|
12
|
+
return {
|
|
13
|
+
name: this.name,
|
|
14
|
+
code: this.code,
|
|
15
|
+
message: this.message,
|
|
16
|
+
context: this.context,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export class NotFoundError extends AppError {
|
|
21
|
+
constructor(entity, identifier, context) {
|
|
22
|
+
super(`${entity} not found: ${identifier}${context ? ` in ${context}` : ''}`, 'NOT_FOUND_ERROR', { entity, identifier, context });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export class CommandError extends AppError {
|
|
26
|
+
constructor(command, exitCode, stderr) {
|
|
27
|
+
super(`Command failed: ${command} (exit code ${exitCode})${stderr ? `: ${stderr}` : ''}`, 'COMMAND_ERROR', { command, exitCode, stderr });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export class CacheError extends AppError {
|
|
31
|
+
constructor(message, operation, cause) {
|
|
32
|
+
super(`Cache ${operation} failed: ${message}`, 'CACHE_ERROR', { operation, cause: cause?.message });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export class ConfigError extends AppError {
|
|
36
|
+
constructor(message, filePath, cause) {
|
|
37
|
+
super(filePath ? `Config error in ${filePath}: ${message}` : `Config error: ${message}`, 'CONFIG_ERROR', { filePath, cause: cause?.message });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/errors/types.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,QAAS,SAAQ,KAAK;IAGxB;IACA;IAHT,YACE,OAAe,EACR,OAAe,eAAe,EAC9B,OAAiC;QAExC,KAAK,CAAC,OAAO,CAAC,CAAC;QAHR,SAAI,GAAJ,IAAI,CAA0B;QAC9B,YAAO,GAAP,OAAO,CAA0B;QAGxC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QAClC,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAClD,CAAC;IAED,MAAM;QACJ,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC;IACJ,CAAC;CACF;AAED,MAAM,OAAO,aAAc,SAAQ,QAAQ;IACzC,YAAY,MAAc,EAAE,UAAkB,EAAE,OAAgB;QAC9D,KAAK,CACH,GAAG,MAAM,eAAe,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EACtE,iBAAiB,EACjB,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,CAChC,CAAC;IACJ,CAAC;CACF;AAED,MAAM,OAAO,YAAa,SAAQ,QAAQ;IACxC,YACE,OAAe,EACf,QAAgB,EAChB,MAAe;QAEf,KAAK,CACH,mBAAmB,OAAO,eAAe,QAAQ,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAClF,eAAe,EACf,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAC9B,CAAC;IACJ,CAAC;CACF;AAED,MAAM,OAAO,UAAW,SAAQ,QAAQ;IACtC,YACE,OAAe,EACf,SAAqC,EACrC,KAAa;QAEb,KAAK,CACH,SAAS,SAAS,YAAY,OAAO,EAAE,EACvC,aAAa,EACb,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CACrC,CAAC;IACJ,CAAC;CACF;AAED,MAAM,OAAO,WAAY,SAAQ,QAAQ;IACvC,YACE,OAAe,EACf,QAAiB,EACjB,KAAa;QAEb,KAAK,CACH,QAAQ,CAAC,CAAC,CAAC,mBAAmB,QAAQ,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC,iBAAiB,OAAO,EAAE,EACjF,cAAc,EACd,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CACpC,CAAC;IACJ,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { validateManifest } from './core/validate-manifest.js';
|
|
2
|
+
export type { ValidateManifestOptions, ValidateManifestResult, ManifestIssue } from './core/validate-manifest.js';
|
|
3
|
+
export { validateSkill } from './core/validate-skill.js';
|
|
4
|
+
export type { ValidateSkillOptions, ValidateSkillResult, SkillIssue } from './core/validate-skill.js';
|
|
5
|
+
export { listProject } from './core/list-project.js';
|
|
6
|
+
export type { ListProjectOptions, ListProjectResult, SkillInfo, FragmentInfo } from './core/list-project.js';
|
|
7
|
+
export { scaffold } from './core/scaffold.js';
|
|
8
|
+
export type { ScaffoldOptions, ScaffoldResult, ScaffoldFile, ScaffoldKind } from './core/scaffold.js';
|
|
9
|
+
export { checkExports } from './core/check-exports.js';
|
|
10
|
+
export type { CheckExportsOptions, CheckExportsResult, CoreModuleInfo, ExportIssue } from './core/check-exports.js';
|
|
11
|
+
export { CacheManager } from './cache/cache-manager.js';
|
|
12
|
+
export type { CacheEntry, CacheStats, CacheOptions } from './cache/cache-manager.js';
|
|
13
|
+
export { AppError, NotFoundError, CommandError, CacheError, ConfigError, } from './errors/types.js';
|
|
14
|
+
export { OutputFormatter } from './cli/output-formatter.js';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,YAAY,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAElH,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtG,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE7G,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEtG,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAGpH,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGrF,OAAO,EACL,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,UAAU,EACV,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC"}
|