agents-inc 0.156.0 → 0.158.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 (173) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/dist/{chunk-4A4L3YIW.js → chunk-2PN4QXON.js} +6 -7
  3. package/dist/chunk-2PN4QXON.js.map +1 -0
  4. package/dist/{chunk-QWVXOCXO.js → chunk-3NBXQSW2.js} +7 -9
  5. package/dist/{chunk-QWVXOCXO.js.map → chunk-3NBXQSW2.js.map} +1 -1
  6. package/dist/{chunk-WCAUUBHO.js → chunk-3PJLLBUS.js} +14597 -14536
  7. package/dist/chunk-3PJLLBUS.js.map +1 -0
  8. package/dist/{chunk-6RLV45HN.js → chunk-3Q2N7CSY.js} +6 -6
  9. package/dist/chunk-3Q2N7CSY.js.map +1 -0
  10. package/dist/{chunk-LJCNUP6M.js → chunk-4ABNXKAR.js} +2 -2
  11. package/dist/{chunk-D2CAV7MG.js → chunk-4DMFK67G.js} +2 -2
  12. package/dist/{chunk-MO5FGLVS.js → chunk-54QLV3OH.js} +11 -12
  13. package/dist/chunk-54QLV3OH.js.map +1 -0
  14. package/dist/{chunk-5F2YR5XV.js → chunk-6DBE562W.js} +15 -5
  15. package/dist/chunk-6DBE562W.js.map +1 -0
  16. package/dist/{chunk-RWOYPOMR.js → chunk-7Z4N4JWQ.js} +19 -245
  17. package/dist/chunk-7Z4N4JWQ.js.map +1 -0
  18. package/dist/{chunk-H6UTKTLK.js → chunk-DAUY2SB3.js} +98 -34
  19. package/dist/chunk-DAUY2SB3.js.map +1 -0
  20. package/dist/{chunk-2H7UWE2G.js → chunk-DP6YQFVO.js} +13 -12
  21. package/dist/chunk-DP6YQFVO.js.map +1 -0
  22. package/dist/{chunk-ILUVL7WM.js → chunk-DZD25NHW.js} +2 -2
  23. package/dist/{chunk-PCC4LBKB.js → chunk-EEAX7E2X.js} +2 -2
  24. package/dist/{chunk-IO5YBKHV.js → chunk-G6G2FT2G.js} +10 -8
  25. package/dist/chunk-G6G2FT2G.js.map +1 -0
  26. package/dist/{chunk-5QZAK6J7.js → chunk-H25VRR2T.js} +50 -18
  27. package/dist/chunk-H25VRR2T.js.map +1 -0
  28. package/dist/chunk-H2DHTJKW.js +1352 -0
  29. package/dist/chunk-H2DHTJKW.js.map +1 -0
  30. package/dist/{chunk-MHRC3KRX.js → chunk-H4CL23HG.js} +3 -3
  31. package/dist/chunk-H4CL23HG.js.map +1 -0
  32. package/dist/{chunk-F5T6TV4Z.js → chunk-IK6YOXZH.js} +40 -14
  33. package/dist/chunk-IK6YOXZH.js.map +1 -0
  34. package/dist/{chunk-HG4JPXJT.js → chunk-JG3B47P3.js} +23 -10
  35. package/dist/chunk-JG3B47P3.js.map +1 -0
  36. package/dist/{chunk-SY4X2LND.js → chunk-KUZBMEWR.js} +3 -3
  37. package/dist/{chunk-5OKLCVM4.js → chunk-KVVXINCJ.js} +3 -3
  38. package/dist/{chunk-PNMM5HNX.js → chunk-L4FHSOL5.js} +9 -10
  39. package/dist/chunk-L4FHSOL5.js.map +1 -0
  40. package/dist/{chunk-PMUABBPG.js → chunk-LKI3ENGQ.js} +9 -13
  41. package/dist/chunk-LKI3ENGQ.js.map +1 -0
  42. package/dist/{chunk-CLFHC2DK.js → chunk-OQB2CKBT.js} +17 -18
  43. package/dist/chunk-OQB2CKBT.js.map +1 -0
  44. package/dist/{chunk-HXKOIWLU.js → chunk-P6OKOH62.js} +2 -6
  45. package/dist/chunk-P6OKOH62.js.map +1 -0
  46. package/dist/{chunk-TNGMF4UX.js → chunk-PNRLBPGS.js} +12 -12
  47. package/dist/chunk-PNRLBPGS.js.map +1 -0
  48. package/dist/{chunk-Y5Y7XHVU.js → chunk-PZNXBORZ.js} +4 -4
  49. package/dist/{chunk-HTYH7CKN.js → chunk-Q7CAE5NN.js} +3 -3
  50. package/dist/{chunk-G47TDUK3.js → chunk-QNAMXQKF.js} +2 -2
  51. package/dist/{chunk-GS2NZ3GD.js → chunk-SJ4T5YLG.js} +5 -5
  52. package/dist/chunk-SJ4T5YLG.js.map +1 -0
  53. package/dist/{chunk-UMH2YZKG.js → chunk-TPQ5M3BW.js} +4 -6
  54. package/dist/{chunk-UMH2YZKG.js.map → chunk-TPQ5M3BW.js.map} +1 -1
  55. package/dist/{chunk-4G2YHZIM.js → chunk-TUXXBEBB.js} +4 -6
  56. package/dist/{chunk-4G2YHZIM.js.map → chunk-TUXXBEBB.js.map} +1 -1
  57. package/dist/{chunk-WFRTHH3A.js → chunk-TZRXWFF5.js} +3 -3
  58. package/dist/{chunk-TBOVYLQJ.js → chunk-VTIDLRNA.js} +2 -2
  59. package/dist/{chunk-OKH64JZE.js → chunk-WCZNQECQ.js} +2 -2
  60. package/dist/{chunk-ZUAZHDKP.js → chunk-WMVOJY6V.js} +277 -40
  61. package/dist/chunk-WMVOJY6V.js.map +1 -0
  62. package/dist/{chunk-YO2LTXB4.js → chunk-X52QUV4U.js} +115 -10
  63. package/dist/chunk-X52QUV4U.js.map +1 -0
  64. package/dist/{chunk-IXRZAHZF.js → chunk-XNYHMRVJ.js} +4 -4
  65. package/dist/{chunk-VPASBA7P.js → chunk-YXI3BTQQ.js} +2 -2
  66. package/dist/commands/build/marketplace.js +9 -12
  67. package/dist/commands/build/marketplace.js.map +1 -1
  68. package/dist/commands/build/plugins.js +9 -12
  69. package/dist/commands/build/plugins.js.map +1 -1
  70. package/dist/commands/compile.js +15 -19
  71. package/dist/commands/compile.js.map +1 -1
  72. package/dist/commands/doctor.js +75 -54
  73. package/dist/commands/doctor.js.map +1 -1
  74. package/dist/commands/edit.js +154 -109
  75. package/dist/commands/edit.js.map +1 -1
  76. package/dist/commands/eject.js +68 -38
  77. package/dist/commands/eject.js.map +1 -1
  78. package/dist/commands/init.js +36 -39
  79. package/dist/commands/list.js +8 -10
  80. package/dist/commands/list.js.map +1 -1
  81. package/dist/commands/new/marketplace.js +8 -11
  82. package/dist/commands/new/marketplace.js.map +1 -1
  83. package/dist/commands/search.js +10 -13
  84. package/dist/commands/search.js.map +1 -1
  85. package/dist/commands/share.js +8 -10
  86. package/dist/commands/share.js.map +1 -1
  87. package/dist/commands/uninstall.js +39 -28
  88. package/dist/commands/uninstall.js.map +1 -1
  89. package/dist/commands/update.js +7 -10
  90. package/dist/commands/update.js.map +1 -1
  91. package/dist/components/common/removal-plan-confirm.js +2 -2
  92. package/dist/components/common/select-list.js +2 -2
  93. package/dist/components/wizard/category-grid.js +4 -5
  94. package/dist/components/wizard/checkbox-grid.js +4 -4
  95. package/dist/components/wizard/domain-selection.js +9 -11
  96. package/dist/components/wizard/run-wizard-session.js +26 -28
  97. package/dist/components/wizard/scroll-affordance.js +2 -2
  98. package/dist/components/wizard/skill-agent-summary.js +5 -7
  99. package/dist/components/wizard/source-grid.js +5 -6
  100. package/dist/components/wizard/stack-selection.js +7 -9
  101. package/dist/components/wizard/step-agents.js +8 -10
  102. package/dist/components/wizard/step-build.js +7 -9
  103. package/dist/components/wizard/step-confirm.js +9 -11
  104. package/dist/components/wizard/step-sources.js +8 -10
  105. package/dist/components/wizard/step-stack.js +8 -10
  106. package/dist/components/wizard/summary-panel.js +8 -10
  107. package/dist/components/wizard/toast.js +2 -2
  108. package/dist/components/wizard/wizard-layout.js +12 -14
  109. package/dist/components/wizard/wizard-tabs.js +2 -4
  110. package/dist/components/wizard/wizard.js +25 -27
  111. package/dist/hooks/init.js +36 -39
  112. package/dist/hooks/init.js.map +1 -1
  113. package/dist/load-agent-defs-2VYAV5GL.js +13 -0
  114. package/dist/recompile-project-agents-NG5DCPHJ.js +17 -0
  115. package/dist/{source-loader-3DL3NYUX.js → source-loader-CO2FZ3OO.js} +4 -8
  116. package/dist/src/agents/_templates/agent.liquid +2 -2
  117. package/dist/stores/wizard-store.js +6 -6
  118. package/package.json +2 -4
  119. package/src/agents/_templates/agent.liquid +2 -2
  120. package/src/schemas/custom-metadata.schema.json +1 -1
  121. package/src/schemas/marketplace.schema.json +2 -1
  122. package/dist/chunk-2H7UWE2G.js.map +0 -1
  123. package/dist/chunk-4A4L3YIW.js.map +0 -1
  124. package/dist/chunk-5F2YR5XV.js.map +0 -1
  125. package/dist/chunk-5QZAK6J7.js.map +0 -1
  126. package/dist/chunk-6RLV45HN.js.map +0 -1
  127. package/dist/chunk-CLFHC2DK.js.map +0 -1
  128. package/dist/chunk-F2AMBBIA.js +0 -64
  129. package/dist/chunk-F2AMBBIA.js.map +0 -1
  130. package/dist/chunk-F5T6TV4Z.js.map +0 -1
  131. package/dist/chunk-GS2NZ3GD.js.map +0 -1
  132. package/dist/chunk-H6UTKTLK.js.map +0 -1
  133. package/dist/chunk-HG4JPXJT.js.map +0 -1
  134. package/dist/chunk-HXKOIWLU.js.map +0 -1
  135. package/dist/chunk-IO5YBKHV.js.map +0 -1
  136. package/dist/chunk-MHRC3KRX.js.map +0 -1
  137. package/dist/chunk-MO5FGLVS.js.map +0 -1
  138. package/dist/chunk-PMUABBPG.js.map +0 -1
  139. package/dist/chunk-PNMM5HNX.js.map +0 -1
  140. package/dist/chunk-RWOYPOMR.js.map +0 -1
  141. package/dist/chunk-TNGMF4UX.js.map +0 -1
  142. package/dist/chunk-VASLW636.js +0 -23
  143. package/dist/chunk-VASLW636.js.map +0 -1
  144. package/dist/chunk-WCAUUBHO.js.map +0 -1
  145. package/dist/chunk-WUQ3MTPF.js +0 -173
  146. package/dist/chunk-WUQ3MTPF.js.map +0 -1
  147. package/dist/chunk-XAXJWXI4.js +0 -1667
  148. package/dist/chunk-XAXJWXI4.js.map +0 -1
  149. package/dist/chunk-YO2LTXB4.js.map +0 -1
  150. package/dist/chunk-ZUAZHDKP.js.map +0 -1
  151. package/dist/copy-local-skills-NSUTBVLJ.js +0 -14
  152. package/dist/load-agent-defs-X4E57I2U.js +0 -15
  153. package/dist/loader-G6BFG2VA.js +0 -24
  154. package/dist/recompile-project-agents-JE4MM72I.js +0 -20
  155. package/dist/recompile-project-agents-JE4MM72I.js.map +0 -1
  156. package/dist/source-loader-3DL3NYUX.js.map +0 -1
  157. /package/dist/{chunk-LJCNUP6M.js.map → chunk-4ABNXKAR.js.map} +0 -0
  158. /package/dist/{chunk-D2CAV7MG.js.map → chunk-4DMFK67G.js.map} +0 -0
  159. /package/dist/{chunk-ILUVL7WM.js.map → chunk-DZD25NHW.js.map} +0 -0
  160. /package/dist/{chunk-PCC4LBKB.js.map → chunk-EEAX7E2X.js.map} +0 -0
  161. /package/dist/{chunk-SY4X2LND.js.map → chunk-KUZBMEWR.js.map} +0 -0
  162. /package/dist/{chunk-5OKLCVM4.js.map → chunk-KVVXINCJ.js.map} +0 -0
  163. /package/dist/{chunk-Y5Y7XHVU.js.map → chunk-PZNXBORZ.js.map} +0 -0
  164. /package/dist/{chunk-HTYH7CKN.js.map → chunk-Q7CAE5NN.js.map} +0 -0
  165. /package/dist/{chunk-G47TDUK3.js.map → chunk-QNAMXQKF.js.map} +0 -0
  166. /package/dist/{chunk-WFRTHH3A.js.map → chunk-TZRXWFF5.js.map} +0 -0
  167. /package/dist/{chunk-TBOVYLQJ.js.map → chunk-VTIDLRNA.js.map} +0 -0
  168. /package/dist/{chunk-OKH64JZE.js.map → chunk-WCZNQECQ.js.map} +0 -0
  169. /package/dist/{chunk-IXRZAHZF.js.map → chunk-XNYHMRVJ.js.map} +0 -0
  170. /package/dist/{chunk-VPASBA7P.js.map → chunk-YXI3BTQQ.js.map} +0 -0
  171. /package/dist/{copy-local-skills-NSUTBVLJ.js.map → load-agent-defs-2VYAV5GL.js.map} +0 -0
  172. /package/dist/{load-agent-defs-X4E57I2U.js.map → recompile-project-agents-NG5DCPHJ.js.map} +0 -0
  173. /package/dist/{loader-G6BFG2VA.js.map → source-loader-CO2FZ3OO.js.map} +0 -0
