agentpacks 1.7.13 → 1.8.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/dist/api.js +48 -3658
- package/dist/cli/export-cmd.js +7 -1027
- package/dist/cli/generate.js +39 -2731
- package/dist/cli/import-cmd.js +19 -770
- package/dist/cli/info.js +4 -231
- package/dist/cli/init.js +9 -185
- package/dist/cli/install.js +4 -902
- package/dist/cli/login.js +6 -201
- package/dist/cli/models-explain.js +14 -1266
- package/dist/cli/pack/create.js +4 -146
- package/dist/cli/pack/enable.js +2 -65
- package/dist/cli/pack/list.js +5 -893
- package/dist/cli/pack/validate.js +4 -642
- package/dist/cli/publish.js +8 -679
- package/dist/cli/search.js +4 -209
- package/dist/core/config.d.ts +1 -1
- package/dist/core/config.js +1 -145
- package/dist/core/dependency-resolver.js +1 -126
- package/dist/core/feature-merger.js +3 -398
- package/dist/core/index.js +5 -1129
- package/dist/core/lockfile.js +2 -43
- package/dist/core/metarepo.js +1 -183
- package/dist/core/pack-loader.js +4 -841
- package/dist/core/profile-resolver.js +1 -110
- package/dist/exporters/cursor-plugin.js +6 -404
- package/dist/exporters/index.js +6 -404
- package/dist/features/agents.js +3 -161
- package/dist/features/commands.js +3 -161
- package/dist/features/hooks.js +3 -153
- package/dist/features/ignore.js +2 -43
- package/dist/features/index.js +4 -629
- package/dist/features/mcp.js +3 -143
- package/dist/features/models.js +3 -292
- package/dist/features/plugins.js +3 -139
- package/dist/features/rules.d.ts +0 -1
- package/dist/features/rules.js +3 -169
- package/dist/features/skills.js +3 -228
- package/dist/importers/claude-code.js +6 -195
- package/dist/importers/cursor.js +5 -355
- package/dist/importers/opencode.js +6 -346
- package/dist/importers/rulesync.js +5 -365
- package/dist/index.js +89 -4934
- package/dist/node/api.js +48 -3659
- package/dist/node/cli/export-cmd.js +7 -1028
- package/dist/node/cli/generate.js +39 -2732
- package/dist/node/cli/import-cmd.js +19 -771
- package/dist/node/cli/info.js +4 -232
- package/dist/node/cli/init.js +9 -186
- package/dist/node/cli/install.js +4 -903
- package/dist/node/cli/login.js +6 -202
- package/dist/node/cli/models-explain.js +14 -1267
- package/dist/node/cli/pack/create.js +4 -147
- package/dist/node/cli/pack/enable.js +2 -66
- package/dist/node/cli/pack/list.js +5 -894
- package/dist/node/cli/pack/validate.js +4 -643
- package/dist/node/cli/publish.js +8 -680
- package/dist/node/cli/search.js +4 -210
- package/dist/node/core/config.js +1 -146
- package/dist/node/core/dependency-resolver.js +1 -127
- package/dist/node/core/feature-merger.js +3 -399
- package/dist/node/core/index.js +5 -1130
- package/dist/node/core/lockfile.js +2 -44
- package/dist/node/core/metarepo.js +1 -184
- package/dist/node/core/pack-loader.js +4 -842
- package/dist/node/core/profile-resolver.js +1 -111
- package/dist/node/exporters/cursor-plugin.js +6 -405
- package/dist/node/exporters/index.js +6 -405
- package/dist/node/features/agents.js +3 -162
- package/dist/node/features/commands.js +3 -162
- package/dist/node/features/hooks.js +3 -154
- package/dist/node/features/ignore.js +2 -44
- package/dist/node/features/index.js +4 -630
- package/dist/node/features/mcp.js +3 -144
- package/dist/node/features/models.js +3 -293
- package/dist/node/features/plugins.js +3 -140
- package/dist/node/features/rules.js +3 -170
- package/dist/node/features/skills.js +3 -229
- package/dist/node/importers/claude-code.js +6 -196
- package/dist/node/importers/cursor.js +5 -356
- package/dist/node/importers/opencode.js +6 -347
- package/dist/node/importers/rulesync.js +5 -366
- package/dist/node/index.js +89 -4935
- package/dist/node/sources/git-ref.js +1 -56
- package/dist/node/sources/git.js +2 -222
- package/dist/node/sources/index.js +4 -714
- package/dist/node/sources/local.js +1 -24
- package/dist/node/sources/npm-ref.js +1 -56
- package/dist/node/sources/npm.js +2 -184
- package/dist/node/sources/registry-ref.js +1 -37
- package/dist/node/sources/registry.js +4 -355
- package/dist/node/targets/additional-targets.js +6 -587
- package/dist/node/targets/base-target.js +1 -23
- package/dist/node/targets/claude-code.js +6 -714
- package/dist/node/targets/codex-cli.js +3 -324
- package/dist/node/targets/copilot.js +5 -603
- package/dist/node/targets/cursor.js +6 -700
- package/dist/node/targets/gemini-cli.js +10 -319
- package/dist/node/targets/generic-md-target.js +6 -478
- package/dist/node/targets/index.js +32 -1873
- package/dist/node/targets/mistral-vibe.js +7 -661
- package/dist/node/targets/opencode.js +13 -723
- package/dist/node/targets/registry.js +32 -1864
- package/dist/node/utils/credentials.js +3 -38
- package/dist/node/utils/diff.js +5 -132
- package/dist/node/utils/filesystem.js +3 -124
- package/dist/node/utils/frontmatter.js +1 -24
- package/dist/node/utils/global.js +1 -53
- package/dist/node/utils/markdown.js +3 -30
- package/dist/node/utils/model-allowlist.js +1 -126
- package/dist/node/utils/model-guidance.js +2 -78
- package/dist/node/utils/registry-client.js +1 -142
- package/dist/node/utils/tarball.js +1 -49
- package/dist/sources/git-ref.js +1 -55
- package/dist/sources/git.js +2 -221
- package/dist/sources/index.js +4 -713
- package/dist/sources/local.js +1 -23
- package/dist/sources/npm-ref.js +1 -55
- package/dist/sources/npm.js +2 -183
- package/dist/sources/registry-ref.js +1 -36
- package/dist/sources/registry.js +4 -354
- package/dist/targets/additional-targets.js +6 -586
- package/dist/targets/base-target.js +1 -22
- package/dist/targets/claude-code.js +6 -713
- package/dist/targets/codex-cli.js +3 -323
- package/dist/targets/copilot.js +5 -602
- package/dist/targets/cursor.js +6 -699
- package/dist/targets/gemini-cli.js +10 -318
- package/dist/targets/generic-md-target.js +6 -477
- package/dist/targets/index.d.ts +0 -1
- package/dist/targets/index.js +32 -1872
- package/dist/targets/mistral-vibe.js +7 -660
- package/dist/targets/opencode.js +13 -722
- package/dist/targets/registry.js +32 -1863
- package/dist/utils/credentials.js +3 -37
- package/dist/utils/diff.js +5 -131
- package/dist/utils/filesystem.js +3 -123
- package/dist/utils/frontmatter.js +1 -23
- package/dist/utils/global.js +1 -52
- package/dist/utils/markdown.js +3 -29
- package/dist/utils/model-allowlist.js +1 -125
- package/dist/utils/model-guidance.js +2 -77
- package/dist/utils/registry-client.js +1 -141
- package/dist/utils/tarball.js +1 -48
- package/package.json +4 -16
- package/dist/node/targets/agents-md.js +0 -211
- package/dist/targets/agents-md.d.ts +0 -13
- package/dist/targets/agents-md.js +0 -211
package/dist/api.js
CHANGED
|
@@ -1,3675 +1,65 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"augmentcode",
|
|
27
|
-
"windsurf",
|
|
28
|
-
"warp",
|
|
29
|
-
"replit",
|
|
30
|
-
"zed"
|
|
31
|
-
];
|
|
32
|
-
var FEATURE_IDS = [
|
|
33
|
-
"rules",
|
|
34
|
-
"commands",
|
|
35
|
-
"agents",
|
|
36
|
-
"skills",
|
|
37
|
-
"hooks",
|
|
38
|
-
"plugins",
|
|
39
|
-
"mcp",
|
|
40
|
-
"ignore",
|
|
41
|
-
"models"
|
|
42
|
-
];
|
|
43
|
-
var REPO_MODES = ["repo", "monorepo", "metarepo"];
|
|
44
|
-
var PackManifestSchema = z.object({
|
|
45
|
-
name: z.string().min(1),
|
|
46
|
-
version: z.string().default("1.0.0"),
|
|
47
|
-
description: z.string().default(""),
|
|
48
|
-
author: z.union([
|
|
49
|
-
z.string(),
|
|
50
|
-
z.object({ name: z.string(), email: z.string().optional() })
|
|
51
|
-
]).optional(),
|
|
52
|
-
homepage: z.string().optional(),
|
|
53
|
-
repository: z.union([
|
|
54
|
-
z.string(),
|
|
55
|
-
z.object({ url: z.string(), type: z.string().optional() })
|
|
56
|
-
]).optional(),
|
|
57
|
-
license: z.string().optional(),
|
|
58
|
-
logo: z.string().optional(),
|
|
59
|
-
tags: z.array(z.string()).default([]),
|
|
60
|
-
dependencies: z.array(z.string()).default([]),
|
|
61
|
-
conflicts: z.array(z.string()).default([]),
|
|
62
|
-
targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
|
|
63
|
-
features: z.union([z.literal("*"), z.array(z.string())]).default("*")
|
|
64
|
-
});
|
|
65
|
-
var FeaturesSchema = z.union([
|
|
66
|
-
z.literal("*"),
|
|
67
|
-
z.array(z.string()),
|
|
68
|
-
z.record(z.string(), z.union([z.literal("*"), z.array(z.string())]))
|
|
69
|
-
]);
|
|
70
|
-
var WorkspaceConfigSchema = z.object({
|
|
71
|
-
$schema: z.string().optional(),
|
|
72
|
-
packs: z.array(z.string()).default(["./packs/default"]),
|
|
73
|
-
disabled: z.array(z.string()).default([]),
|
|
74
|
-
targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
|
|
75
|
-
features: FeaturesSchema.default("*"),
|
|
76
|
-
mode: z.enum(REPO_MODES).default("repo"),
|
|
77
|
-
baseDirs: z.array(z.string()).default(["."]),
|
|
78
|
-
global: z.boolean().default(false),
|
|
79
|
-
delete: z.boolean().default(true),
|
|
80
|
-
verbose: z.boolean().default(false),
|
|
81
|
-
silent: z.boolean().default(false),
|
|
82
|
-
overrides: z.record(z.string(), z.record(z.string(), z.string())).default({}),
|
|
83
|
-
sources: z.array(z.object({
|
|
84
|
-
source: z.string(),
|
|
85
|
-
packs: z.array(z.string()).optional(),
|
|
86
|
-
skills: z.array(z.string()).optional()
|
|
87
|
-
})).default([]),
|
|
88
|
-
modelProfile: z.string().optional()
|
|
89
|
-
});
|
|
90
|
-
var CONFIG_FILES = ["agentpacks.local.jsonc", "agentpacks.jsonc"];
|
|
91
|
-
function loadWorkspaceConfig(projectRoot) {
|
|
92
|
-
for (const filename of CONFIG_FILES) {
|
|
93
|
-
const filepath = resolve(projectRoot, filename);
|
|
94
|
-
if (existsSync(filepath)) {
|
|
95
|
-
const raw = readFileSync(filepath, "utf-8");
|
|
96
|
-
const parsed = parseJsonc(raw);
|
|
97
|
-
return WorkspaceConfigSchema.parse(parsed);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
return WorkspaceConfigSchema.parse({});
|
|
101
|
-
}
|
|
102
|
-
function loadPackManifest(packDir) {
|
|
103
|
-
const filepath = resolve(packDir, "pack.json");
|
|
104
|
-
if (!existsSync(filepath)) {
|
|
105
|
-
const dirName = packDir.split("/").pop() ?? "unknown";
|
|
106
|
-
return PackManifestSchema.parse({ name: dirName });
|
|
107
|
-
}
|
|
108
|
-
const raw = readFileSync(filepath, "utf-8");
|
|
109
|
-
const parsed = JSON.parse(raw);
|
|
110
|
-
return PackManifestSchema.parse(parsed);
|
|
111
|
-
}
|
|
112
|
-
function resolveFeatures(config, targetId) {
|
|
113
|
-
const { features } = config;
|
|
114
|
-
if (features === "*") {
|
|
115
|
-
return [...FEATURE_IDS];
|
|
116
|
-
}
|
|
117
|
-
if (Array.isArray(features)) {
|
|
118
|
-
if (features.includes("*"))
|
|
119
|
-
return [...FEATURE_IDS];
|
|
120
|
-
return features.filter((f) => FEATURE_IDS.includes(f));
|
|
121
|
-
}
|
|
122
|
-
const targetFeatures = features[targetId];
|
|
123
|
-
if (!targetFeatures)
|
|
124
|
-
return [];
|
|
125
|
-
if (targetFeatures === "*")
|
|
126
|
-
return [...FEATURE_IDS];
|
|
127
|
-
if (Array.isArray(targetFeatures) && targetFeatures.includes("*"))
|
|
128
|
-
return [...FEATURE_IDS];
|
|
129
|
-
return targetFeatures.filter((f) => FEATURE_IDS.includes(f));
|
|
130
|
-
}
|
|
131
|
-
function resolveTargets(config) {
|
|
132
|
-
if (config.targets === "*")
|
|
133
|
-
return [...TARGET_IDS];
|
|
134
|
-
return config.targets;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// src/core/dependency-resolver.ts
|
|
138
|
-
function buildDependencyGraph(manifests) {
|
|
139
|
-
const graph = new Map;
|
|
140
|
-
for (const m of manifests) {
|
|
141
|
-
graph.set(m.name, {
|
|
142
|
-
name: m.name,
|
|
143
|
-
manifest: m,
|
|
144
|
-
dependencies: m.dependencies,
|
|
145
|
-
conflicts: m.conflicts
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
return graph;
|
|
149
|
-
}
|
|
150
|
-
function resolveDependencies(manifests) {
|
|
151
|
-
const graph = buildDependencyGraph(manifests);
|
|
152
|
-
const allNames = new Set(graph.keys());
|
|
153
|
-
const missingDeps = [];
|
|
154
|
-
for (const [name, node] of graph) {
|
|
155
|
-
for (const dep of node.dependencies) {
|
|
156
|
-
if (!allNames.has(dep)) {
|
|
157
|
-
missingDeps.push([name, dep]);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
const { sorted, cycles } = topologicalSort(graph);
|
|
162
|
-
const conflictPairs = detectConflicts(graph);
|
|
163
|
-
const ok = cycles.length === 0 && conflictPairs.length === 0 && missingDeps.length === 0;
|
|
164
|
-
return { sorted, cycles, conflictPairs, missingDeps, ok };
|
|
165
|
-
}
|
|
166
|
-
function topologicalSort(graph) {
|
|
167
|
-
const inDegree = new Map;
|
|
168
|
-
for (const name of graph.keys()) {
|
|
169
|
-
inDegree.set(name, 0);
|
|
170
|
-
}
|
|
171
|
-
for (const [, node] of graph) {
|
|
172
|
-
for (const dep of node.dependencies) {
|
|
173
|
-
if (graph.has(dep)) {
|
|
174
|
-
inDegree.set(dep, (inDegree.get(dep) ?? 0) + 1);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
const queue = [];
|
|
179
|
-
for (const [name, degree] of inDegree) {
|
|
180
|
-
if (degree === 0)
|
|
181
|
-
queue.push(name);
|
|
182
|
-
}
|
|
183
|
-
const sorted = [];
|
|
184
|
-
while (queue.length > 0) {
|
|
185
|
-
const current = queue.shift();
|
|
186
|
-
if (!current)
|
|
187
|
-
continue;
|
|
188
|
-
sorted.push(current);
|
|
189
|
-
const node = graph.get(current);
|
|
190
|
-
if (!node)
|
|
191
|
-
continue;
|
|
192
|
-
for (const dep of node.dependencies) {
|
|
193
|
-
if (!graph.has(dep))
|
|
194
|
-
continue;
|
|
195
|
-
const newDegree = (inDegree.get(dep) ?? 1) - 1;
|
|
196
|
-
inDegree.set(dep, newDegree);
|
|
197
|
-
if (newDegree === 0) {
|
|
198
|
-
queue.push(dep);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
const cycles = [];
|
|
203
|
-
if (sorted.length < graph.size) {
|
|
204
|
-
const remaining = new Set;
|
|
205
|
-
for (const name of graph.keys()) {
|
|
206
|
-
if (!sorted.includes(name))
|
|
207
|
-
remaining.add(name);
|
|
208
|
-
}
|
|
209
|
-
const visited = new Set;
|
|
210
|
-
for (const start of remaining) {
|
|
211
|
-
if (visited.has(start))
|
|
212
|
-
continue;
|
|
213
|
-
const cycle = traceCycle(start, graph, remaining);
|
|
214
|
-
if (cycle.length > 0) {
|
|
215
|
-
cycles.push(cycle);
|
|
216
|
-
for (const n of cycle)
|
|
217
|
-
visited.add(n);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
return { sorted: sorted.reverse(), cycles };
|
|
222
|
-
}
|
|
223
|
-
function traceCycle(start, graph, remaining) {
|
|
224
|
-
const path = [];
|
|
225
|
-
const pathSet = new Set;
|
|
226
|
-
let current = start;
|
|
227
|
-
while (current && !pathSet.has(current)) {
|
|
228
|
-
path.push(current);
|
|
229
|
-
pathSet.add(current);
|
|
230
|
-
const node = graph.get(current);
|
|
231
|
-
if (!node)
|
|
232
|
-
break;
|
|
233
|
-
current = node.dependencies.find((d) => remaining.has(d) && graph.has(d));
|
|
234
|
-
}
|
|
235
|
-
if (current && pathSet.has(current)) {
|
|
236
|
-
const cycleStart = path.indexOf(current);
|
|
237
|
-
return path.slice(cycleStart);
|
|
238
|
-
}
|
|
239
|
-
return path;
|
|
240
|
-
}
|
|
241
|
-
function detectConflicts(graph) {
|
|
242
|
-
const conflicts = [];
|
|
243
|
-
const seen = new Set;
|
|
244
|
-
for (const [name, node] of graph) {
|
|
245
|
-
for (const conflict of node.conflicts) {
|
|
246
|
-
if (graph.has(conflict)) {
|
|
247
|
-
const key = [name, conflict].sort().join(":");
|
|
248
|
-
if (!seen.has(key)) {
|
|
249
|
-
seen.add(key);
|
|
250
|
-
conflicts.push([name, conflict]);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
return conflicts;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// src/utils/filesystem.ts
|
|
259
|
-
import {
|
|
260
|
-
existsSync as existsSync2,
|
|
261
|
-
mkdirSync,
|
|
262
|
-
readdirSync,
|
|
263
|
-
readFileSync as readFileSync2,
|
|
264
|
-
rmSync,
|
|
265
|
-
statSync,
|
|
266
|
-
writeFileSync
|
|
267
|
-
} from "fs";
|
|
268
|
-
import { dirname, join, relative } from "path";
|
|
269
|
-
var GENERATED_HEADER_MD = "<!-- Generated by agentpacks. DO NOT EDIT. -->";
|
|
270
|
-
var GENERATED_HEADER_JSON = "// Generated by agentpacks. DO NOT EDIT.";
|
|
271
|
-
var GENERATED_HEADER_JS = "// Generated by agentpacks. DO NOT EDIT.";
|
|
272
|
-
function writeGeneratedFile(filepath, content, options = {}) {
|
|
273
|
-
const { header = true, type } = options;
|
|
274
|
-
const ext = type ?? inferFileType(filepath);
|
|
275
|
-
ensureDir(dirname(filepath));
|
|
276
|
-
let output = content;
|
|
277
|
-
if (header) {
|
|
278
|
-
const headerComment = getHeader(ext);
|
|
279
|
-
if (headerComment) {
|
|
280
|
-
output = `${headerComment}
|
|
281
|
-
${content}`;
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
writeFileSync(filepath, output, "utf-8");
|
|
285
|
-
}
|
|
286
|
-
function writeGeneratedJson(filepath, data, options = {}) {
|
|
287
|
-
const json = JSON.stringify(data, null, 2);
|
|
288
|
-
writeGeneratedFile(filepath, json + `
|
|
289
|
-
`, { ...options, type: "json" });
|
|
290
|
-
}
|
|
291
|
-
function readFileOrNull(filepath) {
|
|
292
|
-
if (!existsSync2(filepath))
|
|
293
|
-
return null;
|
|
294
|
-
return readFileSync2(filepath, "utf-8");
|
|
295
|
-
}
|
|
296
|
-
function readJsonOrNull(filepath) {
|
|
297
|
-
const content = readFileOrNull(filepath);
|
|
298
|
-
if (content === null)
|
|
299
|
-
return null;
|
|
300
|
-
return JSON.parse(content);
|
|
301
|
-
}
|
|
302
|
-
function ensureDir(dirPath) {
|
|
303
|
-
if (!existsSync2(dirPath)) {
|
|
304
|
-
mkdirSync(dirPath, { recursive: true });
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
function removeIfExists(targetPath) {
|
|
308
|
-
if (existsSync2(targetPath)) {
|
|
309
|
-
rmSync(targetPath, { recursive: true, force: true });
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
function listFiles(dirPath, options = {}) {
|
|
313
|
-
const { extension, recursive = false } = options;
|
|
314
|
-
if (!existsSync2(dirPath))
|
|
315
|
-
return [];
|
|
316
|
-
const results = [];
|
|
317
|
-
const entries = readdirSync(dirPath);
|
|
318
|
-
for (const entry of entries) {
|
|
319
|
-
const fullPath = join(dirPath, entry);
|
|
320
|
-
const stat = statSync(fullPath);
|
|
321
|
-
if (stat.isDirectory() && recursive) {
|
|
322
|
-
results.push(...listFiles(fullPath, options));
|
|
323
|
-
} else if (stat.isFile()) {
|
|
324
|
-
if (!extension || entry.endsWith(extension)) {
|
|
325
|
-
results.push(fullPath);
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
return results;
|
|
330
|
-
}
|
|
331
|
-
function listDirs(dirPath) {
|
|
332
|
-
if (!existsSync2(dirPath))
|
|
333
|
-
return [];
|
|
334
|
-
return readdirSync(dirPath).map((entry) => join(dirPath, entry)).filter((fullPath) => statSync(fullPath).isDirectory());
|
|
335
|
-
}
|
|
336
|
-
function relPath(projectRoot, filepath) {
|
|
337
|
-
return relative(projectRoot, filepath);
|
|
338
|
-
}
|
|
339
|
-
function isGeneratedFile(filepath) {
|
|
340
|
-
const content = readFileOrNull(filepath);
|
|
341
|
-
if (!content)
|
|
342
|
-
return false;
|
|
343
|
-
return content.startsWith(GENERATED_HEADER_MD) || content.startsWith(GENERATED_HEADER_JSON) || content.startsWith(GENERATED_HEADER_JS);
|
|
344
|
-
}
|
|
345
|
-
function inferFileType(filepath) {
|
|
346
|
-
if (filepath.endsWith(".json") || filepath.endsWith(".jsonc"))
|
|
347
|
-
return "json";
|
|
348
|
-
if (filepath.endsWith(".ts") || filepath.endsWith(".mts"))
|
|
349
|
-
return "ts";
|
|
350
|
-
if (filepath.endsWith(".js") || filepath.endsWith(".mjs"))
|
|
351
|
-
return "js";
|
|
352
|
-
return "md";
|
|
353
|
-
}
|
|
354
|
-
function getHeader(type) {
|
|
355
|
-
switch (type) {
|
|
356
|
-
case "md":
|
|
357
|
-
return GENERATED_HEADER_MD;
|
|
358
|
-
case "json":
|
|
359
|
-
return GENERATED_HEADER_JSON;
|
|
360
|
-
case "js":
|
|
361
|
-
case "ts":
|
|
362
|
-
return GENERATED_HEADER_JS;
|
|
363
|
-
default:
|
|
364
|
-
return null;
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
// src/features/models.ts
|
|
369
|
-
import { join as join2 } from "path";
|
|
370
|
-
import { z as z2 } from "zod";
|
|
371
|
-
var SECRET_PATTERNS = [
|
|
372
|
-
/["']api[_-]?key["']\s*:/i,
|
|
373
|
-
/["']apiKey["']\s*:/i,
|
|
374
|
-
/["']secret["']\s*:/i,
|
|
375
|
-
/["']password["']\s*:/i,
|
|
376
|
-
/["'](?:auth_token|access_token|bearer_token)["']\s*:/i,
|
|
377
|
-
/["']private[_-]?key["']\s*:/i,
|
|
378
|
-
/-----BEGIN\s+(RSA|EC|DSA|OPENSSH|PGP)\s+PRIVATE\s+KEY-----/,
|
|
379
|
-
/sk-[a-zA-Z0-9]{20,}/,
|
|
380
|
-
/Bearer\s+[a-zA-Z0-9._-]{20,}/
|
|
381
|
-
];
|
|
382
|
-
var AgentModelSchema = z2.object({
|
|
383
|
-
model: z2.string(),
|
|
384
|
-
temperature: z2.number().min(0).max(2).optional(),
|
|
385
|
-
top_p: z2.number().min(0).max(1).optional()
|
|
386
|
-
});
|
|
387
|
-
var ModelProfileSchema = z2.object({
|
|
388
|
-
extends: z2.string().optional(),
|
|
389
|
-
description: z2.string().optional(),
|
|
390
|
-
default: z2.string().optional(),
|
|
391
|
-
small: z2.string().optional(),
|
|
392
|
-
agents: z2.record(z2.string(), AgentModelSchema).optional()
|
|
393
|
-
});
|
|
394
|
-
var RoutingConditionSchema = z2.object({
|
|
395
|
-
complexity: z2.enum(["low", "medium", "high", "critical"]).optional().describe("Task complexity level"),
|
|
396
|
-
urgency: z2.enum(["low", "normal", "high"]).optional().describe("Time sensitivity"),
|
|
397
|
-
budget: z2.enum(["minimal", "standard", "premium"]).optional().describe("Cost/token budget tier"),
|
|
398
|
-
contextWindowNeed: z2.enum(["small", "medium", "large", "max"]).optional().describe("Required context window size"),
|
|
399
|
-
toolUseIntensity: z2.enum(["none", "light", "heavy"]).optional().describe("Expected tool/function calling intensity")
|
|
400
|
-
});
|
|
401
|
-
var RoutingRuleSchema = z2.object({
|
|
402
|
-
when: z2.record(z2.string(), z2.string()),
|
|
403
|
-
use: z2.string(),
|
|
404
|
-
description: z2.string().optional(),
|
|
405
|
-
priority: z2.number().optional()
|
|
406
|
-
});
|
|
407
|
-
var ProviderModelSchema = z2.object({
|
|
408
|
-
options: z2.record(z2.string(), z2.unknown()).optional(),
|
|
409
|
-
variants: z2.record(z2.string(), z2.record(z2.string(), z2.unknown())).optional()
|
|
410
|
-
});
|
|
411
|
-
var ProviderConfigSchema = z2.object({
|
|
412
|
-
options: z2.record(z2.string(), z2.unknown()).optional(),
|
|
413
|
-
models: z2.record(z2.string(), ProviderModelSchema).optional()
|
|
414
|
-
});
|
|
415
|
-
var ModelsSchema = z2.object({
|
|
416
|
-
default: z2.string().optional(),
|
|
417
|
-
small: z2.string().optional(),
|
|
418
|
-
agents: z2.record(z2.string(), AgentModelSchema).optional(),
|
|
419
|
-
profiles: z2.record(z2.string(), ModelProfileSchema).optional(),
|
|
420
|
-
providers: z2.record(z2.string(), ProviderConfigSchema).optional(),
|
|
421
|
-
routing: z2.array(RoutingRuleSchema).optional(),
|
|
422
|
-
overrides: z2.record(z2.string(), z2.object({
|
|
423
|
-
default: z2.string().optional(),
|
|
424
|
-
small: z2.string().optional(),
|
|
425
|
-
agents: z2.record(z2.string(), AgentModelSchema).optional()
|
|
426
|
-
})).optional()
|
|
427
|
-
});
|
|
428
|
-
function parseModels(packDir, packName) {
|
|
429
|
-
const modelsPath = join2(packDir, "models.json");
|
|
430
|
-
const raw = readJsonOrNull(modelsPath);
|
|
431
|
-
if (!raw)
|
|
432
|
-
return null;
|
|
433
|
-
const parsed = ModelsSchema.parse(raw);
|
|
434
|
-
return {
|
|
435
|
-
packName,
|
|
436
|
-
sourcePath: modelsPath,
|
|
437
|
-
config: parsed
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
function mergeModelsConfigs(configs) {
|
|
441
|
-
const warnings = [];
|
|
442
|
-
const result = {};
|
|
443
|
-
for (const entry of configs) {
|
|
444
|
-
const { config, packName } = entry;
|
|
445
|
-
if (config.default !== undefined && result.default === undefined) {
|
|
446
|
-
result.default = config.default;
|
|
447
|
-
} else if (config.default !== undefined && result.default !== undefined) {
|
|
448
|
-
warnings.push(`Models "default" from pack "${packName}" skipped (already defined).`);
|
|
449
|
-
}
|
|
450
|
-
if (config.small !== undefined && result.small === undefined) {
|
|
451
|
-
result.small = config.small;
|
|
452
|
-
} else if (config.small !== undefined && result.small !== undefined) {
|
|
453
|
-
warnings.push(`Models "small" from pack "${packName}" skipped (already defined).`);
|
|
454
|
-
}
|
|
455
|
-
if (config.agents) {
|
|
456
|
-
if (!result.agents)
|
|
457
|
-
result.agents = {};
|
|
458
|
-
for (const [name, assignment] of Object.entries(config.agents)) {
|
|
459
|
-
if (name in result.agents) {
|
|
460
|
-
warnings.push(`Models agent "${name}" from pack "${packName}" skipped (already defined).`);
|
|
461
|
-
continue;
|
|
462
|
-
}
|
|
463
|
-
result.agents[name] = assignment;
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
if (config.profiles) {
|
|
467
|
-
if (!result.profiles)
|
|
468
|
-
result.profiles = {};
|
|
469
|
-
for (const [name, profile] of Object.entries(config.profiles)) {
|
|
470
|
-
if (name in result.profiles) {
|
|
471
|
-
warnings.push(`Models profile "${name}" from pack "${packName}" skipped (already defined).`);
|
|
472
|
-
continue;
|
|
473
|
-
}
|
|
474
|
-
result.profiles[name] = profile;
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
if (config.providers) {
|
|
478
|
-
if (!result.providers)
|
|
479
|
-
result.providers = {};
|
|
480
|
-
for (const [providerName, providerConfig] of Object.entries(config.providers)) {
|
|
481
|
-
if (!(providerName in result.providers)) {
|
|
482
|
-
result.providers[providerName] = providerConfig;
|
|
483
|
-
} else {
|
|
484
|
-
const existing = result.providers[providerName];
|
|
485
|
-
if (!existing) {
|
|
486
|
-
result.providers[providerName] = providerConfig;
|
|
487
|
-
continue;
|
|
488
|
-
}
|
|
489
|
-
if (providerConfig.options) {
|
|
490
|
-
existing.options = {
|
|
491
|
-
...providerConfig.options,
|
|
492
|
-
...existing.options
|
|
493
|
-
};
|
|
494
|
-
}
|
|
495
|
-
if (providerConfig.models) {
|
|
496
|
-
if (!existing.models)
|
|
497
|
-
existing.models = {};
|
|
498
|
-
for (const [modelName, modelConfig] of Object.entries(providerConfig.models)) {
|
|
499
|
-
if (!(modelName in existing.models)) {
|
|
500
|
-
existing.models[modelName] = modelConfig;
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
if (config.routing) {
|
|
508
|
-
if (!result.routing)
|
|
509
|
-
result.routing = [];
|
|
510
|
-
result.routing.push(...config.routing);
|
|
511
|
-
}
|
|
512
|
-
if (config.overrides) {
|
|
513
|
-
if (!result.overrides)
|
|
514
|
-
result.overrides = {};
|
|
515
|
-
for (const [targetId, override] of Object.entries(config.overrides)) {
|
|
516
|
-
if (targetId in result.overrides) {
|
|
517
|
-
warnings.push(`Models override for target "${targetId}" from pack "${packName}" skipped (already defined).`);
|
|
518
|
-
continue;
|
|
519
|
-
}
|
|
520
|
-
result.overrides[targetId] = override;
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
return { config: result, warnings };
|
|
525
|
-
}
|
|
526
|
-
function scanModelsForSecrets(config) {
|
|
527
|
-
const warnings = [];
|
|
528
|
-
const json = JSON.stringify(config);
|
|
529
|
-
for (const pattern of SECRET_PATTERNS) {
|
|
530
|
-
if (pattern.test(json)) {
|
|
531
|
-
warnings.push(`Potential secret detected in models.json matching pattern: ${pattern.source}`);
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
return warnings;
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
// src/core/feature-merger.ts
|
|
538
|
-
class FeatureMerger {
|
|
539
|
-
packs;
|
|
540
|
-
warnings = [];
|
|
541
|
-
constructor(packs) {
|
|
542
|
-
this.packs = packs;
|
|
543
|
-
}
|
|
544
|
-
merge() {
|
|
545
|
-
this.warnings = [];
|
|
546
|
-
const features = {
|
|
547
|
-
rules: this.mergeRules(),
|
|
548
|
-
commands: this.mergeByName("commands"),
|
|
549
|
-
agents: this.mergeByName("agents"),
|
|
550
|
-
skills: this.mergeByName("skills"),
|
|
551
|
-
hooks: this.mergeHooks(),
|
|
552
|
-
plugins: this.mergePlugins(),
|
|
553
|
-
mcpServers: this.mergeMcp(),
|
|
554
|
-
ignorePatterns: this.mergeIgnore(),
|
|
555
|
-
models: this.mergeModels()
|
|
556
|
-
};
|
|
557
|
-
return { features, warnings: this.warnings };
|
|
558
|
-
}
|
|
559
|
-
mergeRules() {
|
|
560
|
-
const seen = new Map;
|
|
561
|
-
const result = [];
|
|
562
|
-
for (const pack of this.packs) {
|
|
563
|
-
for (const rule of pack.rules) {
|
|
564
|
-
const existing = seen.get(rule.name);
|
|
565
|
-
if (existing) {
|
|
566
|
-
this.warnings.push(`Rule "${rule.name}" from pack "${rule.packName}" skipped (already defined by "${existing}").`);
|
|
567
|
-
continue;
|
|
568
|
-
}
|
|
569
|
-
seen.set(rule.name, rule.packName);
|
|
570
|
-
result.push(rule);
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
return result;
|
|
574
|
-
}
|
|
575
|
-
mergeByName(featureKey) {
|
|
576
|
-
const seen = new Map;
|
|
577
|
-
const result = [];
|
|
578
|
-
for (const pack of this.packs) {
|
|
579
|
-
const items = pack[featureKey];
|
|
580
|
-
for (const item of items) {
|
|
581
|
-
const existing = seen.get(item.name);
|
|
582
|
-
if (existing) {
|
|
583
|
-
this.warnings.push(`${featureKey.slice(0, -1)} "${item.name}" from pack "${item.packName}" skipped (already defined by "${existing}").`);
|
|
584
|
-
continue;
|
|
585
|
-
}
|
|
586
|
-
seen.set(item.name, item.packName);
|
|
587
|
-
result.push(item);
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
return result;
|
|
591
|
-
}
|
|
592
|
-
mergeHooks() {
|
|
593
|
-
return this.packs.map((p) => p.hooks).filter((h) => h !== null);
|
|
594
|
-
}
|
|
595
|
-
mergePlugins() {
|
|
596
|
-
const seen = new Map;
|
|
597
|
-
const result = [];
|
|
598
|
-
for (const pack of this.packs) {
|
|
599
|
-
for (const plugin of pack.plugins) {
|
|
600
|
-
const key = `${plugin.name}.${plugin.extension}`;
|
|
601
|
-
const existing = seen.get(key);
|
|
602
|
-
if (existing) {
|
|
603
|
-
this.warnings.push(`Plugin "${key}" from pack "${plugin.packName}" skipped (already defined by "${existing}").`);
|
|
604
|
-
continue;
|
|
605
|
-
}
|
|
606
|
-
seen.set(key, plugin.packName);
|
|
607
|
-
result.push(plugin);
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
return result;
|
|
611
|
-
}
|
|
612
|
-
mergeMcp() {
|
|
613
|
-
const servers = {};
|
|
614
|
-
for (const pack of this.packs) {
|
|
615
|
-
if (!pack.mcp)
|
|
616
|
-
continue;
|
|
617
|
-
for (const [name, entry] of Object.entries(pack.mcp.servers)) {
|
|
618
|
-
if (name in servers) {
|
|
619
|
-
this.warnings.push(`MCP server "${name}" from pack "${pack.manifest.name}" skipped (already defined).`);
|
|
620
|
-
continue;
|
|
621
|
-
}
|
|
622
|
-
servers[name] = entry;
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
return servers;
|
|
626
|
-
}
|
|
627
|
-
mergeIgnore() {
|
|
628
|
-
const seen = new Set;
|
|
629
|
-
const result = [];
|
|
630
|
-
for (const pack of this.packs) {
|
|
631
|
-
if (!pack.ignore)
|
|
632
|
-
continue;
|
|
633
|
-
for (const pattern of pack.ignore.patterns) {
|
|
634
|
-
if (!seen.has(pattern)) {
|
|
635
|
-
seen.add(pattern);
|
|
636
|
-
result.push(pattern);
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
return result;
|
|
641
|
-
}
|
|
642
|
-
mergeModels() {
|
|
643
|
-
const configs = this.packs.map((p) => p.models).filter((m) => m != null);
|
|
644
|
-
if (configs.length === 0)
|
|
645
|
-
return null;
|
|
646
|
-
const { config, warnings } = mergeModelsConfigs(configs);
|
|
647
|
-
this.warnings.push(...warnings);
|
|
648
|
-
return config;
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
// src/core/lockfile.ts
|
|
653
|
-
import { createHash } from "crypto";
|
|
654
|
-
import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
655
|
-
import { resolve as resolve2 } from "path";
|
|
656
|
-
var LOCKFILE_VERSION = 1;
|
|
657
|
-
var LOCKFILE_NAME = "agentpacks.lock";
|
|
658
|
-
function loadLockfile(projectRoot) {
|
|
659
|
-
const filepath = resolve2(projectRoot, LOCKFILE_NAME);
|
|
660
|
-
if (!existsSync3(filepath)) {
|
|
661
|
-
return { lockfileVersion: LOCKFILE_VERSION, sources: {} };
|
|
662
|
-
}
|
|
663
|
-
const raw = readFileSync3(filepath, "utf-8");
|
|
664
|
-
return JSON.parse(raw);
|
|
665
|
-
}
|
|
666
|
-
function saveLockfile(projectRoot, lockfile) {
|
|
667
|
-
const filepath = resolve2(projectRoot, LOCKFILE_NAME);
|
|
668
|
-
writeFileSync2(filepath, JSON.stringify(lockfile, null, 2) + `
|
|
669
|
-
`);
|
|
670
|
-
}
|
|
671
|
-
function getLockedSource(lockfile, sourceKey) {
|
|
672
|
-
return lockfile.sources[sourceKey];
|
|
673
|
-
}
|
|
674
|
-
function setLockedSource(lockfile, sourceKey, entry) {
|
|
675
|
-
lockfile.sources[sourceKey] = entry;
|
|
676
|
-
}
|
|
677
|
-
function computeIntegrity(content) {
|
|
678
|
-
const hash = createHash("sha256").update(content).digest("hex");
|
|
679
|
-
return `sha256-${hash}`;
|
|
680
|
-
}
|
|
681
|
-
function isLockfileFrozenValid(lockfile, sourceKeys) {
|
|
682
|
-
const missing = sourceKeys.filter((key) => !(key in lockfile.sources));
|
|
683
|
-
return { valid: missing.length === 0, missing };
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
// src/utils/frontmatter.ts
|
|
687
|
-
import matter from "gray-matter";
|
|
688
|
-
function parseFrontmatter(source) {
|
|
689
|
-
const { data, content } = matter(source);
|
|
690
|
-
return {
|
|
691
|
-
data,
|
|
692
|
-
content: content.trim(),
|
|
693
|
-
raw: source
|
|
694
|
-
};
|
|
695
|
-
}
|
|
696
|
-
function serializeFrontmatter(data, content) {
|
|
697
|
-
const filtered = Object.fromEntries(Object.entries(data).filter(([, v]) => v !== undefined));
|
|
698
|
-
if (Object.keys(filtered).length === 0) {
|
|
699
|
-
return content;
|
|
700
|
-
}
|
|
701
|
-
return matter.stringify(content, filtered);
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
// src/features/agents.ts
|
|
705
|
-
import { readFileSync as readFileSync4 } from "fs";
|
|
706
|
-
import { basename } from "path";
|
|
707
|
-
function parseAgents(agentsDir, packName) {
|
|
708
|
-
const files = listFiles(agentsDir, { extension: ".md" });
|
|
709
|
-
return files.map((filepath) => parseAgentFile(filepath, packName));
|
|
710
|
-
}
|
|
711
|
-
function parseAgentFile(filepath, packName) {
|
|
712
|
-
const raw = readFileSync4(filepath, "utf-8");
|
|
713
|
-
const { data, content } = parseFrontmatter(raw);
|
|
714
|
-
return {
|
|
715
|
-
name: data.name ?? basename(filepath, ".md"),
|
|
716
|
-
sourcePath: filepath,
|
|
717
|
-
packName,
|
|
718
|
-
meta: data,
|
|
719
|
-
content
|
|
720
|
-
};
|
|
721
|
-
}
|
|
722
|
-
function agentMatchesTarget(agent, targetId) {
|
|
723
|
-
const { targets } = agent.meta;
|
|
724
|
-
if (!targets || targets === "*")
|
|
725
|
-
return true;
|
|
726
|
-
if (Array.isArray(targets) && targets.includes("*"))
|
|
727
|
-
return true;
|
|
728
|
-
return Array.isArray(targets) && targets.includes(targetId);
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
// src/features/commands.ts
|
|
732
|
-
import { readFileSync as readFileSync5 } from "fs";
|
|
733
|
-
import { basename as basename2 } from "path";
|
|
734
|
-
function parseCommands(commandsDir, packName) {
|
|
735
|
-
const files = listFiles(commandsDir, { extension: ".md" });
|
|
736
|
-
return files.map((filepath) => parseCommandFile(filepath, packName));
|
|
737
|
-
}
|
|
738
|
-
function parseCommandFile(filepath, packName) {
|
|
739
|
-
const raw = readFileSync5(filepath, "utf-8");
|
|
740
|
-
const { data, content } = parseFrontmatter(raw);
|
|
741
|
-
return {
|
|
742
|
-
name: basename2(filepath, ".md"),
|
|
743
|
-
sourcePath: filepath,
|
|
744
|
-
packName,
|
|
745
|
-
meta: data,
|
|
746
|
-
content
|
|
747
|
-
};
|
|
748
|
-
}
|
|
749
|
-
function commandMatchesTarget(cmd, targetId) {
|
|
750
|
-
const { targets } = cmd.meta;
|
|
751
|
-
if (!targets || targets === "*")
|
|
752
|
-
return true;
|
|
753
|
-
if (Array.isArray(targets) && targets.includes("*"))
|
|
754
|
-
return true;
|
|
755
|
-
return Array.isArray(targets) && targets.includes(targetId);
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
// src/features/hooks.ts
|
|
759
|
-
import { join as join3 } from "path";
|
|
760
|
-
var TARGET_OVERRIDE_KEYS = ["cursor", "claudecode", "opencode"];
|
|
761
|
-
function parseHooks(packDir, packName) {
|
|
762
|
-
const hooksPath = join3(packDir, "hooks", "hooks.json");
|
|
763
|
-
const raw = readJsonOrNull(hooksPath);
|
|
764
|
-
if (!raw)
|
|
765
|
-
return null;
|
|
766
|
-
const shared = raw.hooks ?? {};
|
|
767
|
-
const targetOverrides = {};
|
|
768
|
-
for (const key of TARGET_OVERRIDE_KEYS) {
|
|
769
|
-
const override = raw[key];
|
|
770
|
-
if (override && typeof override === "object" && "hooks" in override && override.hooks) {
|
|
771
|
-
targetOverrides[key] = override.hooks;
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
return {
|
|
775
|
-
packName,
|
|
776
|
-
sourcePath: hooksPath,
|
|
777
|
-
version: raw.version,
|
|
778
|
-
shared,
|
|
779
|
-
targetOverrides
|
|
780
|
-
};
|
|
781
|
-
}
|
|
782
|
-
function resolveHooksForTarget(hooks, targetId) {
|
|
783
|
-
const merged = {};
|
|
784
|
-
for (const [event, entries] of Object.entries(hooks.shared)) {
|
|
785
|
-
merged[event] = [...entries];
|
|
786
|
-
}
|
|
787
|
-
const overrides = hooks.targetOverrides[targetId];
|
|
788
|
-
if (overrides) {
|
|
789
|
-
for (const [event, entries] of Object.entries(overrides)) {
|
|
790
|
-
merged[event] = [...merged[event] ?? [], ...entries];
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
return merged;
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
// src/features/ignore.ts
|
|
797
|
-
import { existsSync as existsSync4, readFileSync as readFileSync6 } from "fs";
|
|
798
|
-
import { join as join4 } from "path";
|
|
799
|
-
var IGNORE_FILES = ["ignore", ".aiignore"];
|
|
800
|
-
function parseIgnore(packDir, packName) {
|
|
801
|
-
for (const filename of IGNORE_FILES) {
|
|
802
|
-
const filepath = join4(packDir, filename);
|
|
803
|
-
if (existsSync4(filepath)) {
|
|
804
|
-
const raw = readFileSync6(filepath, "utf-8");
|
|
805
|
-
const patterns = parseIgnoreContent(raw);
|
|
806
|
-
return {
|
|
807
|
-
packName,
|
|
808
|
-
sourcePath: filepath,
|
|
809
|
-
patterns
|
|
810
|
-
};
|
|
811
|
-
}
|
|
812
|
-
}
|
|
813
|
-
return null;
|
|
814
|
-
}
|
|
815
|
-
function parseIgnoreContent(content) {
|
|
816
|
-
return content.split(`
|
|
817
|
-
`).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
818
|
-
}
|
|
819
|
-
function mergeIgnorePatterns(configs) {
|
|
820
|
-
const seen = new Set;
|
|
821
|
-
const result = [];
|
|
822
|
-
for (const config of configs) {
|
|
823
|
-
for (const pattern of config.patterns) {
|
|
824
|
-
if (!seen.has(pattern)) {
|
|
825
|
-
seen.add(pattern);
|
|
826
|
-
result.push(pattern);
|
|
827
|
-
}
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
return result;
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
// src/features/mcp.ts
|
|
834
|
-
import { join as join5 } from "path";
|
|
835
|
-
function parseMcp(packDir, packName) {
|
|
836
|
-
const mcpPath = join5(packDir, "mcp.json");
|
|
837
|
-
const raw = readJsonOrNull(mcpPath);
|
|
838
|
-
if (!raw?.mcpServers)
|
|
839
|
-
return null;
|
|
840
|
-
return {
|
|
841
|
-
packName,
|
|
842
|
-
sourcePath: mcpPath,
|
|
843
|
-
servers: raw.mcpServers
|
|
844
|
-
};
|
|
845
|
-
}
|
|
846
|
-
function mergeMcpConfigs(configs) {
|
|
847
|
-
const servers = {};
|
|
848
|
-
const warnings = [];
|
|
849
|
-
for (const config of configs) {
|
|
850
|
-
for (const [name, entry] of Object.entries(config.servers)) {
|
|
851
|
-
if (name in servers) {
|
|
852
|
-
warnings.push(`MCP server "${name}" from pack "${config.packName}" skipped (already defined).`);
|
|
853
|
-
continue;
|
|
854
|
-
}
|
|
855
|
-
servers[name] = entry;
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
return { servers, warnings };
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
// src/features/plugins.ts
|
|
862
|
-
import { existsSync as existsSync5, readFileSync as readFileSync7 } from "fs";
|
|
863
|
-
import { basename as basename3, join as join6 } from "path";
|
|
864
|
-
function parsePlugins(packDir, packName) {
|
|
865
|
-
const pluginsDir = join6(packDir, "plugins");
|
|
866
|
-
if (!existsSync5(pluginsDir))
|
|
867
|
-
return [];
|
|
868
|
-
const tsFiles = listFiles(pluginsDir, { extension: ".ts" });
|
|
869
|
-
const jsFiles = listFiles(pluginsDir, { extension: ".js" });
|
|
870
|
-
const allFiles = [...tsFiles, ...jsFiles];
|
|
871
|
-
return allFiles.map((filepath) => parsePluginFile(filepath, packName));
|
|
872
|
-
}
|
|
873
|
-
function parsePluginFile(filepath, packName) {
|
|
874
|
-
const content = readFileSync7(filepath, "utf-8");
|
|
875
|
-
const ext = filepath.endsWith(".ts") ? "ts" : "js";
|
|
876
|
-
return {
|
|
877
|
-
name: basename3(filepath, `.${ext}`),
|
|
878
|
-
sourcePath: filepath,
|
|
879
|
-
packName,
|
|
880
|
-
content,
|
|
881
|
-
extension: ext
|
|
882
|
-
};
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
// src/features/rules.ts
|
|
886
|
-
import { readFileSync as readFileSync8 } from "fs";
|
|
887
|
-
import { basename as basename4 } from "path";
|
|
888
|
-
function parseRules(rulesDir, packName) {
|
|
889
|
-
const files = listFiles(rulesDir, { extension: ".md" });
|
|
890
|
-
return files.map((filepath) => parseRuleFile(filepath, packName));
|
|
891
|
-
}
|
|
892
|
-
function parseRuleFile(filepath, packName) {
|
|
893
|
-
const raw = readFileSync8(filepath, "utf-8");
|
|
894
|
-
const { data, content } = parseFrontmatter(raw);
|
|
895
|
-
return {
|
|
896
|
-
name: basename4(filepath, ".md"),
|
|
897
|
-
sourcePath: filepath,
|
|
898
|
-
packName,
|
|
899
|
-
meta: data,
|
|
900
|
-
content
|
|
901
|
-
};
|
|
902
|
-
}
|
|
903
|
-
function ruleMatchesTarget(rule, targetId) {
|
|
904
|
-
const { targets } = rule.meta;
|
|
905
|
-
if (!targets || targets === "*")
|
|
906
|
-
return true;
|
|
907
|
-
if (Array.isArray(targets) && targets.includes("*"))
|
|
908
|
-
return true;
|
|
909
|
-
return Array.isArray(targets) && targets.includes(targetId);
|
|
910
|
-
}
|
|
911
|
-
function getRootRules(rules) {
|
|
912
|
-
return rules.filter((r) => r.meta.root === true);
|
|
913
|
-
}
|
|
914
|
-
function getDetailRules(rules) {
|
|
915
|
-
return rules.filter((r) => r.meta.root !== true);
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
// src/features/skills.ts
|
|
919
|
-
import { existsSync as existsSync6, readFileSync as readFileSync9 } from "fs";
|
|
920
|
-
import { basename as basename5, join as join7 } from "path";
|
|
921
|
-
var SKILL_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
922
|
-
var SKILL_NAME_MAX_LENGTH = 64;
|
|
923
|
-
function parseSkills(skillsDir, packName) {
|
|
924
|
-
const dirs = listDirs(skillsDir);
|
|
925
|
-
const skills = [];
|
|
926
|
-
for (const dir of dirs) {
|
|
927
|
-
const skillMd = join7(dir, "SKILL.md");
|
|
928
|
-
if (existsSync6(skillMd)) {
|
|
929
|
-
skills.push(parseSkillFile(skillMd, dir, packName));
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
return skills;
|
|
933
|
-
}
|
|
934
|
-
function parseSkillFile(filepath, skillDir, packName) {
|
|
935
|
-
const raw = readFileSync9(filepath, "utf-8");
|
|
936
|
-
const { data, content } = parseFrontmatter(raw);
|
|
937
|
-
return {
|
|
938
|
-
name: data.name ?? basename5(skillDir),
|
|
939
|
-
sourcePath: filepath,
|
|
940
|
-
sourceDir: skillDir,
|
|
941
|
-
packName,
|
|
942
|
-
meta: data,
|
|
943
|
-
content
|
|
944
|
-
};
|
|
945
|
-
}
|
|
946
|
-
function buildSkillFrontmatter(skill) {
|
|
947
|
-
return {
|
|
948
|
-
...skill.meta,
|
|
949
|
-
name: skill.name
|
|
950
|
-
};
|
|
951
|
-
}
|
|
952
|
-
function serializeSkill(skill) {
|
|
953
|
-
return serializeFrontmatter(buildSkillFrontmatter(skill), skill.content);
|
|
954
|
-
}
|
|
955
|
-
function normalizeImportedSkillMarkdown(source, skillName) {
|
|
956
|
-
const { data, content } = parseFrontmatter(source);
|
|
957
|
-
const normalized = {
|
|
958
|
-
...data,
|
|
959
|
-
name: skillName
|
|
960
|
-
};
|
|
961
|
-
let addedDescription = false;
|
|
962
|
-
const description = normalized.description;
|
|
963
|
-
if (typeof description !== "string" || description.trim().length === 0) {
|
|
964
|
-
normalized.description = `Imported skill: ${skillName}`;
|
|
965
|
-
addedDescription = true;
|
|
966
|
-
}
|
|
967
|
-
return {
|
|
968
|
-
content: serializeFrontmatter(normalized, content),
|
|
969
|
-
addedDescription
|
|
970
|
-
};
|
|
971
|
-
}
|
|
972
|
-
function validateAgentSkillsFrontmatter(skill) {
|
|
973
|
-
const errors = [];
|
|
974
|
-
const dirName = basename5(skill.sourceDir);
|
|
975
|
-
const declaredName = skill.meta.name;
|
|
976
|
-
if (typeof declaredName !== "string" || declaredName.trim().length === 0) {
|
|
977
|
-
errors.push('Missing required frontmatter field "name".');
|
|
978
|
-
} else {
|
|
979
|
-
if (declaredName.length > SKILL_NAME_MAX_LENGTH) {
|
|
980
|
-
errors.push(`Invalid "name": must be at most ${SKILL_NAME_MAX_LENGTH} characters.`);
|
|
981
|
-
}
|
|
982
|
-
if (!SKILL_NAME_PATTERN.test(declaredName)) {
|
|
983
|
-
errors.push('Invalid "name": use lowercase letters, numbers, and single hyphens only.');
|
|
984
|
-
}
|
|
985
|
-
if (declaredName !== dirName) {
|
|
986
|
-
errors.push(`Invalid "name": must match containing directory "${dirName}".`);
|
|
987
|
-
}
|
|
988
|
-
}
|
|
989
|
-
const description = skill.meta.description;
|
|
990
|
-
if (typeof description !== "string" || description.trim().length === 0) {
|
|
991
|
-
errors.push('Missing required frontmatter field "description".');
|
|
992
|
-
}
|
|
993
|
-
const allowedTools = skill.meta["allowed-tools"];
|
|
994
|
-
if (allowedTools !== undefined && (!Array.isArray(allowedTools) || allowedTools.some((tool) => typeof tool !== "string" || tool.length === 0))) {
|
|
995
|
-
errors.push('Invalid "allowed-tools": expected an array of non-empty strings.');
|
|
996
|
-
}
|
|
997
|
-
return errors;
|
|
998
|
-
}
|
|
999
|
-
function skillMatchesTarget(skill, targetId) {
|
|
1000
|
-
const { targets } = skill.meta;
|
|
1001
|
-
if (!targets || targets === "*")
|
|
1002
|
-
return true;
|
|
1003
|
-
if (Array.isArray(targets) && targets.includes("*"))
|
|
1004
|
-
return true;
|
|
1005
|
-
return Array.isArray(targets) && targets.includes(targetId);
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
// src/core/pack-loader.ts
|
|
1009
|
-
import { existsSync as existsSync7 } from "fs";
|
|
1010
|
-
import { isAbsolute, resolve as resolve3 } from "path";
|
|
1011
|
-
class PackLoader {
|
|
1012
|
-
projectRoot;
|
|
1013
|
-
config;
|
|
1014
|
-
constructor(projectRoot, config) {
|
|
1015
|
-
this.projectRoot = projectRoot;
|
|
1016
|
-
this.config = config;
|
|
1017
|
-
}
|
|
1018
|
-
loadAll() {
|
|
1019
|
-
const warnings = [];
|
|
1020
|
-
const packs = [];
|
|
1021
|
-
const disabledSet = new Set(this.config.disabled);
|
|
1022
|
-
for (const packRef of this.config.packs) {
|
|
1023
|
-
const packDir = this.resolvePackPath(packRef);
|
|
1024
|
-
if (!packDir) {
|
|
1025
|
-
warnings.push(`Pack "${packRef}" could not be resolved. Skipping.`);
|
|
1026
|
-
continue;
|
|
1027
|
-
}
|
|
1028
|
-
if (!existsSync7(packDir)) {
|
|
1029
|
-
warnings.push(`Pack directory "${packDir}" does not exist. Skipping.`);
|
|
1030
|
-
continue;
|
|
1031
|
-
}
|
|
1032
|
-
const manifest = loadPackManifest(packDir);
|
|
1033
|
-
if (disabledSet.has(manifest.name) || disabledSet.has(packRef)) {
|
|
1034
|
-
continue;
|
|
1035
|
-
}
|
|
1036
|
-
const loaded = this.loadPack(packDir, manifest);
|
|
1037
|
-
packs.push(loaded);
|
|
1038
|
-
}
|
|
1039
|
-
return { packs, warnings };
|
|
1040
|
-
}
|
|
1041
|
-
loadPack(packDir, manifest) {
|
|
1042
|
-
const name = manifest.name;
|
|
1043
|
-
const rulesDir = resolve3(packDir, "rules");
|
|
1044
|
-
const commandsDir = resolve3(packDir, "commands");
|
|
1045
|
-
const agentsDir = resolve3(packDir, "agents");
|
|
1046
|
-
const skillsDir = resolve3(packDir, "skills");
|
|
1047
|
-
return {
|
|
1048
|
-
manifest,
|
|
1049
|
-
directory: packDir,
|
|
1050
|
-
rules: existsSync7(rulesDir) ? parseRules(rulesDir, name) : [],
|
|
1051
|
-
commands: existsSync7(commandsDir) ? parseCommands(commandsDir, name) : [],
|
|
1052
|
-
agents: existsSync7(agentsDir) ? parseAgents(agentsDir, name) : [],
|
|
1053
|
-
skills: existsSync7(skillsDir) ? parseSkills(skillsDir, name) : [],
|
|
1054
|
-
hooks: parseHooks(packDir, name),
|
|
1055
|
-
plugins: parsePlugins(packDir, name),
|
|
1056
|
-
mcp: parseMcp(packDir, name),
|
|
1057
|
-
ignore: parseIgnore(packDir, name),
|
|
1058
|
-
models: parseModels(packDir, name)
|
|
1059
|
-
};
|
|
1060
|
-
}
|
|
1061
|
-
loadForBaseDir(baseDir) {
|
|
1062
|
-
const baseDirRoot = resolve3(this.projectRoot, baseDir);
|
|
1063
|
-
const localConfigPath = resolve3(baseDirRoot, "agentpacks.jsonc");
|
|
1064
|
-
if (!existsSync7(localConfigPath)) {
|
|
1065
|
-
return { packs: [], warnings: [] };
|
|
1066
|
-
}
|
|
1067
|
-
const localConfig = loadWorkspaceConfig(baseDirRoot);
|
|
1068
|
-
const loader = new PackLoader(baseDirRoot, localConfig);
|
|
1069
|
-
return loader.loadAll();
|
|
1070
|
-
}
|
|
1071
|
-
resolveCuratedPack(packRef) {
|
|
1072
|
-
const curatedDir = resolve3(this.projectRoot, ".agentpacks", ".curated");
|
|
1073
|
-
let packName = packRef;
|
|
1074
|
-
if (packName.startsWith("registry:"))
|
|
1075
|
-
packName = packName.slice(9);
|
|
1076
|
-
if (packName.startsWith("npm:"))
|
|
1077
|
-
packName = packName.slice(4);
|
|
1078
|
-
if (packName.startsWith("github:"))
|
|
1079
|
-
packName = packName.slice(7);
|
|
1080
|
-
if (packName.startsWith("@"))
|
|
1081
|
-
packName = packName.slice(1);
|
|
1082
|
-
if (packName.includes("/")) {
|
|
1083
|
-
const parts = packName.split("/");
|
|
1084
|
-
packName = packName.includes("@") ? parts.join("-") : parts[parts.length - 1] ?? packName;
|
|
1085
|
-
}
|
|
1086
|
-
const withoutVersion = packName.split("@")[0] ?? packName;
|
|
1087
|
-
packName = withoutVersion.split(":")[0] ?? withoutVersion;
|
|
1088
|
-
const resolved = resolve3(curatedDir, packName);
|
|
1089
|
-
return existsSync7(resolved) ? resolved : null;
|
|
1090
|
-
}
|
|
1091
|
-
resolvePackPath(packRef) {
|
|
1092
|
-
if (packRef.startsWith("./") || packRef.startsWith("../")) {
|
|
1093
|
-
return resolve3(this.projectRoot, packRef);
|
|
1094
|
-
}
|
|
1095
|
-
if (isAbsolute(packRef)) {
|
|
1096
|
-
return packRef;
|
|
1097
|
-
}
|
|
1098
|
-
if (packRef.startsWith("registry:")) {
|
|
1099
|
-
return this.resolveCuratedPack(packRef);
|
|
1100
|
-
}
|
|
1101
|
-
if (packRef.startsWith("@") || packRef.startsWith("npm:") || !packRef.includes("/")) {
|
|
1102
|
-
return this.resolveCuratedPack(packRef);
|
|
1103
|
-
}
|
|
1104
|
-
if (packRef.startsWith("github:") || packRef.includes("/")) {
|
|
1105
|
-
return this.resolveCuratedPack(packRef);
|
|
1106
|
-
}
|
|
1107
|
-
return resolve3(this.projectRoot, packRef);
|
|
1108
|
-
}
|
|
1109
|
-
}
|
|
1110
|
-
|
|
1111
|
-
// src/core/profile-resolver.ts
|
|
1112
|
-
function resolveModels(merged, modelProfile, targetId) {
|
|
1113
|
-
let defaultModel = merged.default;
|
|
1114
|
-
let smallModel = merged.small;
|
|
1115
|
-
let agents = { ...merged.agents };
|
|
1116
|
-
if (modelProfile && merged.profiles?.[modelProfile]) {
|
|
1117
|
-
const resolvedProfile = resolveProfileInheritance(modelProfile, merged.profiles);
|
|
1118
|
-
if (resolvedProfile.default)
|
|
1119
|
-
defaultModel = resolvedProfile.default;
|
|
1120
|
-
if (resolvedProfile.small)
|
|
1121
|
-
smallModel = resolvedProfile.small;
|
|
1122
|
-
if (resolvedProfile.agents) {
|
|
1123
|
-
agents = { ...agents, ...resolvedProfile.agents };
|
|
1124
|
-
}
|
|
1125
|
-
}
|
|
1126
|
-
if (targetId) {
|
|
1127
|
-
const targetOverride = merged.overrides?.[targetId];
|
|
1128
|
-
if (targetOverride) {
|
|
1129
|
-
if (targetOverride.default)
|
|
1130
|
-
defaultModel = targetOverride.default;
|
|
1131
|
-
if (targetOverride.small)
|
|
1132
|
-
smallModel = targetOverride.small;
|
|
1133
|
-
if (targetOverride.agents) {
|
|
1134
|
-
agents = { ...agents, ...targetOverride.agents };
|
|
1135
|
-
}
|
|
1136
|
-
}
|
|
1137
|
-
}
|
|
1138
|
-
const providers = {};
|
|
1139
|
-
if (merged.providers) {
|
|
1140
|
-
for (const [name, config] of Object.entries(merged.providers)) {
|
|
1141
|
-
providers[name] = {
|
|
1142
|
-
...config.options ? { options: config.options } : {},
|
|
1143
|
-
...config.models ? { models: config.models } : {}
|
|
1144
|
-
};
|
|
1145
|
-
}
|
|
1146
|
-
}
|
|
1147
|
-
const profileNames = Object.keys(merged.profiles ?? {});
|
|
1148
|
-
const profiles = {};
|
|
1149
|
-
if (merged.profiles) {
|
|
1150
|
-
for (const [name, profile] of Object.entries(merged.profiles)) {
|
|
1151
|
-
profiles[name] = {
|
|
1152
|
-
description: profile.description,
|
|
1153
|
-
default: profile.default,
|
|
1154
|
-
small: profile.small
|
|
1155
|
-
};
|
|
1156
|
-
}
|
|
1157
|
-
}
|
|
1158
|
-
return {
|
|
1159
|
-
default: defaultModel,
|
|
1160
|
-
small: smallModel,
|
|
1161
|
-
agents,
|
|
1162
|
-
providers,
|
|
1163
|
-
routing: merged.routing ?? [],
|
|
1164
|
-
profileNames,
|
|
1165
|
-
activeProfile: modelProfile,
|
|
1166
|
-
profiles
|
|
1167
|
-
};
|
|
1168
|
-
}
|
|
1169
|
-
function resolveAgentModel(resolved, agentName, frontmatterModel) {
|
|
1170
|
-
const fromModels = resolved.agents[agentName];
|
|
1171
|
-
if (fromModels) {
|
|
1172
|
-
return {
|
|
1173
|
-
model: fromModels.model,
|
|
1174
|
-
temperature: fromModels.temperature,
|
|
1175
|
-
top_p: fromModels.top_p
|
|
1176
|
-
};
|
|
1177
|
-
}
|
|
1178
|
-
if (frontmatterModel) {
|
|
1179
|
-
return { model: frontmatterModel };
|
|
1180
|
-
}
|
|
1181
|
-
return {};
|
|
1182
|
-
}
|
|
1183
|
-
function resolveProfileInheritance(profileName, profiles) {
|
|
1184
|
-
const visited = new Set;
|
|
1185
|
-
return resolveProfileChain(profileName, profiles, visited, 0);
|
|
1186
|
-
}
|
|
1187
|
-
var MAX_INHERITANCE_DEPTH = 10;
|
|
1188
|
-
function resolveProfileChain(name, profiles, visited, depth) {
|
|
1189
|
-
if (depth > MAX_INHERITANCE_DEPTH) {
|
|
1190
|
-
throw new Error(`Profile inheritance too deep (max ${MAX_INHERITANCE_DEPTH}): ${name}`);
|
|
1191
|
-
}
|
|
1192
|
-
if (visited.has(name)) {
|
|
1193
|
-
throw new Error(`Circular profile inheritance detected: ${[...visited, name].join(" \u2192 ")}`);
|
|
1194
|
-
}
|
|
1195
|
-
const profile = profiles[name];
|
|
1196
|
-
if (!profile) {
|
|
1197
|
-
throw new Error(`Profile "${name}" not found`);
|
|
1198
|
-
}
|
|
1199
|
-
visited.add(name);
|
|
1200
|
-
if (!profile.extends) {
|
|
1201
|
-
return { ...profile };
|
|
1202
|
-
}
|
|
1203
|
-
const parent = resolveProfileChain(profile.extends, profiles, visited, depth + 1);
|
|
1204
|
-
return {
|
|
1205
|
-
description: profile.description ?? parent.description,
|
|
1206
|
-
default: profile.default ?? parent.default,
|
|
1207
|
-
small: profile.small ?? parent.small,
|
|
1208
|
-
agents: {
|
|
1209
|
-
...parent.agents,
|
|
1210
|
-
...profile.agents
|
|
1211
|
-
}
|
|
1212
|
-
};
|
|
1213
|
-
}
|
|
1214
|
-
|
|
1215
|
-
// src/exporters/cursor-plugin.ts
|
|
1216
|
-
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
1217
|
-
import { join as join8, resolve as resolve4 } from "path";
|
|
1218
|
-
function exportCursorPlugin(pack, outputDir) {
|
|
1219
|
-
const filesWritten = [];
|
|
1220
|
-
const pluginName = normalizeCursorPluginName(pack.manifest.name);
|
|
1221
|
-
const pluginDir = resolve4(outputDir, pluginName);
|
|
1222
|
-
mkdirSync2(pluginDir, { recursive: true });
|
|
1223
|
-
const manifest = {
|
|
1224
|
-
name: pluginName
|
|
1225
|
-
};
|
|
1226
|
-
if (pack.manifest.version) {
|
|
1227
|
-
manifest.version = pack.manifest.version;
|
|
1228
|
-
}
|
|
1229
|
-
if (pack.manifest.description) {
|
|
1230
|
-
manifest.description = pack.manifest.description;
|
|
1231
|
-
}
|
|
1232
|
-
const author = toCursorPluginAuthor(pack.manifest.author);
|
|
1233
|
-
if (author) {
|
|
1234
|
-
manifest.author = author;
|
|
1235
|
-
}
|
|
1236
|
-
if (pack.manifest.homepage) {
|
|
1237
|
-
manifest.homepage = pack.manifest.homepage;
|
|
1238
|
-
}
|
|
1239
|
-
if (pack.manifest.repository) {
|
|
1240
|
-
manifest.repository = typeof pack.manifest.repository === "string" ? pack.manifest.repository : pack.manifest.repository.url;
|
|
1241
|
-
}
|
|
1242
|
-
if (pack.manifest.license) {
|
|
1243
|
-
manifest.license = pack.manifest.license;
|
|
1244
|
-
}
|
|
1245
|
-
if (pack.manifest.logo) {
|
|
1246
|
-
manifest.logo = pack.manifest.logo;
|
|
1247
|
-
}
|
|
1248
|
-
if (pack.manifest.tags.length > 0) {
|
|
1249
|
-
manifest.keywords = pack.manifest.tags;
|
|
1250
|
-
}
|
|
1251
|
-
if (pack.rules.length > 0) {
|
|
1252
|
-
const rulesDir = join8(pluginDir, "rules");
|
|
1253
|
-
ensureDir(rulesDir);
|
|
1254
|
-
manifest.rules = "rules";
|
|
1255
|
-
for (const rule of pack.rules) {
|
|
1256
|
-
const cursorMeta = rule.meta.cursor ?? {};
|
|
1257
|
-
const fm = {
|
|
1258
|
-
description: cursorMeta.description ?? rule.meta.description ?? "",
|
|
1259
|
-
alwaysApply: cursorMeta.alwaysApply ?? rule.meta.root ?? false
|
|
1260
|
-
};
|
|
1261
|
-
const globs = cursorMeta.globs ?? rule.meta.globs;
|
|
1262
|
-
if (globs)
|
|
1263
|
-
fm.globs = globs;
|
|
1264
|
-
const filename = `${rule.name}.mdc`;
|
|
1265
|
-
const filepath = join8(rulesDir, filename);
|
|
1266
|
-
writeFileSync3(filepath, serializeFrontmatter(fm, rule.content));
|
|
1267
|
-
filesWritten.push(filepath);
|
|
1268
|
-
}
|
|
1269
|
-
}
|
|
1270
|
-
if (pack.agents.length > 0) {
|
|
1271
|
-
const agentsDir = join8(pluginDir, "agents");
|
|
1272
|
-
ensureDir(agentsDir);
|
|
1273
|
-
manifest.agents = "agents";
|
|
1274
|
-
for (const agent of pack.agents) {
|
|
1275
|
-
const fm = {
|
|
1276
|
-
name: agent.name,
|
|
1277
|
-
description: agent.meta.description ?? ""
|
|
1278
|
-
};
|
|
1279
|
-
const filename = `${agent.name}.md`;
|
|
1280
|
-
const filepath = join8(agentsDir, filename);
|
|
1281
|
-
writeFileSync3(filepath, serializeFrontmatter(fm, agent.content));
|
|
1282
|
-
filesWritten.push(filepath);
|
|
1283
|
-
}
|
|
1284
|
-
}
|
|
1285
|
-
if (pack.skills.length > 0) {
|
|
1286
|
-
const skillsDir = join8(pluginDir, "skills");
|
|
1287
|
-
ensureDir(skillsDir);
|
|
1288
|
-
manifest.skills = "skills";
|
|
1289
|
-
for (const skill of pack.skills) {
|
|
1290
|
-
const skillSubDir = join8(skillsDir, skill.name);
|
|
1291
|
-
ensureDir(skillSubDir);
|
|
1292
|
-
const filepath = join8(skillSubDir, "SKILL.md");
|
|
1293
|
-
const content = serializeFrontmatter(buildSkillFrontmatter(skill), skill.content);
|
|
1294
|
-
writeFileSync3(filepath, content);
|
|
1295
|
-
filesWritten.push(filepath);
|
|
1296
|
-
}
|
|
1297
|
-
}
|
|
1298
|
-
if (pack.commands.length > 0) {
|
|
1299
|
-
const commandsDir = join8(pluginDir, "commands");
|
|
1300
|
-
ensureDir(commandsDir);
|
|
1301
|
-
manifest.commands = "commands";
|
|
1302
|
-
for (const cmd of pack.commands) {
|
|
1303
|
-
const fm = {
|
|
1304
|
-
name: cmd.name
|
|
1305
|
-
};
|
|
1306
|
-
if (cmd.meta.description) {
|
|
1307
|
-
fm.description = cmd.meta.description;
|
|
1308
|
-
}
|
|
1309
|
-
const filename = `${cmd.name}.md`;
|
|
1310
|
-
const filepath = join8(commandsDir, filename);
|
|
1311
|
-
writeFileSync3(filepath, serializeFrontmatter(fm, cmd.content));
|
|
1312
|
-
filesWritten.push(filepath);
|
|
1313
|
-
}
|
|
1314
|
-
}
|
|
1315
|
-
if (pack.hooks) {
|
|
1316
|
-
const events = resolveHooksForTarget(pack.hooks, "cursor");
|
|
1317
|
-
if (Object.keys(events).length > 0) {
|
|
1318
|
-
const hooksDir = join8(pluginDir, "hooks");
|
|
1319
|
-
ensureDir(hooksDir);
|
|
1320
|
-
const filepath = join8(hooksDir, "hooks.json");
|
|
1321
|
-
writeFileSync3(filepath, JSON.stringify({ version: pack.hooks.version ?? 1, hooks: events }, null, 2) + `
|
|
1322
|
-
`);
|
|
1323
|
-
filesWritten.push(filepath);
|
|
1324
|
-
manifest.hooks = "hooks/hooks.json";
|
|
1325
|
-
}
|
|
1326
|
-
}
|
|
1327
|
-
if (pack.mcp && Object.keys(pack.mcp.servers).length > 0) {
|
|
1328
|
-
manifest.mcpServers = ".mcp.json";
|
|
1329
|
-
const filepath = join8(pluginDir, ".mcp.json");
|
|
1330
|
-
writeFileSync3(filepath, JSON.stringify({ mcpServers: pack.mcp.servers }, null, 2) + `
|
|
1331
|
-
`);
|
|
1332
|
-
filesWritten.push(filepath);
|
|
1333
|
-
}
|
|
1334
|
-
const manifestDir = join8(pluginDir, ".cursor-plugin");
|
|
1335
|
-
ensureDir(manifestDir);
|
|
1336
|
-
const manifestPath = join8(manifestDir, "plugin.json");
|
|
1337
|
-
writeFileSync3(manifestPath, JSON.stringify(manifest, null, 2) + `
|
|
1338
|
-
`);
|
|
1339
|
-
filesWritten.push(manifestPath);
|
|
1340
|
-
return { outputDir: pluginDir, filesWritten, manifest };
|
|
1341
|
-
}
|
|
1342
|
-
function normalizeCursorPluginName(name) {
|
|
1343
|
-
const normalized = name.toLowerCase().replace(/[^a-z0-9.-]+/g, "-").replace(/-+/g, "-").replace(/^[^a-z0-9]+/, "").replace(/[^a-z0-9]+$/, "");
|
|
1344
|
-
return normalized.length > 0 ? normalized : "agentpacks-plugin";
|
|
1345
|
-
}
|
|
1346
|
-
function toCursorPluginAuthor(author) {
|
|
1347
|
-
if (!author) {
|
|
1348
|
-
return null;
|
|
1349
|
-
}
|
|
1350
|
-
if (typeof author === "string") {
|
|
1351
|
-
return { name: author };
|
|
1352
|
-
}
|
|
1353
|
-
return {
|
|
1354
|
-
name: author.name,
|
|
1355
|
-
...author.email ? { email: author.email } : {}
|
|
1356
|
-
};
|
|
1357
|
-
}
|
|
1358
|
-
|
|
1359
|
-
// src/importers/claude-code.ts
|
|
1360
|
-
import { copyFileSync, existsSync as existsSync8, readFileSync as readFileSync10, writeFileSync as writeFileSync4 } from "fs";
|
|
1361
|
-
import { basename as basename6, join as join9, resolve as resolve5 } from "path";
|
|
1362
|
-
function importFromClaudeCode(projectRoot, outputPackDir) {
|
|
1363
|
-
const warnings = [];
|
|
1364
|
-
const filesImported = [];
|
|
1365
|
-
const claudeDir = resolve5(projectRoot, ".claude");
|
|
1366
|
-
const hasClaudeMd = existsSync8(resolve5(projectRoot, "CLAUDE.md"));
|
|
1367
|
-
const hasClaudeDir = existsSync8(claudeDir);
|
|
1368
|
-
if (!hasClaudeMd && !hasClaudeDir) {
|
|
1369
|
-
return {
|
|
1370
|
-
packDir: "",
|
|
1371
|
-
filesImported: [],
|
|
1372
|
-
warnings: ["No CLAUDE.md or .claude/ directory found."],
|
|
1373
|
-
configGenerated: false
|
|
1374
|
-
};
|
|
1375
|
-
}
|
|
1376
|
-
const packDir = outputPackDir ?? resolve5(projectRoot, "packs", "claude-import");
|
|
1377
|
-
ensureDir(packDir);
|
|
1378
|
-
const rulesDir = resolve5(packDir, "rules");
|
|
1379
|
-
ensureDir(rulesDir);
|
|
1380
|
-
if (hasClaudeMd) {
|
|
1381
|
-
const raw = readFileSync10(resolve5(projectRoot, "CLAUDE.md"), "utf-8");
|
|
1382
|
-
const ruleContent = [
|
|
1383
|
-
"---",
|
|
1384
|
-
"root: true",
|
|
1385
|
-
'description: "Root Claude Code rules"',
|
|
1386
|
-
"---",
|
|
1387
|
-
"",
|
|
1388
|
-
raw
|
|
1389
|
-
].join(`
|
|
1390
|
-
`);
|
|
1391
|
-
const dest = join9(rulesDir, "claude-root.md");
|
|
1392
|
-
writeFileSync4(dest, ruleContent);
|
|
1393
|
-
filesImported.push(dest);
|
|
1394
|
-
}
|
|
1395
|
-
if (hasClaudeDir) {
|
|
1396
|
-
const claudeRulesDir = resolve5(claudeDir, "rules");
|
|
1397
|
-
if (existsSync8(claudeRulesDir)) {
|
|
1398
|
-
const files = listFiles(claudeRulesDir, { extension: ".md" });
|
|
1399
|
-
for (const file of files) {
|
|
1400
|
-
const dest = join9(rulesDir, basename6(file));
|
|
1401
|
-
copyFileSync(file, dest);
|
|
1402
|
-
filesImported.push(dest);
|
|
1403
|
-
}
|
|
1404
|
-
}
|
|
1405
|
-
const settingsPath = resolve5(claudeDir, "settings.json");
|
|
1406
|
-
if (existsSync8(settingsPath)) {
|
|
1407
|
-
try {
|
|
1408
|
-
const raw = readFileSync10(settingsPath, "utf-8");
|
|
1409
|
-
const settings = JSON.parse(raw);
|
|
1410
|
-
const mcpServers = settings.mcpServers ?? settings.mcp_servers;
|
|
1411
|
-
if (mcpServers && typeof mcpServers === "object") {
|
|
1412
|
-
const mcpConfig = { servers: mcpServers };
|
|
1413
|
-
const dest = join9(packDir, "mcp.json");
|
|
1414
|
-
writeFileSync4(dest, JSON.stringify(mcpConfig, null, 2) + `
|
|
1415
|
-
`);
|
|
1416
|
-
filesImported.push(dest);
|
|
1417
|
-
}
|
|
1418
|
-
} catch {
|
|
1419
|
-
warnings.push("Failed to parse .claude/settings.json");
|
|
1420
|
-
}
|
|
1421
|
-
}
|
|
1422
|
-
}
|
|
1423
|
-
const packJson = {
|
|
1424
|
-
name: "claude-import",
|
|
1425
|
-
version: "1.0.0",
|
|
1426
|
-
description: "Imported from Claude Code",
|
|
1427
|
-
tags: ["imported", "claude-code"],
|
|
1428
|
-
dependencies: [],
|
|
1429
|
-
conflicts: [],
|
|
1430
|
-
targets: "*",
|
|
1431
|
-
features: "*"
|
|
1432
|
-
};
|
|
1433
|
-
const packJsonPath = join9(packDir, "pack.json");
|
|
1434
|
-
writeFileSync4(packJsonPath, JSON.stringify(packJson, null, 2) + `
|
|
1435
|
-
`);
|
|
1436
|
-
filesImported.push(packJsonPath);
|
|
1437
|
-
return { packDir, filesImported, warnings, configGenerated: false };
|
|
1438
|
-
}
|
|
1439
|
-
|
|
1440
|
-
// src/importers/cursor.ts
|
|
1441
|
-
import { copyFileSync as copyFileSync2, existsSync as existsSync9, readFileSync as readFileSync11, writeFileSync as writeFileSync5 } from "fs";
|
|
1442
|
-
import { basename as basename7, join as join10, resolve as resolve6 } from "path";
|
|
1443
|
-
function importFromCursor(projectRoot, outputPackDir) {
|
|
1444
|
-
const cursorDir = resolve6(projectRoot, ".cursor");
|
|
1445
|
-
const warnings = [];
|
|
1446
|
-
const filesImported = [];
|
|
1447
|
-
if (!existsSync9(cursorDir)) {
|
|
1448
|
-
return {
|
|
1449
|
-
packDir: "",
|
|
1450
|
-
filesImported: [],
|
|
1451
|
-
warnings: ["No .cursor/ directory found."],
|
|
1452
|
-
configGenerated: false
|
|
1453
|
-
};
|
|
1454
|
-
}
|
|
1455
|
-
const packDir = outputPackDir ?? resolve6(projectRoot, "packs", "cursor-import");
|
|
1456
|
-
ensureDir(packDir);
|
|
1457
|
-
const rulesDir = resolve6(cursorDir, "rules");
|
|
1458
|
-
if (existsSync9(rulesDir)) {
|
|
1459
|
-
const outRulesDir = resolve6(packDir, "rules");
|
|
1460
|
-
ensureDir(outRulesDir);
|
|
1461
|
-
const files = listFiles(rulesDir, { extension: ".mdc" });
|
|
1462
|
-
for (const file of files) {
|
|
1463
|
-
const raw = readFileSync11(file, "utf-8");
|
|
1464
|
-
const { data, content } = parseFrontmatter(raw);
|
|
1465
|
-
const meta = {};
|
|
1466
|
-
if (data.description)
|
|
1467
|
-
meta.description = data.description;
|
|
1468
|
-
if (data.alwaysApply)
|
|
1469
|
-
meta.root = true;
|
|
1470
|
-
if (data.globs)
|
|
1471
|
-
meta.globs = data.globs;
|
|
1472
|
-
meta.cursor = { ...data };
|
|
1473
|
-
const mdContent = buildAgentpacksRule(meta, content);
|
|
1474
|
-
const name = basename7(file, ".mdc");
|
|
1475
|
-
const dest = join10(outRulesDir, `${name}.md`);
|
|
1476
|
-
writeFileSync5(dest, mdContent);
|
|
1477
|
-
filesImported.push(dest);
|
|
1478
|
-
}
|
|
1479
|
-
const mdFiles = listFiles(rulesDir, { extension: ".md" });
|
|
1480
|
-
for (const file of mdFiles) {
|
|
1481
|
-
const dest = join10(outRulesDir, basename7(file));
|
|
1482
|
-
copyFileSync2(file, dest);
|
|
1483
|
-
filesImported.push(dest);
|
|
1484
|
-
}
|
|
1485
|
-
}
|
|
1486
|
-
const agentsDir = resolve6(cursorDir, "agents");
|
|
1487
|
-
if (existsSync9(agentsDir)) {
|
|
1488
|
-
const outDir = resolve6(packDir, "agents");
|
|
1489
|
-
ensureDir(outDir);
|
|
1490
|
-
const files = listFiles(agentsDir, { extension: ".md" });
|
|
1491
|
-
for (const file of files) {
|
|
1492
|
-
const dest = join10(outDir, basename7(file));
|
|
1493
|
-
copyFileSync2(file, dest);
|
|
1494
|
-
filesImported.push(dest);
|
|
1495
|
-
}
|
|
1496
|
-
}
|
|
1497
|
-
const skillsDir = resolve6(cursorDir, "skills");
|
|
1498
|
-
if (existsSync9(skillsDir)) {
|
|
1499
|
-
const outDir = resolve6(packDir, "skills");
|
|
1500
|
-
ensureDir(outDir);
|
|
1501
|
-
const dirs = listDirs(skillsDir);
|
|
1502
|
-
for (const dir of dirs) {
|
|
1503
|
-
const name = basename7(dir);
|
|
1504
|
-
const skillMd = join10(dir, "SKILL.md");
|
|
1505
|
-
if (existsSync9(skillMd)) {
|
|
1506
|
-
const outSkillDir = join10(outDir, name);
|
|
1507
|
-
ensureDir(outSkillDir);
|
|
1508
|
-
const rawSkill = readFileSync11(skillMd, "utf-8");
|
|
1509
|
-
const normalized = normalizeImportedSkillMarkdown(rawSkill, name);
|
|
1510
|
-
const dest = join10(outSkillDir, "SKILL.md");
|
|
1511
|
-
writeFileSync5(dest, normalized.content);
|
|
1512
|
-
filesImported.push(dest);
|
|
1513
|
-
if (normalized.addedDescription) {
|
|
1514
|
-
warnings.push(`skills/${name}/SKILL.md missing description; added import placeholder.`);
|
|
1515
|
-
}
|
|
1516
|
-
}
|
|
1517
|
-
}
|
|
1518
|
-
}
|
|
1519
|
-
const commandsDir = resolve6(cursorDir, "commands");
|
|
1520
|
-
if (existsSync9(commandsDir)) {
|
|
1521
|
-
const outDir = resolve6(packDir, "commands");
|
|
1522
|
-
ensureDir(outDir);
|
|
1523
|
-
const files = listFiles(commandsDir, { extension: ".md" });
|
|
1524
|
-
for (const file of files) {
|
|
1525
|
-
const dest = join10(outDir, basename7(file));
|
|
1526
|
-
copyFileSync2(file, dest);
|
|
1527
|
-
filesImported.push(dest);
|
|
1528
|
-
}
|
|
1529
|
-
}
|
|
1530
|
-
const mcpJson = resolve6(cursorDir, "mcp.json");
|
|
1531
|
-
if (existsSync9(mcpJson)) {
|
|
1532
|
-
copyFileSync2(mcpJson, join10(packDir, "mcp.json"));
|
|
1533
|
-
filesImported.push(join10(packDir, "mcp.json"));
|
|
1534
|
-
}
|
|
1535
|
-
const cursorIgnore = resolve6(projectRoot, ".cursorignore");
|
|
1536
|
-
if (existsSync9(cursorIgnore)) {
|
|
1537
|
-
copyFileSync2(cursorIgnore, join10(packDir, "ignore"));
|
|
1538
|
-
filesImported.push(join10(packDir, "ignore"));
|
|
1539
|
-
}
|
|
1540
|
-
writePackJson(packDir, "cursor-import", filesImported);
|
|
1541
|
-
return { packDir, filesImported, warnings, configGenerated: false };
|
|
1542
|
-
}
|
|
1543
|
-
function buildAgentpacksRule(meta, content) {
|
|
1544
|
-
const lines = ["---"];
|
|
1545
|
-
for (const [k, v] of Object.entries(meta)) {
|
|
1546
|
-
if (typeof v === "object") {
|
|
1547
|
-
lines.push(`${k}: ${JSON.stringify(v)}`);
|
|
1548
|
-
} else {
|
|
1549
|
-
lines.push(`${k}: ${v}`);
|
|
1550
|
-
}
|
|
1551
|
-
}
|
|
1552
|
-
lines.push("---", "", content);
|
|
1553
|
-
return lines.join(`
|
|
1554
|
-
`);
|
|
1555
|
-
}
|
|
1556
|
-
function writePackJson(packDir, name, filesImported) {
|
|
1557
|
-
const packJson = {
|
|
1558
|
-
name,
|
|
1559
|
-
version: "1.0.0",
|
|
1560
|
-
description: `Imported from Cursor`,
|
|
1561
|
-
tags: ["imported", "cursor"],
|
|
1562
|
-
dependencies: [],
|
|
1563
|
-
conflicts: [],
|
|
1564
|
-
targets: "*",
|
|
1565
|
-
features: "*"
|
|
1566
|
-
};
|
|
1567
|
-
const dest = join10(packDir, "pack.json");
|
|
1568
|
-
writeFileSync5(dest, JSON.stringify(packJson, null, 2) + `
|
|
1569
|
-
`);
|
|
1570
|
-
filesImported.push(dest);
|
|
1571
|
-
}
|
|
1572
|
-
|
|
1573
|
-
// src/importers/opencode.ts
|
|
1574
|
-
import { copyFileSync as copyFileSync3, existsSync as existsSync10, readFileSync as readFileSync12, writeFileSync as writeFileSync6 } from "fs";
|
|
1575
|
-
import { basename as basename8, join as join11, resolve as resolve7 } from "path";
|
|
1576
|
-
function importFromOpenCode(projectRoot, outputPackDir) {
|
|
1577
|
-
const warnings = [];
|
|
1578
|
-
const filesImported = [];
|
|
1579
|
-
const ocDir = resolve7(projectRoot, ".opencode");
|
|
1580
|
-
if (!existsSync10(ocDir)) {
|
|
1581
|
-
return {
|
|
1582
|
-
packDir: "",
|
|
1583
|
-
filesImported: [],
|
|
1584
|
-
warnings: ["No .opencode/ directory found."],
|
|
1585
|
-
configGenerated: false
|
|
1586
|
-
};
|
|
1587
|
-
}
|
|
1588
|
-
const packDir = outputPackDir ?? resolve7(projectRoot, "packs", "opencode-import");
|
|
1589
|
-
ensureDir(packDir);
|
|
1590
|
-
importDirMd(resolve7(ocDir, "rules"), resolve7(packDir, "rules"), filesImported);
|
|
1591
|
-
importDirMd(resolve7(ocDir, "commands"), resolve7(packDir, "commands"), filesImported);
|
|
1592
|
-
importDirMd(resolve7(ocDir, "agents"), resolve7(packDir, "agents"), filesImported);
|
|
1593
|
-
const skillDir = resolve7(ocDir, "skill");
|
|
1594
|
-
if (existsSync10(skillDir)) {
|
|
1595
|
-
const outSkillDir = resolve7(packDir, "skills");
|
|
1596
|
-
ensureDir(outSkillDir);
|
|
1597
|
-
const dirs = listDirs(skillDir);
|
|
1598
|
-
for (const dir of dirs) {
|
|
1599
|
-
const name = basename8(dir);
|
|
1600
|
-
if (name.startsWith("."))
|
|
1601
|
-
continue;
|
|
1602
|
-
const skillMd = join11(dir, "SKILL.md");
|
|
1603
|
-
if (existsSync10(skillMd)) {
|
|
1604
|
-
const outDir = join11(outSkillDir, name);
|
|
1605
|
-
ensureDir(outDir);
|
|
1606
|
-
const rawSkill = readFileSync12(skillMd, "utf-8");
|
|
1607
|
-
const normalized = normalizeImportedSkillMarkdown(rawSkill, name);
|
|
1608
|
-
const dest2 = join11(outDir, "SKILL.md");
|
|
1609
|
-
writeFileSync6(dest2, normalized.content);
|
|
1610
|
-
filesImported.push(dest2);
|
|
1611
|
-
if (normalized.addedDescription) {
|
|
1612
|
-
warnings.push(`skills/${name}/SKILL.md missing description; added import placeholder.`);
|
|
1613
|
-
}
|
|
1614
|
-
}
|
|
1615
|
-
}
|
|
1616
|
-
}
|
|
1617
|
-
const pluginsDir = resolve7(ocDir, "plugins");
|
|
1618
|
-
if (existsSync10(pluginsDir)) {
|
|
1619
|
-
const outPluginsDir = resolve7(packDir, "plugins");
|
|
1620
|
-
ensureDir(outPluginsDir);
|
|
1621
|
-
const files = listFiles(pluginsDir);
|
|
1622
|
-
for (const file of files) {
|
|
1623
|
-
if (file.endsWith(".ts") || file.endsWith(".js")) {
|
|
1624
|
-
const dest2 = join11(outPluginsDir, basename8(file));
|
|
1625
|
-
copyFileSync3(file, dest2);
|
|
1626
|
-
filesImported.push(dest2);
|
|
1627
|
-
}
|
|
1628
|
-
}
|
|
1629
|
-
}
|
|
1630
|
-
const agentsMd = resolve7(projectRoot, "AGENTS.md");
|
|
1631
|
-
if (existsSync10(agentsMd)) {
|
|
1632
|
-
const outRulesDir = resolve7(packDir, "rules");
|
|
1633
|
-
ensureDir(outRulesDir);
|
|
1634
|
-
const raw = readFileSync12(agentsMd, "utf-8");
|
|
1635
|
-
const ruleContent = [
|
|
1636
|
-
"---",
|
|
1637
|
-
"root: true",
|
|
1638
|
-
'description: "AGENTS.md root rules"',
|
|
1639
|
-
"---",
|
|
1640
|
-
"",
|
|
1641
|
-
raw
|
|
1642
|
-
].join(`
|
|
1643
|
-
`);
|
|
1644
|
-
const dest2 = join11(outRulesDir, "agents-md-root.md");
|
|
1645
|
-
writeFileSync6(dest2, ruleContent);
|
|
1646
|
-
filesImported.push(dest2);
|
|
1647
|
-
}
|
|
1648
|
-
const ocJson = resolve7(projectRoot, "opencode.json");
|
|
1649
|
-
if (existsSync10(ocJson)) {
|
|
1650
|
-
try {
|
|
1651
|
-
const raw = readFileSync12(ocJson, "utf-8");
|
|
1652
|
-
const config = JSON.parse(raw);
|
|
1653
|
-
const mcpObj = config.mcp;
|
|
1654
|
-
if (mcpObj) {
|
|
1655
|
-
const dest2 = join11(packDir, "mcp.json");
|
|
1656
|
-
writeFileSync6(dest2, JSON.stringify({ servers: mcpObj }, null, 2) + `
|
|
1657
|
-
`);
|
|
1658
|
-
filesImported.push(dest2);
|
|
1659
|
-
}
|
|
1660
|
-
} catch {
|
|
1661
|
-
warnings.push("Failed to parse opencode.json");
|
|
1662
|
-
}
|
|
1663
|
-
}
|
|
1664
|
-
const ocIgnore = resolve7(projectRoot, ".opencodeignore");
|
|
1665
|
-
if (existsSync10(ocIgnore)) {
|
|
1666
|
-
copyFileSync3(ocIgnore, join11(packDir, "ignore"));
|
|
1667
|
-
filesImported.push(join11(packDir, "ignore"));
|
|
1668
|
-
}
|
|
1669
|
-
const packJson = {
|
|
1670
|
-
name: "opencode-import",
|
|
1671
|
-
version: "1.0.0",
|
|
1672
|
-
description: "Imported from OpenCode",
|
|
1673
|
-
tags: ["imported", "opencode"],
|
|
1674
|
-
dependencies: [],
|
|
1675
|
-
conflicts: [],
|
|
1676
|
-
targets: "*",
|
|
1677
|
-
features: "*"
|
|
1678
|
-
};
|
|
1679
|
-
const dest = join11(packDir, "pack.json");
|
|
1680
|
-
writeFileSync6(dest, JSON.stringify(packJson, null, 2) + `
|
|
1681
|
-
`);
|
|
1682
|
-
filesImported.push(dest);
|
|
1683
|
-
return { packDir, filesImported, warnings, configGenerated: false };
|
|
1684
|
-
}
|
|
1685
|
-
function importDirMd(srcDir, outDir, filesImported) {
|
|
1686
|
-
if (!existsSync10(srcDir))
|
|
1687
|
-
return;
|
|
1688
|
-
ensureDir(outDir);
|
|
1689
|
-
const files = listFiles(srcDir, { extension: ".md" });
|
|
1690
|
-
for (const file of files) {
|
|
1691
|
-
const dest = join11(outDir, basename8(file));
|
|
1692
|
-
copyFileSync3(file, dest);
|
|
1693
|
-
filesImported.push(dest);
|
|
1694
|
-
}
|
|
1695
|
-
}
|
|
1696
|
-
|
|
1697
|
-
// src/importers/rulesync.ts
|
|
1698
|
-
import { copyFileSync as copyFileSync4, existsSync as existsSync11, readFileSync as readFileSync13, writeFileSync as writeFileSync7 } from "fs";
|
|
1699
|
-
import { parse as parseJsonc2 } from "jsonc-parser";
|
|
1700
|
-
import { basename as basename9, join as join12, resolve as resolve8 } from "path";
|
|
1701
|
-
function importFromRulesync(projectRoot, outputPackDir) {
|
|
1702
|
-
const rulesyncDir = resolve8(projectRoot, ".rulesync");
|
|
1703
|
-
const warnings = [];
|
|
1704
|
-
const filesImported = [];
|
|
1705
|
-
if (!existsSync11(rulesyncDir)) {
|
|
1706
|
-
return {
|
|
1707
|
-
packDir: "",
|
|
1708
|
-
filesImported: [],
|
|
1709
|
-
warnings: ["No .rulesync/ directory found."],
|
|
1710
|
-
configGenerated: false
|
|
1711
|
-
};
|
|
1712
|
-
}
|
|
1713
|
-
const packDir = outputPackDir ?? resolve8(projectRoot, "packs", "default");
|
|
1714
|
-
ensureDir(packDir);
|
|
1715
|
-
const rulesDir = resolve8(rulesyncDir, "rules");
|
|
1716
|
-
if (existsSync11(rulesDir)) {
|
|
1717
|
-
const outRulesDir = resolve8(packDir, "rules");
|
|
1718
|
-
ensureDir(outRulesDir);
|
|
1719
|
-
const files = listFiles(rulesDir, { extension: ".md" });
|
|
1720
|
-
for (const file of files) {
|
|
1721
|
-
const dest = join12(outRulesDir, basename9(file));
|
|
1722
|
-
copyFileSync4(file, dest);
|
|
1723
|
-
filesImported.push(dest);
|
|
1724
|
-
}
|
|
1725
|
-
}
|
|
1726
|
-
const commandsDir = resolve8(rulesyncDir, "commands");
|
|
1727
|
-
if (existsSync11(commandsDir)) {
|
|
1728
|
-
const outCommandsDir = resolve8(packDir, "commands");
|
|
1729
|
-
ensureDir(outCommandsDir);
|
|
1730
|
-
const files = listFiles(commandsDir, { extension: ".md" });
|
|
1731
|
-
for (const file of files) {
|
|
1732
|
-
const dest = join12(outCommandsDir, basename9(file));
|
|
1733
|
-
copyFileSync4(file, dest);
|
|
1734
|
-
filesImported.push(dest);
|
|
1735
|
-
}
|
|
1736
|
-
}
|
|
1737
|
-
const subagentsDir = resolve8(rulesyncDir, "subagents");
|
|
1738
|
-
if (existsSync11(subagentsDir)) {
|
|
1739
|
-
const outAgentsDir = resolve8(packDir, "agents");
|
|
1740
|
-
ensureDir(outAgentsDir);
|
|
1741
|
-
const files = listFiles(subagentsDir, { extension: ".md" });
|
|
1742
|
-
for (const file of files) {
|
|
1743
|
-
const dest = join12(outAgentsDir, basename9(file));
|
|
1744
|
-
copyFileSync4(file, dest);
|
|
1745
|
-
filesImported.push(dest);
|
|
1746
|
-
}
|
|
1747
|
-
}
|
|
1748
|
-
const skillsDir = resolve8(rulesyncDir, "skills");
|
|
1749
|
-
if (existsSync11(skillsDir)) {
|
|
1750
|
-
const outSkillsDir = resolve8(packDir, "skills");
|
|
1751
|
-
ensureDir(outSkillsDir);
|
|
1752
|
-
const skillDirs = listDirs(skillsDir);
|
|
1753
|
-
for (const skillDir of skillDirs) {
|
|
1754
|
-
const skillName = basename9(skillDir);
|
|
1755
|
-
if (skillName.startsWith("."))
|
|
1756
|
-
continue;
|
|
1757
|
-
const skillMd = join12(skillDir, "SKILL.md");
|
|
1758
|
-
if (existsSync11(skillMd)) {
|
|
1759
|
-
const outSkillDir = join12(outSkillsDir, skillName);
|
|
1760
|
-
ensureDir(outSkillDir);
|
|
1761
|
-
const rawSkill = readFileSync13(skillMd, "utf-8");
|
|
1762
|
-
const normalized = normalizeImportedSkillMarkdown(rawSkill, skillName);
|
|
1763
|
-
const dest = join12(outSkillDir, "SKILL.md");
|
|
1764
|
-
writeFileSync7(dest, normalized.content);
|
|
1765
|
-
filesImported.push(dest);
|
|
1766
|
-
if (normalized.addedDescription) {
|
|
1767
|
-
warnings.push(`skills/${skillName}/SKILL.md missing description; added import placeholder.`);
|
|
1768
|
-
}
|
|
1769
|
-
}
|
|
1770
|
-
}
|
|
1771
|
-
}
|
|
1772
|
-
const hooksJson = resolve8(rulesyncDir, "hooks.json");
|
|
1773
|
-
if (existsSync11(hooksJson)) {
|
|
1774
|
-
const outHooksDir = resolve8(packDir, "hooks");
|
|
1775
|
-
ensureDir(outHooksDir);
|
|
1776
|
-
copyFileSync4(hooksJson, join12(outHooksDir, "hooks.json"));
|
|
1777
|
-
filesImported.push(join12(outHooksDir, "hooks.json"));
|
|
1778
|
-
}
|
|
1779
|
-
const mcpJson = resolve8(rulesyncDir, "mcp.json");
|
|
1780
|
-
if (existsSync11(mcpJson)) {
|
|
1781
|
-
copyFileSync4(mcpJson, join12(packDir, "mcp.json"));
|
|
1782
|
-
filesImported.push(join12(packDir, "mcp.json"));
|
|
1783
|
-
}
|
|
1784
|
-
const aiIgnore = resolve8(rulesyncDir, ".aiignore");
|
|
1785
|
-
const rulesyncIgnore = resolve8(projectRoot, ".rulesyncignore");
|
|
1786
|
-
if (existsSync11(aiIgnore)) {
|
|
1787
|
-
copyFileSync4(aiIgnore, join12(packDir, "ignore"));
|
|
1788
|
-
filesImported.push(join12(packDir, "ignore"));
|
|
1789
|
-
} else if (existsSync11(rulesyncIgnore)) {
|
|
1790
|
-
copyFileSync4(rulesyncIgnore, join12(packDir, "ignore"));
|
|
1791
|
-
filesImported.push(join12(packDir, "ignore"));
|
|
1792
|
-
}
|
|
1793
|
-
const packJson = {
|
|
1794
|
-
name: "default",
|
|
1795
|
-
version: "1.0.0",
|
|
1796
|
-
description: "Imported from rulesync",
|
|
1797
|
-
tags: ["imported", "rulesync"],
|
|
1798
|
-
dependencies: [],
|
|
1799
|
-
conflicts: [],
|
|
1800
|
-
targets: "*",
|
|
1801
|
-
features: "*"
|
|
1802
|
-
};
|
|
1803
|
-
writeFileSync7(join12(packDir, "pack.json"), JSON.stringify(packJson, null, 2) + `
|
|
1804
|
-
`);
|
|
1805
|
-
filesImported.push(join12(packDir, "pack.json"));
|
|
1806
|
-
let configGenerated = false;
|
|
1807
|
-
const rulesyncConfig = resolve8(projectRoot, "rulesync.jsonc");
|
|
1808
|
-
if (existsSync11(rulesyncConfig)) {
|
|
1809
|
-
const agentpacksConfig = convertRulesyncConfig(rulesyncConfig, packDir);
|
|
1810
|
-
const configPath = resolve8(projectRoot, "agentpacks.jsonc");
|
|
1811
|
-
writeFileSync7(configPath, agentpacksConfig);
|
|
1812
|
-
configGenerated = true;
|
|
1813
|
-
}
|
|
1814
|
-
return { packDir, filesImported, warnings, configGenerated };
|
|
1815
|
-
}
|
|
1816
|
-
function convertRulesyncConfig(rulesyncPath, _packDir) {
|
|
1817
|
-
const raw = readFileSync13(rulesyncPath, "utf-8");
|
|
1818
|
-
const parsed = parseJsonc2(raw);
|
|
1819
|
-
const targets = parsed.targets ?? ["opencode", "cursor", "claudecode"];
|
|
1820
|
-
const features = parsed.features ?? ["*"];
|
|
1821
|
-
const baseDirs = parsed.baseDirs ?? ["."];
|
|
1822
|
-
const global = parsed.global ?? false;
|
|
1823
|
-
const deleteVal = parsed.delete ?? true;
|
|
1824
|
-
const relPackDir = "./" + join12("packs", "default");
|
|
1825
|
-
const config = {
|
|
1826
|
-
$schema: "https://unpkg.com/agentpacks/schema.json",
|
|
1827
|
-
packs: [relPackDir],
|
|
1828
|
-
disabled: [],
|
|
1829
|
-
targets,
|
|
1830
|
-
features,
|
|
1831
|
-
mode: baseDirs.length > 1 ? "monorepo" : "repo",
|
|
1832
|
-
baseDirs,
|
|
1833
|
-
global,
|
|
1834
|
-
delete: deleteVal
|
|
1835
|
-
};
|
|
1836
|
-
return JSON.stringify(config, null, 2) + `
|
|
1837
|
-
`;
|
|
1838
|
-
}
|
|
1839
|
-
|
|
1840
|
-
// src/sources/git-ref.ts
|
|
1841
|
-
function parseGitSourceRef(source) {
|
|
1842
|
-
let s = source;
|
|
1843
|
-
if (s.startsWith("github:")) {
|
|
1844
|
-
s = s.slice(7);
|
|
1845
|
-
}
|
|
1846
|
-
let path = "";
|
|
1847
|
-
const atIdx = s.indexOf("@");
|
|
1848
|
-
const colonIdx = s.indexOf(":", atIdx > -1 ? atIdx : 0);
|
|
1849
|
-
if (colonIdx > -1) {
|
|
1850
|
-
path = s.slice(colonIdx + 1);
|
|
1851
|
-
s = s.slice(0, colonIdx);
|
|
1852
|
-
}
|
|
1853
|
-
let ref = "main";
|
|
1854
|
-
if (atIdx > -1) {
|
|
1855
|
-
ref = s.slice(atIdx + 1);
|
|
1856
|
-
s = s.slice(0, atIdx);
|
|
1857
|
-
}
|
|
1858
|
-
const parts = s.split("/");
|
|
1859
|
-
if (parts.length < 2) {
|
|
1860
|
-
throw new Error(`Invalid git source reference: "${source}". Expected owner/repo format.`);
|
|
1861
|
-
}
|
|
1862
|
-
const owner = parts[0];
|
|
1863
|
-
const repo = parts[1];
|
|
1864
|
-
if (!owner || !repo) {
|
|
1865
|
-
throw new Error(`Invalid git source reference: "${source}". Expected owner/repo format.`);
|
|
1866
|
-
}
|
|
1867
|
-
return {
|
|
1868
|
-
owner,
|
|
1869
|
-
repo,
|
|
1870
|
-
ref,
|
|
1871
|
-
path: path || ""
|
|
1872
|
-
};
|
|
1873
|
-
}
|
|
1874
|
-
function isGitPackRef(packRef) {
|
|
1875
|
-
if (packRef.startsWith("github:"))
|
|
1876
|
-
return true;
|
|
1877
|
-
if (packRef.startsWith("./") || packRef.startsWith("../") || packRef.startsWith("/")) {
|
|
1878
|
-
return false;
|
|
1879
|
-
}
|
|
1880
|
-
if (packRef.startsWith("@") || packRef.startsWith("npm:"))
|
|
1881
|
-
return false;
|
|
1882
|
-
const parts = packRef.split("/");
|
|
1883
|
-
return parts.length === 2 && !packRef.includes("node_modules");
|
|
1884
|
-
}
|
|
1885
|
-
function gitSourceKey(parsed) {
|
|
1886
|
-
return `${parsed.owner}/${parsed.repo}`;
|
|
1887
|
-
}
|
|
1888
|
-
|
|
1889
|
-
// src/sources/git.ts
|
|
1890
|
-
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync8 } from "fs";
|
|
1891
|
-
import { join as join13, resolve as resolve9 } from "path";
|
|
1892
|
-
var GITHUB_API = "https://api.github.com";
|
|
1893
|
-
function githubHeaders(token) {
|
|
1894
|
-
const h = {
|
|
1895
|
-
Accept: "application/vnd.github.v3+json",
|
|
1896
|
-
"User-Agent": "agentpacks"
|
|
1897
|
-
};
|
|
1898
|
-
if (token)
|
|
1899
|
-
h.Authorization = `token ${token}`;
|
|
1900
|
-
return h;
|
|
1901
|
-
}
|
|
1902
|
-
async function resolveGitRef(parsed, token) {
|
|
1903
|
-
const base = `${GITHUB_API}/repos/${parsed.owner}/${parsed.repo}/git/ref`;
|
|
1904
|
-
const res = await fetch(`${base}/heads/${parsed.ref}`, {
|
|
1905
|
-
headers: githubHeaders(token)
|
|
1906
|
-
});
|
|
1907
|
-
if (!res.ok) {
|
|
1908
|
-
const tagRes = await fetch(`${base}/tags/${parsed.ref}`, {
|
|
1909
|
-
headers: githubHeaders(token)
|
|
1910
|
-
});
|
|
1911
|
-
if (!tagRes.ok) {
|
|
1912
|
-
throw new Error(`Could not resolve ref "${parsed.ref}" for ${parsed.owner}/${parsed.repo}: ${res.status}`);
|
|
1913
|
-
}
|
|
1914
|
-
const tagData = await tagRes.json();
|
|
1915
|
-
return tagData.object.sha;
|
|
1916
|
-
}
|
|
1917
|
-
const data = await res.json();
|
|
1918
|
-
return data.object.sha;
|
|
1919
|
-
}
|
|
1920
|
-
async function fetchGitDirectory(parsed, sha, subpath, token) {
|
|
1921
|
-
const path = parsed.path ? `${parsed.path}/${subpath}` : subpath;
|
|
1922
|
-
const url = `${GITHUB_API}/repos/${parsed.owner}/${parsed.repo}/contents/${path}?ref=${sha}`;
|
|
1923
|
-
const res = await fetch(url, { headers: githubHeaders(token) });
|
|
1924
|
-
if (!res.ok)
|
|
1925
|
-
return [];
|
|
1926
|
-
return await res.json();
|
|
1927
|
-
}
|
|
1928
|
-
async function fetchGitFile(downloadUrl, token) {
|
|
1929
|
-
const headers = { "User-Agent": "agentpacks" };
|
|
1930
|
-
if (token)
|
|
1931
|
-
headers.Authorization = `token ${token}`;
|
|
1932
|
-
const res = await fetch(downloadUrl, { headers });
|
|
1933
|
-
if (!res.ok) {
|
|
1934
|
-
throw new Error(`Failed to fetch ${downloadUrl}: ${res.status}`);
|
|
1935
|
-
}
|
|
1936
|
-
return res.text();
|
|
1937
|
-
}
|
|
1938
|
-
async function fetchAndWriteSubdir(parsed, sha, remotePath, localDir, installed, token) {
|
|
1939
|
-
mkdirSync3(localDir, { recursive: true });
|
|
1940
|
-
const entries = await fetchGitDirectory(parsed, sha, remotePath, token);
|
|
1941
|
-
for (const entry of entries) {
|
|
1942
|
-
if (entry.type === "file" && entry.download_url) {
|
|
1943
|
-
const content = await fetchGitFile(entry.download_url, token);
|
|
1944
|
-
const filepath = join13(localDir, entry.name);
|
|
1945
|
-
writeFileSync8(filepath, content);
|
|
1946
|
-
installed.push(filepath);
|
|
1947
|
-
} else if (entry.type === "dir") {
|
|
1948
|
-
await fetchAndWriteSubdir(parsed, sha, `${remotePath}/${entry.name}`, join13(localDir, entry.name), installed, token);
|
|
1949
|
-
}
|
|
1950
|
-
}
|
|
1951
|
-
}
|
|
1952
|
-
async function installGitSource(projectRoot, source, lockfile, options = {}) {
|
|
1953
|
-
const parsed = parseGitSourceRef(source);
|
|
1954
|
-
const sourceKey = gitSourceKey(parsed);
|
|
1955
|
-
const installed = [];
|
|
1956
|
-
const warnings = [];
|
|
1957
|
-
let resolvedSha;
|
|
1958
|
-
const locked = getLockedSource(lockfile, sourceKey);
|
|
1959
|
-
if (options.frozen && !locked) {
|
|
1960
|
-
throw new Error(`Frozen mode: no lockfile entry for source "${sourceKey}".`);
|
|
1961
|
-
}
|
|
1962
|
-
if (locked && !options.update) {
|
|
1963
|
-
resolvedSha = locked.resolvedRef;
|
|
1964
|
-
} else {
|
|
1965
|
-
resolvedSha = await resolveGitRef(parsed, options.token);
|
|
1966
|
-
}
|
|
1967
|
-
const basePath = parsed.path || "packs";
|
|
1968
|
-
const entries = await fetchGitDirectory(parsed, resolvedSha, basePath, options.token);
|
|
1969
|
-
const curatedDir = resolve9(projectRoot, ".agentpacks", ".curated");
|
|
1970
|
-
mkdirSync3(curatedDir, { recursive: true });
|
|
1971
|
-
const newLockEntry = {
|
|
1972
|
-
requestedRef: parsed.ref,
|
|
1973
|
-
resolvedRef: resolvedSha,
|
|
1974
|
-
resolvedAt: new Date().toISOString(),
|
|
1975
|
-
skills: {},
|
|
1976
|
-
packs: {}
|
|
1977
|
-
};
|
|
1978
|
-
const packDirs = entries.filter((e) => e.type === "dir");
|
|
1979
|
-
for (const packEntry of packDirs) {
|
|
1980
|
-
const packName = packEntry.name;
|
|
1981
|
-
const packOutDir = resolve9(curatedDir, packName);
|
|
1982
|
-
const packFiles = await fetchGitDirectory(parsed, resolvedSha, `${basePath}/${packName}`, options.token);
|
|
1983
|
-
mkdirSync3(packOutDir, { recursive: true });
|
|
1984
|
-
for (const file of packFiles) {
|
|
1985
|
-
if (file.type === "file" && file.download_url) {
|
|
1986
|
-
const content = await fetchGitFile(file.download_url, options.token);
|
|
1987
|
-
writeFileSync8(join13(packOutDir, file.name), content);
|
|
1988
|
-
installed.push(join13(packOutDir, file.name));
|
|
1989
|
-
if (newLockEntry.packs) {
|
|
1990
|
-
newLockEntry.packs[packName] = {
|
|
1991
|
-
integrity: computeIntegrity(content)
|
|
1992
|
-
};
|
|
1993
|
-
}
|
|
1994
|
-
} else if (file.type === "dir") {
|
|
1995
|
-
await fetchAndWriteSubdir(parsed, resolvedSha, `${basePath}/${packName}/${file.name}`, join13(packOutDir, file.name), installed, options.token);
|
|
1996
|
-
}
|
|
1997
|
-
}
|
|
1998
|
-
}
|
|
1999
|
-
if (packDirs.length === 0) {
|
|
2000
|
-
const fileEntries = entries.filter((e) => e.type === "file");
|
|
2001
|
-
if (fileEntries.length > 0) {
|
|
2002
|
-
const packName = parsed.path.split("/").pop() ?? parsed.repo;
|
|
2003
|
-
const packOutDir = resolve9(curatedDir, packName);
|
|
2004
|
-
mkdirSync3(packOutDir, { recursive: true });
|
|
2005
|
-
for (const file of entries) {
|
|
2006
|
-
if (file.type === "file" && file.download_url) {
|
|
2007
|
-
const content = await fetchGitFile(file.download_url, options.token);
|
|
2008
|
-
writeFileSync8(join13(packOutDir, file.name), content);
|
|
2009
|
-
installed.push(join13(packOutDir, file.name));
|
|
2010
|
-
} else if (file.type === "dir") {
|
|
2011
|
-
await fetchAndWriteSubdir(parsed, resolvedSha, `${basePath}/${file.name}`, join13(packOutDir, file.name), installed, options.token);
|
|
2012
|
-
}
|
|
2013
|
-
}
|
|
2014
|
-
}
|
|
2015
|
-
}
|
|
2016
|
-
setLockedSource(lockfile, sourceKey, newLockEntry);
|
|
2017
|
-
return { installed, warnings };
|
|
2018
|
-
}
|
|
2019
|
-
|
|
2020
|
-
// src/sources/local.ts
|
|
2021
|
-
import { existsSync as existsSync12 } from "fs";
|
|
2022
|
-
import { isAbsolute as isAbsolute2, resolve as resolve10 } from "path";
|
|
2023
|
-
function resolveLocalPack(packRef, projectRoot) {
|
|
2024
|
-
let resolved;
|
|
2025
|
-
if (isAbsolute2(packRef)) {
|
|
2026
|
-
resolved = packRef;
|
|
2027
|
-
} else {
|
|
2028
|
-
resolved = resolve10(projectRoot, packRef);
|
|
2029
|
-
}
|
|
2030
|
-
if (!existsSync12(resolved))
|
|
2031
|
-
return null;
|
|
2032
|
-
return resolved;
|
|
2033
|
-
}
|
|
2034
|
-
function isLocalPackRef(packRef) {
|
|
2035
|
-
return packRef.startsWith("./") || packRef.startsWith("../") || isAbsolute2(packRef);
|
|
2036
|
-
}
|
|
2037
|
-
|
|
2038
|
-
// src/sources/npm-ref.ts
|
|
2039
|
-
function parseNpmSourceRef(source) {
|
|
2040
|
-
let s = source;
|
|
2041
|
-
if (s.startsWith("npm:")) {
|
|
2042
|
-
s = s.slice(4);
|
|
2043
|
-
}
|
|
2044
|
-
let path = "";
|
|
2045
|
-
const pathColonIdx = findPathColon(s);
|
|
2046
|
-
if (pathColonIdx > -1) {
|
|
2047
|
-
path = s.slice(pathColonIdx + 1);
|
|
2048
|
-
s = s.slice(0, pathColonIdx);
|
|
2049
|
-
}
|
|
2050
|
-
let version = "latest";
|
|
2051
|
-
const versionAtIdx = findVersionAt(s);
|
|
2052
|
-
if (versionAtIdx > -1) {
|
|
2053
|
-
version = s.slice(versionAtIdx + 1);
|
|
2054
|
-
s = s.slice(0, versionAtIdx);
|
|
2055
|
-
}
|
|
2056
|
-
if (!s) {
|
|
2057
|
-
throw new Error(`Invalid npm source reference: "${source}". Expected package name.`);
|
|
2058
|
-
}
|
|
2059
|
-
return { packageName: s, version, path };
|
|
2060
|
-
}
|
|
2061
|
-
function findPathColon(s) {
|
|
2062
|
-
const startAfter = s.startsWith("@") ? s.indexOf("/") + 1 : 0;
|
|
2063
|
-
const vAt = findVersionAt(s);
|
|
2064
|
-
const searchFrom = vAt > -1 ? vAt : startAfter;
|
|
2065
|
-
return s.indexOf(":", searchFrom);
|
|
2066
|
-
}
|
|
2067
|
-
function findVersionAt(s) {
|
|
2068
|
-
if (s.startsWith("@")) {
|
|
2069
|
-
const slashIdx = s.indexOf("/");
|
|
2070
|
-
if (slashIdx === -1)
|
|
2071
|
-
return -1;
|
|
2072
|
-
return s.indexOf("@", slashIdx + 1);
|
|
2073
|
-
}
|
|
2074
|
-
return s.indexOf("@");
|
|
2075
|
-
}
|
|
2076
|
-
function isNpmPackRef(packRef) {
|
|
2077
|
-
if (packRef.startsWith("npm:"))
|
|
2078
|
-
return true;
|
|
2079
|
-
if (packRef.startsWith("@") && packRef.includes("/"))
|
|
2080
|
-
return true;
|
|
2081
|
-
return false;
|
|
2082
|
-
}
|
|
2083
|
-
function npmSourceKey(parsed) {
|
|
2084
|
-
return `npm:${parsed.packageName}`;
|
|
2085
|
-
}
|
|
2086
|
-
|
|
2087
|
-
// src/sources/npm.ts
|
|
2088
|
-
import { execSync } from "child_process";
|
|
2089
|
-
import { existsSync as existsSync13, mkdirSync as mkdirSync4, readdirSync as readdirSync2 } from "fs";
|
|
2090
|
-
import { join as join14, resolve as resolve11 } from "path";
|
|
2091
|
-
var NPM_REGISTRY = "https://registry.npmjs.org";
|
|
2092
|
-
async function resolveNpmVersion(parsed) {
|
|
2093
|
-
const url = `${NPM_REGISTRY}/${encodeURIComponent(parsed.packageName)}/${parsed.version}`;
|
|
2094
|
-
const res = await fetch(url, {
|
|
2095
|
-
headers: { Accept: "application/json" }
|
|
2096
|
-
});
|
|
2097
|
-
if (!res.ok) {
|
|
2098
|
-
throw new Error(`Could not resolve npm package "${parsed.packageName}@${parsed.version}": ${res.status}`);
|
|
2099
|
-
}
|
|
2100
|
-
const data = await res.json();
|
|
2101
|
-
return { version: data.version, tarball: data.dist.tarball };
|
|
2102
|
-
}
|
|
2103
|
-
async function installNpmSource(projectRoot, source, lockfile, options = {}) {
|
|
2104
|
-
const parsed = parseNpmSourceRef(source);
|
|
2105
|
-
const sourceKey = npmSourceKey(parsed);
|
|
2106
|
-
const installed = [];
|
|
2107
|
-
const warnings = [];
|
|
2108
|
-
const locked = getLockedSource(lockfile, sourceKey);
|
|
2109
|
-
if (options.frozen && !locked) {
|
|
2110
|
-
throw new Error(`Frozen mode: no lockfile entry for source "${sourceKey}".`);
|
|
2111
|
-
}
|
|
2112
|
-
let resolvedVersion;
|
|
2113
|
-
if (locked && !options.update) {
|
|
2114
|
-
resolvedVersion = locked.resolvedRef;
|
|
2115
|
-
} else {
|
|
2116
|
-
const resolved = await resolveNpmVersion(parsed);
|
|
2117
|
-
resolvedVersion = resolved.version;
|
|
2118
|
-
}
|
|
2119
|
-
const curatedDir = resolve11(projectRoot, ".agentpacks", ".curated");
|
|
2120
|
-
mkdirSync4(curatedDir, { recursive: true });
|
|
2121
|
-
extractNpmPack(parsed, resolvedVersion, curatedDir, installed, warnings);
|
|
2122
|
-
const newEntry = {
|
|
2123
|
-
requestedRef: parsed.version,
|
|
2124
|
-
resolvedRef: resolvedVersion,
|
|
2125
|
-
resolvedAt: new Date().toISOString(),
|
|
2126
|
-
skills: {},
|
|
2127
|
-
packs: {}
|
|
2128
|
-
};
|
|
2129
|
-
setLockedSource(lockfile, sourceKey, newEntry);
|
|
2130
|
-
return { installed, warnings };
|
|
2131
|
-
}
|
|
2132
|
-
function extractNpmPack(parsed, version, curatedDir, installed, warnings) {
|
|
2133
|
-
const pkgSpec = `${parsed.packageName}@${version}`;
|
|
2134
|
-
const packName = parsed.packageName.replace(/^@/, "").replace(/\//g, "-");
|
|
2135
|
-
const packOutDir = resolve11(curatedDir, packName);
|
|
2136
|
-
try {
|
|
2137
|
-
const tmpDir = resolve11(curatedDir, ".tmp-npm");
|
|
2138
|
-
mkdirSync4(tmpDir, { recursive: true });
|
|
2139
|
-
execSync(`npm pack ${pkgSpec} --pack-destination "${tmpDir}"`, {
|
|
2140
|
-
stdio: "pipe",
|
|
2141
|
-
timeout: 30000
|
|
2142
|
-
});
|
|
2143
|
-
const tgzFiles = readdirSync2(tmpDir).filter((f) => f.endsWith(".tgz"));
|
|
2144
|
-
if (tgzFiles.length === 0) {
|
|
2145
|
-
warnings.push(`No tarball found for ${pkgSpec}`);
|
|
2146
|
-
return packOutDir;
|
|
2147
|
-
}
|
|
2148
|
-
const firstTgz = tgzFiles[0];
|
|
2149
|
-
if (!firstTgz) {
|
|
2150
|
-
warnings.push(`No tarball found for ${pkgSpec}`);
|
|
2151
|
-
return packOutDir;
|
|
2152
|
-
}
|
|
2153
|
-
const tgzPath = join14(tmpDir, firstTgz);
|
|
2154
|
-
mkdirSync4(packOutDir, { recursive: true });
|
|
2155
|
-
execSync(`tar xzf "${tgzPath}" -C "${packOutDir}" --strip-components=1`, {
|
|
2156
|
-
stdio: "pipe",
|
|
2157
|
-
timeout: 15000
|
|
2158
|
-
});
|
|
2159
|
-
execSync(`rm -rf "${tmpDir}"`, { stdio: "pipe" });
|
|
2160
|
-
const subpath = parsed.path || "";
|
|
2161
|
-
const targetDir = subpath ? join14(packOutDir, subpath) : packOutDir;
|
|
2162
|
-
if (existsSync13(targetDir)) {
|
|
2163
|
-
collectFiles(targetDir, installed);
|
|
2164
|
-
}
|
|
2165
|
-
} catch (err) {
|
|
2166
|
-
warnings.push(`Failed to extract npm pack ${pkgSpec}: ${err instanceof Error ? err.message : String(err)}`);
|
|
2167
|
-
}
|
|
2168
|
-
return packOutDir;
|
|
2169
|
-
}
|
|
2170
|
-
function collectFiles(dir, out) {
|
|
2171
|
-
const entries = readdirSync2(dir, { withFileTypes: true });
|
|
2172
|
-
for (const entry of entries) {
|
|
2173
|
-
const full = join14(dir, entry.name);
|
|
2174
|
-
if (entry.isDirectory()) {
|
|
2175
|
-
collectFiles(full, out);
|
|
2176
|
-
} else {
|
|
2177
|
-
out.push(full);
|
|
2178
|
-
}
|
|
2179
|
-
}
|
|
2180
|
-
}
|
|
2181
|
-
|
|
2182
|
-
// src/sources/registry-ref.ts
|
|
2183
|
-
function parseRegistrySourceRef(source) {
|
|
2184
|
-
let s = source;
|
|
2185
|
-
if (s.startsWith("registry:")) {
|
|
2186
|
-
s = s.slice(9);
|
|
2187
|
-
}
|
|
2188
|
-
if (!s) {
|
|
2189
|
-
throw new Error(`Invalid registry source reference: "${source}". Expected pack name.`);
|
|
2190
|
-
}
|
|
2191
|
-
let version = "latest";
|
|
2192
|
-
const atIdx = s.indexOf("@");
|
|
2193
|
-
if (atIdx > 0) {
|
|
2194
|
-
version = s.slice(atIdx + 1);
|
|
2195
|
-
s = s.slice(0, atIdx);
|
|
2196
|
-
}
|
|
2197
|
-
if (!s) {
|
|
2198
|
-
throw new Error(`Invalid registry source reference: "${source}". Pack name is empty.`);
|
|
2199
|
-
}
|
|
2200
|
-
if (!/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(s)) {
|
|
2201
|
-
throw new Error(`Invalid registry pack name: "${s}". Must be lowercase alphanumeric with hyphens.`);
|
|
2202
|
-
}
|
|
2203
|
-
return { packName: s, version };
|
|
2204
|
-
}
|
|
2205
|
-
function isRegistryPackRef(packRef) {
|
|
2206
|
-
return packRef.startsWith("registry:");
|
|
2207
|
-
}
|
|
2208
|
-
function registrySourceKey(parsed) {
|
|
2209
|
-
return `registry:${parsed.packName}`;
|
|
2210
|
-
}
|
|
2211
|
-
|
|
2212
|
-
// src/utils/model-guidance.ts
|
|
2213
|
-
function generateModelGuidanceMarkdown(resolved) {
|
|
2214
|
-
if (!resolved.default && !resolved.small && Object.keys(resolved.agents).length === 0 && Object.keys(resolved.profiles).length === 0) {
|
|
2215
|
-
return null;
|
|
2216
|
-
}
|
|
2217
|
-
const lines = [];
|
|
2218
|
-
lines.push("# Model Configuration");
|
|
2219
|
-
lines.push("");
|
|
2220
|
-
lines.push("Use the following model preferences when working in this project.");
|
|
2221
|
-
lines.push("");
|
|
2222
|
-
if (resolved.default || resolved.small) {
|
|
2223
|
-
lines.push("## Default Models");
|
|
2224
|
-
lines.push("");
|
|
2225
|
-
if (resolved.default) {
|
|
2226
|
-
lines.push(`- **Primary model**: ${resolved.default}`);
|
|
2227
|
-
}
|
|
2228
|
-
if (resolved.small) {
|
|
2229
|
-
lines.push(`- **Lightweight tasks** (titles, summaries): ${resolved.small}`);
|
|
2230
|
-
}
|
|
2231
|
-
lines.push("");
|
|
2232
|
-
}
|
|
2233
|
-
const agentEntries = Object.entries(resolved.agents);
|
|
2234
|
-
if (agentEntries.length > 0) {
|
|
2235
|
-
lines.push("## Agent Model Assignments");
|
|
2236
|
-
lines.push("");
|
|
2237
|
-
lines.push("| Agent | Model | Temperature |");
|
|
2238
|
-
lines.push("| --- | --- | --- |");
|
|
2239
|
-
for (const [name, assignment] of agentEntries) {
|
|
2240
|
-
const temp = assignment.temperature !== undefined ? String(assignment.temperature) : "\u2014";
|
|
2241
|
-
lines.push(`| ${name} | ${assignment.model} | ${temp} |`);
|
|
2242
|
-
}
|
|
2243
|
-
lines.push("");
|
|
2244
|
-
}
|
|
2245
|
-
if (Object.keys(resolved.profiles).length > 0) {
|
|
2246
|
-
lines.push("## Available Profiles");
|
|
2247
|
-
lines.push("");
|
|
2248
|
-
lines.push("| Profile | Description | Default Model |");
|
|
2249
|
-
lines.push("| --- | --- | --- |");
|
|
2250
|
-
for (const [name, profile] of Object.entries(resolved.profiles)) {
|
|
2251
|
-
lines.push(`| ${name} | ${profile.description ?? "\u2014"} | ${profile.default ?? "\u2014"} |`);
|
|
2252
|
-
}
|
|
2253
|
-
lines.push("");
|
|
2254
|
-
}
|
|
2255
|
-
if (resolved.activeProfile) {
|
|
2256
|
-
lines.push(`**Active profile**: \`${resolved.activeProfile}\``);
|
|
2257
|
-
lines.push("");
|
|
2258
|
-
}
|
|
2259
|
-
if (resolved.routing.length > 0) {
|
|
2260
|
-
lines.push("## Task-Aware Routing");
|
|
2261
|
-
lines.push("");
|
|
2262
|
-
lines.push("Select the appropriate profile based on the task context:");
|
|
2263
|
-
lines.push("");
|
|
2264
|
-
lines.push("| Condition | Profile | Description |");
|
|
2265
|
-
lines.push("| --- | --- | --- |");
|
|
2266
|
-
for (const rule of resolved.routing) {
|
|
2267
|
-
const conditions = Object.entries(rule.when).map(([k, v]) => `${k}=${v}`).join(", ");
|
|
2268
|
-
const desc = rule.description ?? "\u2014";
|
|
2269
|
-
lines.push(`| ${conditions} | ${rule.use} | ${desc} |`);
|
|
2270
|
-
}
|
|
2271
|
-
lines.push("");
|
|
2272
|
-
lines.push("### Condition Reference");
|
|
2273
|
-
lines.push("");
|
|
2274
|
-
lines.push("- **complexity**: low | medium | high | critical");
|
|
2275
|
-
lines.push("- **urgency**: low | normal | high");
|
|
2276
|
-
lines.push("- **budget**: minimal | standard | premium");
|
|
2277
|
-
lines.push("- **contextWindowNeed**: small | medium | large | max");
|
|
2278
|
-
lines.push("- **toolUseIntensity**: none | light | heavy");
|
|
2279
|
-
lines.push("");
|
|
2280
|
-
}
|
|
2281
|
-
return lines.join(`
|
|
2282
|
-
`);
|
|
2283
|
-
}
|
|
2284
|
-
|
|
2285
|
-
// src/targets/base-target.ts
|
|
2286
|
-
class BaseTarget {
|
|
2287
|
-
supportsFeature(feature) {
|
|
2288
|
-
return this.supportedFeatures.includes(feature);
|
|
2289
|
-
}
|
|
2290
|
-
getEffectiveFeatures(enabledFeatures) {
|
|
2291
|
-
return enabledFeatures.filter((f) => this.supportsFeature(f));
|
|
2292
|
-
}
|
|
2293
|
-
createResult(filesWritten = [], filesDeleted = [], warnings = []) {
|
|
2294
|
-
return {
|
|
2295
|
-
targetId: this.id,
|
|
2296
|
-
filesWritten,
|
|
2297
|
-
filesDeleted,
|
|
2298
|
-
warnings
|
|
2299
|
-
};
|
|
2300
|
-
}
|
|
2301
|
-
}
|
|
2302
|
-
|
|
2303
|
-
// src/targets/generic-md-target.ts
|
|
2304
|
-
import { join as join15, resolve as resolve12 } from "path";
|
|
2305
|
-
function createGenericMdTarget(config) {
|
|
2306
|
-
return new GenericMdTarget(config);
|
|
2307
|
-
}
|
|
2308
|
-
|
|
2309
|
-
class GenericMdTarget extends BaseTarget {
|
|
2310
|
-
id;
|
|
2311
|
-
name;
|
|
2312
|
-
supportedFeatures;
|
|
2313
|
-
config;
|
|
2314
|
-
constructor(config) {
|
|
2315
|
-
super();
|
|
2316
|
-
this.id = config.id;
|
|
2317
|
-
this.name = config.name;
|
|
2318
|
-
this.supportedFeatures = config.supportedFeatures;
|
|
2319
|
-
this.config = config;
|
|
2320
|
-
}
|
|
2321
|
-
generate(options) {
|
|
2322
|
-
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
2323
|
-
const root = resolve12(projectRoot, baseDir);
|
|
2324
|
-
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
2325
|
-
const filesWritten = [];
|
|
2326
|
-
const filesDeleted = [];
|
|
2327
|
-
const warnings = [];
|
|
2328
|
-
const configDir = resolve12(root, this.config.configDir);
|
|
2329
|
-
const rulesSubDir = this.config.rulesDir ?? "rules";
|
|
2330
|
-
const ext = this.config.ruleExtension ?? ".md";
|
|
2331
|
-
if (effective.includes("rules")) {
|
|
2332
|
-
const rulesDir = resolve12(configDir, rulesSubDir);
|
|
2333
|
-
if (deleteExisting) {
|
|
2334
|
-
removeIfExists(rulesDir);
|
|
2335
|
-
filesDeleted.push(rulesDir);
|
|
2336
|
-
}
|
|
2337
|
-
ensureDir(rulesDir);
|
|
2338
|
-
const rules = features.rules.filter((r) => ruleMatchesTarget(r, this.id));
|
|
2339
|
-
for (const rule of rules) {
|
|
2340
|
-
const filepath = join15(rulesDir, `${rule.name}${ext}`);
|
|
2341
|
-
writeGeneratedFile(filepath, rule.content);
|
|
2342
|
-
filesWritten.push(filepath);
|
|
2343
|
-
}
|
|
2344
|
-
}
|
|
2345
|
-
if (effective.includes("commands")) {
|
|
2346
|
-
const commandsDir = resolve12(configDir, "commands");
|
|
2347
|
-
if (deleteExisting) {
|
|
2348
|
-
removeIfExists(commandsDir);
|
|
2349
|
-
filesDeleted.push(commandsDir);
|
|
2350
|
-
}
|
|
2351
|
-
ensureDir(commandsDir);
|
|
2352
|
-
const commands = features.commands.filter((c) => commandMatchesTarget(c, this.id));
|
|
2353
|
-
for (const cmd of commands) {
|
|
2354
|
-
const filepath = join15(commandsDir, `${cmd.name}.md`);
|
|
2355
|
-
writeGeneratedFile(filepath, cmd.content);
|
|
2356
|
-
filesWritten.push(filepath);
|
|
2357
|
-
}
|
|
2358
|
-
}
|
|
2359
|
-
if (effective.includes("mcp")) {
|
|
2360
|
-
const mcpEntries = Object.entries(features.mcpServers);
|
|
2361
|
-
if (mcpEntries.length > 0) {
|
|
2362
|
-
const mcpDir = this.config.mcpInConfigDir ? configDir : root;
|
|
2363
|
-
const filepath = resolve12(mcpDir, "mcp.json");
|
|
2364
|
-
writeGeneratedJson(filepath, { mcpServers: features.mcpServers }, {
|
|
2365
|
-
header: false
|
|
2366
|
-
});
|
|
2367
|
-
filesWritten.push(filepath);
|
|
2368
|
-
}
|
|
2369
|
-
}
|
|
2370
|
-
if (effective.includes("ignore") && this.config.ignoreFile) {
|
|
2371
|
-
if (features.ignorePatterns.length > 0) {
|
|
2372
|
-
const filepath = resolve12(root, this.config.ignoreFile);
|
|
2373
|
-
writeGeneratedFile(filepath, features.ignorePatterns.join(`
|
|
2374
|
-
`) + `
|
|
2375
|
-
`);
|
|
2376
|
-
filesWritten.push(filepath);
|
|
2377
|
-
}
|
|
2378
|
-
}
|
|
2379
|
-
if (effective.includes("models") && features.models) {
|
|
2380
|
-
const resolved = resolveModels(features.models, options.modelProfile, this.id);
|
|
2381
|
-
const guidance = generateModelGuidanceMarkdown(resolved);
|
|
2382
|
-
if (guidance) {
|
|
2383
|
-
ensureDir(configDir);
|
|
2384
|
-
const filepath = join15(configDir, "model-config.md");
|
|
2385
|
-
writeGeneratedFile(filepath, guidance);
|
|
2386
|
-
filesWritten.push(filepath);
|
|
2387
|
-
}
|
|
2388
|
-
}
|
|
2389
|
-
return this.createResult(filesWritten, filesDeleted, warnings);
|
|
2390
|
-
}
|
|
2391
|
-
}
|
|
2392
|
-
|
|
2393
|
-
// src/targets/additional-targets.ts
|
|
2394
|
-
var ClineTarget = createGenericMdTarget({
|
|
2395
|
-
id: "cline",
|
|
2396
|
-
name: "Cline",
|
|
2397
|
-
configDir: ".cline",
|
|
2398
|
-
supportedFeatures: ["rules", "commands", "mcp", "ignore"],
|
|
2399
|
-
ignoreFile: ".clineignore",
|
|
2400
|
-
mcpInConfigDir: true
|
|
2401
|
-
});
|
|
2402
|
-
var KiloTarget = createGenericMdTarget({
|
|
2403
|
-
id: "kilo",
|
|
2404
|
-
name: "Kilo Code",
|
|
2405
|
-
configDir: ".kilo",
|
|
2406
|
-
supportedFeatures: ["rules", "commands", "mcp", "ignore"],
|
|
2407
|
-
ignoreFile: ".kiloignore",
|
|
2408
|
-
mcpInConfigDir: true
|
|
2409
|
-
});
|
|
2410
|
-
var RooTarget = createGenericMdTarget({
|
|
2411
|
-
id: "roo",
|
|
2412
|
-
name: "Roo Code",
|
|
2413
|
-
configDir: ".roo",
|
|
2414
|
-
supportedFeatures: ["rules", "commands", "mcp", "ignore"],
|
|
2415
|
-
ignoreFile: ".rooignore",
|
|
2416
|
-
mcpInConfigDir: true
|
|
2417
|
-
});
|
|
2418
|
-
var QwenCodeTarget = createGenericMdTarget({
|
|
2419
|
-
id: "qwencode",
|
|
2420
|
-
name: "Qwen Code",
|
|
2421
|
-
configDir: ".qwencode",
|
|
2422
|
-
supportedFeatures: ["rules", "mcp", "ignore"],
|
|
2423
|
-
ignoreFile: ".qwencodeignore",
|
|
2424
|
-
mcpInConfigDir: true
|
|
2425
|
-
});
|
|
2426
|
-
var KiroTarget = createGenericMdTarget({
|
|
2427
|
-
id: "kiro",
|
|
2428
|
-
name: "Kiro",
|
|
2429
|
-
configDir: ".kiro",
|
|
2430
|
-
supportedFeatures: ["rules", "mcp"],
|
|
2431
|
-
mcpInConfigDir: true
|
|
2432
|
-
});
|
|
2433
|
-
var FactoryDroidTarget = createGenericMdTarget({
|
|
2434
|
-
id: "factorydroid",
|
|
2435
|
-
name: "Factory Droid",
|
|
2436
|
-
configDir: ".factorydroid",
|
|
2437
|
-
supportedFeatures: ["rules", "mcp"],
|
|
2438
|
-
mcpInConfigDir: true
|
|
2439
|
-
});
|
|
2440
|
-
var AntiGravityTarget = createGenericMdTarget({
|
|
2441
|
-
id: "antigravity",
|
|
2442
|
-
name: "AntiGravity",
|
|
2443
|
-
configDir: ".antigravity",
|
|
2444
|
-
supportedFeatures: ["rules", "mcp"],
|
|
2445
|
-
mcpInConfigDir: true
|
|
2446
|
-
});
|
|
2447
|
-
var JunieTarget = createGenericMdTarget({
|
|
2448
|
-
id: "junie",
|
|
2449
|
-
name: "Junie",
|
|
2450
|
-
configDir: ".junie",
|
|
2451
|
-
supportedFeatures: ["rules", "mcp"],
|
|
2452
|
-
mcpInConfigDir: true
|
|
2453
|
-
});
|
|
2454
|
-
var AugmentCodeTarget = createGenericMdTarget({
|
|
2455
|
-
id: "augmentcode",
|
|
2456
|
-
name: "Augment Code",
|
|
2457
|
-
configDir: ".augmentcode",
|
|
2458
|
-
supportedFeatures: ["rules", "mcp"],
|
|
2459
|
-
mcpInConfigDir: true
|
|
2460
|
-
});
|
|
2461
|
-
var WindsurfTarget = createGenericMdTarget({
|
|
2462
|
-
id: "windsurf",
|
|
2463
|
-
name: "Windsurf",
|
|
2464
|
-
configDir: ".windsurf",
|
|
2465
|
-
supportedFeatures: ["rules", "mcp", "ignore"],
|
|
2466
|
-
ignoreFile: ".windsurfignore",
|
|
2467
|
-
mcpInConfigDir: true
|
|
2468
|
-
});
|
|
2469
|
-
var WarpTarget = createGenericMdTarget({
|
|
2470
|
-
id: "warp",
|
|
2471
|
-
name: "Warp",
|
|
2472
|
-
configDir: ".warp",
|
|
2473
|
-
supportedFeatures: ["rules"]
|
|
2474
|
-
});
|
|
2475
|
-
var ReplitTarget = createGenericMdTarget({
|
|
2476
|
-
id: "replit",
|
|
2477
|
-
name: "Replit Agent",
|
|
2478
|
-
configDir: ".replit",
|
|
2479
|
-
supportedFeatures: ["rules", "mcp"],
|
|
2480
|
-
mcpInConfigDir: true
|
|
2481
|
-
});
|
|
2482
|
-
var ZedTarget = createGenericMdTarget({
|
|
2483
|
-
id: "zed",
|
|
2484
|
-
name: "Zed",
|
|
2485
|
-
configDir: ".zed",
|
|
2486
|
-
supportedFeatures: ["rules", "mcp"],
|
|
2487
|
-
mcpInConfigDir: true
|
|
2488
|
-
});
|
|
2489
|
-
|
|
2490
|
-
// src/targets/agents-md.ts
|
|
2491
|
-
import { resolve as resolve13 } from "path";
|
|
2492
|
-
class AgentsMdTarget extends BaseTarget {
|
|
2493
|
-
id = "agentsmd";
|
|
2494
|
-
name = "AGENTS.md";
|
|
2495
|
-
supportedFeatures = ["rules"];
|
|
2496
|
-
generate(options) {
|
|
2497
|
-
const { projectRoot, baseDir, features } = options;
|
|
2498
|
-
const root = resolve13(projectRoot, baseDir);
|
|
2499
|
-
const filesWritten = [];
|
|
2500
|
-
const warnings = [];
|
|
2501
|
-
const rootRules = getRootRules(features.rules);
|
|
2502
|
-
if (rootRules.length === 0) {
|
|
2503
|
-
warnings.push("No root rules found. AGENTS.md will not be generated.");
|
|
2504
|
-
return this.createResult(filesWritten, [], warnings);
|
|
2505
|
-
}
|
|
2506
|
-
const sections = rootRules.map((r) => r.content);
|
|
2507
|
-
const content = sections.join(`
|
|
2508
|
-
|
|
2509
|
-
`);
|
|
2510
|
-
const filepath = resolve13(root, "AGENTS.md");
|
|
2511
|
-
writeGeneratedFile(filepath, content);
|
|
2512
|
-
filesWritten.push(filepath);
|
|
2513
|
-
return this.createResult(filesWritten, [], warnings);
|
|
2514
|
-
}
|
|
2515
|
-
}
|
|
2516
|
-
|
|
2517
|
-
// src/targets/claude-code.ts
|
|
2518
|
-
import { join as join16, resolve as resolve14 } from "path";
|
|
2519
|
-
var TARGET_ID = "claudecode";
|
|
2520
|
-
|
|
2521
|
-
class ClaudeCodeTarget extends BaseTarget {
|
|
2522
|
-
id = TARGET_ID;
|
|
2523
|
-
name = "Claude Code";
|
|
2524
|
-
supportedFeatures = [
|
|
2525
|
-
"rules",
|
|
2526
|
-
"commands",
|
|
2527
|
-
"agents",
|
|
2528
|
-
"skills",
|
|
2529
|
-
"hooks",
|
|
2530
|
-
"mcp",
|
|
2531
|
-
"ignore",
|
|
2532
|
-
"models"
|
|
2533
|
-
];
|
|
2534
|
-
generate(options) {
|
|
2535
|
-
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
2536
|
-
const root = resolve14(projectRoot, baseDir);
|
|
2537
|
-
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
2538
|
-
const filesWritten = [];
|
|
2539
|
-
const filesDeleted = [];
|
|
2540
|
-
const warnings = [];
|
|
2541
|
-
const claudeDir = resolve14(root, ".claude");
|
|
2542
|
-
if (effective.includes("rules")) {
|
|
2543
|
-
const rulesDir = resolve14(claudeDir, "rules");
|
|
2544
|
-
if (deleteExisting) {
|
|
2545
|
-
removeIfExists(rulesDir);
|
|
2546
|
-
filesDeleted.push(rulesDir);
|
|
2547
|
-
}
|
|
2548
|
-
ensureDir(rulesDir);
|
|
2549
|
-
const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID));
|
|
2550
|
-
const rootRules = getRootRules(rules);
|
|
2551
|
-
const detailRules = getDetailRules(rules);
|
|
2552
|
-
if (rootRules.length > 0) {
|
|
2553
|
-
const claudeMd = rootRules.map((r) => r.content).join(`
|
|
2554
|
-
|
|
2555
|
-
`);
|
|
2556
|
-
const filepath = resolve14(claudeDir, "CLAUDE.md");
|
|
2557
|
-
writeGeneratedFile(filepath, claudeMd);
|
|
2558
|
-
filesWritten.push(filepath);
|
|
2559
|
-
}
|
|
2560
|
-
for (const rule of detailRules) {
|
|
2561
|
-
const filepath = join16(rulesDir, `${rule.name}.md`);
|
|
2562
|
-
writeGeneratedFile(filepath, rule.content);
|
|
2563
|
-
filesWritten.push(filepath);
|
|
2564
|
-
}
|
|
2565
|
-
}
|
|
2566
|
-
if (effective.includes("agents")) {
|
|
2567
|
-
const agentsDir = resolve14(claudeDir, "agents");
|
|
2568
|
-
if (deleteExisting) {
|
|
2569
|
-
removeIfExists(agentsDir);
|
|
2570
|
-
filesDeleted.push(agentsDir);
|
|
2571
|
-
}
|
|
2572
|
-
ensureDir(agentsDir);
|
|
2573
|
-
const resolvedModels = features.models ? resolveModels(features.models, options.modelProfile, TARGET_ID) : null;
|
|
2574
|
-
const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID));
|
|
2575
|
-
for (const agent of agents) {
|
|
2576
|
-
const filepath = join16(agentsDir, `${agent.name}.md`);
|
|
2577
|
-
const cc = agent.meta.claudecode ?? {};
|
|
2578
|
-
const modelsAgent = resolvedModels?.agents[agent.name];
|
|
2579
|
-
const agentModel = modelsAgent?.model ?? cc.model;
|
|
2580
|
-
let content = agent.content;
|
|
2581
|
-
if (agentModel) {
|
|
2582
|
-
content = `<!-- model: ${agentModel} -->
|
|
2583
|
-
${content}`;
|
|
2584
|
-
}
|
|
2585
|
-
writeGeneratedFile(filepath, content);
|
|
2586
|
-
filesWritten.push(filepath);
|
|
2587
|
-
}
|
|
2588
|
-
}
|
|
2589
|
-
if (effective.includes("skills")) {
|
|
2590
|
-
const skillsDir = resolve14(claudeDir, "skills");
|
|
2591
|
-
if (deleteExisting) {
|
|
2592
|
-
removeIfExists(skillsDir);
|
|
2593
|
-
filesDeleted.push(skillsDir);
|
|
2594
|
-
}
|
|
2595
|
-
ensureDir(skillsDir);
|
|
2596
|
-
const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID));
|
|
2597
|
-
for (const skill of skills) {
|
|
2598
|
-
const skillSubDir = join16(skillsDir, skill.name);
|
|
2599
|
-
ensureDir(skillSubDir);
|
|
2600
|
-
const filepath = join16(skillSubDir, "SKILL.md");
|
|
2601
|
-
writeGeneratedFile(filepath, serializeSkill(skill));
|
|
2602
|
-
filesWritten.push(filepath);
|
|
2603
|
-
}
|
|
2604
|
-
}
|
|
2605
|
-
if (effective.includes("commands")) {
|
|
2606
|
-
const commandsDir = resolve14(claudeDir, "commands");
|
|
2607
|
-
if (deleteExisting) {
|
|
2608
|
-
removeIfExists(commandsDir);
|
|
2609
|
-
filesDeleted.push(commandsDir);
|
|
2610
|
-
}
|
|
2611
|
-
ensureDir(commandsDir);
|
|
2612
|
-
const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID));
|
|
2613
|
-
for (const cmd of commands) {
|
|
2614
|
-
const filepath = join16(commandsDir, `${cmd.name}.md`);
|
|
2615
|
-
writeGeneratedFile(filepath, cmd.content);
|
|
2616
|
-
filesWritten.push(filepath);
|
|
2617
|
-
}
|
|
2618
|
-
}
|
|
2619
|
-
if (effective.includes("models") && features.models) {
|
|
2620
|
-
const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID);
|
|
2621
|
-
const guidance = generateModelGuidanceMarkdown(resolved);
|
|
2622
|
-
if (guidance) {
|
|
2623
|
-
const rulesDir = resolve14(claudeDir, "rules");
|
|
2624
|
-
ensureDir(rulesDir);
|
|
2625
|
-
const filepath = join16(rulesDir, "model-config.md");
|
|
2626
|
-
writeGeneratedFile(filepath, guidance);
|
|
2627
|
-
filesWritten.push(filepath);
|
|
2628
|
-
}
|
|
2629
|
-
}
|
|
2630
|
-
if (effective.includes("hooks") || effective.includes("mcp") || effective.includes("ignore")) {
|
|
2631
|
-
const settings = buildClaudeSettings(options, effective);
|
|
2632
|
-
if (Object.keys(settings).length > 0) {
|
|
2633
|
-
const filepath = resolve14(claudeDir, "settings.json");
|
|
2634
|
-
const existing = readJsonOrNull(filepath) ?? {};
|
|
2635
|
-
const merged = { ...existing, ...settings };
|
|
2636
|
-
writeGeneratedJson(filepath, merged, { header: false });
|
|
2637
|
-
filesWritten.push(filepath);
|
|
2638
|
-
}
|
|
2639
|
-
}
|
|
2640
|
-
return this.createResult(filesWritten, filesDeleted, warnings);
|
|
2641
|
-
}
|
|
2642
|
-
}
|
|
2643
|
-
function buildClaudeSettings(options, effective) {
|
|
2644
|
-
const settings = {};
|
|
2645
|
-
if (effective.includes("hooks")) {
|
|
2646
|
-
const allHookEntries = {};
|
|
2647
|
-
for (const hookSet of options.features.hooks) {
|
|
2648
|
-
const events = resolveHooksForTarget(hookSet, TARGET_ID);
|
|
2649
|
-
for (const [event, entries] of Object.entries(events)) {
|
|
2650
|
-
const pascalEvent = toPascalCase(event);
|
|
2651
|
-
if (!allHookEntries[pascalEvent]) {
|
|
2652
|
-
allHookEntries[pascalEvent] = [];
|
|
2653
|
-
}
|
|
2654
|
-
allHookEntries[pascalEvent].push(...entries.map((e) => ({
|
|
2655
|
-
type: e.type ?? "command",
|
|
2656
|
-
...e.matcher ? { matcher: e.matcher } : {},
|
|
2657
|
-
command: e.command
|
|
2658
|
-
})));
|
|
2659
|
-
}
|
|
2660
|
-
}
|
|
2661
|
-
if (Object.keys(allHookEntries).length > 0) {
|
|
2662
|
-
settings.hooks = allHookEntries;
|
|
2663
|
-
}
|
|
2664
|
-
}
|
|
2665
|
-
if (effective.includes("mcp")) {
|
|
2666
|
-
const mcpEntries = Object.entries(options.features.mcpServers);
|
|
2667
|
-
if (mcpEntries.length > 0) {
|
|
2668
|
-
const mcpServers = {};
|
|
2669
|
-
for (const [name, entry] of mcpEntries) {
|
|
2670
|
-
if (entry.url) {
|
|
2671
|
-
mcpServers[name] = { url: entry.url };
|
|
2672
|
-
} else if (entry.command) {
|
|
2673
|
-
mcpServers[name] = {
|
|
2674
|
-
command: entry.command,
|
|
2675
|
-
...entry.args ? { args: entry.args } : {},
|
|
2676
|
-
...entry.env ? { env: entry.env } : {}
|
|
2677
|
-
};
|
|
2678
|
-
}
|
|
2679
|
-
}
|
|
2680
|
-
settings.mcpServers = mcpServers;
|
|
2681
|
-
}
|
|
2682
|
-
}
|
|
2683
|
-
return settings;
|
|
2684
|
-
}
|
|
2685
|
-
function toPascalCase(str) {
|
|
2686
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
2687
|
-
}
|
|
2688
|
-
|
|
2689
|
-
// src/targets/codex-cli.ts
|
|
2690
|
-
import { join as join17, resolve as resolve15 } from "path";
|
|
2691
|
-
var TARGET_ID2 = "codexcli";
|
|
2692
|
-
|
|
2693
|
-
class CodexCliTarget extends BaseTarget {
|
|
2694
|
-
id = TARGET_ID2;
|
|
2695
|
-
name = "Codex CLI";
|
|
2696
|
-
supportedFeatures = ["rules", "skills", "mcp", "hooks"];
|
|
2697
|
-
generate(options) {
|
|
2698
|
-
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
2699
|
-
const root = resolve15(projectRoot, baseDir);
|
|
2700
|
-
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
2701
|
-
const filesWritten = [];
|
|
2702
|
-
const filesDeleted = [];
|
|
2703
|
-
const warnings = [];
|
|
2704
|
-
const codexDir = resolve15(root, ".codex");
|
|
2705
|
-
if (effective.includes("rules")) {
|
|
2706
|
-
const memoriesDir = resolve15(codexDir, "memories");
|
|
2707
|
-
if (deleteExisting) {
|
|
2708
|
-
removeIfExists(memoriesDir);
|
|
2709
|
-
filesDeleted.push(memoriesDir);
|
|
2710
|
-
}
|
|
2711
|
-
ensureDir(memoriesDir);
|
|
2712
|
-
const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID2));
|
|
2713
|
-
for (const rule of rules) {
|
|
2714
|
-
const filepath = join17(memoriesDir, `${rule.name}.md`);
|
|
2715
|
-
writeGeneratedFile(filepath, rule.content);
|
|
2716
|
-
filesWritten.push(filepath);
|
|
2717
|
-
}
|
|
2718
|
-
}
|
|
2719
|
-
if (effective.includes("skills")) {
|
|
2720
|
-
const skillsDir = resolve15(codexDir, "skills");
|
|
2721
|
-
if (deleteExisting) {
|
|
2722
|
-
removeIfExists(skillsDir);
|
|
2723
|
-
filesDeleted.push(skillsDir);
|
|
2724
|
-
}
|
|
2725
|
-
ensureDir(skillsDir);
|
|
2726
|
-
const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID2));
|
|
2727
|
-
for (const skill of skills) {
|
|
2728
|
-
const skillSubDir = join17(skillsDir, skill.name);
|
|
2729
|
-
ensureDir(skillSubDir);
|
|
2730
|
-
const filepath = join17(skillSubDir, "SKILL.md");
|
|
2731
|
-
writeGeneratedFile(filepath, serializeSkill(skill));
|
|
2732
|
-
filesWritten.push(filepath);
|
|
2733
|
-
}
|
|
2734
|
-
}
|
|
2735
|
-
return this.createResult(filesWritten, filesDeleted, warnings);
|
|
2736
|
-
}
|
|
2737
|
-
}
|
|
2738
|
-
|
|
2739
|
-
// src/targets/copilot.ts
|
|
2740
|
-
import { join as join18, resolve as resolve16 } from "path";
|
|
2741
|
-
var TARGET_ID3 = "copilot";
|
|
2742
|
-
|
|
2743
|
-
class CopilotTarget extends BaseTarget {
|
|
2744
|
-
id = TARGET_ID3;
|
|
2745
|
-
name = "GitHub Copilot";
|
|
2746
|
-
supportedFeatures = [
|
|
2747
|
-
"rules",
|
|
2748
|
-
"commands",
|
|
2749
|
-
"agents",
|
|
2750
|
-
"skills",
|
|
2751
|
-
"mcp",
|
|
2752
|
-
"ignore",
|
|
2753
|
-
"models"
|
|
2754
|
-
];
|
|
2755
|
-
generate(options) {
|
|
2756
|
-
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
2757
|
-
const root = resolve16(projectRoot, baseDir);
|
|
2758
|
-
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
2759
|
-
const filesWritten = [];
|
|
2760
|
-
const filesDeleted = [];
|
|
2761
|
-
const warnings = [];
|
|
2762
|
-
const githubDir = resolve16(root, ".github");
|
|
2763
|
-
if (effective.includes("rules")) {
|
|
2764
|
-
const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID3));
|
|
2765
|
-
if (rules.length > 0) {
|
|
2766
|
-
const combinedContent = rules.map((r) => r.content).join(`
|
|
2
|
+
var k1=import.meta.require;import{existsSync as I$,readFileSync as E$}from"fs";import{parse as j2}from"jsonc-parser";import{resolve as T$}from"path";import{z as N}from"zod";var R$=["opencode","cursor","claudecode","codexcli","mistralvibe","geminicli","copilot","cline","kilo","roo","qwencode","kiro","factorydroid","antigravity","junie","augmentcode","windsurf","warp","replit","zed"],K0=["rules","commands","agents","skills","hooks","plugins","mcp","ignore","models"],S$=["repo","monorepo","metarepo"],D0=N.object({name:N.string().min(1),version:N.string().default("1.0.0"),description:N.string().default(""),author:N.union([N.string(),N.object({name:N.string(),email:N.string().optional()})]).optional(),homepage:N.string().optional(),repository:N.union([N.string(),N.object({url:N.string(),type:N.string().optional()})]).optional(),license:N.string().optional(),logo:N.string().optional(),tags:N.array(N.string()).default([]),dependencies:N.array(N.string()).default([]),conflicts:N.array(N.string()).default([]),targets:N.union([N.literal("*"),N.array(N.string())]).default("*"),features:N.union([N.literal("*"),N.array(N.string())]).default("*")}),h2=N.union([N.literal("*"),N.array(N.string()),N.record(N.string(),N.union([N.literal("*"),N.array(N.string())]))]),u0=N.object({$schema:N.string().optional(),packs:N.array(N.string()).default(["./packs/default"]),disabled:N.array(N.string()).default([]),targets:N.union([N.literal("*"),N.array(N.string())]).default("*"),features:h2.default("*"),mode:N.enum(S$).default("repo"),baseDirs:N.array(N.string()).default(["."]),global:N.boolean().default(!1),delete:N.boolean().default(!0),verbose:N.boolean().default(!1),silent:N.boolean().default(!1),overrides:N.record(N.string(),N.record(N.string(),N.string())).default({}),sources:N.array(N.object({source:N.string(),packs:N.array(N.string()).optional(),skills:N.array(N.string()).optional()})).default([]),modelProfile:N.string().optional()}),v2=["agentpacks.local.jsonc","agentpacks.jsonc"];function f0($){for(let Q of v2){let Y=T$($,Q);if(I$(Y)){let Z=E$(Y,"utf-8"),q=j2(Z);return u0.parse(q)}}return u0.parse({})}function p0($){let Q=T$($,"pack.json");if(!I$(Q)){let q=$.split("/").pop()??"unknown";return D0.parse({name:q})}let Y=E$(Q,"utf-8"),Z=JSON.parse(Y);return D0.parse(Z)}function k2($,Q){let{features:Y}=$;if(Y==="*")return[...K0];if(Array.isArray(Y)){if(Y.includes("*"))return[...K0];return Y.filter((q)=>K0.includes(q))}let Z=Y[Q];if(!Z)return[];if(Z==="*")return[...K0];if(Array.isArray(Z)&&Z.includes("*"))return[...K0];return Z.filter((q)=>K0.includes(q))}function g2($){if($.targets==="*")return[...R$];return $.targets}function m2($){let Q=new Map;for(let Y of $)Q.set(Y.name,{name:Y.name,manifest:Y,dependencies:Y.dependencies,conflicts:Y.conflicts});return Q}function D2($){let Q=m2($),Y=new Set(Q.keys()),Z=[];for(let[H,W]of Q)for(let _ of W.dependencies)if(!Y.has(_))Z.push([H,_]);let{sorted:q,cycles:X}=u2(Q),J=p2(Q),K=X.length===0&&J.length===0&&Z.length===0;return{sorted:q,cycles:X,conflictPairs:J,missingDeps:Z,ok:K}}function u2($){let Q=new Map;for(let X of $.keys())Q.set(X,0);for(let[,X]of $)for(let J of X.dependencies)if($.has(J))Q.set(J,(Q.get(J)??0)+1);let Y=[];for(let[X,J]of Q)if(J===0)Y.push(X);let Z=[];while(Y.length>0){let X=Y.shift();if(!X)continue;Z.push(X);let J=$.get(X);if(!J)continue;for(let K of J.dependencies){if(!$.has(K))continue;let H=(Q.get(K)??1)-1;if(Q.set(K,H),H===0)Y.push(K)}}let q=[];if(Z.length<$.size){let X=new Set;for(let K of $.keys())if(!Z.includes(K))X.add(K);let J=new Set;for(let K of X){if(J.has(K))continue;let H=f2(K,$,X);if(H.length>0){q.push(H);for(let W of H)J.add(W)}}}return{sorted:Z.reverse(),cycles:q}}function f2($,Q,Y){let Z=[],q=new Set,X=$;while(X&&!q.has(X)){Z.push(X),q.add(X);let J=Q.get(X);if(!J)break;X=J.dependencies.find((K)=>Y.has(K)&&Q.has(K))}if(X&&q.has(X)){let J=Z.indexOf(X);return Z.slice(J)}return Z}function p2($){let Q=[],Y=new Set;for(let[Z,q]of $)for(let X of q.conflicts)if($.has(X)){let J=[Z,X].sort().join(":");if(!Y.has(J))Y.add(J),Q.push([Z,X])}return Q}import{existsSync as F0,mkdirSync as d2,readdirSync as y$,readFileSync as c2,rmSync as n2,statSync as j$,writeFileSync as o2}from"fs";import{dirname as l2,join as h$,relative as a2}from"path";var v$="<!-- Generated by agentpacks. DO NOT EDIT. -->",k$="// Generated by agentpacks. DO NOT EDIT.",g$="// Generated by agentpacks. DO NOT EDIT.";function G($,Q,Y={}){let{header:Z=!0,type:q}=Y,X=q??t2($);A(l2($));let J=Q;if(Z){let K=s2(X);if(K)J=`${K}
|
|
3
|
+
${Q}`}o2($,J,"utf-8")}function S($,Q,Y={}){let Z=JSON.stringify(Q,null,2);G($,Z+`
|
|
4
|
+
`,{...Y,type:"json"})}function m$($){if(!F0($))return null;return c2($,"utf-8")}function e($){let Q=m$($);if(Q===null)return null;return JSON.parse(Q)}function A($){if(!F0($))d2($,{recursive:!0})}function w($){if(F0($))n2($,{recursive:!0,force:!0})}function F($,Q={}){let{extension:Y,recursive:Z=!1}=Q;if(!F0($))return[];let q=[],X=y$($);for(let J of X){let K=h$($,J),H=j$(K);if(H.isDirectory()&&Z)q.push(...F(K,Q));else if(H.isFile()){if(!Y||J.endsWith(Y))q.push(K)}}return q}function $0($){if(!F0($))return[];return y$($).map((Q)=>h$($,Q)).filter((Q)=>j$(Q).isDirectory())}function o1($,Q){return a2($,Q)}function l1($){let Q=m$($);if(!Q)return!1;return Q.startsWith(v$)||Q.startsWith(k$)||Q.startsWith(g$)}function t2($){if($.endsWith(".json")||$.endsWith(".jsonc"))return"json";if($.endsWith(".ts")||$.endsWith(".mts"))return"ts";if($.endsWith(".js")||$.endsWith(".mjs"))return"js";return"md"}function s2($){switch($){case"md":return v$;case"json":return k$;case"js":case"ts":return g$;default:return null}}import{join as i2}from"path";import{z as M}from"zod";var r2=[/["']api[_-]?key["']\s*:/i,/["']apiKey["']\s*:/i,/["']secret["']\s*:/i,/["']password["']\s*:/i,/["'](?:auth_token|access_token|bearer_token)["']\s*:/i,/["']private[_-]?key["']\s*:/i,/-----BEGIN\s+(RSA|EC|DSA|OPENSSH|PGP)\s+PRIVATE\s+KEY-----/,/sk-[a-zA-Z0-9]{20,}/,/Bearer\s+[a-zA-Z0-9._-]{20,}/],d0=M.object({model:M.string(),temperature:M.number().min(0).max(2).optional(),top_p:M.number().min(0).max(1).optional()}),e2=M.object({extends:M.string().optional(),description:M.string().optional(),default:M.string().optional(),small:M.string().optional(),agents:M.record(M.string(),d0).optional()}),r1=M.object({complexity:M.enum(["low","medium","high","critical"]).optional().describe("Task complexity level"),urgency:M.enum(["low","normal","high"]).optional().describe("Time sensitivity"),budget:M.enum(["minimal","standard","premium"]).optional().describe("Cost/token budget tier"),contextWindowNeed:M.enum(["small","medium","large","max"]).optional().describe("Required context window size"),toolUseIntensity:M.enum(["none","light","heavy"]).optional().describe("Expected tool/function calling intensity")}),$9=M.object({when:M.record(M.string(),M.string()),use:M.string(),description:M.string().optional(),priority:M.number().optional()}),Q9=M.object({options:M.record(M.string(),M.unknown()).optional(),variants:M.record(M.string(),M.record(M.string(),M.unknown())).optional()}),Y9=M.object({options:M.record(M.string(),M.unknown()).optional(),models:M.record(M.string(),Q9).optional()}),Z9=M.object({default:M.string().optional(),small:M.string().optional(),agents:M.record(M.string(),d0).optional(),profiles:M.record(M.string(),e2).optional(),providers:M.record(M.string(),Y9).optional(),routing:M.array($9).optional(),overrides:M.record(M.string(),M.object({default:M.string().optional(),small:M.string().optional(),agents:M.record(M.string(),d0).optional()})).optional()});function D$($,Q){let Y=i2($,"models.json"),Z=e(Y);if(!Z)return null;let q=Z9.parse(Z);return{packName:Q,sourcePath:Y,config:q}}function u$($){let Q=[],Y={};for(let Z of $){let{config:q,packName:X}=Z;if(q.default!==void 0&&Y.default===void 0)Y.default=q.default;else if(q.default!==void 0&&Y.default!==void 0)Q.push(`Models "default" from pack "${X}" skipped (already defined).`);if(q.small!==void 0&&Y.small===void 0)Y.small=q.small;else if(q.small!==void 0&&Y.small!==void 0)Q.push(`Models "small" from pack "${X}" skipped (already defined).`);if(q.agents){if(!Y.agents)Y.agents={};for(let[J,K]of Object.entries(q.agents)){if(J in Y.agents){Q.push(`Models agent "${J}" from pack "${X}" skipped (already defined).`);continue}Y.agents[J]=K}}if(q.profiles){if(!Y.profiles)Y.profiles={};for(let[J,K]of Object.entries(q.profiles)){if(J in Y.profiles){Q.push(`Models profile "${J}" from pack "${X}" skipped (already defined).`);continue}Y.profiles[J]=K}}if(q.providers){if(!Y.providers)Y.providers={};for(let[J,K]of Object.entries(q.providers))if(!(J in Y.providers))Y.providers[J]=K;else{let H=Y.providers[J];if(!H){Y.providers[J]=K;continue}if(K.options)H.options={...K.options,...H.options};if(K.models){if(!H.models)H.models={};for(let[W,_]of Object.entries(K.models))if(!(W in H.models))H.models[W]=_}}}if(q.routing){if(!Y.routing)Y.routing=[];Y.routing.push(...q.routing)}if(q.overrides){if(!Y.overrides)Y.overrides={};for(let[J,K]of Object.entries(q.overrides)){if(J in Y.overrides){Q.push(`Models override for target "${J}" from pack "${X}" skipped (already defined).`);continue}Y.overrides[J]=K}}}return{config:Y,warnings:Q}}function e1($){let Q=[],Y=JSON.stringify($);for(let Z of r2)if(Z.test(Y))Q.push(`Potential secret detected in models.json matching pattern: ${Z.source}`);return Q}class f${packs;warnings=[];constructor($){this.packs=$}merge(){return this.warnings=[],{features:{rules:this.mergeRules(),commands:this.mergeByName("commands"),agents:this.mergeByName("agents"),skills:this.mergeByName("skills"),hooks:this.mergeHooks(),plugins:this.mergePlugins(),mcpServers:this.mergeMcp(),ignorePatterns:this.mergeIgnore(),models:this.mergeModels()},warnings:this.warnings}}mergeRules(){let $=new Map,Q=[];for(let Y of this.packs)for(let Z of Y.rules){let q=$.get(Z.name);if(q){this.warnings.push(`Rule "${Z.name}" from pack "${Z.packName}" skipped (already defined by "${q}").`);continue}$.set(Z.name,Z.packName),Q.push(Z)}return Q}mergeByName($){let Q=new Map,Y=[];for(let Z of this.packs){let q=Z[$];for(let X of q){let J=Q.get(X.name);if(J){this.warnings.push(`${$.slice(0,-1)} "${X.name}" from pack "${X.packName}" skipped (already defined by "${J}").`);continue}Q.set(X.name,X.packName),Y.push(X)}}return Y}mergeHooks(){return this.packs.map(($)=>$.hooks).filter(($)=>$!==null)}mergePlugins(){let $=new Map,Q=[];for(let Y of this.packs)for(let Z of Y.plugins){let q=`${Z.name}.${Z.extension}`,X=$.get(q);if(X){this.warnings.push(`Plugin "${q}" from pack "${Z.packName}" skipped (already defined by "${X}").`);continue}$.set(q,Z.packName),Q.push(Z)}return Q}mergeMcp(){let $={};for(let Q of this.packs){if(!Q.mcp)continue;for(let[Y,Z]of Object.entries(Q.mcp.servers)){if(Y in $){this.warnings.push(`MCP server "${Y}" from pack "${Q.manifest.name}" skipped (already defined).`);continue}$[Y]=Z}}return $}mergeIgnore(){let $=new Set,Q=[];for(let Y of this.packs){if(!Y.ignore)continue;for(let Z of Y.ignore.patterns)if(!$.has(Z))$.add(Z),Q.push(Z)}return Q}mergeModels(){let $=this.packs.map((Z)=>Z.models).filter((Z)=>Z!=null);if($.length===0)return null;let{config:Q,warnings:Y}=u$($);return this.warnings.push(...Y),Q}}import{createHash as q9}from"crypto";import{existsSync as X9,readFileSync as L9,writeFileSync as U9}from"fs";import{resolve as p$}from"path";var B9=1,d$="agentpacks.lock";function V9($){let Q=p$($,d$);if(!X9(Q))return{lockfileVersion:B9,sources:{}};let Y=L9(Q,"utf-8");return JSON.parse(Y)}function K9($,Q){let Y=p$($,d$);U9(Y,JSON.stringify(Q,null,2)+`
|
|
5
|
+
`)}function R0($,Q){return $.sources[Q]}function S0($,Q,Y){$.sources[Q]=Y}function c0($){return`sha256-${q9("sha256").update($).digest("hex")}`}function L3($,Q){let Y=Q.filter((Z)=>!(Z in $.sources));return{valid:Y.length===0,missing:Y}}import c$ from"gray-matter";function d($){let{data:Q,content:Y}=c$($);return{data:Q,content:Y.trim(),raw:$}}function v($,Q){let Y=Object.fromEntries(Object.entries($).filter(([,Z])=>Z!==void 0));if(Object.keys(Y).length===0)return Q;return c$.stringify(Q,Y)}import{readFileSync as J9}from"fs";import{basename as O9}from"path";function n$($,Q){return F($,{extension:".md"}).map((Z)=>H9(Z,Q))}function H9($,Q){let Y=J9($,"utf-8"),{data:Z,content:q}=d(Y);return{name:Z.name??O9($,".md"),sourcePath:$,packName:Q,meta:Z,content:q}}function n($,Q){let{targets:Y}=$.meta;if(!Y||Y==="*")return!0;if(Array.isArray(Y)&&Y.includes("*"))return!0;return Array.isArray(Y)&&Y.includes(Q)}import{readFileSync as W9}from"fs";import{basename as P9}from"path";function o$($,Q){return F($,{extension:".md"}).map((Z)=>C9(Z,Q))}function C9($,Q){let Y=W9($,"utf-8"),{data:Z,content:q}=d(Y);return{name:P9($,".md"),sourcePath:$,packName:Q,meta:Z,content:q}}function k($,Q){let{targets:Y}=$.meta;if(!Y||Y==="*")return!0;if(Array.isArray(Y)&&Y.includes("*"))return!0;return Array.isArray(Y)&&Y.includes(Q)}import{join as _9}from"path";var A9=["cursor","claudecode","codexcli","opencode"];function l$($,Q){let Y=_9($,"hooks","hooks.json"),Z=e(Y);if(!Z)return null;let q=Z.hooks??{},X={};for(let J of A9){let K=Z[J];if(K&&typeof K==="object"&&"hooks"in K&&K.hooks)X[J]=K.hooks}return{packName:Q,sourcePath:Y,version:Z.version,shared:q,targetOverrides:X}}function o($,Q){let Y={};for(let[q,X]of Object.entries($.shared))Y[q]=[...X];let Z=$.targetOverrides[Q];if(Z)for(let[q,X]of Object.entries(Z))Y[q]=[...Y[q]??[],...X];return Y}import{existsSync as N9,readFileSync as x9}from"fs";import{join as b9}from"path";var M9=["ignore",".aiignore"];function a$($,Q){for(let Y of M9){let Z=b9($,Y);if(N9(Z)){let q=x9(Z,"utf-8"),X=G9(q);return{packName:Q,sourcePath:Z,patterns:X}}}return null}function G9($){return $.split(`
|
|
6
|
+
`).map((Q)=>Q.trim()).filter((Q)=>Q.length>0&&!Q.startsWith("#"))}function w3($){let Q=new Set,Y=[];for(let Z of $)for(let q of Z.patterns)if(!Q.has(q))Q.add(q),Y.push(q);return Y}import{join as z9}from"path";function t$($,Q){let Y=z9($,"mcp.json"),Z=e(Y);if(!Z?.mcpServers)return null;return{packName:Q,sourcePath:Y,servers:Z.mcpServers}}function T3($){let Q={},Y=[];for(let Z of $)for(let[q,X]of Object.entries(Z.servers)){if(q in Q){Y.push(`MCP server "${q}" from pack "${Z.packName}" skipped (already defined).`);continue}Q[q]=X}return{servers:Q,warnings:Y}}import{existsSync as w9,readFileSync as F9}from"fs";import{basename as I9,join as E9}from"path";function s$($,Q){let Y=E9($,"plugins");if(!w9(Y))return[];let Z=F(Y,{extension:".ts"}),q=F(Y,{extension:".js"});return[...Z,...q].map((J)=>T9(J,Q))}function T9($,Q){let Y=F9($,"utf-8"),Z=$.endsWith(".ts")?"ts":"js";return{name:I9($,`.${Z}`),sourcePath:$,packName:Q,content:Y,extension:Z}}import{readFileSync as R9}from"fs";import{basename as S9}from"path";function i$($,Q){return F($,{extension:".md"}).map((Z)=>y9(Z,Q))}function y9($,Q){let Y=R9($,"utf-8"),{data:Z,content:q}=d(Y);return{name:S9($,".md"),sourcePath:$,packName:Q,meta:Z,content:q}}function y($,Q){let{targets:Y}=$.meta;if(!Y||Y==="*")return!0;if(Array.isArray(Y)&&Y.includes("*"))return!0;return Array.isArray(Y)&&Y.includes(Q)}function y0($){return $.filter((Q)=>Q.meta.root===!0)}function _0($){return $.filter((Q)=>Q.meta.root!==!0)}import{existsSync as j9,readFileSync as h9}from"fs";import{basename as e$,join as v9}from"path";var k9=/^[a-z0-9]+(?:-[a-z0-9]+)*$/,r$=64;function $2($,Q){let Y=$0($),Z=[];for(let q of Y){let X=v9(q,"SKILL.md");if(j9(X))Z.push(g9(X,q,Q))}return Z}function g9($,Q,Y){let Z=h9($,"utf-8"),{data:q,content:X}=d(Z);return{name:q.name??e$(Q),sourcePath:$,sourceDir:Q,packName:Y,meta:q,content:X}}function n0($){return{...$.meta,name:$.name}}function D($){return v(n0($),$.content)}function A0($,Q){let{data:Y,content:Z}=d($),q={...Y,name:Q},X=!1,J=q.description;if(typeof J!=="string"||J.trim().length===0)q.description=`Imported skill: ${Q}`,X=!0;return{content:v(q,Z),addedDescription:X}}function c3($){let Q=[],Y=e$($.sourceDir),Z=$.meta.name;if(typeof Z!=="string"||Z.trim().length===0)Q.push('Missing required frontmatter field "name".');else{if(Z.length>r$)Q.push(`Invalid "name": must be at most ${r$} characters.`);if(!k9.test(Z))Q.push('Invalid "name": use lowercase letters, numbers, and single hyphens only.');if(Z!==Y)Q.push(`Invalid "name": must match containing directory "${Y}".`)}let q=$.meta.description;if(typeof q!=="string"||q.trim().length===0)Q.push('Missing required frontmatter field "description".');let X=$.meta["allowed-tools"];if(X!==void 0&&(!Array.isArray(X)||X.some((J)=>typeof J!=="string"||J.length===0)))Q.push('Invalid "allowed-tools": expected an array of non-empty strings.');return Q}function u($,Q){let{targets:Y}=$.meta;if(!Y||Y==="*")return!0;if(Array.isArray(Y)&&Y.includes("*"))return!0;return Array.isArray(Y)&&Y.includes(Q)}import{existsSync as J0}from"fs";import{isAbsolute as m9,resolve as l}from"path";class o0{projectRoot;config;constructor($,Q){this.projectRoot=$,this.config=Q}loadAll(){let $=[],Q=[],Y=new Set(this.config.disabled);for(let Z of this.config.packs){let q=this.resolvePackPath(Z);if(!q){$.push(`Pack "${Z}" could not be resolved. Skipping.`);continue}if(!J0(q)){$.push(`Pack directory "${q}" does not exist. Skipping.`);continue}let X=p0(q);if(Y.has(X.name)||Y.has(Z))continue;let J=this.loadPack(q,X);Q.push(J)}return{packs:Q,warnings:$}}loadPack($,Q){let Y=Q.name,Z=l($,"rules"),q=l($,"commands"),X=l($,"agents"),J=l($,"skills");return{manifest:Q,directory:$,rules:J0(Z)?i$(Z,Y):[],commands:J0(q)?o$(q,Y):[],agents:J0(X)?n$(X,Y):[],skills:J0(J)?$2(J,Y):[],hooks:l$($,Y),plugins:s$($,Y),mcp:t$($,Y),ignore:a$($,Y),models:D$($,Y)}}loadForBaseDir($){let Q=l(this.projectRoot,$),Y=l(Q,"agentpacks.jsonc");if(!J0(Y))return{packs:[],warnings:[]};let Z=f0(Q);return new o0(Q,Z).loadAll()}resolveCuratedPack($){let Q=l(this.projectRoot,".agentpacks",".curated"),Y=$;if(Y.startsWith("registry:"))Y=Y.slice(9);if(Y.startsWith("npm:"))Y=Y.slice(4);if(Y.startsWith("github:"))Y=Y.slice(7);if(Y.startsWith("@"))Y=Y.slice(1);if(Y.includes("/")){let X=Y.split("/");Y=Y.includes("@")?X.join("-"):X[X.length-1]??Y}let Z=Y.split("@")[0]??Y;Y=Z.split(":")[0]??Z;let q=l(Q,Y);return J0(q)?q:null}resolvePackPath($){if($.startsWith("./")||$.startsWith("../"))return l(this.projectRoot,$);if(m9($))return $;if($.startsWith("registry:"))return this.resolveCuratedPack($);if($.startsWith("@")||$.startsWith("npm:")||!$.includes("/"))return this.resolveCuratedPack($);if($.startsWith("github:")||$.includes("/"))return this.resolveCuratedPack($);return l(this.projectRoot,$)}}function j($,Q,Y){let{default:Z,small:q}=$,X={...$.agents};if(Q&&$.profiles?.[Q]){let W=u9(Q,$.profiles);if(W.default)Z=W.default;if(W.small)q=W.small;if(W.agents)X={...X,...W.agents}}if(Y){let W=$.overrides?.[Y];if(W){if(W.default)Z=W.default;if(W.small)q=W.small;if(W.agents)X={...X,...W.agents}}}let J={};if($.providers)for(let[W,_]of Object.entries($.providers))J[W]={..._.options?{options:_.options}:{},..._.models?{models:_.models}:{}};let K=Object.keys($.profiles??{}),H={};if($.profiles)for(let[W,_]of Object.entries($.profiles))H[W]={description:_.description,default:_.default,small:_.small};return{default:Z,small:q,agents:X,providers:J,routing:$.routing??[],profileNames:K,activeProfile:Q,profiles:H}}function D9($,Q,Y){let Z=$.agents[Q];if(Z)return{model:Z.model,temperature:Z.temperature,top_p:Z.top_p};if(Y)return{model:Y};return{}}function u9($,Q){return Y2($,Q,new Set,0)}var Q2=10;function Y2($,Q,Y,Z){if(Z>Q2)throw Error(`Profile inheritance too deep (max ${Q2}): ${$}`);if(Y.has($))throw Error(`Circular profile inheritance detected: ${[...Y,$].join(" \u2192 ")}`);let q=Q[$];if(!q)throw Error(`Profile "${$}" not found`);if(Y.add($),!q.extends)return{...q};let X=Y2(q.extends,Q,Y,Z+1);return{description:q.description??X.description,default:q.default??X.default,small:q.small??X.small,agents:{...X.agents,...q.agents}}}import{copyFileSync as Z2,existsSync as q2,mkdirSync as f9,writeFileSync as O0}from"fs";import{dirname as p9,join as I,resolve as d9}from"path";function c9($,Q){let Y=[],Z=n9($.manifest.name),q=d9(Q,Z);f9(q,{recursive:!0});let X={name:Z};if($.manifest.version)X.version=$.manifest.version;if($.manifest.description)X.description=$.manifest.description;let J=o9($.manifest.author);if(J)X.author=J;if($.manifest.homepage)X.homepage=$.manifest.homepage;if($.manifest.repository)X.repository=typeof $.manifest.repository==="string"?$.manifest.repository:$.manifest.repository.url;if($.manifest.license)X.license=$.manifest.license;if($.manifest.logo)X.logo=$.manifest.logo;if($.manifest.tags.length>0)X.keywords=$.manifest.tags;if($.rules.length>0){let W=I(q,"rules");A(W),X.rules="rules";for(let _ of $.rules){let C=_.meta.cursor??{},B={description:C.description??_.meta.description??"",alwaysApply:C.alwaysApply??_.meta.root??!1},V=C.globs??_.meta.globs;if(V)B.globs=V;let L=`${_.name}.mdc`,U=I(W,L);O0(U,v(B,_.content)),Y.push(U)}}if($.agents.length>0){let W=I(q,"agents");A(W),X.agents="agents";for(let _ of $.agents){let C={name:_.name,description:_.meta.description??""},B=`${_.name}.md`,V=I(W,B);O0(V,v(C,_.content)),Y.push(V)}}if($.skills.length>0){let W=I(q,"skills");A(W),X.skills="skills";for(let _ of $.skills){let C=I(W,_.name);A(C);let B=I(C,"SKILL.md"),V=v(n0(_),_.content);O0(B,V),Y.push(B)}}if($.commands.length>0){let W=I(q,"commands");A(W),X.commands="commands";for(let _ of $.commands){let C={name:_.name};if(_.meta.description)C.description=_.meta.description;let B=`${_.name}.md`,V=I(W,B);O0(V,v(C,_.content)),Y.push(V)}}if($.hooks){let W=o($.hooks,"cursor");if(Object.keys(W).length>0){let _=I(q,"hooks");A(_);let C=I(_,"hooks.json");O0(C,JSON.stringify({version:$.hooks.version??1,hooks:W},null,2)+`
|
|
7
|
+
`),Y.push(C),X.hooks="hooks/hooks.json"}}if($.mcp&&Object.keys($.mcp.servers).length>0){X.mcpServers=".mcp.json";let W=I(q,".mcp.json");O0(W,JSON.stringify({mcpServers:$.mcp.servers},null,2)+`
|
|
8
|
+
`),Y.push(W)}l9($,q,Y),a9($,q,Y);let K=I(q,".cursor-plugin");A(K);let H=I(K,"plugin.json");return O0(H,JSON.stringify(X,null,2)+`
|
|
9
|
+
`),Y.push(H),{outputDir:q,filesWritten:Y,manifest:X}}function n9($){let Q=$.toLowerCase().replace(/[^a-z0-9.-]+/g,"-").replace(/-+/g,"-").replace(/^[^a-z0-9]+/,"").replace(/[^a-z0-9]+$/,"");return Q.length>0?Q:"agentpacks-plugin"}function o9($){if(!$)return null;if(typeof $==="string")return{name:$};return{name:$.name,...$.email?{email:$.email}:{}}}function l9($,Q,Y){let Z=I($.directory,"README.md");if(!q2(Z))return;let q=I(Q,"README.md");Z2(Z,q),Y.push(q)}function a9($,Q,Y){if(!$.manifest.logo)return;let Z=I($.directory,$.manifest.logo);if(!q2(Z))return;let q=I(Q,$.manifest.logo);A(p9(q)),Z2(Z,q),Y.push(q)}import{copyFileSync as t9,existsSync as j0,readFileSync as X2,writeFileSync as l0}from"fs";import{basename as s9,join as h0,resolve as H0}from"path";function i9($,Q){let Y=[],Z=[],q=H0($,".claude"),X=j0(H0($,"CLAUDE.md")),J=j0(q);if(!X&&!J)return{packDir:"",filesImported:[],warnings:["No CLAUDE.md or .claude/ directory found."],configGenerated:!1};let K=Q??H0($,"packs","claude-import");A(K);let H=H0(K,"rules");if(A(H),X){let B=["---","root: true",'description: "Root Claude Code rules"',"---","",X2(H0($,"CLAUDE.md"),"utf-8")].join(`
|
|
10
|
+
`),V=h0(H,"claude-root.md");l0(V,B),Z.push(V)}if(J){let C=H0(q,"rules");if(j0(C)){let V=F(C,{extension:".md"});for(let L of V){let U=h0(H,s9(L));t9(L,U),Z.push(U)}}let B=H0(q,"settings.json");if(j0(B))try{let V=X2(B,"utf-8"),L=JSON.parse(V),U=L.mcpServers??L.mcp_servers;if(U&&typeof U==="object"){let O={servers:U},P=h0(K,"mcp.json");l0(P,JSON.stringify(O,null,2)+`
|
|
11
|
+
`),Z.push(P)}}catch{Y.push("Failed to parse .claude/settings.json")}}let W={name:"claude-import",version:"1.0.0",description:"Imported from Claude Code",tags:["imported","claude-code"],dependencies:[],conflicts:[],targets:"*",features:"*"},_=h0(K,"pack.json");return l0(_,JSON.stringify(W,null,2)+`
|
|
12
|
+
`),Z.push(_),{packDir:K,filesImported:Z,warnings:Y,configGenerated:!1}}import{copyFileSync as I0,existsSync as Q0,readFileSync as L2,writeFileSync as a0}from"fs";import{basename as E0,join as p,resolve as f}from"path";function r9($,Q){let Y=f($,".cursor"),Z=[],q=[];if(!Q0(Y))return{packDir:"",filesImported:[],warnings:["No .cursor/ directory found."],configGenerated:!1};let X=Q??f($,"packs","cursor-import");A(X);let J=f(Y,"rules");if(Q0(J)){let B=f(X,"rules");A(B);let V=F(J,{extension:".mdc"});for(let U of V){let O=L2(U,"utf-8"),{data:P,content:x}=d(O),b={};if(P.description)b.description=P.description;if(P.alwaysApply)b.root=!0;if(P.globs)b.globs=P.globs;b.cursor={...P};let z=e9(b,x),m=E0(U,".mdc"),V0=p(B,`${m}.md`);a0(V0,z),q.push(V0)}let L=F(J,{extension:".md"});for(let U of L){let O=p(B,E0(U));I0(U,O),q.push(O)}}let K=f(Y,"agents");if(Q0(K)){let B=f(X,"agents");A(B);let V=F(K,{extension:".md"});for(let L of V){let U=p(B,E0(L));I0(L,U),q.push(U)}}let H=f(Y,"skills");if(Q0(H)){let B=f(X,"skills");A(B);let V=$0(H);for(let L of V){let U=E0(L),O=p(L,"SKILL.md");if(Q0(O)){let P=p(B,U);A(P);let x=L2(O,"utf-8"),b=A0(x,U),z=p(P,"SKILL.md");if(a0(z,b.content),q.push(z),b.addedDescription)Z.push(`skills/${U}/SKILL.md missing description; added import placeholder.`)}}}let W=f(Y,"commands");if(Q0(W)){let B=f(X,"commands");A(B);let V=F(W,{extension:".md"});for(let L of V){let U=p(B,E0(L));I0(L,U),q.push(U)}}let _=f(Y,"mcp.json");if(Q0(_))I0(_,p(X,"mcp.json")),q.push(p(X,"mcp.json"));let C=f($,".cursorignore");if(Q0(C))I0(C,p(X,"ignore")),q.push(p(X,"ignore"));return $1(X,"cursor-import",q),{packDir:X,filesImported:q,warnings:Z,configGenerated:!1}}function e9($,Q){let Y=["---"];for(let[Z,q]of Object.entries($))if(typeof q==="object")Y.push(`${Z}: ${JSON.stringify(q)}`);else Y.push(`${Z}: ${q}`);return Y.push("---","",Q),Y.join(`
|
|
13
|
+
`)}function $1($,Q,Y){let Z={name:Q,version:"1.0.0",description:"Imported from Cursor",tags:["imported","cursor"],dependencies:[],conflicts:[],targets:"*",features:"*"},q=p($,"pack.json");a0(q,JSON.stringify(Z,null,2)+`
|
|
14
|
+
`),Y.push(q)}import{copyFileSync as i0,existsSync as Y0,readFileSync as t0,writeFileSync as v0}from"fs";import{basename as r0,join as a,resolve as h}from"path";function Q1($,Q){let Y=[],Z=[],q=h($,".opencode");if(!Y0(q))return{packDir:"",filesImported:[],warnings:["No .opencode/ directory found."],configGenerated:!1};let X=Q??h($,"packs","opencode-import");A(X),s0(h(q,"rules"),h(X,"rules"),Z),s0(h(q,"commands"),h(X,"commands"),Z),s0(h(q,"agents"),h(X,"agents"),Z);let J=h(q,"skill");if(Y0(J)){let V=h(X,"skills");A(V);let L=$0(J);for(let U of L){let O=r0(U);if(O.startsWith("."))continue;let P=a(U,"SKILL.md");if(Y0(P)){let x=a(V,O);A(x);let b=t0(P,"utf-8"),z=A0(b,O),m=a(x,"SKILL.md");if(v0(m,z.content),Z.push(m),z.addedDescription)Y.push(`skills/${O}/SKILL.md missing description; added import placeholder.`)}}}let K=h(q,"plugins");if(Y0(K)){let V=h(X,"plugins");A(V);let L=F(K);for(let U of L)if(U.endsWith(".ts")||U.endsWith(".js")){let O=a(V,r0(U));i0(U,O),Z.push(O)}}let H=h($,"AGENTS.md");if(Y0(H)){let V=h(X,"rules");A(V);let U=["---","root: true",'description: "AGENTS.md root rules"',"---","",t0(H,"utf-8")].join(`
|
|
15
|
+
`),O=a(V,"agents-md-root.md");v0(O,U),Z.push(O)}let W=h($,"opencode.json");if(Y0(W))try{let V=t0(W,"utf-8"),U=JSON.parse(V).mcp;if(U){let O=a(X,"mcp.json");v0(O,JSON.stringify({servers:U},null,2)+`
|
|
16
|
+
`),Z.push(O)}}catch{Y.push("Failed to parse opencode.json")}let _=h($,".opencodeignore");if(Y0(_))i0(_,a(X,"ignore")),Z.push(a(X,"ignore"));let C={name:"opencode-import",version:"1.0.0",description:"Imported from OpenCode",tags:["imported","opencode"],dependencies:[],conflicts:[],targets:"*",features:"*"},B=a(X,"pack.json");return v0(B,JSON.stringify(C,null,2)+`
|
|
17
|
+
`),Z.push(B),{packDir:X,filesImported:Z,warnings:Y,configGenerated:!1}}function s0($,Q,Y){if(!Y0($))return;A(Q);let Z=F($,{extension:".md"});for(let q of Z){let X=a(Q,r0(q));i0(q,X),Y.push(X)}}import{copyFileSync as W0,existsSync as c,readFileSync as U2,writeFileSync as e0}from"fs";import{parse as Y1}from"jsonc-parser";import{basename as k0,join as T,resolve as E}from"path";function Z1($,Q){let Y=E($,".rulesync"),Z=[],q=[];if(!c(Y))return{packDir:"",filesImported:[],warnings:["No .rulesync/ directory found."],configGenerated:!1};let X=Q??E($,"packs","default");A(X);let J=E(Y,"rules");if(c(J)){let P=E(X,"rules");A(P);let x=F(J,{extension:".md"});for(let b of x){let z=T(P,k0(b));W0(b,z),q.push(z)}}let K=E(Y,"commands");if(c(K)){let P=E(X,"commands");A(P);let x=F(K,{extension:".md"});for(let b of x){let z=T(P,k0(b));W0(b,z),q.push(z)}}let H=E(Y,"subagents");if(c(H)){let P=E(X,"agents");A(P);let x=F(H,{extension:".md"});for(let b of x){let z=T(P,k0(b));W0(b,z),q.push(z)}}let W=E(Y,"skills");if(c(W)){let P=E(X,"skills");A(P);let x=$0(W);for(let b of x){let z=k0(b);if(z.startsWith("."))continue;let m=T(b,"SKILL.md");if(c(m)){let V0=T(P,z);A(V0);let y2=U2(m,"utf-8"),w$=A0(y2,z),F$=T(V0,"SKILL.md");if(e0(F$,w$.content),q.push(F$),w$.addedDescription)Z.push(`skills/${z}/SKILL.md missing description; added import placeholder.`)}}}let _=E(Y,"hooks.json");if(c(_)){let P=E(X,"hooks");A(P),W0(_,T(P,"hooks.json")),q.push(T(P,"hooks.json"))}let C=E(Y,"mcp.json");if(c(C))W0(C,T(X,"mcp.json")),q.push(T(X,"mcp.json"));let B=E(Y,".aiignore"),V=E($,".rulesyncignore");if(c(B))W0(B,T(X,"ignore")),q.push(T(X,"ignore"));else if(c(V))W0(V,T(X,"ignore")),q.push(T(X,"ignore"));let L={name:"default",version:"1.0.0",description:"Imported from rulesync",tags:["imported","rulesync"],dependencies:[],conflicts:[],targets:"*",features:"*"};e0(T(X,"pack.json"),JSON.stringify(L,null,2)+`
|
|
18
|
+
`),q.push(T(X,"pack.json"));let U=!1,O=E($,"rulesync.jsonc");if(c(O)){let P=q1(O,X),x=E($,"agentpacks.jsonc");e0(x,P),U=!0}return{packDir:X,filesImported:q,warnings:Z,configGenerated:U}}function q1($,Q){let Y=U2($,"utf-8"),Z=Y1(Y),q=Z.targets??["opencode","cursor","claudecode"],X=Z.features??["*"],J=Z.baseDirs??["."],K=Z.global??!1,H=Z.delete??!0,_={$schema:"https://unpkg.com/agentpacks/schema.json",packs:["./"+T("packs","default")],disabled:[],targets:q,features:X,mode:J.length>1?"monorepo":"repo",baseDirs:J,global:K,delete:H};return JSON.stringify(_,null,2)+`
|
|
19
|
+
`}function $$($){let Q=$;if(Q.startsWith("github:"))Q=Q.slice(7);let Y="",Z=Q.indexOf("@"),q=Q.indexOf(":",Z>-1?Z:0);if(q>-1)Y=Q.slice(q+1),Q=Q.slice(0,q);let X="main";if(Z>-1)X=Q.slice(Z+1),Q=Q.slice(0,Z);let J=Q.split("/");if(J.length<2)throw Error(`Invalid git source reference: "${$}". Expected owner/repo format.`);let K=J[0],H=J[1];if(!K||!H)throw Error(`Invalid git source reference: "${$}". Expected owner/repo format.`);return{owner:K,repo:H,ref:X,path:Y||""}}function X1($){if($.startsWith("github:"))return!0;if($.startsWith("./")||$.startsWith("../")||$.startsWith("/"))return!1;if($.startsWith("@")||$.startsWith("npm:"))return!1;return $.split("/").length===2&&!$.includes("node_modules")}function B2($){return`${$.owner}/${$.repo}`}import{mkdirSync as g0,writeFileSync as Y$}from"fs";import{join as Z0,resolve as Q$}from"path";var V2="https://api.github.com";function Z$($){let Q={Accept:"application/vnd.github.v3+json","User-Agent":"agentpacks"};if($)Q.Authorization=`token ${$}`;return Q}async function L1($,Q){let Y=`${V2}/repos/${$.owner}/${$.repo}/git/ref`,Z=await fetch(`${Y}/heads/${$.ref}`,{headers:Z$(Q)});if(!Z.ok){let X=await fetch(`${Y}/tags/${$.ref}`,{headers:Z$(Q)});if(!X.ok)throw Error(`Could not resolve ref "${$.ref}" for ${$.owner}/${$.repo}: ${Z.status}`);return(await X.json()).object.sha}return(await Z.json()).object.sha}async function q$($,Q,Y,Z){let q=$.path?`${$.path}/${Y}`:Y,X=`${V2}/repos/${$.owner}/${$.repo}/contents/${q}?ref=${Q}`,J=await fetch(X,{headers:Z$(Z)});if(!J.ok)return[];return await J.json()}async function X$($,Q){let Y={"User-Agent":"agentpacks"};if(Q)Y.Authorization=`token ${Q}`;let Z=await fetch($,{headers:Y});if(!Z.ok)throw Error(`Failed to fetch ${$}: ${Z.status}`);return Z.text()}async function L$($,Q,Y,Z,q,X){g0(Z,{recursive:!0});let J=await q$($,Q,Y,X);for(let K of J)if(K.type==="file"&&K.download_url){let H=await X$(K.download_url,X),W=Z0(Z,K.name);Y$(W,H),q.push(W)}else if(K.type==="dir")await L$($,Q,`${Y}/${K.name}`,Z0(Z,K.name),q,X)}async function U1($,Q,Y,Z={}){let q=$$(Q),X=B2(q),J=[],K=[],H,W=R0(Y,X);if(Z.frozen&&!W)throw Error(`Frozen mode: no lockfile entry for source "${X}".`);if(W&&!Z.update)H=W.resolvedRef;else H=await L1(q,Z.token);let _=q.path||"packs",C=await q$(q,H,_,Z.token),B=Q$($,".agentpacks",".curated");g0(B,{recursive:!0});let V={requestedRef:q.ref,resolvedRef:H,resolvedAt:new Date().toISOString(),skills:{},packs:{}},L=C.filter((U)=>U.type==="dir");for(let U of L){let O=U.name,P=Q$(B,O),x=await q$(q,H,`${_}/${O}`,Z.token);g0(P,{recursive:!0});for(let b of x)if(b.type==="file"&&b.download_url){let z=await X$(b.download_url,Z.token);if(Y$(Z0(P,b.name),z),J.push(Z0(P,b.name)),V.packs)V.packs[O]={integrity:c0(z)}}else if(b.type==="dir")await L$(q,H,`${_}/${O}/${b.name}`,Z0(P,b.name),J,Z.token)}if(L.length===0){if(C.filter((O)=>O.type==="file").length>0){let O=q.path.split("/").pop()??q.repo,P=Q$(B,O);g0(P,{recursive:!0});for(let x of C)if(x.type==="file"&&x.download_url){let b=await X$(x.download_url,Z.token);Y$(Z0(P,x.name),b),J.push(Z0(P,x.name))}else if(x.type==="dir")await L$(q,H,`${_}/${x.name}`,Z0(P,x.name),J,Z.token)}}return S0(Y,X,V),{installed:J,warnings:K}}import{existsSync as B1}from"fs";import{isAbsolute as K2,resolve as V1}from"path";function K1($,Q){let Y;if(K2($))Y=$;else Y=V1(Q,$);if(!B1(Y))return null;return Y}function J1($){return $.startsWith("./")||$.startsWith("../")||K2($)}function U$($){let Q=$;if(Q.startsWith("npm:"))Q=Q.slice(4);let Y="",Z=O1(Q);if(Z>-1)Y=Q.slice(Z+1),Q=Q.slice(0,Z);let q="latest",X=J2(Q);if(X>-1)q=Q.slice(X+1),Q=Q.slice(0,X);if(!Q)throw Error(`Invalid npm source reference: "${$}". Expected package name.`);return{packageName:Q,version:q,path:Y}}function O1($){let Q=$.startsWith("@")?$.indexOf("/")+1:0,Y=J2($),Z=Y>-1?Y:Q;return $.indexOf(":",Z)}function J2($){if($.startsWith("@")){let Q=$.indexOf("/");if(Q===-1)return-1;return $.indexOf("@",Q+1)}return $.indexOf("@")}function H1($){if($.startsWith("npm:"))return!0;if($.startsWith("@")&&$.includes("/"))return!0;return!1}function O2($){return`npm:${$.packageName}`}import{execSync as B$}from"child_process";import{existsSync as W1,mkdirSync as V$,readdirSync as H2}from"fs";import{join as K$,resolve as J$}from"path";var P1="https://registry.npmjs.org";async function C1($){let Q=`${P1}/${encodeURIComponent($.packageName)}/${$.version}`,Y=await fetch(Q,{headers:{Accept:"application/json"}});if(!Y.ok)throw Error(`Could not resolve npm package "${$.packageName}@${$.version}": ${Y.status}`);let Z=await Y.json();return{version:Z.version,tarball:Z.dist.tarball}}async function _1($,Q,Y,Z={}){let q=U$(Q),X=O2(q),J=[],K=[],H=R0(Y,X);if(Z.frozen&&!H)throw Error(`Frozen mode: no lockfile entry for source "${X}".`);let W;if(H&&!Z.update)W=H.resolvedRef;else W=(await C1(q)).version;let _=J$($,".agentpacks",".curated");V$(_,{recursive:!0}),A1(q,W,_,J,K);let C={requestedRef:q.version,resolvedRef:W,resolvedAt:new Date().toISOString(),skills:{},packs:{}};return S0(Y,X,C),{installed:J,warnings:K}}function A1($,Q,Y,Z,q){let X=`${$.packageName}@${Q}`,J=$.packageName.replace(/^@/,"").replace(/\//g,"-"),K=J$(Y,J);try{let H=J$(Y,".tmp-npm");V$(H,{recursive:!0}),B$(`npm pack ${X} --pack-destination "${H}"`,{stdio:"pipe",timeout:30000});let W=H2(H).filter((L)=>L.endsWith(".tgz"));if(W.length===0)return q.push(`No tarball found for ${X}`),K;let _=W[0];if(!_)return q.push(`No tarball found for ${X}`),K;let C=K$(H,_);V$(K,{recursive:!0}),B$(`tar xzf "${C}" -C "${K}" --strip-components=1`,{stdio:"pipe",timeout:15000}),B$(`rm -rf "${H}"`,{stdio:"pipe"});let B=$.path||"",V=B?K$(K,B):K;if(W1(V))W2(V,Z)}catch(H){q.push(`Failed to extract npm pack ${X}: ${H instanceof Error?H.message:String(H)}`)}return K}function W2($,Q){let Y=H2($,{withFileTypes:!0});for(let Z of Y){let q=K$($,Z.name);if(Z.isDirectory())W2(q,Q);else Q.push(q)}}function N1($){let Q=$;if(Q.startsWith("registry:"))Q=Q.slice(9);if(!Q)throw Error(`Invalid registry source reference: "${$}". Expected pack name.`);let Y="latest",Z=Q.indexOf("@");if(Z>0)Y=Q.slice(Z+1),Q=Q.slice(0,Z);if(!Q)throw Error(`Invalid registry source reference: "${$}". Pack name is empty.`);if(!/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(Q))throw Error(`Invalid registry pack name: "${Q}". Must be lowercase alphanumeric with hyphens.`);return{packName:Q,version:Y}}function x1($){return $.startsWith("registry:")}function b1($){return`registry:${$.packName}`}function q0($){if(!$.default&&!$.small&&Object.keys($.agents).length===0&&Object.keys($.profiles).length===0)return null;let Q=[];if(Q.push("# Model Configuration"),Q.push(""),Q.push("Use the following model preferences when working in this project."),Q.push(""),$.default||$.small){if(Q.push("## Default Models"),Q.push(""),$.default)Q.push(`- **Primary model**: ${$.default}`);if($.small)Q.push(`- **Lightweight tasks** (titles, summaries): ${$.small}`);Q.push("")}let Y=Object.entries($.agents);if(Y.length>0){Q.push("## Agent Model Assignments"),Q.push(""),Q.push("| Agent | Model | Temperature |"),Q.push("| --- | --- | --- |");for(let[Z,q]of Y){let X=q.temperature!==void 0?String(q.temperature):"\u2014";Q.push(`| ${Z} | ${q.model} | ${X} |`)}Q.push("")}if(Object.keys($.profiles).length>0){Q.push("## Available Profiles"),Q.push(""),Q.push("| Profile | Description | Default Model |"),Q.push("| --- | --- | --- |");for(let[Z,q]of Object.entries($.profiles))Q.push(`| ${Z} | ${q.description??"\u2014"} | ${q.default??"\u2014"} |`);Q.push("")}if($.activeProfile)Q.push(`**Active profile**: \`${$.activeProfile}\``),Q.push("");if($.routing.length>0){Q.push("## Task-Aware Routing"),Q.push(""),Q.push("Select the appropriate profile based on the task context:"),Q.push(""),Q.push("| Condition | Profile | Description |"),Q.push("| --- | --- | --- |");for(let Z of $.routing){let q=Object.entries(Z.when).map(([J,K])=>`${J}=${K}`).join(", "),X=Z.description??"\u2014";Q.push(`| ${q} | ${Z.use} | ${X} |`)}Q.push(""),Q.push("### Condition Reference"),Q.push(""),Q.push("- **complexity**: low | medium | high | critical"),Q.push("- **urgency**: low | normal | high"),Q.push("- **budget**: minimal | standard | premium"),Q.push("- **contextWindowNeed**: small | medium | large | max"),Q.push("- **toolUseIntensity**: none | light | heavy"),Q.push("")}return Q.join(`
|
|
20
|
+
`)}class R{supportsFeature($){return this.supportedFeatures.includes($)}getEffectiveFeatures($){return $.filter((Q)=>this.supportsFeature(Q))}createResult($=[],Q=[],Y=[]){return{targetId:this.id,filesWritten:$,filesDeleted:Q,warnings:Y}}}import{join as O$,resolve as N0}from"path";function g($){return new P2($)}class P2 extends R{id;name;supportedFeatures;config;constructor($){super();this.id=$.id,this.name=$.name,this.supportedFeatures=$.supportedFeatures,this.config=$}generate($){let{projectRoot:Q,baseDir:Y,features:Z,enabledFeatures:q,deleteExisting:X}=$,J=N0(Q,Y),K=this.getEffectiveFeatures(q),H=[],W=[],_=[],C=N0(J,this.config.configDir),B=this.config.rulesDir??"rules",V=this.config.ruleExtension??".md";if(K.includes("rules")){let L=N0(C,B);if(X)w(L),W.push(L);A(L);let U=Z.rules.filter((O)=>y(O,this.id));for(let O of U){let P=O$(L,`${O.name}${V}`);G(P,O.content),H.push(P)}}if(K.includes("commands")){let L=N0(C,"commands");if(X)w(L),W.push(L);A(L);let U=Z.commands.filter((O)=>k(O,this.id));for(let O of U){let P=O$(L,`${O.name}.md`);G(P,O.content),H.push(P)}}if(K.includes("mcp")){if(Object.entries(Z.mcpServers).length>0){let U=this.config.mcpInConfigDir?C:J,O=N0(U,"mcp.json");S(O,{mcpServers:Z.mcpServers},{header:!1}),H.push(O)}}if(K.includes("ignore")&&this.config.ignoreFile){if(Z.ignorePatterns.length>0){let L=N0(J,this.config.ignoreFile);G(L,Z.ignorePatterns.join(`
|
|
21
|
+
`)+`
|
|
22
|
+
`),H.push(L)}}if(K.includes("models")&&Z.models){let L=j(Z.models,$.modelProfile,this.id),U=q0(L);if(U){A(C);let O=O$(C,"model-config.md");G(O,U),H.push(O)}}return this.createResult(H,W,_)}}var C2=g({id:"cline",name:"Cline",configDir:".cline",supportedFeatures:["rules","commands","mcp","ignore"],ignoreFile:".clineignore",mcpInConfigDir:!0}),_2=g({id:"kilo",name:"Kilo Code",configDir:".kilo",supportedFeatures:["rules","commands","mcp","ignore"],ignoreFile:".kiloignore",mcpInConfigDir:!0}),A2=g({id:"roo",name:"Roo Code",configDir:".roo",supportedFeatures:["rules","commands","mcp","ignore"],ignoreFile:".rooignore",mcpInConfigDir:!0}),N2=g({id:"qwencode",name:"Qwen Code",configDir:".qwencode",supportedFeatures:["rules","mcp","ignore"],ignoreFile:".qwencodeignore",mcpInConfigDir:!0}),x2=g({id:"kiro",name:"Kiro",configDir:".kiro",supportedFeatures:["rules","mcp"],mcpInConfigDir:!0}),b2=g({id:"factorydroid",name:"Factory Droid",configDir:".factorydroid",supportedFeatures:["rules","mcp"],mcpInConfigDir:!0}),M2=g({id:"antigravity",name:"AntiGravity",configDir:".antigravity",supportedFeatures:["rules","mcp"],mcpInConfigDir:!0}),G2=g({id:"junie",name:"Junie",configDir:".junie",supportedFeatures:["rules","mcp"],mcpInConfigDir:!0}),z2=g({id:"augmentcode",name:"Augment Code",configDir:".augmentcode",supportedFeatures:["rules","mcp"],mcpInConfigDir:!0}),w2=g({id:"windsurf",name:"Windsurf",configDir:".windsurf",supportedFeatures:["rules","mcp","ignore"],ignoreFile:".windsurfignore",mcpInConfigDir:!0}),F2=g({id:"warp",name:"Warp",configDir:".warp",supportedFeatures:["rules"]}),I2=g({id:"replit",name:"Replit Agent",configDir:".replit",supportedFeatures:["rules","mcp"],mcpInConfigDir:!0}),E2=g({id:"zed",name:"Zed",configDir:".zed",supportedFeatures:["rules","mcp"],mcpInConfigDir:!0});import{join as x0,resolve as i}from"path";var X0="claudecode";class H$ extends R{id=X0;name="Claude Code";supportedFeatures=["rules","commands","agents","skills","hooks","mcp","ignore","models"];generate($){let{projectRoot:Q,baseDir:Y,features:Z,enabledFeatures:q,deleteExisting:X}=$,J=i(Q,Y),K=this.getEffectiveFeatures(q),H=[],W=[],_=[],C=i(J,".claude");if(K.includes("rules")){let B=i(C,"rules");if(X)w(B),W.push(B);A(B);let V=Z.rules.filter((O)=>y(O,X0)),L=y0(V),U=_0(V);if(L.length>0){let O=L.map((x)=>x.content).join(`
|
|
23
|
+
|
|
24
|
+
`),P=i(C,"CLAUDE.md");G(P,O),H.push(P)}for(let O of U){let P=x0(B,`${O.name}.md`);G(P,O.content),H.push(P)}}if(K.includes("agents")){let B=i(C,"agents");if(X)w(B),W.push(B);A(B);let V=Z.models?j(Z.models,$.modelProfile,X0):null,L=Z.agents.filter((U)=>n(U,X0));for(let U of L){let O=x0(B,`${U.name}.md`),P=U.meta.claudecode??{},b=V?.agents[U.name]?.model??P.model,z=U.content;if(b)z=`<!-- model: ${b} -->
|
|
25
|
+
${z}`;G(O,z),H.push(O)}}if(K.includes("skills")){let B=i(C,"skills");if(X)w(B),W.push(B);A(B);let V=Z.skills.filter((L)=>u(L,X0));for(let L of V){let U=x0(B,L.name);A(U);let O=x0(U,"SKILL.md");G(O,D(L)),H.push(O)}}if(K.includes("commands")){let B=i(C,"commands");if(X)w(B),W.push(B);A(B);let V=Z.commands.filter((L)=>k(L,X0));for(let L of V){let U=x0(B,`${L.name}.md`);G(U,L.content),H.push(U)}}if(K.includes("models")&&Z.models){let B=j(Z.models,$.modelProfile,X0),V=q0(B);if(V){let L=i(C,"rules");A(L);let U=x0(L,"model-config.md");G(U,V),H.push(U)}}if(K.includes("hooks")||K.includes("mcp")||K.includes("ignore")){let B=M1($,K);if(Object.keys(B).length>0){let V=i(C,"settings.json"),U={...e(V)??{},...B};S(V,U,{header:!1}),H.push(V)}}return this.createResult(H,W,_)}}function M1($,Q){let Y={};if(Q.includes("hooks")){let Z={};for(let q of $.features.hooks){let X=o(q,X0);for(let[J,K]of Object.entries(X)){let H=G1(J);if(!Z[H])Z[H]=[];Z[H].push(...K.map((W)=>({type:W.type??"command",...W.matcher?{matcher:W.matcher}:{},command:W.command})))}}if(Object.keys(Z).length>0)Y.hooks=Z}if(Q.includes("mcp")){let Z=Object.entries($.features.mcpServers);if(Z.length>0){let q={};for(let[X,J]of Z)if(J.url)q[X]={url:J.url};else if(J.command)q[X]={command:J.command,...J.args?{args:J.args}:{},...J.env?{env:J.env}:{}};Y.mcpServers=q}}return Y}function G1($){return $.charAt(0).toUpperCase()+$.slice(1)}import{join as W$,resolve as b0}from"path";var m0="codexcli";class C$ extends R{id=m0;name="Codex CLI";supportedFeatures=["rules","skills","mcp","hooks"];generate($){let{projectRoot:Q,baseDir:Y,features:Z,enabledFeatures:q,deleteExisting:X}=$,J=b0(Q,Y),K=this.getEffectiveFeatures(q),H=[],W=[],_=[],C=b0(J,".codex");if(K.includes("rules")){let B=b0(C,"memories");if(X)P$(B,W,_);A(B);let V=Z.rules.filter((L)=>y(L,m0));for(let L of V){let U=W$(B,`${L.name}.md`);G(U,L.content),H.push(U)}}if(K.includes("skills")){let B=b0(C,"skills");if(X)P$(B,W,_);A(B);let V=Z.skills.filter((L)=>u(L,m0));for(let L of V){let U=W$(B,L.name);A(U);let O=W$(U,"SKILL.md");G(O,D(L)),H.push(O)}}if(K.includes("hooks")){let B=b0(C,"hooks.json");if(X)P$(B,W,_);let V={};for(let L of Z.hooks){let U=o(L,m0);for(let[O,P]of Object.entries(U)){if(!V[O])V[O]=[];V[O].push(...P)}}if(Object.keys(V).length>0){let L=Z.hooks.find((U)=>U.version!==void 0)?.version??1;S(B,{version:L,hooks:V},{header:!1}),H.push(B)}}if(K.includes("mcp")){let B=Object.entries(Z.mcpServers);if(B.length>0){let V={};for(let[L,U]of B)if(U.url)V[L]={url:U.url};else if(U.command)V[L]={command:U.command,...U.args?{args:U.args}:{},...U.env?{env:U.env}:{}};if(Object.keys(V).length>0){let L=b0(C,"mcp.json");S(L,{mcpServers:V},{header:!1}),H.push(L)}}}return this.createResult(H,W,_)}}function P$($,Q,Y){try{w($),Q.push($)}catch(Z){Y.push(`Could not remove ${$}: ${Z instanceof Error?Z.message:String(Z)}`)}}import{join as T0,resolve as t}from"path";var M0="copilot";class _$ extends R{id=M0;name="GitHub Copilot";supportedFeatures=["rules","commands","agents","skills","mcp","ignore","models"];generate($){let{projectRoot:Q,baseDir:Y,features:Z,enabledFeatures:q,deleteExisting:X}=$,J=t(Q,Y),K=this.getEffectiveFeatures(q),H=[],W=[],_=[],C=t(J,".github");if(K.includes("rules")){let B=Z.rules.filter((V)=>y(V,M0));if(B.length>0){let V=B.map((U)=>U.content).join(`
|
|
2767
26
|
|
|
2768
27
|
---
|
|
2769
28
|
|
|
2770
|
-
`);
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
filesWritten.push(filepath);
|
|
2775
|
-
}
|
|
2776
|
-
}
|
|
2777
|
-
if (effective.includes("agents")) {
|
|
2778
|
-
const copilotDir = resolve16(githubDir, "copilot");
|
|
2779
|
-
const agentsDir = resolve16(copilotDir, "agents");
|
|
2780
|
-
if (deleteExisting) {
|
|
2781
|
-
removeIfExists(agentsDir);
|
|
2782
|
-
filesDeleted.push(agentsDir);
|
|
2783
|
-
}
|
|
2784
|
-
ensureDir(agentsDir);
|
|
2785
|
-
const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID3));
|
|
2786
|
-
for (const agent of agents) {
|
|
2787
|
-
const filepath = join18(agentsDir, `${agent.name}.md`);
|
|
2788
|
-
writeGeneratedFile(filepath, agent.content);
|
|
2789
|
-
filesWritten.push(filepath);
|
|
2790
|
-
}
|
|
2791
|
-
}
|
|
2792
|
-
if (effective.includes("skills")) {
|
|
2793
|
-
const copilotDir = resolve16(githubDir, "copilot");
|
|
2794
|
-
const skillsDir = resolve16(copilotDir, "skills");
|
|
2795
|
-
if (deleteExisting) {
|
|
2796
|
-
removeIfExists(skillsDir);
|
|
2797
|
-
filesDeleted.push(skillsDir);
|
|
2798
|
-
}
|
|
2799
|
-
ensureDir(skillsDir);
|
|
2800
|
-
const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID3));
|
|
2801
|
-
for (const skill of skills) {
|
|
2802
|
-
const skillSubDir = join18(skillsDir, skill.name);
|
|
2803
|
-
ensureDir(skillSubDir);
|
|
2804
|
-
const filepath = join18(skillSubDir, "SKILL.md");
|
|
2805
|
-
writeGeneratedFile(filepath, serializeSkill(skill));
|
|
2806
|
-
filesWritten.push(filepath);
|
|
2807
|
-
}
|
|
2808
|
-
}
|
|
2809
|
-
if (effective.includes("commands")) {
|
|
2810
|
-
const copilotDir = resolve16(githubDir, "copilot");
|
|
2811
|
-
const commandsDir = resolve16(copilotDir, "commands");
|
|
2812
|
-
if (deleteExisting) {
|
|
2813
|
-
removeIfExists(commandsDir);
|
|
2814
|
-
filesDeleted.push(commandsDir);
|
|
2815
|
-
}
|
|
2816
|
-
ensureDir(commandsDir);
|
|
2817
|
-
const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID3));
|
|
2818
|
-
for (const cmd of commands) {
|
|
2819
|
-
const filepath = join18(commandsDir, `${cmd.name}.md`);
|
|
2820
|
-
writeGeneratedFile(filepath, cmd.content);
|
|
2821
|
-
filesWritten.push(filepath);
|
|
2822
|
-
}
|
|
2823
|
-
}
|
|
2824
|
-
if (effective.includes("ignore")) {}
|
|
2825
|
-
if (effective.includes("models") && features.models) {
|
|
2826
|
-
const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID3);
|
|
2827
|
-
const guidance = generateModelGuidanceMarkdown(resolved);
|
|
2828
|
-
if (guidance) {
|
|
2829
|
-
const copilotDir = resolve16(githubDir, "copilot");
|
|
2830
|
-
ensureDir(copilotDir);
|
|
2831
|
-
const filepath = join18(copilotDir, "model-config.md");
|
|
2832
|
-
writeGeneratedFile(filepath, guidance);
|
|
2833
|
-
filesWritten.push(filepath);
|
|
2834
|
-
}
|
|
2835
|
-
}
|
|
2836
|
-
return this.createResult(filesWritten, filesDeleted, warnings);
|
|
2837
|
-
}
|
|
2838
|
-
}
|
|
2839
|
-
|
|
2840
|
-
// src/targets/cursor.ts
|
|
2841
|
-
import { join as join19, resolve as resolve17 } from "path";
|
|
2842
|
-
var TARGET_ID4 = "cursor";
|
|
29
|
+
`),L=t(C,"copilot-instructions.md");A(C),G(L,V),H.push(L)}}if(K.includes("agents")){let B=t(C,"copilot"),V=t(B,"agents");if(X)w(V),W.push(V);A(V);let L=Z.agents.filter((U)=>n(U,M0));for(let U of L){let O=T0(V,`${U.name}.md`);G(O,U.content),H.push(O)}}if(K.includes("skills")){let B=t(C,"copilot"),V=t(B,"skills");if(X)w(V),W.push(V);A(V);let L=Z.skills.filter((U)=>u(U,M0));for(let U of L){let O=T0(V,U.name);A(O);let P=T0(O,"SKILL.md");G(P,D(U)),H.push(P)}}if(K.includes("commands")){let B=t(C,"copilot"),V=t(B,"commands");if(X)w(V),W.push(V);A(V);let L=Z.commands.filter((U)=>k(U,M0));for(let U of L){let O=T0(V,`${U.name}.md`);G(O,U.content),H.push(O)}}if(K.includes("ignore"));if(K.includes("models")&&Z.models){let B=j(Z.models,$.modelProfile,M0),V=q0(B);if(V){let L=t(C,"copilot");A(L);let U=T0(L,"model-config.md");G(U,V),H.push(U)}}return this.createResult(H,W,_)}}import{join as G0,resolve as s}from"path";var L0="cursor";class A$ extends R{id=L0;name="Cursor";supportedFeatures=["rules","commands","agents","skills","hooks","mcp","ignore","models"];generate($){let{projectRoot:Q,baseDir:Y,features:Z,enabledFeatures:q,deleteExisting:X}=$,J=s(Q,Y),K=this.getEffectiveFeatures(q),H=[],W=[],_=[],C=s(J,".cursor");if(K.includes("rules")){let B=s(C,"rules");if(X)w(B),W.push(B);A(B);let V=Z.rules.filter((L)=>y(L,L0));for(let L of V){let U=L.meta.cursor??{},O={description:U.description??L.meta.description??"",alwaysApply:U.alwaysApply??L.meta.root??!1},P=U.globs??L.meta.globs;if(P)O.globs=P;let x=G0(B,`${L.name}.mdc`),b=v(O,L.content);G(x,b),H.push(x)}}if(K.includes("agents")){let B=s(C,"agents");if(X)w(B),W.push(B);A(B);let V=Z.models?j(Z.models,$.modelProfile,L0):null,L=Z.agents.filter((U)=>n(U,L0));for(let U of L){let O={name:U.name,description:U.meta.description??""},P=U.meta.cursor??{},b=V?.agents[U.name]?.model??P.model;if(b)O.model=b;let z=G0(B,`${U.name}.md`),m=v(O,U.content);G(z,m),H.push(z)}}if(K.includes("skills")){let B=s(C,"skills");if(X)w(B),W.push(B);A(B);let V=Z.skills.filter((L)=>u(L,L0));for(let L of V){let U=G0(B,L.name);A(U);let O=G0(U,"SKILL.md"),P=D(L);G(O,P),H.push(O)}}if(K.includes("commands")){let B=s(C,"commands");if(X)w(B),W.push(B);A(B);let V=Z.commands.filter((L)=>k(L,L0));for(let L of V){let U=G0(B,`${L.name}.md`);G(U,L.content),H.push(U)}}if(K.includes("hooks")){let B=s(C,"hooks.json");if(X)w(B),W.push(B);let V={};for(let L of Z.hooks){let U=o(L,L0);for(let[O,P]of Object.entries(U)){if(!V[O])V[O]=[];V[O].push(...P)}}if(Object.keys(V).length>0){let L=Z.hooks.find((U)=>U.version!==void 0)?.version??1;S(B,{version:L,hooks:V},{header:!1}),H.push(B)}}if(K.includes("mcp")){if(Object.entries(Z.mcpServers).length>0){let V=z1(Z.mcpServers),L=s(C,"mcp.json");S(L,V,{header:!1}),H.push(L)}}if(K.includes("ignore")){if(Z.ignorePatterns.length>0){let B=s(J,".cursorignore"),V=Z.ignorePatterns.join(`
|
|
30
|
+
`)+`
|
|
31
|
+
`;G(B,V),H.push(B)}}if(K.includes("models")&&Z.models){let B=j(Z.models,$.modelProfile,L0),V=w1(B);if(V){let L=s(C,"rules");A(L);let U=G0(L,"model-config.mdc");G(U,V,{header:!1}),H.push(U)}}return this.createResult(H,W,_)}}function z1($){let Q={};for(let[Y,Z]of Object.entries($))if(Z.url)Q[Y]={url:Z.url};else if(Z.command)Q[Y]={command:Z.command,...Z.args?{args:Z.args}:{},...Z.env?{env:Z.env}:{}};return{mcpServers:Q}}function w1($){if(!$.default&&!$.small&&Object.keys($.agents).length===0)return null;let Q={description:"Model configuration and selection guidelines for this workspace",alwaysApply:!0},Y=[];if(Y.push("# Model Configuration"),Y.push(""),Y.push("Use the following model preferences when working in this project."),Y.push(""),$.default||$.small){if(Y.push("## Default Models"),Y.push(""),$.default)Y.push(`- **Primary model**: ${$.default}`);if($.small)Y.push(`- **Lightweight tasks** (titles, summaries): ${$.small}`);Y.push("")}let Z=Object.entries($.agents);if(Z.length>0){Y.push("## Agent Model Assignments"),Y.push(""),Y.push("| Agent | Model | Temperature |"),Y.push("| --- | --- | --- |");for(let[q,X]of Z){let J=X.temperature!==void 0?String(X.temperature):"\u2014";Y.push(`| ${q} | ${X.model} | ${J} |`)}Y.push("")}if(Object.keys($.profiles).length>0){Y.push("## Available Profiles"),Y.push(""),Y.push("| Profile | Description | Default Model |"),Y.push("| --- | --- | --- |");for(let[q,X]of Object.entries($.profiles))Y.push(`| ${q} | ${X.description??"\u2014"} | ${X.default??"\u2014"} |`);Y.push("")}if($.activeProfile)Y.push(`**Active profile**: \`${$.activeProfile}\``),Y.push("");return v(Q,Y.join(`
|
|
32
|
+
`))}import{join as T2,resolve as P0}from"path";var N$="geminicli";class x$ extends R{id=N$;name="Gemini CLI";supportedFeatures=["rules","commands","mcp","ignore","skills","hooks"];generate($){let{projectRoot:Q,baseDir:Y,features:Z,enabledFeatures:q,deleteExisting:X}=$,J=P0(Q,Y),K=this.getEffectiveFeatures(q),H=[],W=[],_=[],C=P0(J,".gemini");if(K.includes("rules")){let B=Z.rules.filter((U)=>y(U,N$)),V=y0(B),L=_0(B);if(V.length>0){let U=V.map((P)=>P.content).join(`
|
|
2843
33
|
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
"commands",
|
|
2850
|
-
"agents",
|
|
2851
|
-
"skills",
|
|
2852
|
-
"hooks",
|
|
2853
|
-
"mcp",
|
|
2854
|
-
"ignore",
|
|
2855
|
-
"models"
|
|
2856
|
-
];
|
|
2857
|
-
generate(options) {
|
|
2858
|
-
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
2859
|
-
const root = resolve17(projectRoot, baseDir);
|
|
2860
|
-
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
2861
|
-
const filesWritten = [];
|
|
2862
|
-
const filesDeleted = [];
|
|
2863
|
-
const warnings = [];
|
|
2864
|
-
const cursorDir = resolve17(root, ".cursor");
|
|
2865
|
-
if (effective.includes("rules")) {
|
|
2866
|
-
const rulesDir = resolve17(cursorDir, "rules");
|
|
2867
|
-
if (deleteExisting) {
|
|
2868
|
-
removeIfExists(rulesDir);
|
|
2869
|
-
filesDeleted.push(rulesDir);
|
|
2870
|
-
}
|
|
2871
|
-
ensureDir(rulesDir);
|
|
2872
|
-
const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID4));
|
|
2873
|
-
for (const rule of rules) {
|
|
2874
|
-
const cursorMeta = rule.meta.cursor ?? {};
|
|
2875
|
-
const frontmatter = {
|
|
2876
|
-
description: cursorMeta.description ?? rule.meta.description ?? "",
|
|
2877
|
-
alwaysApply: cursorMeta.alwaysApply ?? rule.meta.root ?? false
|
|
2878
|
-
};
|
|
2879
|
-
const globs = cursorMeta.globs ?? rule.meta.globs;
|
|
2880
|
-
if (globs) {
|
|
2881
|
-
frontmatter.globs = globs;
|
|
2882
|
-
}
|
|
2883
|
-
const filepath = join19(rulesDir, `${rule.name}.mdc`);
|
|
2884
|
-
const content = serializeFrontmatter(frontmatter, rule.content);
|
|
2885
|
-
writeGeneratedFile(filepath, content);
|
|
2886
|
-
filesWritten.push(filepath);
|
|
2887
|
-
}
|
|
2888
|
-
}
|
|
2889
|
-
if (effective.includes("agents")) {
|
|
2890
|
-
const agentsDir = resolve17(cursorDir, "agents");
|
|
2891
|
-
if (deleteExisting) {
|
|
2892
|
-
removeIfExists(agentsDir);
|
|
2893
|
-
filesDeleted.push(agentsDir);
|
|
2894
|
-
}
|
|
2895
|
-
ensureDir(agentsDir);
|
|
2896
|
-
const resolvedModels = features.models ? resolveModels(features.models, options.modelProfile, TARGET_ID4) : null;
|
|
2897
|
-
const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID4));
|
|
2898
|
-
for (const agent of agents) {
|
|
2899
|
-
const frontmatter = {
|
|
2900
|
-
name: agent.name,
|
|
2901
|
-
description: agent.meta.description ?? ""
|
|
2902
|
-
};
|
|
2903
|
-
const cursorMeta = agent.meta.cursor ?? {};
|
|
2904
|
-
const modelsAgent = resolvedModels?.agents[agent.name];
|
|
2905
|
-
const model = modelsAgent?.model ?? cursorMeta.model;
|
|
2906
|
-
if (model) {
|
|
2907
|
-
frontmatter.model = model;
|
|
2908
|
-
}
|
|
2909
|
-
const filepath = join19(agentsDir, `${agent.name}.md`);
|
|
2910
|
-
const content = serializeFrontmatter(frontmatter, agent.content);
|
|
2911
|
-
writeGeneratedFile(filepath, content);
|
|
2912
|
-
filesWritten.push(filepath);
|
|
2913
|
-
}
|
|
2914
|
-
}
|
|
2915
|
-
if (effective.includes("skills")) {
|
|
2916
|
-
const skillsDir = resolve17(cursorDir, "skills");
|
|
2917
|
-
if (deleteExisting) {
|
|
2918
|
-
removeIfExists(skillsDir);
|
|
2919
|
-
filesDeleted.push(skillsDir);
|
|
2920
|
-
}
|
|
2921
|
-
ensureDir(skillsDir);
|
|
2922
|
-
const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID4));
|
|
2923
|
-
for (const skill of skills) {
|
|
2924
|
-
const skillSubDir = join19(skillsDir, skill.name);
|
|
2925
|
-
ensureDir(skillSubDir);
|
|
2926
|
-
const filepath = join19(skillSubDir, "SKILL.md");
|
|
2927
|
-
const content = serializeSkill(skill);
|
|
2928
|
-
writeGeneratedFile(filepath, content);
|
|
2929
|
-
filesWritten.push(filepath);
|
|
2930
|
-
}
|
|
2931
|
-
}
|
|
2932
|
-
if (effective.includes("commands")) {
|
|
2933
|
-
const commandsDir = resolve17(cursorDir, "commands");
|
|
2934
|
-
if (deleteExisting) {
|
|
2935
|
-
removeIfExists(commandsDir);
|
|
2936
|
-
filesDeleted.push(commandsDir);
|
|
2937
|
-
}
|
|
2938
|
-
ensureDir(commandsDir);
|
|
2939
|
-
const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID4));
|
|
2940
|
-
for (const cmd of commands) {
|
|
2941
|
-
const filepath = join19(commandsDir, `${cmd.name}.md`);
|
|
2942
|
-
writeGeneratedFile(filepath, cmd.content);
|
|
2943
|
-
filesWritten.push(filepath);
|
|
2944
|
-
}
|
|
2945
|
-
}
|
|
2946
|
-
if (effective.includes("hooks")) {
|
|
2947
|
-
const hooksFilepath = resolve17(cursorDir, "hooks.json");
|
|
2948
|
-
if (deleteExisting) {
|
|
2949
|
-
removeIfExists(hooksFilepath);
|
|
2950
|
-
filesDeleted.push(hooksFilepath);
|
|
2951
|
-
}
|
|
2952
|
-
const mergedHooks = {};
|
|
2953
|
-
for (const hookSet of features.hooks) {
|
|
2954
|
-
const events = resolveHooksForTarget(hookSet, TARGET_ID4);
|
|
2955
|
-
for (const [event, entries] of Object.entries(events)) {
|
|
2956
|
-
if (!mergedHooks[event]) {
|
|
2957
|
-
mergedHooks[event] = [];
|
|
2958
|
-
}
|
|
2959
|
-
mergedHooks[event].push(...entries);
|
|
2960
|
-
}
|
|
2961
|
-
}
|
|
2962
|
-
if (Object.keys(mergedHooks).length > 0) {
|
|
2963
|
-
const hooksVersion = features.hooks.find((h) => h.version !== undefined)?.version ?? 1;
|
|
2964
|
-
writeGeneratedJson(hooksFilepath, { version: hooksVersion, hooks: mergedHooks }, { header: false });
|
|
2965
|
-
filesWritten.push(hooksFilepath);
|
|
2966
|
-
}
|
|
2967
|
-
}
|
|
2968
|
-
if (effective.includes("mcp")) {
|
|
2969
|
-
const mcpEntries = Object.entries(features.mcpServers);
|
|
2970
|
-
if (mcpEntries.length > 0) {
|
|
2971
|
-
const mcpConfig = buildCursorMcp(features.mcpServers);
|
|
2972
|
-
const filepath = resolve17(cursorDir, "mcp.json");
|
|
2973
|
-
writeGeneratedJson(filepath, mcpConfig, { header: false });
|
|
2974
|
-
filesWritten.push(filepath);
|
|
2975
|
-
}
|
|
2976
|
-
}
|
|
2977
|
-
if (effective.includes("ignore")) {
|
|
2978
|
-
if (features.ignorePatterns.length > 0) {
|
|
2979
|
-
const filepath = resolve17(root, ".cursorignore");
|
|
2980
|
-
const content = features.ignorePatterns.join(`
|
|
2981
|
-
`) + `
|
|
2982
|
-
`;
|
|
2983
|
-
writeGeneratedFile(filepath, content);
|
|
2984
|
-
filesWritten.push(filepath);
|
|
2985
|
-
}
|
|
2986
|
-
}
|
|
2987
|
-
if (effective.includes("models") && features.models) {
|
|
2988
|
-
const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID4);
|
|
2989
|
-
const guidanceContent = buildCursorModelGuidance(resolved);
|
|
2990
|
-
if (guidanceContent) {
|
|
2991
|
-
const rulesDir = resolve17(cursorDir, "rules");
|
|
2992
|
-
ensureDir(rulesDir);
|
|
2993
|
-
const filepath = join19(rulesDir, "model-config.mdc");
|
|
2994
|
-
writeGeneratedFile(filepath, guidanceContent, { header: false });
|
|
2995
|
-
filesWritten.push(filepath);
|
|
2996
|
-
}
|
|
2997
|
-
}
|
|
2998
|
-
return this.createResult(filesWritten, filesDeleted, warnings);
|
|
2999
|
-
}
|
|
3000
|
-
}
|
|
3001
|
-
function buildCursorMcp(servers) {
|
|
3002
|
-
const mcpServers = {};
|
|
3003
|
-
for (const [name, entry] of Object.entries(servers)) {
|
|
3004
|
-
if (entry.url) {
|
|
3005
|
-
mcpServers[name] = { url: entry.url };
|
|
3006
|
-
} else if (entry.command) {
|
|
3007
|
-
mcpServers[name] = {
|
|
3008
|
-
command: entry.command,
|
|
3009
|
-
...entry.args ? { args: entry.args } : {},
|
|
3010
|
-
...entry.env ? { env: entry.env } : {}
|
|
3011
|
-
};
|
|
3012
|
-
}
|
|
3013
|
-
}
|
|
3014
|
-
return { mcpServers };
|
|
3015
|
-
}
|
|
3016
|
-
function buildCursorModelGuidance(resolved) {
|
|
3017
|
-
if (!resolved.default && !resolved.small && Object.keys(resolved.agents).length === 0) {
|
|
3018
|
-
return null;
|
|
3019
|
-
}
|
|
3020
|
-
const frontmatter = {
|
|
3021
|
-
description: "Model configuration and selection guidelines for this workspace",
|
|
3022
|
-
alwaysApply: true
|
|
3023
|
-
};
|
|
3024
|
-
const lines = [];
|
|
3025
|
-
lines.push("# Model Configuration");
|
|
3026
|
-
lines.push("");
|
|
3027
|
-
lines.push("Use the following model preferences when working in this project.");
|
|
3028
|
-
lines.push("");
|
|
3029
|
-
if (resolved.default || resolved.small) {
|
|
3030
|
-
lines.push("## Default Models");
|
|
3031
|
-
lines.push("");
|
|
3032
|
-
if (resolved.default) {
|
|
3033
|
-
lines.push(`- **Primary model**: ${resolved.default}`);
|
|
3034
|
-
}
|
|
3035
|
-
if (resolved.small) {
|
|
3036
|
-
lines.push(`- **Lightweight tasks** (titles, summaries): ${resolved.small}`);
|
|
3037
|
-
}
|
|
3038
|
-
lines.push("");
|
|
3039
|
-
}
|
|
3040
|
-
const agentEntries = Object.entries(resolved.agents);
|
|
3041
|
-
if (agentEntries.length > 0) {
|
|
3042
|
-
lines.push("## Agent Model Assignments");
|
|
3043
|
-
lines.push("");
|
|
3044
|
-
lines.push("| Agent | Model | Temperature |");
|
|
3045
|
-
lines.push("| --- | --- | --- |");
|
|
3046
|
-
for (const [name, assignment] of agentEntries) {
|
|
3047
|
-
const temp = assignment.temperature !== undefined ? String(assignment.temperature) : "\u2014";
|
|
3048
|
-
lines.push(`| ${name} | ${assignment.model} | ${temp} |`);
|
|
3049
|
-
}
|
|
3050
|
-
lines.push("");
|
|
3051
|
-
}
|
|
3052
|
-
if (Object.keys(resolved.profiles).length > 0) {
|
|
3053
|
-
lines.push("## Available Profiles");
|
|
3054
|
-
lines.push("");
|
|
3055
|
-
lines.push("| Profile | Description | Default Model |");
|
|
3056
|
-
lines.push("| --- | --- | --- |");
|
|
3057
|
-
for (const [name, profile] of Object.entries(resolved.profiles)) {
|
|
3058
|
-
lines.push(`| ${name} | ${profile.description ?? "\u2014"} | ${profile.default ?? "\u2014"} |`);
|
|
3059
|
-
}
|
|
3060
|
-
lines.push("");
|
|
3061
|
-
}
|
|
3062
|
-
if (resolved.activeProfile) {
|
|
3063
|
-
lines.push(`**Active profile**: \`${resolved.activeProfile}\``);
|
|
3064
|
-
lines.push("");
|
|
3065
|
-
}
|
|
3066
|
-
return serializeFrontmatter(frontmatter, lines.join(`
|
|
3067
|
-
`));
|
|
3068
|
-
}
|
|
3069
|
-
|
|
3070
|
-
// src/targets/gemini-cli.ts
|
|
3071
|
-
import { join as join20, resolve as resolve18 } from "path";
|
|
3072
|
-
var TARGET_ID5 = "geminicli";
|
|
3073
|
-
|
|
3074
|
-
class GeminiCliTarget extends BaseTarget {
|
|
3075
|
-
id = TARGET_ID5;
|
|
3076
|
-
name = "Gemini CLI";
|
|
3077
|
-
supportedFeatures = [
|
|
3078
|
-
"rules",
|
|
3079
|
-
"commands",
|
|
3080
|
-
"mcp",
|
|
3081
|
-
"ignore",
|
|
3082
|
-
"skills",
|
|
3083
|
-
"hooks"
|
|
3084
|
-
];
|
|
3085
|
-
generate(options) {
|
|
3086
|
-
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
3087
|
-
const root = resolve18(projectRoot, baseDir);
|
|
3088
|
-
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
3089
|
-
const filesWritten = [];
|
|
3090
|
-
const filesDeleted = [];
|
|
3091
|
-
const warnings = [];
|
|
3092
|
-
const geminiDir = resolve18(root, ".gemini");
|
|
3093
|
-
if (effective.includes("rules")) {
|
|
3094
|
-
const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID5));
|
|
3095
|
-
const rootRules = getRootRules(rules);
|
|
3096
|
-
const detailRules = getDetailRules(rules);
|
|
3097
|
-
if (rootRules.length > 0) {
|
|
3098
|
-
const geminiMd = rootRules.map((r) => r.content).join(`
|
|
3099
|
-
|
|
3100
|
-
`);
|
|
3101
|
-
const filepath = resolve18(root, "GEMINI.md");
|
|
3102
|
-
writeGeneratedFile(filepath, geminiMd);
|
|
3103
|
-
filesWritten.push(filepath);
|
|
3104
|
-
}
|
|
3105
|
-
if (detailRules.length > 0) {
|
|
3106
|
-
const memoriesDir = resolve18(geminiDir, "memories");
|
|
3107
|
-
if (deleteExisting) {
|
|
3108
|
-
removeIfExists(memoriesDir);
|
|
3109
|
-
filesDeleted.push(memoriesDir);
|
|
3110
|
-
}
|
|
3111
|
-
ensureDir(memoriesDir);
|
|
3112
|
-
for (const rule of detailRules) {
|
|
3113
|
-
const filepath = join20(memoriesDir, `${rule.name}.md`);
|
|
3114
|
-
writeGeneratedFile(filepath, rule.content);
|
|
3115
|
-
filesWritten.push(filepath);
|
|
3116
|
-
}
|
|
3117
|
-
}
|
|
3118
|
-
}
|
|
3119
|
-
if (effective.includes("commands")) {
|
|
3120
|
-
const commandsDir = resolve18(geminiDir, "commands");
|
|
3121
|
-
if (deleteExisting) {
|
|
3122
|
-
removeIfExists(commandsDir);
|
|
3123
|
-
filesDeleted.push(commandsDir);
|
|
3124
|
-
}
|
|
3125
|
-
ensureDir(commandsDir);
|
|
3126
|
-
const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID5));
|
|
3127
|
-
for (const cmd of commands) {
|
|
3128
|
-
const toml = buildGeminiCommand(cmd.name, cmd.meta.description ?? "", cmd.content);
|
|
3129
|
-
const filepath = join20(commandsDir, `${cmd.name}.toml`);
|
|
3130
|
-
writeGeneratedFile(filepath, toml, { type: "md" });
|
|
3131
|
-
filesWritten.push(filepath);
|
|
3132
|
-
}
|
|
3133
|
-
}
|
|
3134
|
-
if (effective.includes("mcp")) {
|
|
3135
|
-
const mcpEntries = Object.entries(features.mcpServers);
|
|
3136
|
-
if (mcpEntries.length > 0) {
|
|
3137
|
-
const settings = buildGeminiSettings(features.mcpServers);
|
|
3138
|
-
const filepath = resolve18(geminiDir, "settings.json");
|
|
3139
|
-
writeGeneratedJson(filepath, settings, { header: false });
|
|
3140
|
-
filesWritten.push(filepath);
|
|
3141
|
-
}
|
|
3142
|
-
}
|
|
3143
|
-
if (effective.includes("ignore")) {
|
|
3144
|
-
if (features.ignorePatterns.length > 0) {
|
|
3145
|
-
const filepath = resolve18(root, ".geminiignore");
|
|
3146
|
-
const content = features.ignorePatterns.join(`
|
|
3147
|
-
`) + `
|
|
3148
|
-
`;
|
|
3149
|
-
writeGeneratedFile(filepath, content);
|
|
3150
|
-
filesWritten.push(filepath);
|
|
3151
|
-
}
|
|
3152
|
-
}
|
|
3153
|
-
return this.createResult(filesWritten, filesDeleted, warnings);
|
|
3154
|
-
}
|
|
3155
|
-
}
|
|
3156
|
-
function buildGeminiCommand(name, description, content) {
|
|
3157
|
-
return `[command]
|
|
3158
|
-
name = "${name}"
|
|
3159
|
-
description = "${description}"
|
|
34
|
+
`),O=P0(J,"GEMINI.md");G(O,U),H.push(O)}if(L.length>0){let U=P0(C,"memories");if(X)w(U),W.push(U);A(U);for(let O of L){let P=T2(U,`${O.name}.md`);G(P,O.content),H.push(P)}}}if(K.includes("commands")){let B=P0(C,"commands");if(X)w(B),W.push(B);A(B);let V=Z.commands.filter((L)=>k(L,N$));for(let L of V){let U=F1(L.name,L.meta.description??"",L.content),O=T2(B,`${L.name}.toml`);G(O,U,{type:"md"}),H.push(O)}}if(K.includes("mcp")){if(Object.entries(Z.mcpServers).length>0){let V=I1(Z.mcpServers),L=P0(C,"settings.json");S(L,V,{header:!1}),H.push(L)}}if(K.includes("ignore")){if(Z.ignorePatterns.length>0){let B=P0(J,".geminiignore"),V=Z.ignorePatterns.join(`
|
|
35
|
+
`)+`
|
|
36
|
+
`;G(B,V),H.push(B)}}return this.createResult(H,W,_)}}function F1($,Q,Y){return`[command]
|
|
37
|
+
name = "${$}"
|
|
38
|
+
description = "${Q}"
|
|
3160
39
|
|
|
3161
40
|
[prompt]
|
|
3162
41
|
content = """
|
|
3163
|
-
${
|
|
42
|
+
${Y}
|
|
3164
43
|
"""
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
function
|
|
3168
|
-
|
|
3169
|
-
for (const [name, entry] of Object.entries(servers)) {
|
|
3170
|
-
if (entry.command) {
|
|
3171
|
-
mcpServers[name] = {
|
|
3172
|
-
command: entry.command,
|
|
3173
|
-
...entry.args ? { args: entry.args } : {},
|
|
3174
|
-
...entry.env ? { env: entry.env } : {}
|
|
3175
|
-
};
|
|
3176
|
-
} else if (entry.url) {
|
|
3177
|
-
mcpServers[name] = { url: entry.url };
|
|
3178
|
-
}
|
|
3179
|
-
}
|
|
3180
|
-
return { mcpServers };
|
|
3181
|
-
}
|
|
3182
|
-
|
|
3183
|
-
// src/targets/mistral-vibe.ts
|
|
3184
|
-
import { join as join21, resolve as resolve19 } from "path";
|
|
3185
|
-
var TARGET_ID6 = "mistralvibe";
|
|
3186
|
-
|
|
3187
|
-
class MistralVibeTarget extends BaseTarget {
|
|
3188
|
-
id = TARGET_ID6;
|
|
3189
|
-
name = "Mistral Vibe";
|
|
3190
|
-
supportedFeatures = [
|
|
3191
|
-
"rules",
|
|
3192
|
-
"commands",
|
|
3193
|
-
"agents",
|
|
3194
|
-
"skills",
|
|
3195
|
-
"mcp",
|
|
3196
|
-
"ignore",
|
|
3197
|
-
"models"
|
|
3198
|
-
];
|
|
3199
|
-
generate(options) {
|
|
3200
|
-
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
3201
|
-
const root = resolve19(projectRoot, baseDir);
|
|
3202
|
-
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
3203
|
-
const filesWritten = [];
|
|
3204
|
-
const filesDeleted = [];
|
|
3205
|
-
const warnings = [];
|
|
3206
|
-
const vibeDir = resolve19(root, ".vibe");
|
|
3207
|
-
ensureDir(vibeDir);
|
|
3208
|
-
if (effective.includes("rules")) {
|
|
3209
|
-
const rulesDir = resolve19(vibeDir, "rules");
|
|
3210
|
-
if (deleteExisting) {
|
|
3211
|
-
removeIfExists(rulesDir);
|
|
3212
|
-
filesDeleted.push(rulesDir);
|
|
3213
|
-
}
|
|
3214
|
-
ensureDir(rulesDir);
|
|
3215
|
-
const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID6));
|
|
3216
|
-
for (const rule of rules) {
|
|
3217
|
-
const filepath = join21(rulesDir, `${rule.name}.md`);
|
|
3218
|
-
writeGeneratedFile(filepath, rule.content);
|
|
3219
|
-
filesWritten.push(filepath);
|
|
3220
|
-
}
|
|
3221
|
-
}
|
|
3222
|
-
if (effective.includes("agents")) {
|
|
3223
|
-
const agentsDir = resolve19(vibeDir, "agents");
|
|
3224
|
-
if (deleteExisting) {
|
|
3225
|
-
removeIfExists(agentsDir);
|
|
3226
|
-
filesDeleted.push(agentsDir);
|
|
3227
|
-
}
|
|
3228
|
-
ensureDir(agentsDir);
|
|
3229
|
-
const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID6));
|
|
3230
|
-
for (const agent of agents) {
|
|
3231
|
-
const filepath = join21(agentsDir, `${agent.name}.md`);
|
|
3232
|
-
writeGeneratedFile(filepath, agent.content);
|
|
3233
|
-
filesWritten.push(filepath);
|
|
3234
|
-
}
|
|
3235
|
-
}
|
|
3236
|
-
if (effective.includes("skills")) {
|
|
3237
|
-
const skillsDir = resolve19(vibeDir, "skills");
|
|
3238
|
-
if (deleteExisting) {
|
|
3239
|
-
removeIfExists(skillsDir);
|
|
3240
|
-
filesDeleted.push(skillsDir);
|
|
3241
|
-
}
|
|
3242
|
-
ensureDir(skillsDir);
|
|
3243
|
-
const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID6));
|
|
3244
|
-
for (const skill of skills) {
|
|
3245
|
-
const skillSubDir = join21(skillsDir, skill.name);
|
|
3246
|
-
ensureDir(skillSubDir);
|
|
3247
|
-
const filepath = join21(skillSubDir, "SKILL.md");
|
|
3248
|
-
writeGeneratedFile(filepath, serializeSkill(skill));
|
|
3249
|
-
filesWritten.push(filepath);
|
|
3250
|
-
}
|
|
3251
|
-
}
|
|
3252
|
-
if (effective.includes("commands")) {
|
|
3253
|
-
const commandsDir = resolve19(vibeDir, "commands");
|
|
3254
|
-
if (deleteExisting) {
|
|
3255
|
-
removeIfExists(commandsDir);
|
|
3256
|
-
filesDeleted.push(commandsDir);
|
|
3257
|
-
}
|
|
3258
|
-
ensureDir(commandsDir);
|
|
3259
|
-
const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID6));
|
|
3260
|
-
for (const command of commands) {
|
|
3261
|
-
const filepath = join21(commandsDir, `${command.name}.md`);
|
|
3262
|
-
writeGeneratedFile(filepath, command.content);
|
|
3263
|
-
filesWritten.push(filepath);
|
|
3264
|
-
}
|
|
3265
|
-
}
|
|
3266
|
-
let hasMcpConfig = false;
|
|
3267
|
-
if (effective.includes("mcp")) {
|
|
3268
|
-
const mcpEntries = Object.entries(features.mcpServers);
|
|
3269
|
-
if (mcpEntries.length > 0) {
|
|
3270
|
-
const filepath = resolve19(vibeDir, "mcp.json");
|
|
3271
|
-
writeGeneratedJson(filepath, { mcpServers: features.mcpServers }, {
|
|
3272
|
-
header: false
|
|
3273
|
-
});
|
|
3274
|
-
filesWritten.push(filepath);
|
|
3275
|
-
hasMcpConfig = true;
|
|
3276
|
-
}
|
|
3277
|
-
}
|
|
3278
|
-
if (effective.includes("ignore") && features.ignorePatterns.length > 0) {
|
|
3279
|
-
const filepath = resolve19(root, ".vibeignore");
|
|
3280
|
-
writeGeneratedFile(filepath, features.ignorePatterns.join(`
|
|
3281
|
-
`) + `
|
|
3282
|
-
`);
|
|
3283
|
-
filesWritten.push(filepath);
|
|
3284
|
-
}
|
|
3285
|
-
let defaultModel;
|
|
3286
|
-
let smallModel;
|
|
3287
|
-
if (effective.includes("models") && features.models) {
|
|
3288
|
-
const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID6);
|
|
3289
|
-
defaultModel = resolved.default;
|
|
3290
|
-
smallModel = resolved.small;
|
|
3291
|
-
const guidance = generateModelGuidanceMarkdown(resolved);
|
|
3292
|
-
if (guidance) {
|
|
3293
|
-
const filepath = join21(vibeDir, "model-config.md");
|
|
3294
|
-
writeGeneratedFile(filepath, guidance);
|
|
3295
|
-
filesWritten.push(filepath);
|
|
3296
|
-
}
|
|
3297
|
-
}
|
|
3298
|
-
const vibeConfig = buildVibeConfigToml({
|
|
3299
|
-
hasMcpConfig,
|
|
3300
|
-
defaultModel,
|
|
3301
|
-
smallModel,
|
|
3302
|
-
profile: options.modelProfile
|
|
3303
|
-
});
|
|
3304
|
-
if (vibeConfig.length > 0) {
|
|
3305
|
-
const filepath = resolve19(vibeDir, "config.toml");
|
|
3306
|
-
writeGeneratedFile(filepath, vibeConfig);
|
|
3307
|
-
filesWritten.push(filepath);
|
|
3308
|
-
}
|
|
3309
|
-
return this.createResult(filesWritten, filesDeleted, warnings);
|
|
3310
|
-
}
|
|
3311
|
-
}
|
|
3312
|
-
function buildVibeConfigToml(options) {
|
|
3313
|
-
const lines = [];
|
|
3314
|
-
if (options.defaultModel || options.smallModel || options.profile) {
|
|
3315
|
-
lines.push("[models]");
|
|
3316
|
-
if (options.defaultModel) {
|
|
3317
|
-
lines.push(`default = "${escapeTomlString(options.defaultModel)}"`);
|
|
3318
|
-
}
|
|
3319
|
-
if (options.smallModel) {
|
|
3320
|
-
lines.push(`small = "${escapeTomlString(options.smallModel)}"`);
|
|
3321
|
-
}
|
|
3322
|
-
if (options.profile) {
|
|
3323
|
-
lines.push(`profile = "${escapeTomlString(options.profile)}"`);
|
|
3324
|
-
}
|
|
3325
|
-
lines.push("");
|
|
3326
|
-
}
|
|
3327
|
-
if (options.hasMcpConfig) {
|
|
3328
|
-
lines.push("[mcp]");
|
|
3329
|
-
lines.push('config_path = ".vibe/mcp.json"');
|
|
3330
|
-
lines.push("");
|
|
3331
|
-
}
|
|
3332
|
-
return lines.join(`
|
|
3333
|
-
`).trim();
|
|
3334
|
-
}
|
|
3335
|
-
function escapeTomlString(value) {
|
|
3336
|
-
return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
|
3337
|
-
}
|
|
3338
|
-
|
|
3339
|
-
// src/utils/markdown.ts
|
|
3340
|
-
function stripGeneratedHeader(content) {
|
|
3341
|
-
return content.replace(/^<!-- Generated by agentpacks.*-->\n/, "").replace(/^\/\/ Generated by agentpacks.*\n/, "");
|
|
3342
|
-
}
|
|
3343
|
-
function packNameToIdentifier(packName) {
|
|
3344
|
-
return packName.split(/[-_.]/).filter((part) => part.length > 0).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
3345
|
-
}
|
|
3346
|
-
function extractFirstHeading(content) {
|
|
3347
|
-
const match = content.match(/^#{1,6}\s+(.+)$/m);
|
|
3348
|
-
return match?.[1]?.trim() ?? null;
|
|
3349
|
-
}
|
|
3350
|
-
function combineMarkdown(sections, separator = `
|
|
44
|
+
`}function I1($){let Q={};for(let[Y,Z]of Object.entries($))if(Z.command)Q[Y]={command:Z.command,...Z.args?{args:Z.args}:{},...Z.env?{env:Z.env}:{}};else if(Z.url)Q[Y]={url:Z.url};return{mcpServers:Q}}import{join as z0,resolve as r}from"path";var w0="mistralvibe";class M$ extends R{id=w0;name="Mistral Vibe";supportedFeatures=["rules","commands","agents","skills","mcp","ignore","models"];generate($){let{projectRoot:Q,baseDir:Y,features:Z,enabledFeatures:q,deleteExisting:X}=$,J=r(Q,Y),K=this.getEffectiveFeatures(q),H=[],W=[],_=[],C=r(J,".vibe");if(A(C),K.includes("rules")){let O=r(C,"rules");if(X)w(O),W.push(O);A(O);let P=Z.rules.filter((x)=>y(x,w0));for(let x of P){let b=z0(O,`${x.name}.md`);G(b,x.content),H.push(b)}}if(K.includes("agents")){let O=r(C,"agents");if(X)w(O),W.push(O);A(O);let P=Z.agents.filter((x)=>n(x,w0));for(let x of P){let b=z0(O,`${x.name}.md`);G(b,x.content),H.push(b)}}if(K.includes("skills")){let O=r(C,"skills");if(X)w(O),W.push(O);A(O);let P=Z.skills.filter((x)=>u(x,w0));for(let x of P){let b=z0(O,x.name);A(b);let z=z0(b,"SKILL.md");G(z,D(x)),H.push(z)}}if(K.includes("commands")){let O=r(C,"commands");if(X)w(O),W.push(O);A(O);let P=Z.commands.filter((x)=>k(x,w0));for(let x of P){let b=z0(O,`${x.name}.md`);G(b,x.content),H.push(b)}}let B=!1;if(K.includes("mcp")){if(Object.entries(Z.mcpServers).length>0){let P=r(C,"mcp.json");S(P,{mcpServers:Z.mcpServers},{header:!1}),H.push(P),B=!0}}if(K.includes("ignore")&&Z.ignorePatterns.length>0){let O=r(J,".vibeignore");G(O,Z.ignorePatterns.join(`
|
|
45
|
+
`)+`
|
|
46
|
+
`),H.push(O)}let V,L;if(K.includes("models")&&Z.models){let O=j(Z.models,$.modelProfile,w0);V=O.default,L=O.small;let P=q0(O);if(P){let x=z0(C,"model-config.md");G(x,P),H.push(x)}}let U=E1({hasMcpConfig:B,defaultModel:V,smallModel:L,profile:$.modelProfile});if(U.length>0){let O=r(C,"config.toml");G(O,U),H.push(O)}return this.createResult(H,W,_)}}function E1($){let Q=[];if($.defaultModel||$.smallModel||$.profile){if(Q.push("[models]"),$.defaultModel)Q.push(`default = "${b$($.defaultModel)}"`);if($.smallModel)Q.push(`small = "${b$($.smallModel)}"`);if($.profile)Q.push(`profile = "${b$($.profile)}"`);Q.push("")}if($.hasMcpConfig)Q.push("[mcp]"),Q.push('config_path = ".vibe/mcp.json"'),Q.push("");return Q.join(`
|
|
47
|
+
`).trim()}function b$($){return $.replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}function K6($){return $.replace(/^<!-- Generated by agentpacks.*-->\n/,"").replace(/^\/\/ Generated by agentpacks.*\n/,"")}function R2($){return $.split(/[-_.]/).filter((Q)=>Q.length>0).map((Q)=>Q.charAt(0).toUpperCase()+Q.slice(1)).join("")}function J6($){return $.match(/^#{1,6}\s+(.+)$/m)?.[1]?.trim()??null}function O6($,Q=`
|
|
3351
48
|
|
|
3352
49
|
---
|
|
3353
50
|
|
|
3354
|
-
`) {
|
|
3355
|
-
return sections.filter(Boolean).join(separator);
|
|
3356
|
-
}
|
|
3357
|
-
function wrapSection(heading, content, level = 2) {
|
|
3358
|
-
const prefix = "#".repeat(level);
|
|
3359
|
-
return `${prefix} ${heading}
|
|
51
|
+
`){return $.filter(Boolean).join(Q)}function H6($,Q,Y=2){return`${"#".repeat(Y)} ${$}
|
|
3360
52
|
|
|
3361
|
-
${content}
|
|
3362
|
-
}
|
|
53
|
+
${Q}`}import{join as C0,resolve as U0}from"path";var B0="opencode";class G$ extends R{id=B0;name="OpenCode";supportedFeatures=["rules","commands","agents","skills","hooks","plugins","mcp","ignore","models"];generate($){let{projectRoot:Q,baseDir:Y,features:Z,enabledFeatures:q,deleteExisting:X}=$,J=U0(Q,Y),K=this.getEffectiveFeatures(q),H=[],W=[],_=[],C=U0(J,".opencode");if(K.includes("agents")){let B=U0(C,"agent");if(X)w(B),W.push(B);A(B);let V=Z.models?j(Z.models,$.modelProfile,B0):null,L=Z.agents.filter((U)=>n(U,B0));for(let U of L){let O=C0(B,`${U.name}.md`),P={},x=U.meta.opencode??{},b=V?.agents[U.name],z=b?.model??x.model,m=b?.temperature??x.temperature;if(z)P.model=z;if(m!==void 0)P.temperature=m;if(x.mode)P.mode=x.mode;if(x.top_p!==void 0)P.top_p=x.top_p;let V0=Object.keys(P).length>0?v(P,U.content):U.content;G(O,V0),H.push(O)}}if(K.includes("skills")){let B=U0(C,"skill");if(X)w(B),W.push(B);A(B);let V=Z.skills.filter((L)=>u(L,B0));for(let L of V){let U=C0(B,L.name);A(U);let O=C0(U,"SKILL.md");G(O,D(L)),H.push(O)}}if(K.includes("commands")){let B=U0(C,"command");if(X)w(B),W.push(B);A(B);let V=Z.commands.filter((L)=>k(L,B0));for(let L of V){let U=C0(B,`${L.name}.md`);G(U,L.content),H.push(U)}}if(K.includes("hooks")||K.includes("plugins")){let B=U0(C,"plugins");if(A(B),K.includes("hooks"))for(let V of Z.hooks){let L=o(V,B0);if(Object.keys(L).length>0){let U=C0(B,`agentpacks-${V.packName}.ts`),O=R1(V.packName,L);G(U,O,{type:"ts"}),H.push(U)}}if(K.includes("plugins"))for(let V of Z.plugins){let L=C0(B,`agentpacks-${V.packName}-${V.name}.${V.extension}`);G(L,V.content,{type:V.extension}),H.push(L)}}if(K.includes("mcp")||K.includes("models")){let B=U0(J,"opencode.json"),V={$schema:"https://opencode.ai/config.json"};if(K.includes("mcp")){if(Object.entries(Z.mcpServers).length>0)V.mcp=T1(Z.mcpServers)}if(K.includes("models")&&Z.models){let L=j(Z.models,$.modelProfile,B0);if(L.default)V.model=L.default;if(L.small)V.small_model=L.small;if(Object.keys(L.providers).length>0)V.provider=L.providers;let U=Object.entries(L.agents);if(U.length>0){let O={};for(let[P,x]of U){let b={model:x.model};if(x.temperature!==void 0)b.temperature=x.temperature;if(x.top_p!==void 0)b.top_p=x.top_p;O[P]=b}V.agent=O}}if(Object.keys(V).length>1)S(B,V,{header:!1}),H.push(B)}if(K.includes("rules")){let B=Z.rules.filter((L)=>y(L,B0)),V=_0(B);if(V.length>0){let L=U0(C,"memories");if(X)w(L),W.push(L);A(L);for(let U of V){let O=C0(L,`${U.name}.md`);G(O,U.content),H.push(O)}}}return this.createResult(H,W,_)}}function T1($){let Q={};for(let[Y,Z]of Object.entries($))if(Z.url)Q[Y]={type:"remote",url:Z.url,enabled:!0,...Z.headers&&Object.keys(Z.headers).length>0?{headers:Z.headers}:{}};else if(Z.command){let q=Z.args?[Z.command,...Z.args]:[Z.command];Q[Y]={type:"local",command:q,enabled:!0,...Z.env&&Object.keys(Z.env).length>0?{environment:Z.env}:{}}}return Q}function R1($,Q){let Y=R2($),Z=S1(Q),q=Object.entries(Z).map(([X,J])=>{let K=J.map((H)=>{return` ${H.matcher?`if (!/(?:${H.matcher})/.test(String(input?.tool ?? ""))) return;
|
|
54
|
+
`:""}await $\`${H.command}\`;`}).join(`
|
|
55
|
+
`);return` "${X}": async (input, output) => {
|
|
56
|
+
${K}
|
|
57
|
+
},`}).join(`
|
|
58
|
+
`);return`import type { Plugin } from "@opencode-ai/plugin";
|
|
3363
59
|
|
|
3364
|
-
|
|
3365
|
-
import { join as join22, resolve as resolve20 } from "path";
|
|
3366
|
-
var TARGET_ID7 = "opencode";
|
|
3367
|
-
|
|
3368
|
-
class OpenCodeTarget extends BaseTarget {
|
|
3369
|
-
id = TARGET_ID7;
|
|
3370
|
-
name = "OpenCode";
|
|
3371
|
-
supportedFeatures = [
|
|
3372
|
-
"rules",
|
|
3373
|
-
"commands",
|
|
3374
|
-
"agents",
|
|
3375
|
-
"skills",
|
|
3376
|
-
"hooks",
|
|
3377
|
-
"plugins",
|
|
3378
|
-
"mcp",
|
|
3379
|
-
"ignore",
|
|
3380
|
-
"models"
|
|
3381
|
-
];
|
|
3382
|
-
generate(options) {
|
|
3383
|
-
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
3384
|
-
const root = resolve20(projectRoot, baseDir);
|
|
3385
|
-
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
3386
|
-
const filesWritten = [];
|
|
3387
|
-
const filesDeleted = [];
|
|
3388
|
-
const warnings = [];
|
|
3389
|
-
const opencodeDir = resolve20(root, ".opencode");
|
|
3390
|
-
if (effective.includes("agents")) {
|
|
3391
|
-
const agentDir = resolve20(opencodeDir, "agent");
|
|
3392
|
-
if (deleteExisting) {
|
|
3393
|
-
removeIfExists(agentDir);
|
|
3394
|
-
filesDeleted.push(agentDir);
|
|
3395
|
-
}
|
|
3396
|
-
ensureDir(agentDir);
|
|
3397
|
-
const resolvedModels = features.models ? resolveModels(features.models, options.modelProfile, TARGET_ID7) : null;
|
|
3398
|
-
const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID7));
|
|
3399
|
-
for (const agent of agents) {
|
|
3400
|
-
const filepath = join22(agentDir, `${agent.name}.md`);
|
|
3401
|
-
const fm = {};
|
|
3402
|
-
const oc = agent.meta.opencode ?? {};
|
|
3403
|
-
const modelsAgent = resolvedModels?.agents[agent.name];
|
|
3404
|
-
const agentModel = modelsAgent?.model ?? oc.model;
|
|
3405
|
-
const agentTemp = modelsAgent?.temperature ?? oc.temperature;
|
|
3406
|
-
if (agentModel)
|
|
3407
|
-
fm.model = agentModel;
|
|
3408
|
-
if (agentTemp !== undefined)
|
|
3409
|
-
fm.temperature = agentTemp;
|
|
3410
|
-
if (oc.mode)
|
|
3411
|
-
fm.mode = oc.mode;
|
|
3412
|
-
if (oc.top_p !== undefined)
|
|
3413
|
-
fm.top_p = oc.top_p;
|
|
3414
|
-
const content = Object.keys(fm).length > 0 ? serializeFrontmatter(fm, agent.content) : agent.content;
|
|
3415
|
-
writeGeneratedFile(filepath, content);
|
|
3416
|
-
filesWritten.push(filepath);
|
|
3417
|
-
}
|
|
3418
|
-
}
|
|
3419
|
-
if (effective.includes("skills")) {
|
|
3420
|
-
const skillDir = resolve20(opencodeDir, "skill");
|
|
3421
|
-
if (deleteExisting) {
|
|
3422
|
-
removeIfExists(skillDir);
|
|
3423
|
-
filesDeleted.push(skillDir);
|
|
3424
|
-
}
|
|
3425
|
-
ensureDir(skillDir);
|
|
3426
|
-
const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID7));
|
|
3427
|
-
for (const skill of skills) {
|
|
3428
|
-
const skillSubDir = join22(skillDir, skill.name);
|
|
3429
|
-
ensureDir(skillSubDir);
|
|
3430
|
-
const filepath = join22(skillSubDir, "SKILL.md");
|
|
3431
|
-
writeGeneratedFile(filepath, serializeSkill(skill));
|
|
3432
|
-
filesWritten.push(filepath);
|
|
3433
|
-
}
|
|
3434
|
-
}
|
|
3435
|
-
if (effective.includes("commands")) {
|
|
3436
|
-
const cmdDir = resolve20(opencodeDir, "command");
|
|
3437
|
-
if (deleteExisting) {
|
|
3438
|
-
removeIfExists(cmdDir);
|
|
3439
|
-
filesDeleted.push(cmdDir);
|
|
3440
|
-
}
|
|
3441
|
-
ensureDir(cmdDir);
|
|
3442
|
-
const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID7));
|
|
3443
|
-
for (const cmd of commands) {
|
|
3444
|
-
const filepath = join22(cmdDir, `${cmd.name}.md`);
|
|
3445
|
-
writeGeneratedFile(filepath, cmd.content);
|
|
3446
|
-
filesWritten.push(filepath);
|
|
3447
|
-
}
|
|
3448
|
-
}
|
|
3449
|
-
if (effective.includes("hooks") || effective.includes("plugins")) {
|
|
3450
|
-
const pluginsDir = resolve20(opencodeDir, "plugins");
|
|
3451
|
-
ensureDir(pluginsDir);
|
|
3452
|
-
if (effective.includes("hooks")) {
|
|
3453
|
-
for (const hookSet of features.hooks) {
|
|
3454
|
-
const events = resolveHooksForTarget(hookSet, TARGET_ID7);
|
|
3455
|
-
if (Object.keys(events).length > 0) {
|
|
3456
|
-
const filepath = join22(pluginsDir, `agentpacks-${hookSet.packName}.ts`);
|
|
3457
|
-
const content = generateOpenCodeHookPlugin(hookSet.packName, events);
|
|
3458
|
-
writeGeneratedFile(filepath, content, { type: "ts" });
|
|
3459
|
-
filesWritten.push(filepath);
|
|
3460
|
-
}
|
|
3461
|
-
}
|
|
3462
|
-
}
|
|
3463
|
-
if (effective.includes("plugins")) {
|
|
3464
|
-
for (const plugin of features.plugins) {
|
|
3465
|
-
const filepath = join22(pluginsDir, `agentpacks-${plugin.packName}-${plugin.name}.${plugin.extension}`);
|
|
3466
|
-
writeGeneratedFile(filepath, plugin.content, {
|
|
3467
|
-
type: plugin.extension
|
|
3468
|
-
});
|
|
3469
|
-
filesWritten.push(filepath);
|
|
3470
|
-
}
|
|
3471
|
-
}
|
|
3472
|
-
}
|
|
3473
|
-
if (effective.includes("mcp") || effective.includes("models")) {
|
|
3474
|
-
const filepath = resolve20(root, "opencode.json");
|
|
3475
|
-
const opencodeConfig = {
|
|
3476
|
-
$schema: "https://opencode.ai/config.json"
|
|
3477
|
-
};
|
|
3478
|
-
if (effective.includes("mcp")) {
|
|
3479
|
-
const mcpEntries = Object.entries(features.mcpServers);
|
|
3480
|
-
if (mcpEntries.length > 0) {
|
|
3481
|
-
opencodeConfig.mcp = buildOpenCodeMcpServers(features.mcpServers);
|
|
3482
|
-
}
|
|
3483
|
-
}
|
|
3484
|
-
if (effective.includes("models") && features.models) {
|
|
3485
|
-
const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID7);
|
|
3486
|
-
if (resolved.default)
|
|
3487
|
-
opencodeConfig.model = resolved.default;
|
|
3488
|
-
if (resolved.small)
|
|
3489
|
-
opencodeConfig.small_model = resolved.small;
|
|
3490
|
-
if (Object.keys(resolved.providers).length > 0) {
|
|
3491
|
-
opencodeConfig.provider = resolved.providers;
|
|
3492
|
-
}
|
|
3493
|
-
const agentEntries = Object.entries(resolved.agents);
|
|
3494
|
-
if (agentEntries.length > 0) {
|
|
3495
|
-
const agentConfig = {};
|
|
3496
|
-
for (const [name, assignment] of agentEntries) {
|
|
3497
|
-
const config = { model: assignment.model };
|
|
3498
|
-
if (assignment.temperature !== undefined) {
|
|
3499
|
-
config.temperature = assignment.temperature;
|
|
3500
|
-
}
|
|
3501
|
-
if (assignment.top_p !== undefined) {
|
|
3502
|
-
config.top_p = assignment.top_p;
|
|
3503
|
-
}
|
|
3504
|
-
agentConfig[name] = config;
|
|
3505
|
-
}
|
|
3506
|
-
opencodeConfig.agent = agentConfig;
|
|
3507
|
-
}
|
|
3508
|
-
}
|
|
3509
|
-
if (Object.keys(opencodeConfig).length > 1) {
|
|
3510
|
-
writeGeneratedJson(filepath, opencodeConfig, { header: false });
|
|
3511
|
-
filesWritten.push(filepath);
|
|
3512
|
-
}
|
|
3513
|
-
}
|
|
3514
|
-
if (effective.includes("rules")) {
|
|
3515
|
-
const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID7));
|
|
3516
|
-
const detailRules = getDetailRules(rules);
|
|
3517
|
-
if (detailRules.length > 0) {
|
|
3518
|
-
const memoriesDir = resolve20(opencodeDir, "memories");
|
|
3519
|
-
if (deleteExisting) {
|
|
3520
|
-
removeIfExists(memoriesDir);
|
|
3521
|
-
filesDeleted.push(memoriesDir);
|
|
3522
|
-
}
|
|
3523
|
-
ensureDir(memoriesDir);
|
|
3524
|
-
for (const rule of detailRules) {
|
|
3525
|
-
const filepath = join22(memoriesDir, `${rule.name}.md`);
|
|
3526
|
-
writeGeneratedFile(filepath, rule.content);
|
|
3527
|
-
filesWritten.push(filepath);
|
|
3528
|
-
}
|
|
3529
|
-
}
|
|
3530
|
-
}
|
|
3531
|
-
return this.createResult(filesWritten, filesDeleted, warnings);
|
|
3532
|
-
}
|
|
3533
|
-
}
|
|
3534
|
-
function buildOpenCodeMcpServers(servers) {
|
|
3535
|
-
const mcp = {};
|
|
3536
|
-
for (const [name, entry] of Object.entries(servers)) {
|
|
3537
|
-
if (entry.url) {
|
|
3538
|
-
mcp[name] = {
|
|
3539
|
-
type: "remote",
|
|
3540
|
-
url: entry.url,
|
|
3541
|
-
enabled: true,
|
|
3542
|
-
...entry.headers && Object.keys(entry.headers).length > 0 ? { headers: entry.headers } : {}
|
|
3543
|
-
};
|
|
3544
|
-
} else if (entry.command) {
|
|
3545
|
-
const cmd = entry.args ? [entry.command, ...entry.args] : [entry.command];
|
|
3546
|
-
mcp[name] = {
|
|
3547
|
-
type: "local",
|
|
3548
|
-
command: cmd,
|
|
3549
|
-
enabled: true,
|
|
3550
|
-
...entry.env && Object.keys(entry.env).length > 0 ? { environment: entry.env } : {}
|
|
3551
|
-
};
|
|
3552
|
-
}
|
|
3553
|
-
}
|
|
3554
|
-
return mcp;
|
|
3555
|
-
}
|
|
3556
|
-
function generateOpenCodeHookPlugin(packName, events) {
|
|
3557
|
-
const identifier = packNameToIdentifier(packName);
|
|
3558
|
-
const hookMap = mapHookEvents(events);
|
|
3559
|
-
const hookEntries = Object.entries(hookMap).map(([event, handlers]) => {
|
|
3560
|
-
const body = handlers.map((h) => {
|
|
3561
|
-
const matcherGuard = h.matcher ? `if (!/(?:${h.matcher})/.test(String(input?.tool ?? ""))) return;
|
|
3562
|
-
` : "";
|
|
3563
|
-
return ` ${matcherGuard}await $\`${h.command}\`;`;
|
|
3564
|
-
}).join(`
|
|
3565
|
-
`);
|
|
3566
|
-
return ` "${event}": async (input, output) => {
|
|
3567
|
-
${body}
|
|
3568
|
-
},`;
|
|
3569
|
-
}).join(`
|
|
3570
|
-
`);
|
|
3571
|
-
return `import type { Plugin } from "@opencode-ai/plugin";
|
|
3572
|
-
|
|
3573
|
-
export const ${identifier}Plugin: Plugin = async ({ project, client, $, directory, worktree }) => {
|
|
60
|
+
export const ${Y}Plugin: Plugin = async ({ project, client, $, directory, worktree }) => {
|
|
3574
61
|
return {
|
|
3575
|
-
${
|
|
62
|
+
${q}
|
|
3576
63
|
};
|
|
3577
64
|
};
|
|
3578
|
-
|
|
3579
|
-
}
|
|
3580
|
-
function mapHookEvents(events) {
|
|
3581
|
-
const mapped = {};
|
|
3582
|
-
const eventMapping = {
|
|
3583
|
-
sessionStart: "session.created",
|
|
3584
|
-
postToolUse: "tool.execute.after",
|
|
3585
|
-
preToolUse: "tool.execute.before",
|
|
3586
|
-
stop: "session.idle",
|
|
3587
|
-
afterFileEdit: "file.edited",
|
|
3588
|
-
afterShellExecution: "command.executed"
|
|
3589
|
-
};
|
|
3590
|
-
for (const [event, handlers] of Object.entries(events)) {
|
|
3591
|
-
const opencodeEvent = eventMapping[event] ?? event;
|
|
3592
|
-
if (!mapped[opencodeEvent]) {
|
|
3593
|
-
mapped[opencodeEvent] = [];
|
|
3594
|
-
}
|
|
3595
|
-
mapped[opencodeEvent].push(...handlers.filter((h) => h.command));
|
|
3596
|
-
}
|
|
3597
|
-
return mapped;
|
|
3598
|
-
}
|
|
3599
|
-
|
|
3600
|
-
// src/targets/registry.ts
|
|
3601
|
-
var TARGETS = [
|
|
3602
|
-
new OpenCodeTarget,
|
|
3603
|
-
new CursorTarget,
|
|
3604
|
-
new ClaudeCodeTarget,
|
|
3605
|
-
new CodexCliTarget,
|
|
3606
|
-
new MistralVibeTarget,
|
|
3607
|
-
new GeminiCliTarget,
|
|
3608
|
-
new CopilotTarget,
|
|
3609
|
-
new AgentsMdTarget,
|
|
3610
|
-
ClineTarget,
|
|
3611
|
-
KiloTarget,
|
|
3612
|
-
RooTarget,
|
|
3613
|
-
QwenCodeTarget,
|
|
3614
|
-
KiroTarget,
|
|
3615
|
-
FactoryDroidTarget,
|
|
3616
|
-
AntiGravityTarget,
|
|
3617
|
-
JunieTarget,
|
|
3618
|
-
AugmentCodeTarget,
|
|
3619
|
-
WindsurfTarget,
|
|
3620
|
-
WarpTarget,
|
|
3621
|
-
ReplitTarget,
|
|
3622
|
-
ZedTarget
|
|
3623
|
-
];
|
|
3624
|
-
var targetMap = new Map(TARGETS.map((t) => [t.id, t]));
|
|
3625
|
-
function getTarget(id) {
|
|
3626
|
-
return targetMap.get(id);
|
|
3627
|
-
}
|
|
3628
|
-
function getAllTargets() {
|
|
3629
|
-
return [...TARGETS];
|
|
3630
|
-
}
|
|
3631
|
-
function getTargets(ids) {
|
|
3632
|
-
return ids.map((id) => targetMap.get(id)).filter((t) => t !== undefined);
|
|
3633
|
-
}
|
|
3634
|
-
function listTargetIds() {
|
|
3635
|
-
return TARGETS.map((t) => t.id);
|
|
3636
|
-
}
|
|
3637
|
-
export {
|
|
3638
|
-
saveLockfile,
|
|
3639
|
-
resolveTargets,
|
|
3640
|
-
resolveModels,
|
|
3641
|
-
resolveLocalPack,
|
|
3642
|
-
resolveFeatures,
|
|
3643
|
-
resolveDependencies,
|
|
3644
|
-
resolveAgentModel,
|
|
3645
|
-
registrySourceKey,
|
|
3646
|
-
parseRegistrySourceRef,
|
|
3647
|
-
parseNpmSourceRef,
|
|
3648
|
-
parseGitSourceRef,
|
|
3649
|
-
loadWorkspaceConfig,
|
|
3650
|
-
loadPackManifest,
|
|
3651
|
-
loadLockfile,
|
|
3652
|
-
listTargetIds,
|
|
3653
|
-
isRegistryPackRef,
|
|
3654
|
-
isNpmPackRef,
|
|
3655
|
-
isLocalPackRef,
|
|
3656
|
-
isGitPackRef,
|
|
3657
|
-
installNpmSource,
|
|
3658
|
-
installGitSource,
|
|
3659
|
-
importFromRulesync,
|
|
3660
|
-
importFromOpenCode,
|
|
3661
|
-
importFromCursor,
|
|
3662
|
-
importFromClaudeCode,
|
|
3663
|
-
getTargets,
|
|
3664
|
-
getTarget,
|
|
3665
|
-
getAllTargets,
|
|
3666
|
-
exportCursorPlugin,
|
|
3667
|
-
computeIntegrity,
|
|
3668
|
-
WorkspaceConfigSchema,
|
|
3669
|
-
TARGET_IDS,
|
|
3670
|
-
REPO_MODES,
|
|
3671
|
-
PackManifestSchema,
|
|
3672
|
-
PackLoader,
|
|
3673
|
-
FeatureMerger,
|
|
3674
|
-
FEATURE_IDS
|
|
3675
|
-
};
|
|
65
|
+
`}function S1($){let Q={},Y={sessionStart:"session.created",postToolUse:"tool.execute.after",preToolUse:"tool.execute.before",stop:"session.idle",afterFileEdit:"file.edited",afterShellExecution:"command.executed"};for(let[Z,q]of Object.entries($)){let X=Y[Z]??Z;if(!Q[X])Q[X]=[];Q[X].push(...q.filter((J)=>J.command))}return Q}var z$=[new G$,new A$,new H$,new C$,new M$,new x$,new _$,C2,_2,A2,N2,x2,b2,M2,G2,z2,w2,F2,I2,E2],S2=new Map(z$.map(($)=>[$.id,$]));function y1($){return S2.get($)}function j1(){return[...z$]}function h1($){return $.map((Q)=>S2.get(Q)).filter((Q)=>Q!==void 0)}function v1(){return z$.map(($)=>$.id)}export{K9 as saveLockfile,g2 as resolveTargets,j as resolveModels,K1 as resolveLocalPack,k2 as resolveFeatures,D2 as resolveDependencies,D9 as resolveAgentModel,b1 as registrySourceKey,N1 as parseRegistrySourceRef,U$ as parseNpmSourceRef,$$ as parseGitSourceRef,f0 as loadWorkspaceConfig,p0 as loadPackManifest,V9 as loadLockfile,v1 as listTargetIds,x1 as isRegistryPackRef,H1 as isNpmPackRef,J1 as isLocalPackRef,X1 as isGitPackRef,_1 as installNpmSource,U1 as installGitSource,Z1 as importFromRulesync,Q1 as importFromOpenCode,r9 as importFromCursor,i9 as importFromClaudeCode,h1 as getTargets,y1 as getTarget,j1 as getAllTargets,c9 as exportCursorPlugin,c0 as computeIntegrity,u0 as WorkspaceConfigSchema,R$ as TARGET_IDS,S$ as REPO_MODES,D0 as PackManifestSchema,o0 as PackLoader,f$ as FeatureMerger,K0 as FEATURE_IDS};
|