agentpacks 0.9.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -14
- package/dist/api.js +403 -179
- package/dist/cli/export-cmd.js +58 -5
- package/dist/cli/generate.js +268 -59
- package/dist/cli/import-cmd.js +203 -95
- package/dist/cli/install.js +1 -0
- package/dist/cli/models-explain.js +56 -0
- package/dist/cli/pack/list.js +56 -0
- package/dist/cli/pack/validate.js +143 -18
- package/dist/cli/publish.js +1 -0
- package/dist/core/config.d.ts +1 -1
- package/dist/core/config.js +1 -0
- package/dist/core/index.js +56 -0
- package/dist/core/metarepo.js +1 -0
- package/dist/core/pack-loader.js +56 -0
- package/dist/exporters/cursor-plugin.js +109 -22
- package/dist/exporters/index.js +109 -22
- package/dist/features/index.d.ts +1 -1
- package/dist/features/index.js +59 -0
- package/dist/features/skills.d.ts +22 -0
- package/dist/features/skills.js +60 -1
- package/dist/importers/cursor.js +122 -26
- package/dist/importers/opencode.js +138 -24
- package/dist/importers/rulesync.js +147 -33
- package/dist/index.js +484 -244
- package/dist/node/api.js +403 -179
- package/dist/node/cli/export-cmd.js +58 -5
- package/dist/node/cli/generate.js +268 -59
- package/dist/node/cli/import-cmd.js +203 -95
- package/dist/node/cli/install.js +1 -0
- package/dist/node/cli/models-explain.js +56 -0
- package/dist/node/cli/pack/list.js +56 -0
- package/dist/node/cli/pack/validate.js +143 -18
- package/dist/node/cli/publish.js +1 -0
- package/dist/node/core/config.js +1 -0
- package/dist/node/core/index.js +56 -0
- package/dist/node/core/metarepo.js +1 -0
- package/dist/node/core/pack-loader.js +56 -0
- package/dist/node/exporters/cursor-plugin.js +109 -22
- package/dist/node/exporters/index.js +109 -22
- package/dist/node/features/index.js +59 -0
- package/dist/node/features/skills.js +60 -1
- package/dist/node/importers/cursor.js +122 -26
- package/dist/node/importers/opencode.js +138 -24
- package/dist/node/importers/rulesync.js +147 -33
- package/dist/node/index.js +484 -244
- package/dist/node/targets/claude-code.js +56 -1
- package/dist/node/targets/codex-cli.js +56 -1
- package/dist/node/targets/copilot.js +56 -1
- package/dist/node/targets/cursor.js +56 -5
- package/dist/node/targets/index.js +268 -59
- package/dist/node/targets/mistral-vibe.js +661 -0
- package/dist/node/targets/opencode.js +56 -1
- package/dist/node/targets/registry.js +267 -59
- package/dist/node/utils/model-allowlist.js +6 -2
- package/dist/targets/claude-code.js +56 -1
- package/dist/targets/codex-cli.js +56 -1
- package/dist/targets/copilot.js +56 -1
- package/dist/targets/cursor.js +56 -5
- package/dist/targets/index.d.ts +1 -0
- package/dist/targets/index.js +268 -59
- package/dist/targets/mistral-vibe.d.ts +13 -0
- package/dist/targets/mistral-vibe.js +661 -0
- package/dist/targets/opencode.js +56 -1
- package/dist/targets/registry.js +267 -59
- package/dist/utils/model-allowlist.js +6 -2
- package/package.json +15 -3
|
@@ -219,6 +219,8 @@ function agentMatchesTarget(agent, targetId) {
|
|
|
219
219
|
// src/features/skills.ts
|
|
220
220
|
import { readFileSync as readFileSync5, existsSync as existsSync2 } from "fs";
|
|
221
221
|
import { basename as basename4, join as join2 } from "path";
|
|
222
|
+
var SKILL_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
223
|
+
var SKILL_NAME_MAX_LENGTH = 64;
|
|
222
224
|
function parseSkills(skillsDir, packName) {
|
|
223
225
|
const dirs = listDirs(skillsDir);
|
|
224
226
|
const skills = [];
|
|
@@ -242,6 +244,59 @@ function parseSkillFile(filepath, skillDir, packName) {
|
|
|
242
244
|
content
|
|
243
245
|
};
|
|
244
246
|
}
|
|
247
|
+
function buildSkillFrontmatter(skill) {
|
|
248
|
+
return {
|
|
249
|
+
...skill.meta,
|
|
250
|
+
name: skill.name
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
function serializeSkill(skill) {
|
|
254
|
+
return serializeFrontmatter(buildSkillFrontmatter(skill), skill.content);
|
|
255
|
+
}
|
|
256
|
+
function normalizeImportedSkillMarkdown(source, skillName) {
|
|
257
|
+
const { data, content } = parseFrontmatter(source);
|
|
258
|
+
const normalized = {
|
|
259
|
+
...data,
|
|
260
|
+
name: skillName
|
|
261
|
+
};
|
|
262
|
+
let addedDescription = false;
|
|
263
|
+
const description = normalized.description;
|
|
264
|
+
if (typeof description !== "string" || description.trim().length === 0) {
|
|
265
|
+
normalized.description = `Imported skill: ${skillName}`;
|
|
266
|
+
addedDescription = true;
|
|
267
|
+
}
|
|
268
|
+
return {
|
|
269
|
+
content: serializeFrontmatter(normalized, content),
|
|
270
|
+
addedDescription
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
function validateAgentSkillsFrontmatter(skill) {
|
|
274
|
+
const errors = [];
|
|
275
|
+
const dirName = basename4(skill.sourceDir);
|
|
276
|
+
const declaredName = skill.meta.name;
|
|
277
|
+
if (typeof declaredName !== "string" || declaredName.trim().length === 0) {
|
|
278
|
+
errors.push('Missing required frontmatter field "name".');
|
|
279
|
+
} else {
|
|
280
|
+
if (declaredName.length > SKILL_NAME_MAX_LENGTH) {
|
|
281
|
+
errors.push(`Invalid "name": must be at most ${SKILL_NAME_MAX_LENGTH} characters.`);
|
|
282
|
+
}
|
|
283
|
+
if (!SKILL_NAME_PATTERN.test(declaredName)) {
|
|
284
|
+
errors.push('Invalid "name": use lowercase letters, numbers, and single hyphens only.');
|
|
285
|
+
}
|
|
286
|
+
if (declaredName !== dirName) {
|
|
287
|
+
errors.push(`Invalid "name": must match containing directory "${dirName}".`);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
const description = skill.meta.description;
|
|
291
|
+
if (typeof description !== "string" || description.trim().length === 0) {
|
|
292
|
+
errors.push('Missing required frontmatter field "description".');
|
|
293
|
+
}
|
|
294
|
+
const allowedTools = skill.meta["allowed-tools"];
|
|
295
|
+
if (allowedTools !== undefined && (!Array.isArray(allowedTools) || allowedTools.some((tool) => typeof tool !== "string" || tool.length === 0))) {
|
|
296
|
+
errors.push('Invalid "allowed-tools": expected an array of non-empty strings.');
|
|
297
|
+
}
|
|
298
|
+
return errors;
|
|
299
|
+
}
|
|
245
300
|
function skillMatchesTarget(skill, targetId) {
|
|
246
301
|
const { targets } = skill.meta;
|
|
247
302
|
if (!targets || targets === "*")
|
|
@@ -568,7 +623,7 @@ ${content}`;
|
|
|
568
623
|
const skillSubDir = join4(skillsDir, skill.name);
|
|
569
624
|
ensureDir(skillSubDir);
|
|
570
625
|
const filepath = join4(skillSubDir, "SKILL.md");
|
|
571
|
-
writeGeneratedFile(filepath, skill
|
|
626
|
+
writeGeneratedFile(filepath, serializeSkill(skill));
|
|
572
627
|
filesWritten.push(filepath);
|
|
573
628
|
}
|
|
574
629
|
}
|
|
@@ -165,6 +165,8 @@ function getDetailRules(rules) {
|
|
|
165
165
|
// src/features/skills.ts
|
|
166
166
|
import { readFileSync as readFileSync3, existsSync as existsSync2 } from "fs";
|
|
167
167
|
import { basename as basename2, join as join2 } from "path";
|
|
168
|
+
var SKILL_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
169
|
+
var SKILL_NAME_MAX_LENGTH = 64;
|
|
168
170
|
function parseSkills(skillsDir, packName) {
|
|
169
171
|
const dirs = listDirs(skillsDir);
|
|
170
172
|
const skills = [];
|
|
@@ -188,6 +190,59 @@ function parseSkillFile(filepath, skillDir, packName) {
|
|
|
188
190
|
content
|
|
189
191
|
};
|
|
190
192
|
}
|
|
193
|
+
function buildSkillFrontmatter(skill) {
|
|
194
|
+
return {
|
|
195
|
+
...skill.meta,
|
|
196
|
+
name: skill.name
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function serializeSkill(skill) {
|
|
200
|
+
return serializeFrontmatter(buildSkillFrontmatter(skill), skill.content);
|
|
201
|
+
}
|
|
202
|
+
function normalizeImportedSkillMarkdown(source, skillName) {
|
|
203
|
+
const { data, content } = parseFrontmatter(source);
|
|
204
|
+
const normalized = {
|
|
205
|
+
...data,
|
|
206
|
+
name: skillName
|
|
207
|
+
};
|
|
208
|
+
let addedDescription = false;
|
|
209
|
+
const description = normalized.description;
|
|
210
|
+
if (typeof description !== "string" || description.trim().length === 0) {
|
|
211
|
+
normalized.description = `Imported skill: ${skillName}`;
|
|
212
|
+
addedDescription = true;
|
|
213
|
+
}
|
|
214
|
+
return {
|
|
215
|
+
content: serializeFrontmatter(normalized, content),
|
|
216
|
+
addedDescription
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
function validateAgentSkillsFrontmatter(skill) {
|
|
220
|
+
const errors = [];
|
|
221
|
+
const dirName = basename2(skill.sourceDir);
|
|
222
|
+
const declaredName = skill.meta.name;
|
|
223
|
+
if (typeof declaredName !== "string" || declaredName.trim().length === 0) {
|
|
224
|
+
errors.push('Missing required frontmatter field "name".');
|
|
225
|
+
} else {
|
|
226
|
+
if (declaredName.length > SKILL_NAME_MAX_LENGTH) {
|
|
227
|
+
errors.push(`Invalid "name": must be at most ${SKILL_NAME_MAX_LENGTH} characters.`);
|
|
228
|
+
}
|
|
229
|
+
if (!SKILL_NAME_PATTERN.test(declaredName)) {
|
|
230
|
+
errors.push('Invalid "name": use lowercase letters, numbers, and single hyphens only.');
|
|
231
|
+
}
|
|
232
|
+
if (declaredName !== dirName) {
|
|
233
|
+
errors.push(`Invalid "name": must match containing directory "${dirName}".`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
const description = skill.meta.description;
|
|
237
|
+
if (typeof description !== "string" || description.trim().length === 0) {
|
|
238
|
+
errors.push('Missing required frontmatter field "description".');
|
|
239
|
+
}
|
|
240
|
+
const allowedTools = skill.meta["allowed-tools"];
|
|
241
|
+
if (allowedTools !== undefined && (!Array.isArray(allowedTools) || allowedTools.some((tool) => typeof tool !== "string" || tool.length === 0))) {
|
|
242
|
+
errors.push('Invalid "allowed-tools": expected an array of non-empty strings.');
|
|
243
|
+
}
|
|
244
|
+
return errors;
|
|
245
|
+
}
|
|
191
246
|
function skillMatchesTarget(skill, targetId) {
|
|
192
247
|
const { targets } = skill.meta;
|
|
193
248
|
if (!targets || targets === "*")
|
|
@@ -257,7 +312,7 @@ class CodexCliTarget extends BaseTarget {
|
|
|
257
312
|
const skillSubDir = join3(skillsDir, skill.name);
|
|
258
313
|
ensureDir(skillSubDir);
|
|
259
314
|
const filepath = join3(skillSubDir, "SKILL.md");
|
|
260
|
-
writeGeneratedFile(filepath, skill
|
|
315
|
+
writeGeneratedFile(filepath, serializeSkill(skill));
|
|
261
316
|
filesWritten.push(filepath);
|
|
262
317
|
}
|
|
263
318
|
}
|
package/dist/targets/copilot.js
CHANGED
|
@@ -219,6 +219,8 @@ function agentMatchesTarget(agent, targetId) {
|
|
|
219
219
|
// src/features/skills.ts
|
|
220
220
|
import { readFileSync as readFileSync5, existsSync as existsSync2 } from "fs";
|
|
221
221
|
import { basename as basename4, join as join2 } from "path";
|
|
222
|
+
var SKILL_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
223
|
+
var SKILL_NAME_MAX_LENGTH = 64;
|
|
222
224
|
function parseSkills(skillsDir, packName) {
|
|
223
225
|
const dirs = listDirs(skillsDir);
|
|
224
226
|
const skills = [];
|
|
@@ -242,6 +244,59 @@ function parseSkillFile(filepath, skillDir, packName) {
|
|
|
242
244
|
content
|
|
243
245
|
};
|
|
244
246
|
}
|
|
247
|
+
function buildSkillFrontmatter(skill) {
|
|
248
|
+
return {
|
|
249
|
+
...skill.meta,
|
|
250
|
+
name: skill.name
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
function serializeSkill(skill) {
|
|
254
|
+
return serializeFrontmatter(buildSkillFrontmatter(skill), skill.content);
|
|
255
|
+
}
|
|
256
|
+
function normalizeImportedSkillMarkdown(source, skillName) {
|
|
257
|
+
const { data, content } = parseFrontmatter(source);
|
|
258
|
+
const normalized = {
|
|
259
|
+
...data,
|
|
260
|
+
name: skillName
|
|
261
|
+
};
|
|
262
|
+
let addedDescription = false;
|
|
263
|
+
const description = normalized.description;
|
|
264
|
+
if (typeof description !== "string" || description.trim().length === 0) {
|
|
265
|
+
normalized.description = `Imported skill: ${skillName}`;
|
|
266
|
+
addedDescription = true;
|
|
267
|
+
}
|
|
268
|
+
return {
|
|
269
|
+
content: serializeFrontmatter(normalized, content),
|
|
270
|
+
addedDescription
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
function validateAgentSkillsFrontmatter(skill) {
|
|
274
|
+
const errors = [];
|
|
275
|
+
const dirName = basename4(skill.sourceDir);
|
|
276
|
+
const declaredName = skill.meta.name;
|
|
277
|
+
if (typeof declaredName !== "string" || declaredName.trim().length === 0) {
|
|
278
|
+
errors.push('Missing required frontmatter field "name".');
|
|
279
|
+
} else {
|
|
280
|
+
if (declaredName.length > SKILL_NAME_MAX_LENGTH) {
|
|
281
|
+
errors.push(`Invalid "name": must be at most ${SKILL_NAME_MAX_LENGTH} characters.`);
|
|
282
|
+
}
|
|
283
|
+
if (!SKILL_NAME_PATTERN.test(declaredName)) {
|
|
284
|
+
errors.push('Invalid "name": use lowercase letters, numbers, and single hyphens only.');
|
|
285
|
+
}
|
|
286
|
+
if (declaredName !== dirName) {
|
|
287
|
+
errors.push(`Invalid "name": must match containing directory "${dirName}".`);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
const description = skill.meta.description;
|
|
291
|
+
if (typeof description !== "string" || description.trim().length === 0) {
|
|
292
|
+
errors.push('Missing required frontmatter field "description".');
|
|
293
|
+
}
|
|
294
|
+
const allowedTools = skill.meta["allowed-tools"];
|
|
295
|
+
if (allowedTools !== undefined && (!Array.isArray(allowedTools) || allowedTools.some((tool) => typeof tool !== "string" || tool.length === 0))) {
|
|
296
|
+
errors.push('Invalid "allowed-tools": expected an array of non-empty strings.');
|
|
297
|
+
}
|
|
298
|
+
return errors;
|
|
299
|
+
}
|
|
245
300
|
function skillMatchesTarget(skill, targetId) {
|
|
246
301
|
const { targets } = skill.meta;
|
|
247
302
|
if (!targets || targets === "*")
|
|
@@ -512,7 +567,7 @@ class CopilotTarget extends BaseTarget {
|
|
|
512
567
|
const skillSubDir = join3(skillsDir, skill.name);
|
|
513
568
|
ensureDir(skillSubDir);
|
|
514
569
|
const filepath = join3(skillSubDir, "SKILL.md");
|
|
515
|
-
writeGeneratedFile(filepath, skill
|
|
570
|
+
writeGeneratedFile(filepath, serializeSkill(skill));
|
|
516
571
|
filesWritten.push(filepath);
|
|
517
572
|
}
|
|
518
573
|
}
|
package/dist/targets/cursor.js
CHANGED
|
@@ -219,6 +219,8 @@ function agentMatchesTarget(agent, targetId) {
|
|
|
219
219
|
// src/features/skills.ts
|
|
220
220
|
import { readFileSync as readFileSync5, existsSync as existsSync2 } from "fs";
|
|
221
221
|
import { basename as basename4, join as join2 } from "path";
|
|
222
|
+
var SKILL_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
223
|
+
var SKILL_NAME_MAX_LENGTH = 64;
|
|
222
224
|
function parseSkills(skillsDir, packName) {
|
|
223
225
|
const dirs = listDirs(skillsDir);
|
|
224
226
|
const skills = [];
|
|
@@ -242,6 +244,59 @@ function parseSkillFile(filepath, skillDir, packName) {
|
|
|
242
244
|
content
|
|
243
245
|
};
|
|
244
246
|
}
|
|
247
|
+
function buildSkillFrontmatter(skill) {
|
|
248
|
+
return {
|
|
249
|
+
...skill.meta,
|
|
250
|
+
name: skill.name
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
function serializeSkill(skill) {
|
|
254
|
+
return serializeFrontmatter(buildSkillFrontmatter(skill), skill.content);
|
|
255
|
+
}
|
|
256
|
+
function normalizeImportedSkillMarkdown(source, skillName) {
|
|
257
|
+
const { data, content } = parseFrontmatter(source);
|
|
258
|
+
const normalized = {
|
|
259
|
+
...data,
|
|
260
|
+
name: skillName
|
|
261
|
+
};
|
|
262
|
+
let addedDescription = false;
|
|
263
|
+
const description = normalized.description;
|
|
264
|
+
if (typeof description !== "string" || description.trim().length === 0) {
|
|
265
|
+
normalized.description = `Imported skill: ${skillName}`;
|
|
266
|
+
addedDescription = true;
|
|
267
|
+
}
|
|
268
|
+
return {
|
|
269
|
+
content: serializeFrontmatter(normalized, content),
|
|
270
|
+
addedDescription
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
function validateAgentSkillsFrontmatter(skill) {
|
|
274
|
+
const errors = [];
|
|
275
|
+
const dirName = basename4(skill.sourceDir);
|
|
276
|
+
const declaredName = skill.meta.name;
|
|
277
|
+
if (typeof declaredName !== "string" || declaredName.trim().length === 0) {
|
|
278
|
+
errors.push('Missing required frontmatter field "name".');
|
|
279
|
+
} else {
|
|
280
|
+
if (declaredName.length > SKILL_NAME_MAX_LENGTH) {
|
|
281
|
+
errors.push(`Invalid "name": must be at most ${SKILL_NAME_MAX_LENGTH} characters.`);
|
|
282
|
+
}
|
|
283
|
+
if (!SKILL_NAME_PATTERN.test(declaredName)) {
|
|
284
|
+
errors.push('Invalid "name": use lowercase letters, numbers, and single hyphens only.');
|
|
285
|
+
}
|
|
286
|
+
if (declaredName !== dirName) {
|
|
287
|
+
errors.push(`Invalid "name": must match containing directory "${dirName}".`);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
const description = skill.meta.description;
|
|
291
|
+
if (typeof description !== "string" || description.trim().length === 0) {
|
|
292
|
+
errors.push('Missing required frontmatter field "description".');
|
|
293
|
+
}
|
|
294
|
+
const allowedTools = skill.meta["allowed-tools"];
|
|
295
|
+
if (allowedTools !== undefined && (!Array.isArray(allowedTools) || allowedTools.some((tool) => typeof tool !== "string" || tool.length === 0))) {
|
|
296
|
+
errors.push('Invalid "allowed-tools": expected an array of non-empty strings.');
|
|
297
|
+
}
|
|
298
|
+
return errors;
|
|
299
|
+
}
|
|
245
300
|
function skillMatchesTarget(skill, targetId) {
|
|
246
301
|
const { targets } = skill.meta;
|
|
247
302
|
if (!targets || targets === "*")
|
|
@@ -497,12 +552,8 @@ class CursorTarget extends BaseTarget {
|
|
|
497
552
|
for (const skill of skills) {
|
|
498
553
|
const skillSubDir = join4(skillsDir, skill.name);
|
|
499
554
|
ensureDir(skillSubDir);
|
|
500
|
-
const frontmatter = {
|
|
501
|
-
name: skill.name,
|
|
502
|
-
description: skill.meta.description ?? ""
|
|
503
|
-
};
|
|
504
555
|
const filepath = join4(skillSubDir, "SKILL.md");
|
|
505
|
-
const content =
|
|
556
|
+
const content = serializeSkill(skill);
|
|
506
557
|
writeGeneratedFile(filepath, content);
|
|
507
558
|
filesWritten.push(filepath);
|
|
508
559
|
}
|
package/dist/targets/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export { OpenCodeTarget } from './opencode.js';
|
|
|
3
3
|
export { CursorTarget } from './cursor.js';
|
|
4
4
|
export { ClaudeCodeTarget } from './claude-code.js';
|
|
5
5
|
export { CodexCliTarget } from './codex-cli.js';
|
|
6
|
+
export { MistralVibeTarget } from './mistral-vibe.js';
|
|
6
7
|
export { GeminiCliTarget } from './gemini-cli.js';
|
|
7
8
|
export { CopilotTarget } from './copilot.js';
|
|
8
9
|
export { AgentsMdTarget } from './agents-md.js';
|