@@ -1,21 +1,19 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- readPluginManifest
4
- } from "./chunk-WCAUUBHO.js";
5
2
  import {
6
3
  ensureDir,
7
4
  glob,
5
+ readPluginManifest,
8
6
  verbose,
9
7
  warn,
10
8
  writeFile
11
- } from "./chunk-XAXJWXI4.js";
9
+ } from "./chunk-3PJLLBUS.js";
12
10
  import {
13
11
  DEFAULT_PUBLIC_SOURCE_NAME,
14
12
  DEFAULT_VERSION,
15
13
  PLUGIN_MANIFEST_DIR,
16
14
  PLUGIN_MANIFEST_FILE,
17
15
  PUBLIC_CATALOGUE_PACKAGE
18
- } from "./chunk-IO5YBKHV.js";
16
+ } from "./chunk-G6G2FT2G.js";
19
17
 
20
18
  // src/cli/lib/marketplace-generator.ts
21
19
  import path from "path";
@@ -129,4 +127,4 @@ export {
129
127
  writeMarketplace,
130
128
  getMarketplaceStats
131
129
  };
132
- //# sourceMappingURL=chunk-4G2YHZIM.js.map
130
+ //# sourceMappingURL=chunk-TUXXBEBB.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/lib/marketplace-generator.ts"],"sourcesContent":["import path from \"path\";\nimport { countBy, sortBy } from \"remeda\";\n\nimport {\n DEFAULT_PUBLIC_SOURCE_NAME,\n DEFAULT_VERSION,\n PLUGIN_MANIFEST_DIR,\n PLUGIN_MANIFEST_FILE,\n PUBLIC_CATALOGUE_PACKAGE,\n} from \"../consts\";\nimport { writeFile, glob, ensureDir } from \"../utils/fs\";\nimport { verbose, warn } from \"../utils/logger\";\nimport type { Marketplace, MarketplacePlugin, PluginManifest } from \"../types\";\nimport { readPluginManifest } from \"./plugins\";\n\nconst PLUGIN_MANIFEST_PATH = `${PLUGIN_MANIFEST_DIR}/${PLUGIN_MANIFEST_FILE}`;\nconst MARKETPLACE_SCHEMA_URL = \"https://anthropic.com/claude-code/marketplace.schema.json\";\n\n/** Namespace a skill with no marketplace at all is given. */\nconst EXTERNAL_SKILL_NAMESPACE = \"external\";\n\n/** Namespace a skill created in place, rather than fetched from a marketplace, is given. */\nconst LOCAL_SKILL_NAMESPACE = \"local\";\n\n/**\n * Marketplace names that are not an author's to take.\n *\n * The public catalogue's skills ship unprefixed, so every bare id in the catalogue\n * already lives in `agents-inc`; the other two hold the skills that belong to no\n * marketplace. Publishing under any of them claims ids the marketplace does not own.\n */\nconst RESERVED_MARKETPLACE_NAMES: readonly string[] = [\n DEFAULT_PUBLIC_SOURCE_NAME,\n EXTERNAL_SKILL_NAMESPACE,\n LOCAL_SKILL_NAMESPACE,\n];\n\n/** How many offending ids a namespace refusal lists before summarising the rest. */\nconst MAX_REPORTED_NAMESPACE_VIOLATIONS = 10;\n\ntype MarketplaceOptions = {\n name: string;\n version?: string;\n description?: string;\n ownerName: string;\n ownerEmail?: string;\n pluginRoot: string;\n};\n\nfunction convertManifestToMarketplacePlugin(\n manifest: PluginManifest,\n pluginRoot: string,\n pluginDirName: string,\n): MarketplacePlugin {\n return {\n name: manifest.name,\n source: `./${pluginRoot}/${pluginDirName}`,\n ...(manifest.description !== undefined && { description: manifest.description }),\n ...(manifest.version !== undefined && { version: manifest.version }),\n ...(manifest.author !== undefined && { author: manifest.author }),\n ...(manifest.category !== undefined && { category: manifest.category }),\n ...(manifest.keywords !== undefined && { keywords: manifest.keywords }),\n };\n}\n\nexport async function generateMarketplace(\n pluginsDir: string,\n options: MarketplaceOptions,\n): Promise<Marketplace> {\n verbose(`Scanning plugins directory: ${pluginsDir}`);\n\n const manifestFiles = await glob(`**/${PLUGIN_MANIFEST_PATH}`, pluginsDir);\n verbose(`Found ${manifestFiles.length} plugin manifests`);\n\n const plugins: MarketplacePlugin[] = [];\n\n for (const manifestFile of manifestFiles) {\n const separator = manifestFile.indexOf(\"/\");\n const pluginDirName = separator === -1 ? manifestFile : manifestFile.slice(0, separator);\n const pluginDir = path.join(pluginsDir, pluginDirName);\n\n const manifest = await readPluginManifest(pluginDir);\n if (!manifest) {\n warn(`Could not read plugin manifest: '${manifestFile}'`);\n continue;\n }\n\n const plugin = convertManifestToMarketplacePlugin(\n manifest,\n options.pluginRoot.replace(/^\\.\\//, \"\"),\n pluginDirName,\n );\n plugins.push(plugin);\n verbose(` [OK] ${plugin.name}`);\n }\n\n const sortedPlugins = sortBy(plugins, (p) => p.name);\n\n // Field order matters: the object is serialized verbatim into marketplace.json,\n // so conditional fields keep the same positions the previous emissions used.\n return {\n $schema: MARKETPLACE_SCHEMA_URL,\n name: options.name,\n version: options.version ?? DEFAULT_VERSION,\n owner: {\n name: options.ownerName,\n ...(options.ownerEmail ? { email: options.ownerEmail } : {}),\n },\n metadata: {\n pluginRoot: options.pluginRoot,\n },\n plugins: sortedPlugins,\n ...(options.description ? { description: options.description } : {}),\n };\n}\n\n/**\n * Refuses a marketplace name that belongs to a namespace the author does not own,\n * or returns null when the name is theirs to take.\n *\n * `packageName` is package.json's own `name`. It is read for one purpose: the public\n * catalogue publishes under a reserved name legitimately, and\n * {@link PUBLIC_CATALOGUE_PACKAGE} is what distinguishes it from a claimant.\n */\nexport function validateMarketplaceName(\n marketplaceName: string,\n packageName: string,\n): string | null {\n if (!RESERVED_MARKETPLACE_NAMES.includes(marketplaceName)) return null;\n if (isCatalogueOwnReservedName(marketplaceName, packageName)) return null;\n\n return reservedNameError(marketplaceName);\n}\n\n/**\n * Refuses a marketplace whose skill ids fall outside its own namespace, or returns\n * null when every id carries it.\n *\n * The public catalogue is exempt: its skills ship unprefixed by design and\n * `agents-inc` IS the namespace they occupy. Reading that exemption off the NAME is\n * only safe because {@link validateMarketplaceName} runs first and lets nothing but\n * the catalogue's own package hold it — the two checks are a pair, in that order.\n */\nexport function validateSkillIdNamespace(marketplace: Marketplace): string | null {\n if (marketplace.name === DEFAULT_PUBLIC_SOURCE_NAME) return null;\n\n const foreignIds = marketplace.plugins\n .filter((plugin) => !carriesNamespace(plugin.name, marketplace.name))\n .map((plugin) => plugin.name);\n\n if (foreignIds.length === 0) return null;\n\n return namespaceViolationError(foreignIds, marketplace.name);\n}\n\n/**\n * Whether the reserved NAME this build publishes under is the catalogue's own, which\n * takes both halves: the name claimed is the catalogue's, and the package claiming it\n * is the catalogue's package.\n *\n * The load side asks a different question of the same identity: `isPublicCatalogueCheckout`\n * in `configuration/config.ts` asks whether a DIRECTORY is a checkout of that repository,\n * and reads the package name off it rather than being handed one.\n */\nfunction isCatalogueOwnReservedName(marketplaceName: string, packageName: string): boolean {\n return marketplaceName === DEFAULT_PUBLIC_SOURCE_NAME && packageName === PUBLIC_CATALOGUE_PACKAGE;\n}\n\nfunction carriesNamespace(skillId: string, marketplaceName: string): boolean {\n return skillId.startsWith(`${marketplaceName}-`);\n}\n\nfunction reservedNameError(marketplaceName: string): string {\n return (\n `Marketplace name '${marketplaceName}' is reserved. ` +\n `'${DEFAULT_PUBLIC_SOURCE_NAME}' is the public catalogue's own namespace, and ` +\n `'${EXTERNAL_SKILL_NAMESPACE}' and '${LOCAL_SKILL_NAMESPACE}' hold the skills that belong to ` +\n `no marketplace — publishing under any of them claims skill ids that are not this ` +\n `marketplace's. Choose a name of your own: set package.json 'name', or pass --name.`\n );\n}\n\nfunction namespaceViolationError(foreignIds: string[], marketplaceName: string): string {\n const listed = foreignIds\n .slice(0, MAX_REPORTED_NAMESPACE_VIOLATIONS)\n .map((id) => ` ${id} -> ${marketplaceName}-${id}`);\n const unlisted = foreignIds.length - listed.length;\n\n return [\n `Marketplace '${marketplaceName}' ships ${foreignIds.length} skill id(s) outside its own ` +\n `namespace. Every skill id must begin with the marketplace's name:`,\n ...listed,\n ...(unlisted > 0 ? [` ... and ${unlisted} more`] : []),\n `Rename each skill directory and the id in its metadata, re-run 'build plugins', then ` +\n `build the marketplace again.`,\n ].join(\"\\n\");\n}\n\nexport async function writeMarketplace(\n outputPath: string,\n marketplace: Marketplace,\n): Promise<void> {\n await ensureDir(path.dirname(outputPath));\n const content = `${JSON.stringify(marketplace, null, 2)}\\n`;\n await writeFile(outputPath, content);\n}\n\nexport function getMarketplaceStats(marketplace: Marketplace): {\n total: number;\n byCategory: Record<string, number>;\n} {\n return {\n total: marketplace.plugins.length,\n byCategory: countBy(marketplace.plugins, (p) => p.category ?? \"uncategorized\"),\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/cli/lib/marketplace-generator.ts"],"sourcesContent":["import path from \"path\";\nimport { countBy, sortBy } from \"remeda\";\n\nimport {\n DEFAULT_PUBLIC_SOURCE_NAME,\n DEFAULT_VERSION,\n PLUGIN_MANIFEST_DIR,\n PLUGIN_MANIFEST_FILE,\n PUBLIC_CATALOGUE_PACKAGE,\n} from \"../consts\";\nimport { writeFile, glob, ensureDir } from \"../utils/fs\";\nimport { verbose, warn } from \"../utils/logger\";\nimport type { Marketplace, MarketplacePlugin, PluginManifest } from \"../types\";\nimport { readPluginManifest } from \"./plugins\";\n\nconst PLUGIN_MANIFEST_PATH = `${PLUGIN_MANIFEST_DIR}/${PLUGIN_MANIFEST_FILE}`;\nconst MARKETPLACE_SCHEMA_URL = \"https://anthropic.com/claude-code/marketplace.schema.json\";\n\n/** Namespace a skill with no marketplace at all is given. */\nconst EXTERNAL_SKILL_NAMESPACE = \"external\";\n\n/** Namespace a skill created in place, rather than fetched from a marketplace, is given. */\nconst LOCAL_SKILL_NAMESPACE = \"local\";\n\n/**\n * Marketplace names that are not an author's to take.\n *\n * The public catalogue's skills ship unprefixed, so every bare id in the catalogue\n * already lives in `agents-inc`; the other two hold the skills that belong to no\n * marketplace. Publishing under any of them claims ids the marketplace does not own.\n */\nconst RESERVED_MARKETPLACE_NAMES: readonly string[] = [\n DEFAULT_PUBLIC_SOURCE_NAME,\n EXTERNAL_SKILL_NAMESPACE,\n LOCAL_SKILL_NAMESPACE,\n];\n\n/** How many offending ids a namespace refusal lists before summarising the rest. */\nconst MAX_REPORTED_NAMESPACE_VIOLATIONS = 10;\n\ntype MarketplaceOptions = {\n name: string;\n version?: string;\n description?: string;\n ownerName: string;\n ownerEmail?: string;\n pluginRoot: string;\n};\n\nfunction convertManifestToMarketplacePlugin(\n manifest: PluginManifest,\n pluginRoot: string,\n pluginDirName: string,\n): MarketplacePlugin {\n return {\n name: manifest.name,\n source: `./${pluginRoot}/${pluginDirName}`,\n ...(manifest.description !== undefined && { description: manifest.description }),\n ...(manifest.version !== undefined && { version: manifest.version }),\n ...(manifest.author !== undefined && { author: manifest.author }),\n ...(manifest.category !== undefined && { category: manifest.category }),\n ...(manifest.keywords !== undefined && { keywords: manifest.keywords }),\n };\n}\n\nexport async function generateMarketplace(\n pluginsDir: string,\n options: MarketplaceOptions,\n): Promise<Marketplace> {\n verbose(`Scanning plugins directory: ${pluginsDir}`);\n\n const manifestFiles = await glob(`**/${PLUGIN_MANIFEST_PATH}`, pluginsDir);\n verbose(`Found ${manifestFiles.length} plugin manifests`);\n\n const plugins: MarketplacePlugin[] = [];\n\n for (const manifestFile of manifestFiles) {\n const separator = manifestFile.indexOf(\"/\");\n const pluginDirName = separator === -1 ? manifestFile : manifestFile.slice(0, separator);\n const pluginDir = path.join(pluginsDir, pluginDirName);\n\n const manifest = await readPluginManifest(pluginDir);\n if (!manifest) {\n warn(`Could not read plugin manifest: '${manifestFile}'`);\n continue;\n }\n\n const plugin = convertManifestToMarketplacePlugin(\n manifest,\n options.pluginRoot.replace(/^\\.\\//, \"\"),\n pluginDirName,\n );\n plugins.push(plugin);\n verbose(` [OK] ${plugin.name}`);\n }\n\n const sortedPlugins = sortBy(plugins, (p) => p.name);\n\n // Field order matters: the object is serialized verbatim into marketplace.json,\n // so conditional fields keep the same positions the previous emissions used.\n return {\n $schema: MARKETPLACE_SCHEMA_URL,\n name: options.name,\n version: options.version ?? DEFAULT_VERSION,\n owner: {\n name: options.ownerName,\n ...(options.ownerEmail ? { email: options.ownerEmail } : {}),\n },\n metadata: {\n pluginRoot: options.pluginRoot,\n },\n plugins: sortedPlugins,\n ...(options.description ? { description: options.description } : {}),\n };\n}\n\n/**\n * Refuses a marketplace name that belongs to a namespace the author does not own,\n * or returns null when the name is theirs to take.\n *\n * `packageName` is package.json's own `name`. It is read for one purpose: the public\n * catalogue publishes under a reserved name legitimately, and\n * {@link PUBLIC_CATALOGUE_PACKAGE} is what distinguishes it from a claimant.\n */\nexport function validateMarketplaceName(\n marketplaceName: string,\n packageName: string,\n): string | null {\n if (!RESERVED_MARKETPLACE_NAMES.includes(marketplaceName)) return null;\n if (isCatalogueOwnReservedName(marketplaceName, packageName)) return null;\n\n return reservedNameError(marketplaceName);\n}\n\n/**\n * Refuses a marketplace whose skill ids fall outside its own namespace, or returns\n * null when every id carries it.\n *\n * The public catalogue is exempt: its skills ship unprefixed by design and\n * `agents-inc` IS the namespace they occupy. Reading that exemption off the NAME is\n * only safe because {@link validateMarketplaceName} runs first and lets nothing but\n * the catalogue's own package hold it — the two checks are a pair, in that order.\n */\nexport function validateSkillIdNamespace(marketplace: Marketplace): string | null {\n if (marketplace.name === DEFAULT_PUBLIC_SOURCE_NAME) return null;\n\n const foreignIds = marketplace.plugins\n .filter((plugin) => !carriesNamespace(plugin.name, marketplace.name))\n .map((plugin) => plugin.name);\n\n if (foreignIds.length === 0) return null;\n\n return namespaceViolationError(foreignIds, marketplace.name);\n}\n\n/**\n * Whether the reserved NAME this build publishes under is the catalogue's own, which\n * takes both halves: the name claimed is the catalogue's, and the package claiming it\n * is the catalogue's package.\n *\n * The load side asks a different question of the same identity: `isPublicCatalogueCheckout`\n * in `configuration/config.ts` asks whether a DIRECTORY is a checkout of that repository,\n * and reads the package name off it rather than being handed one.\n */\nfunction isCatalogueOwnReservedName(marketplaceName: string, packageName: string): boolean {\n return marketplaceName === DEFAULT_PUBLIC_SOURCE_NAME && packageName === PUBLIC_CATALOGUE_PACKAGE;\n}\n\nfunction carriesNamespace(skillId: string, marketplaceName: string): boolean {\n return skillId.startsWith(`${marketplaceName}-`);\n}\n\nfunction reservedNameError(marketplaceName: string): string {\n return (\n `Marketplace name '${marketplaceName}' is reserved. ` +\n `'${DEFAULT_PUBLIC_SOURCE_NAME}' is the public catalogue's own namespace, and ` +\n `'${EXTERNAL_SKILL_NAMESPACE}' and '${LOCAL_SKILL_NAMESPACE}' hold the skills that belong to ` +\n `no marketplace — publishing under any of them claims skill ids that are not this ` +\n `marketplace's. Choose a name of your own: set package.json 'name', or pass --name.`\n );\n}\n\nfunction namespaceViolationError(foreignIds: string[], marketplaceName: string): string {\n const listed = foreignIds\n .slice(0, MAX_REPORTED_NAMESPACE_VIOLATIONS)\n .map((id) => ` ${id} -> ${marketplaceName}-${id}`);\n const unlisted = foreignIds.length - listed.length;\n\n return [\n `Marketplace '${marketplaceName}' ships ${foreignIds.length} skill id(s) outside its own ` +\n `namespace. Every skill id must begin with the marketplace's name:`,\n ...listed,\n ...(unlisted > 0 ? [` ... and ${unlisted} more`] : []),\n `Rename each skill directory and the id in its metadata, re-run 'build plugins', then ` +\n `build the marketplace again.`,\n ].join(\"\\n\");\n}\n\nexport async function writeMarketplace(\n outputPath: string,\n marketplace: Marketplace,\n): Promise<void> {\n await ensureDir(path.dirname(outputPath));\n const content = `${JSON.stringify(marketplace, null, 2)}\\n`;\n await writeFile(outputPath, content);\n}\n\nexport function getMarketplaceStats(marketplace: Marketplace): {\n total: number;\n byCategory: Record<string, number>;\n} {\n return {\n total: marketplace.plugins.length,\n byCategory: countBy(marketplace.plugins, (p) => p.category ?? \"uncategorized\"),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA,OAAO,UAAU;AACjB,SAAS,SAAS,cAAc;AAchC,IAAM,uBAAuB,GAAG,mBAAmB,IAAI,oBAAoB;AAC3E,IAAM,yBAAyB;AAG/B,IAAM,2BAA2B;AAGjC,IAAM,wBAAwB;AAS9B,IAAM,6BAAgD;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AACF;AAGA,IAAM,oCAAoC;AAW1C,SAAS,mCACP,UACA,YACA,eACmB;AACnB,SAAO;AAAA,IACL,MAAM,SAAS;AAAA,IACf,QAAQ,KAAK,UAAU,IAAI,aAAa;AAAA,IACxC,GAAI,SAAS,gBAAgB,UAAa,EAAE,aAAa,SAAS,YAAY;AAAA,IAC9E,GAAI,SAAS,YAAY,UAAa,EAAE,SAAS,SAAS,QAAQ;AAAA,IAClE,GAAI,SAAS,WAAW,UAAa,EAAE,QAAQ,SAAS,OAAO;AAAA,IAC/D,GAAI,SAAS,aAAa,UAAa,EAAE,UAAU,SAAS,SAAS;AAAA,IACrE,GAAI,SAAS,aAAa,UAAa,EAAE,UAAU,SAAS,SAAS;AAAA,EACvE;AACF;AAEA,eAAsB,oBACpB,YACA,SACsB;AACtB,UAAQ,+BAA+B,UAAU,EAAE;AAEnD,QAAM,gBAAgB,MAAM,KAAK,MAAM,oBAAoB,IAAI,UAAU;AACzE,UAAQ,SAAS,cAAc,MAAM,mBAAmB;AAExD,QAAM,UAA+B,CAAC;AAEtC,aAAW,gBAAgB,eAAe;AACxC,UAAM,YAAY,aAAa,QAAQ,GAAG;AAC1C,UAAM,gBAAgB,cAAc,KAAK,eAAe,aAAa,MAAM,GAAG,SAAS;AACvF,UAAM,YAAY,KAAK,KAAK,YAAY,aAAa;AAErD,UAAM,WAAW,MAAM,mBAAmB,SAAS;AACnD,QAAI,CAAC,UAAU;AACb,WAAK,oCAAoC,YAAY,GAAG;AACxD;AAAA,IACF;AAEA,UAAM,SAAS;AAAA,MACb;AAAA,MACA,QAAQ,WAAW,QAAQ,SAAS,EAAE;AAAA,MACtC;AAAA,IACF;AACA,YAAQ,KAAK,MAAM;AACnB,YAAQ,UAAU,OAAO,IAAI,EAAE;AAAA,EACjC;AAEA,QAAM,gBAAgB,OAAO,SAAS,CAAC,MAAM,EAAE,IAAI;AAInD,SAAO;AAAA,IACL,SAAS;AAAA,IACT,MAAM,QAAQ;AAAA,IACd,SAAS,QAAQ,WAAW;AAAA,IAC5B,OAAO;AAAA,MACL,MAAM,QAAQ;AAAA,MACd,GAAI,QAAQ,aAAa,EAAE,OAAO,QAAQ,WAAW,IAAI,CAAC;AAAA,IAC5D;AAAA,IACA,UAAU;AAAA,MACR,YAAY,QAAQ;AAAA,IACtB;AAAA,IACA,SAAS;AAAA,IACT,GAAI,QAAQ,cAAc,EAAE,aAAa,QAAQ,YAAY,IAAI,CAAC;AAAA,EACpE;AACF;AAUO,SAAS,wBACd,iBACA,aACe;AACf,MAAI,CAAC,2BAA2B,SAAS,eAAe,EAAG,QAAO;AAClE,MAAI,2BAA2B,iBAAiB,WAAW,EAAG,QAAO;AAErE,SAAO,kBAAkB,eAAe;AAC1C;AAWO,SAAS,yBAAyB,aAAyC;AAChF,MAAI,YAAY,SAAS,2BAA4B,QAAO;AAE5D,QAAM,aAAa,YAAY,QAC5B,OAAO,CAAC,WAAW,CAAC,iBAAiB,OAAO,MAAM,YAAY,IAAI,CAAC,EACnE,IAAI,CAAC,WAAW,OAAO,IAAI;AAE9B,MAAI,WAAW,WAAW,EAAG,QAAO;AAEpC,SAAO,wBAAwB,YAAY,YAAY,IAAI;AAC7D;AAWA,SAAS,2BAA2B,iBAAyB,aAA8B;AACzF,SAAO,oBAAoB,8BAA8B,gBAAgB;AAC3E;AAEA,SAAS,iBAAiB,SAAiB,iBAAkC;AAC3E,SAAO,QAAQ,WAAW,GAAG,eAAe,GAAG;AACjD;AAEA,SAAS,kBAAkB,iBAAiC;AAC1D,SACE,qBAAqB,eAAe,mBAChC,0BAA0B,mDAC1B,wBAAwB,UAAU,qBAAqB;AAI/D;AAEA,SAAS,wBAAwB,YAAsB,iBAAiC;AACtF,QAAM,SAAS,WACZ,MAAM,GAAG,iCAAiC,EAC1C,IAAI,CAAC,OAAO,KAAK,EAAE,OAAO,eAAe,IAAI,EAAE,EAAE;AACpD,QAAM,WAAW,WAAW,SAAS,OAAO;AAE5C,SAAO;AAAA,IACL,gBAAgB,eAAe,WAAW,WAAW,MAAM;AAAA,IAE3D,GAAG;AAAA,IACH,GAAI,WAAW,IAAI,CAAC,aAAa,QAAQ,OAAO,IAAI,CAAC;AAAA,IACrD;AAAA,EAEF,EAAE,KAAK,IAAI;AACb;AAEA,eAAsB,iBACpB,YACA,aACe;AACf,QAAM,UAAU,KAAK,QAAQ,UAAU,CAAC;AACxC,QAAM,UAAU,GAAG,KAAK,UAAU,aAAa,MAAM,CAAC,CAAC;AAAA;AACvD,QAAM,UAAU,YAAY,OAAO;AACrC;AAEO,SAAS,oBAAoB,aAGlC;AACA,SAAO;AAAA,IACL,OAAO,YAAY,QAAQ;AAAA,IAC3B,YAAY,QAAQ,YAAY,SAAS,CAAC,MAAM,EAAE,YAAY,eAAe;AAAA,EAC/E;AACF;","names":[]}
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  computeRowScrollTop
4
- } from "./chunk-OKH64JZE.js";
4
+ } from "./chunk-WCZNQECQ.js";
5
5
  import {
6
6
  SCROLL_VIEWPORT
7
- } from "./chunk-IO5YBKHV.js";
7
+ } from "./chunk-G6G2FT2G.js";
8
8
 
