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.
Files changed (166) hide show
  1. package/README.md +168 -8
  2. package/dist/api.d.ts +2 -0
  3. package/dist/api.js +929 -409
  4. package/dist/cli/export-cmd.js +281 -149
  5. package/dist/cli/generate.js +740 -247
  6. package/dist/cli/import-cmd.js +57 -85
  7. package/dist/cli/info.d.ts +4 -0
  8. package/dist/cli/info.js +232 -0
  9. package/dist/cli/init.js +8 -36
  10. package/dist/cli/install.js +414 -129
  11. package/dist/cli/login.d.ts +9 -0
  12. package/dist/cli/login.js +202 -0
  13. package/dist/cli/models-explain.d.ts +16 -0
  14. package/dist/cli/models-explain.js +1205 -0
  15. package/dist/cli/pack/create.js +4 -32
  16. package/dist/cli/pack/enable.js +1 -29
  17. package/dist/cli/pack/list.js +266 -134
  18. package/dist/cli/pack/validate.js +274 -127
  19. package/dist/cli/publish.d.ts +8 -0
  20. package/dist/cli/publish.js +672 -0
  21. package/dist/cli/search.d.ts +12 -0
  22. package/dist/cli/search.js +210 -0
  23. package/dist/core/config.d.ts +2 -1
  24. package/dist/core/config.js +74 -117
  25. package/dist/core/dependency-resolver.js +4 -28
  26. package/dist/core/feature-merger.d.ts +7 -0
  27. package/dist/core/feature-merger.js +289 -29
  28. package/dist/core/index.js +283 -140
  29. package/dist/core/lockfile.js +0 -28
  30. package/dist/core/metarepo.js +74 -116
  31. package/dist/core/pack-loader.d.ts +2 -0
  32. package/dist/core/pack-loader.js +266 -133
  33. package/dist/core/profile-resolver.d.ts +75 -0
  34. package/dist/core/profile-resolver.js +111 -0
  35. package/dist/exporters/cursor-plugin.js +4 -32
  36. package/dist/exporters/index.js +4 -32
  37. package/dist/features/agents.d.ts +5 -0
  38. package/dist/features/agents.js +2 -30
  39. package/dist/features/commands.js +2 -30
  40. package/dist/features/hooks.js +2 -30
  41. package/dist/features/ignore.js +0 -28
  42. package/dist/features/index.d.ts +1 -0
  43. package/dist/features/index.js +176 -31
  44. package/dist/features/mcp.js +2 -30
  45. package/dist/features/models.d.ts +167 -0
  46. package/dist/features/models.js +293 -0
  47. package/dist/features/plugins.js +2 -30
  48. package/dist/features/rules.js +2 -30
  49. package/dist/features/skills.js +2 -30
  50. package/dist/importers/claude-code.js +10 -38
  51. package/dist/importers/cursor.js +15 -43
  52. package/dist/importers/opencode.js +16 -44
  53. package/dist/importers/rulesync.js +22 -50
  54. package/dist/index.js +1710 -538
  55. package/dist/node/api.js +929 -409
  56. package/dist/node/cli/export-cmd.js +281 -149
  57. package/dist/node/cli/generate.js +740 -247
  58. package/dist/node/cli/import-cmd.js +57 -85
  59. package/dist/node/cli/info.js +232 -0
  60. package/dist/node/cli/init.js +8 -36
  61. package/dist/node/cli/install.js +414 -129
  62. package/dist/node/cli/login.js +202 -0
  63. package/dist/node/cli/models-explain.js +1205 -0
  64. package/dist/node/cli/pack/create.js +4 -32
  65. package/dist/node/cli/pack/enable.js +1 -29
  66. package/dist/node/cli/pack/list.js +266 -134
  67. package/dist/node/cli/pack/validate.js +274 -127
  68. package/dist/node/cli/publish.js +672 -0
  69. package/dist/node/cli/search.js +210 -0
  70. package/dist/node/core/config.js +74 -117
  71. package/dist/node/core/dependency-resolver.js +4 -28
  72. package/dist/node/core/feature-merger.js +289 -29
  73. package/dist/node/core/index.js +283 -140
  74. package/dist/node/core/lockfile.js +0 -28
  75. package/dist/node/core/metarepo.js +74 -116
  76. package/dist/node/core/pack-loader.js +266 -133
  77. package/dist/node/core/profile-resolver.js +111 -0
  78. package/dist/node/exporters/cursor-plugin.js +4 -32
  79. package/dist/node/exporters/index.js +4 -32
  80. package/dist/node/features/agents.js +2 -30
  81. package/dist/node/features/commands.js +2 -30
  82. package/dist/node/features/hooks.js +2 -30
  83. package/dist/node/features/ignore.js +0 -28
  84. package/dist/node/features/index.js +176 -31
  85. package/dist/node/features/mcp.js +2 -30
  86. package/dist/node/features/models.js +293 -0
  87. package/dist/node/features/plugins.js +2 -30
  88. package/dist/node/features/rules.js +2 -30
  89. package/dist/node/features/skills.js +2 -30
  90. package/dist/node/importers/claude-code.js +10 -38
  91. package/dist/node/importers/cursor.js +15 -43
  92. package/dist/node/importers/opencode.js +16 -44
  93. package/dist/node/importers/rulesync.js +22 -50
  94. package/dist/node/index.js +1710 -538
  95. package/dist/node/sources/git-ref.js +7 -30
  96. package/dist/node/sources/git.js +7 -30
  97. package/dist/node/sources/index.js +337 -39
  98. package/dist/node/sources/local.js +0 -28
  99. package/dist/node/sources/npm-ref.js +0 -28
  100. package/dist/node/sources/npm.js +10 -37
  101. package/dist/node/sources/registry-ref.js +37 -0
  102. package/dist/node/sources/registry.js +355 -0
  103. package/dist/node/targets/additional-targets.js +196 -37
  104. package/dist/node/targets/agents-md.js +5 -33
  105. package/dist/node/targets/base-target.js +0 -28
  106. package/dist/node/targets/claude-code.js +211 -41
  107. package/dist/node/targets/codex-cli.js +7 -35
  108. package/dist/node/targets/copilot.js +202 -41
  109. package/dist/node/targets/cursor.js +188 -40
  110. package/dist/node/targets/gemini-cli.js +10 -38
  111. package/dist/node/targets/generic-md-target.js +196 -37
  112. package/dist/node/targets/index.js +414 -106
  113. package/dist/node/targets/opencode.js +171 -51
  114. package/dist/node/targets/registry.js +414 -106
  115. package/dist/node/utils/credentials.js +38 -0
  116. package/dist/node/utils/diff.js +22 -34
  117. package/dist/node/utils/filesystem.js +2 -30
  118. package/dist/node/utils/frontmatter.js +0 -28
  119. package/dist/node/utils/global.js +3 -31
  120. package/dist/node/utils/markdown.js +0 -28
  121. package/dist/node/utils/model-allowlist.js +110 -0
  122. package/dist/node/utils/model-guidance.js +78 -0
  123. package/dist/node/utils/registry-client.js +142 -0
  124. package/dist/node/utils/tarball.js +49 -0
  125. package/dist/sources/git-ref.js +7 -30
  126. package/dist/sources/git.d.ts +2 -2
  127. package/dist/sources/git.js +7 -30
  128. package/dist/sources/index.d.ts +2 -0
  129. package/dist/sources/index.js +337 -39
  130. package/dist/sources/local.js +0 -28
  131. package/dist/sources/npm-ref.js +0 -28
  132. package/dist/sources/npm.js +10 -37
  133. package/dist/sources/registry-ref.d.ts +30 -0
  134. package/dist/sources/registry-ref.js +37 -0
  135. package/dist/sources/registry.d.ts +18 -0
  136. package/dist/sources/registry.js +355 -0
  137. package/dist/targets/additional-targets.js +196 -37
  138. package/dist/targets/agents-md.js +5 -33
  139. package/dist/targets/base-target.d.ts +2 -0
  140. package/dist/targets/base-target.js +0 -28
  141. package/dist/targets/claude-code.js +211 -41
  142. package/dist/targets/codex-cli.js +7 -35
  143. package/dist/targets/copilot.js +202 -41
  144. package/dist/targets/cursor.js +188 -40
  145. package/dist/targets/gemini-cli.js +10 -38
  146. package/dist/targets/generic-md-target.js +196 -37
  147. package/dist/targets/index.js +414 -106
  148. package/dist/targets/opencode.js +171 -51
  149. package/dist/targets/registry.js +414 -106
  150. package/dist/utils/credentials.d.ts +19 -0
  151. package/dist/utils/credentials.js +38 -0
  152. package/dist/utils/diff.js +22 -34
  153. package/dist/utils/filesystem.js +2 -30
  154. package/dist/utils/frontmatter.js +0 -28
  155. package/dist/utils/global.js +3 -31
  156. package/dist/utils/markdown.js +0 -28
  157. package/dist/utils/model-allowlist.d.ts +39 -0
  158. package/dist/utils/model-allowlist.js +110 -0
  159. package/dist/utils/model-guidance.d.ts +6 -0
  160. package/dist/utils/model-guidance.js +78 -0
  161. package/dist/utils/registry-client.d.ts +141 -0
  162. package/dist/utils/registry-client.js +142 -0
  163. package/dist/utils/tarball.d.ts +13 -0
  164. package/dist/utils/tarball.js +49 -0
  165. package/package.json +171 -5
  166. package/templates/pack/models.json +38 -0
