agentpacks 1.7.6 → 1.7.8

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 (133) hide show
  1. package/README.md +69 -742
  2. package/dist/api.d.ts +15 -15
  3. package/dist/api.js +2706 -2706
  4. package/dist/cli/export-cmd.js +364 -364
  5. package/dist/cli/generate.js +1409 -1409
  6. package/dist/cli/import-cmd.js +249 -249
  7. package/dist/cli/info.js +31 -31
  8. package/dist/cli/init.js +6 -6
  9. package/dist/cli/install.js +141 -141
  10. package/dist/cli/login.js +31 -31
  11. package/dist/cli/models-explain.js +514 -514
  12. package/dist/cli/pack/create.js +6 -6
  13. package/dist/cli/pack/enable.js +2 -2
  14. package/dist/cli/pack/list.js +362 -362
  15. package/dist/cli/pack/validate.js +119 -119
  16. package/dist/cli/publish.js +42 -42
  17. package/dist/cli/search.js +31 -31
  18. package/dist/core/config.js +3 -3
  19. package/dist/core/feature-merger.d.ts +5 -5
  20. package/dist/core/feature-merger.js +4 -4
  21. package/dist/core/index.d.ts +4 -4
  22. package/dist/core/index.js +633 -633
  23. package/dist/core/lockfile.js +1 -1
  24. package/dist/core/metarepo.js +3 -3
  25. package/dist/core/pack-loader.d.ts +6 -6
  26. package/dist/core/pack-loader.js +362 -362
  27. package/dist/core/profile-resolver.d.ts +1 -1
  28. package/dist/exporters/cursor-plugin.d.ts +12 -0
  29. package/dist/exporters/cursor-plugin.js +46 -46
  30. package/dist/exporters/index.d.ts +1 -1
  31. package/dist/exporters/index.js +46 -46
  32. package/dist/features/agents.js +4 -4
  33. package/dist/features/commands.js +4 -4
  34. package/dist/features/hooks.js +4 -4
  35. package/dist/features/index.d.ts +8 -8
  36. package/dist/features/index.js +350 -350
  37. package/dist/features/mcp.js +4 -4
  38. package/dist/features/models.js +4 -4
  39. package/dist/features/plugins.js +5 -5
  40. package/dist/features/rules.js +4 -4
  41. package/dist/features/skills.js +5 -5
  42. package/dist/importers/claude-code.js +6 -6
  43. package/dist/importers/cursor.js +7 -7
  44. package/dist/importers/opencode.js +7 -7
  45. package/dist/importers/rulesync.js +7 -7
  46. package/dist/index.js +2674 -2674
  47. package/dist/node/api.js +2706 -2706
  48. package/dist/node/cli/export-cmd.js +364 -364
  49. package/dist/node/cli/generate.js +1409 -1409
  50. package/dist/node/cli/import-cmd.js +249 -249
  51. package/dist/node/cli/info.js +31 -31
  52. package/dist/node/cli/init.js +6 -6
  53. package/dist/node/cli/install.js +141 -141
  54. package/dist/node/cli/login.js +31 -31
  55. package/dist/node/cli/models-explain.js +514 -514
  56. package/dist/node/cli/pack/create.js +6 -6
  57. package/dist/node/cli/pack/enable.js +2 -2
  58. package/dist/node/cli/pack/list.js +362 -362
  59. package/dist/node/cli/pack/validate.js +119 -119
  60. package/dist/node/cli/publish.js +42 -42
  61. package/dist/node/cli/search.js +31 -31
  62. package/dist/node/core/config.js +3 -3
  63. package/dist/node/core/feature-merger.js +4 -4
  64. package/dist/node/core/index.js +633 -633
  65. package/dist/node/core/lockfile.js +1 -1
  66. package/dist/node/core/metarepo.js +3 -3
  67. package/dist/node/core/pack-loader.js +362 -362
  68. package/dist/node/exporters/cursor-plugin.js +46 -46
  69. package/dist/node/exporters/index.js +46 -46
  70. package/dist/node/features/agents.js +4 -4
  71. package/dist/node/features/commands.js +4 -4
  72. package/dist/node/features/hooks.js +4 -4
  73. package/dist/node/features/index.js +350 -350
  74. package/dist/node/features/mcp.js +4 -4
  75. package/dist/node/features/models.js +4 -4
  76. package/dist/node/features/plugins.js +5 -5
  77. package/dist/node/features/rules.js +4 -4
  78. package/dist/node/features/skills.js +5 -5
  79. package/dist/node/importers/claude-code.js +6 -6
  80. package/dist/node/importers/cursor.js +7 -7
  81. package/dist/node/importers/opencode.js +7 -7
  82. package/dist/node/importers/rulesync.js +7 -7
  83. package/dist/node/index.js +2674 -2674
  84. package/dist/node/sources/git.js +2 -2
  85. package/dist/node/sources/index.js +138 -138
  86. package/dist/node/sources/local.js +1 -1
  87. package/dist/node/sources/npm.js +3 -3
  88. package/dist/node/sources/registry.js +35 -35
  89. package/dist/node/targets/additional-targets.js +43 -43
  90. package/dist/node/targets/agents-md.js +4 -4
  91. package/dist/node/targets/claude-code.js +86 -86
  92. package/dist/node/targets/codex-cli.js +6 -6
  93. package/dist/node/targets/copilot.js +46 -46
  94. package/dist/node/targets/cursor.js +68 -68
  95. package/dist/node/targets/gemini-cli.js +25 -25
  96. package/dist/node/targets/generic-md-target.js +43 -43
  97. package/dist/node/targets/index.js +911 -911
  98. package/dist/node/targets/mistral-vibe.js +46 -46
  99. package/dist/node/targets/opencode.js +68 -68
  100. package/dist/node/targets/registry.js +911 -911
  101. package/dist/node/utils/credentials.js +2 -2
  102. package/dist/node/utils/filesystem.js +4 -4
  103. package/dist/node/utils/global.js +1 -1
  104. package/dist/node/utils/tarball.js +2 -2
  105. package/dist/sources/git.js +2 -2
  106. package/dist/sources/index.d.ts +6 -6
  107. package/dist/sources/index.js +138 -138
  108. package/dist/sources/local.js +1 -1
  109. package/dist/sources/npm.d.ts +3 -0
  110. package/dist/sources/npm.js +3 -3
  111. package/dist/sources/registry.js +35 -35
  112. package/dist/targets/additional-targets.js +43 -43
  113. package/dist/targets/agents-md.js +4 -4
  114. package/dist/targets/claude-code.js +86 -86
  115. package/dist/targets/codex-cli.js +6 -6
  116. package/dist/targets/copilot.js +46 -46
  117. package/dist/targets/cursor.js +68 -68
  118. package/dist/targets/gemini-cli.js +25 -25
  119. package/dist/targets/generic-md-target.js +43 -43
  120. package/dist/targets/index.d.ts +6 -6
  121. package/dist/targets/index.js +911 -911
  122. package/dist/targets/mistral-vibe.js +46 -46
  123. package/dist/targets/opencode.js +68 -68
  124. package/dist/targets/registry.js +911 -911
  125. package/dist/utils/credentials.js +2 -2
  126. package/dist/utils/filesystem.js +4 -4
  127. package/dist/utils/global.d.ts +3 -0
  128. package/dist/utils/global.js +1 -1
  129. package/dist/utils/tarball.js +2 -2
  130. package/package.json +5 -5
  131. package/templates/pack/models.json +36 -36
  132. package/templates/pack/pack.json +8 -8
  133. package/templates/workspace/agentpacks.jsonc +24 -24