9
9
  // src/cli/components/hooks/use-row-scroll.ts
10
10
  import { useRef } from "react";
@@ -24,4 +24,4 @@ function useRowScroll({
24
24
  export {
25
25
  useRowScroll
26
26
  };
27
- //# sourceMappingURL=chunk-WFRTHH3A.js.map
27
+ //# sourceMappingURL=chunk-TZRXWFF5.js.map
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  CLI_COLORS,
7
7
  UI_SYMBOLS
8
- } from "./chunk-IO5YBKHV.js";
8
+ } from "./chunk-G6G2FT2G.js";
9
9
 
10
10
  // src/cli/components/common/select-list.tsx
11
11
  import { useCallback } from "react";
@@ -48,4 +48,4 @@ function SelectList({
48
48
  export {
49
49
  SelectList
50
50
  };
51
- //# sourceMappingURL=chunk-TBOVYLQJ.js.map
51
+ //# sourceMappingURL=chunk-VTIDLRNA.js.map
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  SCROLL_VIEWPORT
4
- } from "./chunk-IO5YBKHV.js";
4
+ } from "./chunk-G6G2FT2G.js";
5
5
 
6
6
  // src/cli/components/hooks/use-section-scroll.ts
7
7
  import { useCallback, useEffect, useRef, useState } from "react";
