agentpacks 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +168 -8
- package/dist/api.d.ts +2 -0
- package/dist/api.js +929 -409
- package/dist/cli/export-cmd.js +281 -149
- package/dist/cli/generate.js +740 -247
- package/dist/cli/import-cmd.js +57 -85
- package/dist/cli/info.d.ts +4 -0
- package/dist/cli/info.js +232 -0
- package/dist/cli/init.js +8 -36
- package/dist/cli/install.js +414 -129
- package/dist/cli/login.d.ts +9 -0
- package/dist/cli/login.js +202 -0
- package/dist/cli/models-explain.d.ts +16 -0
- package/dist/cli/models-explain.js +1205 -0
- package/dist/cli/pack/create.js +4 -32
- package/dist/cli/pack/enable.js +1 -29
- package/dist/cli/pack/list.js +266 -134
- package/dist/cli/pack/validate.js +274 -127
- package/dist/cli/publish.d.ts +8 -0
- package/dist/cli/publish.js +672 -0
- package/dist/cli/search.d.ts +12 -0
- package/dist/cli/search.js +210 -0
- package/dist/core/config.d.ts +2 -1
- package/dist/core/config.js +74 -117
- package/dist/core/dependency-resolver.js +4 -28
- package/dist/core/feature-merger.d.ts +7 -0
- package/dist/core/feature-merger.js +289 -29
- package/dist/core/index.js +283 -140
- package/dist/core/lockfile.js +0 -28
- package/dist/core/metarepo.js +74 -116
- package/dist/core/pack-loader.d.ts +2 -0
- package/dist/core/pack-loader.js +266 -133
- package/dist/core/profile-resolver.d.ts +75 -0
- package/dist/core/profile-resolver.js +111 -0
- package/dist/exporters/cursor-plugin.js +4 -32
- package/dist/exporters/index.js +4 -32
- package/dist/features/agents.d.ts +5 -0
- package/dist/features/agents.js +2 -30
- package/dist/features/commands.js +2 -30
- package/dist/features/hooks.js +2 -30
- package/dist/features/ignore.js +0 -28
- package/dist/features/index.d.ts +1 -0
- package/dist/features/index.js +176 -31
- package/dist/features/mcp.js +2 -30
- package/dist/features/models.d.ts +167 -0
- package/dist/features/models.js +293 -0
- package/dist/features/plugins.js +2 -30
- package/dist/features/rules.js +2 -30
- package/dist/features/skills.js +2 -30
- package/dist/importers/claude-code.js +10 -38
- package/dist/importers/cursor.js +15 -43
- package/dist/importers/opencode.js +16 -44
- package/dist/importers/rulesync.js +22 -50
- package/dist/index.js +1710 -538
- package/dist/node/api.js +929 -409
- package/dist/node/cli/export-cmd.js +281 -149
- package/dist/node/cli/generate.js +740 -247
- package/dist/node/cli/import-cmd.js +57 -85
- package/dist/node/cli/info.js +232 -0
- package/dist/node/cli/init.js +8 -36
- package/dist/node/cli/install.js +414 -129
- package/dist/node/cli/login.js +202 -0
- package/dist/node/cli/models-explain.js +1205 -0
- package/dist/node/cli/pack/create.js +4 -32
- package/dist/node/cli/pack/enable.js +1 -29
- package/dist/node/cli/pack/list.js +266 -134
- package/dist/node/cli/pack/validate.js +274 -127
- package/dist/node/cli/publish.js +672 -0
- package/dist/node/cli/search.js +210 -0
- package/dist/node/core/config.js +74 -117
- package/dist/node/core/dependency-resolver.js +4 -28
- package/dist/node/core/feature-merger.js +289 -29
- package/dist/node/core/index.js +283 -140
- package/dist/node/core/lockfile.js +0 -28
- package/dist/node/core/metarepo.js +74 -116
- package/dist/node/core/pack-loader.js +266 -133
- package/dist/node/core/profile-resolver.js +111 -0
- package/dist/node/exporters/cursor-plugin.js +4 -32
- package/dist/node/exporters/index.js +4 -32
- package/dist/node/features/agents.js +2 -30
- package/dist/node/features/commands.js +2 -30
- package/dist/node/features/hooks.js +2 -30
- package/dist/node/features/ignore.js +0 -28
- package/dist/node/features/index.js +176 -31
- package/dist/node/features/mcp.js +2 -30
- package/dist/node/features/models.js +293 -0
- package/dist/node/features/plugins.js +2 -30
- package/dist/node/features/rules.js +2 -30
- package/dist/node/features/skills.js +2 -30
- package/dist/node/importers/claude-code.js +10 -38
- package/dist/node/importers/cursor.js +15 -43
- package/dist/node/importers/opencode.js +16 -44
- package/dist/node/importers/rulesync.js +22 -50
- package/dist/node/index.js +1710 -538
- package/dist/node/sources/git-ref.js +7 -30
- package/dist/node/sources/git.js +7 -30
- package/dist/node/sources/index.js +337 -39
- package/dist/node/sources/local.js +0 -28
- package/dist/node/sources/npm-ref.js +0 -28
- package/dist/node/sources/npm.js +10 -37
- package/dist/node/sources/registry-ref.js +37 -0
- package/dist/node/sources/registry.js +355 -0
- package/dist/node/targets/additional-targets.js +196 -37
- package/dist/node/targets/agents-md.js +5 -33
- package/dist/node/targets/base-target.js +0 -28
- package/dist/node/targets/claude-code.js +211 -41
- package/dist/node/targets/codex-cli.js +7 -35
- package/dist/node/targets/copilot.js +202 -41
- package/dist/node/targets/cursor.js +188 -40
- package/dist/node/targets/gemini-cli.js +10 -38
- package/dist/node/targets/generic-md-target.js +196 -37
- package/dist/node/targets/index.js +414 -106
- package/dist/node/targets/opencode.js +171 -51
- package/dist/node/targets/registry.js +414 -106
- package/dist/node/utils/credentials.js +38 -0
- package/dist/node/utils/diff.js +22 -34
- package/dist/node/utils/filesystem.js +2 -30
- package/dist/node/utils/frontmatter.js +0 -28
- package/dist/node/utils/global.js +3 -31
- package/dist/node/utils/markdown.js +0 -28
- package/dist/node/utils/model-allowlist.js +110 -0
- package/dist/node/utils/model-guidance.js +78 -0
- package/dist/node/utils/registry-client.js +142 -0
- package/dist/node/utils/tarball.js +49 -0
- package/dist/sources/git-ref.js +7 -30
- package/dist/sources/git.d.ts +2 -2
- package/dist/sources/git.js +7 -30
- package/dist/sources/index.d.ts +2 -0
- package/dist/sources/index.js +337 -39
- package/dist/sources/local.js +0 -28
- package/dist/sources/npm-ref.js +0 -28
- package/dist/sources/npm.js +10 -37
- package/dist/sources/registry-ref.d.ts +30 -0
- package/dist/sources/registry-ref.js +37 -0
- package/dist/sources/registry.d.ts +18 -0
- package/dist/sources/registry.js +355 -0
- package/dist/targets/additional-targets.js +196 -37
- package/dist/targets/agents-md.js +5 -33
- package/dist/targets/base-target.d.ts +2 -0
- package/dist/targets/base-target.js +0 -28
- package/dist/targets/claude-code.js +211 -41
- package/dist/targets/codex-cli.js +7 -35
- package/dist/targets/copilot.js +202 -41
- package/dist/targets/cursor.js +188 -40
- package/dist/targets/gemini-cli.js +10 -38
- package/dist/targets/generic-md-target.js +196 -37
- package/dist/targets/index.js +414 -106
- package/dist/targets/opencode.js +171 -51
- package/dist/targets/registry.js +414 -106
- package/dist/utils/credentials.d.ts +19 -0
- package/dist/utils/credentials.js +38 -0
- package/dist/utils/diff.js +22 -34
- package/dist/utils/filesystem.js +2 -30
- package/dist/utils/frontmatter.js +0 -28
- package/dist/utils/global.js +3 -31
- package/dist/utils/markdown.js +0 -28
- package/dist/utils/model-allowlist.d.ts +39 -0
- package/dist/utils/model-allowlist.js +110 -0
- package/dist/utils/model-guidance.d.ts +6 -0
- package/dist/utils/model-guidance.js +78 -0
- package/dist/utils/registry-client.d.ts +141 -0
- package/dist/utils/registry-client.js +142 -0
- package/dist/utils/tarball.d.ts +13 -0
- package/dist/utils/tarball.js +49 -0
- package/package.json +171 -5
- package/templates/pack/models.json +38 -0
package/dist/api.js
CHANGED
|
@@ -1,51 +1,85 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
7
|
-
var __toCommonJS = (from) => {
|
|
8
|
-
var entry = __moduleCache.get(from), desc;
|
|
9
|
-
if (entry)
|
|
10
|
-
return entry;
|
|
11
|
-
entry = __defProp({}, "__esModule", { value: true });
|
|
12
|
-
if (from && typeof from === "object" || typeof from === "function")
|
|
13
|
-
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
14
|
-
get: () => from[key],
|
|
15
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
-
}));
|
|
17
|
-
__moduleCache.set(from, entry);
|
|
18
|
-
return entry;
|
|
19
|
-
};
|
|
20
|
-
var __export = (target, all) => {
|
|
21
|
-
for (var name in all)
|
|
22
|
-
__defProp(target, name, {
|
|
23
|
-
get: all[name],
|
|
24
|
-
enumerable: true,
|
|
25
|
-
configurable: true,
|
|
26
|
-
set: (newValue) => all[name] = () => newValue
|
|
27
|
-
});
|
|
28
|
-
};
|
|
29
|
-
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
30
2
|
var __require = import.meta.require;
|
|
31
3
|
|
|
32
4
|
// src/core/config.ts
|
|
33
|
-
var exports_config = {};
|
|
34
|
-
__export(exports_config, {
|
|
35
|
-
resolveTargets: () => resolveTargets,
|
|
36
|
-
resolveFeatures: () => resolveFeatures,
|
|
37
|
-
loadWorkspaceConfig: () => loadWorkspaceConfig,
|
|
38
|
-
loadPackManifest: () => loadPackManifest,
|
|
39
|
-
WorkspaceConfigSchema: () => WorkspaceConfigSchema,
|
|
40
|
-
TARGET_IDS: () => TARGET_IDS,
|
|
41
|
-
REPO_MODES: () => REPO_MODES,
|
|
42
|
-
PackManifestSchema: () => PackManifestSchema,
|
|
43
|
-
FEATURE_IDS: () => FEATURE_IDS
|
|
44
|
-
});
|
|
45
5
|
import { z } from "zod";
|
|
46
6
|
import { readFileSync, existsSync } from "fs";
|
|
47
7
|
import { resolve } from "path";
|
|
48
8
|
import { parse as parseJsonc } from "jsonc-parser";
|
|
9
|
+
var TARGET_IDS = [
|
|
10
|
+
"opencode",
|
|
11
|
+
"cursor",
|
|
12
|
+
"claudecode",
|
|
13
|
+
"codexcli",
|
|
14
|
+
"geminicli",
|
|
15
|
+
"copilot",
|
|
16
|
+
"agentsmd",
|
|
17
|
+
"cline",
|
|
18
|
+
"kilo",
|
|
19
|
+
"roo",
|
|
20
|
+
"qwencode",
|
|
21
|
+
"kiro",
|
|
22
|
+
"factorydroid",
|
|
23
|
+
"antigravity",
|
|
24
|
+
"junie",
|
|
25
|
+
"augmentcode",
|
|
26
|
+
"windsurf",
|
|
27
|
+
"warp",
|
|
28
|
+
"replit",
|
|
29
|
+
"zed"
|
|
30
|
+
];
|
|
31
|
+
var FEATURE_IDS = [
|
|
32
|
+
"rules",
|
|
33
|
+
"commands",
|
|
34
|
+
"agents",
|
|
35
|
+
"skills",
|
|
36
|
+
"hooks",
|
|
37
|
+
"plugins",
|
|
38
|
+
"mcp",
|
|
39
|
+
"ignore",
|
|
40
|
+
"models"
|
|
41
|
+
];
|
|
42
|
+
var REPO_MODES = ["repo", "monorepo", "metarepo"];
|
|
43
|
+
var PackManifestSchema = z.object({
|
|
44
|
+
name: z.string().min(1),
|
|
45
|
+
version: z.string().default("1.0.0"),
|
|
46
|
+
description: z.string().default(""),
|
|
47
|
+
author: z.union([
|
|
48
|
+
z.string(),
|
|
49
|
+
z.object({ name: z.string(), email: z.string().optional() })
|
|
50
|
+
]).optional(),
|
|
51
|
+
tags: z.array(z.string()).default([]),
|
|
52
|
+
dependencies: z.array(z.string()).default([]),
|
|
53
|
+
conflicts: z.array(z.string()).default([]),
|
|
54
|
+
targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
|
|
55
|
+
features: z.union([z.literal("*"), z.array(z.string())]).default("*")
|
|
56
|
+
});
|
|
57
|
+
var FeaturesSchema = z.union([
|
|
58
|
+
z.literal("*"),
|
|
59
|
+
z.array(z.string()),
|
|
60
|
+
z.record(z.string(), z.union([z.literal("*"), z.array(z.string())]))
|
|
61
|
+
]);
|
|
62
|
+
var WorkspaceConfigSchema = z.object({
|
|
63
|
+
$schema: z.string().optional(),
|
|
64
|
+
packs: z.array(z.string()).default(["./packs/default"]),
|
|
65
|
+
disabled: z.array(z.string()).default([]),
|
|
66
|
+
targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
|
|
67
|
+
features: FeaturesSchema.default("*"),
|
|
68
|
+
mode: z.enum(REPO_MODES).default("repo"),
|
|
69
|
+
baseDirs: z.array(z.string()).default(["."]),
|
|
70
|
+
global: z.boolean().default(false),
|
|
71
|
+
delete: z.boolean().default(true),
|
|
72
|
+
verbose: z.boolean().default(false),
|
|
73
|
+
silent: z.boolean().default(false),
|
|
74
|
+
overrides: z.record(z.string(), z.record(z.string(), z.string())).default({}),
|
|
75
|
+
sources: z.array(z.object({
|
|
76
|
+
source: z.string(),
|
|
77
|
+
packs: z.array(z.string()).optional(),
|
|
78
|
+
skills: z.array(z.string()).optional()
|
|
79
|
+
})).default([]),
|
|
80
|
+
modelProfile: z.string().optional()
|
|
81
|
+
});
|
|
82
|
+
var CONFIG_FILES = ["agentpacks.local.jsonc", "agentpacks.jsonc"];
|
|
49
83
|
function loadWorkspaceConfig(projectRoot) {
|
|
50
84
|
for (const filename of CONFIG_FILES) {
|
|
51
85
|
const filepath = resolve(projectRoot, filename);
|
|
@@ -91,81 +125,6 @@ function resolveTargets(config) {
|
|
|
91
125
|
return [...TARGET_IDS];
|
|
92
126
|
return config.targets;
|
|
93
127
|
}
|
|
94
|
-
var TARGET_IDS, FEATURE_IDS, REPO_MODES, PackManifestSchema, FeaturesSchema, WorkspaceConfigSchema, CONFIG_FILES;
|
|
95
|
-
var init_config = __esm(() => {
|
|
96
|
-
TARGET_IDS = [
|
|
97
|
-
"opencode",
|
|
98
|
-
"cursor",
|
|
99
|
-
"claudecode",
|
|
100
|
-
"codexcli",
|
|
101
|
-
"geminicli",
|
|
102
|
-
"copilot",
|
|
103
|
-
"agentsmd",
|
|
104
|
-
"cline",
|
|
105
|
-
"kilo",
|
|
106
|
-
"roo",
|
|
107
|
-
"qwencode",
|
|
108
|
-
"kiro",
|
|
109
|
-
"factorydroid",
|
|
110
|
-
"antigravity",
|
|
111
|
-
"junie",
|
|
112
|
-
"augmentcode",
|
|
113
|
-
"windsurf",
|
|
114
|
-
"warp",
|
|
115
|
-
"replit",
|
|
116
|
-
"zed"
|
|
117
|
-
];
|
|
118
|
-
FEATURE_IDS = [
|
|
119
|
-
"rules",
|
|
120
|
-
"commands",
|
|
121
|
-
"agents",
|
|
122
|
-
"skills",
|
|
123
|
-
"hooks",
|
|
124
|
-
"plugins",
|
|
125
|
-
"mcp",
|
|
126
|
-
"ignore"
|
|
127
|
-
];
|
|
128
|
-
REPO_MODES = ["repo", "monorepo", "metarepo"];
|
|
129
|
-
PackManifestSchema = z.object({
|
|
130
|
-
name: z.string().min(1),
|
|
131
|
-
version: z.string().default("1.0.0"),
|
|
132
|
-
description: z.string().default(""),
|
|
133
|
-
author: z.union([
|
|
134
|
-
z.string(),
|
|
135
|
-
z.object({ name: z.string(), email: z.string().optional() })
|
|
136
|
-
]).optional(),
|
|
137
|
-
tags: z.array(z.string()).default([]),
|
|
138
|
-
dependencies: z.array(z.string()).default([]),
|
|
139
|
-
conflicts: z.array(z.string()).default([]),
|
|
140
|
-
targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
|
|
141
|
-
features: z.union([z.literal("*"), z.array(z.string())]).default("*")
|
|
142
|
-
});
|
|
143
|
-
FeaturesSchema = z.union([
|
|
144
|
-
z.literal("*"),
|
|
145
|
-
z.array(z.string()),
|
|
146
|
-
z.record(z.string(), z.union([z.literal("*"), z.array(z.string())]))
|
|
147
|
-
]);
|
|
148
|
-
WorkspaceConfigSchema = z.object({
|
|
149
|
-
$schema: z.string().optional(),
|
|
150
|
-
packs: z.array(z.string()).default(["./packs/default"]),
|
|
151
|
-
disabled: z.array(z.string()).default([]),
|
|
152
|
-
targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
|
|
153
|
-
features: FeaturesSchema.default("*"),
|
|
154
|
-
mode: z.enum(REPO_MODES).default("repo"),
|
|
155
|
-
baseDirs: z.array(z.string()).default(["."]),
|
|
156
|
-
global: z.boolean().default(false),
|
|
157
|
-
delete: z.boolean().default(true),
|
|
158
|
-
verbose: z.boolean().default(false),
|
|
159
|
-
silent: z.boolean().default(false),
|
|
160
|
-
overrides: z.record(z.string(), z.record(z.string(), z.string())).default({}),
|
|
161
|
-
sources: z.array(z.object({
|
|
162
|
-
source: z.string(),
|
|
163
|
-
packs: z.array(z.string()).optional(),
|
|
164
|
-
skills: z.array(z.string()).optional()
|
|
165
|
-
})).default([])
|
|
166
|
-
});
|
|
167
|
-
CONFIG_FILES = ["agentpacks.local.jsonc", "agentpacks.jsonc"];
|
|
168
|
-
});
|
|
169
128
|
|
|
170
129
|
// src/utils/filesystem.ts
|
|
171
130
|
import {
|
|
@@ -174,10 +133,10 @@ import {
|
|
|
174
133
|
readFileSync as readFileSync2,
|
|
175
134
|
writeFileSync,
|
|
176
135
|
readdirSync,
|
|
136
|
+
rmSync,
|
|
177
137
|
statSync
|
|
178
138
|
} from "fs";
|
|
179
139
|
import { dirname, relative, join } from "path";
|
|
180
|
-
import { removeSync } from "fs-extra";
|
|
181
140
|
var GENERATED_HEADER_MD = "<!-- Generated by agentpacks. DO NOT EDIT. -->";
|
|
182
141
|
var GENERATED_HEADER_JSON = "// Generated by agentpacks. DO NOT EDIT.";
|
|
183
142
|
var GENERATED_HEADER_JS = "// Generated by agentpacks. DO NOT EDIT.";
|
|
@@ -218,7 +177,7 @@ function ensureDir(dirPath) {
|
|
|
218
177
|
}
|
|
219
178
|
function removeIfExists(targetPath) {
|
|
220
179
|
if (existsSync2(targetPath)) {
|
|
221
|
-
|
|
180
|
+
rmSync(targetPath, { recursive: true, force: true });
|
|
222
181
|
}
|
|
223
182
|
}
|
|
224
183
|
function listFiles(dirPath, options = {}) {
|
|
@@ -544,10 +503,178 @@ function mergeIgnorePatterns(configs) {
|
|
|
544
503
|
return result;
|
|
545
504
|
}
|
|
546
505
|
|
|
506
|
+
// src/features/models.ts
|
|
507
|
+
import { join as join7 } from "path";
|
|
508
|
+
import { z as z2 } from "zod";
|
|
509
|
+
var SECRET_PATTERNS = [
|
|
510
|
+
/["']api[_-]?key["']\s*:/i,
|
|
511
|
+
/["']apiKey["']\s*:/i,
|
|
512
|
+
/["']secret["']\s*:/i,
|
|
513
|
+
/["']password["']\s*:/i,
|
|
514
|
+
/["'](?:auth_token|access_token|bearer_token)["']\s*:/i,
|
|
515
|
+
/["']private[_-]?key["']\s*:/i,
|
|
516
|
+
/-----BEGIN\s+(RSA|EC|DSA|OPENSSH|PGP)\s+PRIVATE\s+KEY-----/,
|
|
517
|
+
/sk-[a-zA-Z0-9]{20,}/,
|
|
518
|
+
/Bearer\s+[a-zA-Z0-9._-]{20,}/
|
|
519
|
+
];
|
|
520
|
+
var AgentModelSchema = z2.object({
|
|
521
|
+
model: z2.string(),
|
|
522
|
+
temperature: z2.number().min(0).max(2).optional(),
|
|
523
|
+
top_p: z2.number().min(0).max(1).optional()
|
|
524
|
+
});
|
|
525
|
+
var ModelProfileSchema = z2.object({
|
|
526
|
+
extends: z2.string().optional(),
|
|
527
|
+
description: z2.string().optional(),
|
|
528
|
+
default: z2.string().optional(),
|
|
529
|
+
small: z2.string().optional(),
|
|
530
|
+
agents: z2.record(z2.string(), AgentModelSchema).optional()
|
|
531
|
+
});
|
|
532
|
+
var RoutingConditionSchema = z2.object({
|
|
533
|
+
complexity: z2.enum(["low", "medium", "high", "critical"]).optional().describe("Task complexity level"),
|
|
534
|
+
urgency: z2.enum(["low", "normal", "high"]).optional().describe("Time sensitivity"),
|
|
535
|
+
budget: z2.enum(["minimal", "standard", "premium"]).optional().describe("Cost/token budget tier"),
|
|
536
|
+
contextWindowNeed: z2.enum(["small", "medium", "large", "max"]).optional().describe("Required context window size"),
|
|
537
|
+
toolUseIntensity: z2.enum(["none", "light", "heavy"]).optional().describe("Expected tool/function calling intensity")
|
|
538
|
+
});
|
|
539
|
+
var RoutingRuleSchema = z2.object({
|
|
540
|
+
when: z2.record(z2.string(), z2.string()),
|
|
541
|
+
use: z2.string(),
|
|
542
|
+
description: z2.string().optional(),
|
|
543
|
+
priority: z2.number().optional()
|
|
544
|
+
});
|
|
545
|
+
var ProviderModelSchema = z2.object({
|
|
546
|
+
options: z2.record(z2.string(), z2.unknown()).optional(),
|
|
547
|
+
variants: z2.record(z2.string(), z2.record(z2.string(), z2.unknown())).optional()
|
|
548
|
+
});
|
|
549
|
+
var ProviderConfigSchema = z2.object({
|
|
550
|
+
options: z2.record(z2.string(), z2.unknown()).optional(),
|
|
551
|
+
models: z2.record(z2.string(), ProviderModelSchema).optional()
|
|
552
|
+
});
|
|
553
|
+
var ModelsSchema = z2.object({
|
|
554
|
+
default: z2.string().optional(),
|
|
555
|
+
small: z2.string().optional(),
|
|
556
|
+
agents: z2.record(z2.string(), AgentModelSchema).optional(),
|
|
557
|
+
profiles: z2.record(z2.string(), ModelProfileSchema).optional(),
|
|
558
|
+
providers: z2.record(z2.string(), ProviderConfigSchema).optional(),
|
|
559
|
+
routing: z2.array(RoutingRuleSchema).optional(),
|
|
560
|
+
overrides: z2.record(z2.string(), z2.object({
|
|
561
|
+
default: z2.string().optional(),
|
|
562
|
+
small: z2.string().optional(),
|
|
563
|
+
agents: z2.record(z2.string(), AgentModelSchema).optional()
|
|
564
|
+
})).optional()
|
|
565
|
+
});
|
|
566
|
+
function parseModels(packDir, packName) {
|
|
567
|
+
const modelsPath = join7(packDir, "models.json");
|
|
568
|
+
const raw = readJsonOrNull(modelsPath);
|
|
569
|
+
if (!raw)
|
|
570
|
+
return null;
|
|
571
|
+
const parsed = ModelsSchema.parse(raw);
|
|
572
|
+
return {
|
|
573
|
+
packName,
|
|
574
|
+
sourcePath: modelsPath,
|
|
575
|
+
config: parsed
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
function mergeModelsConfigs(configs) {
|
|
579
|
+
const warnings = [];
|
|
580
|
+
const result = {};
|
|
581
|
+
for (const entry of configs) {
|
|
582
|
+
const { config, packName } = entry;
|
|
583
|
+
if (config.default !== undefined && result.default === undefined) {
|
|
584
|
+
result.default = config.default;
|
|
585
|
+
} else if (config.default !== undefined && result.default !== undefined) {
|
|
586
|
+
warnings.push(`Models "default" from pack "${packName}" skipped (already defined).`);
|
|
587
|
+
}
|
|
588
|
+
if (config.small !== undefined && result.small === undefined) {
|
|
589
|
+
result.small = config.small;
|
|
590
|
+
} else if (config.small !== undefined && result.small !== undefined) {
|
|
591
|
+
warnings.push(`Models "small" from pack "${packName}" skipped (already defined).`);
|
|
592
|
+
}
|
|
593
|
+
if (config.agents) {
|
|
594
|
+
if (!result.agents)
|
|
595
|
+
result.agents = {};
|
|
596
|
+
for (const [name, assignment] of Object.entries(config.agents)) {
|
|
597
|
+
if (name in result.agents) {
|
|
598
|
+
warnings.push(`Models agent "${name}" from pack "${packName}" skipped (already defined).`);
|
|
599
|
+
continue;
|
|
600
|
+
}
|
|
601
|
+
result.agents[name] = assignment;
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
if (config.profiles) {
|
|
605
|
+
if (!result.profiles)
|
|
606
|
+
result.profiles = {};
|
|
607
|
+
for (const [name, profile] of Object.entries(config.profiles)) {
|
|
608
|
+
if (name in result.profiles) {
|
|
609
|
+
warnings.push(`Models profile "${name}" from pack "${packName}" skipped (already defined).`);
|
|
610
|
+
continue;
|
|
611
|
+
}
|
|
612
|
+
result.profiles[name] = profile;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
if (config.providers) {
|
|
616
|
+
if (!result.providers)
|
|
617
|
+
result.providers = {};
|
|
618
|
+
for (const [providerName, providerConfig] of Object.entries(config.providers)) {
|
|
619
|
+
if (!(providerName in result.providers)) {
|
|
620
|
+
result.providers[providerName] = providerConfig;
|
|
621
|
+
} else {
|
|
622
|
+
const existing = result.providers[providerName];
|
|
623
|
+
if (!existing) {
|
|
624
|
+
result.providers[providerName] = providerConfig;
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
if (providerConfig.options) {
|
|
628
|
+
existing.options = {
|
|
629
|
+
...providerConfig.options,
|
|
630
|
+
...existing.options
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
if (providerConfig.models) {
|
|
634
|
+
if (!existing.models)
|
|
635
|
+
existing.models = {};
|
|
636
|
+
for (const [modelName, modelConfig] of Object.entries(providerConfig.models)) {
|
|
637
|
+
if (!(modelName in existing.models)) {
|
|
638
|
+
existing.models[modelName] = modelConfig;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
if (config.routing) {
|
|
646
|
+
if (!result.routing)
|
|
647
|
+
result.routing = [];
|
|
648
|
+
result.routing.push(...config.routing);
|
|
649
|
+
}
|
|
650
|
+
if (config.overrides) {
|
|
651
|
+
if (!result.overrides)
|
|
652
|
+
result.overrides = {};
|
|
653
|
+
for (const [targetId, override] of Object.entries(config.overrides)) {
|
|
654
|
+
if (targetId in result.overrides) {
|
|
655
|
+
warnings.push(`Models override for target "${targetId}" from pack "${packName}" skipped (already defined).`);
|
|
656
|
+
continue;
|
|
657
|
+
}
|
|
658
|
+
result.overrides[targetId] = override;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
return { config: result, warnings };
|
|
663
|
+
}
|
|
664
|
+
function scanModelsForSecrets(config) {
|
|
665
|
+
const warnings = [];
|
|
666
|
+
const json = JSON.stringify(config);
|
|
667
|
+
for (const pattern of SECRET_PATTERNS) {
|
|
668
|
+
if (pattern.test(json)) {
|
|
669
|
+
warnings.push(`Potential secret detected in models.json matching pattern: ${pattern.source}`);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
return warnings;
|
|
673
|
+
}
|
|
674
|
+
|
|
547
675
|
// src/core/pack-loader.ts
|
|
548
|
-
init_config();
|
|
549
676
|
import { existsSync as existsSync6 } from "fs";
|
|
550
|
-
import { resolve as
|
|
677
|
+
import { resolve as resolve2, isAbsolute } from "path";
|
|
551
678
|
class PackLoader {
|
|
552
679
|
projectRoot;
|
|
553
680
|
config;
|
|
@@ -580,10 +707,10 @@ class PackLoader {
|
|
|
580
707
|
}
|
|
581
708
|
loadPack(packDir, manifest) {
|
|
582
709
|
const name = manifest.name;
|
|
583
|
-
const rulesDir =
|
|
584
|
-
const commandsDir =
|
|
585
|
-
const agentsDir =
|
|
586
|
-
const skillsDir =
|
|
710
|
+
const rulesDir = resolve2(packDir, "rules");
|
|
711
|
+
const commandsDir = resolve2(packDir, "commands");
|
|
712
|
+
const agentsDir = resolve2(packDir, "agents");
|
|
713
|
+
const skillsDir = resolve2(packDir, "skills");
|
|
587
714
|
return {
|
|
588
715
|
manifest,
|
|
589
716
|
directory: packDir,
|
|
@@ -594,23 +721,25 @@ class PackLoader {
|
|
|
594
721
|
hooks: parseHooks(packDir, name),
|
|
595
722
|
plugins: parsePlugins(packDir, name),
|
|
596
723
|
mcp: parseMcp(packDir, name),
|
|
597
|
-
ignore: parseIgnore(packDir, name)
|
|
724
|
+
ignore: parseIgnore(packDir, name),
|
|
725
|
+
models: parseModels(packDir, name)
|
|
598
726
|
};
|
|
599
727
|
}
|
|
600
728
|
loadForBaseDir(baseDir) {
|
|
601
|
-
const baseDirRoot =
|
|
602
|
-
const localConfigPath =
|
|
729
|
+
const baseDirRoot = resolve2(this.projectRoot, baseDir);
|
|
730
|
+
const localConfigPath = resolve2(baseDirRoot, "agentpacks.jsonc");
|
|
603
731
|
if (!existsSync6(localConfigPath)) {
|
|
604
732
|
return { packs: [], warnings: [] };
|
|
605
733
|
}
|
|
606
|
-
const
|
|
607
|
-
const localConfig = loadWorkspaceConfig2(baseDirRoot);
|
|
734
|
+
const localConfig = loadWorkspaceConfig(baseDirRoot);
|
|
608
735
|
const loader = new PackLoader(baseDirRoot, localConfig);
|
|
609
736
|
return loader.loadAll();
|
|
610
737
|
}
|
|
611
738
|
resolveCuratedPack(packRef) {
|
|
612
|
-
const curatedDir =
|
|
739
|
+
const curatedDir = resolve2(this.projectRoot, ".agentpacks", ".curated");
|
|
613
740
|
let packName = packRef;
|
|
741
|
+
if (packName.startsWith("registry:"))
|
|
742
|
+
packName = packName.slice(9);
|
|
614
743
|
if (packName.startsWith("npm:"))
|
|
615
744
|
packName = packName.slice(4);
|
|
616
745
|
if (packName.startsWith("github:"))
|
|
@@ -621,24 +750,28 @@ class PackLoader {
|
|
|
621
750
|
const parts = packName.split("/");
|
|
622
751
|
packName = packName.includes("@") ? parts.join("-") : parts[parts.length - 1] ?? packName;
|
|
623
752
|
}
|
|
624
|
-
|
|
625
|
-
|
|
753
|
+
const withoutVersion = packName.split("@")[0] ?? packName;
|
|
754
|
+
packName = withoutVersion.split(":")[0] ?? withoutVersion;
|
|
755
|
+
const resolved = resolve2(curatedDir, packName);
|
|
626
756
|
return existsSync6(resolved) ? resolved : null;
|
|
627
757
|
}
|
|
628
758
|
resolvePackPath(packRef) {
|
|
629
759
|
if (packRef.startsWith("./") || packRef.startsWith("../")) {
|
|
630
|
-
return
|
|
760
|
+
return resolve2(this.projectRoot, packRef);
|
|
631
761
|
}
|
|
632
762
|
if (isAbsolute(packRef)) {
|
|
633
763
|
return packRef;
|
|
634
764
|
}
|
|
765
|
+
if (packRef.startsWith("registry:")) {
|
|
766
|
+
return this.resolveCuratedPack(packRef);
|
|
767
|
+
}
|
|
635
768
|
if (packRef.startsWith("@") || packRef.startsWith("npm:") || !packRef.includes("/")) {
|
|
636
769
|
return this.resolveCuratedPack(packRef);
|
|
637
770
|
}
|
|
638
771
|
if (packRef.startsWith("github:") || packRef.includes("/")) {
|
|
639
772
|
return this.resolveCuratedPack(packRef);
|
|
640
773
|
}
|
|
641
|
-
return
|
|
774
|
+
return resolve2(this.projectRoot, packRef);
|
|
642
775
|
}
|
|
643
776
|
}
|
|
644
777
|
|
|
@@ -659,7 +792,8 @@ class FeatureMerger {
|
|
|
659
792
|
hooks: this.mergeHooks(),
|
|
660
793
|
plugins: this.mergePlugins(),
|
|
661
794
|
mcpServers: this.mergeMcp(),
|
|
662
|
-
ignorePatterns: this.mergeIgnore()
|
|
795
|
+
ignorePatterns: this.mergeIgnore(),
|
|
796
|
+
models: this.mergeModels()
|
|
663
797
|
};
|
|
664
798
|
return { features, warnings: this.warnings };
|
|
665
799
|
}
|
|
@@ -746,16 +880,24 @@ class FeatureMerger {
|
|
|
746
880
|
}
|
|
747
881
|
return result;
|
|
748
882
|
}
|
|
883
|
+
mergeModels() {
|
|
884
|
+
const configs = this.packs.map((p) => p.models).filter((m) => m != null);
|
|
885
|
+
if (configs.length === 0)
|
|
886
|
+
return null;
|
|
887
|
+
const { config, warnings } = mergeModelsConfigs(configs);
|
|
888
|
+
this.warnings.push(...warnings);
|
|
889
|
+
return config;
|
|
890
|
+
}
|
|
749
891
|
}
|
|
750
892
|
|
|
751
893
|
// src/core/lockfile.ts
|
|
752
894
|
import { existsSync as existsSync7, readFileSync as readFileSync9, writeFileSync as writeFileSync2 } from "fs";
|
|
753
|
-
import { resolve as
|
|
895
|
+
import { resolve as resolve3 } from "path";
|
|
754
896
|
import { createHash } from "crypto";
|
|
755
897
|
var LOCKFILE_VERSION = 1;
|
|
756
898
|
var LOCKFILE_NAME = "agentpacks.lock";
|
|
757
899
|
function loadLockfile(projectRoot) {
|
|
758
|
-
const filepath =
|
|
900
|
+
const filepath = resolve3(projectRoot, LOCKFILE_NAME);
|
|
759
901
|
if (!existsSync7(filepath)) {
|
|
760
902
|
return { lockfileVersion: LOCKFILE_VERSION, sources: {} };
|
|
761
903
|
}
|
|
@@ -763,7 +905,7 @@ function loadLockfile(projectRoot) {
|
|
|
763
905
|
return JSON.parse(raw);
|
|
764
906
|
}
|
|
765
907
|
function saveLockfile(projectRoot, lockfile) {
|
|
766
|
-
const filepath =
|
|
908
|
+
const filepath = resolve3(projectRoot, LOCKFILE_NAME);
|
|
767
909
|
writeFileSync2(filepath, JSON.stringify(lockfile, null, 2) + `
|
|
768
910
|
`);
|
|
769
911
|
}
|
|
@@ -831,8 +973,12 @@ function topologicalSort(graph) {
|
|
|
831
973
|
const sorted = [];
|
|
832
974
|
while (queue.length > 0) {
|
|
833
975
|
const current = queue.shift();
|
|
976
|
+
if (!current)
|
|
977
|
+
continue;
|
|
834
978
|
sorted.push(current);
|
|
835
979
|
const node = graph.get(current);
|
|
980
|
+
if (!node)
|
|
981
|
+
continue;
|
|
836
982
|
for (const dep of node.dependencies) {
|
|
837
983
|
if (!graph.has(dep))
|
|
838
984
|
continue;
|
|
@@ -899,15 +1045,119 @@ function detectConflicts(graph) {
|
|
|
899
1045
|
return conflicts;
|
|
900
1046
|
}
|
|
901
1047
|
|
|
1048
|
+
// src/core/profile-resolver.ts
|
|
1049
|
+
function resolveModels(merged, modelProfile, targetId) {
|
|
1050
|
+
let defaultModel = merged.default;
|
|
1051
|
+
let smallModel = merged.small;
|
|
1052
|
+
let agents = { ...merged.agents };
|
|
1053
|
+
if (modelProfile && merged.profiles?.[modelProfile]) {
|
|
1054
|
+
const resolvedProfile = resolveProfileInheritance(modelProfile, merged.profiles);
|
|
1055
|
+
if (resolvedProfile.default)
|
|
1056
|
+
defaultModel = resolvedProfile.default;
|
|
1057
|
+
if (resolvedProfile.small)
|
|
1058
|
+
smallModel = resolvedProfile.small;
|
|
1059
|
+
if (resolvedProfile.agents) {
|
|
1060
|
+
agents = { ...agents, ...resolvedProfile.agents };
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
if (targetId) {
|
|
1064
|
+
const targetOverride = merged.overrides?.[targetId];
|
|
1065
|
+
if (targetOverride) {
|
|
1066
|
+
if (targetOverride.default)
|
|
1067
|
+
defaultModel = targetOverride.default;
|
|
1068
|
+
if (targetOverride.small)
|
|
1069
|
+
smallModel = targetOverride.small;
|
|
1070
|
+
if (targetOverride.agents) {
|
|
1071
|
+
agents = { ...agents, ...targetOverride.agents };
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
const providers = {};
|
|
1076
|
+
if (merged.providers) {
|
|
1077
|
+
for (const [name, config] of Object.entries(merged.providers)) {
|
|
1078
|
+
providers[name] = {
|
|
1079
|
+
...config.options ? { options: config.options } : {},
|
|
1080
|
+
...config.models ? { models: config.models } : {}
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
const profileNames = Object.keys(merged.profiles ?? {});
|
|
1085
|
+
const profiles = {};
|
|
1086
|
+
if (merged.profiles) {
|
|
1087
|
+
for (const [name, profile] of Object.entries(merged.profiles)) {
|
|
1088
|
+
profiles[name] = {
|
|
1089
|
+
description: profile.description,
|
|
1090
|
+
default: profile.default,
|
|
1091
|
+
small: profile.small
|
|
1092
|
+
};
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
return {
|
|
1096
|
+
default: defaultModel,
|
|
1097
|
+
small: smallModel,
|
|
1098
|
+
agents,
|
|
1099
|
+
providers,
|
|
1100
|
+
routing: merged.routing ?? [],
|
|
1101
|
+
profileNames,
|
|
1102
|
+
activeProfile: modelProfile,
|
|
1103
|
+
profiles
|
|
1104
|
+
};
|
|
1105
|
+
}
|
|
1106
|
+
function resolveAgentModel(resolved, agentName, frontmatterModel) {
|
|
1107
|
+
const fromModels = resolved.agents[agentName];
|
|
1108
|
+
if (fromModels) {
|
|
1109
|
+
return {
|
|
1110
|
+
model: fromModels.model,
|
|
1111
|
+
temperature: fromModels.temperature,
|
|
1112
|
+
top_p: fromModels.top_p
|
|
1113
|
+
};
|
|
1114
|
+
}
|
|
1115
|
+
if (frontmatterModel) {
|
|
1116
|
+
return { model: frontmatterModel };
|
|
1117
|
+
}
|
|
1118
|
+
return {};
|
|
1119
|
+
}
|
|
1120
|
+
function resolveProfileInheritance(profileName, profiles) {
|
|
1121
|
+
const visited = new Set;
|
|
1122
|
+
return resolveProfileChain(profileName, profiles, visited, 0);
|
|
1123
|
+
}
|
|
1124
|
+
var MAX_INHERITANCE_DEPTH = 10;
|
|
1125
|
+
function resolveProfileChain(name, profiles, visited, depth) {
|
|
1126
|
+
if (depth > MAX_INHERITANCE_DEPTH) {
|
|
1127
|
+
throw new Error(`Profile inheritance too deep (max ${MAX_INHERITANCE_DEPTH}): ${name}`);
|
|
1128
|
+
}
|
|
1129
|
+
if (visited.has(name)) {
|
|
1130
|
+
throw new Error(`Circular profile inheritance detected: ${[...visited, name].join(" \u2192 ")}`);
|
|
1131
|
+
}
|
|
1132
|
+
const profile = profiles[name];
|
|
1133
|
+
if (!profile) {
|
|
1134
|
+
throw new Error(`Profile "${name}" not found`);
|
|
1135
|
+
}
|
|
1136
|
+
visited.add(name);
|
|
1137
|
+
if (!profile.extends) {
|
|
1138
|
+
return { ...profile };
|
|
1139
|
+
}
|
|
1140
|
+
const parent = resolveProfileChain(profile.extends, profiles, visited, depth + 1);
|
|
1141
|
+
return {
|
|
1142
|
+
description: profile.description ?? parent.description,
|
|
1143
|
+
default: profile.default ?? parent.default,
|
|
1144
|
+
small: profile.small ?? parent.small,
|
|
1145
|
+
agents: {
|
|
1146
|
+
...parent.agents,
|
|
1147
|
+
...profile.agents
|
|
1148
|
+
}
|
|
1149
|
+
};
|
|
1150
|
+
}
|
|
1151
|
+
|
|
902
1152
|
// src/sources/local.ts
|
|
903
1153
|
import { existsSync as existsSync8 } from "fs";
|
|
904
|
-
import { resolve as
|
|
1154
|
+
import { resolve as resolve4, isAbsolute as isAbsolute2 } from "path";
|
|
905
1155
|
function resolveLocalPack(packRef, projectRoot) {
|
|
906
1156
|
let resolved;
|
|
907
1157
|
if (isAbsolute2(packRef)) {
|
|
908
1158
|
resolved = packRef;
|
|
909
1159
|
} else {
|
|
910
|
-
resolved =
|
|
1160
|
+
resolved = resolve4(projectRoot, packRef);
|
|
911
1161
|
}
|
|
912
1162
|
if (!existsSync8(resolved))
|
|
913
1163
|
return null;
|
|
@@ -939,9 +1189,14 @@ function parseGitSourceRef(source) {
|
|
|
939
1189
|
if (parts.length < 2) {
|
|
940
1190
|
throw new Error(`Invalid git source reference: "${source}". Expected owner/repo format.`);
|
|
941
1191
|
}
|
|
1192
|
+
const owner = parts[0];
|
|
1193
|
+
const repo = parts[1];
|
|
1194
|
+
if (!owner || !repo) {
|
|
1195
|
+
throw new Error(`Invalid git source reference: "${source}". Expected owner/repo format.`);
|
|
1196
|
+
}
|
|
942
1197
|
return {
|
|
943
|
-
owner
|
|
944
|
-
repo
|
|
1198
|
+
owner,
|
|
1199
|
+
repo,
|
|
945
1200
|
ref,
|
|
946
1201
|
path: path || ""
|
|
947
1202
|
};
|
|
@@ -1010,9 +1265,39 @@ function npmSourceKey(parsed) {
|
|
|
1010
1265
|
return `npm:${parsed.packageName}`;
|
|
1011
1266
|
}
|
|
1012
1267
|
|
|
1268
|
+
// src/sources/registry-ref.ts
|
|
1269
|
+
function parseRegistrySourceRef(source) {
|
|
1270
|
+
let s = source;
|
|
1271
|
+
if (s.startsWith("registry:")) {
|
|
1272
|
+
s = s.slice(9);
|
|
1273
|
+
}
|
|
1274
|
+
if (!s) {
|
|
1275
|
+
throw new Error(`Invalid registry source reference: "${source}". Expected pack name.`);
|
|
1276
|
+
}
|
|
1277
|
+
let version = "latest";
|
|
1278
|
+
const atIdx = s.indexOf("@");
|
|
1279
|
+
if (atIdx > 0) {
|
|
1280
|
+
version = s.slice(atIdx + 1);
|
|
1281
|
+
s = s.slice(0, atIdx);
|
|
1282
|
+
}
|
|
1283
|
+
if (!s) {
|
|
1284
|
+
throw new Error(`Invalid registry source reference: "${source}". Pack name is empty.`);
|
|
1285
|
+
}
|
|
1286
|
+
if (!/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(s)) {
|
|
1287
|
+
throw new Error(`Invalid registry pack name: "${s}". Must be lowercase alphanumeric with hyphens.`);
|
|
1288
|
+
}
|
|
1289
|
+
return { packName: s, version };
|
|
1290
|
+
}
|
|
1291
|
+
function isRegistryPackRef(packRef) {
|
|
1292
|
+
return packRef.startsWith("registry:");
|
|
1293
|
+
}
|
|
1294
|
+
function registrySourceKey(parsed) {
|
|
1295
|
+
return `registry:${parsed.packName}`;
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1013
1298
|
// src/sources/git.ts
|
|
1014
1299
|
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
1015
|
-
import { resolve as
|
|
1300
|
+
import { resolve as resolve5, join as join8 } from "path";
|
|
1016
1301
|
var GITHUB_API = "https://api.github.com";
|
|
1017
1302
|
function githubHeaders(token) {
|
|
1018
1303
|
const h = {
|
|
@@ -1065,11 +1350,11 @@ async function fetchAndWriteSubdir(parsed, sha, remotePath, localDir, installed,
|
|
|
1065
1350
|
for (const entry of entries) {
|
|
1066
1351
|
if (entry.type === "file" && entry.download_url) {
|
|
1067
1352
|
const content = await fetchGitFile(entry.download_url, token);
|
|
1068
|
-
const filepath =
|
|
1353
|
+
const filepath = join8(localDir, entry.name);
|
|
1069
1354
|
writeFileSync3(filepath, content);
|
|
1070
1355
|
installed.push(filepath);
|
|
1071
1356
|
} else if (entry.type === "dir") {
|
|
1072
|
-
await fetchAndWriteSubdir(parsed, sha, `${remotePath}/${entry.name}`,
|
|
1357
|
+
await fetchAndWriteSubdir(parsed, sha, `${remotePath}/${entry.name}`, join8(localDir, entry.name), installed, token);
|
|
1073
1358
|
}
|
|
1074
1359
|
}
|
|
1075
1360
|
}
|
|
@@ -1090,7 +1375,7 @@ async function installGitSource(projectRoot, source, lockfile, options = {}) {
|
|
|
1090
1375
|
}
|
|
1091
1376
|
const basePath = parsed.path || "packs";
|
|
1092
1377
|
const entries = await fetchGitDirectory(parsed, resolvedSha, basePath, options.token);
|
|
1093
|
-
const curatedDir =
|
|
1378
|
+
const curatedDir = resolve5(projectRoot, ".agentpacks", ".curated");
|
|
1094
1379
|
mkdirSync2(curatedDir, { recursive: true });
|
|
1095
1380
|
const newLockEntry = {
|
|
1096
1381
|
requestedRef: parsed.ref,
|
|
@@ -1102,21 +1387,21 @@ async function installGitSource(projectRoot, source, lockfile, options = {}) {
|
|
|
1102
1387
|
const packDirs = entries.filter((e) => e.type === "dir");
|
|
1103
1388
|
for (const packEntry of packDirs) {
|
|
1104
1389
|
const packName = packEntry.name;
|
|
1105
|
-
const packOutDir =
|
|
1390
|
+
const packOutDir = resolve5(curatedDir, packName);
|
|
1106
1391
|
const packFiles = await fetchGitDirectory(parsed, resolvedSha, `${basePath}/${packName}`, options.token);
|
|
1107
1392
|
mkdirSync2(packOutDir, { recursive: true });
|
|
1108
1393
|
for (const file of packFiles) {
|
|
1109
1394
|
if (file.type === "file" && file.download_url) {
|
|
1110
1395
|
const content = await fetchGitFile(file.download_url, options.token);
|
|
1111
|
-
writeFileSync3(
|
|
1112
|
-
installed.push(
|
|
1396
|
+
writeFileSync3(join8(packOutDir, file.name), content);
|
|
1397
|
+
installed.push(join8(packOutDir, file.name));
|
|
1113
1398
|
if (newLockEntry.packs) {
|
|
1114
1399
|
newLockEntry.packs[packName] = {
|
|
1115
1400
|
integrity: computeIntegrity(content)
|
|
1116
1401
|
};
|
|
1117
1402
|
}
|
|
1118
1403
|
} else if (file.type === "dir") {
|
|
1119
|
-
await fetchAndWriteSubdir(parsed, resolvedSha, `${basePath}/${packName}/${file.name}`,
|
|
1404
|
+
await fetchAndWriteSubdir(parsed, resolvedSha, `${basePath}/${packName}/${file.name}`, join8(packOutDir, file.name), installed, options.token);
|
|
1120
1405
|
}
|
|
1121
1406
|
}
|
|
1122
1407
|
}
|
|
@@ -1124,15 +1409,15 @@ async function installGitSource(projectRoot, source, lockfile, options = {}) {
|
|
|
1124
1409
|
const fileEntries = entries.filter((e) => e.type === "file");
|
|
1125
1410
|
if (fileEntries.length > 0) {
|
|
1126
1411
|
const packName = parsed.path.split("/").pop() ?? parsed.repo;
|
|
1127
|
-
const packOutDir =
|
|
1412
|
+
const packOutDir = resolve5(curatedDir, packName);
|
|
1128
1413
|
mkdirSync2(packOutDir, { recursive: true });
|
|
1129
1414
|
for (const file of entries) {
|
|
1130
1415
|
if (file.type === "file" && file.download_url) {
|
|
1131
1416
|
const content = await fetchGitFile(file.download_url, options.token);
|
|
1132
|
-
writeFileSync3(
|
|
1133
|
-
installed.push(
|
|
1417
|
+
writeFileSync3(join8(packOutDir, file.name), content);
|
|
1418
|
+
installed.push(join8(packOutDir, file.name));
|
|
1134
1419
|
} else if (file.type === "dir") {
|
|
1135
|
-
await fetchAndWriteSubdir(parsed, resolvedSha, `${basePath}/${file.name}`,
|
|
1420
|
+
await fetchAndWriteSubdir(parsed, resolvedSha, `${basePath}/${file.name}`, join8(packOutDir, file.name), installed, options.token);
|
|
1136
1421
|
}
|
|
1137
1422
|
}
|
|
1138
1423
|
}
|
|
@@ -1142,8 +1427,8 @@ async function installGitSource(projectRoot, source, lockfile, options = {}) {
|
|
|
1142
1427
|
}
|
|
1143
1428
|
|
|
1144
1429
|
// src/sources/npm.ts
|
|
1145
|
-
import { mkdirSync as mkdirSync3, existsSync as existsSync9 } from "fs";
|
|
1146
|
-
import { resolve as
|
|
1430
|
+
import { mkdirSync as mkdirSync3, existsSync as existsSync9, readdirSync as readdirSync2 } from "fs";
|
|
1431
|
+
import { resolve as resolve6, join as join9 } from "path";
|
|
1147
1432
|
import { execSync } from "child_process";
|
|
1148
1433
|
var NPM_REGISTRY = "https://registry.npmjs.org";
|
|
1149
1434
|
async function resolveNpmVersion(parsed) {
|
|
@@ -1167,18 +1452,15 @@ async function installNpmSource(projectRoot, source, lockfile, options = {}) {
|
|
|
1167
1452
|
throw new Error(`Frozen mode: no lockfile entry for source "${sourceKey}".`);
|
|
1168
1453
|
}
|
|
1169
1454
|
let resolvedVersion;
|
|
1170
|
-
let tarballUrl;
|
|
1171
1455
|
if (locked && !options.update) {
|
|
1172
1456
|
resolvedVersion = locked.resolvedRef;
|
|
1173
|
-
tarballUrl = "";
|
|
1174
1457
|
} else {
|
|
1175
1458
|
const resolved = await resolveNpmVersion(parsed);
|
|
1176
1459
|
resolvedVersion = resolved.version;
|
|
1177
|
-
tarballUrl = resolved.tarball;
|
|
1178
1460
|
}
|
|
1179
|
-
const curatedDir =
|
|
1461
|
+
const curatedDir = resolve6(projectRoot, ".agentpacks", ".curated");
|
|
1180
1462
|
mkdirSync3(curatedDir, { recursive: true });
|
|
1181
|
-
|
|
1463
|
+
extractNpmPack(parsed, resolvedVersion, curatedDir, installed, warnings);
|
|
1182
1464
|
const newEntry = {
|
|
1183
1465
|
requestedRef: parsed.version,
|
|
1184
1466
|
resolvedRef: resolvedVersion,
|
|
@@ -1192,20 +1474,25 @@ async function installNpmSource(projectRoot, source, lockfile, options = {}) {
|
|
|
1192
1474
|
function extractNpmPack(parsed, version, curatedDir, installed, warnings) {
|
|
1193
1475
|
const pkgSpec = `${parsed.packageName}@${version}`;
|
|
1194
1476
|
const packName = parsed.packageName.replace(/^@/, "").replace(/\//g, "-");
|
|
1195
|
-
const packOutDir =
|
|
1477
|
+
const packOutDir = resolve6(curatedDir, packName);
|
|
1196
1478
|
try {
|
|
1197
|
-
const tmpDir =
|
|
1479
|
+
const tmpDir = resolve6(curatedDir, ".tmp-npm");
|
|
1198
1480
|
mkdirSync3(tmpDir, { recursive: true });
|
|
1199
1481
|
execSync(`npm pack ${pkgSpec} --pack-destination "${tmpDir}"`, {
|
|
1200
1482
|
stdio: "pipe",
|
|
1201
1483
|
timeout: 30000
|
|
1202
1484
|
});
|
|
1203
|
-
const tgzFiles =
|
|
1485
|
+
const tgzFiles = readdirSync2(tmpDir).filter((f) => f.endsWith(".tgz"));
|
|
1204
1486
|
if (tgzFiles.length === 0) {
|
|
1205
1487
|
warnings.push(`No tarball found for ${pkgSpec}`);
|
|
1206
1488
|
return packOutDir;
|
|
1207
1489
|
}
|
|
1208
|
-
const
|
|
1490
|
+
const firstTgz = tgzFiles[0];
|
|
1491
|
+
if (!firstTgz) {
|
|
1492
|
+
warnings.push(`No tarball found for ${pkgSpec}`);
|
|
1493
|
+
return packOutDir;
|
|
1494
|
+
}
|
|
1495
|
+
const tgzPath = join9(tmpDir, firstTgz);
|
|
1209
1496
|
mkdirSync3(packOutDir, { recursive: true });
|
|
1210
1497
|
execSync(`tar xzf "${tgzPath}" -C "${packOutDir}" --strip-components=1`, {
|
|
1211
1498
|
stdio: "pipe",
|
|
@@ -1213,7 +1500,7 @@ function extractNpmPack(parsed, version, curatedDir, installed, warnings) {
|
|
|
1213
1500
|
});
|
|
1214
1501
|
execSync(`rm -rf "${tmpDir}"`, { stdio: "pipe" });
|
|
1215
1502
|
const subpath = parsed.path || "";
|
|
1216
|
-
const targetDir = subpath ?
|
|
1503
|
+
const targetDir = subpath ? join9(packOutDir, subpath) : packOutDir;
|
|
1217
1504
|
if (existsSync9(targetDir)) {
|
|
1218
1505
|
collectFiles(targetDir, installed);
|
|
1219
1506
|
}
|
|
@@ -1223,10 +1510,9 @@ function extractNpmPack(parsed, version, curatedDir, installed, warnings) {
|
|
|
1223
1510
|
return packOutDir;
|
|
1224
1511
|
}
|
|
1225
1512
|
function collectFiles(dir, out) {
|
|
1226
|
-
const
|
|
1227
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
1513
|
+
const entries = readdirSync2(dir, { withFileTypes: true });
|
|
1228
1514
|
for (const entry of entries) {
|
|
1229
|
-
const full =
|
|
1515
|
+
const full = join9(dir, entry.name);
|
|
1230
1516
|
if (entry.isDirectory()) {
|
|
1231
1517
|
collectFiles(full, out);
|
|
1232
1518
|
} else {
|
|
@@ -1279,7 +1565,7 @@ ${content}`;
|
|
|
1279
1565
|
}
|
|
1280
1566
|
|
|
1281
1567
|
// src/targets/opencode.ts
|
|
1282
|
-
import { resolve as
|
|
1568
|
+
import { resolve as resolve7, join as join10 } from "path";
|
|
1283
1569
|
var TARGET_ID = "opencode";
|
|
1284
1570
|
|
|
1285
1571
|
class OpenCodeTarget extends BaseTarget {
|
|
@@ -1293,32 +1579,48 @@ class OpenCodeTarget extends BaseTarget {
|
|
|
1293
1579
|
"hooks",
|
|
1294
1580
|
"plugins",
|
|
1295
1581
|
"mcp",
|
|
1296
|
-
"ignore"
|
|
1582
|
+
"ignore",
|
|
1583
|
+
"models"
|
|
1297
1584
|
];
|
|
1298
1585
|
generate(options) {
|
|
1299
1586
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
1300
|
-
const root =
|
|
1587
|
+
const root = resolve7(projectRoot, baseDir);
|
|
1301
1588
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
1302
1589
|
const filesWritten = [];
|
|
1303
1590
|
const filesDeleted = [];
|
|
1304
1591
|
const warnings = [];
|
|
1305
|
-
const opencodeDir =
|
|
1592
|
+
const opencodeDir = resolve7(root, ".opencode");
|
|
1306
1593
|
if (effective.includes("agents")) {
|
|
1307
|
-
const agentDir =
|
|
1594
|
+
const agentDir = resolve7(opencodeDir, "agent");
|
|
1308
1595
|
if (deleteExisting) {
|
|
1309
1596
|
removeIfExists(agentDir);
|
|
1310
1597
|
filesDeleted.push(agentDir);
|
|
1311
1598
|
}
|
|
1312
1599
|
ensureDir(agentDir);
|
|
1600
|
+
const resolvedModels = features.models ? resolveModels(features.models, options.modelProfile, TARGET_ID) : null;
|
|
1313
1601
|
const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID));
|
|
1314
1602
|
for (const agent of agents) {
|
|
1315
|
-
const filepath =
|
|
1316
|
-
|
|
1603
|
+
const filepath = join10(agentDir, `${agent.name}.md`);
|
|
1604
|
+
const fm = {};
|
|
1605
|
+
const oc = agent.meta.opencode ?? {};
|
|
1606
|
+
const modelsAgent = resolvedModels?.agents[agent.name];
|
|
1607
|
+
const agentModel = modelsAgent?.model ?? oc.model;
|
|
1608
|
+
const agentTemp = modelsAgent?.temperature ?? oc.temperature;
|
|
1609
|
+
if (agentModel)
|
|
1610
|
+
fm.model = agentModel;
|
|
1611
|
+
if (agentTemp !== undefined)
|
|
1612
|
+
fm.temperature = agentTemp;
|
|
1613
|
+
if (oc.mode)
|
|
1614
|
+
fm.mode = oc.mode;
|
|
1615
|
+
if (oc.top_p !== undefined)
|
|
1616
|
+
fm.top_p = oc.top_p;
|
|
1617
|
+
const content = Object.keys(fm).length > 0 ? serializeFrontmatter(fm, agent.content) : agent.content;
|
|
1618
|
+
writeGeneratedFile(filepath, content);
|
|
1317
1619
|
filesWritten.push(filepath);
|
|
1318
1620
|
}
|
|
1319
1621
|
}
|
|
1320
1622
|
if (effective.includes("skills")) {
|
|
1321
|
-
const skillDir =
|
|
1623
|
+
const skillDir = resolve7(opencodeDir, "skill");
|
|
1322
1624
|
if (deleteExisting) {
|
|
1323
1625
|
removeIfExists(skillDir);
|
|
1324
1626
|
filesDeleted.push(skillDir);
|
|
@@ -1326,15 +1628,15 @@ class OpenCodeTarget extends BaseTarget {
|
|
|
1326
1628
|
ensureDir(skillDir);
|
|
1327
1629
|
const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID));
|
|
1328
1630
|
for (const skill of skills) {
|
|
1329
|
-
const skillSubDir =
|
|
1631
|
+
const skillSubDir = join10(skillDir, skill.name);
|
|
1330
1632
|
ensureDir(skillSubDir);
|
|
1331
|
-
const filepath =
|
|
1633
|
+
const filepath = join10(skillSubDir, "SKILL.md");
|
|
1332
1634
|
writeGeneratedFile(filepath, skill.content);
|
|
1333
1635
|
filesWritten.push(filepath);
|
|
1334
1636
|
}
|
|
1335
1637
|
}
|
|
1336
1638
|
if (effective.includes("commands")) {
|
|
1337
|
-
const cmdDir =
|
|
1639
|
+
const cmdDir = resolve7(opencodeDir, "command");
|
|
1338
1640
|
if (deleteExisting) {
|
|
1339
1641
|
removeIfExists(cmdDir);
|
|
1340
1642
|
filesDeleted.push(cmdDir);
|
|
@@ -1342,19 +1644,19 @@ class OpenCodeTarget extends BaseTarget {
|
|
|
1342
1644
|
ensureDir(cmdDir);
|
|
1343
1645
|
const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID));
|
|
1344
1646
|
for (const cmd of commands) {
|
|
1345
|
-
const filepath =
|
|
1647
|
+
const filepath = join10(cmdDir, `${cmd.name}.md`);
|
|
1346
1648
|
writeGeneratedFile(filepath, cmd.content);
|
|
1347
1649
|
filesWritten.push(filepath);
|
|
1348
1650
|
}
|
|
1349
1651
|
}
|
|
1350
1652
|
if (effective.includes("hooks") || effective.includes("plugins")) {
|
|
1351
|
-
const pluginsDir =
|
|
1653
|
+
const pluginsDir = resolve7(opencodeDir, "plugins");
|
|
1352
1654
|
ensureDir(pluginsDir);
|
|
1353
1655
|
if (effective.includes("hooks")) {
|
|
1354
1656
|
for (const hookSet of features.hooks) {
|
|
1355
1657
|
const events = resolveHooksForTarget(hookSet, TARGET_ID);
|
|
1356
1658
|
if (Object.keys(events).length > 0) {
|
|
1357
|
-
const filepath =
|
|
1659
|
+
const filepath = join10(pluginsDir, `agentpacks-${hookSet.packName}.ts`);
|
|
1358
1660
|
const content = generateOpenCodeHookPlugin(hookSet.packName, events);
|
|
1359
1661
|
writeGeneratedFile(filepath, content, { type: "ts" });
|
|
1360
1662
|
filesWritten.push(filepath);
|
|
@@ -1363,7 +1665,7 @@ class OpenCodeTarget extends BaseTarget {
|
|
|
1363
1665
|
}
|
|
1364
1666
|
if (effective.includes("plugins")) {
|
|
1365
1667
|
for (const plugin of features.plugins) {
|
|
1366
|
-
const filepath =
|
|
1668
|
+
const filepath = join10(pluginsDir, `agentpacks-${plugin.packName}-${plugin.name}.${plugin.extension}`);
|
|
1367
1669
|
writeGeneratedFile(filepath, plugin.content, {
|
|
1368
1670
|
type: plugin.extension
|
|
1369
1671
|
});
|
|
@@ -1371,28 +1673,59 @@ class OpenCodeTarget extends BaseTarget {
|
|
|
1371
1673
|
}
|
|
1372
1674
|
}
|
|
1373
1675
|
}
|
|
1374
|
-
if (effective.includes("mcp")) {
|
|
1375
|
-
const
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1676
|
+
if (effective.includes("mcp") || effective.includes("models")) {
|
|
1677
|
+
const filepath = resolve7(root, "opencode.json");
|
|
1678
|
+
const opencodeConfig = {
|
|
1679
|
+
$schema: "https://opencode.ai/config.json"
|
|
1680
|
+
};
|
|
1681
|
+
if (effective.includes("mcp")) {
|
|
1682
|
+
const mcpEntries = Object.entries(features.mcpServers);
|
|
1683
|
+
if (mcpEntries.length > 0) {
|
|
1684
|
+
opencodeConfig.mcp = buildOpenCodeMcpServers(features.mcpServers);
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
if (effective.includes("models") && features.models) {
|
|
1688
|
+
const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID);
|
|
1689
|
+
if (resolved.default)
|
|
1690
|
+
opencodeConfig.model = resolved.default;
|
|
1691
|
+
if (resolved.small)
|
|
1692
|
+
opencodeConfig.small_model = resolved.small;
|
|
1693
|
+
if (Object.keys(resolved.providers).length > 0) {
|
|
1694
|
+
opencodeConfig.provider = resolved.providers;
|
|
1695
|
+
}
|
|
1696
|
+
const agentEntries = Object.entries(resolved.agents);
|
|
1697
|
+
if (agentEntries.length > 0) {
|
|
1698
|
+
const agentConfig = {};
|
|
1699
|
+
for (const [name, assignment] of agentEntries) {
|
|
1700
|
+
const config = { model: assignment.model };
|
|
1701
|
+
if (assignment.temperature !== undefined) {
|
|
1702
|
+
config.temperature = assignment.temperature;
|
|
1703
|
+
}
|
|
1704
|
+
if (assignment.top_p !== undefined) {
|
|
1705
|
+
config.top_p = assignment.top_p;
|
|
1706
|
+
}
|
|
1707
|
+
agentConfig[name] = config;
|
|
1708
|
+
}
|
|
1709
|
+
opencodeConfig.agent = agentConfig;
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
if (Object.keys(opencodeConfig).length > 1) {
|
|
1379
1713
|
writeGeneratedJson(filepath, opencodeConfig, { header: false });
|
|
1380
1714
|
filesWritten.push(filepath);
|
|
1381
1715
|
}
|
|
1382
1716
|
}
|
|
1383
1717
|
if (effective.includes("rules")) {
|
|
1384
1718
|
const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID));
|
|
1385
|
-
const rootRules = getRootRules(rules);
|
|
1386
1719
|
const detailRules = getDetailRules(rules);
|
|
1387
1720
|
if (detailRules.length > 0) {
|
|
1388
|
-
const memoriesDir =
|
|
1721
|
+
const memoriesDir = resolve7(opencodeDir, "memories");
|
|
1389
1722
|
if (deleteExisting) {
|
|
1390
1723
|
removeIfExists(memoriesDir);
|
|
1391
1724
|
filesDeleted.push(memoriesDir);
|
|
1392
1725
|
}
|
|
1393
1726
|
ensureDir(memoriesDir);
|
|
1394
1727
|
for (const rule of detailRules) {
|
|
1395
|
-
const filepath =
|
|
1728
|
+
const filepath = join10(memoriesDir, `${rule.name}.md`);
|
|
1396
1729
|
writeGeneratedFile(filepath, rule.content);
|
|
1397
1730
|
filesWritten.push(filepath);
|
|
1398
1731
|
}
|
|
@@ -1401,7 +1734,7 @@ class OpenCodeTarget extends BaseTarget {
|
|
|
1401
1734
|
return this.createResult(filesWritten, filesDeleted, warnings);
|
|
1402
1735
|
}
|
|
1403
1736
|
}
|
|
1404
|
-
function
|
|
1737
|
+
function buildOpenCodeMcpServers(servers) {
|
|
1405
1738
|
const mcp = {};
|
|
1406
1739
|
for (const [name, entry] of Object.entries(servers)) {
|
|
1407
1740
|
if (entry.url) {
|
|
@@ -1421,10 +1754,7 @@ function buildOpenCodeMcp(servers) {
|
|
|
1421
1754
|
};
|
|
1422
1755
|
}
|
|
1423
1756
|
}
|
|
1424
|
-
return
|
|
1425
|
-
$schema: "https://opencode.ai/config.json",
|
|
1426
|
-
mcp
|
|
1427
|
-
};
|
|
1757
|
+
return mcp;
|
|
1428
1758
|
}
|
|
1429
1759
|
function generateOpenCodeHookPlugin(packName, events) {
|
|
1430
1760
|
const identifier = packNameToIdentifier(packName);
|
|
@@ -1471,7 +1801,7 @@ function mapHookEvents(events) {
|
|
|
1471
1801
|
}
|
|
1472
1802
|
|
|
1473
1803
|
// src/targets/cursor.ts
|
|
1474
|
-
import { resolve as
|
|
1804
|
+
import { resolve as resolve8, join as join11 } from "path";
|
|
1475
1805
|
var TARGET_ID2 = "cursor";
|
|
1476
1806
|
|
|
1477
1807
|
class CursorTarget extends BaseTarget {
|
|
@@ -1484,18 +1814,19 @@ class CursorTarget extends BaseTarget {
|
|
|
1484
1814
|
"skills",
|
|
1485
1815
|
"hooks",
|
|
1486
1816
|
"mcp",
|
|
1487
|
-
"ignore"
|
|
1817
|
+
"ignore",
|
|
1818
|
+
"models"
|
|
1488
1819
|
];
|
|
1489
1820
|
generate(options) {
|
|
1490
1821
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
1491
|
-
const root =
|
|
1822
|
+
const root = resolve8(projectRoot, baseDir);
|
|
1492
1823
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
1493
1824
|
const filesWritten = [];
|
|
1494
1825
|
const filesDeleted = [];
|
|
1495
1826
|
const warnings = [];
|
|
1496
|
-
const cursorDir =
|
|
1827
|
+
const cursorDir = resolve8(root, ".cursor");
|
|
1497
1828
|
if (effective.includes("rules")) {
|
|
1498
|
-
const rulesDir =
|
|
1829
|
+
const rulesDir = resolve8(cursorDir, "rules");
|
|
1499
1830
|
if (deleteExisting) {
|
|
1500
1831
|
removeIfExists(rulesDir);
|
|
1501
1832
|
filesDeleted.push(rulesDir);
|
|
@@ -1512,33 +1843,40 @@ class CursorTarget extends BaseTarget {
|
|
|
1512
1843
|
if (globs) {
|
|
1513
1844
|
frontmatter.globs = globs;
|
|
1514
1845
|
}
|
|
1515
|
-
const filepath =
|
|
1846
|
+
const filepath = join11(rulesDir, `${rule.name}.mdc`);
|
|
1516
1847
|
const content = serializeFrontmatter(frontmatter, rule.content);
|
|
1517
1848
|
writeGeneratedFile(filepath, content);
|
|
1518
1849
|
filesWritten.push(filepath);
|
|
1519
1850
|
}
|
|
1520
1851
|
}
|
|
1521
1852
|
if (effective.includes("agents")) {
|
|
1522
|
-
const agentsDir =
|
|
1853
|
+
const agentsDir = resolve8(cursorDir, "agents");
|
|
1523
1854
|
if (deleteExisting) {
|
|
1524
1855
|
removeIfExists(agentsDir);
|
|
1525
1856
|
filesDeleted.push(agentsDir);
|
|
1526
1857
|
}
|
|
1527
1858
|
ensureDir(agentsDir);
|
|
1859
|
+
const resolvedModels = features.models ? resolveModels(features.models, options.modelProfile, TARGET_ID2) : null;
|
|
1528
1860
|
const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID2));
|
|
1529
1861
|
for (const agent of agents) {
|
|
1530
1862
|
const frontmatter = {
|
|
1531
1863
|
name: agent.name,
|
|
1532
1864
|
description: agent.meta.description ?? ""
|
|
1533
1865
|
};
|
|
1534
|
-
const
|
|
1866
|
+
const cursorMeta = agent.meta.cursor ?? {};
|
|
1867
|
+
const modelsAgent = resolvedModels?.agents[agent.name];
|
|
1868
|
+
const model = modelsAgent?.model ?? cursorMeta.model;
|
|
1869
|
+
if (model) {
|
|
1870
|
+
frontmatter.model = model;
|
|
1871
|
+
}
|
|
1872
|
+
const filepath = join11(agentsDir, `${agent.name}.md`);
|
|
1535
1873
|
const content = serializeFrontmatter(frontmatter, agent.content);
|
|
1536
1874
|
writeGeneratedFile(filepath, content);
|
|
1537
1875
|
filesWritten.push(filepath);
|
|
1538
1876
|
}
|
|
1539
1877
|
}
|
|
1540
1878
|
if (effective.includes("skills")) {
|
|
1541
|
-
const skillsDir =
|
|
1879
|
+
const skillsDir = resolve8(cursorDir, "skills");
|
|
1542
1880
|
if (deleteExisting) {
|
|
1543
1881
|
removeIfExists(skillsDir);
|
|
1544
1882
|
filesDeleted.push(skillsDir);
|
|
@@ -1546,20 +1884,20 @@ class CursorTarget extends BaseTarget {
|
|
|
1546
1884
|
ensureDir(skillsDir);
|
|
1547
1885
|
const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID2));
|
|
1548
1886
|
for (const skill of skills) {
|
|
1549
|
-
const skillSubDir =
|
|
1887
|
+
const skillSubDir = join11(skillsDir, skill.name);
|
|
1550
1888
|
ensureDir(skillSubDir);
|
|
1551
1889
|
const frontmatter = {
|
|
1552
1890
|
name: skill.name,
|
|
1553
1891
|
description: skill.meta.description ?? ""
|
|
1554
1892
|
};
|
|
1555
|
-
const filepath =
|
|
1893
|
+
const filepath = join11(skillSubDir, "SKILL.md");
|
|
1556
1894
|
const content = serializeFrontmatter(frontmatter, skill.content);
|
|
1557
1895
|
writeGeneratedFile(filepath, content);
|
|
1558
1896
|
filesWritten.push(filepath);
|
|
1559
1897
|
}
|
|
1560
1898
|
}
|
|
1561
1899
|
if (effective.includes("commands")) {
|
|
1562
|
-
const commandsDir =
|
|
1900
|
+
const commandsDir = resolve8(cursorDir, "commands");
|
|
1563
1901
|
if (deleteExisting) {
|
|
1564
1902
|
removeIfExists(commandsDir);
|
|
1565
1903
|
filesDeleted.push(commandsDir);
|
|
@@ -1567,7 +1905,7 @@ class CursorTarget extends BaseTarget {
|
|
|
1567
1905
|
ensureDir(commandsDir);
|
|
1568
1906
|
const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID2));
|
|
1569
1907
|
for (const cmd of commands) {
|
|
1570
|
-
const filepath =
|
|
1908
|
+
const filepath = join11(commandsDir, `${cmd.name}.md`);
|
|
1571
1909
|
writeGeneratedFile(filepath, cmd.content);
|
|
1572
1910
|
filesWritten.push(filepath);
|
|
1573
1911
|
}
|
|
@@ -1576,14 +1914,14 @@ class CursorTarget extends BaseTarget {
|
|
|
1576
1914
|
const mcpEntries = Object.entries(features.mcpServers);
|
|
1577
1915
|
if (mcpEntries.length > 0) {
|
|
1578
1916
|
const mcpConfig = buildCursorMcp(features.mcpServers);
|
|
1579
|
-
const filepath =
|
|
1917
|
+
const filepath = resolve8(cursorDir, "mcp.json");
|
|
1580
1918
|
writeGeneratedJson(filepath, mcpConfig, { header: false });
|
|
1581
1919
|
filesWritten.push(filepath);
|
|
1582
1920
|
}
|
|
1583
1921
|
}
|
|
1584
1922
|
if (effective.includes("ignore")) {
|
|
1585
1923
|
if (features.ignorePatterns.length > 0) {
|
|
1586
|
-
const filepath =
|
|
1924
|
+
const filepath = resolve8(root, ".cursorignore");
|
|
1587
1925
|
const content = features.ignorePatterns.join(`
|
|
1588
1926
|
`) + `
|
|
1589
1927
|
`;
|
|
@@ -1591,6 +1929,17 @@ class CursorTarget extends BaseTarget {
|
|
|
1591
1929
|
filesWritten.push(filepath);
|
|
1592
1930
|
}
|
|
1593
1931
|
}
|
|
1932
|
+
if (effective.includes("models") && features.models) {
|
|
1933
|
+
const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID2);
|
|
1934
|
+
const guidanceContent = buildCursorModelGuidance(resolved);
|
|
1935
|
+
if (guidanceContent) {
|
|
1936
|
+
const rulesDir = resolve8(cursorDir, "rules");
|
|
1937
|
+
ensureDir(rulesDir);
|
|
1938
|
+
const filepath = join11(rulesDir, "model-config.mdc");
|
|
1939
|
+
writeGeneratedFile(filepath, guidanceContent, { header: false });
|
|
1940
|
+
filesWritten.push(filepath);
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1594
1943
|
return this.createResult(filesWritten, filesDeleted, warnings);
|
|
1595
1944
|
}
|
|
1596
1945
|
}
|
|
@@ -1609,9 +1958,135 @@ function buildCursorMcp(servers) {
|
|
|
1609
1958
|
}
|
|
1610
1959
|
return { mcpServers };
|
|
1611
1960
|
}
|
|
1961
|
+
function buildCursorModelGuidance(resolved) {
|
|
1962
|
+
if (!resolved.default && !resolved.small && Object.keys(resolved.agents).length === 0) {
|
|
1963
|
+
return null;
|
|
1964
|
+
}
|
|
1965
|
+
const frontmatter = {
|
|
1966
|
+
description: "Model configuration and selection guidelines for this workspace",
|
|
1967
|
+
alwaysApply: true
|
|
1968
|
+
};
|
|
1969
|
+
const lines = [];
|
|
1970
|
+
lines.push("# Model Configuration");
|
|
1971
|
+
lines.push("");
|
|
1972
|
+
lines.push("Use the following model preferences when working in this project.");
|
|
1973
|
+
lines.push("");
|
|
1974
|
+
if (resolved.default || resolved.small) {
|
|
1975
|
+
lines.push("## Default Models");
|
|
1976
|
+
lines.push("");
|
|
1977
|
+
if (resolved.default) {
|
|
1978
|
+
lines.push(`- **Primary model**: ${resolved.default}`);
|
|
1979
|
+
}
|
|
1980
|
+
if (resolved.small) {
|
|
1981
|
+
lines.push(`- **Lightweight tasks** (titles, summaries): ${resolved.small}`);
|
|
1982
|
+
}
|
|
1983
|
+
lines.push("");
|
|
1984
|
+
}
|
|
1985
|
+
const agentEntries = Object.entries(resolved.agents);
|
|
1986
|
+
if (agentEntries.length > 0) {
|
|
1987
|
+
lines.push("## Agent Model Assignments");
|
|
1988
|
+
lines.push("");
|
|
1989
|
+
lines.push("| Agent | Model | Temperature |");
|
|
1990
|
+
lines.push("| --- | --- | --- |");
|
|
1991
|
+
for (const [name, assignment] of agentEntries) {
|
|
1992
|
+
const temp = assignment.temperature !== undefined ? String(assignment.temperature) : "\u2014";
|
|
1993
|
+
lines.push(`| ${name} | ${assignment.model} | ${temp} |`);
|
|
1994
|
+
}
|
|
1995
|
+
lines.push("");
|
|
1996
|
+
}
|
|
1997
|
+
if (Object.keys(resolved.profiles).length > 0) {
|
|
1998
|
+
lines.push("## Available Profiles");
|
|
1999
|
+
lines.push("");
|
|
2000
|
+
lines.push("| Profile | Description | Default Model |");
|
|
2001
|
+
lines.push("| --- | --- | --- |");
|
|
2002
|
+
for (const [name, profile] of Object.entries(resolved.profiles)) {
|
|
2003
|
+
lines.push(`| ${name} | ${profile.description ?? "\u2014"} | ${profile.default ?? "\u2014"} |`);
|
|
2004
|
+
}
|
|
2005
|
+
lines.push("");
|
|
2006
|
+
}
|
|
2007
|
+
if (resolved.activeProfile) {
|
|
2008
|
+
lines.push(`**Active profile**: \`${resolved.activeProfile}\``);
|
|
2009
|
+
lines.push("");
|
|
2010
|
+
}
|
|
2011
|
+
return serializeFrontmatter(frontmatter, lines.join(`
|
|
2012
|
+
`));
|
|
2013
|
+
}
|
|
2014
|
+
|
|
2015
|
+
// src/utils/model-guidance.ts
|
|
2016
|
+
function generateModelGuidanceMarkdown(resolved) {
|
|
2017
|
+
if (!resolved.default && !resolved.small && Object.keys(resolved.agents).length === 0 && Object.keys(resolved.profiles).length === 0) {
|
|
2018
|
+
return null;
|
|
2019
|
+
}
|
|
2020
|
+
const lines = [];
|
|
2021
|
+
lines.push("# Model Configuration");
|
|
2022
|
+
lines.push("");
|
|
2023
|
+
lines.push("Use the following model preferences when working in this project.");
|
|
2024
|
+
lines.push("");
|
|
2025
|
+
if (resolved.default || resolved.small) {
|
|
2026
|
+
lines.push("## Default Models");
|
|
2027
|
+
lines.push("");
|
|
2028
|
+
if (resolved.default) {
|
|
2029
|
+
lines.push(`- **Primary model**: ${resolved.default}`);
|
|
2030
|
+
}
|
|
2031
|
+
if (resolved.small) {
|
|
2032
|
+
lines.push(`- **Lightweight tasks** (titles, summaries): ${resolved.small}`);
|
|
2033
|
+
}
|
|
2034
|
+
lines.push("");
|
|
2035
|
+
}
|
|
2036
|
+
const agentEntries = Object.entries(resolved.agents);
|
|
2037
|
+
if (agentEntries.length > 0) {
|
|
2038
|
+
lines.push("## Agent Model Assignments");
|
|
2039
|
+
lines.push("");
|
|
2040
|
+
lines.push("| Agent | Model | Temperature |");
|
|
2041
|
+
lines.push("| --- | --- | --- |");
|
|
2042
|
+
for (const [name, assignment] of agentEntries) {
|
|
2043
|
+
const temp = assignment.temperature !== undefined ? String(assignment.temperature) : "\u2014";
|
|
2044
|
+
lines.push(`| ${name} | ${assignment.model} | ${temp} |`);
|
|
2045
|
+
}
|
|
2046
|
+
lines.push("");
|
|
2047
|
+
}
|
|
2048
|
+
if (Object.keys(resolved.profiles).length > 0) {
|
|
2049
|
+
lines.push("## Available Profiles");
|
|
2050
|
+
lines.push("");
|
|
2051
|
+
lines.push("| Profile | Description | Default Model |");
|
|
2052
|
+
lines.push("| --- | --- | --- |");
|
|
2053
|
+
for (const [name, profile] of Object.entries(resolved.profiles)) {
|
|
2054
|
+
lines.push(`| ${name} | ${profile.description ?? "\u2014"} | ${profile.default ?? "\u2014"} |`);
|
|
2055
|
+
}
|
|
2056
|
+
lines.push("");
|
|
2057
|
+
}
|
|
2058
|
+
if (resolved.activeProfile) {
|
|
2059
|
+
lines.push(`**Active profile**: \`${resolved.activeProfile}\``);
|
|
2060
|
+
lines.push("");
|
|
2061
|
+
}
|
|
2062
|
+
if (resolved.routing.length > 0) {
|
|
2063
|
+
lines.push("## Task-Aware Routing");
|
|
2064
|
+
lines.push("");
|
|
2065
|
+
lines.push("Select the appropriate profile based on the task context:");
|
|
2066
|
+
lines.push("");
|
|
2067
|
+
lines.push("| Condition | Profile | Description |");
|
|
2068
|
+
lines.push("| --- | --- | --- |");
|
|
2069
|
+
for (const rule of resolved.routing) {
|
|
2070
|
+
const conditions = Object.entries(rule.when).map(([k, v]) => `${k}=${v}`).join(", ");
|
|
2071
|
+
const desc = rule.description ?? "\u2014";
|
|
2072
|
+
lines.push(`| ${conditions} | ${rule.use} | ${desc} |`);
|
|
2073
|
+
}
|
|
2074
|
+
lines.push("");
|
|
2075
|
+
lines.push("### Condition Reference");
|
|
2076
|
+
lines.push("");
|
|
2077
|
+
lines.push("- **complexity**: low | medium | high | critical");
|
|
2078
|
+
lines.push("- **urgency**: low | normal | high");
|
|
2079
|
+
lines.push("- **budget**: minimal | standard | premium");
|
|
2080
|
+
lines.push("- **contextWindowNeed**: small | medium | large | max");
|
|
2081
|
+
lines.push("- **toolUseIntensity**: none | light | heavy");
|
|
2082
|
+
lines.push("");
|
|
2083
|
+
}
|
|
2084
|
+
return lines.join(`
|
|
2085
|
+
`);
|
|
2086
|
+
}
|
|
1612
2087
|
|
|
1613
2088
|
// src/targets/claude-code.ts
|
|
1614
|
-
import { resolve as
|
|
2089
|
+
import { resolve as resolve9, join as join12 } from "path";
|
|
1615
2090
|
var TARGET_ID3 = "claudecode";
|
|
1616
2091
|
|
|
1617
2092
|
class ClaudeCodeTarget extends BaseTarget {
|
|
@@ -1624,18 +2099,19 @@ class ClaudeCodeTarget extends BaseTarget {
|
|
|
1624
2099
|
"skills",
|
|
1625
2100
|
"hooks",
|
|
1626
2101
|
"mcp",
|
|
1627
|
-
"ignore"
|
|
2102
|
+
"ignore",
|
|
2103
|
+
"models"
|
|
1628
2104
|
];
|
|
1629
2105
|
generate(options) {
|
|
1630
2106
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
1631
|
-
const root =
|
|
2107
|
+
const root = resolve9(projectRoot, baseDir);
|
|
1632
2108
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
1633
2109
|
const filesWritten = [];
|
|
1634
2110
|
const filesDeleted = [];
|
|
1635
2111
|
const warnings = [];
|
|
1636
|
-
const claudeDir =
|
|
2112
|
+
const claudeDir = resolve9(root, ".claude");
|
|
1637
2113
|
if (effective.includes("rules")) {
|
|
1638
|
-
const rulesDir =
|
|
2114
|
+
const rulesDir = resolve9(claudeDir, "rules");
|
|
1639
2115
|
if (deleteExisting) {
|
|
1640
2116
|
removeIfExists(rulesDir);
|
|
1641
2117
|
filesDeleted.push(rulesDir);
|
|
@@ -1648,32 +2124,41 @@ class ClaudeCodeTarget extends BaseTarget {
|
|
|
1648
2124
|
const claudeMd = rootRules.map((r) => r.content).join(`
|
|
1649
2125
|
|
|
1650
2126
|
`);
|
|
1651
|
-
const filepath =
|
|
2127
|
+
const filepath = resolve9(claudeDir, "CLAUDE.md");
|
|
1652
2128
|
writeGeneratedFile(filepath, claudeMd);
|
|
1653
2129
|
filesWritten.push(filepath);
|
|
1654
2130
|
}
|
|
1655
2131
|
for (const rule of detailRules) {
|
|
1656
|
-
const filepath =
|
|
2132
|
+
const filepath = join12(rulesDir, `${rule.name}.md`);
|
|
1657
2133
|
writeGeneratedFile(filepath, rule.content);
|
|
1658
2134
|
filesWritten.push(filepath);
|
|
1659
2135
|
}
|
|
1660
2136
|
}
|
|
1661
2137
|
if (effective.includes("agents")) {
|
|
1662
|
-
const agentsDir =
|
|
2138
|
+
const agentsDir = resolve9(claudeDir, "agents");
|
|
1663
2139
|
if (deleteExisting) {
|
|
1664
2140
|
removeIfExists(agentsDir);
|
|
1665
2141
|
filesDeleted.push(agentsDir);
|
|
1666
2142
|
}
|
|
1667
2143
|
ensureDir(agentsDir);
|
|
2144
|
+
const resolvedModels = features.models ? resolveModels(features.models, options.modelProfile, TARGET_ID3) : null;
|
|
1668
2145
|
const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID3));
|
|
1669
2146
|
for (const agent of agents) {
|
|
1670
|
-
const filepath =
|
|
1671
|
-
|
|
2147
|
+
const filepath = join12(agentsDir, `${agent.name}.md`);
|
|
2148
|
+
const cc = agent.meta.claudecode ?? {};
|
|
2149
|
+
const modelsAgent = resolvedModels?.agents[agent.name];
|
|
2150
|
+
const agentModel = modelsAgent?.model ?? cc.model;
|
|
2151
|
+
let content = agent.content;
|
|
2152
|
+
if (agentModel) {
|
|
2153
|
+
content = `<!-- model: ${agentModel} -->
|
|
2154
|
+
${content}`;
|
|
2155
|
+
}
|
|
2156
|
+
writeGeneratedFile(filepath, content);
|
|
1672
2157
|
filesWritten.push(filepath);
|
|
1673
2158
|
}
|
|
1674
2159
|
}
|
|
1675
2160
|
if (effective.includes("skills")) {
|
|
1676
|
-
const skillsDir =
|
|
2161
|
+
const skillsDir = resolve9(claudeDir, "skills");
|
|
1677
2162
|
if (deleteExisting) {
|
|
1678
2163
|
removeIfExists(skillsDir);
|
|
1679
2164
|
filesDeleted.push(skillsDir);
|
|
@@ -1681,15 +2166,15 @@ class ClaudeCodeTarget extends BaseTarget {
|
|
|
1681
2166
|
ensureDir(skillsDir);
|
|
1682
2167
|
const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID3));
|
|
1683
2168
|
for (const skill of skills) {
|
|
1684
|
-
const skillSubDir =
|
|
2169
|
+
const skillSubDir = join12(skillsDir, skill.name);
|
|
1685
2170
|
ensureDir(skillSubDir);
|
|
1686
|
-
const filepath =
|
|
2171
|
+
const filepath = join12(skillSubDir, "SKILL.md");
|
|
1687
2172
|
writeGeneratedFile(filepath, skill.content);
|
|
1688
2173
|
filesWritten.push(filepath);
|
|
1689
2174
|
}
|
|
1690
2175
|
}
|
|
1691
2176
|
if (effective.includes("commands")) {
|
|
1692
|
-
const commandsDir =
|
|
2177
|
+
const commandsDir = resolve9(claudeDir, "commands");
|
|
1693
2178
|
if (deleteExisting) {
|
|
1694
2179
|
removeIfExists(commandsDir);
|
|
1695
2180
|
filesDeleted.push(commandsDir);
|
|
@@ -1697,15 +2182,26 @@ class ClaudeCodeTarget extends BaseTarget {
|
|
|
1697
2182
|
ensureDir(commandsDir);
|
|
1698
2183
|
const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID3));
|
|
1699
2184
|
for (const cmd of commands) {
|
|
1700
|
-
const filepath =
|
|
2185
|
+
const filepath = join12(commandsDir, `${cmd.name}.md`);
|
|
1701
2186
|
writeGeneratedFile(filepath, cmd.content);
|
|
1702
2187
|
filesWritten.push(filepath);
|
|
1703
2188
|
}
|
|
1704
2189
|
}
|
|
2190
|
+
if (effective.includes("models") && features.models) {
|
|
2191
|
+
const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID3);
|
|
2192
|
+
const guidance = generateModelGuidanceMarkdown(resolved);
|
|
2193
|
+
if (guidance) {
|
|
2194
|
+
const rulesDir = resolve9(claudeDir, "rules");
|
|
2195
|
+
ensureDir(rulesDir);
|
|
2196
|
+
const filepath = join12(rulesDir, "model-config.md");
|
|
2197
|
+
writeGeneratedFile(filepath, guidance);
|
|
2198
|
+
filesWritten.push(filepath);
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
1705
2201
|
if (effective.includes("hooks") || effective.includes("mcp") || effective.includes("ignore")) {
|
|
1706
2202
|
const settings = buildClaudeSettings(options, effective);
|
|
1707
2203
|
if (Object.keys(settings).length > 0) {
|
|
1708
|
-
const filepath =
|
|
2204
|
+
const filepath = resolve9(claudeDir, "settings.json");
|
|
1709
2205
|
const existing = readJsonOrNull(filepath) ?? {};
|
|
1710
2206
|
const merged = { ...existing, ...settings };
|
|
1711
2207
|
writeGeneratedJson(filepath, merged, { header: false });
|
|
@@ -1762,7 +2258,7 @@ function toPascalCase(str) {
|
|
|
1762
2258
|
}
|
|
1763
2259
|
|
|
1764
2260
|
// src/targets/codex-cli.ts
|
|
1765
|
-
import { resolve as
|
|
2261
|
+
import { resolve as resolve10, join as join13 } from "path";
|
|
1766
2262
|
var TARGET_ID4 = "codexcli";
|
|
1767
2263
|
|
|
1768
2264
|
class CodexCliTarget extends BaseTarget {
|
|
@@ -1771,14 +2267,14 @@ class CodexCliTarget extends BaseTarget {
|
|
|
1771
2267
|
supportedFeatures = ["rules", "skills", "mcp", "hooks"];
|
|
1772
2268
|
generate(options) {
|
|
1773
2269
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
1774
|
-
const root =
|
|
2270
|
+
const root = resolve10(projectRoot, baseDir);
|
|
1775
2271
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
1776
2272
|
const filesWritten = [];
|
|
1777
2273
|
const filesDeleted = [];
|
|
1778
2274
|
const warnings = [];
|
|
1779
|
-
const codexDir =
|
|
2275
|
+
const codexDir = resolve10(root, ".codex");
|
|
1780
2276
|
if (effective.includes("rules")) {
|
|
1781
|
-
const memoriesDir =
|
|
2277
|
+
const memoriesDir = resolve10(codexDir, "memories");
|
|
1782
2278
|
if (deleteExisting) {
|
|
1783
2279
|
removeIfExists(memoriesDir);
|
|
1784
2280
|
filesDeleted.push(memoriesDir);
|
|
@@ -1786,13 +2282,13 @@ class CodexCliTarget extends BaseTarget {
|
|
|
1786
2282
|
ensureDir(memoriesDir);
|
|
1787
2283
|
const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID4));
|
|
1788
2284
|
for (const rule of rules) {
|
|
1789
|
-
const filepath =
|
|
2285
|
+
const filepath = join13(memoriesDir, `${rule.name}.md`);
|
|
1790
2286
|
writeGeneratedFile(filepath, rule.content);
|
|
1791
2287
|
filesWritten.push(filepath);
|
|
1792
2288
|
}
|
|
1793
2289
|
}
|
|
1794
2290
|
if (effective.includes("skills")) {
|
|
1795
|
-
const skillsDir =
|
|
2291
|
+
const skillsDir = resolve10(codexDir, "skills");
|
|
1796
2292
|
if (deleteExisting) {
|
|
1797
2293
|
removeIfExists(skillsDir);
|
|
1798
2294
|
filesDeleted.push(skillsDir);
|
|
@@ -1800,9 +2296,9 @@ class CodexCliTarget extends BaseTarget {
|
|
|
1800
2296
|
ensureDir(skillsDir);
|
|
1801
2297
|
const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID4));
|
|
1802
2298
|
for (const skill of skills) {
|
|
1803
|
-
const skillSubDir =
|
|
2299
|
+
const skillSubDir = join13(skillsDir, skill.name);
|
|
1804
2300
|
ensureDir(skillSubDir);
|
|
1805
|
-
const filepath =
|
|
2301
|
+
const filepath = join13(skillSubDir, "SKILL.md");
|
|
1806
2302
|
writeGeneratedFile(filepath, skill.content);
|
|
1807
2303
|
filesWritten.push(filepath);
|
|
1808
2304
|
}
|
|
@@ -1812,7 +2308,7 @@ class CodexCliTarget extends BaseTarget {
|
|
|
1812
2308
|
}
|
|
1813
2309
|
|
|
1814
2310
|
// src/targets/gemini-cli.ts
|
|
1815
|
-
import { resolve as
|
|
2311
|
+
import { resolve as resolve11, join as join14 } from "path";
|
|
1816
2312
|
var TARGET_ID5 = "geminicli";
|
|
1817
2313
|
|
|
1818
2314
|
class GeminiCliTarget extends BaseTarget {
|
|
@@ -1828,12 +2324,12 @@ class GeminiCliTarget extends BaseTarget {
|
|
|
1828
2324
|
];
|
|
1829
2325
|
generate(options) {
|
|
1830
2326
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
1831
|
-
const root =
|
|
2327
|
+
const root = resolve11(projectRoot, baseDir);
|
|
1832
2328
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
1833
2329
|
const filesWritten = [];
|
|
1834
2330
|
const filesDeleted = [];
|
|
1835
2331
|
const warnings = [];
|
|
1836
|
-
const geminiDir =
|
|
2332
|
+
const geminiDir = resolve11(root, ".gemini");
|
|
1837
2333
|
if (effective.includes("rules")) {
|
|
1838
2334
|
const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID5));
|
|
1839
2335
|
const rootRules = getRootRules(rules);
|
|
@@ -1842,26 +2338,26 @@ class GeminiCliTarget extends BaseTarget {
|
|
|
1842
2338
|
const geminiMd = rootRules.map((r) => r.content).join(`
|
|
1843
2339
|
|
|
1844
2340
|
`);
|
|
1845
|
-
const filepath =
|
|
2341
|
+
const filepath = resolve11(root, "GEMINI.md");
|
|
1846
2342
|
writeGeneratedFile(filepath, geminiMd);
|
|
1847
2343
|
filesWritten.push(filepath);
|
|
1848
2344
|
}
|
|
1849
2345
|
if (detailRules.length > 0) {
|
|
1850
|
-
const memoriesDir =
|
|
2346
|
+
const memoriesDir = resolve11(geminiDir, "memories");
|
|
1851
2347
|
if (deleteExisting) {
|
|
1852
2348
|
removeIfExists(memoriesDir);
|
|
1853
2349
|
filesDeleted.push(memoriesDir);
|
|
1854
2350
|
}
|
|
1855
2351
|
ensureDir(memoriesDir);
|
|
1856
2352
|
for (const rule of detailRules) {
|
|
1857
|
-
const filepath =
|
|
2353
|
+
const filepath = join14(memoriesDir, `${rule.name}.md`);
|
|
1858
2354
|
writeGeneratedFile(filepath, rule.content);
|
|
1859
2355
|
filesWritten.push(filepath);
|
|
1860
2356
|
}
|
|
1861
2357
|
}
|
|
1862
2358
|
}
|
|
1863
2359
|
if (effective.includes("commands")) {
|
|
1864
|
-
const commandsDir =
|
|
2360
|
+
const commandsDir = resolve11(geminiDir, "commands");
|
|
1865
2361
|
if (deleteExisting) {
|
|
1866
2362
|
removeIfExists(commandsDir);
|
|
1867
2363
|
filesDeleted.push(commandsDir);
|
|
@@ -1870,7 +2366,7 @@ class GeminiCliTarget extends BaseTarget {
|
|
|
1870
2366
|
const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID5));
|
|
1871
2367
|
for (const cmd of commands) {
|
|
1872
2368
|
const toml = buildGeminiCommand(cmd.name, cmd.meta.description ?? "", cmd.content);
|
|
1873
|
-
const filepath =
|
|
2369
|
+
const filepath = join14(commandsDir, `${cmd.name}.toml`);
|
|
1874
2370
|
writeGeneratedFile(filepath, toml, { type: "md" });
|
|
1875
2371
|
filesWritten.push(filepath);
|
|
1876
2372
|
}
|
|
@@ -1879,14 +2375,14 @@ class GeminiCliTarget extends BaseTarget {
|
|
|
1879
2375
|
const mcpEntries = Object.entries(features.mcpServers);
|
|
1880
2376
|
if (mcpEntries.length > 0) {
|
|
1881
2377
|
const settings = buildGeminiSettings(features.mcpServers);
|
|
1882
|
-
const filepath =
|
|
2378
|
+
const filepath = resolve11(geminiDir, "settings.json");
|
|
1883
2379
|
writeGeneratedJson(filepath, settings, { header: false });
|
|
1884
2380
|
filesWritten.push(filepath);
|
|
1885
2381
|
}
|
|
1886
2382
|
}
|
|
1887
2383
|
if (effective.includes("ignore")) {
|
|
1888
2384
|
if (features.ignorePatterns.length > 0) {
|
|
1889
|
-
const filepath =
|
|
2385
|
+
const filepath = resolve11(root, ".geminiignore");
|
|
1890
2386
|
const content = features.ignorePatterns.join(`
|
|
1891
2387
|
`) + `
|
|
1892
2388
|
`;
|
|
@@ -1925,7 +2421,7 @@ function buildGeminiSettings(servers) {
|
|
|
1925
2421
|
}
|
|
1926
2422
|
|
|
1927
2423
|
// src/targets/copilot.ts
|
|
1928
|
-
import { resolve as
|
|
2424
|
+
import { resolve as resolve12, join as join15 } from "path";
|
|
1929
2425
|
var TARGET_ID6 = "copilot";
|
|
1930
2426
|
|
|
1931
2427
|
class CopilotTarget extends BaseTarget {
|
|
@@ -1937,16 +2433,17 @@ class CopilotTarget extends BaseTarget {
|
|
|
1937
2433
|
"agents",
|
|
1938
2434
|
"skills",
|
|
1939
2435
|
"mcp",
|
|
1940
|
-
"ignore"
|
|
2436
|
+
"ignore",
|
|
2437
|
+
"models"
|
|
1941
2438
|
];
|
|
1942
2439
|
generate(options) {
|
|
1943
2440
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
1944
|
-
const root =
|
|
2441
|
+
const root = resolve12(projectRoot, baseDir);
|
|
1945
2442
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
1946
2443
|
const filesWritten = [];
|
|
1947
2444
|
const filesDeleted = [];
|
|
1948
2445
|
const warnings = [];
|
|
1949
|
-
const githubDir =
|
|
2446
|
+
const githubDir = resolve12(root, ".github");
|
|
1950
2447
|
if (effective.includes("rules")) {
|
|
1951
2448
|
const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID6));
|
|
1952
2449
|
if (rules.length > 0) {
|
|
@@ -1955,15 +2452,15 @@ class CopilotTarget extends BaseTarget {
|
|
|
1955
2452
|
---
|
|
1956
2453
|
|
|
1957
2454
|
`);
|
|
1958
|
-
const filepath =
|
|
2455
|
+
const filepath = resolve12(githubDir, "copilot-instructions.md");
|
|
1959
2456
|
ensureDir(githubDir);
|
|
1960
2457
|
writeGeneratedFile(filepath, combinedContent);
|
|
1961
2458
|
filesWritten.push(filepath);
|
|
1962
2459
|
}
|
|
1963
2460
|
}
|
|
1964
2461
|
if (effective.includes("agents")) {
|
|
1965
|
-
const copilotDir =
|
|
1966
|
-
const agentsDir =
|
|
2462
|
+
const copilotDir = resolve12(githubDir, "copilot");
|
|
2463
|
+
const agentsDir = resolve12(copilotDir, "agents");
|
|
1967
2464
|
if (deleteExisting) {
|
|
1968
2465
|
removeIfExists(agentsDir);
|
|
1969
2466
|
filesDeleted.push(agentsDir);
|
|
@@ -1971,14 +2468,14 @@ class CopilotTarget extends BaseTarget {
|
|
|
1971
2468
|
ensureDir(agentsDir);
|
|
1972
2469
|
const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID6));
|
|
1973
2470
|
for (const agent of agents) {
|
|
1974
|
-
const filepath =
|
|
2471
|
+
const filepath = join15(agentsDir, `${agent.name}.md`);
|
|
1975
2472
|
writeGeneratedFile(filepath, agent.content);
|
|
1976
2473
|
filesWritten.push(filepath);
|
|
1977
2474
|
}
|
|
1978
2475
|
}
|
|
1979
2476
|
if (effective.includes("skills")) {
|
|
1980
|
-
const copilotDir =
|
|
1981
|
-
const skillsDir =
|
|
2477
|
+
const copilotDir = resolve12(githubDir, "copilot");
|
|
2478
|
+
const skillsDir = resolve12(copilotDir, "skills");
|
|
1982
2479
|
if (deleteExisting) {
|
|
1983
2480
|
removeIfExists(skillsDir);
|
|
1984
2481
|
filesDeleted.push(skillsDir);
|
|
@@ -1986,16 +2483,16 @@ class CopilotTarget extends BaseTarget {
|
|
|
1986
2483
|
ensureDir(skillsDir);
|
|
1987
2484
|
const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID6));
|
|
1988
2485
|
for (const skill of skills) {
|
|
1989
|
-
const skillSubDir =
|
|
2486
|
+
const skillSubDir = join15(skillsDir, skill.name);
|
|
1990
2487
|
ensureDir(skillSubDir);
|
|
1991
|
-
const filepath =
|
|
2488
|
+
const filepath = join15(skillSubDir, "SKILL.md");
|
|
1992
2489
|
writeGeneratedFile(filepath, skill.content);
|
|
1993
2490
|
filesWritten.push(filepath);
|
|
1994
2491
|
}
|
|
1995
2492
|
}
|
|
1996
2493
|
if (effective.includes("commands")) {
|
|
1997
|
-
const copilotDir =
|
|
1998
|
-
const commandsDir =
|
|
2494
|
+
const copilotDir = resolve12(githubDir, "copilot");
|
|
2495
|
+
const commandsDir = resolve12(copilotDir, "commands");
|
|
1999
2496
|
if (deleteExisting) {
|
|
2000
2497
|
removeIfExists(commandsDir);
|
|
2001
2498
|
filesDeleted.push(commandsDir);
|
|
@@ -2003,25 +2500,36 @@ class CopilotTarget extends BaseTarget {
|
|
|
2003
2500
|
ensureDir(commandsDir);
|
|
2004
2501
|
const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID6));
|
|
2005
2502
|
for (const cmd of commands) {
|
|
2006
|
-
const filepath =
|
|
2503
|
+
const filepath = join15(commandsDir, `${cmd.name}.md`);
|
|
2007
2504
|
writeGeneratedFile(filepath, cmd.content);
|
|
2008
2505
|
filesWritten.push(filepath);
|
|
2009
2506
|
}
|
|
2010
2507
|
}
|
|
2011
2508
|
if (effective.includes("ignore")) {}
|
|
2509
|
+
if (effective.includes("models") && features.models) {
|
|
2510
|
+
const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID6);
|
|
2511
|
+
const guidance = generateModelGuidanceMarkdown(resolved);
|
|
2512
|
+
if (guidance) {
|
|
2513
|
+
const copilotDir = resolve12(githubDir, "copilot");
|
|
2514
|
+
ensureDir(copilotDir);
|
|
2515
|
+
const filepath = join15(copilotDir, "model-config.md");
|
|
2516
|
+
writeGeneratedFile(filepath, guidance);
|
|
2517
|
+
filesWritten.push(filepath);
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2012
2520
|
return this.createResult(filesWritten, filesDeleted, warnings);
|
|
2013
2521
|
}
|
|
2014
2522
|
}
|
|
2015
2523
|
|
|
2016
2524
|
// src/targets/agents-md.ts
|
|
2017
|
-
import { resolve as
|
|
2525
|
+
import { resolve as resolve13 } from "path";
|
|
2018
2526
|
class AgentsMdTarget extends BaseTarget {
|
|
2019
2527
|
id = "agentsmd";
|
|
2020
2528
|
name = "AGENTS.md";
|
|
2021
2529
|
supportedFeatures = ["rules"];
|
|
2022
2530
|
generate(options) {
|
|
2023
2531
|
const { projectRoot, baseDir, features } = options;
|
|
2024
|
-
const root =
|
|
2532
|
+
const root = resolve13(projectRoot, baseDir);
|
|
2025
2533
|
const filesWritten = [];
|
|
2026
2534
|
const warnings = [];
|
|
2027
2535
|
const rootRules = getRootRules(features.rules);
|
|
@@ -2033,7 +2541,7 @@ class AgentsMdTarget extends BaseTarget {
|
|
|
2033
2541
|
const content = sections.join(`
|
|
2034
2542
|
|
|
2035
2543
|
`);
|
|
2036
|
-
const filepath =
|
|
2544
|
+
const filepath = resolve13(root, "AGENTS.md");
|
|
2037
2545
|
writeGeneratedFile(filepath, content);
|
|
2038
2546
|
filesWritten.push(filepath);
|
|
2039
2547
|
return this.createResult(filesWritten, [], warnings);
|
|
@@ -2041,7 +2549,7 @@ class AgentsMdTarget extends BaseTarget {
|
|
|
2041
2549
|
}
|
|
2042
2550
|
|
|
2043
2551
|
// src/targets/generic-md-target.ts
|
|
2044
|
-
import { resolve as
|
|
2552
|
+
import { resolve as resolve14, join as join16 } from "path";
|
|
2045
2553
|
function createGenericMdTarget(config) {
|
|
2046
2554
|
return new GenericMdTarget(config);
|
|
2047
2555
|
}
|
|
@@ -2060,16 +2568,16 @@ class GenericMdTarget extends BaseTarget {
|
|
|
2060
2568
|
}
|
|
2061
2569
|
generate(options) {
|
|
2062
2570
|
const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
|
|
2063
|
-
const root =
|
|
2571
|
+
const root = resolve14(projectRoot, baseDir);
|
|
2064
2572
|
const effective = this.getEffectiveFeatures(enabledFeatures);
|
|
2065
2573
|
const filesWritten = [];
|
|
2066
2574
|
const filesDeleted = [];
|
|
2067
2575
|
const warnings = [];
|
|
2068
|
-
const configDir =
|
|
2576
|
+
const configDir = resolve14(root, this.config.configDir);
|
|
2069
2577
|
const rulesSubDir = this.config.rulesDir ?? "rules";
|
|
2070
2578
|
const ext = this.config.ruleExtension ?? ".md";
|
|
2071
2579
|
if (effective.includes("rules")) {
|
|
2072
|
-
const rulesDir =
|
|
2580
|
+
const rulesDir = resolve14(configDir, rulesSubDir);
|
|
2073
2581
|
if (deleteExisting) {
|
|
2074
2582
|
removeIfExists(rulesDir);
|
|
2075
2583
|
filesDeleted.push(rulesDir);
|
|
@@ -2077,13 +2585,13 @@ class GenericMdTarget extends BaseTarget {
|
|
|
2077
2585
|
ensureDir(rulesDir);
|
|
2078
2586
|
const rules = features.rules.filter((r) => ruleMatchesTarget(r, this.id));
|
|
2079
2587
|
for (const rule of rules) {
|
|
2080
|
-
const filepath =
|
|
2588
|
+
const filepath = join16(rulesDir, `${rule.name}${ext}`);
|
|
2081
2589
|
writeGeneratedFile(filepath, rule.content);
|
|
2082
2590
|
filesWritten.push(filepath);
|
|
2083
2591
|
}
|
|
2084
2592
|
}
|
|
2085
2593
|
if (effective.includes("commands")) {
|
|
2086
|
-
const commandsDir =
|
|
2594
|
+
const commandsDir = resolve14(configDir, "commands");
|
|
2087
2595
|
if (deleteExisting) {
|
|
2088
2596
|
removeIfExists(commandsDir);
|
|
2089
2597
|
filesDeleted.push(commandsDir);
|
|
@@ -2091,7 +2599,7 @@ class GenericMdTarget extends BaseTarget {
|
|
|
2091
2599
|
ensureDir(commandsDir);
|
|
2092
2600
|
const commands = features.commands.filter((c) => commandMatchesTarget(c, this.id));
|
|
2093
2601
|
for (const cmd of commands) {
|
|
2094
|
-
const filepath =
|
|
2602
|
+
const filepath = join16(commandsDir, `${cmd.name}.md`);
|
|
2095
2603
|
writeGeneratedFile(filepath, cmd.content);
|
|
2096
2604
|
filesWritten.push(filepath);
|
|
2097
2605
|
}
|
|
@@ -2100,7 +2608,7 @@ class GenericMdTarget extends BaseTarget {
|
|
|
2100
2608
|
const mcpEntries = Object.entries(features.mcpServers);
|
|
2101
2609
|
if (mcpEntries.length > 0) {
|
|
2102
2610
|
const mcpDir = this.config.mcpInConfigDir ? configDir : root;
|
|
2103
|
-
const filepath =
|
|
2611
|
+
const filepath = resolve14(mcpDir, "mcp.json");
|
|
2104
2612
|
writeGeneratedJson(filepath, { mcpServers: features.mcpServers }, {
|
|
2105
2613
|
header: false
|
|
2106
2614
|
});
|
|
@@ -2109,13 +2617,23 @@ class GenericMdTarget extends BaseTarget {
|
|
|
2109
2617
|
}
|
|
2110
2618
|
if (effective.includes("ignore") && this.config.ignoreFile) {
|
|
2111
2619
|
if (features.ignorePatterns.length > 0) {
|
|
2112
|
-
const filepath =
|
|
2620
|
+
const filepath = resolve14(root, this.config.ignoreFile);
|
|
2113
2621
|
writeGeneratedFile(filepath, features.ignorePatterns.join(`
|
|
2114
2622
|
`) + `
|
|
2115
2623
|
`);
|
|
2116
2624
|
filesWritten.push(filepath);
|
|
2117
2625
|
}
|
|
2118
2626
|
}
|
|
2627
|
+
if (effective.includes("models") && features.models) {
|
|
2628
|
+
const resolved = resolveModels(features.models, options.modelProfile, this.id);
|
|
2629
|
+
const guidance = generateModelGuidanceMarkdown(resolved);
|
|
2630
|
+
if (guidance) {
|
|
2631
|
+
ensureDir(configDir);
|
|
2632
|
+
const filepath = join16(configDir, "model-config.md");
|
|
2633
|
+
writeGeneratedFile(filepath, guidance);
|
|
2634
|
+
filesWritten.push(filepath);
|
|
2635
|
+
}
|
|
2636
|
+
}
|
|
2119
2637
|
return this.createResult(filesWritten, filesDeleted, warnings);
|
|
2120
2638
|
}
|
|
2121
2639
|
}
|
|
@@ -2255,11 +2773,11 @@ function listTargetIds() {
|
|
|
2255
2773
|
}
|
|
2256
2774
|
|
|
2257
2775
|
// src/exporters/cursor-plugin.ts
|
|
2258
|
-
import { resolve as
|
|
2259
|
-
import { mkdirSync as mkdirSync4, writeFileSync as
|
|
2776
|
+
import { resolve as resolve15, join as join17 } from "path";
|
|
2777
|
+
import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
2260
2778
|
function exportCursorPlugin(pack, outputDir) {
|
|
2261
2779
|
const filesWritten = [];
|
|
2262
|
-
const pluginDir =
|
|
2780
|
+
const pluginDir = resolve15(outputDir, pack.manifest.name);
|
|
2263
2781
|
mkdirSync4(pluginDir, { recursive: true });
|
|
2264
2782
|
const manifest = {
|
|
2265
2783
|
name: pack.manifest.name,
|
|
@@ -2273,7 +2791,7 @@ function exportCursorPlugin(pack, outputDir) {
|
|
|
2273
2791
|
manifest.tags = pack.manifest.tags;
|
|
2274
2792
|
}
|
|
2275
2793
|
if (pack.rules.length > 0) {
|
|
2276
|
-
const rulesDir =
|
|
2794
|
+
const rulesDir = join17(pluginDir, "rules");
|
|
2277
2795
|
ensureDir(rulesDir);
|
|
2278
2796
|
manifest.rules = [];
|
|
2279
2797
|
for (const rule of pack.rules) {
|
|
@@ -2286,14 +2804,14 @@ function exportCursorPlugin(pack, outputDir) {
|
|
|
2286
2804
|
if (globs)
|
|
2287
2805
|
fm.globs = globs;
|
|
2288
2806
|
const filename = `${rule.name}.mdc`;
|
|
2289
|
-
const filepath =
|
|
2290
|
-
|
|
2807
|
+
const filepath = join17(rulesDir, filename);
|
|
2808
|
+
writeFileSync4(filepath, serializeFrontmatter(fm, rule.content));
|
|
2291
2809
|
filesWritten.push(filepath);
|
|
2292
2810
|
manifest.rules.push(filename);
|
|
2293
2811
|
}
|
|
2294
2812
|
}
|
|
2295
2813
|
if (pack.agents.length > 0) {
|
|
2296
|
-
const agentsDir =
|
|
2814
|
+
const agentsDir = join17(pluginDir, "agents");
|
|
2297
2815
|
ensureDir(agentsDir);
|
|
2298
2816
|
manifest.agents = [];
|
|
2299
2817
|
for (const agent of pack.agents) {
|
|
@@ -2302,61 +2820,61 @@ function exportCursorPlugin(pack, outputDir) {
|
|
|
2302
2820
|
description: agent.meta.description ?? ""
|
|
2303
2821
|
};
|
|
2304
2822
|
const filename = `${agent.name}.md`;
|
|
2305
|
-
const filepath =
|
|
2306
|
-
|
|
2823
|
+
const filepath = join17(agentsDir, filename);
|
|
2824
|
+
writeFileSync4(filepath, serializeFrontmatter(fm, agent.content));
|
|
2307
2825
|
filesWritten.push(filepath);
|
|
2308
2826
|
manifest.agents.push(filename);
|
|
2309
2827
|
}
|
|
2310
2828
|
}
|
|
2311
2829
|
if (pack.skills.length > 0) {
|
|
2312
|
-
const skillsDir =
|
|
2830
|
+
const skillsDir = join17(pluginDir, "skills");
|
|
2313
2831
|
ensureDir(skillsDir);
|
|
2314
2832
|
manifest.skills = [];
|
|
2315
2833
|
for (const skill of pack.skills) {
|
|
2316
|
-
const skillSubDir =
|
|
2834
|
+
const skillSubDir = join17(skillsDir, skill.name);
|
|
2317
2835
|
ensureDir(skillSubDir);
|
|
2318
2836
|
const fm = {
|
|
2319
2837
|
name: skill.name,
|
|
2320
2838
|
description: skill.meta.description ?? ""
|
|
2321
2839
|
};
|
|
2322
|
-
const filepath =
|
|
2323
|
-
|
|
2840
|
+
const filepath = join17(skillSubDir, "SKILL.md");
|
|
2841
|
+
writeFileSync4(filepath, serializeFrontmatter(fm, skill.content));
|
|
2324
2842
|
filesWritten.push(filepath);
|
|
2325
2843
|
manifest.skills.push(skill.name);
|
|
2326
2844
|
}
|
|
2327
2845
|
}
|
|
2328
2846
|
if (pack.commands.length > 0) {
|
|
2329
|
-
const commandsDir =
|
|
2847
|
+
const commandsDir = join17(pluginDir, "commands");
|
|
2330
2848
|
ensureDir(commandsDir);
|
|
2331
2849
|
manifest.commands = [];
|
|
2332
2850
|
for (const cmd of pack.commands) {
|
|
2333
2851
|
const filename = `${cmd.name}.md`;
|
|
2334
|
-
const filepath =
|
|
2335
|
-
|
|
2852
|
+
const filepath = join17(commandsDir, filename);
|
|
2853
|
+
writeFileSync4(filepath, cmd.content);
|
|
2336
2854
|
filesWritten.push(filepath);
|
|
2337
2855
|
manifest.commands.push(filename);
|
|
2338
2856
|
}
|
|
2339
2857
|
}
|
|
2340
2858
|
if (pack.mcp && Object.keys(pack.mcp.servers).length > 0) {
|
|
2341
2859
|
manifest.mcp = true;
|
|
2342
|
-
const filepath =
|
|
2343
|
-
|
|
2860
|
+
const filepath = join17(pluginDir, "mcp.json");
|
|
2861
|
+
writeFileSync4(filepath, JSON.stringify({ mcpServers: pack.mcp.servers }, null, 2) + `
|
|
2344
2862
|
`);
|
|
2345
2863
|
filesWritten.push(filepath);
|
|
2346
2864
|
}
|
|
2347
|
-
const manifestPath =
|
|
2348
|
-
|
|
2865
|
+
const manifestPath = join17(pluginDir, "manifest.json");
|
|
2866
|
+
writeFileSync4(manifestPath, JSON.stringify(manifest, null, 2) + `
|
|
2349
2867
|
`);
|
|
2350
2868
|
filesWritten.push(manifestPath);
|
|
2351
2869
|
return { outputDir: pluginDir, filesWritten, manifest };
|
|
2352
2870
|
}
|
|
2353
2871
|
|
|
2354
2872
|
// src/importers/rulesync.ts
|
|
2355
|
-
import { existsSync as existsSync10, readFileSync as readFileSync10, copyFileSync, writeFileSync as
|
|
2356
|
-
import { resolve as
|
|
2873
|
+
import { existsSync as existsSync10, readFileSync as readFileSync10, copyFileSync, writeFileSync as writeFileSync5 } from "fs";
|
|
2874
|
+
import { resolve as resolve16, join as join18, basename as basename6 } from "path";
|
|
2357
2875
|
import { parse as parseJsonc2 } from "jsonc-parser";
|
|
2358
2876
|
function importFromRulesync(projectRoot, outputPackDir) {
|
|
2359
|
-
const rulesyncDir =
|
|
2877
|
+
const rulesyncDir = resolve16(projectRoot, ".rulesync");
|
|
2360
2878
|
const warnings = [];
|
|
2361
2879
|
const filesImported = [];
|
|
2362
2880
|
if (!existsSync10(rulesyncDir)) {
|
|
@@ -2367,79 +2885,79 @@ function importFromRulesync(projectRoot, outputPackDir) {
|
|
|
2367
2885
|
configGenerated: false
|
|
2368
2886
|
};
|
|
2369
2887
|
}
|
|
2370
|
-
const packDir = outputPackDir ??
|
|
2888
|
+
const packDir = outputPackDir ?? resolve16(projectRoot, "packs", "default");
|
|
2371
2889
|
ensureDir(packDir);
|
|
2372
|
-
const rulesDir =
|
|
2890
|
+
const rulesDir = resolve16(rulesyncDir, "rules");
|
|
2373
2891
|
if (existsSync10(rulesDir)) {
|
|
2374
|
-
const outRulesDir =
|
|
2892
|
+
const outRulesDir = resolve16(packDir, "rules");
|
|
2375
2893
|
ensureDir(outRulesDir);
|
|
2376
2894
|
const files = listFiles(rulesDir, { extension: ".md" });
|
|
2377
2895
|
for (const file of files) {
|
|
2378
|
-
const dest =
|
|
2896
|
+
const dest = join18(outRulesDir, basename6(file));
|
|
2379
2897
|
copyFileSync(file, dest);
|
|
2380
2898
|
filesImported.push(dest);
|
|
2381
2899
|
}
|
|
2382
2900
|
}
|
|
2383
|
-
const commandsDir =
|
|
2901
|
+
const commandsDir = resolve16(rulesyncDir, "commands");
|
|
2384
2902
|
if (existsSync10(commandsDir)) {
|
|
2385
|
-
const outCommandsDir =
|
|
2903
|
+
const outCommandsDir = resolve16(packDir, "commands");
|
|
2386
2904
|
ensureDir(outCommandsDir);
|
|
2387
2905
|
const files = listFiles(commandsDir, { extension: ".md" });
|
|
2388
2906
|
for (const file of files) {
|
|
2389
|
-
const dest =
|
|
2907
|
+
const dest = join18(outCommandsDir, basename6(file));
|
|
2390
2908
|
copyFileSync(file, dest);
|
|
2391
2909
|
filesImported.push(dest);
|
|
2392
2910
|
}
|
|
2393
2911
|
}
|
|
2394
|
-
const subagentsDir =
|
|
2912
|
+
const subagentsDir = resolve16(rulesyncDir, "subagents");
|
|
2395
2913
|
if (existsSync10(subagentsDir)) {
|
|
2396
|
-
const outAgentsDir =
|
|
2914
|
+
const outAgentsDir = resolve16(packDir, "agents");
|
|
2397
2915
|
ensureDir(outAgentsDir);
|
|
2398
2916
|
const files = listFiles(subagentsDir, { extension: ".md" });
|
|
2399
2917
|
for (const file of files) {
|
|
2400
|
-
const dest =
|
|
2918
|
+
const dest = join18(outAgentsDir, basename6(file));
|
|
2401
2919
|
copyFileSync(file, dest);
|
|
2402
2920
|
filesImported.push(dest);
|
|
2403
2921
|
}
|
|
2404
2922
|
}
|
|
2405
|
-
const skillsDir =
|
|
2923
|
+
const skillsDir = resolve16(rulesyncDir, "skills");
|
|
2406
2924
|
if (existsSync10(skillsDir)) {
|
|
2407
|
-
const outSkillsDir =
|
|
2925
|
+
const outSkillsDir = resolve16(packDir, "skills");
|
|
2408
2926
|
ensureDir(outSkillsDir);
|
|
2409
2927
|
const skillDirs = listDirs(skillsDir);
|
|
2410
2928
|
for (const skillDir of skillDirs) {
|
|
2411
2929
|
const skillName = basename6(skillDir);
|
|
2412
2930
|
if (skillName.startsWith("."))
|
|
2413
2931
|
continue;
|
|
2414
|
-
const skillMd =
|
|
2932
|
+
const skillMd = join18(skillDir, "SKILL.md");
|
|
2415
2933
|
if (existsSync10(skillMd)) {
|
|
2416
|
-
const outSkillDir =
|
|
2934
|
+
const outSkillDir = join18(outSkillsDir, skillName);
|
|
2417
2935
|
ensureDir(outSkillDir);
|
|
2418
|
-
copyFileSync(skillMd,
|
|
2419
|
-
filesImported.push(
|
|
2936
|
+
copyFileSync(skillMd, join18(outSkillDir, "SKILL.md"));
|
|
2937
|
+
filesImported.push(join18(outSkillDir, "SKILL.md"));
|
|
2420
2938
|
}
|
|
2421
2939
|
}
|
|
2422
2940
|
}
|
|
2423
|
-
const hooksJson =
|
|
2941
|
+
const hooksJson = resolve16(rulesyncDir, "hooks.json");
|
|
2424
2942
|
if (existsSync10(hooksJson)) {
|
|
2425
|
-
const outHooksDir =
|
|
2943
|
+
const outHooksDir = resolve16(packDir, "hooks");
|
|
2426
2944
|
ensureDir(outHooksDir);
|
|
2427
|
-
copyFileSync(hooksJson,
|
|
2428
|
-
filesImported.push(
|
|
2945
|
+
copyFileSync(hooksJson, join18(outHooksDir, "hooks.json"));
|
|
2946
|
+
filesImported.push(join18(outHooksDir, "hooks.json"));
|
|
2429
2947
|
}
|
|
2430
|
-
const mcpJson =
|
|
2948
|
+
const mcpJson = resolve16(rulesyncDir, "mcp.json");
|
|
2431
2949
|
if (existsSync10(mcpJson)) {
|
|
2432
|
-
copyFileSync(mcpJson,
|
|
2433
|
-
filesImported.push(
|
|
2950
|
+
copyFileSync(mcpJson, join18(packDir, "mcp.json"));
|
|
2951
|
+
filesImported.push(join18(packDir, "mcp.json"));
|
|
2434
2952
|
}
|
|
2435
|
-
const aiIgnore =
|
|
2436
|
-
const rulesyncIgnore =
|
|
2953
|
+
const aiIgnore = resolve16(rulesyncDir, ".aiignore");
|
|
2954
|
+
const rulesyncIgnore = resolve16(projectRoot, ".rulesyncignore");
|
|
2437
2955
|
if (existsSync10(aiIgnore)) {
|
|
2438
|
-
copyFileSync(aiIgnore,
|
|
2439
|
-
filesImported.push(
|
|
2956
|
+
copyFileSync(aiIgnore, join18(packDir, "ignore"));
|
|
2957
|
+
filesImported.push(join18(packDir, "ignore"));
|
|
2440
2958
|
} else if (existsSync10(rulesyncIgnore)) {
|
|
2441
|
-
copyFileSync(rulesyncIgnore,
|
|
2442
|
-
filesImported.push(
|
|
2959
|
+
copyFileSync(rulesyncIgnore, join18(packDir, "ignore"));
|
|
2960
|
+
filesImported.push(join18(packDir, "ignore"));
|
|
2443
2961
|
}
|
|
2444
2962
|
const packJson = {
|
|
2445
2963
|
name: "default",
|
|
@@ -2451,20 +2969,20 @@ function importFromRulesync(projectRoot, outputPackDir) {
|
|
|
2451
2969
|
targets: "*",
|
|
2452
2970
|
features: "*"
|
|
2453
2971
|
};
|
|
2454
|
-
|
|
2972
|
+
writeFileSync5(join18(packDir, "pack.json"), JSON.stringify(packJson, null, 2) + `
|
|
2455
2973
|
`);
|
|
2456
|
-
filesImported.push(
|
|
2974
|
+
filesImported.push(join18(packDir, "pack.json"));
|
|
2457
2975
|
let configGenerated = false;
|
|
2458
|
-
const rulesyncConfig =
|
|
2976
|
+
const rulesyncConfig = resolve16(projectRoot, "rulesync.jsonc");
|
|
2459
2977
|
if (existsSync10(rulesyncConfig)) {
|
|
2460
|
-
const agentpacksConfig = convertRulesyncConfig(rulesyncConfig, packDir
|
|
2461
|
-
const configPath =
|
|
2462
|
-
|
|
2978
|
+
const agentpacksConfig = convertRulesyncConfig(rulesyncConfig, packDir);
|
|
2979
|
+
const configPath = resolve16(projectRoot, "agentpacks.jsonc");
|
|
2980
|
+
writeFileSync5(configPath, agentpacksConfig);
|
|
2463
2981
|
configGenerated = true;
|
|
2464
2982
|
}
|
|
2465
2983
|
return { packDir, filesImported, warnings, configGenerated };
|
|
2466
2984
|
}
|
|
2467
|
-
function convertRulesyncConfig(rulesyncPath,
|
|
2985
|
+
function convertRulesyncConfig(rulesyncPath, _packDir) {
|
|
2468
2986
|
const raw = readFileSync10(rulesyncPath, "utf-8");
|
|
2469
2987
|
const parsed = parseJsonc2(raw);
|
|
2470
2988
|
const targets = parsed.targets ?? ["opencode", "cursor", "claudecode"];
|
|
@@ -2472,7 +2990,7 @@ function convertRulesyncConfig(rulesyncPath, packDir, projectRoot) {
|
|
|
2472
2990
|
const baseDirs = parsed.baseDirs ?? ["."];
|
|
2473
2991
|
const global = parsed.global ?? false;
|
|
2474
2992
|
const deleteVal = parsed.delete ?? true;
|
|
2475
|
-
const relPackDir = "./" +
|
|
2993
|
+
const relPackDir = "./" + join18("packs", "default");
|
|
2476
2994
|
const config = {
|
|
2477
2995
|
$schema: "https://unpkg.com/agentpacks/schema.json",
|
|
2478
2996
|
packs: [relPackDir],
|
|
@@ -2489,10 +3007,10 @@ function convertRulesyncConfig(rulesyncPath, packDir, projectRoot) {
|
|
|
2489
3007
|
}
|
|
2490
3008
|
|
|
2491
3009
|
// src/importers/cursor.ts
|
|
2492
|
-
import { existsSync as existsSync11, readFileSync as readFileSync11, writeFileSync as
|
|
2493
|
-
import { resolve as
|
|
3010
|
+
import { existsSync as existsSync11, readFileSync as readFileSync11, writeFileSync as writeFileSync6, copyFileSync as copyFileSync2 } from "fs";
|
|
3011
|
+
import { resolve as resolve17, join as join19, basename as basename7 } from "path";
|
|
2494
3012
|
function importFromCursor(projectRoot, outputPackDir) {
|
|
2495
|
-
const cursorDir =
|
|
3013
|
+
const cursorDir = resolve17(projectRoot, ".cursor");
|
|
2496
3014
|
const warnings = [];
|
|
2497
3015
|
const filesImported = [];
|
|
2498
3016
|
if (!existsSync11(cursorDir)) {
|
|
@@ -2503,11 +3021,11 @@ function importFromCursor(projectRoot, outputPackDir) {
|
|
|
2503
3021
|
configGenerated: false
|
|
2504
3022
|
};
|
|
2505
3023
|
}
|
|
2506
|
-
const packDir = outputPackDir ??
|
|
3024
|
+
const packDir = outputPackDir ?? resolve17(projectRoot, "packs", "cursor-import");
|
|
2507
3025
|
ensureDir(packDir);
|
|
2508
|
-
const rulesDir =
|
|
3026
|
+
const rulesDir = resolve17(cursorDir, "rules");
|
|
2509
3027
|
if (existsSync11(rulesDir)) {
|
|
2510
|
-
const outRulesDir =
|
|
3028
|
+
const outRulesDir = resolve17(packDir, "rules");
|
|
2511
3029
|
ensureDir(outRulesDir);
|
|
2512
3030
|
const files = listFiles(rulesDir, { extension: ".mdc" });
|
|
2513
3031
|
for (const file of files) {
|
|
@@ -2523,64 +3041,64 @@ function importFromCursor(projectRoot, outputPackDir) {
|
|
|
2523
3041
|
meta.cursor = { ...data };
|
|
2524
3042
|
const mdContent = buildAgentpacksRule(meta, content);
|
|
2525
3043
|
const name = basename7(file, ".mdc");
|
|
2526
|
-
const dest =
|
|
2527
|
-
|
|
3044
|
+
const dest = join19(outRulesDir, `${name}.md`);
|
|
3045
|
+
writeFileSync6(dest, mdContent);
|
|
2528
3046
|
filesImported.push(dest);
|
|
2529
3047
|
}
|
|
2530
3048
|
const mdFiles = listFiles(rulesDir, { extension: ".md" });
|
|
2531
3049
|
for (const file of mdFiles) {
|
|
2532
|
-
const dest =
|
|
3050
|
+
const dest = join19(outRulesDir, basename7(file));
|
|
2533
3051
|
copyFileSync2(file, dest);
|
|
2534
3052
|
filesImported.push(dest);
|
|
2535
3053
|
}
|
|
2536
3054
|
}
|
|
2537
|
-
const agentsDir =
|
|
3055
|
+
const agentsDir = resolve17(cursorDir, "agents");
|
|
2538
3056
|
if (existsSync11(agentsDir)) {
|
|
2539
|
-
const outDir =
|
|
3057
|
+
const outDir = resolve17(packDir, "agents");
|
|
2540
3058
|
ensureDir(outDir);
|
|
2541
3059
|
const files = listFiles(agentsDir, { extension: ".md" });
|
|
2542
3060
|
for (const file of files) {
|
|
2543
|
-
const dest =
|
|
3061
|
+
const dest = join19(outDir, basename7(file));
|
|
2544
3062
|
copyFileSync2(file, dest);
|
|
2545
3063
|
filesImported.push(dest);
|
|
2546
3064
|
}
|
|
2547
3065
|
}
|
|
2548
|
-
const skillsDir =
|
|
3066
|
+
const skillsDir = resolve17(cursorDir, "skills");
|
|
2549
3067
|
if (existsSync11(skillsDir)) {
|
|
2550
|
-
const outDir =
|
|
3068
|
+
const outDir = resolve17(packDir, "skills");
|
|
2551
3069
|
ensureDir(outDir);
|
|
2552
3070
|
const dirs = listDirs(skillsDir);
|
|
2553
3071
|
for (const dir of dirs) {
|
|
2554
3072
|
const name = basename7(dir);
|
|
2555
|
-
const skillMd =
|
|
3073
|
+
const skillMd = join19(dir, "SKILL.md");
|
|
2556
3074
|
if (existsSync11(skillMd)) {
|
|
2557
|
-
const outSkillDir =
|
|
3075
|
+
const outSkillDir = join19(outDir, name);
|
|
2558
3076
|
ensureDir(outSkillDir);
|
|
2559
|
-
copyFileSync2(skillMd,
|
|
2560
|
-
filesImported.push(
|
|
3077
|
+
copyFileSync2(skillMd, join19(outSkillDir, "SKILL.md"));
|
|
3078
|
+
filesImported.push(join19(outSkillDir, "SKILL.md"));
|
|
2561
3079
|
}
|
|
2562
3080
|
}
|
|
2563
3081
|
}
|
|
2564
|
-
const commandsDir =
|
|
3082
|
+
const commandsDir = resolve17(cursorDir, "commands");
|
|
2565
3083
|
if (existsSync11(commandsDir)) {
|
|
2566
|
-
const outDir =
|
|
3084
|
+
const outDir = resolve17(packDir, "commands");
|
|
2567
3085
|
ensureDir(outDir);
|
|
2568
3086
|
const files = listFiles(commandsDir, { extension: ".md" });
|
|
2569
3087
|
for (const file of files) {
|
|
2570
|
-
const dest =
|
|
3088
|
+
const dest = join19(outDir, basename7(file));
|
|
2571
3089
|
copyFileSync2(file, dest);
|
|
2572
3090
|
filesImported.push(dest);
|
|
2573
3091
|
}
|
|
2574
3092
|
}
|
|
2575
|
-
const mcpJson =
|
|
3093
|
+
const mcpJson = resolve17(cursorDir, "mcp.json");
|
|
2576
3094
|
if (existsSync11(mcpJson)) {
|
|
2577
|
-
copyFileSync2(mcpJson,
|
|
2578
|
-
filesImported.push(
|
|
3095
|
+
copyFileSync2(mcpJson, join19(packDir, "mcp.json"));
|
|
3096
|
+
filesImported.push(join19(packDir, "mcp.json"));
|
|
2579
3097
|
}
|
|
2580
|
-
const cursorIgnore =
|
|
3098
|
+
const cursorIgnore = resolve17(projectRoot, ".cursorignore");
|
|
2581
3099
|
if (existsSync11(cursorIgnore)) {
|
|
2582
|
-
copyFileSync2(cursorIgnore,
|
|
2583
|
-
filesImported.push(
|
|
3100
|
+
copyFileSync2(cursorIgnore, join19(packDir, "ignore"));
|
|
3101
|
+
filesImported.push(join19(packDir, "ignore"));
|
|
2584
3102
|
}
|
|
2585
3103
|
writePackJson(packDir, "cursor-import", filesImported);
|
|
2586
3104
|
return { packDir, filesImported, warnings, configGenerated: false };
|
|
@@ -2609,20 +3127,20 @@ function writePackJson(packDir, name, filesImported) {
|
|
|
2609
3127
|
targets: "*",
|
|
2610
3128
|
features: "*"
|
|
2611
3129
|
};
|
|
2612
|
-
const dest =
|
|
2613
|
-
|
|
3130
|
+
const dest = join19(packDir, "pack.json");
|
|
3131
|
+
writeFileSync6(dest, JSON.stringify(packJson, null, 2) + `
|
|
2614
3132
|
`);
|
|
2615
3133
|
filesImported.push(dest);
|
|
2616
3134
|
}
|
|
2617
3135
|
|
|
2618
3136
|
// src/importers/claude-code.ts
|
|
2619
|
-
import { existsSync as existsSync12, readFileSync as readFileSync12, writeFileSync as
|
|
2620
|
-
import { resolve as
|
|
3137
|
+
import { existsSync as existsSync12, readFileSync as readFileSync12, writeFileSync as writeFileSync7, copyFileSync as copyFileSync3 } from "fs";
|
|
3138
|
+
import { resolve as resolve18, join as join20, basename as basename8 } from "path";
|
|
2621
3139
|
function importFromClaudeCode(projectRoot, outputPackDir) {
|
|
2622
3140
|
const warnings = [];
|
|
2623
3141
|
const filesImported = [];
|
|
2624
|
-
const claudeDir =
|
|
2625
|
-
const hasClaudeMd = existsSync12(
|
|
3142
|
+
const claudeDir = resolve18(projectRoot, ".claude");
|
|
3143
|
+
const hasClaudeMd = existsSync12(resolve18(projectRoot, "CLAUDE.md"));
|
|
2626
3144
|
const hasClaudeDir = existsSync12(claudeDir);
|
|
2627
3145
|
if (!hasClaudeMd && !hasClaudeDir) {
|
|
2628
3146
|
return {
|
|
@@ -2632,12 +3150,12 @@ function importFromClaudeCode(projectRoot, outputPackDir) {
|
|
|
2632
3150
|
configGenerated: false
|
|
2633
3151
|
};
|
|
2634
3152
|
}
|
|
2635
|
-
const packDir = outputPackDir ??
|
|
3153
|
+
const packDir = outputPackDir ?? resolve18(projectRoot, "packs", "claude-import");
|
|
2636
3154
|
ensureDir(packDir);
|
|
2637
|
-
const rulesDir =
|
|
3155
|
+
const rulesDir = resolve18(packDir, "rules");
|
|
2638
3156
|
ensureDir(rulesDir);
|
|
2639
3157
|
if (hasClaudeMd) {
|
|
2640
|
-
const raw = readFileSync12(
|
|
3158
|
+
const raw = readFileSync12(resolve18(projectRoot, "CLAUDE.md"), "utf-8");
|
|
2641
3159
|
const ruleContent = [
|
|
2642
3160
|
"---",
|
|
2643
3161
|
"root: true",
|
|
@@ -2647,21 +3165,21 @@ function importFromClaudeCode(projectRoot, outputPackDir) {
|
|
|
2647
3165
|
raw
|
|
2648
3166
|
].join(`
|
|
2649
3167
|
`);
|
|
2650
|
-
const dest =
|
|
2651
|
-
|
|
3168
|
+
const dest = join20(rulesDir, "claude-root.md");
|
|
3169
|
+
writeFileSync7(dest, ruleContent);
|
|
2652
3170
|
filesImported.push(dest);
|
|
2653
3171
|
}
|
|
2654
3172
|
if (hasClaudeDir) {
|
|
2655
|
-
const claudeRulesDir =
|
|
3173
|
+
const claudeRulesDir = resolve18(claudeDir, "rules");
|
|
2656
3174
|
if (existsSync12(claudeRulesDir)) {
|
|
2657
3175
|
const files = listFiles(claudeRulesDir, { extension: ".md" });
|
|
2658
3176
|
for (const file of files) {
|
|
2659
|
-
const dest =
|
|
3177
|
+
const dest = join20(rulesDir, basename8(file));
|
|
2660
3178
|
copyFileSync3(file, dest);
|
|
2661
3179
|
filesImported.push(dest);
|
|
2662
3180
|
}
|
|
2663
3181
|
}
|
|
2664
|
-
const settingsPath =
|
|
3182
|
+
const settingsPath = resolve18(claudeDir, "settings.json");
|
|
2665
3183
|
if (existsSync12(settingsPath)) {
|
|
2666
3184
|
try {
|
|
2667
3185
|
const raw = readFileSync12(settingsPath, "utf-8");
|
|
@@ -2669,8 +3187,8 @@ function importFromClaudeCode(projectRoot, outputPackDir) {
|
|
|
2669
3187
|
const mcpServers = settings.mcpServers ?? settings.mcp_servers;
|
|
2670
3188
|
if (mcpServers && typeof mcpServers === "object") {
|
|
2671
3189
|
const mcpConfig = { servers: mcpServers };
|
|
2672
|
-
const dest =
|
|
2673
|
-
|
|
3190
|
+
const dest = join20(packDir, "mcp.json");
|
|
3191
|
+
writeFileSync7(dest, JSON.stringify(mcpConfig, null, 2) + `
|
|
2674
3192
|
`);
|
|
2675
3193
|
filesImported.push(dest);
|
|
2676
3194
|
}
|
|
@@ -2689,20 +3207,20 @@ function importFromClaudeCode(projectRoot, outputPackDir) {
|
|
|
2689
3207
|
targets: "*",
|
|
2690
3208
|
features: "*"
|
|
2691
3209
|
};
|
|
2692
|
-
const packJsonPath =
|
|
2693
|
-
|
|
3210
|
+
const packJsonPath = join20(packDir, "pack.json");
|
|
3211
|
+
writeFileSync7(packJsonPath, JSON.stringify(packJson, null, 2) + `
|
|
2694
3212
|
`);
|
|
2695
3213
|
filesImported.push(packJsonPath);
|
|
2696
3214
|
return { packDir, filesImported, warnings, configGenerated: false };
|
|
2697
3215
|
}
|
|
2698
3216
|
|
|
2699
3217
|
// src/importers/opencode.ts
|
|
2700
|
-
import { existsSync as existsSync13, readFileSync as readFileSync13, writeFileSync as
|
|
2701
|
-
import { resolve as
|
|
3218
|
+
import { existsSync as existsSync13, readFileSync as readFileSync13, writeFileSync as writeFileSync8, copyFileSync as copyFileSync4 } from "fs";
|
|
3219
|
+
import { resolve as resolve19, join as join21, basename as basename9 } from "path";
|
|
2702
3220
|
function importFromOpenCode(projectRoot, outputPackDir) {
|
|
2703
3221
|
const warnings = [];
|
|
2704
3222
|
const filesImported = [];
|
|
2705
|
-
const ocDir =
|
|
3223
|
+
const ocDir = resolve19(projectRoot, ".opencode");
|
|
2706
3224
|
if (!existsSync13(ocDir)) {
|
|
2707
3225
|
return {
|
|
2708
3226
|
packDir: "",
|
|
@@ -2711,45 +3229,45 @@ function importFromOpenCode(projectRoot, outputPackDir) {
|
|
|
2711
3229
|
configGenerated: false
|
|
2712
3230
|
};
|
|
2713
3231
|
}
|
|
2714
|
-
const packDir = outputPackDir ??
|
|
3232
|
+
const packDir = outputPackDir ?? resolve19(projectRoot, "packs", "opencode-import");
|
|
2715
3233
|
ensureDir(packDir);
|
|
2716
|
-
importDirMd(
|
|
2717
|
-
importDirMd(
|
|
2718
|
-
importDirMd(
|
|
2719
|
-
const skillDir =
|
|
3234
|
+
importDirMd(resolve19(ocDir, "rules"), resolve19(packDir, "rules"), filesImported);
|
|
3235
|
+
importDirMd(resolve19(ocDir, "commands"), resolve19(packDir, "commands"), filesImported);
|
|
3236
|
+
importDirMd(resolve19(ocDir, "agents"), resolve19(packDir, "agents"), filesImported);
|
|
3237
|
+
const skillDir = resolve19(ocDir, "skill");
|
|
2720
3238
|
if (existsSync13(skillDir)) {
|
|
2721
|
-
const outSkillDir =
|
|
3239
|
+
const outSkillDir = resolve19(packDir, "skills");
|
|
2722
3240
|
ensureDir(outSkillDir);
|
|
2723
3241
|
const dirs = listDirs(skillDir);
|
|
2724
3242
|
for (const dir of dirs) {
|
|
2725
3243
|
const name = basename9(dir);
|
|
2726
3244
|
if (name.startsWith("."))
|
|
2727
3245
|
continue;
|
|
2728
|
-
const skillMd =
|
|
3246
|
+
const skillMd = join21(dir, "SKILL.md");
|
|
2729
3247
|
if (existsSync13(skillMd)) {
|
|
2730
|
-
const outDir =
|
|
3248
|
+
const outDir = join21(outSkillDir, name);
|
|
2731
3249
|
ensureDir(outDir);
|
|
2732
|
-
copyFileSync4(skillMd,
|
|
2733
|
-
filesImported.push(
|
|
3250
|
+
copyFileSync4(skillMd, join21(outDir, "SKILL.md"));
|
|
3251
|
+
filesImported.push(join21(outDir, "SKILL.md"));
|
|
2734
3252
|
}
|
|
2735
3253
|
}
|
|
2736
3254
|
}
|
|
2737
|
-
const pluginsDir =
|
|
3255
|
+
const pluginsDir = resolve19(ocDir, "plugins");
|
|
2738
3256
|
if (existsSync13(pluginsDir)) {
|
|
2739
|
-
const outPluginsDir =
|
|
3257
|
+
const outPluginsDir = resolve19(packDir, "plugins");
|
|
2740
3258
|
ensureDir(outPluginsDir);
|
|
2741
3259
|
const files = listFiles(pluginsDir);
|
|
2742
3260
|
for (const file of files) {
|
|
2743
3261
|
if (file.endsWith(".ts") || file.endsWith(".js")) {
|
|
2744
|
-
const dest2 =
|
|
3262
|
+
const dest2 = join21(outPluginsDir, basename9(file));
|
|
2745
3263
|
copyFileSync4(file, dest2);
|
|
2746
3264
|
filesImported.push(dest2);
|
|
2747
3265
|
}
|
|
2748
3266
|
}
|
|
2749
3267
|
}
|
|
2750
|
-
const agentsMd =
|
|
3268
|
+
const agentsMd = resolve19(projectRoot, "AGENTS.md");
|
|
2751
3269
|
if (existsSync13(agentsMd)) {
|
|
2752
|
-
const outRulesDir =
|
|
3270
|
+
const outRulesDir = resolve19(packDir, "rules");
|
|
2753
3271
|
ensureDir(outRulesDir);
|
|
2754
3272
|
const raw = readFileSync13(agentsMd, "utf-8");
|
|
2755
3273
|
const ruleContent = [
|
|
@@ -2761,19 +3279,19 @@ function importFromOpenCode(projectRoot, outputPackDir) {
|
|
|
2761
3279
|
raw
|
|
2762
3280
|
].join(`
|
|
2763
3281
|
`);
|
|
2764
|
-
const dest2 =
|
|
2765
|
-
|
|
3282
|
+
const dest2 = join21(outRulesDir, "agents-md-root.md");
|
|
3283
|
+
writeFileSync8(dest2, ruleContent);
|
|
2766
3284
|
filesImported.push(dest2);
|
|
2767
3285
|
}
|
|
2768
|
-
const ocJson =
|
|
3286
|
+
const ocJson = resolve19(projectRoot, "opencode.json");
|
|
2769
3287
|
if (existsSync13(ocJson)) {
|
|
2770
3288
|
try {
|
|
2771
3289
|
const raw = readFileSync13(ocJson, "utf-8");
|
|
2772
3290
|
const config = JSON.parse(raw);
|
|
2773
3291
|
const mcpObj = config.mcp;
|
|
2774
3292
|
if (mcpObj) {
|
|
2775
|
-
const dest2 =
|
|
2776
|
-
|
|
3293
|
+
const dest2 = join21(packDir, "mcp.json");
|
|
3294
|
+
writeFileSync8(dest2, JSON.stringify({ servers: mcpObj }, null, 2) + `
|
|
2777
3295
|
`);
|
|
2778
3296
|
filesImported.push(dest2);
|
|
2779
3297
|
}
|
|
@@ -2781,10 +3299,10 @@ function importFromOpenCode(projectRoot, outputPackDir) {
|
|
|
2781
3299
|
warnings.push("Failed to parse opencode.json");
|
|
2782
3300
|
}
|
|
2783
3301
|
}
|
|
2784
|
-
const ocIgnore =
|
|
3302
|
+
const ocIgnore = resolve19(projectRoot, ".opencodeignore");
|
|
2785
3303
|
if (existsSync13(ocIgnore)) {
|
|
2786
|
-
copyFileSync4(ocIgnore,
|
|
2787
|
-
filesImported.push(
|
|
3304
|
+
copyFileSync4(ocIgnore, join21(packDir, "ignore"));
|
|
3305
|
+
filesImported.push(join21(packDir, "ignore"));
|
|
2788
3306
|
}
|
|
2789
3307
|
const packJson = {
|
|
2790
3308
|
name: "opencode-import",
|
|
@@ -2796,8 +3314,8 @@ function importFromOpenCode(projectRoot, outputPackDir) {
|
|
|
2796
3314
|
targets: "*",
|
|
2797
3315
|
features: "*"
|
|
2798
3316
|
};
|
|
2799
|
-
const dest =
|
|
2800
|
-
|
|
3317
|
+
const dest = join21(packDir, "pack.json");
|
|
3318
|
+
writeFileSync8(dest, JSON.stringify(packJson, null, 2) + `
|
|
2801
3319
|
`);
|
|
2802
3320
|
filesImported.push(dest);
|
|
2803
3321
|
return { packDir, filesImported, warnings, configGenerated: false };
|
|
@@ -2808,26 +3326,28 @@ function importDirMd(srcDir, outDir, filesImported) {
|
|
|
2808
3326
|
ensureDir(outDir);
|
|
2809
3327
|
const files = listFiles(srcDir, { extension: ".md" });
|
|
2810
3328
|
for (const file of files) {
|
|
2811
|
-
const dest =
|
|
3329
|
+
const dest = join21(outDir, basename9(file));
|
|
2812
3330
|
copyFileSync4(file, dest);
|
|
2813
3331
|
filesImported.push(dest);
|
|
2814
3332
|
}
|
|
2815
3333
|
}
|
|
2816
|
-
|
|
2817
|
-
// src/api.ts
|
|
2818
|
-
init_config();
|
|
2819
3334
|
export {
|
|
2820
3335
|
saveLockfile,
|
|
2821
3336
|
resolveTargets,
|
|
3337
|
+
resolveModels,
|
|
2822
3338
|
resolveLocalPack,
|
|
2823
3339
|
resolveFeatures,
|
|
2824
3340
|
resolveDependencies,
|
|
3341
|
+
resolveAgentModel,
|
|
3342
|
+
registrySourceKey,
|
|
3343
|
+
parseRegistrySourceRef,
|
|
2825
3344
|
parseNpmSourceRef,
|
|
2826
3345
|
parseGitSourceRef,
|
|
2827
3346
|
loadWorkspaceConfig,
|
|
2828
3347
|
loadPackManifest,
|
|
2829
3348
|
loadLockfile,
|
|
2830
3349
|
listTargetIds,
|
|
3350
|
+
isRegistryPackRef,
|
|
2831
3351
|
isNpmPackRef,
|
|
2832
3352
|
isLocalPackRef,
|
|
2833
3353
|
isGitPackRef,
|