@@ -1,51 +1,85 @@
1
1
  import { createRequire } from "node:module";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __moduleCache = /* @__PURE__ */ new WeakMap;
7
- var __toCommonJS = (from) => {
8
- var entry = __moduleCache.get(from), desc;
9
- if (entry)
10
- return entry;
11
- entry = __defProp({}, "__esModule", { value: true });
12
- if (from && typeof from === "object" || typeof from === "function")
13
- __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
14
- get: () => from[key],
15
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
- }));
17
- __moduleCache.set(from, entry);
18
- return entry;
19
- };
20
- var __export = (target, all) => {
21
- for (var name in all)
22
- __defProp(target, name, {
23
- get: all[name],
24
- enumerable: true,
25
- configurable: true,
26
- set: (newValue) => all[name] = () => newValue
27
- });
28
- };
29
- var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
30
2
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
31
3
 
32
4
  // src/core/config.ts
33
- var exports_config = {};
34
- __export(exports_config, {
35
- resolveTargets: () => resolveTargets,
36
- resolveFeatures: () => resolveFeatures,
37
- loadWorkspaceConfig: () => loadWorkspaceConfig,
38
- loadPackManifest: () => loadPackManifest,
39
- WorkspaceConfigSchema: () => WorkspaceConfigSchema,
40
- TARGET_IDS: () => TARGET_IDS,
41
- REPO_MODES: () => REPO_MODES,
42
- PackManifestSchema: () => PackManifestSchema,
43
- FEATURE_IDS: () => FEATURE_IDS
44
- });
45
5
  import { z } from "zod";