@@ -118,4 +118,4 @@ export {
118
118
  useSectionScroll,
119
119
  computeRowScrollTop
120
120
  };
121
- //# sourceMappingURL=chunk-OKH64JZE.js.map
121
+ //# sourceMappingURL=chunk-WCZNQECQ.js.map
@@ -1,55 +1,112 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ agentFrontmatterValidationSchema,
3
4
  buildCompileAgents,
4
5
  computeStringHash,
5
- createLiquidEngine,
6
+ copy,
6
7
  determinePluginVersion,
8
+ directoryExists,
7
9
  discoverAllPluginSkills,
8
10
  effectivelyExcludedSkillIds,
9
- fetchFromSource,
10
- generateAgentPluginManifest,
11
- getPluginAgentsDir,
12
- getPluginManifestPath,
13
- hasProvenanceMarker,
14
- loadProjectConfig,
15
- loadProjectSourceConfig,
16
- resolveAgents,
17
- writeCompiledAgentsByScope,
18
- writeContentHash,
19
- writePluginManifest
20
- } from "./chunk-WCAUUBHO.js";
21
- import {
22
- agentFrontmatterValidationSchema,
23
- copy,
24
- directoryExists,
25
11
  ensureDir,
26
12
  extractFrontmatter,
13
+ fetchFromSource,
14
+ fileExists,
27
15
  formatZodIssues,
16
+ generateAgentPluginManifest,
28
17
  getErrorMessage,
18
+ getPluginAgentsDir,
19
+ getPluginManifestPath,
29
20
  glob,
30
21
  isAgentName,
31
22
  loadAllAgents,
32
23
  loadProjectAgents,
24
+ loadProjectConfig,
25
+ loadProjectSourceConfig,
33
26
  log,
34
27
  readFile,
35
28
  readFileOptional,
36
29
  remove,
30
+ resolveAgents,
31
+ resolveInstallPaths,
37
32
  verbose,
38
- warn
39
- } from "./chunk-XAXJWXI4.js";
33
+ warn,
34
+ writeContentHash,
35
+ writeFile,
36
+ writePluginManifest
37
+ } from "./chunk-3PJLLBUS.js";
40
38
  import {
41
39
  typedEntries,
42
40
  typedFromEntries,
43
41
  typedKeys
44
- } from "./chunk-VASLW636.js";
42
+ } from "./chunk-7Z4N4JWQ.js";
45
43
  import {
44
+ CLAUDE_DIR,
45
+ CLAUDE_SRC_DIR,
46
+ DEFAULT_PLUGIN_NAME,
46
47
  DIRS,
47
- PROJECT_ROOT
48
- } from "./chunk-IO5YBKHV.js";
48
+ EJECT_SOURCE,
49
+ PROJECT_ROOT,
50
+ STANDARD_DIRS,
51
+ STANDARD_FILES
52
+ } from "./chunk-G6G2FT2G.js";
49
53
 
