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 === "*")
|
|
@@ -503,7 +558,7 @@ class OpenCodeTarget extends BaseTarget {
|
|
|
503
558
|
const skillSubDir = join4(skillDir, skill.name);
|
|
504
559
|
ensureDir(skillSubDir);
|
|
505
560
|
const filepath = join4(skillSubDir, "SKILL.md");
|
|
506
|
-
writeGeneratedFile(filepath, skill
|
|
561
|
+
writeGeneratedFile(filepath, serializeSkill(skill));
|
|
507
562
|
filesWritten.push(filepath);
|
|
508
563
|
}
|
|
509
564
|
}
|
|
@@ -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 === "*")
|
|
@@ -503,7 +558,7 @@ class OpenCodeTarget extends BaseTarget {
|
|
|
503
558
|
const skillSubDir = join4(skillDir, skill.name);
|
|
504
559
|
ensureDir(skillSubDir);
|
|
505
560
|
const filepath = join4(skillSubDir, "SKILL.md");
|
|
506
|
-
writeGeneratedFile(filepath, skill
|
|
561
|
+
writeGeneratedFile(filepath, serializeSkill(skill));
|
|
507
562
|
filesWritten.push(filepath);
|
|
508
563
|
}
|
|
509
564
|
}
|
|
@@ -758,12 +813,8 @@ class CursorTarget extends BaseTarget {
|
|
|
758
813
|
for (const skill of skills) {
|
|
759
814
|
const skillSubDir = join5(skillsDir, skill.name);
|
|
760
815
|
ensureDir(skillSubDir);
|
|
761
|
-
const frontmatter = {
|
|
762
|
-
name: skill.name,
|
|
763
|
-
description: skill.meta.description ?? ""
|
|
764
|
-
};
|
|
765
816
|
const filepath = join5(skillSubDir, "SKILL.md");
|
|
766
|
-
const content =
|
|
817
|
+
const content = serializeSkill(skill);
|
|
767
818
|
writeGeneratedFile(filepath, content);
|
|
768
819
|
filesWritten.push(filepath);
|
|
769
820
|
}
|
|
@@ -1063,7 +1114,7 @@ ${content}`;
|
|
|
1063
1114
|
const skillSubDir = join6(skillsDir, skill.name);
|
|
1064
1115
|
ensureDir(skillSubDir);
|
|
1065
1116
|
const filepath = join6(skillSubDir, "SKILL.md");
|
|
1066
|
-
writeGeneratedFile(filepath, skill
|
|
1117
|
+
writeGeneratedFile(filepath, serializeSkill(skill));
|
|
1067
1118
|
filesWritten.push(filepath);
|
|
1068
1119
|
}
|
|
1069
1120
|
}
|
|
@@ -1193,7 +1244,7 @@ class CodexCliTarget extends BaseTarget {
|
|
|
1193
1244
|
const skillSubDir = join7(skillsDir, skill.name);
|
|
1194
1245
|
ensureDir(skillSubDir);
|
|
1195
1246
|
const filepath = join7(skillSubDir, "SKILL.md");
|
|
1196
|
-
writeGeneratedFile(filepath, skill
|
|
1247
|
+
writeGeneratedFile(filepath, serializeSkill(skill));
|
|
1197
1248
|
filesWritten.push(filepath);
|
|
1198
1249
|
}
|
|
1199
1250
|
}
|
|
@@ -1201,12 +1252,168 @@ class CodexCliTarget extends BaseTarget {
|
|
|
1201
1252
|
}
|
|
1202
1253
|
}
|
|
1203
1254
|
|
|
1204
|
-
// src/targets/
|
|
1255
|
+
// src/targets/mistral-vibe.ts
|
|
1205
1256
|
import { resolve as resolve5, join as join8 } from "path";
|
|
1206
|
-
var TARGET_ID5 = "
|
|
1257
|
+
var TARGET_ID5 = "mistralvibe";
|
|
1207
1258
|
|
|
1208
|
-
class
|
|
1259
|
+
class MistralVibeTarget extends BaseTarget {
|
|
1209
1260
|
id = TARGET_ID5;
|
|
1261
|
+
name = "Mistral Vibe";
|
|
1262
|
+
supportedFeatures = [
|
|
1263
|
+
"rules",
|
|
1264
|
+
"commands",
|
|
1265
|
+
"agents",
|
|
1266
|
+
"skills",
|
|
1267
|
+
"mcp",
|
|
1268
|
+
"ignore",
|
|
1269
|
+
"models"
|
|
1270
|
+
];
|
|
1271
|
+
generate(options) {
|
|
1272
|
+
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
1273
|
+
const root = resolve5(projectRoot, baseDir);
|
|
1274
|
+
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
1275
|
+
const filesWritten = [];
|
|
1276
|
+
const filesDeleted = [];
|
|
1277
|
+
const warnings = [];
|
|
1278
|
+
const vibeDir = resolve5(root, ".vibe");
|
|
1279
|
+
ensureDir(vibeDir);
|
|
1280
|
+
if (effective.includes("rules")) {
|
|
1281
|
+
const rulesDir = resolve5(vibeDir, "rules");
|
|
1282
|
+
if (deleteExisting) {
|
|
1283
|
+
removeIfExists(rulesDir);
|
|
1284
|
+
filesDeleted.push(rulesDir);
|
|
1285
|
+
}
|
|
1286
|
+
ensureDir(rulesDir);
|
|
1287
|
+
const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID5));
|
|
1288
|
+
for (const rule of rules) {
|
|
1289
|
+
const filepath = join8(rulesDir, `${rule.name}.md`);
|
|
1290
|
+
writeGeneratedFile(filepath, rule.content);
|
|
1291
|
+
filesWritten.push(filepath);
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
if (effective.includes("agents")) {
|
|
1295
|
+
const agentsDir = resolve5(vibeDir, "agents");
|
|
1296
|
+
if (deleteExisting) {
|
|
1297
|
+
removeIfExists(agentsDir);
|
|
1298
|
+
filesDeleted.push(agentsDir);
|
|
1299
|
+
}
|
|
1300
|
+
ensureDir(agentsDir);
|
|
1301
|
+
const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID5));
|
|
1302
|
+
for (const agent of agents) {
|
|
1303
|
+
const filepath = join8(agentsDir, `${agent.name}.md`);
|
|
1304
|
+
writeGeneratedFile(filepath, agent.content);
|
|
1305
|
+
filesWritten.push(filepath);
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
if (effective.includes("skills")) {
|
|
1309
|
+
const skillsDir = resolve5(vibeDir, "skills");
|
|
1310
|
+
if (deleteExisting) {
|
|
1311
|
+
removeIfExists(skillsDir);
|
|
1312
|
+
filesDeleted.push(skillsDir);
|
|
1313
|
+
}
|
|
1314
|
+
ensureDir(skillsDir);
|
|
1315
|
+
const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID5));
|
|
1316
|
+
for (const skill of skills) {
|
|
1317
|
+
const skillSubDir = join8(skillsDir, skill.name);
|
|
1318
|
+
ensureDir(skillSubDir);
|
|
1319
|
+
const filepath = join8(skillSubDir, "SKILL.md");
|
|
1320
|
+
writeGeneratedFile(filepath, serializeSkill(skill));
|
|
1321
|
+
filesWritten.push(filepath);
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
if (effective.includes("commands")) {
|
|
1325
|
+
const commandsDir = resolve5(vibeDir, "commands");
|
|
1326
|
+
if (deleteExisting) {
|
|
1327
|
+
removeIfExists(commandsDir);
|
|
1328
|
+
filesDeleted.push(commandsDir);
|
|
1329
|
+
}
|
|
1330
|
+
ensureDir(commandsDir);
|
|
1331
|
+
const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID5));
|
|
1332
|
+
for (const command of commands) {
|
|
1333
|
+
const filepath = join8(commandsDir, `${command.name}.md`);
|
|
1334
|
+
writeGeneratedFile(filepath, command.content);
|
|
1335
|
+
filesWritten.push(filepath);
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
let hasMcpConfig = false;
|
|
1339
|
+
if (effective.includes("mcp")) {
|
|
1340
|
+
const mcpEntries = Object.entries(features.mcpServers);
|
|
1341
|
+
if (mcpEntries.length > 0) {
|
|
1342
|
+
const filepath = resolve5(vibeDir, "mcp.json");
|
|
1343
|
+
writeGeneratedJson(filepath, { mcpServers: features.mcpServers }, {
|
|
1344
|
+
header: false
|
|
1345
|
+
});
|
|
1346
|
+
filesWritten.push(filepath);
|
|
1347
|
+
hasMcpConfig = true;
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
if (effective.includes("ignore") && features.ignorePatterns.length > 0) {
|
|
1351
|
+
const filepath = resolve5(root, ".vibeignore");
|
|
1352
|
+
writeGeneratedFile(filepath, features.ignorePatterns.join(`
|
|
1353
|
+
`) + `
|
|
1354
|
+
`);
|
|
1355
|
+
filesWritten.push(filepath);
|
|
1356
|
+
}
|
|
1357
|
+
let defaultModel;
|
|
1358
|
+
let smallModel;
|
|
1359
|
+
if (effective.includes("models") && features.models) {
|
|
1360
|
+
const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID5);
|
|
1361
|
+
defaultModel = resolved.default;
|
|
1362
|
+
smallModel = resolved.small;
|
|
1363
|
+
const guidance = generateModelGuidanceMarkdown(resolved);
|
|
1364
|
+
if (guidance) {
|
|
1365
|
+
const filepath = join8(vibeDir, "model-config.md");
|
|
1366
|
+
writeGeneratedFile(filepath, guidance);
|
|
1367
|
+
filesWritten.push(filepath);
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
const vibeConfig = buildVibeConfigToml({
|
|
1371
|
+
hasMcpConfig,
|
|
1372
|
+
defaultModel,
|
|
1373
|
+
smallModel,
|
|
1374
|
+
profile: options.modelProfile
|
|
1375
|
+
});
|
|
1376
|
+
if (vibeConfig.length > 0) {
|
|
1377
|
+
const filepath = resolve5(vibeDir, "config.toml");
|
|
1378
|
+
writeGeneratedFile(filepath, vibeConfig);
|
|
1379
|
+
filesWritten.push(filepath);
|
|
1380
|
+
}
|
|
1381
|
+
return this.createResult(filesWritten, filesDeleted, warnings);
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
function buildVibeConfigToml(options) {
|
|
1385
|
+
const lines = [];
|
|
1386
|
+
if (options.defaultModel || options.smallModel || options.profile) {
|
|
1387
|
+
lines.push("[models]");
|
|
1388
|
+
if (options.defaultModel) {
|
|
1389
|
+
lines.push(`default = "${escapeTomlString(options.defaultModel)}"`);
|
|
1390
|
+
}
|
|
1391
|
+
if (options.smallModel) {
|
|
1392
|
+
lines.push(`small = "${escapeTomlString(options.smallModel)}"`);
|
|
1393
|
+
}
|
|
1394
|
+
if (options.profile) {
|
|
1395
|
+
lines.push(`profile = "${escapeTomlString(options.profile)}"`);
|
|
1396
|
+
}
|
|
1397
|
+
lines.push("");
|
|
1398
|
+
}
|
|
1399
|
+
if (options.hasMcpConfig) {
|
|
1400
|
+
lines.push("[mcp]");
|
|
1401
|
+
lines.push('config_path = ".vibe/mcp.json"');
|
|
1402
|
+
lines.push("");
|
|
1403
|
+
}
|
|
1404
|
+
return lines.join(`
|
|
1405
|
+
`).trim();
|
|
1406
|
+
}
|
|
1407
|
+
function escapeTomlString(value) {
|
|
1408
|
+
return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
// src/targets/gemini-cli.ts
|
|
1412
|
+
import { resolve as resolve6, join as join9 } from "path";
|
|
1413
|
+
var TARGET_ID6 = "geminicli";
|
|
1414
|
+
|
|
1415
|
+
class GeminiCliTarget extends BaseTarget {
|
|
1416
|
+
id = TARGET_ID6;
|
|
1210
1417
|
name = "Gemini CLI";
|
|
1211
1418
|
supportedFeatures = [
|
|
1212
1419
|
"rules",
|
|
@@ -1218,49 +1425,49 @@ class GeminiCliTarget extends BaseTarget {
|
|
|
1218
1425
|
];
|
|
1219
1426
|
generate(options) {
|
|
1220
1427
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
1221
|
-
const root =
|
|
1428
|
+
const root = resolve6(projectRoot, baseDir);
|
|
1222
1429
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
1223
1430
|
const filesWritten = [];
|
|
1224
1431
|
const filesDeleted = [];
|
|
1225
1432
|
const warnings = [];
|
|
1226
|
-
const geminiDir =
|
|
1433
|
+
const geminiDir = resolve6(root, ".gemini");
|
|
1227
1434
|
if (effective.includes("rules")) {
|
|
1228
|
-
const rules = features.rules.filter((r) => ruleMatchesTarget(r,
|
|
1435
|
+
const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID6));
|
|
1229
1436
|
const rootRules = getRootRules(rules);
|
|
1230
1437
|
const detailRules = getDetailRules(rules);
|
|
1231
1438
|
if (rootRules.length > 0) {
|
|
1232
1439
|
const geminiMd = rootRules.map((r) => r.content).join(`
|
|
1233
1440
|
|
|
1234
1441
|
`);
|
|
1235
|
-
const filepath =
|
|
1442
|
+
const filepath = resolve6(root, "GEMINI.md");
|
|
1236
1443
|
writeGeneratedFile(filepath, geminiMd);
|
|
1237
1444
|
filesWritten.push(filepath);
|
|
1238
1445
|
}
|
|
1239
1446
|
if (detailRules.length > 0) {
|
|
1240
|
-
const memoriesDir =
|
|
1447
|
+
const memoriesDir = resolve6(geminiDir, "memories");
|
|
1241
1448
|
if (deleteExisting) {
|
|
1242
1449
|
removeIfExists(memoriesDir);
|
|
1243
1450
|
filesDeleted.push(memoriesDir);
|
|
1244
1451
|
}
|
|
1245
1452
|
ensureDir(memoriesDir);
|
|
1246
1453
|
for (const rule of detailRules) {
|
|
1247
|
-
const filepath =
|
|
1454
|
+
const filepath = join9(memoriesDir, `${rule.name}.md`);
|
|
1248
1455
|
writeGeneratedFile(filepath, rule.content);
|
|
1249
1456
|
filesWritten.push(filepath);
|
|
1250
1457
|
}
|
|
1251
1458
|
}
|
|
1252
1459
|
}
|
|
1253
1460
|
if (effective.includes("commands")) {
|
|
1254
|
-
const commandsDir =
|
|
1461
|
+
const commandsDir = resolve6(geminiDir, "commands");
|
|
1255
1462
|
if (deleteExisting) {
|
|
1256
1463
|
removeIfExists(commandsDir);
|
|
1257
1464
|
filesDeleted.push(commandsDir);
|
|
1258
1465
|
}
|
|
1259
1466
|
ensureDir(commandsDir);
|
|
1260
|
-
const commands = features.commands.filter((c) => commandMatchesTarget(c,
|
|
1467
|
+
const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID6));
|
|
1261
1468
|
for (const cmd of commands) {
|
|
1262
1469
|
const toml = buildGeminiCommand(cmd.name, cmd.meta.description ?? "", cmd.content);
|
|
1263
|
-
const filepath =
|
|
1470
|
+
const filepath = join9(commandsDir, `${cmd.name}.toml`);
|
|
1264
1471
|
writeGeneratedFile(filepath, toml, { type: "md" });
|
|
1265
1472
|
filesWritten.push(filepath);
|
|
1266
1473
|
}
|
|
@@ -1269,14 +1476,14 @@ class GeminiCliTarget extends BaseTarget {
|
|
|
1269
1476
|
const mcpEntries = Object.entries(features.mcpServers);
|
|
1270
1477
|
if (mcpEntries.length > 0) {
|
|
1271
1478
|
const settings = buildGeminiSettings(features.mcpServers);
|
|
1272
|
-
const filepath =
|
|
1479
|
+
const filepath = resolve6(geminiDir, "settings.json");
|
|
1273
1480
|
writeGeneratedJson(filepath, settings, { header: false });
|
|
1274
1481
|
filesWritten.push(filepath);
|
|
1275
1482
|
}
|
|
1276
1483
|
}
|
|
1277
1484
|
if (effective.includes("ignore")) {
|
|
1278
1485
|
if (features.ignorePatterns.length > 0) {
|
|
1279
|
-
const filepath =
|
|
1486
|
+
const filepath = resolve6(root, ".geminiignore");
|
|
1280
1487
|
const content = features.ignorePatterns.join(`
|
|
1281
1488
|
`) + `
|
|
1282
1489
|
`;
|
|
@@ -1315,11 +1522,11 @@ function buildGeminiSettings(servers) {
|
|
|
1315
1522
|
}
|
|
1316
1523
|
|
|
1317
1524
|
// src/targets/copilot.ts
|
|
1318
|
-
import { resolve as
|
|
1319
|
-
var
|
|
1525
|
+
import { resolve as resolve7, join as join10 } from "path";
|
|
1526
|
+
var TARGET_ID7 = "copilot";
|
|
1320
1527
|
|
|
1321
1528
|
class CopilotTarget extends BaseTarget {
|
|
1322
|
-
id =
|
|
1529
|
+
id = TARGET_ID7;
|
|
1323
1530
|
name = "GitHub Copilot";
|
|
1324
1531
|
supportedFeatures = [
|
|
1325
1532
|
"rules",
|
|
@@ -1332,81 +1539,81 @@ class CopilotTarget extends BaseTarget {
|
|
|
1332
1539
|
];
|
|
1333
1540
|
generate(options) {
|
|
1334
1541
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
1335
|
-
const root =
|
|
1542
|
+
const root = resolve7(projectRoot, baseDir);
|
|
1336
1543
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
1337
1544
|
const filesWritten = [];
|
|
1338
1545
|
const filesDeleted = [];
|
|
1339
1546
|
const warnings = [];
|
|
1340
|
-
const githubDir =
|
|
1547
|
+
const githubDir = resolve7(root, ".github");
|
|
1341
1548
|
if (effective.includes("rules")) {
|
|
1342
|
-
const rules = features.rules.filter((r) => ruleMatchesTarget(r,
|
|
1549
|
+
const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID7));
|
|
1343
1550
|
if (rules.length > 0) {
|
|
1344
1551
|
const combinedContent = rules.map((r) => r.content).join(`
|
|
1345
1552
|
|
|
1346
1553
|
---
|
|
1347
1554
|
|
|
1348
1555
|
`);
|
|
1349
|
-
const filepath =
|
|
1556
|
+
const filepath = resolve7(githubDir, "copilot-instructions.md");
|
|
1350
1557
|
ensureDir(githubDir);
|
|
1351
1558
|
writeGeneratedFile(filepath, combinedContent);
|
|
1352
1559
|
filesWritten.push(filepath);
|
|
1353
1560
|
}
|
|
1354
1561
|
}
|
|
1355
1562
|
if (effective.includes("agents")) {
|
|
1356
|
-
const copilotDir =
|
|
1357
|
-
const agentsDir =
|
|
1563
|
+
const copilotDir = resolve7(githubDir, "copilot");
|
|
1564
|
+
const agentsDir = resolve7(copilotDir, "agents");
|
|
1358
1565
|
if (deleteExisting) {
|
|
1359
1566
|
removeIfExists(agentsDir);
|
|
1360
1567
|
filesDeleted.push(agentsDir);
|
|
1361
1568
|
}
|
|
1362
1569
|
ensureDir(agentsDir);
|
|
1363
|
-
const agents = features.agents.filter((a) => agentMatchesTarget(a,
|
|
1570
|
+
const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID7));
|
|
1364
1571
|
for (const agent of agents) {
|
|
1365
|
-
const filepath =
|
|
1572
|
+
const filepath = join10(agentsDir, `${agent.name}.md`);
|
|
1366
1573
|
writeGeneratedFile(filepath, agent.content);
|
|
1367
1574
|
filesWritten.push(filepath);
|
|
1368
1575
|
}
|
|
1369
1576
|
}
|
|
1370
1577
|
if (effective.includes("skills")) {
|
|
1371
|
-
const copilotDir =
|
|
1372
|
-
const skillsDir =
|
|
1578
|
+
const copilotDir = resolve7(githubDir, "copilot");
|
|
1579
|
+
const skillsDir = resolve7(copilotDir, "skills");
|
|
1373
1580
|
if (deleteExisting) {
|
|
1374
1581
|
removeIfExists(skillsDir);
|
|
1375
1582
|
filesDeleted.push(skillsDir);
|
|
1376
1583
|
}
|
|
1377
1584
|
ensureDir(skillsDir);
|
|
1378
|
-
const skills = features.skills.filter((s) => skillMatchesTarget(s,
|
|
1585
|
+
const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID7));
|
|
1379
1586
|
for (const skill of skills) {
|
|
1380
|
-
const skillSubDir =
|
|
1587
|
+
const skillSubDir = join10(skillsDir, skill.name);
|
|
1381
1588
|
ensureDir(skillSubDir);
|
|
1382
|
-
const filepath =
|
|
1383
|
-
writeGeneratedFile(filepath, skill
|
|
1589
|
+
const filepath = join10(skillSubDir, "SKILL.md");
|
|
1590
|
+
writeGeneratedFile(filepath, serializeSkill(skill));
|
|
1384
1591
|
filesWritten.push(filepath);
|
|
1385
1592
|
}
|
|
1386
1593
|
}
|
|
1387
1594
|
if (effective.includes("commands")) {
|
|
1388
|
-
const copilotDir =
|
|
1389
|
-
const commandsDir =
|
|
1595
|
+
const copilotDir = resolve7(githubDir, "copilot");
|
|
1596
|
+
const commandsDir = resolve7(copilotDir, "commands");
|
|
1390
1597
|
if (deleteExisting) {
|
|
1391
1598
|
removeIfExists(commandsDir);
|
|
1392
1599
|
filesDeleted.push(commandsDir);
|
|
1393
1600
|
}
|
|
1394
1601
|
ensureDir(commandsDir);
|
|
1395
|
-
const commands = features.commands.filter((c) => commandMatchesTarget(c,
|
|
1602
|
+
const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID7));
|
|
1396
1603
|
for (const cmd of commands) {
|
|
1397
|
-
const filepath =
|
|
1604
|
+
const filepath = join10(commandsDir, `${cmd.name}.md`);
|
|
1398
1605
|
writeGeneratedFile(filepath, cmd.content);
|
|
1399
1606
|
filesWritten.push(filepath);
|
|
1400
1607
|
}
|
|
1401
1608
|
}
|
|
1402
1609
|
if (effective.includes("ignore")) {}
|
|
1403
1610
|
if (effective.includes("models") && features.models) {
|
|
1404
|
-
const resolved = resolveModels(features.models, options.modelProfile,
|
|
1611
|
+
const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID7);
|
|
1405
1612
|
const guidance = generateModelGuidanceMarkdown(resolved);
|
|
1406
1613
|
if (guidance) {
|
|
1407
|
-
const copilotDir =
|
|
1614
|
+
const copilotDir = resolve7(githubDir, "copilot");
|
|
1408
1615
|
ensureDir(copilotDir);
|
|
1409
|
-
const filepath =
|
|
1616
|
+
const filepath = join10(copilotDir, "model-config.md");
|
|
1410
1617
|
writeGeneratedFile(filepath, guidance);
|
|
1411
1618
|
filesWritten.push(filepath);
|
|
1412
1619
|
}
|
|
@@ -1416,14 +1623,14 @@ class CopilotTarget extends BaseTarget {
|
|
|
1416
1623
|
}
|
|
1417
1624
|
|
|
1418
1625
|
// src/targets/agents-md.ts
|
|
1419
|
-
import { resolve as
|
|
1626
|
+
import { resolve as resolve8 } from "path";
|
|
1420
1627
|
class AgentsMdTarget extends BaseTarget {
|
|
1421
1628
|
id = "agentsmd";
|
|
1422
1629
|
name = "AGENTS.md";
|
|
1423
1630
|
supportedFeatures = ["rules"];
|
|
1424
1631
|
generate(options) {
|
|
1425
1632
|
const { projectRoot, baseDir, features } = options;
|
|
1426
|
-
const root =
|
|
1633
|
+
const root = resolve8(projectRoot, baseDir);
|
|
1427
1634
|
const filesWritten = [];
|
|
1428
1635
|
const warnings = [];
|
|
1429
1636
|
const rootRules = getRootRules(features.rules);
|
|
@@ -1435,7 +1642,7 @@ class AgentsMdTarget extends BaseTarget {
|
|
|
1435
1642
|
const content = sections.join(`
|
|
1436
1643
|
|
|
1437
1644
|
`);
|
|
1438
|
-
const filepath =
|
|
1645
|
+
const filepath = resolve8(root, "AGENTS.md");
|
|
1439
1646
|
writeGeneratedFile(filepath, content);
|
|
1440
1647
|
filesWritten.push(filepath);
|
|
1441
1648
|
return this.createResult(filesWritten, [], warnings);
|
|
@@ -1443,7 +1650,7 @@ class AgentsMdTarget extends BaseTarget {
|
|
|
1443
1650
|
}
|
|
1444
1651
|
|
|
1445
1652
|
// src/targets/generic-md-target.ts
|
|
1446
|
-
import { resolve as
|
|
1653
|
+
import { resolve as resolve9, join as join11 } from "path";
|
|
1447
1654
|
function createGenericMdTarget(config) {
|
|
1448
1655
|
return new GenericMdTarget(config);
|
|
1449
1656
|
}
|
|
@@ -1462,16 +1669,16 @@ class GenericMdTarget extends BaseTarget {
|
|
|
1462
1669
|
}
|
|
1463
1670
|
generate(options) {
|
|
1464
1671
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
1465
|
-
const root =
|
|
1672
|
+
const root = resolve9(projectRoot, baseDir);
|
|
1466
1673
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
1467
1674
|
const filesWritten = [];
|
|
1468
1675
|
const filesDeleted = [];
|
|
1469
1676
|
const warnings = [];
|
|
1470
|
-
const configDir =
|
|
1677
|
+
const configDir = resolve9(root, this.config.configDir);
|
|
1471
1678
|
const rulesSubDir = this.config.rulesDir ?? "rules";
|
|
1472
1679
|
const ext = this.config.ruleExtension ?? ".md";
|
|
1473
1680
|
if (effective.includes("rules")) {
|
|
1474
|
-
const rulesDir =
|
|
1681
|
+
const rulesDir = resolve9(configDir, rulesSubDir);
|
|
1475
1682
|
if (deleteExisting) {
|
|
1476
1683
|
removeIfExists(rulesDir);
|
|
1477
1684
|
filesDeleted.push(rulesDir);
|
|
@@ -1479,13 +1686,13 @@ class GenericMdTarget extends BaseTarget {
|
|
|
1479
1686
|
ensureDir(rulesDir);
|
|
1480
1687
|
const rules = features.rules.filter((r) => ruleMatchesTarget(r, this.id));
|
|
1481
1688
|
for (const rule of rules) {
|
|
1482
|
-
const filepath =
|
|
1689
|
+
const filepath = join11(rulesDir, `${rule.name}${ext}`);
|
|
1483
1690
|
writeGeneratedFile(filepath, rule.content);
|
|
1484
1691
|
filesWritten.push(filepath);
|
|
1485
1692
|
}
|
|
1486
1693
|
}
|
|
1487
1694
|
if (effective.includes("commands")) {
|
|
1488
|
-
const commandsDir =
|
|
1695
|
+
const commandsDir = resolve9(configDir, "commands");
|
|
1489
1696
|
if (deleteExisting) {
|
|
1490
1697
|
removeIfExists(commandsDir);
|
|
1491
1698
|
filesDeleted.push(commandsDir);
|
|
@@ -1493,7 +1700,7 @@ class GenericMdTarget extends BaseTarget {
|
|
|
1493
1700
|
ensureDir(commandsDir);
|
|
1494
1701
|
const commands = features.commands.filter((c) => commandMatchesTarget(c, this.id));
|
|
1495
1702
|
for (const cmd of commands) {
|
|
1496
|
-
const filepath =
|
|
1703
|
+
const filepath = join11(commandsDir, `${cmd.name}.md`);
|
|
1497
1704
|
writeGeneratedFile(filepath, cmd.content);
|
|
1498
1705
|
filesWritten.push(filepath);
|
|
1499
1706
|
}
|
|
@@ -1502,7 +1709,7 @@ class GenericMdTarget extends BaseTarget {
|
|
|
1502
1709
|
const mcpEntries = Object.entries(features.mcpServers);
|
|
1503
1710
|
if (mcpEntries.length > 0) {
|
|
1504
1711
|
const mcpDir = this.config.mcpInConfigDir ? configDir : root;
|
|
1505
|
-
const filepath =
|
|
1712
|
+
const filepath = resolve9(mcpDir, "mcp.json");
|
|
1506
1713
|
writeGeneratedJson(filepath, { mcpServers: features.mcpServers }, {
|
|
1507
1714
|
header: false
|
|
1508
1715
|
});
|
|
@@ -1511,7 +1718,7 @@ class GenericMdTarget extends BaseTarget {
|
|
|
1511
1718
|
}
|
|
1512
1719
|
if (effective.includes("ignore") && this.config.ignoreFile) {
|
|
1513
1720
|
if (features.ignorePatterns.length > 0) {
|
|
1514
|
-
const filepath =
|
|
1721
|
+
const filepath = resolve9(root, this.config.ignoreFile);
|
|
1515
1722
|
writeGeneratedFile(filepath, features.ignorePatterns.join(`
|
|
1516
1723
|
`) + `
|
|
1517
1724
|
`);
|
|
@@ -1523,7 +1730,7 @@ class GenericMdTarget extends BaseTarget {
|
|
|
1523
1730
|
const guidance = generateModelGuidanceMarkdown(resolved);
|
|
1524
1731
|
if (guidance) {
|
|
1525
1732
|
ensureDir(configDir);
|
|
1526
|
-
const filepath =
|
|
1733
|
+
const filepath = join11(configDir, "model-config.md");
|
|
1527
1734
|
writeGeneratedFile(filepath, guidance);
|
|
1528
1735
|
filesWritten.push(filepath);
|
|
1529
1736
|
}
|
|
@@ -1635,6 +1842,7 @@ var TARGETS = [
|
|
|
1635
1842
|
new CursorTarget,
|
|
1636
1843
|
new ClaudeCodeTarget,
|
|
1637
1844
|
new CodexCliTarget,
|
|
1845
|
+
new MistralVibeTarget,
|
|
1638
1846
|
new GeminiCliTarget,
|
|
1639
1847
|
new CopilotTarget,
|
|
1640
1848
|
new AgentsMdTarget,
|
|
@@ -25,8 +25,12 @@ var KNOWN_MODEL_PATTERNS = [
|
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
provider: "Mistral",
|
|
28
|
-
pattern: /^(mistral(ai)?\/)?(mistral|mixtral|codestral|pixtral)[-.\w]*/i,
|
|
29
|
-
examples: [
|
|
28
|
+
pattern: /^(mistral(ai)?\/)?(mistral|mixtral|codestral|pixtral|devstral|magistral|voxtral|ministral)[-.\w]*/i,
|
|
29
|
+
examples: [
|
|
30
|
+
"mistral-large-latest",
|
|
31
|
+
"codestral-latest",
|
|
32
|
+
"devstral-small-latest"
|
|
33
|
+
]
|
|
30
34
|
},
|
|
31
35
|
{
|
|
32
36
|
provider: "Cohere",
|