@intlayer/chokidar 8.0.5 → 8.1.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/assets/installSkills/LICENCE.md +201 -0
- package/dist/assets/installSkills/skills/angular.md +10 -1
- package/dist/assets/installSkills/skills/astro.md +10 -1
- package/dist/assets/installSkills/skills/cli.md +28 -0
- package/dist/assets/installSkills/skills/config.md +5 -0
- package/dist/assets/installSkills/skills/content.md +5 -0
- package/dist/assets/installSkills/skills/next_js.md +13 -0
- package/dist/assets/installSkills/skills/preact.md +48 -0
- package/dist/assets/installSkills/skills/react.md +20 -3
- package/dist/assets/installSkills/skills/remote_content.md +5 -1
- package/dist/assets/installSkills/skills/solid.md +47 -0
- package/dist/assets/installSkills/skills/svelte.md +11 -1
- package/dist/assets/installSkills/skills/usage.md +5 -1
- package/dist/assets/installSkills/skills/vue.md +14 -1
- package/dist/cjs/installSkills/index.cjs +210 -30
- package/dist/cjs/installSkills/index.cjs.map +1 -1
- package/dist/esm/installSkills/index.mjs +209 -30
- package/dist/esm/installSkills/index.mjs.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/installSkills/index.d.ts +10 -4
- package/dist/types/installSkills/index.d.ts.map +1 -1
- package/package.json +11 -11
- package/dist/assets/installSkills/skills/extra_action.md +0 -6
- package/dist/assets/installSkills/skills/setup.md +0 -25
|
@@ -4,58 +4,238 @@ const require__utils_asset = require('../_virtual/_utils_asset.cjs');
|
|
|
4
4
|
let node_fs = require("node:fs");
|
|
5
5
|
let node_path = require("node:path");
|
|
6
6
|
node_path = require_runtime.__toESM(node_path);
|
|
7
|
+
let _intlayer_core = require("@intlayer/core");
|
|
8
|
+
let node_https = require("node:https");
|
|
9
|
+
node_https = require_runtime.__toESM(node_https);
|
|
7
10
|
|
|
8
11
|
//#region src/installSkills/index.ts
|
|
9
12
|
const SKILLS_METADATA = {
|
|
10
|
-
Setup: "General Intlayer setup guide",
|
|
11
13
|
Usage: "How to use Intlayer in your project",
|
|
12
14
|
RemoteContent: "How to use Intlayer with Remote/CMS/Server-side content",
|
|
13
15
|
Config: "Intlayer configuration documentation",
|
|
14
|
-
ExtraAction: "Additional CLI and automated actions",
|
|
15
16
|
Content: "Reference for all Intlayer content node types (t, enu, etc.)",
|
|
16
17
|
React: "React-specific syntax and hooks usage",
|
|
17
18
|
Angular: "Angular-specific syntax and Injectable Function usage",
|
|
18
19
|
NextJS: "Next.js-specific usage (Server & Client components)",
|
|
19
20
|
Vue: "Vue-specific composables and syntax",
|
|
21
|
+
Preact: "Preact-specific syntax and hooks usage",
|
|
22
|
+
Solid: "Solid-specific primitives and syntax",
|
|
20
23
|
Svelte: "Svelte-specific stores and syntax",
|
|
21
|
-
Astro: "Astro-specific usage and getIntlayer"
|
|
24
|
+
Astro: "Astro-specific usage and getIntlayer",
|
|
25
|
+
CLI: "Intlayer CLI commands and usage"
|
|
22
26
|
};
|
|
23
27
|
const SKILLS = Object.keys(SKILLS_METADATA);
|
|
24
28
|
/**
|
|
25
|
-
*
|
|
29
|
+
* Maps specific skill keys to special filenames if they differ from standard snake_case.
|
|
30
|
+
*/
|
|
31
|
+
const SKILL_FILENAME_MAP = {};
|
|
32
|
+
/**
|
|
33
|
+
* Helper to convert CamelCase to snake_case for directory naming
|
|
26
34
|
*/
|
|
27
35
|
const camelToSnakeCase = (str) => str.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase();
|
|
36
|
+
/**
|
|
37
|
+
* Reads the raw markdown content for a specific skill from the assets folder.
|
|
38
|
+
*/
|
|
28
39
|
const getSkillContent = (skill) => {
|
|
29
|
-
|
|
40
|
+
const fileName = `./skills/${SKILL_FILENAME_MAP[skill] ?? camelToSnakeCase(skill)}.md`;
|
|
41
|
+
try {
|
|
42
|
+
return require__utils_asset.readAsset(fileName);
|
|
43
|
+
} catch {
|
|
44
|
+
console.warn(`Warning: Could not read asset for skill: ${skill} at ${fileName}`);
|
|
45
|
+
return "";
|
|
46
|
+
}
|
|
30
47
|
};
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
/**
|
|
49
|
+
* Reads the licence content from the assets folder.
|
|
50
|
+
*/
|
|
51
|
+
const getLicenceContent = () => {
|
|
52
|
+
try {
|
|
53
|
+
return require__utils_asset.readAsset("./LICENCE.md");
|
|
54
|
+
} catch {
|
|
55
|
+
console.warn("Warning: Could not read LICENCE.md asset");
|
|
56
|
+
return "";
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Fetches the content of a URL (supporting redirects).
|
|
61
|
+
*/
|
|
62
|
+
const fetchUrl = (url) => new Promise((resolve, reject) => {
|
|
63
|
+
node_https.default.get(url, (res) => {
|
|
64
|
+
const { statusCode } = res;
|
|
65
|
+
if (statusCode === 301 || statusCode === 302) {
|
|
66
|
+
const redirectUrl = res.headers.location;
|
|
67
|
+
if (redirectUrl) return fetchUrl(redirectUrl).then(resolve).catch(reject);
|
|
46
68
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
69
|
+
if (statusCode !== 200) return reject(/* @__PURE__ */ new Error(`Failed to fetch ${url}: Status Code ${statusCode}`));
|
|
70
|
+
let data = "";
|
|
71
|
+
res.on("data", (chunk) => {
|
|
72
|
+
data += chunk;
|
|
73
|
+
});
|
|
74
|
+
res.on("end", () => {
|
|
75
|
+
resolve(data);
|
|
76
|
+
});
|
|
77
|
+
}).on("error", (err) => {
|
|
78
|
+
reject(err);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
/**
|
|
82
|
+
* Installs skills using the "Agent Skills" directory standard.
|
|
83
|
+
* Standard: <PROJECT_ROOT>/<CONFIG_DIR>/skills/<SKILL_NAME>/SKILL.md
|
|
84
|
+
*/
|
|
85
|
+
const installSkills = async (projectRoot, platform, skills) => {
|
|
86
|
+
let skillsBaseDir = "";
|
|
87
|
+
const useAgentStructure = platform !== "VSCode";
|
|
88
|
+
switch (platform) {
|
|
89
|
+
case "Cursor":
|
|
90
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".cursor/skills");
|
|
91
|
+
break;
|
|
92
|
+
case "Windsurf":
|
|
93
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".windsurf/skills");
|
|
94
|
+
break;
|
|
95
|
+
case "Trae":
|
|
96
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".trae/skills");
|
|
97
|
+
break;
|
|
98
|
+
case "OpenCode":
|
|
99
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".opencode/skills");
|
|
100
|
+
break;
|
|
101
|
+
case "GitHub":
|
|
102
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".github/skills");
|
|
103
|
+
break;
|
|
104
|
+
case "Claude":
|
|
105
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".claude/skills");
|
|
106
|
+
break;
|
|
107
|
+
case "VSCode":
|
|
108
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".github/skills");
|
|
109
|
+
break;
|
|
110
|
+
case "Antigravity":
|
|
111
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".agent/skills");
|
|
112
|
+
break;
|
|
113
|
+
case "Augment":
|
|
114
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".augment/skills");
|
|
115
|
+
break;
|
|
116
|
+
case "OpenClaw":
|
|
117
|
+
skillsBaseDir = node_path.default.join(projectRoot, "skills");
|
|
118
|
+
break;
|
|
119
|
+
case "Cline":
|
|
120
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".cline/skills");
|
|
121
|
+
break;
|
|
122
|
+
case "CodeBuddy":
|
|
123
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".codebuddy/skills");
|
|
124
|
+
break;
|
|
125
|
+
case "CommandCode":
|
|
126
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".commandcode/skills");
|
|
127
|
+
break;
|
|
128
|
+
case "Continue":
|
|
129
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".continue/skills");
|
|
130
|
+
break;
|
|
131
|
+
case "Crush":
|
|
132
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".crush/skills");
|
|
133
|
+
break;
|
|
134
|
+
case "Droid":
|
|
135
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".factory/skills");
|
|
136
|
+
break;
|
|
137
|
+
case "Goose":
|
|
138
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".goose/skills");
|
|
139
|
+
break;
|
|
140
|
+
case "Junie":
|
|
141
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".junie/skills");
|
|
142
|
+
break;
|
|
143
|
+
case "IFlow":
|
|
144
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".iflow/skills");
|
|
145
|
+
break;
|
|
146
|
+
case "KiloCode":
|
|
147
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".kilocode/skills");
|
|
148
|
+
break;
|
|
149
|
+
case "Kiro":
|
|
150
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".kiro/skills");
|
|
151
|
+
break;
|
|
152
|
+
case "Kode":
|
|
153
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".kode/skills");
|
|
154
|
+
break;
|
|
155
|
+
case "MCPJam":
|
|
156
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".mcpjam/skills");
|
|
157
|
+
break;
|
|
158
|
+
case "MistralVibe":
|
|
159
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".vibe/skills");
|
|
160
|
+
break;
|
|
161
|
+
case "Mux":
|
|
162
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".mux/skills");
|
|
163
|
+
break;
|
|
164
|
+
case "OpenHands":
|
|
165
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".openhands/skills");
|
|
166
|
+
break;
|
|
167
|
+
case "Pi":
|
|
168
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".pi/skills");
|
|
169
|
+
break;
|
|
170
|
+
case "Qoder":
|
|
171
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".qoder/skills");
|
|
172
|
+
break;
|
|
173
|
+
case "Qwen":
|
|
174
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".qwen/skills");
|
|
175
|
+
break;
|
|
176
|
+
case "RooCode":
|
|
177
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".roo/skills");
|
|
178
|
+
break;
|
|
179
|
+
case "TraeCN":
|
|
180
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".trae/skills");
|
|
181
|
+
break;
|
|
182
|
+
case "Zencoder":
|
|
183
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".zencoder/skills");
|
|
184
|
+
break;
|
|
185
|
+
case "Neovate":
|
|
186
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".neovate/skills");
|
|
187
|
+
break;
|
|
188
|
+
case "Pochi":
|
|
189
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".pochi/skills");
|
|
190
|
+
break;
|
|
191
|
+
default:
|
|
192
|
+
skillsBaseDir = node_path.default.join(projectRoot, "skills");
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
await node_fs.promises.mkdir(skillsBaseDir, { recursive: true });
|
|
196
|
+
const createdSkills = [];
|
|
197
|
+
const licenceContent = getLicenceContent();
|
|
198
|
+
for (const skill of skills) {
|
|
199
|
+
const skillName = `intlayer_${SKILL_FILENAME_MAP[skill] ?? camelToSnakeCase(skill)}`;
|
|
200
|
+
const skillContent = getSkillContent(skill);
|
|
201
|
+
if (!skillContent) continue;
|
|
202
|
+
const urls = Array.from(new Set(skillContent.match(/https:\/\/intlayer\.org\/doc\/[^\s)]+\.md/g) || []));
|
|
203
|
+
if (useAgentStructure) {
|
|
204
|
+
const skillDir = node_path.default.join(skillsBaseDir, skillName);
|
|
205
|
+
await node_fs.promises.mkdir(skillDir, { recursive: true });
|
|
206
|
+
const filePath = node_path.default.join(skillDir, "SKILL.md");
|
|
207
|
+
await node_fs.promises.writeFile(filePath, skillContent, "utf-8");
|
|
208
|
+
if (licenceContent) {
|
|
209
|
+
const licencePath = node_path.default.join(skillDir, "LICENCE.md");
|
|
210
|
+
await node_fs.promises.writeFile(licencePath, licenceContent, "utf-8");
|
|
211
|
+
}
|
|
212
|
+
const referenceDir = node_path.default.join(skillDir, "reference");
|
|
213
|
+
await node_fs.promises.mkdir(referenceDir, { recursive: true });
|
|
214
|
+
for (const url of urls) try {
|
|
215
|
+
const content = await fetchUrl(url);
|
|
216
|
+
const metadata = (0, _intlayer_core.getMarkdownMetadata)(content);
|
|
217
|
+
let fileName = "";
|
|
218
|
+
if (Array.isArray(metadata.slugs)) fileName = metadata.slugs.filter((slug) => slug !== "doc").join("_");
|
|
219
|
+
else fileName = new URL(url).pathname.split("/").filter((part) => part !== "" && part !== "doc").map((part, index, array) => {
|
|
220
|
+
if (index === array.length - 1) return part.replace(".md", "");
|
|
221
|
+
return part;
|
|
222
|
+
}).join("_");
|
|
223
|
+
fileName = fileName ? `${fileName}.md` : "index.md";
|
|
224
|
+
const docPath = node_path.default.join(referenceDir, fileName);
|
|
225
|
+
await node_fs.promises.writeFile(docPath, content, "utf-8");
|
|
226
|
+
} catch (error) {
|
|
227
|
+
console.warn(`Warning: Could not fetch documentation for ${skill} from ${url}:`, error);
|
|
228
|
+
}
|
|
229
|
+
createdSkills.push(`${skillName}/SKILL.md`);
|
|
230
|
+
} else {
|
|
231
|
+
const fileName = `${skillName}.md`;
|
|
232
|
+
const filePath = node_path.default.join(skillsBaseDir, fileName);
|
|
233
|
+
await node_fs.promises.writeFile(filePath, skillContent, "utf-8");
|
|
234
|
+
createdSkills.push(fileName);
|
|
56
235
|
}
|
|
57
|
-
return `Created skills files in ${skillsDir}: ${createdFiles.map((f) => node_path.default.basename(f)).join(", ")}`;
|
|
58
236
|
}
|
|
237
|
+
if (createdSkills.length === 0) return `No skill files were created. Check your asset paths.`;
|
|
238
|
+
return `Created ${createdSkills.length} skills in ${skillsBaseDir}`;
|
|
59
239
|
};
|
|
60
240
|
|
|
61
241
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["readAsset","path","fs"],"sources":["../../../src/installSkills/index.ts"],"sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { readAsset } from 'utils:asset';\n\nexport const SKILLS_METADATA = {\n Setup: 'General Intlayer setup guide',\n Usage: 'How to use Intlayer in your project',\n RemoteContent: 'How to use Intlayer with Remote/CMS/Server-side content',\n Config: 'Intlayer configuration documentation',\n ExtraAction: 'Additional CLI and automated actions',\n Content: 'Reference for all Intlayer content node types (t, enu, etc.)',\n React: 'React-specific syntax and hooks usage',\n Angular: 'Angular-specific syntax and Injectable Function usage',\n NextJS: 'Next.js-specific usage (Server & Client components)',\n Vue: 'Vue-specific composables and syntax',\n Svelte: 'Svelte-specific stores and syntax',\n Astro: 'Astro-specific usage and getIntlayer',\n} as const;\n\nexport const SKILLS = Object.keys(\n SKILLS_METADATA\n) as (keyof typeof SKILLS_METADATA)[];\n\nexport type Skill = (typeof SKILLS)[number];\n\n/**\n * Helper to convert CamelCase to snake_case\n */\nconst camelToSnakeCase = (str: string) =>\n str.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase();\n\nconst getSkillContent = (skill: Skill): string => {\n const fileName = `./skills/${camelToSnakeCase(skill)}.md`;\n return readAsset(fileName);\n};\n\nexport const installSkills = async (\n projectRoot: string,\n platform: 'Cursor' | 'VSCode' | 'OpenCode' | 'Claude' | 'Other',\n skills: Skill[]\n): Promise<string> => {\n const content = skills.map((skill) => getSkillContent(skill)).join('\\n\\n');\n\n if (platform === 'Cursor' || platform === 'Claude') {\n const fileName = platform === 'Cursor' ? '.cursorrules' : '.clauderules';\n const filePath = path.join(projectRoot, fileName);\n try {\n let existingContent = '';\n try {\n existingContent = await fs.readFile(filePath, 'utf-8');\n } catch {\n // File doesn't exist, ignore\n }\n\n const newContent = existingContent\n ? `${existingContent}\\n\\n${content}`\n : content;\n await fs.writeFile(filePath, newContent, 'utf-8');\n return `Updated ${fileName} with ${skills.join(', ')} skills.`;\n } catch (error) {\n throw new Error(`Failed to write ${fileName}: ${error}`);\n }\n } else {\n // For other platforms, write to .intlayer/skills\n const skillsDir = path.join(projectRoot, '.intlayer/skills');\n await fs.mkdir(skillsDir, { recursive: true });\n\n const createdFiles: string[] = [];\n\n for (const skill of skills) {\n const fileName = `${camelToSnakeCase(skill)}.md`;\n const filePath = path.join(skillsDir, fileName);\n await fs.writeFile(filePath, getSkillContent(skill), 'utf-8');\n createdFiles.push(filePath);\n }\n\n return `Created skills files in ${skillsDir}: ${createdFiles.map((f) => path.basename(f)).join(', ')}`;\n }\n};\n"],"mappings":";;;;;;;;AAIA,MAAa,kBAAkB;CAC7B,OAAO;CACP,OAAO;CACP,eAAe;CACf,QAAQ;CACR,aAAa;CACb,SAAS;CACT,OAAO;CACP,SAAS;CACT,QAAQ;CACR,KAAK;CACL,QAAQ;CACR,OAAO;CACR;AAED,MAAa,SAAS,OAAO,KAC3B,gBACD;;;;AAOD,MAAM,oBAAoB,QACxB,IAAI,QAAQ,sBAAsB,QAAQ,CAAC,aAAa;AAE1D,MAAM,mBAAmB,UAAyB;AAEhD,QAAOA,+BADU,YAAY,iBAAiB,MAAM,CAAC,KAC3B;;AAG5B,MAAa,gBAAgB,OAC3B,aACA,UACA,WACoB;CACpB,MAAM,UAAU,OAAO,KAAK,UAAU,gBAAgB,MAAM,CAAC,CAAC,KAAK,OAAO;AAE1E,KAAI,aAAa,YAAY,aAAa,UAAU;EAClD,MAAM,WAAW,aAAa,WAAW,iBAAiB;EAC1D,MAAM,WAAWC,kBAAK,KAAK,aAAa,SAAS;AACjD,MAAI;GACF,IAAI,kBAAkB;AACtB,OAAI;AACF,sBAAkB,MAAMC,iBAAG,SAAS,UAAU,QAAQ;WAChD;GAIR,MAAM,aAAa,kBACf,GAAG,gBAAgB,MAAM,YACzB;AACJ,SAAMA,iBAAG,UAAU,UAAU,YAAY,QAAQ;AACjD,UAAO,WAAW,SAAS,QAAQ,OAAO,KAAK,KAAK,CAAC;WAC9C,OAAO;AACd,SAAM,IAAI,MAAM,mBAAmB,SAAS,IAAI,QAAQ;;QAErD;EAEL,MAAM,YAAYD,kBAAK,KAAK,aAAa,mBAAmB;AAC5D,QAAMC,iBAAG,MAAM,WAAW,EAAE,WAAW,MAAM,CAAC;EAE9C,MAAM,eAAyB,EAAE;AAEjC,OAAK,MAAM,SAAS,QAAQ;GAC1B,MAAM,WAAW,GAAG,iBAAiB,MAAM,CAAC;GAC5C,MAAM,WAAWD,kBAAK,KAAK,WAAW,SAAS;AAC/C,SAAMC,iBAAG,UAAU,UAAU,gBAAgB,MAAM,EAAE,QAAQ;AAC7D,gBAAa,KAAK,SAAS;;AAG7B,SAAO,2BAA2B,UAAU,IAAI,aAAa,KAAK,MAAMD,kBAAK,SAAS,EAAE,CAAC,CAAC,KAAK,KAAK"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["readAsset","path","fs"],"sources":["../../../src/installSkills/index.ts"],"sourcesContent":["import { promises as fs } from 'node:fs';\nimport https from 'node:https';\nimport path from 'node:path';\nimport { readAsset } from 'utils:asset';\nimport { getMarkdownMetadata } from '@intlayer/core';\n\nexport const SKILLS_METADATA = {\n Usage: 'How to use Intlayer in your project',\n RemoteContent: 'How to use Intlayer with Remote/CMS/Server-side content',\n Config: 'Intlayer configuration documentation',\n Content: 'Reference for all Intlayer content node types (t, enu, etc.)',\n React: 'React-specific syntax and hooks usage',\n Angular: 'Angular-specific syntax and Injectable Function usage',\n NextJS: 'Next.js-specific usage (Server & Client components)',\n Vue: 'Vue-specific composables and syntax',\n Preact: 'Preact-specific syntax and hooks usage',\n Solid: 'Solid-specific primitives and syntax',\n Svelte: 'Svelte-specific stores and syntax',\n Astro: 'Astro-specific usage and getIntlayer',\n CLI: 'Intlayer CLI commands and usage',\n} as const;\n\nexport const SKILLS = Object.keys(\n SKILLS_METADATA\n) as (keyof typeof SKILLS_METADATA)[];\n\nexport type Skill = (typeof SKILLS)[number];\n\nexport type Platform =\n | 'Cursor'\n | 'Windsurf'\n | 'Trae'\n | 'OpenCode'\n | 'GitHub'\n | 'Claude'\n | 'VSCode'\n | 'Antigravity'\n | 'Augment'\n | 'OpenClaw'\n | 'Cline'\n | 'CodeBuddy'\n | 'CommandCode'\n | 'Continue'\n | 'Crush'\n | 'Droid'\n | 'Goose'\n | 'Junie'\n | 'IFlow'\n | 'KiloCode'\n | 'Kiro'\n | 'Kode'\n | 'MCPJam'\n | 'MistralVibe'\n | 'Mux'\n | 'OpenHands'\n | 'Pi'\n | 'Qoder'\n | 'Qwen'\n | 'RooCode'\n | 'TraeCN'\n | 'Zencoder'\n | 'Neovate'\n | 'Pochi'\n | 'Other';\n\n/**\n * Maps specific skill keys to special filenames if they differ from standard snake_case.\n */\nconst SKILL_FILENAME_MAP: Partial<Record<Skill, string>> = {};\n\n/**\n * Helper to convert CamelCase to snake_case for directory naming\n */\nconst camelToSnakeCase = (str: string) =>\n str.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase();\n\n/**\n * Reads the raw markdown content for a specific skill from the assets folder.\n */\nconst getSkillContent = (skill: Skill): string => {\n const baseName = SKILL_FILENAME_MAP[skill] ?? camelToSnakeCase(skill);\n // Source files are flat: ./skills/vue.md\n const fileName = `./skills/${baseName}.md`;\n\n try {\n return readAsset(fileName);\n } catch {\n console.warn(\n `Warning: Could not read asset for skill: ${skill} at ${fileName}`\n );\n return '';\n }\n};\n\n/**\n * Reads the licence content from the assets folder.\n */\nconst getLicenceContent = (): string => {\n try {\n return readAsset('./LICENCE.md');\n } catch {\n console.warn('Warning: Could not read LICENCE.md asset');\n return '';\n }\n};\n\n/**\n * Fetches the content of a URL (supporting redirects).\n */\nconst fetchUrl = (url: string): Promise<string> =>\n new Promise((resolve, reject) => {\n https\n .get(url, (res) => {\n const { statusCode } = res;\n\n if (statusCode === 301 || statusCode === 302) {\n const redirectUrl = res.headers.location;\n if (redirectUrl) {\n return fetchUrl(redirectUrl).then(resolve).catch(reject);\n }\n }\n\n if (statusCode !== 200) {\n return reject(\n new Error(`Failed to fetch ${url}: Status Code ${statusCode}`)\n );\n }\n\n let data = '';\n res.on('data', (chunk) => {\n data += chunk;\n });\n res.on('end', () => {\n resolve(data);\n });\n })\n .on('error', (err) => {\n reject(err);\n });\n });\n\n/**\n * Installs skills using the \"Agent Skills\" directory standard.\n * Standard: <PROJECT_ROOT>/<CONFIG_DIR>/skills/<SKILL_NAME>/SKILL.md\n */\nexport const installSkills = async (\n projectRoot: string,\n platform: Platform,\n skills: Skill[]\n): Promise<string> => {\n let skillsBaseDir = '';\n const useAgentStructure = platform !== 'VSCode';\n\n // Determine the root configuration directory based on Platform\n switch (platform) {\n case 'Cursor':\n skillsBaseDir = path.join(projectRoot, '.cursor/skills');\n break;\n case 'Windsurf':\n skillsBaseDir = path.join(projectRoot, '.windsurf/skills');\n break;\n case 'Trae':\n skillsBaseDir = path.join(projectRoot, '.trae/skills');\n break;\n case 'OpenCode':\n skillsBaseDir = path.join(projectRoot, '.opencode/skills');\n break;\n case 'GitHub': // GitHub Copilot Workspace\n skillsBaseDir = path.join(projectRoot, '.github/skills');\n break;\n case 'Claude': // Claude Desktop / Agent\n skillsBaseDir = path.join(projectRoot, '.claude/skills');\n break;\n case 'VSCode':\n skillsBaseDir = path.join(projectRoot, '.github/skills');\n break;\n case 'Antigravity':\n skillsBaseDir = path.join(projectRoot, '.agent/skills');\n break;\n case 'Augment':\n skillsBaseDir = path.join(projectRoot, '.augment/skills');\n break;\n case 'OpenClaw':\n skillsBaseDir = path.join(projectRoot, 'skills');\n break;\n case 'Cline':\n skillsBaseDir = path.join(projectRoot, '.cline/skills');\n break;\n case 'CodeBuddy':\n skillsBaseDir = path.join(projectRoot, '.codebuddy/skills');\n break;\n case 'CommandCode':\n skillsBaseDir = path.join(projectRoot, '.commandcode/skills');\n break;\n case 'Continue':\n skillsBaseDir = path.join(projectRoot, '.continue/skills');\n break;\n case 'Crush':\n skillsBaseDir = path.join(projectRoot, '.crush/skills');\n break;\n case 'Droid':\n skillsBaseDir = path.join(projectRoot, '.factory/skills');\n break;\n case 'Goose':\n skillsBaseDir = path.join(projectRoot, '.goose/skills');\n break;\n case 'Junie':\n skillsBaseDir = path.join(projectRoot, '.junie/skills');\n break;\n case 'IFlow':\n skillsBaseDir = path.join(projectRoot, '.iflow/skills');\n break;\n case 'KiloCode':\n skillsBaseDir = path.join(projectRoot, '.kilocode/skills');\n break;\n case 'Kiro':\n skillsBaseDir = path.join(projectRoot, '.kiro/skills');\n break;\n case 'Kode':\n skillsBaseDir = path.join(projectRoot, '.kode/skills');\n break;\n case 'MCPJam':\n skillsBaseDir = path.join(projectRoot, '.mcpjam/skills');\n break;\n case 'MistralVibe':\n skillsBaseDir = path.join(projectRoot, '.vibe/skills');\n break;\n case 'Mux':\n skillsBaseDir = path.join(projectRoot, '.mux/skills');\n break;\n case 'OpenHands':\n skillsBaseDir = path.join(projectRoot, '.openhands/skills');\n break;\n case 'Pi':\n skillsBaseDir = path.join(projectRoot, '.pi/skills');\n break;\n case 'Qoder':\n skillsBaseDir = path.join(projectRoot, '.qoder/skills');\n break;\n case 'Qwen':\n skillsBaseDir = path.join(projectRoot, '.qwen/skills');\n break;\n case 'RooCode':\n skillsBaseDir = path.join(projectRoot, '.roo/skills');\n break;\n case 'TraeCN':\n skillsBaseDir = path.join(projectRoot, '.trae/skills');\n break;\n case 'Zencoder':\n skillsBaseDir = path.join(projectRoot, '.zencoder/skills');\n break;\n case 'Neovate':\n skillsBaseDir = path.join(projectRoot, '.neovate/skills');\n break;\n case 'Pochi':\n skillsBaseDir = path.join(projectRoot, '.pochi/skills');\n break;\n default:\n skillsBaseDir = path.join(projectRoot, 'skills');\n break;\n }\n\n // Ensure the base directory exists\n await fs.mkdir(skillsBaseDir, { recursive: true });\n\n const createdSkills: string[] = [];\n const licenceContent = getLicenceContent();\n\n for (const skill of skills) {\n const baseName = SKILL_FILENAME_MAP[skill] ?? camelToSnakeCase(skill);\n const skillName = `intlayer_${baseName}`;\n const skillContent = getSkillContent(skill);\n\n if (!skillContent) continue;\n\n const urls = Array.from(\n new Set(\n skillContent.match(/https:\\/\\/intlayer\\.org\\/doc\\/[^\\s)]+\\.md/g) || []\n )\n );\n\n if (useAgentStructure) {\n // Agent Standard: .../skills/<skill-name>/SKILL.md\n const skillDir = path.join(skillsBaseDir, skillName);\n\n await fs.mkdir(skillDir, { recursive: true });\n\n const filePath = path.join(skillDir, 'SKILL.md');\n\n await fs.writeFile(filePath, skillContent, 'utf-8');\n\n if (licenceContent) {\n const licencePath = path.join(skillDir, 'LICENCE.md');\n\n await fs.writeFile(licencePath, licenceContent, 'utf-8');\n }\n\n // Fetch and save documentation files\n const referenceDir = path.join(skillDir, 'reference');\n\n await fs.mkdir(referenceDir, { recursive: true });\n\n for (const url of urls) {\n try {\n const content = await fetchUrl(url);\n const metadata = getMarkdownMetadata<{\n slugs?: string[];\n }>(content);\n\n let fileName = '';\n\n if (Array.isArray(metadata.slugs)) {\n fileName = metadata.slugs\n .filter((slug) => slug !== 'doc')\n .join('_');\n } else {\n const urlPath = new URL(url).pathname;\n\n fileName = urlPath\n .split('/')\n .filter((part) => part !== '' && part !== 'doc')\n .map((part, index, array) => {\n if (index === array.length - 1) {\n return part.replace('.md', '');\n }\n return part;\n })\n .join('_');\n }\n\n fileName = fileName ? `${fileName}.md` : 'index.md';\n\n const docPath = path.join(referenceDir, fileName);\n\n await fs.writeFile(docPath, content, 'utf-8');\n } catch (error) {\n console.warn(\n `Warning: Could not fetch documentation for ${skill} from ${url}:`,\n error\n );\n }\n }\n\n createdSkills.push(`${skillName}/SKILL.md`);\n } else {\n // Flat Structure (Generic): .../skills/<skill-name>.md\n const fileName = `${skillName}.md`;\n const filePath = path.join(skillsBaseDir, fileName);\n\n await fs.writeFile(filePath, skillContent, 'utf-8');\n\n createdSkills.push(fileName);\n }\n }\n\n if (createdSkills.length === 0) {\n return `No skill files were created. Check your asset paths.`;\n }\n\n return `Created ${createdSkills.length} skills in ${skillsBaseDir}`;\n};\n"],"mappings":"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"}
|
|
@@ -1,58 +1,237 @@
|
|
|
1
1
|
import { readAsset } from "../_virtual/_utils_asset.mjs";
|
|
2
2
|
import { promises } from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import { getMarkdownMetadata } from "@intlayer/core";
|
|
5
|
+
import https from "node:https";
|
|
4
6
|
|
|
5
7
|
//#region src/installSkills/index.ts
|
|
6
8
|
const SKILLS_METADATA = {
|
|
7
|
-
Setup: "General Intlayer setup guide",
|
|
8
9
|
Usage: "How to use Intlayer in your project",
|
|
9
10
|
RemoteContent: "How to use Intlayer with Remote/CMS/Server-side content",
|
|
10
11
|
Config: "Intlayer configuration documentation",
|
|
11
|
-
ExtraAction: "Additional CLI and automated actions",
|
|
12
12
|
Content: "Reference for all Intlayer content node types (t, enu, etc.)",
|
|
13
13
|
React: "React-specific syntax and hooks usage",
|
|
14
14
|
Angular: "Angular-specific syntax and Injectable Function usage",
|
|
15
15
|
NextJS: "Next.js-specific usage (Server & Client components)",
|
|
16
16
|
Vue: "Vue-specific composables and syntax",
|
|
17
|
+
Preact: "Preact-specific syntax and hooks usage",
|
|
18
|
+
Solid: "Solid-specific primitives and syntax",
|
|
17
19
|
Svelte: "Svelte-specific stores and syntax",
|
|
18
|
-
Astro: "Astro-specific usage and getIntlayer"
|
|
20
|
+
Astro: "Astro-specific usage and getIntlayer",
|
|
21
|
+
CLI: "Intlayer CLI commands and usage"
|
|
19
22
|
};
|
|
20
23
|
const SKILLS = Object.keys(SKILLS_METADATA);
|
|
21
24
|
/**
|
|
22
|
-
*
|
|
25
|
+
* Maps specific skill keys to special filenames if they differ from standard snake_case.
|
|
26
|
+
*/
|
|
27
|
+
const SKILL_FILENAME_MAP = {};
|
|
28
|
+
/**
|
|
29
|
+
* Helper to convert CamelCase to snake_case for directory naming
|
|
23
30
|
*/
|
|
24
31
|
const camelToSnakeCase = (str) => str.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase();
|
|
32
|
+
/**
|
|
33
|
+
* Reads the raw markdown content for a specific skill from the assets folder.
|
|
34
|
+
*/
|
|
25
35
|
const getSkillContent = (skill) => {
|
|
26
|
-
|
|
36
|
+
const fileName = `./skills/${SKILL_FILENAME_MAP[skill] ?? camelToSnakeCase(skill)}.md`;
|
|
37
|
+
try {
|
|
38
|
+
return readAsset(fileName);
|
|
39
|
+
} catch {
|
|
40
|
+
console.warn(`Warning: Could not read asset for skill: ${skill} at ${fileName}`);
|
|
41
|
+
return "";
|
|
42
|
+
}
|
|
27
43
|
};
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Reads the licence content from the assets folder.
|
|
46
|
+
*/
|
|
47
|
+
const getLicenceContent = () => {
|
|
48
|
+
try {
|
|
49
|
+
return readAsset("./LICENCE.md");
|
|
50
|
+
} catch {
|
|
51
|
+
console.warn("Warning: Could not read LICENCE.md asset");
|
|
52
|
+
return "";
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Fetches the content of a URL (supporting redirects).
|
|
57
|
+
*/
|
|
58
|
+
const fetchUrl = (url) => new Promise((resolve, reject) => {
|
|
59
|
+
https.get(url, (res) => {
|
|
60
|
+
const { statusCode } = res;
|
|
61
|
+
if (statusCode === 301 || statusCode === 302) {
|
|
62
|
+
const redirectUrl = res.headers.location;
|
|
63
|
+
if (redirectUrl) return fetchUrl(redirectUrl).then(resolve).catch(reject);
|
|
43
64
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
65
|
+
if (statusCode !== 200) return reject(/* @__PURE__ */ new Error(`Failed to fetch ${url}: Status Code ${statusCode}`));
|
|
66
|
+
let data = "";
|
|
67
|
+
res.on("data", (chunk) => {
|
|
68
|
+
data += chunk;
|
|
69
|
+
});
|
|
70
|
+
res.on("end", () => {
|
|
71
|
+
resolve(data);
|
|
72
|
+
});
|
|
73
|
+
}).on("error", (err) => {
|
|
74
|
+
reject(err);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
/**
|
|
78
|
+
* Installs skills using the "Agent Skills" directory standard.
|
|
79
|
+
* Standard: <PROJECT_ROOT>/<CONFIG_DIR>/skills/<SKILL_NAME>/SKILL.md
|
|
80
|
+
*/
|
|
81
|
+
const installSkills = async (projectRoot, platform, skills) => {
|
|
82
|
+
let skillsBaseDir = "";
|
|
83
|
+
const useAgentStructure = platform !== "VSCode";
|
|
84
|
+
switch (platform) {
|
|
85
|
+
case "Cursor":
|
|
86
|
+
skillsBaseDir = path.join(projectRoot, ".cursor/skills");
|
|
87
|
+
break;
|
|
88
|
+
case "Windsurf":
|
|
89
|
+
skillsBaseDir = path.join(projectRoot, ".windsurf/skills");
|
|
90
|
+
break;
|
|
91
|
+
case "Trae":
|
|
92
|
+
skillsBaseDir = path.join(projectRoot, ".trae/skills");
|
|
93
|
+
break;
|
|
94
|
+
case "OpenCode":
|
|
95
|
+
skillsBaseDir = path.join(projectRoot, ".opencode/skills");
|
|
96
|
+
break;
|
|
97
|
+
case "GitHub":
|
|
98
|
+
skillsBaseDir = path.join(projectRoot, ".github/skills");
|
|
99
|
+
break;
|
|
100
|
+
case "Claude":
|
|
101
|
+
skillsBaseDir = path.join(projectRoot, ".claude/skills");
|
|
102
|
+
break;
|
|
103
|
+
case "VSCode":
|
|
104
|
+
skillsBaseDir = path.join(projectRoot, ".github/skills");
|
|
105
|
+
break;
|
|
106
|
+
case "Antigravity":
|
|
107
|
+
skillsBaseDir = path.join(projectRoot, ".agent/skills");
|
|
108
|
+
break;
|
|
109
|
+
case "Augment":
|
|
110
|
+
skillsBaseDir = path.join(projectRoot, ".augment/skills");
|
|
111
|
+
break;
|
|
112
|
+
case "OpenClaw":
|
|
113
|
+
skillsBaseDir = path.join(projectRoot, "skills");
|
|
114
|
+
break;
|
|
115
|
+
case "Cline":
|
|
116
|
+
skillsBaseDir = path.join(projectRoot, ".cline/skills");
|
|
117
|
+
break;
|
|
118
|
+
case "CodeBuddy":
|
|
119
|
+
skillsBaseDir = path.join(projectRoot, ".codebuddy/skills");
|
|
120
|
+
break;
|
|
121
|
+
case "CommandCode":
|
|
122
|
+
skillsBaseDir = path.join(projectRoot, ".commandcode/skills");
|
|
123
|
+
break;
|
|
124
|
+
case "Continue":
|
|
125
|
+
skillsBaseDir = path.join(projectRoot, ".continue/skills");
|
|
126
|
+
break;
|
|
127
|
+
case "Crush":
|
|
128
|
+
skillsBaseDir = path.join(projectRoot, ".crush/skills");
|
|
129
|
+
break;
|
|
130
|
+
case "Droid":
|
|
131
|
+
skillsBaseDir = path.join(projectRoot, ".factory/skills");
|
|
132
|
+
break;
|
|
133
|
+
case "Goose":
|
|
134
|
+
skillsBaseDir = path.join(projectRoot, ".goose/skills");
|
|
135
|
+
break;
|
|
136
|
+
case "Junie":
|
|
137
|
+
skillsBaseDir = path.join(projectRoot, ".junie/skills");
|
|
138
|
+
break;
|
|
139
|
+
case "IFlow":
|
|
140
|
+
skillsBaseDir = path.join(projectRoot, ".iflow/skills");
|
|
141
|
+
break;
|
|
142
|
+
case "KiloCode":
|
|
143
|
+
skillsBaseDir = path.join(projectRoot, ".kilocode/skills");
|
|
144
|
+
break;
|
|
145
|
+
case "Kiro":
|
|
146
|
+
skillsBaseDir = path.join(projectRoot, ".kiro/skills");
|
|
147
|
+
break;
|
|
148
|
+
case "Kode":
|
|
149
|
+
skillsBaseDir = path.join(projectRoot, ".kode/skills");
|
|
150
|
+
break;
|
|
151
|
+
case "MCPJam":
|
|
152
|
+
skillsBaseDir = path.join(projectRoot, ".mcpjam/skills");
|
|
153
|
+
break;
|
|
154
|
+
case "MistralVibe":
|
|
155
|
+
skillsBaseDir = path.join(projectRoot, ".vibe/skills");
|
|
156
|
+
break;
|
|
157
|
+
case "Mux":
|
|
158
|
+
skillsBaseDir = path.join(projectRoot, ".mux/skills");
|
|
159
|
+
break;
|
|
160
|
+
case "OpenHands":
|
|
161
|
+
skillsBaseDir = path.join(projectRoot, ".openhands/skills");
|
|
162
|
+
break;
|
|
163
|
+
case "Pi":
|
|
164
|
+
skillsBaseDir = path.join(projectRoot, ".pi/skills");
|
|
165
|
+
break;
|
|
166
|
+
case "Qoder":
|
|
167
|
+
skillsBaseDir = path.join(projectRoot, ".qoder/skills");
|
|
168
|
+
break;
|
|
169
|
+
case "Qwen":
|
|
170
|
+
skillsBaseDir = path.join(projectRoot, ".qwen/skills");
|
|
171
|
+
break;
|
|
172
|
+
case "RooCode":
|
|
173
|
+
skillsBaseDir = path.join(projectRoot, ".roo/skills");
|
|
174
|
+
break;
|
|
175
|
+
case "TraeCN":
|
|
176
|
+
skillsBaseDir = path.join(projectRoot, ".trae/skills");
|
|
177
|
+
break;
|
|
178
|
+
case "Zencoder":
|
|
179
|
+
skillsBaseDir = path.join(projectRoot, ".zencoder/skills");
|
|
180
|
+
break;
|
|
181
|
+
case "Neovate":
|
|
182
|
+
skillsBaseDir = path.join(projectRoot, ".neovate/skills");
|
|
183
|
+
break;
|
|
184
|
+
case "Pochi":
|
|
185
|
+
skillsBaseDir = path.join(projectRoot, ".pochi/skills");
|
|
186
|
+
break;
|
|
187
|
+
default:
|
|
188
|
+
skillsBaseDir = path.join(projectRoot, "skills");
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
await promises.mkdir(skillsBaseDir, { recursive: true });
|
|
192
|
+
const createdSkills = [];
|
|
193
|
+
const licenceContent = getLicenceContent();
|
|
194
|
+
for (const skill of skills) {
|
|
195
|
+
const skillName = `intlayer_${SKILL_FILENAME_MAP[skill] ?? camelToSnakeCase(skill)}`;
|
|
196
|
+
const skillContent = getSkillContent(skill);
|
|
197
|
+
if (!skillContent) continue;
|
|
198
|
+
const urls = Array.from(new Set(skillContent.match(/https:\/\/intlayer\.org\/doc\/[^\s)]+\.md/g) || []));
|
|
199
|
+
if (useAgentStructure) {
|
|
200
|
+
const skillDir = path.join(skillsBaseDir, skillName);
|
|
201
|
+
await promises.mkdir(skillDir, { recursive: true });
|
|
202
|
+
const filePath = path.join(skillDir, "SKILL.md");
|
|
203
|
+
await promises.writeFile(filePath, skillContent, "utf-8");
|
|
204
|
+
if (licenceContent) {
|
|
205
|
+
const licencePath = path.join(skillDir, "LICENCE.md");
|
|
206
|
+
await promises.writeFile(licencePath, licenceContent, "utf-8");
|
|
207
|
+
}
|
|
208
|
+
const referenceDir = path.join(skillDir, "reference");
|
|
209
|
+
await promises.mkdir(referenceDir, { recursive: true });
|
|
210
|
+
for (const url of urls) try {
|
|
211
|
+
const content = await fetchUrl(url);
|
|
212
|
+
const metadata = getMarkdownMetadata(content);
|
|
213
|
+
let fileName = "";
|
|
214
|
+
if (Array.isArray(metadata.slugs)) fileName = metadata.slugs.filter((slug) => slug !== "doc").join("_");
|
|
215
|
+
else fileName = new URL(url).pathname.split("/").filter((part) => part !== "" && part !== "doc").map((part, index, array) => {
|
|
216
|
+
if (index === array.length - 1) return part.replace(".md", "");
|
|
217
|
+
return part;
|
|
218
|
+
}).join("_");
|
|
219
|
+
fileName = fileName ? `${fileName}.md` : "index.md";
|
|
220
|
+
const docPath = path.join(referenceDir, fileName);
|
|
221
|
+
await promises.writeFile(docPath, content, "utf-8");
|
|
222
|
+
} catch (error) {
|
|
223
|
+
console.warn(`Warning: Could not fetch documentation for ${skill} from ${url}:`, error);
|
|
224
|
+
}
|
|
225
|
+
createdSkills.push(`${skillName}/SKILL.md`);
|
|
226
|
+
} else {
|
|
227
|
+
const fileName = `${skillName}.md`;
|
|
228
|
+
const filePath = path.join(skillsBaseDir, fileName);
|
|
229
|
+
await promises.writeFile(filePath, skillContent, "utf-8");
|
|
230
|
+
createdSkills.push(fileName);
|
|
53
231
|
}
|
|
54
|
-
return `Created skills files in ${skillsDir}: ${createdFiles.map((f) => path.basename(f)).join(", ")}`;
|
|
55
232
|
}
|
|
233
|
+
if (createdSkills.length === 0) return `No skill files were created. Check your asset paths.`;
|
|
234
|
+
return `Created ${createdSkills.length} skills in ${skillsBaseDir}`;
|
|
56
235
|
};
|
|
57
236
|
|
|
58
237
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["fs"],"sources":["../../../src/installSkills/index.ts"],"sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { readAsset } from 'utils:asset';\n\nexport const SKILLS_METADATA = {\n Setup: 'General Intlayer setup guide',\n Usage: 'How to use Intlayer in your project',\n RemoteContent: 'How to use Intlayer with Remote/CMS/Server-side content',\n Config: 'Intlayer configuration documentation',\n ExtraAction: 'Additional CLI and automated actions',\n Content: 'Reference for all Intlayer content node types (t, enu, etc.)',\n React: 'React-specific syntax and hooks usage',\n Angular: 'Angular-specific syntax and Injectable Function usage',\n NextJS: 'Next.js-specific usage (Server & Client components)',\n Vue: 'Vue-specific composables and syntax',\n Svelte: 'Svelte-specific stores and syntax',\n Astro: 'Astro-specific usage and getIntlayer',\n} as const;\n\nexport const SKILLS = Object.keys(\n SKILLS_METADATA\n) as (keyof typeof SKILLS_METADATA)[];\n\nexport type Skill = (typeof SKILLS)[number];\n\n/**\n * Helper to convert CamelCase to snake_case\n */\nconst camelToSnakeCase = (str: string) =>\n str.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase();\n\nconst getSkillContent = (skill: Skill): string => {\n const fileName = `./skills/${camelToSnakeCase(skill)}.md`;\n return readAsset(fileName);\n};\n\nexport const installSkills = async (\n projectRoot: string,\n platform: 'Cursor' | 'VSCode' | 'OpenCode' | 'Claude' | 'Other',\n skills: Skill[]\n): Promise<string> => {\n const content = skills.map((skill) => getSkillContent(skill)).join('\\n\\n');\n\n if (platform === 'Cursor' || platform === 'Claude') {\n const fileName = platform === 'Cursor' ? '.cursorrules' : '.clauderules';\n const filePath = path.join(projectRoot, fileName);\n try {\n let existingContent = '';\n try {\n existingContent = await fs.readFile(filePath, 'utf-8');\n } catch {\n // File doesn't exist, ignore\n }\n\n const newContent = existingContent\n ? `${existingContent}\\n\\n${content}`\n : content;\n await fs.writeFile(filePath, newContent, 'utf-8');\n return `Updated ${fileName} with ${skills.join(', ')} skills.`;\n } catch (error) {\n throw new Error(`Failed to write ${fileName}: ${error}`);\n }\n } else {\n // For other platforms, write to .intlayer/skills\n const skillsDir = path.join(projectRoot, '.intlayer/skills');\n await fs.mkdir(skillsDir, { recursive: true });\n\n const createdFiles: string[] = [];\n\n for (const skill of skills) {\n const fileName = `${camelToSnakeCase(skill)}.md`;\n const filePath = path.join(skillsDir, fileName);\n await fs.writeFile(filePath, getSkillContent(skill), 'utf-8');\n createdFiles.push(filePath);\n }\n\n return `Created skills files in ${skillsDir}: ${createdFiles.map((f) => path.basename(f)).join(', ')}`;\n }\n};\n"],"mappings":";;;;;AAIA,MAAa,kBAAkB;CAC7B,OAAO;CACP,OAAO;CACP,eAAe;CACf,QAAQ;CACR,aAAa;CACb,SAAS;CACT,OAAO;CACP,SAAS;CACT,QAAQ;CACR,KAAK;CACL,QAAQ;CACR,OAAO;CACR;AAED,MAAa,SAAS,OAAO,KAC3B,gBACD;;;;AAOD,MAAM,oBAAoB,QACxB,IAAI,QAAQ,sBAAsB,QAAQ,CAAC,aAAa;AAE1D,MAAM,mBAAmB,UAAyB;AAEhD,QAAO,UADU,YAAY,iBAAiB,MAAM,CAAC,KAC3B;;AAG5B,MAAa,gBAAgB,OAC3B,aACA,UACA,WACoB;CACpB,MAAM,UAAU,OAAO,KAAK,UAAU,gBAAgB,MAAM,CAAC,CAAC,KAAK,OAAO;AAE1E,KAAI,aAAa,YAAY,aAAa,UAAU;EAClD,MAAM,WAAW,aAAa,WAAW,iBAAiB;EAC1D,MAAM,WAAW,KAAK,KAAK,aAAa,SAAS;AACjD,MAAI;GACF,IAAI,kBAAkB;AACtB,OAAI;AACF,sBAAkB,MAAMA,SAAG,SAAS,UAAU,QAAQ;WAChD;GAIR,MAAM,aAAa,kBACf,GAAG,gBAAgB,MAAM,YACzB;AACJ,SAAMA,SAAG,UAAU,UAAU,YAAY,QAAQ;AACjD,UAAO,WAAW,SAAS,QAAQ,OAAO,KAAK,KAAK,CAAC;WAC9C,OAAO;AACd,SAAM,IAAI,MAAM,mBAAmB,SAAS,IAAI,QAAQ;;QAErD;EAEL,MAAM,YAAY,KAAK,KAAK,aAAa,mBAAmB;AAC5D,QAAMA,SAAG,MAAM,WAAW,EAAE,WAAW,MAAM,CAAC;EAE9C,MAAM,eAAyB,EAAE;AAEjC,OAAK,MAAM,SAAS,QAAQ;GAC1B,MAAM,WAAW,GAAG,iBAAiB,MAAM,CAAC;GAC5C,MAAM,WAAW,KAAK,KAAK,WAAW,SAAS;AAC/C,SAAMA,SAAG,UAAU,UAAU,gBAAgB,MAAM,EAAE,QAAQ;AAC7D,gBAAa,KAAK,SAAS;;AAG7B,SAAO,2BAA2B,UAAU,IAAI,aAAa,KAAK,MAAM,KAAK,SAAS,EAAE,CAAC,CAAC,KAAK,KAAK"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["fs"],"sources":["../../../src/installSkills/index.ts"],"sourcesContent":["import { promises as fs } from 'node:fs';\nimport https from 'node:https';\nimport path from 'node:path';\nimport { readAsset } from 'utils:asset';\nimport { getMarkdownMetadata } from '@intlayer/core';\n\nexport const SKILLS_METADATA = {\n Usage: 'How to use Intlayer in your project',\n RemoteContent: 'How to use Intlayer with Remote/CMS/Server-side content',\n Config: 'Intlayer configuration documentation',\n Content: 'Reference for all Intlayer content node types (t, enu, etc.)',\n React: 'React-specific syntax and hooks usage',\n Angular: 'Angular-specific syntax and Injectable Function usage',\n NextJS: 'Next.js-specific usage (Server & Client components)',\n Vue: 'Vue-specific composables and syntax',\n Preact: 'Preact-specific syntax and hooks usage',\n Solid: 'Solid-specific primitives and syntax',\n Svelte: 'Svelte-specific stores and syntax',\n Astro: 'Astro-specific usage and getIntlayer',\n CLI: 'Intlayer CLI commands and usage',\n} as const;\n\nexport const SKILLS = Object.keys(\n SKILLS_METADATA\n) as (keyof typeof SKILLS_METADATA)[];\n\nexport type Skill = (typeof SKILLS)[number];\n\nexport type Platform =\n | 'Cursor'\n | 'Windsurf'\n | 'Trae'\n | 'OpenCode'\n | 'GitHub'\n | 'Claude'\n | 'VSCode'\n | 'Antigravity'\n | 'Augment'\n | 'OpenClaw'\n | 'Cline'\n | 'CodeBuddy'\n | 'CommandCode'\n | 'Continue'\n | 'Crush'\n | 'Droid'\n | 'Goose'\n | 'Junie'\n | 'IFlow'\n | 'KiloCode'\n | 'Kiro'\n | 'Kode'\n | 'MCPJam'\n | 'MistralVibe'\n | 'Mux'\n | 'OpenHands'\n | 'Pi'\n | 'Qoder'\n | 'Qwen'\n | 'RooCode'\n | 'TraeCN'\n | 'Zencoder'\n | 'Neovate'\n | 'Pochi'\n | 'Other';\n\n/**\n * Maps specific skill keys to special filenames if they differ from standard snake_case.\n */\nconst SKILL_FILENAME_MAP: Partial<Record<Skill, string>> = {};\n\n/**\n * Helper to convert CamelCase to snake_case for directory naming\n */\nconst camelToSnakeCase = (str: string) =>\n str.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase();\n\n/**\n * Reads the raw markdown content for a specific skill from the assets folder.\n */\nconst getSkillContent = (skill: Skill): string => {\n const baseName = SKILL_FILENAME_MAP[skill] ?? camelToSnakeCase(skill);\n // Source files are flat: ./skills/vue.md\n const fileName = `./skills/${baseName}.md`;\n\n try {\n return readAsset(fileName);\n } catch {\n console.warn(\n `Warning: Could not read asset for skill: ${skill} at ${fileName}`\n );\n return '';\n }\n};\n\n/**\n * Reads the licence content from the assets folder.\n */\nconst getLicenceContent = (): string => {\n try {\n return readAsset('./LICENCE.md');\n } catch {\n console.warn('Warning: Could not read LICENCE.md asset');\n return '';\n }\n};\n\n/**\n * Fetches the content of a URL (supporting redirects).\n */\nconst fetchUrl = (url: string): Promise<string> =>\n new Promise((resolve, reject) => {\n https\n .get(url, (res) => {\n const { statusCode } = res;\n\n if (statusCode === 301 || statusCode === 302) {\n const redirectUrl = res.headers.location;\n if (redirectUrl) {\n return fetchUrl(redirectUrl).then(resolve).catch(reject);\n }\n }\n\n if (statusCode !== 200) {\n return reject(\n new Error(`Failed to fetch ${url}: Status Code ${statusCode}`)\n );\n }\n\n let data = '';\n res.on('data', (chunk) => {\n data += chunk;\n });\n res.on('end', () => {\n resolve(data);\n });\n })\n .on('error', (err) => {\n reject(err);\n });\n });\n\n/**\n * Installs skills using the \"Agent Skills\" directory standard.\n * Standard: <PROJECT_ROOT>/<CONFIG_DIR>/skills/<SKILL_NAME>/SKILL.md\n */\nexport const installSkills = async (\n projectRoot: string,\n platform: Platform,\n skills: Skill[]\n): Promise<string> => {\n let skillsBaseDir = '';\n const useAgentStructure = platform !== 'VSCode';\n\n // Determine the root configuration directory based on Platform\n switch (platform) {\n case 'Cursor':\n skillsBaseDir = path.join(projectRoot, '.cursor/skills');\n break;\n case 'Windsurf':\n skillsBaseDir = path.join(projectRoot, '.windsurf/skills');\n break;\n case 'Trae':\n skillsBaseDir = path.join(projectRoot, '.trae/skills');\n break;\n case 'OpenCode':\n skillsBaseDir = path.join(projectRoot, '.opencode/skills');\n break;\n case 'GitHub': // GitHub Copilot Workspace\n skillsBaseDir = path.join(projectRoot, '.github/skills');\n break;\n case 'Claude': // Claude Desktop / Agent\n skillsBaseDir = path.join(projectRoot, '.claude/skills');\n break;\n case 'VSCode':\n skillsBaseDir = path.join(projectRoot, '.github/skills');\n break;\n case 'Antigravity':\n skillsBaseDir = path.join(projectRoot, '.agent/skills');\n break;\n case 'Augment':\n skillsBaseDir = path.join(projectRoot, '.augment/skills');\n break;\n case 'OpenClaw':\n skillsBaseDir = path.join(projectRoot, 'skills');\n break;\n case 'Cline':\n skillsBaseDir = path.join(projectRoot, '.cline/skills');\n break;\n case 'CodeBuddy':\n skillsBaseDir = path.join(projectRoot, '.codebuddy/skills');\n break;\n case 'CommandCode':\n skillsBaseDir = path.join(projectRoot, '.commandcode/skills');\n break;\n case 'Continue':\n skillsBaseDir = path.join(projectRoot, '.continue/skills');\n break;\n case 'Crush':\n skillsBaseDir = path.join(projectRoot, '.crush/skills');\n break;\n case 'Droid':\n skillsBaseDir = path.join(projectRoot, '.factory/skills');\n break;\n case 'Goose':\n skillsBaseDir = path.join(projectRoot, '.goose/skills');\n break;\n case 'Junie':\n skillsBaseDir = path.join(projectRoot, '.junie/skills');\n break;\n case 'IFlow':\n skillsBaseDir = path.join(projectRoot, '.iflow/skills');\n break;\n case 'KiloCode':\n skillsBaseDir = path.join(projectRoot, '.kilocode/skills');\n break;\n case 'Kiro':\n skillsBaseDir = path.join(projectRoot, '.kiro/skills');\n break;\n case 'Kode':\n skillsBaseDir = path.join(projectRoot, '.kode/skills');\n break;\n case 'MCPJam':\n skillsBaseDir = path.join(projectRoot, '.mcpjam/skills');\n break;\n case 'MistralVibe':\n skillsBaseDir = path.join(projectRoot, '.vibe/skills');\n break;\n case 'Mux':\n skillsBaseDir = path.join(projectRoot, '.mux/skills');\n break;\n case 'OpenHands':\n skillsBaseDir = path.join(projectRoot, '.openhands/skills');\n break;\n case 'Pi':\n skillsBaseDir = path.join(projectRoot, '.pi/skills');\n break;\n case 'Qoder':\n skillsBaseDir = path.join(projectRoot, '.qoder/skills');\n break;\n case 'Qwen':\n skillsBaseDir = path.join(projectRoot, '.qwen/skills');\n break;\n case 'RooCode':\n skillsBaseDir = path.join(projectRoot, '.roo/skills');\n break;\n case 'TraeCN':\n skillsBaseDir = path.join(projectRoot, '.trae/skills');\n break;\n case 'Zencoder':\n skillsBaseDir = path.join(projectRoot, '.zencoder/skills');\n break;\n case 'Neovate':\n skillsBaseDir = path.join(projectRoot, '.neovate/skills');\n break;\n case 'Pochi':\n skillsBaseDir = path.join(projectRoot, '.pochi/skills');\n break;\n default:\n skillsBaseDir = path.join(projectRoot, 'skills');\n break;\n }\n\n // Ensure the base directory exists\n await fs.mkdir(skillsBaseDir, { recursive: true });\n\n const createdSkills: string[] = [];\n const licenceContent = getLicenceContent();\n\n for (const skill of skills) {\n const baseName = SKILL_FILENAME_MAP[skill] ?? camelToSnakeCase(skill);\n const skillName = `intlayer_${baseName}`;\n const skillContent = getSkillContent(skill);\n\n if (!skillContent) continue;\n\n const urls = Array.from(\n new Set(\n skillContent.match(/https:\\/\\/intlayer\\.org\\/doc\\/[^\\s)]+\\.md/g) || []\n )\n );\n\n if (useAgentStructure) {\n // Agent Standard: .../skills/<skill-name>/SKILL.md\n const skillDir = path.join(skillsBaseDir, skillName);\n\n await fs.mkdir(skillDir, { recursive: true });\n\n const filePath = path.join(skillDir, 'SKILL.md');\n\n await fs.writeFile(filePath, skillContent, 'utf-8');\n\n if (licenceContent) {\n const licencePath = path.join(skillDir, 'LICENCE.md');\n\n await fs.writeFile(licencePath, licenceContent, 'utf-8');\n }\n\n // Fetch and save documentation files\n const referenceDir = path.join(skillDir, 'reference');\n\n await fs.mkdir(referenceDir, { recursive: true });\n\n for (const url of urls) {\n try {\n const content = await fetchUrl(url);\n const metadata = getMarkdownMetadata<{\n slugs?: string[];\n }>(content);\n\n let fileName = '';\n\n if (Array.isArray(metadata.slugs)) {\n fileName = metadata.slugs\n .filter((slug) => slug !== 'doc')\n .join('_');\n } else {\n const urlPath = new URL(url).pathname;\n\n fileName = urlPath\n .split('/')\n .filter((part) => part !== '' && part !== 'doc')\n .map((part, index, array) => {\n if (index === array.length - 1) {\n return part.replace('.md', '');\n }\n return part;\n })\n .join('_');\n }\n\n fileName = fileName ? `${fileName}.md` : 'index.md';\n\n const docPath = path.join(referenceDir, fileName);\n\n await fs.writeFile(docPath, content, 'utf-8');\n } catch (error) {\n console.warn(\n `Warning: Could not fetch documentation for ${skill} from ${url}:`,\n error\n );\n }\n }\n\n createdSkills.push(`${skillName}/SKILL.md`);\n } else {\n // Flat Structure (Generic): .../skills/<skill-name>.md\n const fileName = `${skillName}.md`;\n const filePath = path.join(skillsBaseDir, fileName);\n\n await fs.writeFile(filePath, skillContent, 'utf-8');\n\n createdSkills.push(fileName);\n }\n }\n\n if (createdSkills.length === 0) {\n return `No skill files were created. Check your asset paths.`;\n }\n\n return `Created ${createdSkills.length} skills in ${skillsBaseDir}`;\n};\n"],"mappings":"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"}
|