50
54
  // src/cli/lib/agents/list-compiled-agents.ts
51
- import path from "path";
55
+ import path2 from "path";
52
56
  import { partition } from "remeda";
57
+
58
+ // src/cli/lib/agents/agent-provenance.ts
59
+ import path from "path";
60
+ import { z } from "zod";
61
+ var MARKER_OPEN = `<!-- Generated by ${DEFAULT_PLUGIN_NAME} v`;
62
+ var MARKER_NOTICE = " \u2014 do not edit; compile rewrites this file";
63
+ var MARKER_CLOSE = " -->";
64
+ var FRONTMATTER_FENCE = "---";
65
+ var PACKAGE_JSON_FILE = "package.json";
66
+ var ownPackageJsonSchema = z.object({ version: z.string().min(1) });
67
+ function provenanceMarker(version) {
68
+ return `${MARKER_OPEN}${version}${MARKER_NOTICE}${MARKER_CLOSE}`;
69
+ }
70
+ function isProvenanceMarker(line) {
71
+ return line.startsWith(MARKER_OPEN) && line.endsWith(MARKER_CLOSE);
72
+ }
73
+ function bodyStartIndex(lines) {
74
+ if (lines[0] !== FRONTMATTER_FENCE) return 0;
75
+ const closingFence = lines.indexOf(FRONTMATTER_FENCE, 1);
76
+ if (closingFence === -1) return 0;
77
+ return closingFence + 1;
78
+ }
79
+ function hasProvenanceMarker(content) {
80
+ const lines = content.split("\n");
81
+ const firstBodyLine = lines[bodyStartIndex(lines)];
82
+ return firstBodyLine !== void 0 && isProvenanceMarker(firstBodyLine);
83
+ }
84
+ function stampProvenanceMarker(content, version) {
85
+ const lines = content.split("\n");
86
+ const bodyStart = bodyStartIndex(lines);
87
+ const replacedLines = hasProvenanceMarker(content) ? 1 : 0;
88
+ return [
89
+ ...lines.slice(0, bodyStart),
90
+ provenanceMarker(version),
91
+ ...lines.slice(bodyStart + replacedLines)
92
+ ].join("\n");
93
+ }
94
+ var ownVersion;
95
+ function cliVersion() {
96
+ ownVersion ??= readOwnVersion();
97
+ return ownVersion;
98
+ }
99
+ async function readOwnVersion() {
100
+ const manifestPath = path.join(PROJECT_ROOT, PACKAGE_JSON_FILE);
101
+ const raw = JSON.parse(await readFile(manifestPath));
102
+ const parsed = ownPackageJsonSchema.safeParse(raw);
103
+ if (!parsed.success) {
104
+ throw new Error(`Could not read this CLI's own version from ${manifestPath}`);
105
+ }
106
+ return parsed.data.version;
107
+ }
108
+
109
+ // src/cli/lib/agents/list-compiled-agents.ts
53
110
  async function listAgentMdFiles(agentsDir) {
54
111
  return glob("*.md", agentsDir);
55
112
  }
