agentpacks 0.3.0 → 0.4.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 +168 -8
- package/dist/api.d.ts +2 -0
- package/dist/api.js +929 -409
- package/dist/cli/export-cmd.js +281 -149
- package/dist/cli/generate.js +740 -247
- package/dist/cli/import-cmd.js +57 -85
- package/dist/cli/info.d.ts +4 -0
- package/dist/cli/info.js +232 -0
- package/dist/cli/init.js +8 -36
- package/dist/cli/install.js +414 -129
- package/dist/cli/login.d.ts +9 -0
- package/dist/cli/login.js +202 -0
- package/dist/cli/models-explain.d.ts +16 -0
- package/dist/cli/models-explain.js +1205 -0
- package/dist/cli/pack/create.js +4 -32
- package/dist/cli/pack/enable.js +1 -29
- package/dist/cli/pack/list.js +266 -134
- package/dist/cli/pack/validate.js +274 -127
- package/dist/cli/publish.d.ts +8 -0
- package/dist/cli/publish.js +672 -0
- package/dist/cli/search.d.ts +12 -0
- package/dist/cli/search.js +210 -0
- package/dist/core/config.d.ts +2 -1
- package/dist/core/config.js +74 -117
- package/dist/core/dependency-resolver.js +4 -28
- package/dist/core/feature-merger.d.ts +7 -0
- package/dist/core/feature-merger.js +289 -29
- package/dist/core/index.js +283 -140
- package/dist/core/lockfile.js +0 -28
- package/dist/core/metarepo.js +74 -116
- package/dist/core/pack-loader.d.ts +2 -0
- package/dist/core/pack-loader.js +266 -133
- package/dist/core/profile-resolver.d.ts +75 -0
- package/dist/core/profile-resolver.js +111 -0
- package/dist/exporters/cursor-plugin.js +4 -32
- package/dist/exporters/index.js +4 -32
- package/dist/features/agents.d.ts +5 -0
- package/dist/features/agents.js +2 -30
- package/dist/features/commands.js +2 -30
- package/dist/features/hooks.js +2 -30
- package/dist/features/ignore.js +0 -28
- package/dist/features/index.d.ts +1 -0
- package/dist/features/index.js +176 -31
- package/dist/features/mcp.js +2 -30
- package/dist/features/models.d.ts +167 -0
- package/dist/features/models.js +293 -0
- package/dist/features/plugins.js +2 -30
- package/dist/features/rules.js +2 -30
- package/dist/features/skills.js +2 -30
- package/dist/importers/claude-code.js +10 -38
- package/dist/importers/cursor.js +15 -43
- package/dist/importers/opencode.js +16 -44
- package/dist/importers/rulesync.js +22 -50
- package/dist/index.js +1710 -538
- package/dist/node/api.js +929 -409
- package/dist/node/cli/export-cmd.js +281 -149
- package/dist/node/cli/generate.js +740 -247
- package/dist/node/cli/import-cmd.js +57 -85
- package/dist/node/cli/info.js +232 -0
- package/dist/node/cli/init.js +8 -36
- package/dist/node/cli/install.js +414 -129
- package/dist/node/cli/login.js +202 -0
- package/dist/node/cli/models-explain.js +1205 -0
- package/dist/node/cli/pack/create.js +4 -32
- package/dist/node/cli/pack/enable.js +1 -29
- package/dist/node/cli/pack/list.js +266 -134
- package/dist/node/cli/pack/validate.js +274 -127
- package/dist/node/cli/publish.js +672 -0
- package/dist/node/cli/search.js +210 -0
- package/dist/node/core/config.js +74 -117
- package/dist/node/core/dependency-resolver.js +4 -28
- package/dist/node/core/feature-merger.js +289 -29
- package/dist/node/core/index.js +283 -140
- package/dist/node/core/lockfile.js +0 -28
- package/dist/node/core/metarepo.js +74 -116
- package/dist/node/core/pack-loader.js +266 -133
- package/dist/node/core/profile-resolver.js +111 -0
- package/dist/node/exporters/cursor-plugin.js +4 -32
- package/dist/node/exporters/index.js +4 -32
- package/dist/node/features/agents.js +2 -30
- package/dist/node/features/commands.js +2 -30
- package/dist/node/features/hooks.js +2 -30
- package/dist/node/features/ignore.js +0 -28
- package/dist/node/features/index.js +176 -31
- package/dist/node/features/mcp.js +2 -30
- package/dist/node/features/models.js +293 -0
- package/dist/node/features/plugins.js +2 -30
- package/dist/node/features/rules.js +2 -30
- package/dist/node/features/skills.js +2 -30
- package/dist/node/importers/claude-code.js +10 -38
- package/dist/node/importers/cursor.js +15 -43
- package/dist/node/importers/opencode.js +16 -44
- package/dist/node/importers/rulesync.js +22 -50
- package/dist/node/index.js +1710 -538
- package/dist/node/sources/git-ref.js +7 -30
- package/dist/node/sources/git.js +7 -30
- package/dist/node/sources/index.js +337 -39
- package/dist/node/sources/local.js +0 -28
- package/dist/node/sources/npm-ref.js +0 -28
- package/dist/node/sources/npm.js +10 -37
- package/dist/node/sources/registry-ref.js +37 -0
- package/dist/node/sources/registry.js +355 -0
- package/dist/node/targets/additional-targets.js +196 -37
- package/dist/node/targets/agents-md.js +5 -33
- package/dist/node/targets/base-target.js +0 -28
- package/dist/node/targets/claude-code.js +211 -41
- package/dist/node/targets/codex-cli.js +7 -35
- package/dist/node/targets/copilot.js +202 -41
- package/dist/node/targets/cursor.js +188 -40
- package/dist/node/targets/gemini-cli.js +10 -38
- package/dist/node/targets/generic-md-target.js +196 -37
- package/dist/node/targets/index.js +414 -106
- package/dist/node/targets/opencode.js +171 -51
- package/dist/node/targets/registry.js +414 -106
- package/dist/node/utils/credentials.js +38 -0
- package/dist/node/utils/diff.js +22 -34
- package/dist/node/utils/filesystem.js +2 -30
- package/dist/node/utils/frontmatter.js +0 -28
- package/dist/node/utils/global.js +3 -31
- package/dist/node/utils/markdown.js +0 -28
- package/dist/node/utils/model-allowlist.js +110 -0
- package/dist/node/utils/model-guidance.js +78 -0
- package/dist/node/utils/registry-client.js +142 -0
- package/dist/node/utils/tarball.js +49 -0
- package/dist/sources/git-ref.js +7 -30
- package/dist/sources/git.d.ts +2 -2
- package/dist/sources/git.js +7 -30
- package/dist/sources/index.d.ts +2 -0
- package/dist/sources/index.js +337 -39
- package/dist/sources/local.js +0 -28
- package/dist/sources/npm-ref.js +0 -28
- package/dist/sources/npm.js +10 -37
- package/dist/sources/registry-ref.d.ts +30 -0
- package/dist/sources/registry-ref.js +37 -0
- package/dist/sources/registry.d.ts +18 -0
- package/dist/sources/registry.js +355 -0
- package/dist/targets/additional-targets.js +196 -37
- package/dist/targets/agents-md.js +5 -33
- package/dist/targets/base-target.d.ts +2 -0
- package/dist/targets/base-target.js +0 -28
- package/dist/targets/claude-code.js +211 -41
- package/dist/targets/codex-cli.js +7 -35
- package/dist/targets/copilot.js +202 -41
- package/dist/targets/cursor.js +188 -40
- package/dist/targets/gemini-cli.js +10 -38
- package/dist/targets/generic-md-target.js +196 -37
- package/dist/targets/index.js +414 -106
- package/dist/targets/opencode.js +171 -51
- package/dist/targets/registry.js +414 -106
- package/dist/utils/credentials.d.ts +19 -0
- package/dist/utils/credentials.js +38 -0
- package/dist/utils/diff.js +22 -34
- package/dist/utils/filesystem.js +2 -30
- package/dist/utils/frontmatter.js +0 -28
- package/dist/utils/global.js +3 -31
- package/dist/utils/markdown.js +0 -28
- package/dist/utils/model-allowlist.d.ts +39 -0
- package/dist/utils/model-allowlist.js +110 -0
- package/dist/utils/model-guidance.d.ts +6 -0
- package/dist/utils/model-guidance.js +78 -0
- package/dist/utils/registry-client.d.ts +141 -0
- package/dist/utils/registry-client.js +142 -0
- package/dist/utils/tarball.d.ts +13 -0
- package/dist/utils/tarball.js +49 -0
- package/package.json +171 -5
- package/templates/pack/models.json +38 -0
package/dist/targets/index.js
CHANGED
|
@@ -1,32 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
7
|
-
var __toCommonJS = (from) => {
|
|
8
|
-
var entry = __moduleCache.get(from), desc;
|
|
9
|
-
if (entry)
|
|
10
|
-
return entry;
|
|
11
|
-
entry = __defProp({}, "__esModule", { value: true });
|
|
12
|
-
if (from && typeof from === "object" || typeof from === "function")
|
|
13
|
-
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
14
|
-
get: () => from[key],
|
|
15
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
-
}));
|
|
17
|
-
__moduleCache.set(from, entry);
|
|
18
|
-
return entry;
|
|
19
|
-
};
|
|
20
|
-
var __export = (target, all) => {
|
|
21
|
-
for (var name in all)
|
|
22
|
-
__defProp(target, name, {
|
|
23
|
-
get: all[name],
|
|
24
|
-
enumerable: true,
|
|
25
|
-
configurable: true,
|
|
26
|
-
set: (newValue) => all[name] = () => newValue
|
|
27
|
-
});
|
|
28
|
-
};
|
|
29
|
-
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
30
2
|
var __require = import.meta.require;
|
|
31
3
|
|
|
32
4
|
// src/utils/filesystem.ts
|
|
@@ -36,10 +8,10 @@ import {
|
|
|
36
8
|
readFileSync,
|
|
37
9
|
writeFileSync,
|
|
38
10
|
readdirSync,
|
|
11
|
+
rmSync,
|
|
39
12
|
statSync
|
|
40
13
|
} from "fs";
|
|
41
14
|
import { dirname, relative, join } from "path";
|
|
42
|
-
import { removeSync } from "fs-extra";
|
|
43
15
|
var GENERATED_HEADER_MD = "<!-- Generated by agentpacks. DO NOT EDIT. -->";
|
|
44
16
|
var GENERATED_HEADER_JSON = "// Generated by agentpacks. DO NOT EDIT.";
|
|
45
17
|
var GENERATED_HEADER_JS = "// Generated by agentpacks. DO NOT EDIT.";
|
|
@@ -80,7 +52,7 @@ function ensureDir(dirPath) {
|
|
|
80
52
|
}
|
|
81
53
|
function removeIfExists(targetPath) {
|
|
82
54
|
if (existsSync(targetPath)) {
|
|
83
|
-
|
|
55
|
+
rmSync(targetPath, { recursive: true, force: true });
|
|
84
56
|
}
|
|
85
57
|
}
|
|
86
58
|
function listFiles(dirPath, options = {}) {
|
|
@@ -317,6 +289,110 @@ function resolveHooksForTarget(hooks, targetId) {
|
|
|
317
289
|
return merged;
|
|
318
290
|
}
|
|
319
291
|
|
|
292
|
+
// src/core/profile-resolver.ts
|
|
293
|
+
function resolveModels(merged, modelProfile, targetId) {
|
|
294
|
+
let defaultModel = merged.default;
|
|
295
|
+
let smallModel = merged.small;
|
|
296
|
+
let agents = { ...merged.agents };
|
|
297
|
+
if (modelProfile && merged.profiles?.[modelProfile]) {
|
|
298
|
+
const resolvedProfile = resolveProfileInheritance(modelProfile, merged.profiles);
|
|
299
|
+
if (resolvedProfile.default)
|
|
300
|
+
defaultModel = resolvedProfile.default;
|
|
301
|
+
if (resolvedProfile.small)
|
|
302
|
+
smallModel = resolvedProfile.small;
|
|
303
|
+
if (resolvedProfile.agents) {
|
|
304
|
+
agents = { ...agents, ...resolvedProfile.agents };
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
if (targetId) {
|
|
308
|
+
const targetOverride = merged.overrides?.[targetId];
|
|
309
|
+
if (targetOverride) {
|
|
310
|
+
if (targetOverride.default)
|
|
311
|
+
defaultModel = targetOverride.default;
|
|
312
|
+
if (targetOverride.small)
|
|
313
|
+
smallModel = targetOverride.small;
|
|
314
|
+
if (targetOverride.agents) {
|
|
315
|
+
agents = { ...agents, ...targetOverride.agents };
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
const providers = {};
|
|
320
|
+
if (merged.providers) {
|
|
321
|
+
for (const [name, config] of Object.entries(merged.providers)) {
|
|
322
|
+
providers[name] = {
|
|
323
|
+
...config.options ? { options: config.options } : {},
|
|
324
|
+
...config.models ? { models: config.models } : {}
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
const profileNames = Object.keys(merged.profiles ?? {});
|
|
329
|
+
const profiles = {};
|
|
330
|
+
if (merged.profiles) {
|
|
331
|
+
for (const [name, profile] of Object.entries(merged.profiles)) {
|
|
332
|
+
profiles[name] = {
|
|
333
|
+
description: profile.description,
|
|
334
|
+
default: profile.default,
|
|
335
|
+
small: profile.small
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return {
|
|
340
|
+
default: defaultModel,
|
|
341
|
+
small: smallModel,
|
|
342
|
+
agents,
|
|
343
|
+
providers,
|
|
344
|
+
routing: merged.routing ?? [],
|
|
345
|
+
profileNames,
|
|
346
|
+
activeProfile: modelProfile,
|
|
347
|
+
profiles
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
function resolveAgentModel(resolved, agentName, frontmatterModel) {
|
|
351
|
+
const fromModels = resolved.agents[agentName];
|
|
352
|
+
if (fromModels) {
|
|
353
|
+
return {
|
|
354
|
+
model: fromModels.model,
|
|
355
|
+
temperature: fromModels.temperature,
|
|
356
|
+
top_p: fromModels.top_p
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
if (frontmatterModel) {
|
|
360
|
+
return { model: frontmatterModel };
|
|
361
|
+
}
|
|
362
|
+
return {};
|
|
363
|
+
}
|
|
364
|
+
function resolveProfileInheritance(profileName, profiles) {
|
|
365
|
+
const visited = new Set;
|
|
366
|
+
return resolveProfileChain(profileName, profiles, visited, 0);
|
|
367
|
+
}
|
|
368
|
+
var MAX_INHERITANCE_DEPTH = 10;
|
|
369
|
+
function resolveProfileChain(name, profiles, visited, depth) {
|
|
370
|
+
if (depth > MAX_INHERITANCE_DEPTH) {
|
|
371
|
+
throw new Error(`Profile inheritance too deep (max ${MAX_INHERITANCE_DEPTH}): ${name}`);
|
|
372
|
+
}
|
|
373
|
+
if (visited.has(name)) {
|
|
374
|
+
throw new Error(`Circular profile inheritance detected: ${[...visited, name].join(" \u2192 ")}`);
|
|
375
|
+
}
|
|
376
|
+
const profile = profiles[name];
|
|
377
|
+
if (!profile) {
|
|
378
|
+
throw new Error(`Profile "${name}" not found`);
|
|
379
|
+
}
|
|
380
|
+
visited.add(name);
|
|
381
|
+
if (!profile.extends) {
|
|
382
|
+
return { ...profile };
|
|
383
|
+
}
|
|
384
|
+
const parent = resolveProfileChain(profile.extends, profiles, visited, depth + 1);
|
|
385
|
+
return {
|
|
386
|
+
description: profile.description ?? parent.description,
|
|
387
|
+
default: profile.default ?? parent.default,
|
|
388
|
+
small: profile.small ?? parent.small,
|
|
389
|
+
agents: {
|
|
390
|
+
...parent.agents,
|
|
391
|
+
...profile.agents
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
|
|
320
396
|
// src/targets/base-target.ts
|
|
321
397
|
class BaseTarget {
|
|
322
398
|
supportsFeature(feature) {
|
|
@@ -361,7 +437,7 @@ ${content}`;
|
|
|
361
437
|
}
|
|
362
438
|
|
|
363
439
|
// src/targets/opencode.ts
|
|
364
|
-
import { resolve
|
|
440
|
+
import { resolve, join as join4 } from "path";
|
|
365
441
|
var TARGET_ID = "opencode";
|
|
366
442
|
|
|
367
443
|
class OpenCodeTarget extends BaseTarget {
|
|
@@ -375,32 +451,48 @@ class OpenCodeTarget extends BaseTarget {
|
|
|
375
451
|
"hooks",
|
|
376
452
|
"plugins",
|
|
377
453
|
"mcp",
|
|
378
|
-
"ignore"
|
|
454
|
+
"ignore",
|
|
455
|
+
"models"
|
|
379
456
|
];
|
|
380
457
|
generate(options) {
|
|
381
458
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
382
|
-
const root =
|
|
459
|
+
const root = resolve(projectRoot, baseDir);
|
|
383
460
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
384
461
|
const filesWritten = [];
|
|
385
462
|
const filesDeleted = [];
|
|
386
463
|
const warnings = [];
|
|
387
|
-
const opencodeDir =
|
|
464
|
+
const opencodeDir = resolve(root, ".opencode");
|
|
388
465
|
if (effective.includes("agents")) {
|
|
389
|
-
const agentDir =
|
|
466
|
+
const agentDir = resolve(opencodeDir, "agent");
|
|
390
467
|
if (deleteExisting) {
|
|
391
468
|
removeIfExists(agentDir);
|
|
392
469
|
filesDeleted.push(agentDir);
|
|
393
470
|
}
|
|
394
471
|
ensureDir(agentDir);
|
|
472
|
+
const resolvedModels = features.models ? resolveModels(features.models, options.modelProfile, TARGET_ID) : null;
|
|
395
473
|
const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID));
|
|
396
474
|
for (const agent of agents) {
|
|
397
475
|
const filepath = join4(agentDir, `${agent.name}.md`);
|
|
398
|
-
|
|
476
|
+
const fm = {};
|
|
477
|
+
const oc = agent.meta.opencode ?? {};
|
|
478
|
+
const modelsAgent = resolvedModels?.agents[agent.name];
|
|
479
|
+
const agentModel = modelsAgent?.model ?? oc.model;
|
|
480
|
+
const agentTemp = modelsAgent?.temperature ?? oc.temperature;
|
|
481
|
+
if (agentModel)
|
|
482
|
+
fm.model = agentModel;
|
|
483
|
+
if (agentTemp !== undefined)
|
|
484
|
+
fm.temperature = agentTemp;
|
|
485
|
+
if (oc.mode)
|
|
486
|
+
fm.mode = oc.mode;
|
|
487
|
+
if (oc.top_p !== undefined)
|
|
488
|
+
fm.top_p = oc.top_p;
|
|
489
|
+
const content = Object.keys(fm).length > 0 ? serializeFrontmatter(fm, agent.content) : agent.content;
|
|
490
|
+
writeGeneratedFile(filepath, content);
|
|
399
491
|
filesWritten.push(filepath);
|
|
400
492
|
}
|
|
401
493
|
}
|
|
402
494
|
if (effective.includes("skills")) {
|
|
403
|
-
const skillDir =
|
|
495
|
+
const skillDir = resolve(opencodeDir, "skill");
|
|
404
496
|
if (deleteExisting) {
|
|
405
497
|
removeIfExists(skillDir);
|
|
406
498
|
filesDeleted.push(skillDir);
|
|
@@ -416,7 +508,7 @@ class OpenCodeTarget extends BaseTarget {
|
|
|
416
508
|
}
|
|
417
509
|
}
|
|
418
510
|
if (effective.includes("commands")) {
|
|
419
|
-
const cmdDir =
|
|
511
|
+
const cmdDir = resolve(opencodeDir, "command");
|
|
420
512
|
if (deleteExisting) {
|
|
421
513
|
removeIfExists(cmdDir);
|
|
422
514
|
filesDeleted.push(cmdDir);
|
|
@@ -430,7 +522,7 @@ class OpenCodeTarget extends BaseTarget {
|
|
|
430
522
|
}
|
|
431
523
|
}
|
|
432
524
|
if (effective.includes("hooks") || effective.includes("plugins")) {
|
|
433
|
-
const pluginsDir =
|
|
525
|
+
const pluginsDir = resolve(opencodeDir, "plugins");
|
|
434
526
|
ensureDir(pluginsDir);
|
|
435
527
|
if (effective.includes("hooks")) {
|
|
436
528
|
for (const hookSet of features.hooks) {
|
|
@@ -453,21 +545,52 @@ class OpenCodeTarget extends BaseTarget {
|
|
|
453
545
|
}
|
|
454
546
|
}
|
|
455
547
|
}
|
|
456
|
-
if (effective.includes("mcp")) {
|
|
457
|
-
const
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
548
|
+
if (effective.includes("mcp") || effective.includes("models")) {
|
|
549
|
+
const filepath = resolve(root, "opencode.json");
|
|
550
|
+
const opencodeConfig = {
|
|
551
|
+
$schema: "https://opencode.ai/config.json"
|
|
552
|
+
};
|
|
553
|
+
if (effective.includes("mcp")) {
|
|
554
|
+
const mcpEntries = Object.entries(features.mcpServers);
|
|
555
|
+
if (mcpEntries.length > 0) {
|
|
556
|
+
opencodeConfig.mcp = buildOpenCodeMcpServers(features.mcpServers);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
if (effective.includes("models") && features.models) {
|
|
560
|
+
const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID);
|
|
561
|
+
if (resolved.default)
|
|
562
|
+
opencodeConfig.model = resolved.default;
|
|
563
|
+
if (resolved.small)
|
|
564
|
+
opencodeConfig.small_model = resolved.small;
|
|
565
|
+
if (Object.keys(resolved.providers).length > 0) {
|
|
566
|
+
opencodeConfig.provider = resolved.providers;
|
|
567
|
+
}
|
|
568
|
+
const agentEntries = Object.entries(resolved.agents);
|
|
569
|
+
if (agentEntries.length > 0) {
|
|
570
|
+
const agentConfig = {};
|
|
571
|
+
for (const [name, assignment] of agentEntries) {
|
|
572
|
+
const config = { model: assignment.model };
|
|
573
|
+
if (assignment.temperature !== undefined) {
|
|
574
|
+
config.temperature = assignment.temperature;
|
|
575
|
+
}
|
|
576
|
+
if (assignment.top_p !== undefined) {
|
|
577
|
+
config.top_p = assignment.top_p;
|
|
578
|
+
}
|
|
579
|
+
agentConfig[name] = config;
|
|
580
|
+
}
|
|
581
|
+
opencodeConfig.agent = agentConfig;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
if (Object.keys(opencodeConfig).length > 1) {
|
|
461
585
|
writeGeneratedJson(filepath, opencodeConfig, { header: false });
|
|
462
586
|
filesWritten.push(filepath);
|
|
463
587
|
}
|
|
464
588
|
}
|
|
465
589
|
if (effective.includes("rules")) {
|
|
466
590
|
const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID));
|
|
467
|
-
const rootRules = getRootRules(rules);
|
|
468
591
|
const detailRules = getDetailRules(rules);
|
|
469
592
|
if (detailRules.length > 0) {
|
|
470
|
-
const memoriesDir =
|
|
593
|
+
const memoriesDir = resolve(opencodeDir, "memories");
|
|
471
594
|
if (deleteExisting) {
|
|
472
595
|
removeIfExists(memoriesDir);
|
|
473
596
|
filesDeleted.push(memoriesDir);
|
|
@@ -483,7 +606,7 @@ class OpenCodeTarget extends BaseTarget {
|
|
|
483
606
|
return this.createResult(filesWritten, filesDeleted, warnings);
|
|
484
607
|
}
|
|
485
608
|
}
|
|
486
|
-
function
|
|
609
|
+
function buildOpenCodeMcpServers(servers) {
|
|
487
610
|
const mcp = {};
|
|
488
611
|
for (const [name, entry] of Object.entries(servers)) {
|
|
489
612
|
if (entry.url) {
|
|
@@ -503,10 +626,7 @@ function buildOpenCodeMcp(servers) {
|
|
|
503
626
|
};
|
|
504
627
|
}
|
|
505
628
|
}
|
|
506
|
-
return
|
|
507
|
-
$schema: "https://opencode.ai/config.json",
|
|
508
|
-
mcp
|
|
509
|
-
};
|
|
629
|
+
return mcp;
|
|
510
630
|
}
|
|
511
631
|
function generateOpenCodeHookPlugin(packName, events) {
|
|
512
632
|
const identifier = packNameToIdentifier(packName);
|
|
@@ -553,7 +673,7 @@ function mapHookEvents(events) {
|
|
|
553
673
|
}
|
|
554
674
|
|
|
555
675
|
// src/targets/cursor.ts
|
|
556
|
-
import { resolve as
|
|
676
|
+
import { resolve as resolve2, join as join5 } from "path";
|
|
557
677
|
var TARGET_ID2 = "cursor";
|
|
558
678
|
|
|
559
679
|
class CursorTarget extends BaseTarget {
|
|
@@ -566,18 +686,19 @@ class CursorTarget extends BaseTarget {
|
|
|
566
686
|
"skills",
|
|
567
687
|
"hooks",
|
|
568
688
|
"mcp",
|
|
569
|
-
"ignore"
|
|
689
|
+
"ignore",
|
|
690
|
+
"models"
|
|
570
691
|
];
|
|
571
692
|
generate(options) {
|
|
572
693
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
573
|
-
const root =
|
|
694
|
+
const root = resolve2(projectRoot, baseDir);
|
|
574
695
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
575
696
|
const filesWritten = [];
|
|
576
697
|
const filesDeleted = [];
|
|
577
698
|
const warnings = [];
|
|
578
|
-
const cursorDir =
|
|
699
|
+
const cursorDir = resolve2(root, ".cursor");
|
|
579
700
|
if (effective.includes("rules")) {
|
|
580
|
-
const rulesDir =
|
|
701
|
+
const rulesDir = resolve2(cursorDir, "rules");
|
|
581
702
|
if (deleteExisting) {
|
|
582
703
|
removeIfExists(rulesDir);
|
|
583
704
|
filesDeleted.push(rulesDir);
|
|
@@ -601,18 +722,25 @@ class CursorTarget extends BaseTarget {
|
|
|
601
722
|
}
|
|
602
723
|
}
|
|
603
724
|
if (effective.includes("agents")) {
|
|
604
|
-
const agentsDir =
|
|
725
|
+
const agentsDir = resolve2(cursorDir, "agents");
|
|
605
726
|
if (deleteExisting) {
|
|
606
727
|
removeIfExists(agentsDir);
|
|
607
728
|
filesDeleted.push(agentsDir);
|
|
608
729
|
}
|
|
609
730
|
ensureDir(agentsDir);
|
|
731
|
+
const resolvedModels = features.models ? resolveModels(features.models, options.modelProfile, TARGET_ID2) : null;
|
|
610
732
|
const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID2));
|
|
611
733
|
for (const agent of agents) {
|
|
612
734
|
const frontmatter = {
|
|
613
735
|
name: agent.name,
|
|
614
736
|
description: agent.meta.description ?? ""
|
|
615
737
|
};
|
|
738
|
+
const cursorMeta = agent.meta.cursor ?? {};
|
|
739
|
+
const modelsAgent = resolvedModels?.agents[agent.name];
|
|
740
|
+
const model = modelsAgent?.model ?? cursorMeta.model;
|
|
741
|
+
if (model) {
|
|
742
|
+
frontmatter.model = model;
|
|
743
|
+
}
|
|
616
744
|
const filepath = join5(agentsDir, `${agent.name}.md`);
|
|
617
745
|
const content = serializeFrontmatter(frontmatter, agent.content);
|
|
618
746
|
writeGeneratedFile(filepath, content);
|
|
@@ -620,7 +748,7 @@ class CursorTarget extends BaseTarget {
|
|
|
620
748
|
}
|
|
621
749
|
}
|
|
622
750
|
if (effective.includes("skills")) {
|
|
623
|
-
const skillsDir =
|
|
751
|
+
const skillsDir = resolve2(cursorDir, "skills");
|
|
624
752
|
if (deleteExisting) {
|
|
625
753
|
removeIfExists(skillsDir);
|
|
626
754
|
filesDeleted.push(skillsDir);
|
|
@@ -641,7 +769,7 @@ class CursorTarget extends BaseTarget {
|
|
|
641
769
|
}
|
|
642
770
|
}
|
|
643
771
|
if (effective.includes("commands")) {
|
|
644
|
-
const commandsDir =
|
|
772
|
+
const commandsDir = resolve2(cursorDir, "commands");
|
|
645
773
|
if (deleteExisting) {
|
|
646
774
|
removeIfExists(commandsDir);
|
|
647
775
|
filesDeleted.push(commandsDir);
|
|
@@ -658,14 +786,14 @@ class CursorTarget extends BaseTarget {
|
|
|
658
786
|
const mcpEntries = Object.entries(features.mcpServers);
|
|
659
787
|
if (mcpEntries.length > 0) {
|
|
660
788
|
const mcpConfig = buildCursorMcp(features.mcpServers);
|
|
661
|
-
const filepath =
|
|
789
|
+
const filepath = resolve2(cursorDir, "mcp.json");
|
|
662
790
|
writeGeneratedJson(filepath, mcpConfig, { header: false });
|
|
663
791
|
filesWritten.push(filepath);
|
|
664
792
|
}
|
|
665
793
|
}
|
|
666
794
|
if (effective.includes("ignore")) {
|
|
667
795
|
if (features.ignorePatterns.length > 0) {
|
|
668
|
-
const filepath =
|
|
796
|
+
const filepath = resolve2(root, ".cursorignore");
|
|
669
797
|
const content = features.ignorePatterns.join(`
|
|
670
798
|
`) + `
|
|
671
799
|
`;
|
|
@@ -673,6 +801,17 @@ class CursorTarget extends BaseTarget {
|
|
|
673
801
|
filesWritten.push(filepath);
|
|
674
802
|
}
|
|
675
803
|
}
|
|
804
|
+
if (effective.includes("models") && features.models) {
|
|
805
|
+
const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID2);
|
|
806
|
+
const guidanceContent = buildCursorModelGuidance(resolved);
|
|
807
|
+
if (guidanceContent) {
|
|
808
|
+
const rulesDir = resolve2(cursorDir, "rules");
|
|
809
|
+
ensureDir(rulesDir);
|
|
810
|
+
const filepath = join5(rulesDir, "model-config.mdc");
|
|
811
|
+
writeGeneratedFile(filepath, guidanceContent, { header: false });
|
|
812
|
+
filesWritten.push(filepath);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
676
815
|
return this.createResult(filesWritten, filesDeleted, warnings);
|
|
677
816
|
}
|
|
678
817
|
}
|
|
@@ -691,9 +830,135 @@ function buildCursorMcp(servers) {
|
|
|
691
830
|
}
|
|
692
831
|
return { mcpServers };
|
|
693
832
|
}
|
|
833
|
+
function buildCursorModelGuidance(resolved) {
|
|
834
|
+
if (!resolved.default && !resolved.small && Object.keys(resolved.agents).length === 0) {
|
|
835
|
+
return null;
|
|
836
|
+
}
|
|
837
|
+
const frontmatter = {
|
|
838
|
+
description: "Model configuration and selection guidelines for this workspace",
|
|
839
|
+
alwaysApply: true
|
|
840
|
+
};
|
|
841
|
+
const lines = [];
|
|
842
|
+
lines.push("# Model Configuration");
|
|
843
|
+
lines.push("");
|
|
844
|
+
lines.push("Use the following model preferences when working in this project.");
|
|
845
|
+
lines.push("");
|
|
846
|
+
if (resolved.default || resolved.small) {
|
|
847
|
+
lines.push("## Default Models");
|
|
848
|
+
lines.push("");
|
|
849
|
+
if (resolved.default) {
|
|
850
|
+
lines.push(`- **Primary model**: ${resolved.default}`);
|
|
851
|
+
}
|
|
852
|
+
if (resolved.small) {
|
|
853
|
+
lines.push(`- **Lightweight tasks** (titles, summaries): ${resolved.small}`);
|
|
854
|
+
}
|
|
855
|
+
lines.push("");
|
|
856
|
+
}
|
|
857
|
+
const agentEntries = Object.entries(resolved.agents);
|
|
858
|
+
if (agentEntries.length > 0) {
|
|
859
|
+
lines.push("## Agent Model Assignments");
|
|
860
|
+
lines.push("");
|
|
861
|
+
lines.push("| Agent | Model | Temperature |");
|
|
862
|
+
lines.push("| --- | --- | --- |");
|
|
863
|
+
for (const [name, assignment] of agentEntries) {
|
|
864
|
+
const temp = assignment.temperature !== undefined ? String(assignment.temperature) : "\u2014";
|
|
865
|
+
lines.push(`| ${name} | ${assignment.model} | ${temp} |`);
|
|
866
|
+
}
|
|
867
|
+
lines.push("");
|
|
868
|
+
}
|
|
869
|
+
if (Object.keys(resolved.profiles).length > 0) {
|
|
870
|
+
lines.push("## Available Profiles");
|
|
871
|
+
lines.push("");
|
|
872
|
+
lines.push("| Profile | Description | Default Model |");
|
|
873
|
+
lines.push("| --- | --- | --- |");
|
|
874
|
+
for (const [name, profile] of Object.entries(resolved.profiles)) {
|
|
875
|
+
lines.push(`| ${name} | ${profile.description ?? "\u2014"} | ${profile.default ?? "\u2014"} |`);
|
|
876
|
+
}
|
|
877
|
+
lines.push("");
|
|
878
|
+
}
|
|
879
|
+
if (resolved.activeProfile) {
|
|
880
|
+
lines.push(`**Active profile**: \`${resolved.activeProfile}\``);
|
|
881
|
+
lines.push("");
|
|
882
|
+
}
|
|
883
|
+
return serializeFrontmatter(frontmatter, lines.join(`
|
|
884
|
+
`));
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
// src/utils/model-guidance.ts
|
|
888
|
+
function generateModelGuidanceMarkdown(resolved) {
|
|
889
|
+
if (!resolved.default && !resolved.small && Object.keys(resolved.agents).length === 0 && Object.keys(resolved.profiles).length === 0) {
|
|
890
|
+
return null;
|
|
891
|
+
}
|
|
892
|
+
const lines = [];
|
|
893
|
+
lines.push("# Model Configuration");
|
|
894
|
+
lines.push("");
|
|
895
|
+
lines.push("Use the following model preferences when working in this project.");
|
|
896
|
+
lines.push("");
|
|
897
|
+
if (resolved.default || resolved.small) {
|
|
898
|
+
lines.push("## Default Models");
|
|
899
|
+
lines.push("");
|
|
900
|
+
if (resolved.default) {
|
|
901
|
+
lines.push(`- **Primary model**: ${resolved.default}`);
|
|
902
|
+
}
|
|
903
|
+
if (resolved.small) {
|
|
904
|
+
lines.push(`- **Lightweight tasks** (titles, summaries): ${resolved.small}`);
|
|
905
|
+
}
|
|
906
|
+
lines.push("");
|
|
907
|
+
}
|
|
908
|
+
const agentEntries = Object.entries(resolved.agents);
|
|
909
|
+
if (agentEntries.length > 0) {
|
|
910
|
+
lines.push("## Agent Model Assignments");
|
|
911
|
+
lines.push("");
|
|
912
|
+
lines.push("| Agent | Model | Temperature |");
|
|
913
|
+
lines.push("| --- | --- | --- |");
|
|
914
|
+
for (const [name, assignment] of agentEntries) {
|
|
915
|
+
const temp = assignment.temperature !== undefined ? String(assignment.temperature) : "\u2014";
|
|
916
|
+
lines.push(`| ${name} | ${assignment.model} | ${temp} |`);
|
|
917
|
+
}
|
|
918
|
+
lines.push("");
|
|
919
|
+
}
|
|
920
|
+
if (Object.keys(resolved.profiles).length > 0) {
|
|
921
|
+
lines.push("## Available Profiles");
|
|
922
|
+
lines.push("");
|
|
923
|
+
lines.push("| Profile | Description | Default Model |");
|
|
924
|
+
lines.push("| --- | --- | --- |");
|
|
925
|
+
for (const [name, profile] of Object.entries(resolved.profiles)) {
|
|
926
|
+
lines.push(`| ${name} | ${profile.description ?? "\u2014"} | ${profile.default ?? "\u2014"} |`);
|
|
927
|
+
}
|
|
928
|
+
lines.push("");
|
|
929
|
+
}
|
|
930
|
+
if (resolved.activeProfile) {
|
|
931
|
+
lines.push(`**Active profile**: \`${resolved.activeProfile}\``);
|
|
932
|
+
lines.push("");
|
|
933
|
+
}
|
|
934
|
+
if (resolved.routing.length > 0) {
|
|
935
|
+
lines.push("## Task-Aware Routing");
|
|
936
|
+
lines.push("");
|
|
937
|
+
lines.push("Select the appropriate profile based on the task context:");
|
|
938
|
+
lines.push("");
|
|
939
|
+
lines.push("| Condition | Profile | Description |");
|
|
940
|
+
lines.push("| --- | --- | --- |");
|
|
941
|
+
for (const rule of resolved.routing) {
|
|
942
|
+
const conditions = Object.entries(rule.when).map(([k, v]) => `${k}=${v}`).join(", ");
|
|
943
|
+
const desc = rule.description ?? "\u2014";
|
|
944
|
+
lines.push(`| ${conditions} | ${rule.use} | ${desc} |`);
|
|
945
|
+
}
|
|
946
|
+
lines.push("");
|
|
947
|
+
lines.push("### Condition Reference");
|
|
948
|
+
lines.push("");
|
|
949
|
+
lines.push("- **complexity**: low | medium | high | critical");
|
|
950
|
+
lines.push("- **urgency**: low | normal | high");
|
|
951
|
+
lines.push("- **budget**: minimal | standard | premium");
|
|
952
|
+
lines.push("- **contextWindowNeed**: small | medium | large | max");
|
|
953
|
+
lines.push("- **toolUseIntensity**: none | light | heavy");
|
|
954
|
+
lines.push("");
|
|
955
|
+
}
|
|
956
|
+
return lines.join(`
|
|
957
|
+
`);
|
|
958
|
+
}
|
|
694
959
|
|
|
695
960
|
// src/targets/claude-code.ts
|
|
696
|
-
import { resolve as
|
|
961
|
+
import { resolve as resolve3, join as join6 } from "path";
|
|
697
962
|
var TARGET_ID3 = "claudecode";
|
|
698
963
|
|
|
699
964
|
class ClaudeCodeTarget extends BaseTarget {
|
|
@@ -706,18 +971,19 @@ class ClaudeCodeTarget extends BaseTarget {
|
|
|
706
971
|
"skills",
|
|
707
972
|
"hooks",
|
|
708
973
|
"mcp",
|
|
709
|
-
"ignore"
|
|
974
|
+
"ignore",
|
|
975
|
+
"models"
|
|
710
976
|
];
|
|
711
977
|
generate(options) {
|
|
712
978
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
713
|
-
const root =
|
|
979
|
+
const root = resolve3(projectRoot, baseDir);
|
|
714
980
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
715
981
|
const filesWritten = [];
|
|
716
982
|
const filesDeleted = [];
|
|
717
983
|
const warnings = [];
|
|
718
|
-
const claudeDir =
|
|
984
|
+
const claudeDir = resolve3(root, ".claude");
|
|
719
985
|
if (effective.includes("rules")) {
|
|
720
|
-
const rulesDir =
|
|
986
|
+
const rulesDir = resolve3(claudeDir, "rules");
|
|
721
987
|
if (deleteExisting) {
|
|
722
988
|
removeIfExists(rulesDir);
|
|
723
989
|
filesDeleted.push(rulesDir);
|
|
@@ -730,7 +996,7 @@ class ClaudeCodeTarget extends BaseTarget {
|
|
|
730
996
|
const claudeMd = rootRules.map((r) => r.content).join(`
|
|
731
997
|
|
|
732
998
|
`);
|
|
733
|
-
const filepath =
|
|
999
|
+
const filepath = resolve3(claudeDir, "CLAUDE.md");
|
|
734
1000
|
writeGeneratedFile(filepath, claudeMd);
|
|
735
1001
|
filesWritten.push(filepath);
|
|
736
1002
|
}
|
|
@@ -741,21 +1007,30 @@ class ClaudeCodeTarget extends BaseTarget {
|
|
|
741
1007
|
}
|
|
742
1008
|
}
|
|
743
1009
|
if (effective.includes("agents")) {
|
|
744
|
-
const agentsDir =
|
|
1010
|
+
const agentsDir = resolve3(claudeDir, "agents");
|
|
745
1011
|
if (deleteExisting) {
|
|
746
1012
|
removeIfExists(agentsDir);
|
|
747
1013
|
filesDeleted.push(agentsDir);
|
|
748
1014
|
}
|
|
749
1015
|
ensureDir(agentsDir);
|
|
1016
|
+
const resolvedModels = features.models ? resolveModels(features.models, options.modelProfile, TARGET_ID3) : null;
|
|
750
1017
|
const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID3));
|
|
751
1018
|
for (const agent of agents) {
|
|
752
1019
|
const filepath = join6(agentsDir, `${agent.name}.md`);
|
|
753
|
-
|
|
1020
|
+
const cc = agent.meta.claudecode ?? {};
|
|
1021
|
+
const modelsAgent = resolvedModels?.agents[agent.name];
|
|
1022
|
+
const agentModel = modelsAgent?.model ?? cc.model;
|
|
1023
|
+
let content = agent.content;
|
|
1024
|
+
if (agentModel) {
|
|
1025
|
+
content = `<!-- model: ${agentModel} -->
|
|
1026
|
+
${content}`;
|
|
1027
|
+
}
|
|
1028
|
+
writeGeneratedFile(filepath, content);
|
|
754
1029
|
filesWritten.push(filepath);
|
|
755
1030
|
}
|
|
756
1031
|
}
|
|
757
1032
|
if (effective.includes("skills")) {
|
|
758
|
-
const skillsDir =
|
|
1033
|
+
const skillsDir = resolve3(claudeDir, "skills");
|
|
759
1034
|
if (deleteExisting) {
|
|
760
1035
|
removeIfExists(skillsDir);
|
|
761
1036
|
filesDeleted.push(skillsDir);
|
|
@@ -771,7 +1046,7 @@ class ClaudeCodeTarget extends BaseTarget {
|
|
|
771
1046
|
}
|
|
772
1047
|
}
|
|
773
1048
|
if (effective.includes("commands")) {
|
|
774
|
-
const commandsDir =
|
|
1049
|
+
const commandsDir = resolve3(claudeDir, "commands");
|
|
775
1050
|
if (deleteExisting) {
|
|
776
1051
|
removeIfExists(commandsDir);
|
|
777
1052
|
filesDeleted.push(commandsDir);
|
|
@@ -784,10 +1059,21 @@ class ClaudeCodeTarget extends BaseTarget {
|
|
|
784
1059
|
filesWritten.push(filepath);
|
|
785
1060
|
}
|
|
786
1061
|
}
|
|
1062
|
+
if (effective.includes("models") && features.models) {
|
|
1063
|
+
const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID3);
|
|
1064
|
+
const guidance = generateModelGuidanceMarkdown(resolved);
|
|
1065
|
+
if (guidance) {
|
|
1066
|
+
const rulesDir = resolve3(claudeDir, "rules");
|
|
1067
|
+
ensureDir(rulesDir);
|
|
1068
|
+
const filepath = join6(rulesDir, "model-config.md");
|
|
1069
|
+
writeGeneratedFile(filepath, guidance);
|
|
1070
|
+
filesWritten.push(filepath);
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
787
1073
|
if (effective.includes("hooks") || effective.includes("mcp") || effective.includes("ignore")) {
|
|
788
1074
|
const settings = buildClaudeSettings(options, effective);
|
|
789
1075
|
if (Object.keys(settings).length > 0) {
|
|
790
|
-
const filepath =
|
|
1076
|
+
const filepath = resolve3(claudeDir, "settings.json");
|
|
791
1077
|
const existing = readJsonOrNull(filepath) ?? {};
|
|
792
1078
|
const merged = { ...existing, ...settings };
|
|
793
1079
|
writeGeneratedJson(filepath, merged, { header: false });
|
|
@@ -844,7 +1130,7 @@ function toPascalCase(str) {
|
|
|
844
1130
|
}
|
|
845
1131
|
|
|
846
1132
|
// src/targets/codex-cli.ts
|
|
847
|
-
import { resolve as
|
|
1133
|
+
import { resolve as resolve4, join as join7 } from "path";
|
|
848
1134
|
var TARGET_ID4 = "codexcli";
|
|
849
1135
|
|
|
850
1136
|
class CodexCliTarget extends BaseTarget {
|
|
@@ -853,14 +1139,14 @@ class CodexCliTarget extends BaseTarget {
|
|
|
853
1139
|
supportedFeatures = ["rules", "skills", "mcp", "hooks"];
|
|
854
1140
|
generate(options) {
|
|
855
1141
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
856
|
-
const root =
|
|
1142
|
+
const root = resolve4(projectRoot, baseDir);
|
|
857
1143
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
858
1144
|
const filesWritten = [];
|
|
859
1145
|
const filesDeleted = [];
|
|
860
1146
|
const warnings = [];
|
|
861
|
-
const codexDir =
|
|
1147
|
+
const codexDir = resolve4(root, ".codex");
|
|
862
1148
|
if (effective.includes("rules")) {
|
|
863
|
-
const memoriesDir =
|
|
1149
|
+
const memoriesDir = resolve4(codexDir, "memories");
|
|
864
1150
|
if (deleteExisting) {
|
|
865
1151
|
removeIfExists(memoriesDir);
|
|
866
1152
|
filesDeleted.push(memoriesDir);
|
|
@@ -874,7 +1160,7 @@ class CodexCliTarget extends BaseTarget {
|
|
|
874
1160
|
}
|
|
875
1161
|
}
|
|
876
1162
|
if (effective.includes("skills")) {
|
|
877
|
-
const skillsDir =
|
|
1163
|
+
const skillsDir = resolve4(codexDir, "skills");
|
|
878
1164
|
if (deleteExisting) {
|
|
879
1165
|
removeIfExists(skillsDir);
|
|
880
1166
|
filesDeleted.push(skillsDir);
|
|
@@ -894,7 +1180,7 @@ class CodexCliTarget extends BaseTarget {
|
|
|
894
1180
|
}
|
|
895
1181
|
|
|
896
1182
|
// src/targets/gemini-cli.ts
|
|
897
|
-
import { resolve as
|
|
1183
|
+
import { resolve as resolve5, join as join8 } from "path";
|
|
898
1184
|
var TARGET_ID5 = "geminicli";
|
|
899
1185
|
|
|
900
1186
|
class GeminiCliTarget extends BaseTarget {
|
|
@@ -910,12 +1196,12 @@ class GeminiCliTarget extends BaseTarget {
|
|
|
910
1196
|
];
|
|
911
1197
|
generate(options) {
|
|
912
1198
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
913
|
-
const root =
|
|
1199
|
+
const root = resolve5(projectRoot, baseDir);
|
|
914
1200
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
915
1201
|
const filesWritten = [];
|
|
916
1202
|
const filesDeleted = [];
|
|
917
1203
|
const warnings = [];
|
|
918
|
-
const geminiDir =
|
|
1204
|
+
const geminiDir = resolve5(root, ".gemini");
|
|
919
1205
|
if (effective.includes("rules")) {
|
|
920
1206
|
const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID5));
|
|
921
1207
|
const rootRules = getRootRules(rules);
|
|
@@ -924,12 +1210,12 @@ class GeminiCliTarget extends BaseTarget {
|
|
|
924
1210
|
const geminiMd = rootRules.map((r) => r.content).join(`
|
|
925
1211
|
|
|
926
1212
|
`);
|
|
927
|
-
const filepath =
|
|
1213
|
+
const filepath = resolve5(root, "GEMINI.md");
|
|
928
1214
|
writeGeneratedFile(filepath, geminiMd);
|
|
929
1215
|
filesWritten.push(filepath);
|
|
930
1216
|
}
|
|
931
1217
|
if (detailRules.length > 0) {
|
|
932
|
-
const memoriesDir =
|
|
1218
|
+
const memoriesDir = resolve5(geminiDir, "memories");
|
|
933
1219
|
if (deleteExisting) {
|
|
934
1220
|
removeIfExists(memoriesDir);
|
|
935
1221
|
filesDeleted.push(memoriesDir);
|
|
@@ -943,7 +1229,7 @@ class GeminiCliTarget extends BaseTarget {
|
|
|
943
1229
|
}
|
|
944
1230
|
}
|
|
945
1231
|
if (effective.includes("commands")) {
|
|
946
|
-
const commandsDir =
|
|
1232
|
+
const commandsDir = resolve5(geminiDir, "commands");
|
|
947
1233
|
if (deleteExisting) {
|
|
948
1234
|
removeIfExists(commandsDir);
|
|
949
1235
|
filesDeleted.push(commandsDir);
|
|
@@ -961,14 +1247,14 @@ class GeminiCliTarget extends BaseTarget {
|
|
|
961
1247
|
const mcpEntries = Object.entries(features.mcpServers);
|
|
962
1248
|
if (mcpEntries.length > 0) {
|
|
963
1249
|
const settings = buildGeminiSettings(features.mcpServers);
|
|
964
|
-
const filepath =
|
|
1250
|
+
const filepath = resolve5(geminiDir, "settings.json");
|
|
965
1251
|
writeGeneratedJson(filepath, settings, { header: false });
|
|
966
1252
|
filesWritten.push(filepath);
|
|
967
1253
|
}
|
|
968
1254
|
}
|
|
969
1255
|
if (effective.includes("ignore")) {
|
|
970
1256
|
if (features.ignorePatterns.length > 0) {
|
|
971
|
-
const filepath =
|
|
1257
|
+
const filepath = resolve5(root, ".geminiignore");
|
|
972
1258
|
const content = features.ignorePatterns.join(`
|
|
973
1259
|
`) + `
|
|
974
1260
|
`;
|
|
@@ -1007,7 +1293,7 @@ function buildGeminiSettings(servers) {
|
|
|
1007
1293
|
}
|
|
1008
1294
|
|
|
1009
1295
|
// src/targets/copilot.ts
|
|
1010
|
-
import { resolve as
|
|
1296
|
+
import { resolve as resolve6, join as join9 } from "path";
|
|
1011
1297
|
var TARGET_ID6 = "copilot";
|
|
1012
1298
|
|
|
1013
1299
|
class CopilotTarget extends BaseTarget {
|
|
@@ -1019,16 +1305,17 @@ class CopilotTarget extends BaseTarget {
|
|
|
1019
1305
|
"agents",
|
|
1020
1306
|
"skills",
|
|
1021
1307
|
"mcp",
|
|
1022
|
-
"ignore"
|
|
1308
|
+
"ignore",
|
|
1309
|
+
"models"
|
|
1023
1310
|
];
|
|
1024
1311
|
generate(options) {
|
|
1025
1312
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
1026
|
-
const root =
|
|
1313
|
+
const root = resolve6(projectRoot, baseDir);
|
|
1027
1314
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
1028
1315
|
const filesWritten = [];
|
|
1029
1316
|
const filesDeleted = [];
|
|
1030
1317
|
const warnings = [];
|
|
1031
|
-
const githubDir =
|
|
1318
|
+
const githubDir = resolve6(root, ".github");
|
|
1032
1319
|
if (effective.includes("rules")) {
|
|
1033
1320
|
const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID6));
|
|
1034
1321
|
if (rules.length > 0) {
|
|
@@ -1037,15 +1324,15 @@ class CopilotTarget extends BaseTarget {
|
|
|
1037
1324
|
---
|
|
1038
1325
|
|
|
1039
1326
|
`);
|
|
1040
|
-
const filepath =
|
|
1327
|
+
const filepath = resolve6(githubDir, "copilot-instructions.md");
|
|
1041
1328
|
ensureDir(githubDir);
|
|
1042
1329
|
writeGeneratedFile(filepath, combinedContent);
|
|
1043
1330
|
filesWritten.push(filepath);
|
|
1044
1331
|
}
|
|
1045
1332
|
}
|
|
1046
1333
|
if (effective.includes("agents")) {
|
|
1047
|
-
const copilotDir =
|
|
1048
|
-
const agentsDir =
|
|
1334
|
+
const copilotDir = resolve6(githubDir, "copilot");
|
|
1335
|
+
const agentsDir = resolve6(copilotDir, "agents");
|
|
1049
1336
|
if (deleteExisting) {
|
|
1050
1337
|
removeIfExists(agentsDir);
|
|
1051
1338
|
filesDeleted.push(agentsDir);
|
|
@@ -1059,8 +1346,8 @@ class CopilotTarget extends BaseTarget {
|
|
|
1059
1346
|
}
|
|
1060
1347
|
}
|
|
1061
1348
|
if (effective.includes("skills")) {
|
|
1062
|
-
const copilotDir =
|
|
1063
|
-
const skillsDir =
|
|
1349
|
+
const copilotDir = resolve6(githubDir, "copilot");
|
|
1350
|
+
const skillsDir = resolve6(copilotDir, "skills");
|
|
1064
1351
|
if (deleteExisting) {
|
|
1065
1352
|
removeIfExists(skillsDir);
|
|
1066
1353
|
filesDeleted.push(skillsDir);
|
|
@@ -1076,8 +1363,8 @@ class CopilotTarget extends BaseTarget {
|
|
|
1076
1363
|
}
|
|
1077
1364
|
}
|
|
1078
1365
|
if (effective.includes("commands")) {
|
|
1079
|
-
const copilotDir =
|
|
1080
|
-
const commandsDir =
|
|
1366
|
+
const copilotDir = resolve6(githubDir, "copilot");
|
|
1367
|
+
const commandsDir = resolve6(copilotDir, "commands");
|
|
1081
1368
|
if (deleteExisting) {
|
|
1082
1369
|
removeIfExists(commandsDir);
|
|
1083
1370
|
filesDeleted.push(commandsDir);
|
|
@@ -1091,19 +1378,30 @@ class CopilotTarget extends BaseTarget {
|
|
|
1091
1378
|
}
|
|
1092
1379
|
}
|
|
1093
1380
|
if (effective.includes("ignore")) {}
|
|
1381
|
+
if (effective.includes("models") && features.models) {
|
|
1382
|
+
const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID6);
|
|
1383
|
+
const guidance = generateModelGuidanceMarkdown(resolved);
|
|
1384
|
+
if (guidance) {
|
|
1385
|
+
const copilotDir = resolve6(githubDir, "copilot");
|
|
1386
|
+
ensureDir(copilotDir);
|
|
1387
|
+
const filepath = join9(copilotDir, "model-config.md");
|
|
1388
|
+
writeGeneratedFile(filepath, guidance);
|
|
1389
|
+
filesWritten.push(filepath);
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1094
1392
|
return this.createResult(filesWritten, filesDeleted, warnings);
|
|
1095
1393
|
}
|
|
1096
1394
|
}
|
|
1097
1395
|
|
|
1098
1396
|
// src/targets/agents-md.ts
|
|
1099
|
-
import { resolve as
|
|
1397
|
+
import { resolve as resolve7 } from "path";
|
|
1100
1398
|
class AgentsMdTarget extends BaseTarget {
|
|
1101
1399
|
id = "agentsmd";
|
|
1102
1400
|
name = "AGENTS.md";
|
|
1103
1401
|
supportedFeatures = ["rules"];
|
|
1104
1402
|
generate(options) {
|
|
1105
1403
|
const { projectRoot, baseDir, features } = options;
|
|
1106
|
-
const root =
|
|
1404
|
+
const root = resolve7(projectRoot, baseDir);
|
|
1107
1405
|
const filesWritten = [];
|
|
1108
1406
|
const warnings = [];
|
|
1109
1407
|
const rootRules = getRootRules(features.rules);
|
|
@@ -1115,7 +1413,7 @@ class AgentsMdTarget extends BaseTarget {
|
|
|
1115
1413
|
const content = sections.join(`
|
|
1116
1414
|
|
|
1117
1415
|
`);
|
|
1118
|
-
const filepath =
|
|
1416
|
+
const filepath = resolve7(root, "AGENTS.md");
|
|
1119
1417
|
writeGeneratedFile(filepath, content);
|
|
1120
1418
|
filesWritten.push(filepath);
|
|
1121
1419
|
return this.createResult(filesWritten, [], warnings);
|
|
@@ -1123,7 +1421,7 @@ class AgentsMdTarget extends BaseTarget {
|
|
|
1123
1421
|
}
|
|
1124
1422
|
|
|
1125
1423
|
// src/targets/generic-md-target.ts
|
|
1126
|
-
import { resolve as
|
|
1424
|
+
import { resolve as resolve8, join as join10 } from "path";
|
|
1127
1425
|
function createGenericMdTarget(config) {
|
|
1128
1426
|
return new GenericMdTarget(config);
|
|
1129
1427
|
}
|
|
@@ -1142,16 +1440,16 @@ class GenericMdTarget extends BaseTarget {
|
|
|
1142
1440
|
}
|
|
1143
1441
|
generate(options) {
|
|
1144
1442
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
1145
|
-
const root =
|
|
1443
|
+
const root = resolve8(projectRoot, baseDir);
|
|
1146
1444
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
1147
1445
|
const filesWritten = [];
|
|
1148
1446
|
const filesDeleted = [];
|
|
1149
1447
|
const warnings = [];
|
|
1150
|
-
const configDir =
|
|
1448
|
+
const configDir = resolve8(root, this.config.configDir);
|
|
1151
1449
|
const rulesSubDir = this.config.rulesDir ?? "rules";
|
|
1152
1450
|
const ext = this.config.ruleExtension ?? ".md";
|
|
1153
1451
|
if (effective.includes("rules")) {
|
|
1154
|
-
const rulesDir =
|
|
1452
|
+
const rulesDir = resolve8(configDir, rulesSubDir);
|
|
1155
1453
|
if (deleteExisting) {
|
|
1156
1454
|
removeIfExists(rulesDir);
|
|
1157
1455
|
filesDeleted.push(rulesDir);
|
|
@@ -1165,7 +1463,7 @@ class GenericMdTarget extends BaseTarget {
|
|
|
1165
1463
|
}
|
|
1166
1464
|
}
|
|
1167
1465
|
if (effective.includes("commands")) {
|
|
1168
|
-
const commandsDir =
|
|
1466
|
+
const commandsDir = resolve8(configDir, "commands");
|
|
1169
1467
|
if (deleteExisting) {
|
|
1170
1468
|
removeIfExists(commandsDir);
|
|
1171
1469
|
filesDeleted.push(commandsDir);
|
|
@@ -1182,7 +1480,7 @@ class GenericMdTarget extends BaseTarget {
|
|
|
1182
1480
|
const mcpEntries = Object.entries(features.mcpServers);
|
|
1183
1481
|
if (mcpEntries.length > 0) {
|
|
1184
1482
|
const mcpDir = this.config.mcpInConfigDir ? configDir : root;
|
|
1185
|
-
const filepath =
|
|
1483
|
+
const filepath = resolve8(mcpDir, "mcp.json");
|
|
1186
1484
|
writeGeneratedJson(filepath, { mcpServers: features.mcpServers }, {
|
|
1187
1485
|
header: false
|
|
1188
1486
|
});
|
|
@@ -1191,13 +1489,23 @@ class GenericMdTarget extends BaseTarget {
|
|
|
1191
1489
|
}
|
|
1192
1490
|
if (effective.includes("ignore") && this.config.ignoreFile) {
|
|
1193
1491
|
if (features.ignorePatterns.length > 0) {
|
|
1194
|
-
const filepath =
|
|
1492
|
+
const filepath = resolve8(root, this.config.ignoreFile);
|
|
1195
1493
|
writeGeneratedFile(filepath, features.ignorePatterns.join(`
|
|
1196
1494
|
`) + `
|
|
1197
1495
|
`);
|
|
1198
1496
|
filesWritten.push(filepath);
|
|
1199
1497
|
}
|
|
1200
1498
|
}
|
|
1499
|
+
if (effective.includes("models") && features.models) {
|
|
1500
|
+
const resolved = resolveModels(features.models, options.modelProfile, this.id);
|
|
1501
|
+
const guidance = generateModelGuidanceMarkdown(resolved);
|
|
1502
|
+
if (guidance) {
|
|
1503
|
+
ensureDir(configDir);
|
|
1504
|
+
const filepath = join10(configDir, "model-config.md");
|
|
1505
|
+
writeGeneratedFile(filepath, guidance);
|
|
1506
|
+
filesWritten.push(filepath);
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1201
1509
|
return this.createResult(filesWritten, filesDeleted, warnings);
|
|
1202
1510
|
}
|
|
1203
1511
|
}
|