46
6
  import { readFileSync, existsSync } from "fs";
47
7
  import { resolve } from "path";
48
8
  import { parse as parseJsonc } from "jsonc-parser";
9
+ var TARGET_IDS = [
10
+ "opencode",
11
+ "cursor",
12
+ "claudecode",
13
+ "codexcli",
14
+ "geminicli",
15
+ "copilot",
16
+ "agentsmd",
17
+ "cline",
18
+ "kilo",
19
+ "roo",
20
+ "qwencode",
21
+ "kiro",
22
+ "factorydroid",
23
+ "antigravity",
24
+ "junie",
25
+ "augmentcode",
26
+ "windsurf",
27
+ "warp",
28
+ "replit",
29
+ "zed"
30
+ ];
31
+ var FEATURE_IDS = [
32
+ "rules",
33
+ "commands",
34
+ "agents",
35
+ "skills",
36
+ "hooks",
37
+ "plugins",
38
+ "mcp",
39
+ "ignore",
40
+ "models"
41
+ ];
42
+ var REPO_MODES = ["repo", "monorepo", "metarepo"];
43
+ var PackManifestSchema = z.object({
44
+ name: z.string().min(1),
45
+ version: z.string().default("1.0.0"),
46
+ description: z.string().default(""),
47
+ author: z.union([
48
+ z.string(),
49
+ z.object({ name: z.string(), email: z.string().optional() })
50
+ ]).optional(),
51
+ tags: z.array(z.string()).default([]),
52
+ dependencies: z.array(z.string()).default([]),
53
+ conflicts: z.array(z.string()).default([]),
54
+ targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
55
+ features: z.union([z.literal("*"), z.array(z.string())]).default("*")
56
+ });
57
+ var FeaturesSchema = z.union([
58
+ z.literal("*"),
59
+ z.array(z.string()),
60
+ z.record(z.string(), z.union([z.literal("*"), z.array(z.string())]))
61
+ ]);
62
+ var WorkspaceConfigSchema = z.object({
63
+ $schema: z.string().optional(),
64
+ packs: z.array(z.string()).default(["./packs/default"]),
65
+ disabled: z.array(z.string()).default([]),
66
+ targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
67
+ features: FeaturesSchema.default("*"),
68
+ mode: z.enum(REPO_MODES).default("repo"),
69
+ baseDirs: z.array(z.string()).default(["."]),
70
+ global: z.boolean().default(false),
71
+ delete: z.boolean().default(true),
72
+ verbose: z.boolean().default(false),
73
+ silent: z.boolean().default(false),
74
+ overrides: z.record(z.string(), z.record(z.string(), z.string())).default({}),
75
+ sources: z.array(z.object({
76
+ source: z.string(),
77
+ packs: z.array(z.string()).optional(),
78
+ skills: z.array(z.string()).optional()
79
+ })).default([]),
80
+ modelProfile: z.string().optional()
81
+ });
82
+ var CONFIG_FILES = ["agentpacks.local.jsonc", "agentpacks.jsonc"];
49
83
  function loadWorkspaceConfig(projectRoot) {
50
84
  for (const filename of CONFIG_FILES) {
51
85
  const filepath = resolve(projectRoot, filename);
@@ -91,81 +125,6 @@ function resolveTargets(config) {
91
125
  return [...TARGET_IDS];
92
126
  return config.targets;
93
127
  }
94
- var TARGET_IDS, FEATURE_IDS, REPO_MODES, PackManifestSchema, FeaturesSchema, WorkspaceConfigSchema, CONFIG_FILES;
95
- var init_config = __esm(() => {
96
- TARGET_IDS = [
97
- "opencode",
98
- "cursor",
99
- "claudecode",
100
- "codexcli",
101
- "geminicli",
102
- "copilot",
103
- "agentsmd",
104
- "cline",
105
- "kilo",
106
- "roo",
107
- "qwencode",
108
- "kiro",
109
- "factorydroid",
110
- "antigravity",
111
- "junie",
112
- "augmentcode",
113
- "windsurf",
114
- "warp",
115
- "replit",
116
- "zed"
117
- ];
118
- FEATURE_IDS = [
119
- "rules",
120
- "commands",
121
- "agents",
122
- "skills",
123
- "hooks",
124
- "plugins",
125
- "mcp",
126
- "ignore"
127
- ];
128
- REPO_MODES = ["repo", "monorepo", "metarepo"];
129
- PackManifestSchema = z.object({
130
- name: z.string().min(1),
131
- version: z.string().default("1.0.0"),
132
- description: z.string().default(""),
133
- author: z.union([
134
- z.string(),
135
- z.object({ name: z.string(), email: z.string().optional() })
136
- ]).optional(),
137
- tags: z.array(z.string()).default([]),
138
- dependencies: z.array(z.string()).default([]),
139
- conflicts: z.array(z.string()).default([]),
140
- targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
141
- features: z.union([z.literal("*"), z.array(z.string())]).default("*")
142
- });
143
- FeaturesSchema = z.union([
144
- z.literal("*"),
145
- z.array(z.string()),
146
- z.record(z.string(), z.union([z.literal("*"), z.array(z.string())]))
147
- ]);
148
- WorkspaceConfigSchema = z.object({
149
- $schema: z.string().optional(),
150
- packs: z.array(z.string()).default(["./packs/default"]),
151
- disabled: z.array(z.string()).default([]),
152
- targets: z.union([z.literal("*"), z.array(z.string())]).default("*"),
153
- features: FeaturesSchema.default("*"),
154
- mode: z.enum(REPO_MODES).default("repo"),
155
- baseDirs: z.array(z.string()).default(["."]),
156
- global: z.boolean().default(false),
157
- delete: z.boolean().default(true),
158
- verbose: z.boolean().default(false),
159
- silent: z.boolean().default(false),
160
- overrides: z.record(z.string(), z.record(z.string(), z.string())).default({}),
161
- sources: z.array(z.object({
162
- source: z.string(),
163
- packs: z.array(z.string()).optional(),
164
- skills: z.array(z.string()).optional()
165
- })).default([])
166
- });
167
- CONFIG_FILES = ["agentpacks.local.jsonc", "agentpacks.jsonc"];
168
- });
169
128
 
170
129
  // src/utils/filesystem.ts
171
130
  import {
@@ -174,10 +133,10 @@ import {
174
133
  readFileSync as readFileSync2,
175
134
  writeFileSync,
176
135
  readdirSync,
136
+ rmSync,
177
137
  statSync
178
138
  } from "fs";
179
139
  import { dirname, relative, join } from "path";
180
- import { removeSync } from "fs-extra";
181
140
  var GENERATED_HEADER_MD = "<!-- Generated by agentpacks. DO NOT EDIT. -->";
182
141
  var GENERATED_HEADER_JSON = "// Generated by agentpacks. DO NOT EDIT.";
183
142
  var GENERATED_HEADER_JS = "// Generated by agentpacks. DO NOT EDIT.";
@@ -218,7 +177,7 @@ function ensureDir(dirPath) {
218
177
  }
219
178
  function removeIfExists(targetPath) {
220
179
  if (existsSync2(targetPath)) {
221
- removeSync(targetPath);
180
+ rmSync(targetPath, { recursive: true, force: true });
222
181
  }
223
182
  }
224
183
  function listFiles(dirPath, options = {}) {
@@ -277,10 +236,178 @@ function getHeader(type) {
277
236
  }
278
237
  }
279
238
 
239
+ // src/features/models.ts
240
+ import { join as join2 } from "path";
241
+ import { z as z2 } from "zod";
242
+ var SECRET_PATTERNS = [
243
+ /["']api[_-]?key["']\s*:/i,
244
+ /["']apiKey["']\s*:/i,
245
+ /["']secret["']\s*:/i,
246
+ /["']password["']\s*:/i,
247
+ /["'](?:auth_token|access_token|bearer_token)["']\s*:/i,
248
+ /["']private[_-]?key["']\s*:/i,
249
+ /-----BEGIN\s+(RSA|EC|DSA|OPENSSH|PGP)\s+PRIVATE\s+KEY-----/,
250
+ /sk-[a-zA-Z0-9]{20,}/,
251
+ /Bearer\s+[a-zA-Z0-9._-]{20,}/
252
+ ];
253
+ var AgentModelSchema = z2.object({
254
+ model: z2.string(),
255
+ temperature: z2.number().min(0).max(2).optional(),
256
+ top_p: z2.number().min(0).max(1).optional()
257
+ });
258
+ var ModelProfileSchema = z2.object({
259
+ extends: z2.string().optional(),
260
+ description: z2.string().optional(),
261
+ default: z2.string().optional(),
262
+ small: z2.string().optional(),
263
+ agents: z2.record(z2.string(), AgentModelSchema).optional()
264
+ });
265
+ var RoutingConditionSchema = z2.object({
266
+ complexity: z2.enum(["low", "medium", "high", "critical"]).optional().describe("Task complexity level"),
267
+ urgency: z2.enum(["low", "normal", "high"]).optional().describe("Time sensitivity"),
268
+ budget: z2.enum(["minimal", "standard", "premium"]).optional().describe("Cost/token budget tier"),
269
+ contextWindowNeed: z2.enum(["small", "medium", "large", "max"]).optional().describe("Required context window size"),
270
+ toolUseIntensity: z2.enum(["none", "light", "heavy"]).optional().describe("Expected tool/function calling intensity")
271
+ });
272
+ var RoutingRuleSchema = z2.object({
273
+ when: z2.record(z2.string(), z2.string()),
274
+ use: z2.string(),
275
+ description: z2.string().optional(),
276
+ priority: z2.number().optional()
277
+ });
278
+ var ProviderModelSchema = z2.object({
279
+ options: z2.record(z2.string(), z2.unknown()).optional(),
280
+ variants: z2.record(z2.string(), z2.record(z2.string(), z2.unknown())).optional()
281
+ });
282
+ var ProviderConfigSchema = z2.object({
283
+ options: z2.record(z2.string(), z2.unknown()).optional(),
284
+ models: z2.record(z2.string(), ProviderModelSchema).optional()
285
+ });
286
+ var ModelsSchema = z2.object({
287
+ default: z2.string().optional(),
288
+ small: z2.string().optional(),
289
+ agents: z2.record(z2.string(), AgentModelSchema).optional(),
290
+ profiles: z2.record(z2.string(), ModelProfileSchema).optional(),
291
+ providers: z2.record(z2.string(), ProviderConfigSchema).optional(),
292
+ routing: z2.array(RoutingRuleSchema).optional(),
293
+ overrides: z2.record(z2.string(), z2.object({
294
+ default: z2.string().optional(),
295
+ small: z2.string().optional(),
296
+ agents: z2.record(z2.string(), AgentModelSchema).optional()
297
+ })).optional()
298
+ });
299
+ function parseModels(packDir, packName) {
300
+ const modelsPath = join2(packDir, "models.json");
301
+ const raw = readJsonOrNull(modelsPath);
302
+ if (!raw)
303
+ return null;
304
+ const parsed = ModelsSchema.parse(raw);
305
+ return {
306
+ packName,
307
+ sourcePath: modelsPath,
308
+ config: parsed
309
+ };
310
+ }
311
+ function mergeModelsConfigs(configs) {
312
+ const warnings = [];
313
+ const result = {};
314
+ for (const entry of configs) {
315
+ const { config, packName } = entry;
316
+ if (config.default !== undefined && result.default === undefined) {
317
+ result.default = config.default;
318
+ } else if (config.default !== undefined && result.default !== undefined) {
319
+ warnings.push(`Models "default" from pack "${packName}" skipped (already defined).`);
320
+ }
321
+ if (config.small !== undefined && result.small === undefined) {
322
+ result.small = config.small;
323
+ } else if (config.small !== undefined && result.small !== undefined) {
324
+ warnings.push(`Models "small" from pack "${packName}" skipped (already defined).`);
325
+ }
326
+ if (config.agents) {
327
+ if (!result.agents)
328
+ result.agents = {};
329
+ for (const [name, assignment] of Object.entries(config.agents)) {
330
+ if (name in result.agents) {
331
+ warnings.push(`Models agent "${name}" from pack "${packName}" skipped (already defined).`);
332
+ continue;
333
+ }
334
+ result.agents[name] = assignment;
335
+ }
336
+ }
337
+ if (config.profiles) {
338
+ if (!result.profiles)
339
+ result.profiles = {};
340
+ for (const [name, profile] of Object.entries(config.profiles)) {
341
+ if (name in result.profiles) {
342
+ warnings.push(`Models profile "${name}" from pack "${packName}" skipped (already defined).`);
343
+ continue;
344
+ }
345
+ result.profiles[name] = profile;
346
+ }
347
+ }
348
+ if (config.providers) {
349
+ if (!result.providers)
350
+ result.providers = {};
351
+ for (const [providerName, providerConfig] of Object.entries(config.providers)) {
352
+ if (!(providerName in result.providers)) {
353
+ result.providers[providerName] = providerConfig;
354
+ } else {
355
+ const existing = result.providers[providerName];
356
+ if (!existing) {
357
+ result.providers[providerName] = providerConfig;
358
+ continue;
359
+ }
360
+ if (providerConfig.options) {
361
+ existing.options = {
362
+ ...providerConfig.options,
363
+ ...existing.options
364
+ };
365
+ }
366
+ if (providerConfig.models) {
367
+ if (!existing.models)
368
+ existing.models = {};
369
+ for (const [modelName, modelConfig] of Object.entries(providerConfig.models)) {
370
+ if (!(modelName in existing.models)) {
371
+ existing.models[modelName] = modelConfig;
372
+ }
373
+ }
374
+ }
375
+ }
376
+ }
377
+ }
378
+ if (config.routing) {
379
+ if (!result.routing)
380
+ result.routing = [];
381
+ result.routing.push(...config.routing);
382
+ }
383
+ if (config.overrides) {
384
+ if (!result.overrides)
385
+ result.overrides = {};
386
+ for (const [targetId, override] of Object.entries(config.overrides)) {
387
+ if (targetId in result.overrides) {
388
+ warnings.push(`Models override for target "${targetId}" from pack "${packName}" skipped (already defined).`);
389
+ continue;
390
+ }
391
+ result.overrides[targetId] = override;
392
+ }
393
+ }
394
+ }
395
+ return { config: result, warnings };
396
+ }
397
+ function scanModelsForSecrets(config) {
398
+ const warnings = [];
399
+ const json = JSON.stringify(config);
400
+ for (const pattern of SECRET_PATTERNS) {
401
+ if (pattern.test(json)) {
402
+ warnings.push(`Potential secret detected in models.json matching pattern: ${pattern.source}`);
403
+ }
404
+ }
405
+ return warnings;
406
+ }
407
+
280
408
  // src/cli/pack/validate.ts
281
- init_config();
282
409
  import { existsSync as existsSync3 } from "fs";
283
- import { resolve as resolve3, join as join2 } from "path";
410
+ import { resolve as resolve2, join as join3 } from "path";
284
411
  import chalk from "chalk";
285
412
  function runPackValidate(projectRoot) {
286
413
  const config = loadWorkspaceConfig(projectRoot);
@@ -294,7 +421,7 @@ Validating pack: ${packRef}`));
294
421
  hasErrors = true;
295
422
  continue;
296
423
  }
297
- const packJsonPath = resolve3(packDir, "pack.json");
424
+ const packJsonPath = resolve2(packDir, "pack.json");
298
425
  if (!existsSync3(packJsonPath)) {
299
426
  console.log(chalk.yellow(" warn: No pack.json found. Name will be inferred from directory."));
300
427
  } else {
@@ -309,12 +436,12 @@ Validating pack: ${packRef}`));
309
436
  }
310
437
  const subdirs = ["rules", "commands", "agents", "skills"];
311
438
  for (const sub of subdirs) {
312
- const subDir = join2(packDir, sub);
439
+ const subDir = join3(packDir, sub);
313
440
  if (existsSync3(subDir)) {
314
441
  if (sub === "skills") {
315
442
  const skillDirs = listDirs(subDir);
316
443
  for (const skillDir of skillDirs) {
317
- const skillMd = join2(skillDir, "SKILL.md");
444
+ const skillMd = join3(skillDir, "SKILL.md");
318
445
  if (!existsSync3(skillMd)) {
319
446
  console.log(chalk.yellow(` warn: skills/${skillDir.split("/").pop()} missing SKILL.md`));
320
447
  }
@@ -328,15 +455,15 @@ Validating pack: ${packRef}`));
328
455
  }
329
456
  const optionalFiles = ["mcp.json", "ignore", ".aiignore"];
330
457
  for (const file of optionalFiles) {
331
- if (existsSync3(join2(packDir, file))) {
458
+ if (existsSync3(join3(packDir, file))) {
332
459
  console.log(chalk.green(` ${file}: present`));
333
460
  }
334
461
  }
335
- const hooksJson = join2(packDir, "hooks", "hooks.json");
462
+ const hooksJson = join3(packDir, "hooks", "hooks.json");
336
463
  if (existsSync3(hooksJson)) {
337
464
  console.log(chalk.green(" hooks/hooks.json: present"));
338
465
  }
339
- const pluginsDir = join2(packDir, "plugins");
466
+ const pluginsDir = join3(packDir, "plugins");
340
467
  if (existsSync3(pluginsDir)) {
341
468
  const pluginFiles = [
342
469
  ...listFiles(pluginsDir, { extension: ".ts" }),
@@ -344,6 +471,26 @@ Validating pack: ${packRef}`));
344
471
  ];
345
472
  console.log(chalk.green(` plugins/: ${pluginFiles.length} file(s)`));
346
473
  }
474
+ const modelsJsonPath = join3(packDir, "models.json");
475
+ if (existsSync3(modelsJsonPath)) {
476
+ try {
477
+ const parsed = parseModels(packDir, "validate");
478
+ if (parsed) {
479
+ console.log(chalk.green(" models.json: valid"));
480
+ const secretWarnings = scanModelsForSecrets(parsed.config);
481
+ if (secretWarnings.length > 0) {
482
+ for (const w of secretWarnings) {
483
+ console.log(chalk.red(` ERROR models.json: ${w}`));
484
+ }
485
+ hasErrors = true;
486
+ }
487
+ }
488
+ } catch (err) {
489
+ const message = err instanceof Error ? err.message : String(err);
490
+ console.log(chalk.red(` ERROR models.json: ${message}`));
491
+ hasErrors = true;
492
+ }
493
+ }
347
494
  }
348
495
  console.log();
349
496
  if (hasErrors) {
@@ -355,9 +502,9 @@ Validating pack: ${packRef}`));
355
502
  }
356
503
  function resolvePackDir(projectRoot, packRef) {
357
504
  if (packRef.startsWith("./") || packRef.startsWith("../")) {
358
- return resolve3(projectRoot, packRef);
505
+ return resolve2(projectRoot, packRef);
359
506
  }
360
- return resolve3(projectRoot, packRef);
507
+ return resolve2(projectRoot, packRef);
361
508
  }
362
509
  export {
363
510
  runPackValidate