@@ -60,29 +117,29 @@ async function splitAgentsByProvenance(agentsDir) {
60
117
  return { marked: marked.map(agentName), unmarked: unmarked.map(agentName) };
61
118
  }
62
119
  async function readAgentProvenance(agentsDir, file) {
63
- const content = await readFileOptional(path.join(agentsDir, file));
64
- return { name: path.basename(file, ".md"), compiledHere: hasProvenanceMarker(content) };
120
+ const content = await readFileOptional(path2.join(agentsDir, file));
121
+ return { name: path2.basename(file, ".md"), compiledHere: hasProvenanceMarker(content) };
65
122
  }
66
123
  function agentName(agent) {
67
124
  return agent.name;
68
125
  }
69
126
  async function listCompiledAgentNames(agentsDir) {
70
127
  const files = await listAgentMdFiles(agentsDir);
71
- return files.map((f) => path.basename(f, ".md"));
128
+ return files.map((f) => path2.basename(f, ".md"));
72
129
  }
73
130
  async function pruneStaleCompiledAgents(agentsDir, keep) {
74
131
  const isStaleCompiledAgent = (file) => {
75
- const name = path.basename(file, ".md");
132
+ const name = path2.basename(file, ".md");
76
133
  return isAgentName(name) && !keep.has(name);
77
134
  };
78
135
  const files = await listAgentMdFiles(agentsDir);
79
136
  await Promise.all(
80
- files.filter(isStaleCompiledAgent).map((file) => remove(path.join(agentsDir, file)))
137
+ files.filter(isStaleCompiledAgent).map((file) => remove(path2.join(agentsDir, file)))
81
138
  );
82
139
  }
