skiller 0.7.11 → 0.7.12
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/core/SkillsProcessor.js +89 -3
- package/package.json +1 -1
|
@@ -49,6 +49,92 @@ const yaml = __importStar(require("js-yaml"));
|
|
|
49
49
|
const constants_1 = require("../constants");
|
|
50
50
|
const SkillsUtils_1 = require("./SkillsUtils");
|
|
51
51
|
const FrontmatterParser_1 = require("./FrontmatterParser");
|
|
52
|
+
/**
|
|
53
|
+
* For non-Claude agents, compile a wrapper SKILL.md (body is a single @reference)
|
|
54
|
+
* into a standalone SKILL.md with the referenced file's body inlined.
|
|
55
|
+
*
|
|
56
|
+
* We intentionally keep this conservative: only expand when the body is *just*
|
|
57
|
+
* an @reference line, to avoid accidentally treating email addresses or
|
|
58
|
+
* "@mentions" inside real content as file references.
|
|
59
|
+
*/
|
|
60
|
+
async function compileSkillMdForNonClaudeAgents(skillMdContent, projectRoot, skillFolderPath) {
|
|
61
|
+
const { frontmatter, rawFrontmatter, body } = (0, FrontmatterParser_1.parseFrontmatter)(skillMdContent);
|
|
62
|
+
const refCheck = isReferenceBody(body);
|
|
63
|
+
if (!refCheck.isReference || !refCheck.referencePath) {
|
|
64
|
+
return skillMdContent;
|
|
65
|
+
}
|
|
66
|
+
const referencePath = refCheck.referencePath;
|
|
67
|
+
const absoluteRefPath = referencePath.startsWith('./') || referencePath.startsWith('../')
|
|
68
|
+
? path.resolve(skillFolderPath, referencePath)
|
|
69
|
+
: path.resolve(projectRoot, referencePath);
|
|
70
|
+
// Security: only inline references within the project root.
|
|
71
|
+
const normalizedProjectRoot = path.resolve(projectRoot);
|
|
72
|
+
const normalizedAbsoluteRefPath = path.resolve(absoluteRefPath);
|
|
73
|
+
if (!normalizedAbsoluteRefPath.startsWith(normalizedProjectRoot + path.sep)) {
|
|
74
|
+
return skillMdContent;
|
|
75
|
+
}
|
|
76
|
+
let referencedContent;
|
|
77
|
+
try {
|
|
78
|
+
referencedContent = await fs.readFile(normalizedAbsoluteRefPath, 'utf8');
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return skillMdContent;
|
|
82
|
+
}
|
|
83
|
+
const { body: referencedBody } = (0, FrontmatterParser_1.parseFrontmatter)(referencedContent);
|
|
84
|
+
const fmData = rawFrontmatter && Object.keys(rawFrontmatter).length > 0
|
|
85
|
+
? rawFrontmatter
|
|
86
|
+
: frontmatter && Object.keys(frontmatter).length > 0
|
|
87
|
+
? frontmatter
|
|
88
|
+
: null;
|
|
89
|
+
if (fmData) {
|
|
90
|
+
return `---
|
|
91
|
+
${yaml.dump(fmData, { lineWidth: -1, noRefs: true }).trim()}
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
${referencedBody}
|
|
95
|
+
`;
|
|
96
|
+
}
|
|
97
|
+
return `${referencedBody}\n`;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Copies a single skill directory to an agent skill directory:
|
|
101
|
+
* - SKILL.md is compiled (inlines @reference wrapper content)
|
|
102
|
+
* - .mdc files are excluded (Claude-only sources)
|
|
103
|
+
* - all other files are copied as-is
|
|
104
|
+
*/
|
|
105
|
+
async function copySkillDirectoryForNonClaudeAgents(src, dest, projectRoot, skillFolderPath, depth = 0) {
|
|
106
|
+
// Security: Prevent DoS via deeply nested directories
|
|
107
|
+
if (depth >= constants_1.MAX_RECURSION_DEPTH) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const stat = await fs.stat(src);
|
|
111
|
+
if (stat.isDirectory()) {
|
|
112
|
+
await fs.mkdir(dest, { recursive: true });
|
|
113
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
114
|
+
for (const entry of entries) {
|
|
115
|
+
// Exclude all .mdc files from agent skills directories.
|
|
116
|
+
if (entry.isFile() && entry.name.endsWith('.mdc')) {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
const srcPath = path.join(src, entry.name);
|
|
120
|
+
const destPath = path.join(dest, entry.name);
|
|
121
|
+
await copySkillDirectoryForNonClaudeAgents(srcPath, destPath, projectRoot, skillFolderPath, depth + 1);
|
|
122
|
+
}
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
// Files
|
|
126
|
+
if (path.basename(src) === constants_1.SKILL_MD_FILENAME) {
|
|
127
|
+
const content = await fs.readFile(src, 'utf8');
|
|
128
|
+
const compiled = await compileSkillMdForNonClaudeAgents(content, projectRoot, skillFolderPath);
|
|
129
|
+
await fs.writeFile(dest, compiled, 'utf8');
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
// Extra guard: skip .mdc even if reached via recursion.
|
|
133
|
+
if (src.endsWith('.mdc')) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
await fs.copyFile(src, dest);
|
|
137
|
+
}
|
|
52
138
|
/**
|
|
53
139
|
* Check if SKILL.md body is just a reference (single non-empty line starting with @).
|
|
54
140
|
* This replaces the previous synced: true frontmatter detection.
|
|
@@ -373,7 +459,7 @@ async function discoverSkills(projectRoot, skillerDir) {
|
|
|
373
459
|
* Copies skills from source directory to target agent's skills directory.
|
|
374
460
|
* Validates skill structure and returns copy count and warnings.
|
|
375
461
|
*/
|
|
376
|
-
async function copySkillsToAgent(sourceSkillsDir, targetSkillsDir, verbose, dryRun) {
|
|
462
|
+
async function copySkillsToAgent(sourceSkillsDir, targetSkillsDir, projectRoot, verbose, dryRun) {
|
|
377
463
|
const warnings = [];
|
|
378
464
|
let copied = 0;
|
|
379
465
|
try {
|
|
@@ -402,7 +488,7 @@ async function copySkillsToAgent(sourceSkillsDir, targetSkillsDir, verbose, dryR
|
|
|
402
488
|
const relativeSkillPath = path.relative(sourceSkillsDir, skill.path);
|
|
403
489
|
const targetSkillPath = path.join(targetSkillsDir, relativeSkillPath);
|
|
404
490
|
if (!dryRun) {
|
|
405
|
-
await (
|
|
491
|
+
await copySkillDirectoryForNonClaudeAgents(skillPath, targetSkillPath, projectRoot, skillPath);
|
|
406
492
|
}
|
|
407
493
|
(0, constants_1.logVerboseInfo)(dryRun
|
|
408
494
|
? `DRY RUN: Would copy skill '${skill.name}' to ${targetSkillsDir}`
|
|
@@ -492,7 +578,7 @@ async function propagateSkills(projectRoot, agents, skillsEnabled, verbose, dryR
|
|
|
492
578
|
}
|
|
493
579
|
// Copy skills to each unique destination
|
|
494
580
|
for (const targetPath of destinationPaths) {
|
|
495
|
-
const result = await copySkillsToAgent(skillsDir, targetPath, verbose, dryRun);
|
|
581
|
+
const result = await copySkillsToAgent(skillsDir, targetPath, projectRoot, verbose, dryRun);
|
|
496
582
|
if (result.copied > 0) {
|
|
497
583
|
(0, constants_1.logVerboseInfo)(`Copied ${result.copied} skill(s) to ${targetPath}`, verbose, dryRun);
|
|
498
584
|
}
|