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
|
@@ -1,51 +1,85 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
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 = /* @__PURE__ */ createRequire(import.meta.url);
|
|
31
3
|
|
|
32
4
|
// src/core/config.ts
|
|
33
|
-
var exports_config = {};
|
|
34
|
-
__export(exports_config, {
|
|
35
|
-
resolveTargets: () => resolveTargets,
|
|
36
|
-
resolveFeatures: () => resolveFeatures,
|
|
37
|
-
loadWorkspaceConfig: () => loadWorkspaceConfig,
|
|
38
|
-
loadPackManifest: () => loadPackManifest,
|
|
39
|
-
WorkspaceConfigSchema: () => WorkspaceConfigSchema,
|
|
40
|
-
TARGET_IDS: () => TARGET_IDS,
|
|
41
|
-
REPO_MODES: () => REPO_MODES,
|
|
42
|
-
PackManifestSchema: () => PackManifestSchema,
|
|
43
|
-
FEATURE_IDS: () => FEATURE_IDS
|
|
44
|
-
});
|
|
45
5
|
import { z } from "zod";
|
|
46
6
|
import { readFileSync, existsSync } from "fs";
|
|
47
7
|
import { resolve } from "path";
|
|
48
8
|
import { parse as parseJsonc } from "jsonc-parser";
|
|
9
|
+
var TARGET_IDS = [
|
|
10
|
+
"opencode",
|
|
11
|
+
"cursor",
|
|
12
|
+
"claudecode",
|
|
13
|
+
"codexcli",
|
|
14
|
+
"geminicli",
|
|
15
|
+
"copilot",
|
|
16
|
+
"agentsmd",
|
|
17
|
+
"cline",
|
|
18
|
+
"kilo",
|
|
19
|
+
"roo",
|
|
20
|
+
"qwencode",
|
|
21
|
+
"kiro",
|
|
22
|
+
"factorydroid",
|
|
23
|
+
"antigravity",
|
|
24
|
+
"junie",
|
|
25
|
+
"augmentcode",
|
|
26
|
+
"windsurf",
|
|
27
|
+
"warp",
|
|
28
|
+
"replit",
|
|
29
|
+
"zed"
|
|
30
|
+
];
|
|
31
|
+
var FEATURE_IDS = [
|
|
32
|
+
"rules",
|
|
33
|
+
"commands",
|
|
34
|
+
"agents",
|
|
35
|
+
"skills",
|
|
36
|
+
"hooks",
|
|
37
|
+
"plugins",
|
|
38
|
+
"mcp",
|
|
39
|
+
"ignore",
|
|
40
|
+
"models"
|
|
41
|
+
];
|
|
42
|
+
var REPO_MODES = ["repo", "monorepo", "metarepo"];
|
|
43
|
+
var PackManifestSchema = z.object({
|
|
44
|
+
name: z.string().min(1),
|
|
45
|
+
version: z.string().default("1.0.0"),
|
|
46
|
+
description: z.string().default(""),
|
|
47
|
+
author: z.union([
|
|
48
|
+
z.string(),
|
|
49
|
+
z.object({ name: z.string(), email: z.string().optional() })
|
|
50
|
+
]).optional(),
|
|
51
|
+
tags: z.array(z.string()).default([]),
|
|
52
|
+
dependencies: z.array(z.string()).default([]),
|
|
53
|
+
conflicts: z.array(z.string()).default([]),
|
|
54
|
+
targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
|
|
55
|
+
features: z.union([z.literal("*"), z.array(z.string())]).default("*")
|
|
56
|
+
});
|
|
57
|
+
var FeaturesSchema = z.union([
|
|
58
|
+
z.literal("*"),
|
|
59
|
+
z.array(z.string()),
|
|
60
|
+
z.record(z.string(), z.union([z.literal("*"), z.array(z.string())]))
|
|
61
|
+
]);
|
|
62
|
+
var WorkspaceConfigSchema = z.object({
|
|
63
|
+
$schema: z.string().optional(),
|
|
64
|
+
packs: z.array(z.string()).default(["./packs/default"]),
|
|
65
|
+
disabled: z.array(z.string()).default([]),
|
|
66
|
+
targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
|
|
67
|
+
features: FeaturesSchema.default("*"),
|
|
68
|
+
mode: z.enum(REPO_MODES).default("repo"),
|
|
69
|
+
baseDirs: z.array(z.string()).default(["."]),
|
|
70
|
+
global: z.boolean().default(false),
|
|
71
|
+
delete: z.boolean().default(true),
|
|
72
|
+
verbose: z.boolean().default(false),
|
|
73
|
+
silent: z.boolean().default(false),
|
|
74
|
+
overrides: z.record(z.string(), z.record(z.string(), z.string())).default({}),
|
|
75
|
+
sources: z.array(z.object({
|
|
76
|
+
source: z.string(),
|
|
77
|
+
packs: z.array(z.string()).optional(),
|
|
78
|
+
skills: z.array(z.string()).optional()
|
|
79
|
+
})).default([]),
|
|
80
|
+
modelProfile: z.string().optional()
|
|
81
|
+
});
|
|
82
|
+
var CONFIG_FILES = ["agentpacks.local.jsonc", "agentpacks.jsonc"];
|
|
49
83
|
function loadWorkspaceConfig(projectRoot) {
|
|
50
84
|
for (const filename of CONFIG_FILES) {
|
|
51
85
|
const filepath = resolve(projectRoot, filename);
|
|
@@ -91,81 +125,6 @@ function resolveTargets(config) {
|
|
|
91
125
|
return [...TARGET_IDS];
|
|
92
126
|
return config.targets;
|
|
93
127
|
}
|
|
94
|
-
var TARGET_IDS, FEATURE_IDS, REPO_MODES, PackManifestSchema, FeaturesSchema, WorkspaceConfigSchema, CONFIG_FILES;
|
|
95
|
-
var init_config = __esm(() => {
|
|
96
|
-
TARGET_IDS = [
|
|
97
|
-
"opencode",
|
|
98
|
-
"cursor",
|
|
99
|
-
"claudecode",
|
|
100
|
-
"codexcli",
|
|
101
|
-
"geminicli",
|
|
102
|
-
"copilot",
|
|
103
|
-
"agentsmd",
|
|
104
|
-
"cline",
|
|
105
|
-
"kilo",
|
|
106
|
-
"roo",
|
|
107
|
-
"qwencode",
|
|
108
|
-
"kiro",
|
|
109
|
-
"factorydroid",
|
|
110
|
-
"antigravity",
|
|
111
|
-
"junie",
|
|
112
|
-
"augmentcode",
|
|
113
|
-
"windsurf",
|
|
114
|
-
"warp",
|
|
115
|
-
"replit",
|
|
116
|
-
"zed"
|
|
117
|
-
];
|
|
118
|
-
FEATURE_IDS = [
|
|
119
|
-
"rules",
|
|
120
|
-
"commands",
|
|
121
|
-
"agents",
|
|
122
|
-
"skills",
|
|
123
|
-
"hooks",
|
|
124
|
-
"plugins",
|
|
125
|
-
"mcp",
|
|
126
|
-
"ignore"
|
|
127
|
-
];
|
|
128
|
-
REPO_MODES = ["repo", "monorepo", "metarepo"];
|
|
129
|
-
PackManifestSchema = z.object({
|
|
130
|
-
name: z.string().min(1),
|
|
131
|
-
version: z.string().default("1.0.0"),
|
|
132
|
-
description: z.string().default(""),
|
|
133
|
-
author: z.union([
|
|
134
|
-
z.string(),
|
|
135
|
-
z.object({ name: z.string(), email: z.string().optional() })
|
|
136
|
-
]).optional(),
|
|
137
|
-
tags: z.array(z.string()).default([]),
|
|
138
|
-
dependencies: z.array(z.string()).default([]),
|
|
139
|
-
conflicts: z.array(z.string()).default([]),
|
|
140
|
-
targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
|
|
141
|
-
features: z.union([z.literal("*"), z.array(z.string())]).default("*")
|
|
142
|
-
});
|
|
143
|
-
FeaturesSchema = z.union([
|
|
144
|
-
z.literal("*"),
|
|
145
|
-
z.array(z.string()),
|
|
146
|
-
z.record(z.string(), z.union([z.literal("*"), z.array(z.string())]))
|
|
147
|
-
]);
|
|
148
|
-
WorkspaceConfigSchema = z.object({
|
|
149
|
-
$schema: z.string().optional(),
|
|
150
|
-
packs: z.array(z.string()).default(["./packs/default"]),
|
|
151
|
-
disabled: z.array(z.string()).default([]),
|
|
152
|
-
targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
|
|
153
|
-
features: FeaturesSchema.default("*"),
|
|
154
|
-
mode: z.enum(REPO_MODES).default("repo"),
|
|
155
|
-
baseDirs: z.array(z.string()).default(["."]),
|
|
156
|
-
global: z.boolean().default(false),
|
|
157
|
-
delete: z.boolean().default(true),
|
|
158
|
-
verbose: z.boolean().default(false),
|
|
159
|
-
silent: z.boolean().default(false),
|
|
160
|
-
overrides: z.record(z.string(), z.record(z.string(), z.string())).default({}),
|
|
161
|
-
sources: z.array(z.object({
|
|
162
|
-
source: z.string(),
|
|
163
|
-
packs: z.array(z.string()).optional(),
|
|
164
|
-
skills: z.array(z.string()).optional()
|
|
165
|
-
})).default([])
|
|
166
|
-
});
|
|
167
|
-
CONFIG_FILES = ["agentpacks.local.jsonc", "agentpacks.jsonc"];
|
|
168
|
-
});
|
|
169
128
|
|
|
170
129
|
// src/utils/filesystem.ts
|
|
171
130
|
import {
|
|
@@ -174,10 +133,10 @@ import {
|
|
|
174
133
|
readFileSync as readFileSync2,
|
|
175
134
|
writeFileSync,
|
|
176
135
|
readdirSync,
|
|
136
|
+
rmSync,
|
|
177
137
|
statSync
|
|
178
138
|
} from "fs";
|
|
179
139
|
import { dirname, relative, join } from "path";
|
|
180
|
-
import { removeSync } from "fs-extra";
|
|
181
140
|
var GENERATED_HEADER_MD = "<!-- Generated by agentpacks. DO NOT EDIT. -->";
|
|
182
141
|
var GENERATED_HEADER_JSON = "// Generated by agentpacks. DO NOT EDIT.";
|
|
183
142
|
var GENERATED_HEADER_JS = "// Generated by agentpacks. DO NOT EDIT.";
|
|
@@ -218,7 +177,7 @@ function ensureDir(dirPath) {
|
|
|
218
177
|
}
|
|
219
178
|
function removeIfExists(targetPath) {
|
|
220
179
|
if (existsSync2(targetPath)) {
|
|
221
|
-
|
|
180
|
+
rmSync(targetPath, { recursive: true, force: true });
|
|
222
181
|
}
|
|
223
182
|
}
|
|
224
183
|
function listFiles(dirPath, options = {}) {
|
|
@@ -544,10 +503,178 @@ function mergeIgnorePatterns(configs) {
|
|
|
544
503
|
return result;
|
|
545
504
|
}
|
|
546
505
|
|
|
506
|
+
// src/features/models.ts
|
|
507
|
+
import { join as join7 } from "path";
|
|
508
|
+
import { z as z2 } from "zod";
|
|
509
|
+
var SECRET_PATTERNS = [
|
|
510
|
+
/["']api[_-]?key["']\s*:/i,
|
|
511
|
+
/["']apiKey["']\s*:/i,
|
|
512
|
+
/["']secret["']\s*:/i,
|
|
513
|
+
/["']password["']\s*:/i,
|
|
514
|
+
/["'](?:auth_token|access_token|bearer_token)["']\s*:/i,
|
|
515
|
+
/["']private[_-]?key["']\s*:/i,
|
|
516
|
+
/-----BEGIN\s+(RSA|EC|DSA|OPENSSH|PGP)\s+PRIVATE\s+KEY-----/,
|
|
517
|
+
/sk-[a-zA-Z0-9]{20,}/,
|
|
518
|
+
/Bearer\s+[a-zA-Z0-9._-]{20,}/
|
|
519
|
+
];
|
|
520
|
+
var AgentModelSchema = z2.object({
|
|
521
|
+
model: z2.string(),
|
|
522
|
+
temperature: z2.number().min(0).max(2).optional(),
|
|
523
|
+
top_p: z2.number().min(0).max(1).optional()
|
|
524
|
+
});
|
|
525
|
+
var ModelProfileSchema = z2.object({
|
|
526
|
+
extends: z2.string().optional(),
|
|
527
|
+
description: z2.string().optional(),
|
|
528
|
+
default: z2.string().optional(),
|
|
529
|
+
small: z2.string().optional(),
|
|
530
|
+
agents: z2.record(z2.string(), AgentModelSchema).optional()
|
|
531
|
+
});
|
|
532
|
+
var RoutingConditionSchema = z2.object({
|
|
533
|
+
complexity: z2.enum(["low", "medium", "high", "critical"]).optional().describe("Task complexity level"),
|
|
534
|
+
urgency: z2.enum(["low", "normal", "high"]).optional().describe("Time sensitivity"),
|
|
535
|
+
budget: z2.enum(["minimal", "standard", "premium"]).optional().describe("Cost/token budget tier"),
|
|
536
|
+
contextWindowNeed: z2.enum(["small", "medium", "large", "max"]).optional().describe("Required context window size"),
|
|
537
|
+
toolUseIntensity: z2.enum(["none", "light", "heavy"]).optional().describe("Expected tool/function calling intensity")
|
|
538
|
+
});
|
|
539
|
+
var RoutingRuleSchema = z2.object({
|
|
540
|
+
when: z2.record(z2.string(), z2.string()),
|
|
541
|
+
use: z2.string(),
|
|
542
|
+
description: z2.string().optional(),
|
|
543
|
+
priority: z2.number().optional()
|
|
544
|
+
});
|
|
545
|
+
var ProviderModelSchema = z2.object({
|
|
546
|
+
options: z2.record(z2.string(), z2.unknown()).optional(),
|
|
547
|
+
variants: z2.record(z2.string(), z2.record(z2.string(), z2.unknown())).optional()
|
|
548
|
+
});
|
|
549
|
+
var ProviderConfigSchema = z2.object({
|
|
550
|
+
options: z2.record(z2.string(), z2.unknown()).optional(),
|
|
551
|
+
models: z2.record(z2.string(), ProviderModelSchema).optional()
|
|
552
|
+
});
|
|
553
|
+
var ModelsSchema = z2.object({
|
|
554
|
+
default: z2.string().optional(),
|
|
555
|
+
small: z2.string().optional(),
|
|
556
|
+
agents: z2.record(z2.string(), AgentModelSchema).optional(),
|
|
557
|
+
profiles: z2.record(z2.string(), ModelProfileSchema).optional(),
|
|
558
|
+
providers: z2.record(z2.string(), ProviderConfigSchema).optional(),
|
|
559
|
+
routing: z2.array(RoutingRuleSchema).optional(),
|
|
560
|
+
overrides: z2.record(z2.string(), z2.object({
|
|
561
|
+
default: z2.string().optional(),
|
|
562
|
+
small: z2.string().optional(),
|
|
563
|
+
agents: z2.record(z2.string(), AgentModelSchema).optional()
|
|
564
|
+
})).optional()
|
|
565
|
+
});
|
|
566
|
+
function parseModels(packDir, packName) {
|
|
567
|
+
const modelsPath = join7(packDir, "models.json");
|
|
568
|
+
const raw = readJsonOrNull(modelsPath);
|
|
569
|
+
if (!raw)
|
|
570
|
+
return null;
|
|
571
|
+
const parsed = ModelsSchema.parse(raw);
|
|
572
|
+
return {
|
|
573
|
+
packName,
|
|
574
|
+
sourcePath: modelsPath,
|
|
575
|
+
config: parsed
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
function mergeModelsConfigs(configs) {
|
|
579
|
+
const warnings = [];
|
|
580
|
+
const result = {};
|
|
581
|
+
for (const entry of configs) {
|
|
582
|
+
const { config, packName } = entry;
|
|
583
|
+
if (config.default !== undefined && result.default === undefined) {
|
|
584
|
+
result.default = config.default;
|
|
585
|
+
} else if (config.default !== undefined && result.default !== undefined) {
|
|
586
|
+
warnings.push(`Models "default" from pack "${packName}" skipped (already defined).`);
|
|
587
|
+
}
|
|
588
|
+
if (config.small !== undefined && result.small === undefined) {
|
|
589
|
+
result.small = config.small;
|
|
590
|
+
} else if (config.small !== undefined && result.small !== undefined) {
|
|
591
|
+
warnings.push(`Models "small" from pack "${packName}" skipped (already defined).`);
|
|
592
|
+
}
|
|
593
|
+
if (config.agents) {
|
|
594
|
+
if (!result.agents)
|
|
595
|
+
result.agents = {};
|
|
596
|
+
for (const [name, assignment] of Object.entries(config.agents)) {
|
|
597
|
+
if (name in result.agents) {
|
|
598
|
+
warnings.push(`Models agent "${name}" from pack "${packName}" skipped (already defined).`);
|
|
599
|
+
continue;
|
|
600
|
+
}
|
|
601
|
+
result.agents[name] = assignment;
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
if (config.profiles) {
|
|
605
|
+
if (!result.profiles)
|
|
606
|
+
result.profiles = {};
|
|
607
|
+
for (const [name, profile] of Object.entries(config.profiles)) {
|
|
608
|
+
if (name in result.profiles) {
|
|
609
|
+
warnings.push(`Models profile "${name}" from pack "${packName}" skipped (already defined).`);
|
|
610
|
+
continue;
|
|
611
|
+
}
|
|
612
|
+
result.profiles[name] = profile;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
if (config.providers) {
|
|
616
|
+
if (!result.providers)
|
|
617
|
+
result.providers = {};
|
|
618
|
+
for (const [providerName, providerConfig] of Object.entries(config.providers)) {
|
|
619
|
+
if (!(providerName in result.providers)) {
|
|
620
|
+
result.providers[providerName] = providerConfig;
|
|
621
|
+
} else {
|
|
622
|
+
const existing = result.providers[providerName];
|
|
623
|
+
if (!existing) {
|
|
624
|
+
result.providers[providerName] = providerConfig;
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
if (providerConfig.options) {
|
|
628
|
+
existing.options = {
|
|
629
|
+
...providerConfig.options,
|
|
630
|
+
...existing.options
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
if (providerConfig.models) {
|
|
634
|
+
if (!existing.models)
|
|
635
|
+
existing.models = {};
|
|
636
|
+
for (const [modelName, modelConfig] of Object.entries(providerConfig.models)) {
|
|
637
|
+
if (!(modelName in existing.models)) {
|
|
638
|
+
existing.models[modelName] = modelConfig;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
if (config.routing) {
|
|
646
|
+
if (!result.routing)
|
|
647
|
+
result.routing = [];
|
|
648
|
+
result.routing.push(...config.routing);
|
|
649
|
+
}
|
|
650
|
+
if (config.overrides) {
|
|
651
|
+
if (!result.overrides)
|
|
652
|
+
result.overrides = {};
|
|
653
|
+
for (const [targetId, override] of Object.entries(config.overrides)) {
|
|
654
|
+
if (targetId in result.overrides) {
|
|
655
|
+
warnings.push(`Models override for target "${targetId}" from pack "${packName}" skipped (already defined).`);
|
|
656
|
+
continue;
|
|
657
|
+
}
|
|
658
|
+
result.overrides[targetId] = override;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
return { config: result, warnings };
|
|
663
|
+
}
|
|
664
|
+
function scanModelsForSecrets(config) {
|
|
665
|
+
const warnings = [];
|
|
666
|
+
const json = JSON.stringify(config);
|
|
667
|
+
for (const pattern of SECRET_PATTERNS) {
|
|
668
|
+
if (pattern.test(json)) {
|
|
669
|
+
warnings.push(`Potential secret detected in models.json matching pattern: ${pattern.source}`);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
return warnings;
|
|
673
|
+
}
|
|
674
|
+
|
|
547
675
|
// src/core/pack-loader.ts
|
|
548
|
-
init_config();
|
|
549
676
|
import { existsSync as existsSync6 } from "fs";
|
|
550
|
-
import { resolve as
|
|
677
|
+
import { resolve as resolve2, isAbsolute } from "path";
|
|
551
678
|
class PackLoader {
|
|
552
679
|
projectRoot;
|
|
553
680
|
config;
|
|
@@ -580,10 +707,10 @@ class PackLoader {
|
|
|
580
707
|
}
|
|
581
708
|
loadPack(packDir, manifest) {
|
|
582
709
|
const name = manifest.name;
|
|
583
|
-
const rulesDir =
|
|
584
|
-
const commandsDir =
|
|
585
|
-
const agentsDir =
|
|
586
|
-
const skillsDir =
|
|
710
|
+
const rulesDir = resolve2(packDir, "rules");
|
|
711
|
+
const commandsDir = resolve2(packDir, "commands");
|
|
712
|
+
const agentsDir = resolve2(packDir, "agents");
|
|
713
|
+
const skillsDir = resolve2(packDir, "skills");
|
|
587
714
|
return {
|
|
588
715
|
manifest,
|
|
589
716
|
directory: packDir,
|
|
@@ -594,23 +721,25 @@ class PackLoader {
|
|
|
594
721
|
hooks: parseHooks(packDir, name),
|
|
595
722
|
plugins: parsePlugins(packDir, name),
|
|
596
723
|
mcp: parseMcp(packDir, name),
|
|
597
|
-
ignore: parseIgnore(packDir, name)
|
|
724
|
+
ignore: parseIgnore(packDir, name),
|
|
725
|
+
models: parseModels(packDir, name)
|
|
598
726
|
};
|
|
599
727
|
}
|
|
600
728
|
loadForBaseDir(baseDir) {
|
|
601
|
-
const baseDirRoot =
|
|
602
|
-
const localConfigPath =
|
|
729
|
+
const baseDirRoot = resolve2(this.projectRoot, baseDir);
|
|
730
|
+
const localConfigPath = resolve2(baseDirRoot, "agentpacks.jsonc");
|
|
603
731
|
if (!existsSync6(localConfigPath)) {
|
|
604
732
|
return { packs: [], warnings: [] };
|
|
605
733
|
}
|
|
606
|
-
const
|
|
607
|
-
const localConfig = loadWorkspaceConfig2(baseDirRoot);
|
|
734
|
+
const localConfig = loadWorkspaceConfig(baseDirRoot);
|
|
608
735
|
const loader = new PackLoader(baseDirRoot, localConfig);
|
|
609
736
|
return loader.loadAll();
|
|
610
737
|
}
|
|
611
738
|
resolveCuratedPack(packRef) {
|
|
612
|
-
const curatedDir =
|
|
739
|
+
const curatedDir = resolve2(this.projectRoot, ".agentpacks", ".curated");
|
|
613
740
|
let packName = packRef;
|
|
741
|
+
if (packName.startsWith("registry:"))
|
|
742
|
+
packName = packName.slice(9);
|
|
614
743
|
if (packName.startsWith("npm:"))
|
|
615
744
|
packName = packName.slice(4);
|
|
616
745
|
if (packName.startsWith("github:"))
|
|
@@ -621,24 +750,28 @@ class PackLoader {
|
|
|
621
750
|
const parts = packName.split("/");
|
|
622
751
|
packName = packName.includes("@") ? parts.join("-") : parts[parts.length - 1] ?? packName;
|
|
623
752
|
}
|
|
624
|
-
|
|
625
|
-
|
|
753
|
+
const withoutVersion = packName.split("@")[0] ?? packName;
|
|
754
|
+
packName = withoutVersion.split(":")[0] ?? withoutVersion;
|
|
755
|
+
const resolved = resolve2(curatedDir, packName);
|
|
626
756
|
return existsSync6(resolved) ? resolved : null;
|
|
627
757
|
}
|
|
628
758
|
resolvePackPath(packRef) {
|
|
629
759
|
if (packRef.startsWith("./") || packRef.startsWith("../")) {
|
|
630
|
-
return
|
|
760
|
+
return resolve2(this.projectRoot, packRef);
|
|
631
761
|
}
|
|
632
762
|
if (isAbsolute(packRef)) {
|
|
633
763
|
return packRef;
|
|
634
764
|
}
|
|
765
|
+
if (packRef.startsWith("registry:")) {
|
|
766
|
+
return this.resolveCuratedPack(packRef);
|
|
767
|
+
}
|
|
635
768
|
if (packRef.startsWith("@") || packRef.startsWith("npm:") || !packRef.includes("/")) {
|
|
636
769
|
return this.resolveCuratedPack(packRef);
|
|
637
770
|
}
|
|
638
771
|
if (packRef.startsWith("github:") || packRef.includes("/")) {
|
|
639
772
|
return this.resolveCuratedPack(packRef);
|
|
640
773
|
}
|
|
641
|
-
return
|
|
774
|
+
return resolve2(this.projectRoot, packRef);
|
|
642
775
|
}
|
|
643
776
|
}
|
|
644
777
|
|
|
@@ -659,7 +792,8 @@ class FeatureMerger {
|
|
|
659
792
|
hooks: this.mergeHooks(),
|
|
660
793
|
plugins: this.mergePlugins(),
|
|
661
794
|
mcpServers: this.mergeMcp(),
|
|
662
|
-
ignorePatterns: this.mergeIgnore()
|
|
795
|
+
ignorePatterns: this.mergeIgnore(),
|
|
796
|
+
models: this.mergeModels()
|
|
663
797
|
};
|
|
664
798
|
return { features, warnings: this.warnings };
|
|
665
799
|
}
|
|
@@ -746,6 +880,118 @@ class FeatureMerger {
|
|
|
746
880
|
}
|
|
747
881
|
return result;
|
|
748
882
|
}
|
|
883
|
+
mergeModels() {
|
|
884
|
+
const configs = this.packs.map((p) => p.models).filter((m) => m != null);
|
|
885
|
+
if (configs.length === 0)
|
|
886
|
+
return null;
|
|
887
|
+
const { config, warnings } = mergeModelsConfigs(configs);
|
|
888
|
+
this.warnings.push(...warnings);
|
|
889
|
+
return config;
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
// src/core/profile-resolver.ts
|
|
894
|
+
function resolveModels(merged, modelProfile, targetId) {
|
|
895
|
+
let defaultModel = merged.default;
|
|
896
|
+
let smallModel = merged.small;
|
|
897
|
+
let agents = { ...merged.agents };
|
|
898
|
+
if (modelProfile && merged.profiles?.[modelProfile]) {
|
|
899
|
+
const resolvedProfile = resolveProfileInheritance(modelProfile, merged.profiles);
|
|
900
|
+
if (resolvedProfile.default)
|
|
901
|
+
defaultModel = resolvedProfile.default;
|
|
902
|
+
if (resolvedProfile.small)
|
|
903
|
+
smallModel = resolvedProfile.small;
|
|
904
|
+
if (resolvedProfile.agents) {
|
|
905
|
+
agents = { ...agents, ...resolvedProfile.agents };
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
if (targetId) {
|
|
909
|
+
const targetOverride = merged.overrides?.[targetId];
|
|
910
|
+
if (targetOverride) {
|
|
911
|
+
if (targetOverride.default)
|
|
912
|
+
defaultModel = targetOverride.default;
|
|
913
|
+
if (targetOverride.small)
|
|
914
|
+
smallModel = targetOverride.small;
|
|
915
|
+
if (targetOverride.agents) {
|
|
916
|
+
agents = { ...agents, ...targetOverride.agents };
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
const providers = {};
|
|
921
|
+
if (merged.providers) {
|
|
922
|
+
for (const [name, config] of Object.entries(merged.providers)) {
|
|
923
|
+
providers[name] = {
|
|
924
|
+
...config.options ? { options: config.options } : {},
|
|
925
|
+
...config.models ? { models: config.models } : {}
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
const profileNames = Object.keys(merged.profiles ?? {});
|
|
930
|
+
const profiles = {};
|
|
931
|
+
if (merged.profiles) {
|
|
932
|
+
for (const [name, profile] of Object.entries(merged.profiles)) {
|
|
933
|
+
profiles[name] = {
|
|
934
|
+
description: profile.description,
|
|
935
|
+
default: profile.default,
|
|
936
|
+
small: profile.small
|
|
937
|
+
};
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
return {
|
|
941
|
+
default: defaultModel,
|
|
942
|
+
small: smallModel,
|
|
943
|
+
agents,
|
|
944
|
+
providers,
|
|
945
|
+
routing: merged.routing ?? [],
|
|
946
|
+
profileNames,
|
|
947
|
+
activeProfile: modelProfile,
|
|
948
|
+
profiles
|
|
949
|
+
};
|
|
950
|
+
}
|
|
951
|
+
function resolveAgentModel(resolved, agentName, frontmatterModel) {
|
|
952
|
+
const fromModels = resolved.agents[agentName];
|
|
953
|
+
if (fromModels) {
|
|
954
|
+
return {
|
|
955
|
+
model: fromModels.model,
|
|
956
|
+
temperature: fromModels.temperature,
|
|
957
|
+
top_p: fromModels.top_p
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
if (frontmatterModel) {
|
|
961
|
+
return { model: frontmatterModel };
|
|
962
|
+
}
|
|
963
|
+
return {};
|
|
964
|
+
}
|
|
965
|
+
function resolveProfileInheritance(profileName, profiles) {
|
|
966
|
+
const visited = new Set;
|
|
967
|
+
return resolveProfileChain(profileName, profiles, visited, 0);
|
|
968
|
+
}
|
|
969
|
+
var MAX_INHERITANCE_DEPTH = 10;
|
|
970
|
+
function resolveProfileChain(name, profiles, visited, depth) {
|
|
971
|
+
if (depth > MAX_INHERITANCE_DEPTH) {
|
|
972
|
+
throw new Error(`Profile inheritance too deep (max ${MAX_INHERITANCE_DEPTH}): ${name}`);
|
|
973
|
+
}
|
|
974
|
+
if (visited.has(name)) {
|
|
975
|
+
throw new Error(`Circular profile inheritance detected: ${[...visited, name].join(" → ")}`);
|
|
976
|
+
}
|
|
977
|
+
const profile = profiles[name];
|
|
978
|
+
if (!profile) {
|
|
979
|
+
throw new Error(`Profile "${name}" not found`);
|
|
980
|
+
}
|
|
981
|
+
visited.add(name);
|
|
982
|
+
if (!profile.extends) {
|
|
983
|
+
return { ...profile };
|
|
984
|
+
}
|
|
985
|
+
const parent = resolveProfileChain(profile.extends, profiles, visited, depth + 1);
|
|
986
|
+
return {
|
|
987
|
+
description: profile.description ?? parent.description,
|
|
988
|
+
default: profile.default ?? parent.default,
|
|
989
|
+
small: profile.small ?? parent.small,
|
|
990
|
+
agents: {
|
|
991
|
+
...parent.agents,
|
|
992
|
+
...profile.agents
|
|
993
|
+
}
|
|
994
|
+
};
|
|
749
995
|
}
|
|
750
996
|
|
|
751
997
|
// src/targets/base-target.ts
|
|
@@ -792,7 +1038,7 @@ ${content}`;
|
|
|
792
1038
|
}
|
|
793
1039
|
|
|
794
1040
|
// src/targets/opencode.ts
|
|
795
|
-
import { resolve as
|
|
1041
|
+
import { resolve as resolve3, join as join8 } from "path";
|
|
796
1042
|
var TARGET_ID = "opencode";
|
|
797
1043
|
|
|
798
1044
|
class OpenCodeTarget extends BaseTarget {
|
|
@@ -806,32 +1052,48 @@ class OpenCodeTarget extends BaseTarget {
|
|
|
806
1052
|
"hooks",
|
|
807
1053
|
"plugins",
|
|
808
1054
|
"mcp",
|
|
809
|
-
"ignore"
|
|
1055
|
+
"ignore",
|
|
1056
|
+
"models"
|
|
810
1057
|
];
|
|
811
1058
|
generate(options) {
|
|
812
1059
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
813
|
-
const root =
|
|
1060
|
+
const root = resolve3(projectRoot, baseDir);
|
|
814
1061
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
815
1062
|
const filesWritten = [];
|
|
816
1063
|
const filesDeleted = [];
|
|
817
1064
|
const warnings = [];
|
|
818
|
-
const opencodeDir =
|
|
1065
|
+
const opencodeDir = resolve3(root, ".opencode");
|
|
819
1066
|
if (effective.includes("agents")) {
|
|
820
|
-
const agentDir =
|
|
1067
|
+
const agentDir = resolve3(opencodeDir, "agent");
|
|
821
1068
|
if (deleteExisting) {
|
|
822
1069
|
removeIfExists(agentDir);
|
|
823
1070
|
filesDeleted.push(agentDir);
|
|
824
1071
|
}
|
|
825
1072
|
ensureDir(agentDir);
|
|
1073
|
+
const resolvedModels = features.models ? resolveModels(features.models, options.modelProfile, TARGET_ID) : null;
|
|
826
1074
|
const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID));
|
|
827
1075
|
for (const agent of agents) {
|
|
828
|
-
const filepath =
|
|
829
|
-
|
|
1076
|
+
const filepath = join8(agentDir, `${agent.name}.md`);
|
|
1077
|
+
const fm = {};
|
|
1078
|
+
const oc = agent.meta.opencode ?? {};
|
|
1079
|
+
const modelsAgent = resolvedModels?.agents[agent.name];
|
|
1080
|
+
const agentModel = modelsAgent?.model ?? oc.model;
|
|
1081
|
+
const agentTemp = modelsAgent?.temperature ?? oc.temperature;
|
|
1082
|
+
if (agentModel)
|
|
1083
|
+
fm.model = agentModel;
|
|
1084
|
+
if (agentTemp !== undefined)
|
|
1085
|
+
fm.temperature = agentTemp;
|
|
1086
|
+
if (oc.mode)
|
|
1087
|
+
fm.mode = oc.mode;
|
|
1088
|
+
if (oc.top_p !== undefined)
|
|
1089
|
+
fm.top_p = oc.top_p;
|
|
1090
|
+
const content = Object.keys(fm).length > 0 ? serializeFrontmatter(fm, agent.content) : agent.content;
|
|
1091
|
+
writeGeneratedFile(filepath, content);
|
|
830
1092
|
filesWritten.push(filepath);
|
|
831
1093
|
}
|
|
832
1094
|
}
|
|
833
1095
|
if (effective.includes("skills")) {
|
|
834
|
-
const skillDir =
|
|
1096
|
+
const skillDir = resolve3(opencodeDir, "skill");
|
|
835
1097
|
if (deleteExisting) {
|
|
836
1098
|
removeIfExists(skillDir);
|
|
837
1099
|
filesDeleted.push(skillDir);
|
|
@@ -839,15 +1101,15 @@ class OpenCodeTarget extends BaseTarget {
|
|
|
839
1101
|
ensureDir(skillDir);
|
|
840
1102
|
const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID));
|
|
841
1103
|
for (const skill of skills) {
|
|
842
|
-
const skillSubDir =
|
|
1104
|
+
const skillSubDir = join8(skillDir, skill.name);
|
|
843
1105
|
ensureDir(skillSubDir);
|
|
844
|
-
const filepath =
|
|
1106
|
+
const filepath = join8(skillSubDir, "SKILL.md");
|
|
845
1107
|
writeGeneratedFile(filepath, skill.content);
|
|
846
1108
|
filesWritten.push(filepath);
|
|
847
1109
|
}
|
|
848
1110
|
}
|
|
849
1111
|
if (effective.includes("commands")) {
|
|
850
|
-
const cmdDir =
|
|
1112
|
+
const cmdDir = resolve3(opencodeDir, "command");
|
|
851
1113
|
if (deleteExisting) {
|
|
852
1114
|
removeIfExists(cmdDir);
|
|
853
1115
|
filesDeleted.push(cmdDir);
|
|
@@ -855,19 +1117,19 @@ class OpenCodeTarget extends BaseTarget {
|
|
|
855
1117
|
ensureDir(cmdDir);
|
|
856
1118
|
const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID));
|
|
857
1119
|
for (const cmd of commands) {
|
|
858
|
-
const filepath =
|
|
1120
|
+
const filepath = join8(cmdDir, `${cmd.name}.md`);
|
|
859
1121
|
writeGeneratedFile(filepath, cmd.content);
|
|
860
1122
|
filesWritten.push(filepath);
|
|
861
1123
|
}
|
|
862
1124
|
}
|
|
863
1125
|
if (effective.includes("hooks") || effective.includes("plugins")) {
|
|
864
|
-
const pluginsDir =
|
|
1126
|
+
const pluginsDir = resolve3(opencodeDir, "plugins");
|
|
865
1127
|
ensureDir(pluginsDir);
|
|
866
1128
|
if (effective.includes("hooks")) {
|
|
867
1129
|
for (const hookSet of features.hooks) {
|
|
868
1130
|
const events = resolveHooksForTarget(hookSet, TARGET_ID);
|
|
869
1131
|
if (Object.keys(events).length > 0) {
|
|
870
|
-
const filepath =
|
|
1132
|
+
const filepath = join8(pluginsDir, `agentpacks-${hookSet.packName}.ts`);
|
|
871
1133
|
const content = generateOpenCodeHookPlugin(hookSet.packName, events);
|
|
872
1134
|
writeGeneratedFile(filepath, content, { type: "ts" });
|
|
873
1135
|
filesWritten.push(filepath);
|
|
@@ -876,7 +1138,7 @@ class OpenCodeTarget extends BaseTarget {
|
|
|
876
1138
|
}
|
|
877
1139
|
if (effective.includes("plugins")) {
|
|
878
1140
|
for (const plugin of features.plugins) {
|
|
879
|
-
const filepath =
|
|
1141
|
+
const filepath = join8(pluginsDir, `agentpacks-${plugin.packName}-${plugin.name}.${plugin.extension}`);
|
|
880
1142
|
writeGeneratedFile(filepath, plugin.content, {
|
|
881
1143
|
type: plugin.extension
|
|
882
1144
|
});
|
|
@@ -884,28 +1146,59 @@ class OpenCodeTarget extends BaseTarget {
|
|
|
884
1146
|
}
|
|
885
1147
|
}
|
|
886
1148
|
}
|
|
887
|
-
if (effective.includes("mcp")) {
|
|
888
|
-
const
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
1149
|
+
if (effective.includes("mcp") || effective.includes("models")) {
|
|
1150
|
+
const filepath = resolve3(root, "opencode.json");
|
|
1151
|
+
const opencodeConfig = {
|
|
1152
|
+
$schema: "https://opencode.ai/config.json"
|
|
1153
|
+
};
|
|
1154
|
+
if (effective.includes("mcp")) {
|
|
1155
|
+
const mcpEntries = Object.entries(features.mcpServers);
|
|
1156
|
+
if (mcpEntries.length > 0) {
|
|
1157
|
+
opencodeConfig.mcp = buildOpenCodeMcpServers(features.mcpServers);
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
if (effective.includes("models") && features.models) {
|
|
1161
|
+
const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID);
|
|
1162
|
+
if (resolved.default)
|
|
1163
|
+
opencodeConfig.model = resolved.default;
|
|
1164
|
+
if (resolved.small)
|
|
1165
|
+
opencodeConfig.small_model = resolved.small;
|
|
1166
|
+
if (Object.keys(resolved.providers).length > 0) {
|
|
1167
|
+
opencodeConfig.provider = resolved.providers;
|
|
1168
|
+
}
|
|
1169
|
+
const agentEntries = Object.entries(resolved.agents);
|
|
1170
|
+
if (agentEntries.length > 0) {
|
|
1171
|
+
const agentConfig = {};
|
|
1172
|
+
for (const [name, assignment] of agentEntries) {
|
|
1173
|
+
const config = { model: assignment.model };
|
|
1174
|
+
if (assignment.temperature !== undefined) {
|
|
1175
|
+
config.temperature = assignment.temperature;
|
|
1176
|
+
}
|
|
1177
|
+
if (assignment.top_p !== undefined) {
|
|
1178
|
+
config.top_p = assignment.top_p;
|
|
1179
|
+
}
|
|
1180
|
+
agentConfig[name] = config;
|
|
1181
|
+
}
|
|
1182
|
+
opencodeConfig.agent = agentConfig;
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
if (Object.keys(opencodeConfig).length > 1) {
|
|
892
1186
|
writeGeneratedJson(filepath, opencodeConfig, { header: false });
|
|
893
1187
|
filesWritten.push(filepath);
|
|
894
1188
|
}
|
|
895
1189
|
}
|
|
896
1190
|
if (effective.includes("rules")) {
|
|
897
1191
|
const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID));
|
|
898
|
-
const rootRules = getRootRules(rules);
|
|
899
1192
|
const detailRules = getDetailRules(rules);
|
|
900
1193
|
if (detailRules.length > 0) {
|
|
901
|
-
const memoriesDir =
|
|
1194
|
+
const memoriesDir = resolve3(opencodeDir, "memories");
|
|
902
1195
|
if (deleteExisting) {
|
|
903
1196
|
removeIfExists(memoriesDir);
|
|
904
1197
|
filesDeleted.push(memoriesDir);
|
|
905
1198
|
}
|
|
906
1199
|
ensureDir(memoriesDir);
|
|
907
1200
|
for (const rule of detailRules) {
|
|
908
|
-
const filepath =
|
|
1201
|
+
const filepath = join8(memoriesDir, `${rule.name}.md`);
|
|
909
1202
|
writeGeneratedFile(filepath, rule.content);
|
|
910
1203
|
filesWritten.push(filepath);
|
|
911
1204
|
}
|
|
@@ -914,7 +1207,7 @@ class OpenCodeTarget extends BaseTarget {
|
|
|
914
1207
|
return this.createResult(filesWritten, filesDeleted, warnings);
|
|
915
1208
|
}
|
|
916
1209
|
}
|
|
917
|
-
function
|
|
1210
|
+
function buildOpenCodeMcpServers(servers) {
|
|
918
1211
|
const mcp = {};
|
|
919
1212
|
for (const [name, entry] of Object.entries(servers)) {
|
|
920
1213
|
if (entry.url) {
|
|
@@ -934,10 +1227,7 @@ function buildOpenCodeMcp(servers) {
|
|
|
934
1227
|
};
|
|
935
1228
|
}
|
|
936
1229
|
}
|
|
937
|
-
return
|
|
938
|
-
$schema: "https://opencode.ai/config.json",
|
|
939
|
-
mcp
|
|
940
|
-
};
|
|
1230
|
+
return mcp;
|
|
941
1231
|
}
|
|
942
1232
|
function generateOpenCodeHookPlugin(packName, events) {
|
|
943
1233
|
const identifier = packNameToIdentifier(packName);
|
|
@@ -984,7 +1274,7 @@ function mapHookEvents(events) {
|
|
|
984
1274
|
}
|
|
985
1275
|
|
|
986
1276
|
// src/targets/cursor.ts
|
|
987
|
-
import { resolve as
|
|
1277
|
+
import { resolve as resolve4, join as join9 } from "path";
|
|
988
1278
|
var TARGET_ID2 = "cursor";
|
|
989
1279
|
|
|
990
1280
|
class CursorTarget extends BaseTarget {
|
|
@@ -997,18 +1287,19 @@ class CursorTarget extends BaseTarget {
|
|
|
997
1287
|
"skills",
|
|
998
1288
|
"hooks",
|
|
999
1289
|
"mcp",
|
|
1000
|
-
"ignore"
|
|
1290
|
+
"ignore",
|
|
1291
|
+
"models"
|
|
1001
1292
|
];
|
|
1002
1293
|
generate(options) {
|
|
1003
1294
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
1004
|
-
const root =
|
|
1295
|
+
const root = resolve4(projectRoot, baseDir);
|
|
1005
1296
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
1006
1297
|
const filesWritten = [];
|
|
1007
1298
|
const filesDeleted = [];
|
|
1008
1299
|
const warnings = [];
|
|
1009
|
-
const cursorDir =
|
|
1300
|
+
const cursorDir = resolve4(root, ".cursor");
|
|
1010
1301
|
if (effective.includes("rules")) {
|
|
1011
|
-
const rulesDir =
|
|
1302
|
+
const rulesDir = resolve4(cursorDir, "rules");
|
|
1012
1303
|
if (deleteExisting) {
|
|
1013
1304
|
removeIfExists(rulesDir);
|
|
1014
1305
|
filesDeleted.push(rulesDir);
|
|
@@ -1025,33 +1316,40 @@ class CursorTarget extends BaseTarget {
|
|
|
1025
1316
|
if (globs) {
|
|
1026
1317
|
frontmatter.globs = globs;
|
|
1027
1318
|
}
|
|
1028
|
-
const filepath =
|
|
1319
|
+
const filepath = join9(rulesDir, `${rule.name}.mdc`);
|
|
1029
1320
|
const content = serializeFrontmatter(frontmatter, rule.content);
|
|
1030
1321
|
writeGeneratedFile(filepath, content);
|
|
1031
1322
|
filesWritten.push(filepath);
|
|
1032
1323
|
}
|
|
1033
1324
|
}
|
|
1034
1325
|
if (effective.includes("agents")) {
|
|
1035
|
-
const agentsDir =
|
|
1326
|
+
const agentsDir = resolve4(cursorDir, "agents");
|
|
1036
1327
|
if (deleteExisting) {
|
|
1037
1328
|
removeIfExists(agentsDir);
|
|
1038
1329
|
filesDeleted.push(agentsDir);
|
|
1039
1330
|
}
|
|
1040
1331
|
ensureDir(agentsDir);
|
|
1332
|
+
const resolvedModels = features.models ? resolveModels(features.models, options.modelProfile, TARGET_ID2) : null;
|
|
1041
1333
|
const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID2));
|
|
1042
1334
|
for (const agent of agents) {
|
|
1043
1335
|
const frontmatter = {
|
|
1044
1336
|
name: agent.name,
|
|
1045
1337
|
description: agent.meta.description ?? ""
|
|
1046
1338
|
};
|
|
1047
|
-
const
|
|
1339
|
+
const cursorMeta = agent.meta.cursor ?? {};
|
|
1340
|
+
const modelsAgent = resolvedModels?.agents[agent.name];
|
|
1341
|
+
const model = modelsAgent?.model ?? cursorMeta.model;
|
|
1342
|
+
if (model) {
|
|
1343
|
+
frontmatter.model = model;
|
|
1344
|
+
}
|
|
1345
|
+
const filepath = join9(agentsDir, `${agent.name}.md`);
|
|
1048
1346
|
const content = serializeFrontmatter(frontmatter, agent.content);
|
|
1049
1347
|
writeGeneratedFile(filepath, content);
|
|
1050
1348
|
filesWritten.push(filepath);
|
|
1051
1349
|
}
|
|
1052
1350
|
}
|
|
1053
1351
|
if (effective.includes("skills")) {
|
|
1054
|
-
const skillsDir =
|
|
1352
|
+
const skillsDir = resolve4(cursorDir, "skills");
|
|
1055
1353
|
if (deleteExisting) {
|
|
1056
1354
|
removeIfExists(skillsDir);
|
|
1057
1355
|
filesDeleted.push(skillsDir);
|
|
@@ -1059,20 +1357,20 @@ class CursorTarget extends BaseTarget {
|
|
|
1059
1357
|
ensureDir(skillsDir);
|
|
1060
1358
|
const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID2));
|
|
1061
1359
|
for (const skill of skills) {
|
|
1062
|
-
const skillSubDir =
|
|
1360
|
+
const skillSubDir = join9(skillsDir, skill.name);
|
|
1063
1361
|
ensureDir(skillSubDir);
|
|
1064
1362
|
const frontmatter = {
|
|
1065
1363
|
name: skill.name,
|
|
1066
1364
|
description: skill.meta.description ?? ""
|
|
1067
1365
|
};
|
|
1068
|
-
const filepath =
|
|
1366
|
+
const filepath = join9(skillSubDir, "SKILL.md");
|
|
1069
1367
|
const content = serializeFrontmatter(frontmatter, skill.content);
|
|
1070
1368
|
writeGeneratedFile(filepath, content);
|
|
1071
1369
|
filesWritten.push(filepath);
|
|
1072
1370
|
}
|
|
1073
1371
|
}
|
|
1074
1372
|
if (effective.includes("commands")) {
|
|
1075
|
-
const commandsDir =
|
|
1373
|
+
const commandsDir = resolve4(cursorDir, "commands");
|
|
1076
1374
|
if (deleteExisting) {
|
|
1077
1375
|
removeIfExists(commandsDir);
|
|
1078
1376
|
filesDeleted.push(commandsDir);
|
|
@@ -1080,7 +1378,7 @@ class CursorTarget extends BaseTarget {
|
|
|
1080
1378
|
ensureDir(commandsDir);
|
|
1081
1379
|
const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID2));
|
|
1082
1380
|
for (const cmd of commands) {
|
|
1083
|
-
const filepath =
|
|
1381
|
+
const filepath = join9(commandsDir, `${cmd.name}.md`);
|
|
1084
1382
|
writeGeneratedFile(filepath, cmd.content);
|
|
1085
1383
|
filesWritten.push(filepath);
|
|
1086
1384
|
}
|
|
@@ -1089,14 +1387,14 @@ class CursorTarget extends BaseTarget {
|
|
|
1089
1387
|
const mcpEntries = Object.entries(features.mcpServers);
|
|
1090
1388
|
if (mcpEntries.length > 0) {
|
|
1091
1389
|
const mcpConfig = buildCursorMcp(features.mcpServers);
|
|
1092
|
-
const filepath =
|
|
1390
|
+
const filepath = resolve4(cursorDir, "mcp.json");
|
|
1093
1391
|
writeGeneratedJson(filepath, mcpConfig, { header: false });
|
|
1094
1392
|
filesWritten.push(filepath);
|
|
1095
1393
|
}
|
|
1096
1394
|
}
|
|
1097
1395
|
if (effective.includes("ignore")) {
|
|
1098
1396
|
if (features.ignorePatterns.length > 0) {
|
|
1099
|
-
const filepath =
|
|
1397
|
+
const filepath = resolve4(root, ".cursorignore");
|
|
1100
1398
|
const content = features.ignorePatterns.join(`
|
|
1101
1399
|
`) + `
|
|
1102
1400
|
`;
|
|
@@ -1104,6 +1402,17 @@ class CursorTarget extends BaseTarget {
|
|
|
1104
1402
|
filesWritten.push(filepath);
|
|
1105
1403
|
}
|
|
1106
1404
|
}
|
|
1405
|
+
if (effective.includes("models") && features.models) {
|
|
1406
|
+
const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID2);
|
|
1407
|
+
const guidanceContent = buildCursorModelGuidance(resolved);
|
|
1408
|
+
if (guidanceContent) {
|
|
1409
|
+
const rulesDir = resolve4(cursorDir, "rules");
|
|
1410
|
+
ensureDir(rulesDir);
|
|
1411
|
+
const filepath = join9(rulesDir, "model-config.mdc");
|
|
1412
|
+
writeGeneratedFile(filepath, guidanceContent, { header: false });
|
|
1413
|
+
filesWritten.push(filepath);
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1107
1416
|
return this.createResult(filesWritten, filesDeleted, warnings);
|
|
1108
1417
|
}
|
|
1109
1418
|
}
|
|
@@ -1122,9 +1431,135 @@ function buildCursorMcp(servers) {
|
|
|
1122
1431
|
}
|
|
1123
1432
|
return { mcpServers };
|
|
1124
1433
|
}
|
|
1434
|
+
function buildCursorModelGuidance(resolved) {
|
|
1435
|
+
if (!resolved.default && !resolved.small && Object.keys(resolved.agents).length === 0) {
|
|
1436
|
+
return null;
|
|
1437
|
+
}
|
|
1438
|
+
const frontmatter = {
|
|
1439
|
+
description: "Model configuration and selection guidelines for this workspace",
|
|
1440
|
+
alwaysApply: true
|
|
1441
|
+
};
|
|
1442
|
+
const lines = [];
|
|
1443
|
+
lines.push("# Model Configuration");
|
|
1444
|
+
lines.push("");
|
|
1445
|
+
lines.push("Use the following model preferences when working in this project.");
|
|
1446
|
+
lines.push("");
|
|
1447
|
+
if (resolved.default || resolved.small) {
|
|
1448
|
+
lines.push("## Default Models");
|
|
1449
|
+
lines.push("");
|
|
1450
|
+
if (resolved.default) {
|
|
1451
|
+
lines.push(`- **Primary model**: ${resolved.default}`);
|
|
1452
|
+
}
|
|
1453
|
+
if (resolved.small) {
|
|
1454
|
+
lines.push(`- **Lightweight tasks** (titles, summaries): ${resolved.small}`);
|
|
1455
|
+
}
|
|
1456
|
+
lines.push("");
|
|
1457
|
+
}
|
|
1458
|
+
const agentEntries = Object.entries(resolved.agents);
|
|
1459
|
+
if (agentEntries.length > 0) {
|
|
1460
|
+
lines.push("## Agent Model Assignments");
|
|
1461
|
+
lines.push("");
|
|
1462
|
+
lines.push("| Agent | Model | Temperature |");
|
|
1463
|
+
lines.push("| --- | --- | --- |");
|
|
1464
|
+
for (const [name, assignment] of agentEntries) {
|
|
1465
|
+
const temp = assignment.temperature !== undefined ? String(assignment.temperature) : "—";
|
|
1466
|
+
lines.push(`| ${name} | ${assignment.model} | ${temp} |`);
|
|
1467
|
+
}
|
|
1468
|
+
lines.push("");
|
|
1469
|
+
}
|
|
1470
|
+
if (Object.keys(resolved.profiles).length > 0) {
|
|
1471
|
+
lines.push("## Available Profiles");
|
|
1472
|
+
lines.push("");
|
|
1473
|
+
lines.push("| Profile | Description | Default Model |");
|
|
1474
|
+
lines.push("| --- | --- | --- |");
|
|
1475
|
+
for (const [name, profile] of Object.entries(resolved.profiles)) {
|
|
1476
|
+
lines.push(`| ${name} | ${profile.description ?? "—"} | ${profile.default ?? "—"} |`);
|
|
1477
|
+
}
|
|
1478
|
+
lines.push("");
|
|
1479
|
+
}
|
|
1480
|
+
if (resolved.activeProfile) {
|
|
1481
|
+
lines.push(`**Active profile**: \`${resolved.activeProfile}\``);
|
|
1482
|
+
lines.push("");
|
|
1483
|
+
}
|
|
1484
|
+
return serializeFrontmatter(frontmatter, lines.join(`
|
|
1485
|
+
`));
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
// src/utils/model-guidance.ts
|
|
1489
|
+
function generateModelGuidanceMarkdown(resolved) {
|
|
1490
|
+
if (!resolved.default && !resolved.small && Object.keys(resolved.agents).length === 0 && Object.keys(resolved.profiles).length === 0) {
|
|
1491
|
+
return null;
|
|
1492
|
+
}
|
|
1493
|
+
const lines = [];
|
|
1494
|
+
lines.push("# Model Configuration");
|
|
1495
|
+
lines.push("");
|
|
1496
|
+
lines.push("Use the following model preferences when working in this project.");
|
|
1497
|
+
lines.push("");
|
|
1498
|
+
if (resolved.default || resolved.small) {
|
|
1499
|
+
lines.push("## Default Models");
|
|
1500
|
+
lines.push("");
|
|
1501
|
+
if (resolved.default) {
|
|
1502
|
+
lines.push(`- **Primary model**: ${resolved.default}`);
|
|
1503
|
+
}
|
|
1504
|
+
if (resolved.small) {
|
|
1505
|
+
lines.push(`- **Lightweight tasks** (titles, summaries): ${resolved.small}`);
|
|
1506
|
+
}
|
|
1507
|
+
lines.push("");
|
|
1508
|
+
}
|
|
1509
|
+
const agentEntries = Object.entries(resolved.agents);
|
|
1510
|
+
if (agentEntries.length > 0) {
|
|
1511
|
+
lines.push("## Agent Model Assignments");
|
|
1512
|
+
lines.push("");
|
|
1513
|
+
lines.push("| Agent | Model | Temperature |");
|
|
1514
|
+
lines.push("| --- | --- | --- |");
|
|
1515
|
+
for (const [name, assignment] of agentEntries) {
|
|
1516
|
+
const temp = assignment.temperature !== undefined ? String(assignment.temperature) : "—";
|
|
1517
|
+
lines.push(`| ${name} | ${assignment.model} | ${temp} |`);
|
|
1518
|
+
}
|
|
1519
|
+
lines.push("");
|
|
1520
|
+
}
|
|
1521
|
+
if (Object.keys(resolved.profiles).length > 0) {
|
|
1522
|
+
lines.push("## Available Profiles");
|
|
1523
|
+
lines.push("");
|
|
1524
|
+
lines.push("| Profile | Description | Default Model |");
|
|
1525
|
+
lines.push("| --- | --- | --- |");
|
|
1526
|
+
for (const [name, profile] of Object.entries(resolved.profiles)) {
|
|
1527
|
+
lines.push(`| ${name} | ${profile.description ?? "—"} | ${profile.default ?? "—"} |`);
|
|
1528
|
+
}
|
|
1529
|
+
lines.push("");
|
|
1530
|
+
}
|
|
1531
|
+
if (resolved.activeProfile) {
|
|
1532
|
+
lines.push(`**Active profile**: \`${resolved.activeProfile}\``);
|
|
1533
|
+
lines.push("");
|
|
1534
|
+
}
|
|
1535
|
+
if (resolved.routing.length > 0) {
|
|
1536
|
+
lines.push("## Task-Aware Routing");
|
|
1537
|
+
lines.push("");
|
|
1538
|
+
lines.push("Select the appropriate profile based on the task context:");
|
|
1539
|
+
lines.push("");
|
|
1540
|
+
lines.push("| Condition | Profile | Description |");
|
|
1541
|
+
lines.push("| --- | --- | --- |");
|
|
1542
|
+
for (const rule of resolved.routing) {
|
|
1543
|
+
const conditions = Object.entries(rule.when).map(([k, v]) => `${k}=${v}`).join(", ");
|
|
1544
|
+
const desc = rule.description ?? "—";
|
|
1545
|
+
lines.push(`| ${conditions} | ${rule.use} | ${desc} |`);
|
|
1546
|
+
}
|
|
1547
|
+
lines.push("");
|
|
1548
|
+
lines.push("### Condition Reference");
|
|
1549
|
+
lines.push("");
|
|
1550
|
+
lines.push("- **complexity**: low | medium | high | critical");
|
|
1551
|
+
lines.push("- **urgency**: low | normal | high");
|
|
1552
|
+
lines.push("- **budget**: minimal | standard | premium");
|
|
1553
|
+
lines.push("- **contextWindowNeed**: small | medium | large | max");
|
|
1554
|
+
lines.push("- **toolUseIntensity**: none | light | heavy");
|
|
1555
|
+
lines.push("");
|
|
1556
|
+
}
|
|
1557
|
+
return lines.join(`
|
|
1558
|
+
`);
|
|
1559
|
+
}
|
|
1125
1560
|
|
|
1126
1561
|
// src/targets/claude-code.ts
|
|
1127
|
-
import { resolve as
|
|
1562
|
+
import { resolve as resolve5, join as join10 } from "path";
|
|
1128
1563
|
var TARGET_ID3 = "claudecode";
|
|
1129
1564
|
|
|
1130
1565
|
class ClaudeCodeTarget extends BaseTarget {
|
|
@@ -1137,18 +1572,19 @@ class ClaudeCodeTarget extends BaseTarget {
|
|
|
1137
1572
|
"skills",
|
|
1138
1573
|
"hooks",
|
|
1139
1574
|
"mcp",
|
|
1140
|
-
"ignore"
|
|
1575
|
+
"ignore",
|
|
1576
|
+
"models"
|
|
1141
1577
|
];
|
|
1142
1578
|
generate(options) {
|
|
1143
1579
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
1144
|
-
const root =
|
|
1580
|
+
const root = resolve5(projectRoot, baseDir);
|
|
1145
1581
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
1146
1582
|
const filesWritten = [];
|
|
1147
1583
|
const filesDeleted = [];
|
|
1148
1584
|
const warnings = [];
|
|
1149
|
-
const claudeDir =
|
|
1585
|
+
const claudeDir = resolve5(root, ".claude");
|
|
1150
1586
|
if (effective.includes("rules")) {
|
|
1151
|
-
const rulesDir =
|
|
1587
|
+
const rulesDir = resolve5(claudeDir, "rules");
|
|
1152
1588
|
if (deleteExisting) {
|
|
1153
1589
|
removeIfExists(rulesDir);
|
|
1154
1590
|
filesDeleted.push(rulesDir);
|
|
@@ -1161,32 +1597,41 @@ class ClaudeCodeTarget extends BaseTarget {
|
|
|
1161
1597
|
const claudeMd = rootRules.map((r) => r.content).join(`
|
|
1162
1598
|
|
|
1163
1599
|
`);
|
|
1164
|
-
const filepath =
|
|
1600
|
+
const filepath = resolve5(claudeDir, "CLAUDE.md");
|
|
1165
1601
|
writeGeneratedFile(filepath, claudeMd);
|
|
1166
1602
|
filesWritten.push(filepath);
|
|
1167
1603
|
}
|
|
1168
1604
|
for (const rule of detailRules) {
|
|
1169
|
-
const filepath =
|
|
1605
|
+
const filepath = join10(rulesDir, `${rule.name}.md`);
|
|
1170
1606
|
writeGeneratedFile(filepath, rule.content);
|
|
1171
1607
|
filesWritten.push(filepath);
|
|
1172
1608
|
}
|
|
1173
1609
|
}
|
|
1174
1610
|
if (effective.includes("agents")) {
|
|
1175
|
-
const agentsDir =
|
|
1611
|
+
const agentsDir = resolve5(claudeDir, "agents");
|
|
1176
1612
|
if (deleteExisting) {
|
|
1177
1613
|
removeIfExists(agentsDir);
|
|
1178
1614
|
filesDeleted.push(agentsDir);
|
|
1179
1615
|
}
|
|
1180
1616
|
ensureDir(agentsDir);
|
|
1617
|
+
const resolvedModels = features.models ? resolveModels(features.models, options.modelProfile, TARGET_ID3) : null;
|
|
1181
1618
|
const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID3));
|
|
1182
1619
|
for (const agent of agents) {
|
|
1183
|
-
const filepath =
|
|
1184
|
-
|
|
1620
|
+
const filepath = join10(agentsDir, `${agent.name}.md`);
|
|
1621
|
+
const cc = agent.meta.claudecode ?? {};
|
|
1622
|
+
const modelsAgent = resolvedModels?.agents[agent.name];
|
|
1623
|
+
const agentModel = modelsAgent?.model ?? cc.model;
|
|
1624
|
+
let content = agent.content;
|
|
1625
|
+
if (agentModel) {
|
|
1626
|
+
content = `<!-- model: ${agentModel} -->
|
|
1627
|
+
${content}`;
|
|
1628
|
+
}
|
|
1629
|
+
writeGeneratedFile(filepath, content);
|
|
1185
1630
|
filesWritten.push(filepath);
|
|
1186
1631
|
}
|
|
1187
1632
|
}
|
|
1188
1633
|
if (effective.includes("skills")) {
|
|
1189
|
-
const skillsDir =
|
|
1634
|
+
const skillsDir = resolve5(claudeDir, "skills");
|
|
1190
1635
|
if (deleteExisting) {
|
|
1191
1636
|
removeIfExists(skillsDir);
|
|
1192
1637
|
filesDeleted.push(skillsDir);
|
|
@@ -1194,15 +1639,15 @@ class ClaudeCodeTarget extends BaseTarget {
|
|
|
1194
1639
|
ensureDir(skillsDir);
|
|
1195
1640
|
const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID3));
|
|
1196
1641
|
for (const skill of skills) {
|
|
1197
|
-
const skillSubDir =
|
|
1642
|
+
const skillSubDir = join10(skillsDir, skill.name);
|
|
1198
1643
|
ensureDir(skillSubDir);
|
|
1199
|
-
const filepath =
|
|
1644
|
+
const filepath = join10(skillSubDir, "SKILL.md");
|
|
1200
1645
|
writeGeneratedFile(filepath, skill.content);
|
|
1201
1646
|
filesWritten.push(filepath);
|
|
1202
1647
|
}
|
|
1203
1648
|
}
|
|
1204
1649
|
if (effective.includes("commands")) {
|
|
1205
|
-
const commandsDir =
|
|
1650
|
+
const commandsDir = resolve5(claudeDir, "commands");
|
|
1206
1651
|
if (deleteExisting) {
|
|
1207
1652
|
removeIfExists(commandsDir);
|
|
1208
1653
|
filesDeleted.push(commandsDir);
|
|
@@ -1210,15 +1655,26 @@ class ClaudeCodeTarget extends BaseTarget {
|
|
|
1210
1655
|
ensureDir(commandsDir);
|
|
1211
1656
|
const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID3));
|
|
1212
1657
|
for (const cmd of commands) {
|
|
1213
|
-
const filepath =
|
|
1658
|
+
const filepath = join10(commandsDir, `${cmd.name}.md`);
|
|
1214
1659
|
writeGeneratedFile(filepath, cmd.content);
|
|
1215
1660
|
filesWritten.push(filepath);
|
|
1216
1661
|
}
|
|
1217
1662
|
}
|
|
1663
|
+
if (effective.includes("models") && features.models) {
|
|
1664
|
+
const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID3);
|
|
1665
|
+
const guidance = generateModelGuidanceMarkdown(resolved);
|
|
1666
|
+
if (guidance) {
|
|
1667
|
+
const rulesDir = resolve5(claudeDir, "rules");
|
|
1668
|
+
ensureDir(rulesDir);
|
|
1669
|
+
const filepath = join10(rulesDir, "model-config.md");
|
|
1670
|
+
writeGeneratedFile(filepath, guidance);
|
|
1671
|
+
filesWritten.push(filepath);
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1218
1674
|
if (effective.includes("hooks") || effective.includes("mcp") || effective.includes("ignore")) {
|
|
1219
1675
|
const settings = buildClaudeSettings(options, effective);
|
|
1220
1676
|
if (Object.keys(settings).length > 0) {
|
|
1221
|
-
const filepath =
|
|
1677
|
+
const filepath = resolve5(claudeDir, "settings.json");
|
|
1222
1678
|
const existing = readJsonOrNull(filepath) ?? {};
|
|
1223
1679
|
const merged = { ...existing, ...settings };
|
|
1224
1680
|
writeGeneratedJson(filepath, merged, { header: false });
|
|
@@ -1275,7 +1731,7 @@ function toPascalCase(str) {
|
|
|
1275
1731
|
}
|
|
1276
1732
|
|
|
1277
1733
|
// src/targets/codex-cli.ts
|
|
1278
|
-
import { resolve as
|
|
1734
|
+
import { resolve as resolve6, join as join11 } from "path";
|
|
1279
1735
|
var TARGET_ID4 = "codexcli";
|
|
1280
1736
|
|
|
1281
1737
|
class CodexCliTarget extends BaseTarget {
|
|
@@ -1284,14 +1740,14 @@ class CodexCliTarget extends BaseTarget {
|
|
|
1284
1740
|
supportedFeatures = ["rules", "skills", "mcp", "hooks"];
|
|
1285
1741
|
generate(options) {
|
|
1286
1742
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
1287
|
-
const root =
|
|
1743
|
+
const root = resolve6(projectRoot, baseDir);
|
|
1288
1744
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
1289
1745
|
const filesWritten = [];
|
|
1290
1746
|
const filesDeleted = [];
|
|
1291
1747
|
const warnings = [];
|
|
1292
|
-
const codexDir =
|
|
1748
|
+
const codexDir = resolve6(root, ".codex");
|
|
1293
1749
|
if (effective.includes("rules")) {
|
|
1294
|
-
const memoriesDir =
|
|
1750
|
+
const memoriesDir = resolve6(codexDir, "memories");
|
|
1295
1751
|
if (deleteExisting) {
|
|
1296
1752
|
removeIfExists(memoriesDir);
|
|
1297
1753
|
filesDeleted.push(memoriesDir);
|
|
@@ -1299,13 +1755,13 @@ class CodexCliTarget extends BaseTarget {
|
|
|
1299
1755
|
ensureDir(memoriesDir);
|
|
1300
1756
|
const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID4));
|
|
1301
1757
|
for (const rule of rules) {
|
|
1302
|
-
const filepath =
|
|
1758
|
+
const filepath = join11(memoriesDir, `${rule.name}.md`);
|
|
1303
1759
|
writeGeneratedFile(filepath, rule.content);
|
|
1304
1760
|
filesWritten.push(filepath);
|
|
1305
1761
|
}
|
|
1306
1762
|
}
|
|
1307
1763
|
if (effective.includes("skills")) {
|
|
1308
|
-
const skillsDir =
|
|
1764
|
+
const skillsDir = resolve6(codexDir, "skills");
|
|
1309
1765
|
if (deleteExisting) {
|
|
1310
1766
|
removeIfExists(skillsDir);
|
|
1311
1767
|
filesDeleted.push(skillsDir);
|
|
@@ -1313,9 +1769,9 @@ class CodexCliTarget extends BaseTarget {
|
|
|
1313
1769
|
ensureDir(skillsDir);
|
|
1314
1770
|
const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID4));
|
|
1315
1771
|
for (const skill of skills) {
|
|
1316
|
-
const skillSubDir =
|
|
1772
|
+
const skillSubDir = join11(skillsDir, skill.name);
|
|
1317
1773
|
ensureDir(skillSubDir);
|
|
1318
|
-
const filepath =
|
|
1774
|
+
const filepath = join11(skillSubDir, "SKILL.md");
|
|
1319
1775
|
writeGeneratedFile(filepath, skill.content);
|
|
1320
1776
|
filesWritten.push(filepath);
|
|
1321
1777
|
}
|
|
@@ -1325,7 +1781,7 @@ class CodexCliTarget extends BaseTarget {
|
|
|
1325
1781
|
}
|
|
1326
1782
|
|
|
1327
1783
|
// src/targets/gemini-cli.ts
|
|
1328
|
-
import { resolve as
|
|
1784
|
+
import { resolve as resolve7, join as join12 } from "path";
|
|
1329
1785
|
var TARGET_ID5 = "geminicli";
|
|
1330
1786
|
|
|
1331
1787
|
class GeminiCliTarget extends BaseTarget {
|
|
@@ -1341,12 +1797,12 @@ class GeminiCliTarget extends BaseTarget {
|
|
|
1341
1797
|
];
|
|
1342
1798
|
generate(options) {
|
|
1343
1799
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
1344
|
-
const root =
|
|
1800
|
+
const root = resolve7(projectRoot, baseDir);
|
|
1345
1801
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
1346
1802
|
const filesWritten = [];
|
|
1347
1803
|
const filesDeleted = [];
|
|
1348
1804
|
const warnings = [];
|
|
1349
|
-
const geminiDir =
|
|
1805
|
+
const geminiDir = resolve7(root, ".gemini");
|
|
1350
1806
|
if (effective.includes("rules")) {
|
|
1351
1807
|
const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID5));
|
|
1352
1808
|
const rootRules = getRootRules(rules);
|
|
@@ -1355,26 +1811,26 @@ class GeminiCliTarget extends BaseTarget {
|
|
|
1355
1811
|
const geminiMd = rootRules.map((r) => r.content).join(`
|
|
1356
1812
|
|
|
1357
1813
|
`);
|
|
1358
|
-
const filepath =
|
|
1814
|
+
const filepath = resolve7(root, "GEMINI.md");
|
|
1359
1815
|
writeGeneratedFile(filepath, geminiMd);
|
|
1360
1816
|
filesWritten.push(filepath);
|
|
1361
1817
|
}
|
|
1362
1818
|
if (detailRules.length > 0) {
|
|
1363
|
-
const memoriesDir =
|
|
1819
|
+
const memoriesDir = resolve7(geminiDir, "memories");
|
|
1364
1820
|
if (deleteExisting) {
|
|
1365
1821
|
removeIfExists(memoriesDir);
|
|
1366
1822
|
filesDeleted.push(memoriesDir);
|
|
1367
1823
|
}
|
|
1368
1824
|
ensureDir(memoriesDir);
|
|
1369
1825
|
for (const rule of detailRules) {
|
|
1370
|
-
const filepath =
|
|
1826
|
+
const filepath = join12(memoriesDir, `${rule.name}.md`);
|
|
1371
1827
|
writeGeneratedFile(filepath, rule.content);
|
|
1372
1828
|
filesWritten.push(filepath);
|
|
1373
1829
|
}
|
|
1374
1830
|
}
|
|
1375
1831
|
}
|
|
1376
1832
|
if (effective.includes("commands")) {
|
|
1377
|
-
const commandsDir =
|
|
1833
|
+
const commandsDir = resolve7(geminiDir, "commands");
|
|
1378
1834
|
if (deleteExisting) {
|
|
1379
1835
|
removeIfExists(commandsDir);
|
|
1380
1836
|
filesDeleted.push(commandsDir);
|
|
@@ -1383,7 +1839,7 @@ class GeminiCliTarget extends BaseTarget {
|
|
|
1383
1839
|
const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID5));
|
|
1384
1840
|
for (const cmd of commands) {
|
|
1385
1841
|
const toml = buildGeminiCommand(cmd.name, cmd.meta.description ?? "", cmd.content);
|
|
1386
|
-
const filepath =
|
|
1842
|
+
const filepath = join12(commandsDir, `${cmd.name}.toml`);
|
|
1387
1843
|
writeGeneratedFile(filepath, toml, { type: "md" });
|
|
1388
1844
|
filesWritten.push(filepath);
|
|
1389
1845
|
}
|
|
@@ -1392,14 +1848,14 @@ class GeminiCliTarget extends BaseTarget {
|
|
|
1392
1848
|
const mcpEntries = Object.entries(features.mcpServers);
|
|
1393
1849
|
if (mcpEntries.length > 0) {
|
|
1394
1850
|
const settings = buildGeminiSettings(features.mcpServers);
|
|
1395
|
-
const filepath =
|
|
1851
|
+
const filepath = resolve7(geminiDir, "settings.json");
|
|
1396
1852
|
writeGeneratedJson(filepath, settings, { header: false });
|
|
1397
1853
|
filesWritten.push(filepath);
|
|
1398
1854
|
}
|
|
1399
1855
|
}
|
|
1400
1856
|
if (effective.includes("ignore")) {
|
|
1401
1857
|
if (features.ignorePatterns.length > 0) {
|
|
1402
|
-
const filepath =
|
|
1858
|
+
const filepath = resolve7(root, ".geminiignore");
|
|
1403
1859
|
const content = features.ignorePatterns.join(`
|
|
1404
1860
|
`) + `
|
|
1405
1861
|
`;
|
|
@@ -1438,7 +1894,7 @@ function buildGeminiSettings(servers) {
|
|
|
1438
1894
|
}
|
|
1439
1895
|
|
|
1440
1896
|
// src/targets/copilot.ts
|
|
1441
|
-
import { resolve as
|
|
1897
|
+
import { resolve as resolve8, join as join13 } from "path";
|
|
1442
1898
|
var TARGET_ID6 = "copilot";
|
|
1443
1899
|
|
|
1444
1900
|
class CopilotTarget extends BaseTarget {
|
|
@@ -1450,16 +1906,17 @@ class CopilotTarget extends BaseTarget {
|
|
|
1450
1906
|
"agents",
|
|
1451
1907
|
"skills",
|
|
1452
1908
|
"mcp",
|
|
1453
|
-
"ignore"
|
|
1909
|
+
"ignore",
|
|
1910
|
+
"models"
|
|
1454
1911
|
];
|
|
1455
1912
|
generate(options) {
|
|
1456
1913
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
1457
|
-
const root =
|
|
1914
|
+
const root = resolve8(projectRoot, baseDir);
|
|
1458
1915
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
1459
1916
|
const filesWritten = [];
|
|
1460
1917
|
const filesDeleted = [];
|
|
1461
1918
|
const warnings = [];
|
|
1462
|
-
const githubDir =
|
|
1919
|
+
const githubDir = resolve8(root, ".github");
|
|
1463
1920
|
if (effective.includes("rules")) {
|
|
1464
1921
|
const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID6));
|
|
1465
1922
|
if (rules.length > 0) {
|
|
@@ -1468,15 +1925,15 @@ class CopilotTarget extends BaseTarget {
|
|
|
1468
1925
|
---
|
|
1469
1926
|
|
|
1470
1927
|
`);
|
|
1471
|
-
const filepath =
|
|
1928
|
+
const filepath = resolve8(githubDir, "copilot-instructions.md");
|
|
1472
1929
|
ensureDir(githubDir);
|
|
1473
1930
|
writeGeneratedFile(filepath, combinedContent);
|
|
1474
1931
|
filesWritten.push(filepath);
|
|
1475
1932
|
}
|
|
1476
1933
|
}
|
|
1477
1934
|
if (effective.includes("agents")) {
|
|
1478
|
-
const copilotDir =
|
|
1479
|
-
const agentsDir =
|
|
1935
|
+
const copilotDir = resolve8(githubDir, "copilot");
|
|
1936
|
+
const agentsDir = resolve8(copilotDir, "agents");
|
|
1480
1937
|
if (deleteExisting) {
|
|
1481
1938
|
removeIfExists(agentsDir);
|
|
1482
1939
|
filesDeleted.push(agentsDir);
|
|
@@ -1484,14 +1941,14 @@ class CopilotTarget extends BaseTarget {
|
|
|
1484
1941
|
ensureDir(agentsDir);
|
|
1485
1942
|
const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID6));
|
|
1486
1943
|
for (const agent of agents) {
|
|
1487
|
-
const filepath =
|
|
1944
|
+
const filepath = join13(agentsDir, `${agent.name}.md`);
|
|
1488
1945
|
writeGeneratedFile(filepath, agent.content);
|
|
1489
1946
|
filesWritten.push(filepath);
|
|
1490
1947
|
}
|
|
1491
1948
|
}
|
|
1492
1949
|
if (effective.includes("skills")) {
|
|
1493
|
-
const copilotDir =
|
|
1494
|
-
const skillsDir =
|
|
1950
|
+
const copilotDir = resolve8(githubDir, "copilot");
|
|
1951
|
+
const skillsDir = resolve8(copilotDir, "skills");
|
|
1495
1952
|
if (deleteExisting) {
|
|
1496
1953
|
removeIfExists(skillsDir);
|
|
1497
1954
|
filesDeleted.push(skillsDir);
|
|
@@ -1499,16 +1956,16 @@ class CopilotTarget extends BaseTarget {
|
|
|
1499
1956
|
ensureDir(skillsDir);
|
|
1500
1957
|
const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID6));
|
|
1501
1958
|
for (const skill of skills) {
|
|
1502
|
-
const skillSubDir =
|
|
1959
|
+
const skillSubDir = join13(skillsDir, skill.name);
|
|
1503
1960
|
ensureDir(skillSubDir);
|
|
1504
|
-
const filepath =
|
|
1961
|
+
const filepath = join13(skillSubDir, "SKILL.md");
|
|
1505
1962
|
writeGeneratedFile(filepath, skill.content);
|
|
1506
1963
|
filesWritten.push(filepath);
|
|
1507
1964
|
}
|
|
1508
1965
|
}
|
|
1509
1966
|
if (effective.includes("commands")) {
|
|
1510
|
-
const copilotDir =
|
|
1511
|
-
const commandsDir =
|
|
1967
|
+
const copilotDir = resolve8(githubDir, "copilot");
|
|
1968
|
+
const commandsDir = resolve8(copilotDir, "commands");
|
|
1512
1969
|
if (deleteExisting) {
|
|
1513
1970
|
removeIfExists(commandsDir);
|
|
1514
1971
|
filesDeleted.push(commandsDir);
|
|
@@ -1516,25 +1973,36 @@ class CopilotTarget extends BaseTarget {
|
|
|
1516
1973
|
ensureDir(commandsDir);
|
|
1517
1974
|
const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID6));
|
|
1518
1975
|
for (const cmd of commands) {
|
|
1519
|
-
const filepath =
|
|
1976
|
+
const filepath = join13(commandsDir, `${cmd.name}.md`);
|
|
1520
1977
|
writeGeneratedFile(filepath, cmd.content);
|
|
1521
1978
|
filesWritten.push(filepath);
|
|
1522
1979
|
}
|
|
1523
1980
|
}
|
|
1524
1981
|
if (effective.includes("ignore")) {}
|
|
1982
|
+
if (effective.includes("models") && features.models) {
|
|
1983
|
+
const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID6);
|
|
1984
|
+
const guidance = generateModelGuidanceMarkdown(resolved);
|
|
1985
|
+
if (guidance) {
|
|
1986
|
+
const copilotDir = resolve8(githubDir, "copilot");
|
|
1987
|
+
ensureDir(copilotDir);
|
|
1988
|
+
const filepath = join13(copilotDir, "model-config.md");
|
|
1989
|
+
writeGeneratedFile(filepath, guidance);
|
|
1990
|
+
filesWritten.push(filepath);
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1525
1993
|
return this.createResult(filesWritten, filesDeleted, warnings);
|
|
1526
1994
|
}
|
|
1527
1995
|
}
|
|
1528
1996
|
|
|
1529
1997
|
// src/targets/agents-md.ts
|
|
1530
|
-
import { resolve as
|
|
1998
|
+
import { resolve as resolve9 } from "path";
|
|
1531
1999
|
class AgentsMdTarget extends BaseTarget {
|
|
1532
2000
|
id = "agentsmd";
|
|
1533
2001
|
name = "AGENTS.md";
|
|
1534
2002
|
supportedFeatures = ["rules"];
|
|
1535
2003
|
generate(options) {
|
|
1536
2004
|
const { projectRoot, baseDir, features } = options;
|
|
1537
|
-
const root =
|
|
2005
|
+
const root = resolve9(projectRoot, baseDir);
|
|
1538
2006
|
const filesWritten = [];
|
|
1539
2007
|
const warnings = [];
|
|
1540
2008
|
const rootRules = getRootRules(features.rules);
|
|
@@ -1546,7 +2014,7 @@ class AgentsMdTarget extends BaseTarget {
|
|
|
1546
2014
|
const content = sections.join(`
|
|
1547
2015
|
|
|
1548
2016
|
`);
|
|
1549
|
-
const filepath =
|
|
2017
|
+
const filepath = resolve9(root, "AGENTS.md");
|
|
1550
2018
|
writeGeneratedFile(filepath, content);
|
|
1551
2019
|
filesWritten.push(filepath);
|
|
1552
2020
|
return this.createResult(filesWritten, [], warnings);
|
|
@@ -1554,7 +2022,7 @@ class AgentsMdTarget extends BaseTarget {
|
|
|
1554
2022
|
}
|
|
1555
2023
|
|
|
1556
2024
|
// src/targets/generic-md-target.ts
|
|
1557
|
-
import { resolve as
|
|
2025
|
+
import { resolve as resolve10, join as join14 } from "path";
|
|
1558
2026
|
function createGenericMdTarget(config) {
|
|
1559
2027
|
return new GenericMdTarget(config);
|
|
1560
2028
|
}
|
|
@@ -1573,16 +2041,16 @@ class GenericMdTarget extends BaseTarget {
|
|
|
1573
2041
|
}
|
|
1574
2042
|
generate(options) {
|
|
1575
2043
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
1576
|
-
const root =
|
|
2044
|
+
const root = resolve10(projectRoot, baseDir);
|
|
1577
2045
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
1578
2046
|
const filesWritten = [];
|
|
1579
2047
|
const filesDeleted = [];
|
|
1580
2048
|
const warnings = [];
|
|
1581
|
-
const configDir =
|
|
2049
|
+
const configDir = resolve10(root, this.config.configDir);
|
|
1582
2050
|
const rulesSubDir = this.config.rulesDir ?? "rules";
|
|
1583
2051
|
const ext = this.config.ruleExtension ?? ".md";
|
|
1584
2052
|
if (effective.includes("rules")) {
|
|
1585
|
-
const rulesDir =
|
|
2053
|
+
const rulesDir = resolve10(configDir, rulesSubDir);
|
|
1586
2054
|
if (deleteExisting) {
|
|
1587
2055
|
removeIfExists(rulesDir);
|
|
1588
2056
|
filesDeleted.push(rulesDir);
|
|
@@ -1590,13 +2058,13 @@ class GenericMdTarget extends BaseTarget {
|
|
|
1590
2058
|
ensureDir(rulesDir);
|
|
1591
2059
|
const rules = features.rules.filter((r) => ruleMatchesTarget(r, this.id));
|
|
1592
2060
|
for (const rule of rules) {
|
|
1593
|
-
const filepath =
|
|
2061
|
+
const filepath = join14(rulesDir, `${rule.name}${ext}`);
|
|
1594
2062
|
writeGeneratedFile(filepath, rule.content);
|
|
1595
2063
|
filesWritten.push(filepath);
|
|
1596
2064
|
}
|
|
1597
2065
|
}
|
|
1598
2066
|
if (effective.includes("commands")) {
|
|
1599
|
-
const commandsDir =
|
|
2067
|
+
const commandsDir = resolve10(configDir, "commands");
|
|
1600
2068
|
if (deleteExisting) {
|
|
1601
2069
|
removeIfExists(commandsDir);
|
|
1602
2070
|
filesDeleted.push(commandsDir);
|
|
@@ -1604,7 +2072,7 @@ class GenericMdTarget extends BaseTarget {
|
|
|
1604
2072
|
ensureDir(commandsDir);
|
|
1605
2073
|
const commands = features.commands.filter((c) => commandMatchesTarget(c, this.id));
|
|
1606
2074
|
for (const cmd of commands) {
|
|
1607
|
-
const filepath =
|
|
2075
|
+
const filepath = join14(commandsDir, `${cmd.name}.md`);
|
|
1608
2076
|
writeGeneratedFile(filepath, cmd.content);
|
|
1609
2077
|
filesWritten.push(filepath);
|
|
1610
2078
|
}
|
|
@@ -1613,7 +2081,7 @@ class GenericMdTarget extends BaseTarget {
|
|
|
1613
2081
|
const mcpEntries = Object.entries(features.mcpServers);
|
|
1614
2082
|
if (mcpEntries.length > 0) {
|
|
1615
2083
|
const mcpDir = this.config.mcpInConfigDir ? configDir : root;
|
|
1616
|
-
const filepath =
|
|
2084
|
+
const filepath = resolve10(mcpDir, "mcp.json");
|
|
1617
2085
|
writeGeneratedJson(filepath, { mcpServers: features.mcpServers }, {
|
|
1618
2086
|
header: false
|
|
1619
2087
|
});
|
|
@@ -1622,13 +2090,23 @@ class GenericMdTarget extends BaseTarget {
|
|
|
1622
2090
|
}
|
|
1623
2091
|
if (effective.includes("ignore") && this.config.ignoreFile) {
|
|
1624
2092
|
if (features.ignorePatterns.length > 0) {
|
|
1625
|
-
const filepath =
|
|
2093
|
+
const filepath = resolve10(root, this.config.ignoreFile);
|
|
1626
2094
|
writeGeneratedFile(filepath, features.ignorePatterns.join(`
|
|
1627
2095
|
`) + `
|
|
1628
2096
|
`);
|
|
1629
2097
|
filesWritten.push(filepath);
|
|
1630
2098
|
}
|
|
1631
2099
|
}
|
|
2100
|
+
if (effective.includes("models") && features.models) {
|
|
2101
|
+
const resolved = resolveModels(features.models, options.modelProfile, this.id);
|
|
2102
|
+
const guidance = generateModelGuidanceMarkdown(resolved);
|
|
2103
|
+
if (guidance) {
|
|
2104
|
+
ensureDir(configDir);
|
|
2105
|
+
const filepath = join14(configDir, "model-config.md");
|
|
2106
|
+
writeGeneratedFile(filepath, guidance);
|
|
2107
|
+
filesWritten.push(filepath);
|
|
2108
|
+
}
|
|
2109
|
+
}
|
|
1632
2110
|
return this.createResult(filesWritten, filesDeleted, warnings);
|
|
1633
2111
|
}
|
|
1634
2112
|
}
|
|
@@ -1822,14 +2300,29 @@ function findHunks(oldLines, newLines) {
|
|
|
1822
2300
|
let ni = 0;
|
|
1823
2301
|
while (oi < oldLines.length || ni < newLines.length) {
|
|
1824
2302
|
if (oi < oldLines.length && ni < newLines.length && oldLines[oi] === newLines[ni]) {
|
|
1825
|
-
changes.push({
|
|
2303
|
+
changes.push({
|
|
2304
|
+
type: " ",
|
|
2305
|
+
line: oldLines[oi] ?? "",
|
|
2306
|
+
oldIdx: oi,
|
|
2307
|
+
newIdx: ni
|
|
2308
|
+
});
|
|
1826
2309
|
oi++;
|
|
1827
2310
|
ni++;
|
|
1828
|
-
} else if (ni < newLines.length && (oi >= oldLines.length || !newLines.slice(ni).includes(oldLines[oi]))) {
|
|
1829
|
-
changes.push({
|
|
2311
|
+
} else if (ni < newLines.length && (oi >= oldLines.length || !newLines.slice(ni).includes(oldLines[oi] ?? ""))) {
|
|
2312
|
+
changes.push({
|
|
2313
|
+
type: "+",
|
|
2314
|
+
line: newLines[ni] ?? "",
|
|
2315
|
+
oldIdx: oi,
|
|
2316
|
+
newIdx: ni
|
|
2317
|
+
});
|
|
1830
2318
|
ni++;
|
|
1831
2319
|
} else {
|
|
1832
|
-
changes.push({
|
|
2320
|
+
changes.push({
|
|
2321
|
+
type: "-",
|
|
2322
|
+
line: oldLines[oi] ?? "",
|
|
2323
|
+
oldIdx: oi,
|
|
2324
|
+
newIdx: oi
|
|
2325
|
+
});
|
|
1833
2326
|
oi++;
|
|
1834
2327
|
}
|
|
1835
2328
|
}
|
|
@@ -1858,8 +2351,9 @@ function findHunks(oldLines, newLines) {
|
|
|
1858
2351
|
lines: []
|
|
1859
2352
|
};
|
|
1860
2353
|
for (let i = contextStart;i < changes.indexOf(change); i++) {
|
|
1861
|
-
|
|
1862
|
-
|
|
2354
|
+
const entry = changes[i];
|
|
2355
|
+
if (entry?.type === " ") {
|
|
2356
|
+
currentHunk.lines.push(` ${entry.line}`);
|
|
1863
2357
|
currentHunk.oldCount++;
|
|
1864
2358
|
currentHunk.newCount++;
|
|
1865
2359
|
}
|
|
@@ -1879,7 +2373,6 @@ function findHunks(oldLines, newLines) {
|
|
|
1879
2373
|
}
|
|
1880
2374
|
|
|
1881
2375
|
// src/cli/generate.ts
|
|
1882
|
-
init_config();
|
|
1883
2376
|
import { existsSync as existsSync8, readFileSync as readFileSync10 } from "fs";
|
|
1884
2377
|
import chalk from "chalk";
|
|
1885
2378
|
function runGenerate(projectRoot, options) {
|
|
@@ -1950,9 +2443,9 @@ function runGenerate(projectRoot, options) {
|
|
|
1950
2443
|
enabledFeatures,
|
|
1951
2444
|
deleteExisting: options.diff ? false : config.delete,
|
|
1952
2445
|
global: config.global,
|
|
1953
|
-
verbose: config.verbose
|
|
2446
|
+
verbose: config.verbose,
|
|
2447
|
+
modelProfile: config.modelProfile
|
|
1954
2448
|
};
|
|
1955
|
-
const preSnapshot = new Map;
|
|
1956
2449
|
try {
|
|
1957
2450
|
const result = target.generate(generateOptions);
|
|
1958
2451
|
allResults.push(result);
|