83
140
 
84
141
  // src/cli/lib/agents/agent-fetcher.ts
85
- import path2 from "path";
142
+ import path3 from "path";
86
143
  async function getAgentDefinitions(remoteSource) {
87
144
  if (remoteSource) {
88
145
  return fetchAgentDefinitionsFromRemote(remoteSource);
@@ -90,7 +147,7 @@ async function getAgentDefinitions(remoteSource) {
90
147
  return getLocalAgentDefinitions();
91
148
  }
92
149
  async function getLocalAgentDefinitions() {
93
- const agentsDir = path2.join(PROJECT_ROOT, DIRS.agents);
150
+ const agentsDir = path3.join(PROJECT_ROOT, DIRS.agents);
94
151
  if (!await directoryExists(agentsDir)) {
95
152
  throw new Error(
96
153
  `Agent partials not found at '${agentsDir}'. Ensure the CLI is properly installed.`
@@ -110,7 +167,7 @@ async function fetchAgentDefinitionsFromRemote(source, options = {}) {
110
167
  verbose(`Using agentsDir from source config: ${sourceProjectConfig.agentsDir}`);
111
168
  }
112
169
  const agentsDirRelPath = options.agentsDir ?? sourceProjectConfig?.agentsDir ?? DIRS.agents;
113
- const agentsDir = path2.join(result.path, agentsDirRelPath);
170
+ const agentsDir = path3.join(result.path, agentsDirRelPath);
114
171
  if (!await directoryExists(agentsDir)) {
115
172
  throw new Error(`Agent partials not found at '${agentsDir}'`);
116
173
  }
@@ -123,7 +180,187 @@ async function fetchAgentDefinitionsFromRemote(source, options = {}) {
123
180
 
124
181
  // src/cli/lib/agents/agent-recompiler.ts
125
182
  import { partition as partition2 } from "remeda";
126
- import path3 from "path";
183
+
184
+ // src/cli/lib/agents/write-compiled-agents.ts
185
+ import os from "os";
186
+ import path5 from "path";
187
+
188
+ // src/cli/lib/compiler.ts
189
+ import { Liquid } from "liquidjs";
190
+ import path4 from "path";
191
+ var LIQUID_SYNTAX_PATTERN = /\{\{|\}\}|\{%|%\}/g;
192
+ function sanitizeLiquidSyntax(value, fieldName) {
193
+ if (!LIQUID_SYNTAX_PATTERN.test(value)) return value;
194
+ LIQUID_SYNTAX_PATTERN.lastIndex = 0;
195
+ const sanitized = value.replace(LIQUID_SYNTAX_PATTERN, "");
196
+ warn(`Stripped Liquid template syntax from '${fieldName}' \u2014 possible template injection attempt`);
197
+ return sanitized;
198
+ }
199
+ function sanitizeStringArray(values, fieldName) {
200
+ return values.map((v) => sanitizeLiquidSyntax(v, fieldName));
201
+ }
202
+ function sanitizeSkills(skills) {
203
+ return skills.map((s) => ({
204
+ ...s,
205
+ id: sanitizeLiquidSyntax(s.id, "skill.id"),
206
+ description: sanitizeLiquidSyntax(s.description, "skill.description"),
207
+ usage: sanitizeLiquidSyntax(s.usage, "skill.usage"),
208
+ ...s.pluginRef !== void 0 && {
209
+ pluginRef: sanitizeLiquidSyntax(s.pluginRef, "skill.pluginRef")
210
+ }
211
+ }));
212
+ }
213
+ function sanitizeCompiledAgentData(data) {
214
+ const sanitizedAgent = {
215
+ ...data.agent,
216
+ name: sanitizeLiquidSyntax(data.agent.name, "agent.name"),
217
+ title: sanitizeLiquidSyntax(data.agent.title, "agent.title"),
218
+ description: sanitizeLiquidSyntax(data.agent.description, "agent.description"),
219
+ tools: sanitizeStringArray(data.agent.tools, "agent.tools"),
220
+ ...data.agent.disallowedTools !== void 0 && {
221
+ disallowedTools: sanitizeStringArray(data.agent.disallowedTools, "agent.disallowedTools")
222
+ },
223
+ ...data.agent.model !== void 0 && {
224
+ model: sanitizeLiquidSyntax(data.agent.model, "agent.model")
225
+ },
226
+ ...data.agent.effort !== void 0 && {
227
+ effort: sanitizeLiquidSyntax(data.agent.effort, "agent.effort")
228
+ },
229
+ ...data.agent.permissionMode !== void 0 && {
230
+ permissionMode: sanitizeLiquidSyntax(data.agent.permissionMode, "agent.permissionMode")
231
+ }
232
+ };
233
+ const sanitizedSkills = sanitizeSkills(data.skills);
234
+ const sanitizedPreloaded = sanitizeSkills(data.preloadedSkills);
235
+ const sanitizedDynamic = sanitizeSkills(data.dynamicSkills);
236
+ const sanitizedPreloadedIds = data.preloadedSkillIds.map(
237
+ (id) => sanitizeLiquidSyntax(id, "preloadedSkillId")
238
+ );
239
+ return {
240
+ agent: sanitizedAgent,
241
+ identity: data.identity,
242
+ playbook: data.playbook,
243
+ output: data.output,
244
+ criticalRequirementsTop: data.criticalRequirementsTop,
245
+ criticalReminders: data.criticalReminders,
246
+ skills: sanitizedSkills,
247
+ preloadedSkills: sanitizedPreloaded,
248
+ dynamicSkills: sanitizedDynamic,
249
+ preloadedSkillIds: sanitizedPreloadedIds
250
+ };
251
+ }
252
+ async function readAgentFiles(name, agent, projectRoot) {
253
+ const agentSourceRoot = agent.sourceRoot || projectRoot;
254
+ const agentBaseDir = agent.agentBaseDir || DIRS.agents;
255
+ const agentDir = path4.join(agentSourceRoot, agentBaseDir, agent.path || name);
256
+ const identity = await readFile(path4.join(agentDir, STANDARD_FILES.IDENTITY_MD));
257
+ const playbook = await readFile(path4.join(agentDir, STANDARD_FILES.PLAYBOOK_MD));
258
+ const criticalRequirementsTop = await readFileOptional(
259
+ path4.join(agentDir, STANDARD_FILES.CRITICAL_REQUIREMENTS_MD),
260
+ ""
261
+ );
262
+ const criticalReminders = await readFileOptional(
263
+ path4.join(agentDir, STANDARD_FILES.CRITICAL_REMINDERS_MD),
264
+ ""
265
+ );
266
+ const agentPath = agent.path || name;
267
+ const parts = agentPath.split("/");
268
+ const category = parts[0] || name;
269
+ const categoryDir = path4.join(agentSourceRoot, agentBaseDir, category);
270
+ let output = await readFileOptional(path4.join(agentDir, STANDARD_FILES.OUTPUT_MD), "");
271
+ if (!output) {
272
+ output = await readFileOptional(path4.join(categoryDir, STANDARD_FILES.OUTPUT_MD), "");
273
+ }
274
+ return { identity, playbook, output, criticalRequirementsTop, criticalReminders };
275
+ }
276
+ function buildAgentTemplateContext(name, agent, files, mapSkill = (skill) => skill) {
277
+ const skills = agent.skills.map(mapSkill);
278
+ const preloadedSkills = skills.filter((s) => s.preloaded);
279
+ const dynamicSkills = skills.filter((s) => !s.preloaded);
280
+ const preloadedSkillIds = preloadedSkills.map((s) => s.pluginRef ?? s.id);
281
+ verbose(
282
+ `Skills for ${name}: ${preloadedSkills.length} preloaded, ${dynamicSkills.length} dynamic`
283
+ );
284
+ return {
285
+ agent,
286
+ ...files,
287
+ skills,
288
+ preloadedSkills,
289
+ dynamicSkills,
290
+ preloadedSkillIds
291
+ };
292
+ }
293
+ async function renderCompiledAgent(engine, data) {
294
+ const rendered = await engine.renderFile("agent", sanitizeCompiledAgentData(data));
295
+ return stampProvenanceMarker(rendered, await cliVersion());
296
+ }
297
+ async function createLiquidEngine(projectDir) {
298
+ const roots = [];
299
+ if (projectDir) {
300
+ const srcTemplatesDir = path4.join(
301
+ projectDir,
302
+ CLAUDE_SRC_DIR,
303
+ STANDARD_DIRS.AGENTS,
304
+ path4.basename(DIRS.templates)
305
+ );
306
+ if (await directoryExists(srcTemplatesDir)) {
307
+ roots.push(srcTemplatesDir);
308
+ verbose(`Using local templates from: ${srcTemplatesDir}`);
309
+ }
310
+ const legacyTemplatesDir = path4.join(projectDir, CLAUDE_DIR, STANDARD_DIRS.TEMPLATES);
311
+ if (await directoryExists(legacyTemplatesDir)) {
312
+ roots.push(legacyTemplatesDir);
313
+ verbose(`Using legacy templates from: ${legacyTemplatesDir}`);
314
+ }
315
+ }
316
+ roots.push(path4.join(PROJECT_ROOT, DIRS.templates));
317
+ return new Liquid({
318
+ root: roots,
319
+ extname: ".liquid",
320
+ strictVariables: false,
321
+ strictFilters: true
322
+ });
323
+ }
324
+ function pluginRefFor(skill) {
325
+ if (skill.source === void 0 || skill.source === EJECT_SOURCE) return {};
326
+ return { pluginRef: `${skill.id}:${skill.id}` };
327
+ }
328
+ async function compileAgentForPlugin(name, agent, fallbackRoot, engine) {
329
+ verbose(`Compiling agent: ${name}`);
330
+ const files = await readAgentFiles(name, agent, fallbackRoot);
331
+ const data = buildAgentTemplateContext(name, agent, files, (skill) => ({
332
+ ...skill,
333
+ ...pluginRefFor(skill)
334
+ }));
335
+ return renderCompiledAgent(engine, data);
336
+ }
337
+
338
+ // src/cli/lib/agents/write-compiled-agents.ts
339
+ async function holdsExactly(filePath, content) {
340
+ return await fileExists(filePath) && await readFile(filePath) === content;
341
+ }
342
+ var UNROUTED_AGENT_SCOPE = "project";
343
+ async function writeCompiledAgentsByScope(params) {
344
+ const globalAgentsDir = resolveInstallPaths(os.homedir(), "global").agentsDir;
345
+ const outcomes = [];
346
+ for (const [name, agent] of typedEntries(params.resolvedAgents)) {
347
+ try {
348
+ const output = await compileAgentForPlugin(name, agent, params.sourcePath, params.engine);
349
+ const scope = params.agentScopeMap?.get(name) ?? UNROUTED_AGENT_SCOPE;
350
+ const targetDir = scope === "global" ? globalAgentsDir : params.projectAgentsDir;
351
+ const targetPath = path5.join(targetDir, `${name}.md`);
352
+ const rewritten = !await holdsExactly(targetPath, output);
353
+ if (rewritten) await writeFile(targetPath, output);
354
+ outcomes.push({ name, ok: true, scope, targetDir, rewritten });
355
+ } catch (error) {
356
+ outcomes.push({ name, ok: false, error });
357
+ }
358
+ }
359
+ return outcomes;
360
+ }
361
+
362
+ // src/cli/lib/agents/agent-recompiler.ts
363
+ import path6 from "path";
127
364
  async function getExistingAgentNames(pluginDir) {
128
365
  return listCompiledAgentNames(getPluginAgentsDir(pluginDir));
129
366
  }
@@ -221,7 +458,7 @@ async function recompileAgents(options) {
221
458
  knownAgents.map((name) => [name, allConfigAgents[name] ?? {}])
222
459
  );
223
460
  const compileConfig = {
224
- name: filteredConfig?.name || path3.basename(pluginDir),
461
+ name: filteredConfig?.name || path6.basename(pluginDir),
225
462
  description: filteredConfig?.description || "Recompiled plugin",
226
463
  agents: configAgents
227
464
  };
@@ -240,7 +477,7 @@ async function recompileAgents(options) {
240
477
  }
241
478
 
242
479
  // src/cli/lib/agents/agent-plugin-compiler.ts
243
- import path4 from "path";
480
+ import path7 from "path";
244
481
  function parseAgentFrontmatter(content, filePath) {
245
482
  const raw = extractFrontmatter(content);
246
483
  if (!raw) {
@@ -255,7 +492,7 @@ function parseAgentFrontmatter(content, filePath) {
255
492
  }
256
493
  async function compileAgentPlugin(options) {
257
494
  const { agentPath, outputDir } = options;
258
- const fileName = path4.basename(agentPath);
495
+ const fileName = path7.basename(agentPath);
259
496
  const content = await readFile(agentPath);
260
497
  const frontmatter = parseAgentFrontmatter(content, agentPath);
261
498
  if (!frontmatter) {
@@ -265,8 +502,8 @@ async function compileAgentPlugin(options) {
265
502
  }
266
503
  const agentName2 = frontmatter.name;
267
504
  verbose(`Compiling agent plugin: ${agentName2} from ${agentPath}`);
268
- const pluginDir = path4.join(outputDir, `agent-${agentName2}`);
269
- const agentsDir = path4.join(pluginDir, "agents");
505
+ const pluginDir = path7.join(outputDir, `agent-${agentName2}`);
506
+ const agentsDir = path7.join(pluginDir, "agents");
270
507
  await ensureDir(pluginDir);
271
508
  await ensureDir(agentsDir);
272
509
  const newHash = computeStringHash(content);
@@ -283,7 +520,7 @@ async function compileAgentPlugin(options) {
283
520
  await writePluginManifest(pluginDir, manifest);
284
521
  await writeContentHash(pluginDir, contentHash, getPluginManifestPath);
285
522
  verbose(` Wrote plugin.json for ${agentName2} (v${version})`);
286
- await copy(agentPath, path4.join(agentsDir, `${agentName2}.md`));
523
+ await copy(agentPath, path7.join(agentsDir, `${agentName2}.md`));
287
524
  verbose(` Copied agent ${fileName} -> agents/${agentName2}.md`);
288
525
  return {
289
526
  pluginPath: pluginDir,
@@ -295,7 +532,7 @@ async function compileAllAgentPlugins(agentsDir, outputDir) {
295
532
  const results = [];
296
533
  const agentMdFiles = await listAgentMdFiles(agentsDir);
297
534
  for (const agentFile of agentMdFiles) {
298
- const agentPath = path4.join(agentsDir, agentFile);
535
+ const agentPath = path7.join(agentsDir, agentFile);
299
536
  try {
300
537
  const result = await compileAgentPlugin({
301
538
  agentPath,
@@ -328,4 +565,4 @@ export {
328
565
  compileAllAgentPlugins,
329
566
  printAgentCompilationSummary
330
567
  };
331
- //# sourceMappingURL=chunk-ZUAZHDKP.js.map
568
+ //# sourceMappingURL=chunk-WMVOJY6V.js.map