@@ -2,10 +2,10 @@
2
2
  var __require = import.meta.require;
3
3
 
4
4
  // src/core/config.ts
5
- import { z } from "zod";
6
- import { readFileSync, existsSync } from "fs";
7
- import { resolve } from "path";
5
+ import { existsSync, readFileSync } from "fs";
8
6
  import { parse as parseJsonc } from "jsonc-parser";
7
+ import { resolve } from "path";
8
+ import { z } from "zod";
9
9
  var TARGET_IDS = [
10
10
  "opencode",
11
11
  "cursor",
@@ -138,13 +138,13 @@ function resolveTargets(config) {
138
138
  import {
139
139
  existsSync as existsSync2,
140
140
  mkdirSync,
141
- readFileSync as readFileSync2,
142
- writeFileSync,
143
141
  readdirSync,
142
+ readFileSync as readFileSync2,
144
143
  rmSync,
145
- statSync
144
+ statSync,
145
+ writeFileSync
146
146
  } from "fs";
147
- import { dirname, relative, join } from "path";
147
+ import { dirname, join, relative } from "path";
148
148
  var GENERATED_HEADER_MD = "<!-- Generated by agentpacks. DO NOT EDIT. -->";
149
149
  var GENERATED_HEADER_JSON = "// Generated by agentpacks. DO NOT EDIT.";
150
150
  var GENERATED_HEADER_JS = "// Generated by agentpacks. DO NOT EDIT.";
@@ -244,6 +244,175 @@ function getHeader(type) {
244
244
  }
245
245
  }
246
246
 
247
+ // src/features/models.ts
248
+ import { join as join2 } from "path";
249
+ import { z as z2 } from "zod";
250
+ var SECRET_PATTERNS = [
251
+ /["']api[_-]?key["']\s*:/i,
252
+ /["']apiKey["']\s*:/i,
253
+ /["']secret["']\s*:/i,
254
+ /["']password["']\s*:/i,
255
+ /["'](?:auth_token|access_token|bearer_token)["']\s*:/i,
256
+ /["']private[_-]?key["']\s*:/i,
257
+ /-----BEGIN\s+(RSA|EC|DSA|OPENSSH|PGP)\s+PRIVATE\s+KEY-----/,
258
+ /sk-[a-zA-Z0-9]{20,}/,
259
+ /Bearer\s+[a-zA-Z0-9._-]{20,}/
260
+ ];
261
+ var AgentModelSchema = z2.object({
262
+ model: z2.string(),
263
+ temperature: z2.number().min(0).max(2).optional(),
264
+ top_p: z2.number().min(0).max(1).optional()
265
+ });
266
+ var ModelProfileSchema = z2.object({
267
+ extends: z2.string().optional(),
268
+ description: z2.string().optional(),
269
+ default: z2.string().optional(),
270
+ small: z2.string().optional(),
271
+ agents: z2.record(z2.string(), AgentModelSchema).optional()
272
+ });
273
+ var RoutingConditionSchema = z2.object({
274
+ complexity: z2.enum(["low", "medium", "high", "critical"]).optional().describe("Task complexity level"),
275
+ urgency: z2.enum(["low", "normal", "high"]).optional().describe("Time sensitivity"),
276
+ budget: z2.enum(["minimal", "standard", "premium"]).optional().describe("Cost/token budget tier"),
277
+ contextWindowNeed: z2.enum(["small", "medium", "large", "max"]).optional().describe("Required context window size"),
278
+ toolUseIntensity: z2.enum(["none", "light", "heavy"]).optional().describe("Expected tool/function calling intensity")
279
+ });
280
+ var RoutingRuleSchema = z2.object({
281
+ when: z2.record(z2.string(), z2.string()),
282
+ use: z2.string(),
283
+ description: z2.string().optional(),
284
+ priority: z2.number().optional()
285
+ });
286
+ var ProviderModelSchema = z2.object({
287
+ options: z2.record(z2.string(), z2.unknown()).optional(),
288
+ variants: z2.record(z2.string(), z2.record(z2.string(), z2.unknown())).optional()
289
+ });
290
+ var ProviderConfigSchema = z2.object({
291
+ options: z2.record(z2.string(), z2.unknown()).optional(),
292
+ models: z2.record(z2.string(), ProviderModelSchema).optional()
293
+ });
294
+ var ModelsSchema = z2.object({
295
+ default: z2.string().optional(),
296
+ small: z2.string().optional(),
297
+ agents: z2.record(z2.string(), AgentModelSchema).optional(),
298
+ profiles: z2.record(z2.string(), ModelProfileSchema).optional(),
299
+ providers: z2.record(z2.string(), ProviderConfigSchema).optional(),
300
+ routing: z2.array(RoutingRuleSchema).optional(),
301
+ overrides: z2.record(z2.string(), z2.object({
302
+ default: z2.string().optional(),
303
+ small: z2.string().optional(),
304
+ agents: z2.record(z2.string(), AgentModelSchema).optional()
305
+ })).optional()
306
+ });
307
+ function parseModels(packDir, packName) {
308
+ const modelsPath = join2(packDir, "models.json");
309
+ const raw = readJsonOrNull(modelsPath);
310
+ if (!raw)
311
+ return null;
312
+ const parsed = ModelsSchema.parse(raw);
313
+ return {
314
+ packName,
315
+ sourcePath: modelsPath,
316
+ config: parsed
317
+ };
318
+ }
319
+ function mergeModelsConfigs(configs) {
320
+ const warnings = [];
321
+ const result = {};
322
+ for (const entry of configs) {
323
+ const { config, packName } = entry;
324
+ if (config.default !== undefined && result.default === undefined) {
325
+ result.default = config.default;
326
+ } else if (config.default !== undefined && result.default !== undefined) {
327
+ warnings.push(`Models "default" from pack "${packName}" skipped (already defined).`);
328
+ }
329
+ if (config.small !== undefined && result.small === undefined) {
330
+ result.small = config.small;
331
+ } else if (config.small !== undefined && result.small !== undefined) {
332
+ warnings.push(`Models "small" from pack "${packName}" skipped (already defined).`);
333
+ }
334
+ if (config.agents) {
335
+ if (!result.agents)
336
+ result.agents = {};
337
+ for (const [name, assignment] of Object.entries(config.agents)) {
338
+ if (name in result.agents) {
339
+ warnings.push(`Models agent "${name}" from pack "${packName}" skipped (already defined).`);
340
+ continue;
341
+ }
342
+ result.agents[name] = assignment;
343
+ }
344
+ }
345
+ if (config.profiles) {
346
+ if (!result.profiles)
347
+ result.profiles = {};
348
+ for (const [name, profile] of Object.entries(config.profiles)) {
349
+ if (name in result.profiles) {
350
+ warnings.push(`Models profile "${name}" from pack "${packName}" skipped (already defined).`);
351
+ continue;
352
+ }
353
+ result.profiles[name] = profile;
354
+ }
355
+ }
356
+ if (config.providers) {
357
+ if (!result.providers)
358
+ result.providers = {};
359
+ for (const [providerName, providerConfig] of Object.entries(config.providers)) {
360
+ if (!(providerName in result.providers)) {
361
+ result.providers[providerName] = providerConfig;
362
+ } else {
363
+ const existing = result.providers[providerName];
364
+ if (!existing) {
365
+ result.providers[providerName] = providerConfig;
366
+ continue;
367
+ }
368
+ if (providerConfig.options) {
369
+ existing.options = {
370
+ ...providerConfig.options,
371
+ ...existing.options
372
+ };
373
+ }
374
+ if (providerConfig.models) {
375
+ if (!existing.models)
376
+ existing.models = {};
377
+ for (const [modelName, modelConfig] of Object.entries(providerConfig.models)) {
378
+ if (!(modelName in existing.models)) {
379
+ existing.models[modelName] = modelConfig;
380
+ }
381
+ }
382
+ }
383
+ }
384
+ }
385
+ }
386
+ if (config.routing) {
387
+ if (!result.routing)
388
+ result.routing = [];
389
+ result.routing.push(...config.routing);
390
+ }
391
+ if (config.overrides) {
392
+ if (!result.overrides)
393
+ result.overrides = {};
394
+ for (const [targetId, override] of Object.entries(config.overrides)) {
395
+ if (targetId in result.overrides) {
396
+ warnings.push(`Models override for target "${targetId}" from pack "${packName}" skipped (already defined).`);
397
+ continue;
398
+ }
399
+ result.overrides[targetId] = override;
400
+ }
401
+ }
402
+ }
403
+ return { config: result, warnings };
404
+ }
405
+ function scanModelsForSecrets(config) {
406
+ const warnings = [];
407
+ const json = JSON.stringify(config);
408
+ for (const pattern of SECRET_PATTERNS) {
409
+ if (pattern.test(json)) {
410
+ warnings.push(`Potential secret detected in models.json matching pattern: ${pattern.source}`);
411
+ }
412
+ }
413
+ return warnings;
414
+ }
415
+
247
416
  // src/utils/frontmatter.ts
248
417
  import matter from "gray-matter";
249
418
  function parseFrontmatter(source) {
@@ -262,38 +431,32 @@ function serializeFrontmatter(data, content) {
262
431
  return matter.stringify(content, filtered);
263
432
  }
264
433
 
265
- // src/features/rules.ts
434
+ // src/features/agents.ts
266
435
  import { readFileSync as readFileSync3 } from "fs";
267
436
  import { basename } from "path";
268
- function parseRules(rulesDir, packName) {
269
- const files = listFiles(rulesDir, { extension: ".md" });
270
- return files.map((filepath) => parseRuleFile(filepath, packName));
437
+ function parseAgents(agentsDir, packName) {
438
+ const files = listFiles(agentsDir, { extension: ".md" });
439
+ return files.map((filepath) => parseAgentFile(filepath, packName));
271
440
  }
272
- function parseRuleFile(filepath, packName) {
441
+ function parseAgentFile(filepath, packName) {
273
442
  const raw = readFileSync3(filepath, "utf-8");
274
443
  const { data, content } = parseFrontmatter(raw);
275
444
  return {
276
- name: basename(filepath, ".md"),
445
+ name: data.name ?? basename(filepath, ".md"),
277
446
  sourcePath: filepath,
278
447
  packName,
279
448
  meta: data,
280
449
  content
281
450
  };
282
451
  }
283
- function ruleMatchesTarget(rule, targetId) {
284
- const { targets } = rule.meta;
452
+ function agentMatchesTarget(agent, targetId) {
453
+ const { targets } = agent.meta;
285
454
  if (!targets || targets === "*")
286
455
  return true;
287
456
  if (Array.isArray(targets) && targets.includes("*"))
288
457
  return true;
289
458
  return Array.isArray(targets) && targets.includes(targetId);
290
459
  }
291
- function getRootRules(rules) {
292
- return rules.filter((r) => r.meta.root === true);
293
- }
294
- function getDetailRules(rules) {
295
- return rules.filter((r) => r.meta.root !== true);
296
- }
297
460
 
298
461
  // src/features/commands.ts
299
462
  import { readFileSync as readFileSync4 } from "fs";
@@ -322,56 +485,189 @@ function commandMatchesTarget(cmd, targetId) {
322
485
  return Array.isArray(targets) && targets.includes(targetId);
323
486
  }
324
487
 
325
- // src/features/agents.ts
326
- import { readFileSync as readFileSync5 } from "fs";
327
- import { basename as basename3 } from "path";
328
- function parseAgents(agentsDir, packName) {
329
- const files = listFiles(agentsDir, { extension: ".md" });
330
- return files.map((filepath) => parseAgentFile(filepath, packName));
331
- }
332
- function parseAgentFile(filepath, packName) {
333
- const raw = readFileSync5(filepath, "utf-8");
334
- const { data, content } = parseFrontmatter(raw);
488
+ // src/features/hooks.ts
489
+ import { join as join3 } from "path";
490
+ var TARGET_OVERRIDE_KEYS = ["cursor", "claudecode", "opencode"];
491
+ function parseHooks(packDir, packName) {
492
+ const hooksPath = join3(packDir, "hooks", "hooks.json");
493
+ const raw = readJsonOrNull(hooksPath);
494
+ if (!raw)
495
+ return null;
496
+ const shared = raw.hooks ?? {};
497
+ const targetOverrides = {};
498
+ for (const key of TARGET_OVERRIDE_KEYS) {
499
+ const override = raw[key];
500
+ if (override && typeof override === "object" && "hooks" in override && override.hooks) {
501
+ targetOverrides[key] = override.hooks;
502
+ }
503
+ }
335
504
  return {
336
- name: data.name ?? basename3(filepath, ".md"),
337
- sourcePath: filepath,
338
505
  packName,
339
- meta: data,
340
- content
506
+ sourcePath: hooksPath,
507
+ version: raw.version,
508
+ shared,
509
+ targetOverrides
341
510
  };
342
511
  }
343
- function agentMatchesTarget(agent, targetId) {
344
- const { targets } = agent.meta;
345
- if (!targets || targets === "*")
346
- return true;
347
- if (Array.isArray(targets) && targets.includes("*"))
348
- return true;
349
- return Array.isArray(targets) && targets.includes(targetId);
350
- }
351
-
352
- // src/features/skills.ts
353
- import { readFileSync as readFileSync6, existsSync as existsSync3 } from "fs";
354
- import { basename as basename4, join as join2 } from "path";
355
- var SKILL_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
356
- var SKILL_NAME_MAX_LENGTH = 64;
357
- function parseSkills(skillsDir, packName) {
358
- const dirs = listDirs(skillsDir);
359
- const skills = [];
360
- for (const dir of dirs) {
361
- const skillMd = join2(dir, "SKILL.md");
362
- if (existsSync3(skillMd)) {
363
- skills.push(parseSkillFile(skillMd, dir, packName));
512
+ function resolveHooksForTarget(hooks, targetId) {
513
+ const merged = {};
514
+ for (const [event, entries] of Object.entries(hooks.shared)) {
515
+ merged[event] = [...entries];
516
+ }
517
+ const overrides = hooks.targetOverrides[targetId];
518
+ if (overrides) {
519
+ for (const [event, entries] of Object.entries(overrides)) {
520
+ merged[event] = [...merged[event] ?? [], ...entries];
364
521
  }
365
522
  }
366
- return skills;
523
+ return merged;
367
524
  }
368
- function parseSkillFile(filepath, skillDir, packName) {
369
- const raw = readFileSync6(filepath, "utf-8");
370
- const { data, content } = parseFrontmatter(raw);
371
- return {
372
- name: data.name ?? basename4(skillDir),
373
- sourcePath: filepath,
374
- sourceDir: skillDir,
525
+
526
+ // src/features/ignore.ts
527
+ import { existsSync as existsSync3, readFileSync as readFileSync5 } from "fs";
528
+ import { join as join4 } from "path";
529
+ var IGNORE_FILES = ["ignore", ".aiignore"];
530
+ function parseIgnore(packDir, packName) {
531
+ for (const filename of IGNORE_FILES) {
532
+ const filepath = join4(packDir, filename);
533
+ if (existsSync3(filepath)) {
534
+ const raw = readFileSync5(filepath, "utf-8");
535
+ const patterns = parseIgnoreContent(raw);
536
+ return {
537
+ packName,
538
+ sourcePath: filepath,
539
+ patterns
540
+ };
541
+ }
542
+ }
543
+ return null;
544
+ }
545
+ function parseIgnoreContent(content) {
546
+ return content.split(`
547
+ `).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
548
+ }
549
+ function mergeIgnorePatterns(configs) {
550
+ const seen = new Set;
551
+ const result = [];
552
+ for (const config of configs) {
553
+ for (const pattern of config.patterns) {
554
+ if (!seen.has(pattern)) {
555
+ seen.add(pattern);
556
+ result.push(pattern);
557
+ }
558
+ }
559
+ }
560
+ return result;
561
+ }
562
+
563
+ // src/features/mcp.ts
564
+ import { join as join5 } from "path";
565
+ function parseMcp(packDir, packName) {
566
+ const mcpPath = join5(packDir, "mcp.json");
567
+ const raw = readJsonOrNull(mcpPath);
568
+ if (!raw?.mcpServers)
569
+ return null;
570
+ return {
571
+ packName,
572
+ sourcePath: mcpPath,
573
+ servers: raw.mcpServers
574
+ };
575
+ }
576
+ function mergeMcpConfigs(configs) {
577
+ const servers = {};
578
+ const warnings = [];
579
+ for (const config of configs) {
580
+ for (const [name, entry] of Object.entries(config.servers)) {
581
+ if (name in servers) {
582
+ warnings.push(`MCP server "${name}" from pack "${config.packName}" skipped (already defined).`);
583
+ continue;
584
+ }
585
+ servers[name] = entry;
586
+ }
587
+ }
588
+ return { servers, warnings };
589
+ }
590
+
591
+ // src/features/plugins.ts
592
+ import { existsSync as existsSync4, readFileSync as readFileSync6 } from "fs";
593
+ import { basename as basename3, join as join6 } from "path";
594
+ function parsePlugins(packDir, packName) {
595
+ const pluginsDir = join6(packDir, "plugins");
596
+ if (!existsSync4(pluginsDir))
597
+ return [];
598
+ const tsFiles = listFiles(pluginsDir, { extension: ".ts" });
599
+ const jsFiles = listFiles(pluginsDir, { extension: ".js" });
600
+ const allFiles = [...tsFiles, ...jsFiles];
601
+ return allFiles.map((filepath) => parsePluginFile(filepath, packName));
602
+ }
603
+ function parsePluginFile(filepath, packName) {
604
+ const content = readFileSync6(filepath, "utf-8");
605
+ const ext = filepath.endsWith(".ts") ? "ts" : "js";
606
+ return {
607
+ name: basename3(filepath, `.${ext}`),
608
+ sourcePath: filepath,
609
+ packName,
610
+ content,
611
+ extension: ext
612
+ };
613
+ }
614
+
615
+ // src/features/rules.ts
616
+ import { readFileSync as readFileSync7 } from "fs";
617
+ import { basename as basename4 } from "path";
618
+ function parseRules(rulesDir, packName) {
619
+ const files = listFiles(rulesDir, { extension: ".md" });
620
+ return files.map((filepath) => parseRuleFile(filepath, packName));
621
+ }
622
+ function parseRuleFile(filepath, packName) {
623
+ const raw = readFileSync7(filepath, "utf-8");
624
+ const { data, content } = parseFrontmatter(raw);
625
+ return {
626
+ name: basename4(filepath, ".md"),
627
+ sourcePath: filepath,
628
+ packName,
629
+ meta: data,
630
+ content
631
+ };
632
+ }
633
+ function ruleMatchesTarget(rule, targetId) {
634
+ const { targets } = rule.meta;
635
+ if (!targets || targets === "*")
636
+ return true;
637
+ if (Array.isArray(targets) && targets.includes("*"))
638
+ return true;
639
+ return Array.isArray(targets) && targets.includes(targetId);
640
+ }
641
+ function getRootRules(rules) {
642
+ return rules.filter((r) => r.meta.root === true);
643
+ }
644
+ function getDetailRules(rules) {
645
+ return rules.filter((r) => r.meta.root !== true);
646
+ }
647
+
648
+ // src/features/skills.ts
649
+ import { existsSync as existsSync5, readFileSync as readFileSync8 } from "fs";
650
+ import { basename as basename5, join as join7 } from "path";
651
+ var SKILL_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
652
+ var SKILL_NAME_MAX_LENGTH = 64;
653
+ function parseSkills(skillsDir, packName) {
654
+ const dirs = listDirs(skillsDir);
655
+ const skills = [];
656
+ for (const dir of dirs) {
657
+ const skillMd = join7(dir, "SKILL.md");
658
+ if (existsSync5(skillMd)) {
659
+ skills.push(parseSkillFile(skillMd, dir, packName));
660
+ }
661
+ }
662
+ return skills;
663
+ }
664
+ function parseSkillFile(filepath, skillDir, packName) {
665
+ const raw = readFileSync8(filepath, "utf-8");
666
+ const { data, content } = parseFrontmatter(raw);
667
+ return {
668
+ name: data.name ?? basename5(skillDir),
669
+ sourcePath: filepath,
670
+ sourceDir: skillDir,
375
671
  packName,
376
672
  meta: data,
377
673
  content
@@ -405,7 +701,7 @@ function normalizeImportedSkillMarkdown(source, skillName) {
405
701
  }
406
702
  function validateAgentSkillsFrontmatter(skill) {
407
703
  const errors = [];
408
- const dirName = basename4(skill.sourceDir);
704
+ const dirName = basename5(skill.sourceDir);
409
705
  const declaredName = skill.meta.name;
410
706
  if (typeof declaredName !== "string" || declaredName.trim().length === 0) {
411
707
  errors.push('Missing required frontmatter field "name".');
@@ -439,305 +735,9 @@ function skillMatchesTarget(skill, targetId) {
439
735
  return Array.isArray(targets) && targets.includes(targetId);
440
736
  }
441
737
 
442
- // src/features/hooks.ts
443
- import { join as join3 } from "path";
444
- var TARGET_OVERRIDE_KEYS = ["cursor", "claudecode", "opencode"];
445
- function parseHooks(packDir, packName) {
446
- const hooksPath = join3(packDir, "hooks", "hooks.json");
447
- const raw = readJsonOrNull(hooksPath);
448
- if (!raw)
449
- return null;
450
- const shared = raw.hooks ?? {};
451
- const targetOverrides = {};
452
- for (const key of TARGET_OVERRIDE_KEYS) {
453
- const override = raw[key];
454
- if (override && typeof override === "object" && "hooks" in override && override.hooks) {
455
- targetOverrides[key] = override.hooks;
456
- }
457
- }
458
- return {
459
- packName,
460
- sourcePath: hooksPath,
461
- version: raw.version,
462
- shared,
463
- targetOverrides
464
- };
465
- }
466
- function resolveHooksForTarget(hooks, targetId) {
467
- const merged = {};
468
- for (const [event, entries] of Object.entries(hooks.shared)) {
469
- merged[event] = [...entries];
470
- }
471
- const overrides = hooks.targetOverrides[targetId];
472
- if (overrides) {
473
- for (const [event, entries] of Object.entries(overrides)) {
474
- merged[event] = [...merged[event] ?? [], ...entries];
475
- }
476
- }
477
- return merged;
478
- }
479
-
480
- // src/features/plugins.ts
481
- import { readFileSync as readFileSync7, existsSync as existsSync4 } from "fs";
482
- import { basename as basename5, join as join4 } from "path";
483
- function parsePlugins(packDir, packName) {
484
- const pluginsDir = join4(packDir, "plugins");
485
- if (!existsSync4(pluginsDir))
486
- return [];
487
- const tsFiles = listFiles(pluginsDir, { extension: ".ts" });
488
- const jsFiles = listFiles(pluginsDir, { extension: ".js" });
489
- const allFiles = [...tsFiles, ...jsFiles];
490
- return allFiles.map((filepath) => parsePluginFile(filepath, packName));
491
- }
492
- function parsePluginFile(filepath, packName) {
493
- const content = readFileSync7(filepath, "utf-8");
494
- const ext = filepath.endsWith(".ts") ? "ts" : "js";
495
- return {
496
- name: basename5(filepath, `.${ext}`),
497
- sourcePath: filepath,
498
- packName,
499
- content,
500
- extension: ext
501
- };
502
- }
503
-
504
- // src/features/mcp.ts
505
- import { join as join5 } from "path";
506
- function parseMcp(packDir, packName) {
507
- const mcpPath = join5(packDir, "mcp.json");
508
- const raw = readJsonOrNull(mcpPath);
509
- if (!raw?.mcpServers)
510
- return null;
511
- return {
512
- packName,
513
- sourcePath: mcpPath,
514
- servers: raw.mcpServers
515
- };
516
- }
517
- function mergeMcpConfigs(configs) {
518
- const servers = {};
519
- const warnings = [];
520
- for (const config of configs) {
521
- for (const [name, entry] of Object.entries(config.servers)) {
522
- if (name in servers) {
523
- warnings.push(`MCP server "${name}" from pack "${config.packName}" skipped (already defined).`);
524
- continue;
525
- }
526
- servers[name] = entry;
527
- }
528
- }
529
- return { servers, warnings };
530
- }
531
-
532
- // src/features/ignore.ts
533
- import { existsSync as existsSync5, readFileSync as readFileSync8 } from "fs";
534
- import { join as join6 } from "path";
535
- var IGNORE_FILES = ["ignore", ".aiignore"];
536
- function parseIgnore(packDir, packName) {
537
- for (const filename of IGNORE_FILES) {
538
- const filepath = join6(packDir, filename);
539
- if (existsSync5(filepath)) {
540
- const raw = readFileSync8(filepath, "utf-8");
541
- const patterns = parseIgnoreContent(raw);
542
- return {
543
- packName,
544
- sourcePath: filepath,
545
- patterns
546
- };
547
- }
548
- }
549
- return null;
550
- }
551
- function parseIgnoreContent(content) {
552
- return content.split(`
553
- `).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
554
- }
555
- function mergeIgnorePatterns(configs) {
556
- const seen = new Set;
557
- const result = [];
558
- for (const config of configs) {
559
- for (const pattern of config.patterns) {
560
- if (!seen.has(pattern)) {
561
- seen.add(pattern);
562
- result.push(pattern);
563
- }
564
- }
565
- }
566
- return result;
567
- }
568
-
569
- // src/features/models.ts
570
- import { join as join7 } from "path";
571
- import { z as z2 } from "zod";
572
- var SECRET_PATTERNS = [
573
- /["']api[_-]?key["']\s*:/i,
574
- /["']apiKey["']\s*:/i,
575
- /["']secret["']\s*:/i,
576
- /["']password["']\s*:/i,
577
- /["'](?:auth_token|access_token|bearer_token)["']\s*:/i,
578
- /["']private[_-]?key["']\s*:/i,
579
- /-----BEGIN\s+(RSA|EC|DSA|OPENSSH|PGP)\s+PRIVATE\s+KEY-----/,
580
- /sk-[a-zA-Z0-9]{20,}/,
581
- /Bearer\s+[a-zA-Z0-9._-]{20,}/
582
- ];
583
- var AgentModelSchema = z2.object({
584
- model: z2.string(),
585
- temperature: z2.number().min(0).max(2).optional(),
586
- top_p: z2.number().min(0).max(1).optional()
587
- });
588
- var ModelProfileSchema = z2.object({
589
- extends: z2.string().optional(),
590
- description: z2.string().optional(),
591
- default: z2.string().optional(),
592
- small: z2.string().optional(),
593
- agents: z2.record(z2.string(), AgentModelSchema).optional()
594
- });
595
- var RoutingConditionSchema = z2.object({
596
- complexity: z2.enum(["low", "medium", "high", "critical"]).optional().describe("Task complexity level"),
597
- urgency: z2.enum(["low", "normal", "high"]).optional().describe("Time sensitivity"),
598
- budget: z2.enum(["minimal", "standard", "premium"]).optional().describe("Cost/token budget tier"),
599
- contextWindowNeed: z2.enum(["small", "medium", "large", "max"]).optional().describe("Required context window size"),
600
- toolUseIntensity: z2.enum(["none", "light", "heavy"]).optional().describe("Expected tool/function calling intensity")
601
- });
602
- var RoutingRuleSchema = z2.object({
603
- when: z2.record(z2.string(), z2.string()),
604
- use: z2.string(),
605
- description: z2.string().optional(),
606
- priority: z2.number().optional()
607
- });
608
- var ProviderModelSchema = z2.object({
609
- options: z2.record(z2.string(), z2.unknown()).optional(),
610
- variants: z2.record(z2.string(), z2.record(z2.string(), z2.unknown())).optional()
611
- });
612
- var ProviderConfigSchema = z2.object({
613
- options: z2.record(z2.string(), z2.unknown()).optional(),
614
- models: z2.record(z2.string(), ProviderModelSchema).optional()
615
- });
616
- var ModelsSchema = z2.object({
617
- default: z2.string().optional(),
618
- small: z2.string().optional(),
619
- agents: z2.record(z2.string(), AgentModelSchema).optional(),
620
- profiles: z2.record(z2.string(), ModelProfileSchema).optional(),
621
- providers: z2.record(z2.string(), ProviderConfigSchema).optional(),
622
- routing: z2.array(RoutingRuleSchema).optional(),
623
- overrides: z2.record(z2.string(), z2.object({
624
- default: z2.string().optional(),
625
- small: z2.string().optional(),
626
- agents: z2.record(z2.string(), AgentModelSchema).optional()
627
- })).optional()
628
- });
629
- function parseModels(packDir, packName) {
630
- const modelsPath = join7(packDir, "models.json");
631
- const raw = readJsonOrNull(modelsPath);
632
- if (!raw)
633
- return null;
634
- const parsed = ModelsSchema.parse(raw);
635
- return {
636
- packName,
637
- sourcePath: modelsPath,
638
- config: parsed
639
- };
640
- }
641
- function mergeModelsConfigs(configs) {
642
- const warnings = [];
643
- const result = {};
644
- for (const entry of configs) {
645
- const { config, packName } = entry;
646
- if (config.default !== undefined && result.default === undefined) {
647
- result.default = config.default;
648
- } else if (config.default !== undefined && result.default !== undefined) {
649
- warnings.push(`Models "default" from pack "${packName}" skipped (already defined).`);
650
- }
651
- if (config.small !== undefined && result.small === undefined) {
652
- result.small = config.small;
653
- } else if (config.small !== undefined && result.small !== undefined) {
654
- warnings.push(`Models "small" from pack "${packName}" skipped (already defined).`);
655
- }
656
- if (config.agents) {
657
- if (!result.agents)
658
- result.agents = {};
659
- for (const [name, assignment] of Object.entries(config.agents)) {
660
- if (name in result.agents) {
661
- warnings.push(`Models agent "${name}" from pack "${packName}" skipped (already defined).`);
662
- continue;
663
- }
664
- result.agents[name] = assignment;
665
- }
666
- }
667
- if (config.profiles) {
668
- if (!result.profiles)
669
- result.profiles = {};
670
- for (const [name, profile] of Object.entries(config.profiles)) {
671
- if (name in result.profiles) {
672
- warnings.push(`Models profile "${name}" from pack "${packName}" skipped (already defined).`);
673
- continue;
674
- }
675
- result.profiles[name] = profile;
676
- }
677
- }
678
- if (config.providers) {
679
- if (!result.providers)
680
- result.providers = {};
681
- for (const [providerName, providerConfig] of Object.entries(config.providers)) {
682
- if (!(providerName in result.providers)) {
683
- result.providers[providerName] = providerConfig;
684
- } else {
685
- const existing = result.providers[providerName];
686
- if (!existing) {
687
- result.providers[providerName] = providerConfig;
688
- continue;
689
- }
690
- if (providerConfig.options) {
691
- existing.options = {
692
- ...providerConfig.options,
693
- ...existing.options
694
- };
695
- }
696
- if (providerConfig.models) {
697
- if (!existing.models)
698
- existing.models = {};
699
- for (const [modelName, modelConfig] of Object.entries(providerConfig.models)) {
700
- if (!(modelName in existing.models)) {
701
- existing.models[modelName] = modelConfig;
702
- }
703
- }
704
- }
705
- }
706
- }
707
- }
708
- if (config.routing) {
709
- if (!result.routing)
710
- result.routing = [];
711
- result.routing.push(...config.routing);
712
- }
713
- if (config.overrides) {
714
- if (!result.overrides)
715
- result.overrides = {};
716
- for (const [targetId, override] of Object.entries(config.overrides)) {
717
- if (targetId in result.overrides) {
718
- warnings.push(`Models override for target "${targetId}" from pack "${packName}" skipped (already defined).`);
719
- continue;
720
- }
721
- result.overrides[targetId] = override;
722
- }
723
- }
724
- }
725
- return { config: result, warnings };
726
- }
727
- function scanModelsForSecrets(config) {
728
- const warnings = [];
729
- const json = JSON.stringify(config);
730
- for (const pattern of SECRET_PATTERNS) {
731
- if (pattern.test(json)) {
732
- warnings.push(`Potential secret detected in models.json matching pattern: ${pattern.source}`);
733
- }
734
- }
735
- return warnings;
736
- }
737
-
738
738
  // src/core/pack-loader.ts
739
739
  import { existsSync as existsSync6 } from "fs";
740
- import { resolve as resolve2, isAbsolute } from "path";
740
+ import { isAbsolute, resolve as resolve2 } from "path";
741
741
  class PackLoader {
742
742
  projectRoot;
743
743
  config;
@@ -839,8 +839,8 @@ class PackLoader {
839
839
  }
840
840
 
841
841
  // src/exporters/cursor-plugin.ts
842
- import { resolve as resolve3, join as join8 } from "path";
843
842
  import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
843
+ import { join as join8, resolve as resolve3 } from "path";
844
844
  function exportCursorPlugin(pack, outputDir) {
845
845
  const filesWritten = [];
846
846
  const pluginName = normalizeCursorPluginName(pack.manifest.name);
@@ -983,8 +983,8 @@ function toCursorPluginAuthor(author) {
983
983
  }
984
984
 
985
985
  // src/cli/export-cmd.ts
986
- import { resolve as resolve4 } from "path";
987
986
  import chalk from "chalk";
987
+ import { resolve as resolve4 } from "path";
988
988
  function runExport(projectRoot, options) {
989
989
  const config = loadWorkspaceConfig(projectRoot);
990
990
  const verbose = options.verbose ?? config.verbose;