agents-inc 0.175.0 → 0.176.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 (81) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/dist/{chunk-EGC7PNDI.js → chunk-3F5LT433.js} +138 -41
  3. package/dist/chunk-3F5LT433.js.map +1 -0
  4. package/dist/chunk-5CFHP6Z5.js +109 -0
  5. package/dist/chunk-5CFHP6Z5.js.map +1 -0
  6. package/dist/{chunk-MFCZARV2.js → chunk-B7AVWSK2.js} +18 -8
  7. package/dist/chunk-B7AVWSK2.js.map +1 -0
  8. package/dist/{chunk-6HJVH27C.js → chunk-C2BSCEDN.js} +2 -2
  9. package/dist/{chunk-SNXEYAFP.js → chunk-CKBWEWHZ.js} +60 -30
  10. package/dist/chunk-CKBWEWHZ.js.map +1 -0
  11. package/dist/{chunk-SI2LLEIR.js → chunk-EC3JXT23.js} +4 -4
  12. package/dist/{chunk-YM3VEDAP.js → chunk-ENET4IF6.js} +440 -192
  13. package/dist/chunk-ENET4IF6.js.map +1 -0
  14. package/dist/{chunk-ICHWAFAC.js → chunk-FACDJH6O.js} +11 -104
  15. package/dist/chunk-FACDJH6O.js.map +1 -0
  16. package/dist/{chunk-P5XEK7HC.js → chunk-H6WUOW5F.js} +2 -2
  17. package/dist/{chunk-DQB3E2SX.js → chunk-JNRACLNS.js} +3 -3
  18. package/dist/{chunk-37QFHJUW.js → chunk-JTMSFBCA.js} +106 -28
  19. package/dist/chunk-JTMSFBCA.js.map +1 -0
  20. package/dist/{chunk-GNMRXXRY.js → chunk-MQZNDK5F.js} +3 -3
  21. package/dist/chunk-MQZNDK5F.js.map +1 -0
  22. package/dist/{chunk-SRII2GMF.js → chunk-SN64WNWE.js} +2 -2
  23. package/dist/{chunk-EHEBN4NB.js → chunk-U672FZVC.js} +2 -2
  24. package/dist/{chunk-TG3SPPZY.js → chunk-UE4Z3YMB.js} +1 -1
  25. package/dist/chunk-UE4Z3YMB.js.map +1 -0
  26. package/dist/{chunk-Q4NWATGH.js → chunk-XMQIWPIR.js} +58 -10
  27. package/dist/chunk-XMQIWPIR.js.map +1 -0
  28. package/dist/{chunk-YLFKFVQP.js → chunk-ZBI6GFJD.js} +2 -2
  29. package/dist/commands/build/marketplace.js +4 -3
  30. package/dist/commands/build/marketplace.js.map +1 -1
  31. package/dist/commands/build/plugins.js +6 -5
  32. package/dist/commands/build/plugins.js.map +1 -1
  33. package/dist/commands/compile.js +15 -11
  34. package/dist/commands/compile.js.map +1 -1
  35. package/dist/commands/doctor.js +38 -14
  36. package/dist/commands/doctor.js.map +1 -1
  37. package/dist/commands/edit.js +46 -25
  38. package/dist/commands/edit.js.map +1 -1
  39. package/dist/commands/eject.js +12 -8
  40. package/dist/commands/eject.js.map +1 -1
  41. package/dist/commands/init.js +15 -14
  42. package/dist/commands/list.js +8 -6
  43. package/dist/commands/list.js.map +1 -1
  44. package/dist/commands/new/marketplace.js +4 -3
  45. package/dist/commands/new/marketplace.js.map +1 -1
  46. package/dist/commands/search.js +13 -8
  47. package/dist/commands/search.js.map +1 -1
  48. package/dist/commands/share.js +14 -16
  49. package/dist/commands/share.js.map +1 -1
  50. package/dist/commands/uninstall.js +18 -14
  51. package/dist/commands/uninstall.js.map +1 -1
  52. package/dist/commands/update.js +97 -17
  53. package/dist/commands/update.js.map +1 -1
  54. package/dist/components/common/skill-agent-summary.js +3 -2
  55. package/dist/components/common/summary-panel.js +4 -3
  56. package/dist/hooks/init.js +15 -14
  57. package/dist/hooks/init.js.map +1 -1
  58. package/dist/load-agent-defs-5BSECHE6.js +14 -0
  59. package/dist/{recompile-project-agents-2QTFMYDC.js → recompile-project-agents-U3UGHPWG.js} +7 -7
  60. package/dist/{source-loader-I6SWWDUF.js → source-loader-E2Y5MMN5.js} +3 -3
  61. package/package.json +1 -1
  62. package/dist/chunk-37QFHJUW.js.map +0 -1
  63. package/dist/chunk-EGC7PNDI.js.map +0 -1
  64. package/dist/chunk-GNMRXXRY.js.map +0 -1
  65. package/dist/chunk-ICHWAFAC.js.map +0 -1
  66. package/dist/chunk-MFCZARV2.js.map +0 -1
  67. package/dist/chunk-Q4NWATGH.js.map +0 -1
  68. package/dist/chunk-SNXEYAFP.js.map +0 -1
  69. package/dist/chunk-TG3SPPZY.js.map +0 -1
  70. package/dist/chunk-YM3VEDAP.js.map +0 -1
  71. package/dist/load-agent-defs-BJ4KBKBA.js +0 -14
  72. /package/dist/{chunk-6HJVH27C.js.map → chunk-C2BSCEDN.js.map} +0 -0
  73. /package/dist/{chunk-SI2LLEIR.js.map → chunk-EC3JXT23.js.map} +0 -0
  74. /package/dist/{chunk-P5XEK7HC.js.map → chunk-H6WUOW5F.js.map} +0 -0
  75. /package/dist/{chunk-DQB3E2SX.js.map → chunk-JNRACLNS.js.map} +0 -0
  76. /package/dist/{chunk-SRII2GMF.js.map → chunk-SN64WNWE.js.map} +0 -0
  77. /package/dist/{chunk-EHEBN4NB.js.map → chunk-U672FZVC.js.map} +0 -0
  78. /package/dist/{chunk-YLFKFVQP.js.map → chunk-ZBI6GFJD.js.map} +0 -0
  79. /package/dist/{load-agent-defs-BJ4KBKBA.js.map → load-agent-defs-5BSECHE6.js.map} +0 -0
  80. /package/dist/{recompile-project-agents-2QTFMYDC.js.map → recompile-project-agents-U3UGHPWG.js.map} +0 -0
  81. /package/dist/{source-loader-I6SWWDUF.js.map → source-loader-E2Y5MMN5.js.map} +0 -0
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  pruneStaleCompiledAgents,
4
4
  recompileAgents
5
- } from "./chunk-GNMRXXRY.js";
5
+ } from "./chunk-MQZNDK5F.js";
6
6
  import {
7
7
  agentCodec,
8
8
  buildAgentScopeMap,
@@ -14,6 +14,7 @@ import {
14
14
  hostAt,
15
15
  inheritedGlobalProvider,
16
16
  isHomeDirectory,
17
+ listDirectories,
17
18
  loadProjectConfigFromDir,
18
19
  loadSkillsFromDir,
19
20
  loadSkillsMatrixFromSource,
@@ -26,27 +27,35 @@ import {
26
27
  skillsDir,
27
28
  skillsPathPrefix,
28
29
  verbose
29
- } from "./chunk-YM3VEDAP.js";
30
+ } from "./chunk-ENET4IF6.js";
30
31
  import {
31
32
  initializeMatrix,
32
33
  matrix,
33
34
  typedEntries,
34
35
  typedKeys
35
- } from "./chunk-TG3SPPZY.js";
36
+ } from "./chunk-UE4Z3YMB.js";
36
37
  import {
38
+ EJECT_SOURCE,
37
39
  globalInstallRoot
38
40
  } from "./chunk-U46LYYRA.js";
39
41
 
40
42
  // src/cli/lib/operations/skills/discover-skills.ts
43
+ import path from "path";
41
44
  var NO_LOCAL_SKILLS = { skills: {}, unusableMetadata: [] };
42
45
  async function discoverLocalProjectSkills(projectDir, scope) {
43
46
  const provider = providerAtScope(projectDir, scope);
47
+ const pathPrefix = skillsPathPrefix(provider, scope, projectDir);
44
48
  const scan = () => loadSkillsFromDir(skillsDir(provider, scope, projectDir), {
45
- pathPrefix: skillsPathPrefix(provider, scope, projectDir),
46
- requireMetadata: true
49
+ pathPrefix,
50
+ requireMetadata: true,
51
+ folderLabel: folderLabelAt(pathPrefix, scope)
47
52
  });
48
53
  return scope === "global" ? sayingEachWarningOnce(scan) : scan();
49
54
  }
55
+ function folderLabelAt(pathPrefix, scope) {
56
+ const underHome = scope === "global" && !path.isAbsolute(pathPrefix);
57
+ return underHome ? `~/${pathPrefix}/` : `${pathPrefix}/`;
58
+ }
50
59
  function skillsRootAt(projectDir, scope) {
51
60
  return skillsDir(providerAtScope(projectDir, scope), scope, projectDir);
52
61
  }
@@ -122,6 +131,7 @@ function skillCount(skills) {
122
131
  }
123
132
 
124
133
  // src/cli/lib/operations/skills/copy-local-skills.ts
134
+ import path2 from "path";
125
135
  async function copyScopedLocalSkills(scopeSkills, skillsDir2, sourceResult) {
126
136
  if (scopeSkills.length === 0) return [];
127
137
  await ensureDir(skillsDir2);
@@ -152,6 +162,22 @@ async function copyLocalSkills(skills, projectDir, sourceResult) {
152
162
  totalCopied: projectCopied.length + globalCopied.length
153
163
  };
154
164
  }
165
+ async function skillFoldersAt(projectDir) {
166
+ const skillsDirs = [
167
+ resolveInstallPaths(projectDir, "project").skillsDir,
168
+ resolveInstallPaths(projectDir, "global").skillsDir
169
+ ];
170
+ const folders = await Promise.all(skillsDirs.map(foldersIn));
171
+ return new Set(folders.flat());
172
+ }
173
+ async function foldersIn(dir) {
174
+ return (await listDirectories(dir)).map((name) => path2.join(dir, name));
175
+ }
176
+ async function removeSkillFoldersCreatedSince(before, projectDir) {
177
+ const created = [...await skillFoldersAt(projectDir)].filter((folder) => !before.has(folder));
178
+ await Promise.all(created.map(remove));
179
+ return new Set(created);
180
+ }
155
181
 
156
182
  // src/cli/lib/operations/skills/uninstall-plugin-skills.ts
157
183
  var SCOPE_OF_AN_UNRECORDED_SKILL = "project";
@@ -162,9 +188,13 @@ async function uninstallPluginSkills(skillIds, oldSkills, marketplace, projectDi
162
188
  for (const skillId of skillIds) {
163
189
  const oldSkill = oldSkills.find((s) => s.id === skillId);
164
190
  const pluginScope = oldSkill?.scope ?? SCOPE_OF_AN_UNRECORDED_SKILL;
165
- const pluginRef = buildMarketplacePluginRef(skillId, marketplace);
166
191
  try {
167
- const outcome = await host.uninstallPlugin(pluginRef, pluginScope, projectDir);
192
+ const outcome = await removeUnderFirstNameHeld(
193
+ host,
194
+ pluginRefsOf(skillId, oldSkill?.origin, marketplace),
195
+ pluginScope,
196
+ projectDir
197
+ );
168
198
  if (outcome === "removed") uninstalled.push(skillId);
169
199
  } catch (error) {
170
200
  failed.push({ id: skillId, error: getErrorMessage(error) });
@@ -172,6 +202,20 @@ async function uninstallPluginSkills(skillIds, oldSkills, marketplace, projectDi
172
202
  }
173
203
  return { uninstalled, failed };
174
204
  }
205
+ function pluginRefsOf(skillId, origin, marketplace) {
206
+ const marketplaceRef = buildMarketplacePluginRef(skillId, marketplace);
207
+ if (origin === void 0 || origin === marketplace || origin === EJECT_SOURCE) {
208
+ return [marketplaceRef];
209
+ }
210
+ return [buildMarketplacePluginRef(skillId, origin), marketplaceRef];
211
+ }
212
+ async function removeUnderFirstNameHeld(host, pluginRefs, scope, projectDir) {
213
+ for (const pluginRef of pluginRefs) {
214
+ const outcome = await host.uninstallPlugin(pluginRef, scope, projectDir);
215
+ if (outcome === "removed") return outcome;
216
+ }
217
+ return "absent";
218
+ }
175
219
 
176
220
  // src/cli/lib/loading/catalogue-seat.ts
177
221
  async function withCatalogueSeatedFor(projectDir, body) {
@@ -190,7 +234,7 @@ async function withCatalogueSeatedFor(projectDir, body) {
190
234
  }
191
235
 
192
236
  // src/cli/lib/operations/project/remove-compiled-agents.ts
193
- import path from "path";
237
+ import path3 from "path";
194
238
  async function removeCompiledAgents(options) {
195
239
  const outcomes = await Promise.all(
196
240
  options.agents.map((name) => removeCompiledAgentFile(options.agentsDir, name))
@@ -209,7 +253,7 @@ async function pruneCompiledAgents(options) {
209
253
  }
210
254
  async function removeCompiledAgentFile(agentsDir, name) {
211
255
  try {
212
- await remove(path.join(agentsDir, `${name}${agentCodec("claude").extension}`));
256
+ await remove(path3.join(agentsDir, `${name}${agentCodec("claude").extension}`));
213
257
  return { name, ok: true };
214
258
  } catch (error) {
215
259
  return { name, ok: false, error: getErrorMessage(error) };
@@ -273,9 +317,13 @@ async function pruneStaleAgentsForPass(options, provider, recompileResult) {
273
317
  export {
274
318
  discoverInstalledSkills,
275
319
  copyLocalSkills,
320
+ skillFoldersAt,
321
+ removeSkillFoldersCreatedSince,
276
322
  uninstallPluginSkills,
323
+ pluginRefsOf,
324
+ removeUnderFirstNameHeld,
277
325
  withCatalogueSeatedFor,
278
326
  removeCompiledAgents,
279
327
  compileAgents
280
328
  };
281
- //# sourceMappingURL=chunk-Q4NWATGH.js.map
329
+ //# sourceMappingURL=chunk-XMQIWPIR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/lib/operations/skills/discover-skills.ts","../src/cli/lib/operations/skills/copy-local-skills.ts","../src/cli/lib/operations/skills/uninstall-plugin-skills.ts","../src/cli/lib/loading/catalogue-seat.ts","../src/cli/lib/operations/project/remove-compiled-agents.ts","../src/cli/lib/operations/project/compile-agents.ts"],"sourcesContent":["import path from \"path\";\n\nimport { discoverAllPluginSkills } from \"../../plugins/index.js\";\nimport { isHomeDirectory } from \"../../installation/is-home-directory.js\";\nimport { loadSkillsFromDir, type LoadedSkills } from \"../../loading/index.js\";\nimport { sayingEachWarningOnce, verbose } from \"../../../utils/logger.js\";\nimport { globalInstallRoot } from \"../../../consts.js\";\nimport {\n inheritedGlobalProvider,\n providerAtScope,\n skillsDir,\n skillsPathPrefix,\n} from \"../../installation/install-layout.js\";\nimport { typedEntries, typedKeys } from \"../../../utils/typed-object.js\";\nimport type { UnusableSkillMetadata } from \"../../loading/index.js\";\nimport type {\n SkillDefinition,\n SkillDefinitionMap,\n SkillId,\n SkillScope,\n} from \"../../../types/index.js\";\n\nexport type DiscoveredSkills = {\n allSkills: SkillDefinitionMap;\n totalSkillCount: number;\n pluginSkillCount: number;\n globalPluginSkillCount: number;\n globalLocalSkillCount: number;\n /** Skills whose metadata.yaml describes no skill; `compile` refuses over any entry. */\n unusableMetadata: UnusableSkillMetadata[];\n};\n\nconst NO_LOCAL_SKILLS: LoadedSkills = { skills: {}, unusableMetadata: [] };\n\n/**\n * Discovers copied-in (not plugin) skills at one scope. A global scan's warnings are said once per\n * run, since the fan-out asks for that one directory once per registered project.\n */\nasync function discoverLocalProjectSkills(\n projectDir: string,\n scope: SkillScope,\n): Promise<LoadedSkills> {\n const provider = providerAtScope(projectDir, scope);\n const pathPrefix = skillsPathPrefix(provider, scope, projectDir);\n const scan = () =>\n loadSkillsFromDir(skillsDir(provider, scope, projectDir), {\n pathPrefix,\n requireMetadata: true,\n folderLabel: folderLabelAt(pathPrefix, scope),\n });\n\n return scope === \"global\" ? sayingEachWarningOnce(scan) : scan();\n}\n\n/** From `~/`: saying it once per run matches on text, so it must never equal a project's line. */\nfunction folderLabelAt(pathPrefix: string, scope: SkillScope): string {\n const underHome = scope === \"global\" && !path.isAbsolute(pathPrefix);\n return underHome ? `~/${pathPrefix}/` : `${pathPrefix}/`;\n}\n\nfunction skillsRootAt(projectDir: string, scope: SkillScope): string {\n return skillsDir(providerAtScope(projectDir, scope), scope, projectDir);\n}\n\n/** Later sources win. */\nfunction mergeSkills(...skillSources: SkillDefinitionMap[]): SkillDefinitionMap {\n const merged: SkillDefinitionMap = {};\n\n for (const source of skillSources) {\n for (const [id, skill] of typedEntries<SkillId, SkillDefinition | undefined>(source)) {\n if (skill) {\n merged[id] = skill;\n }\n }\n }\n\n return merged;\n}\n\n/** Merges global plugins, global copied-in, project plugins, project copied-in; project wins. */\nexport async function discoverInstalledSkills(projectDir: string): Promise<DiscoveredSkills> {\n const isGlobalProject = isHomeDirectory(projectDir);\n\n const globalPlugins = isGlobalProject ? {} : await discoverGlobalPluginSkills(projectDir);\n const globalLocal = isGlobalProject\n ? NO_LOCAL_SKILLS\n : await discoverGlobalLocalSkills(projectDir);\n const projectPlugins = await discoverProjectPluginSkills(projectDir);\n // At the home root both scopes are one installation, so ask the global scope only.\n const localScope: SkillScope = isGlobalProject ? \"global\" : \"project\";\n const projectLocal = await discoverLocalSkillsAt(projectDir, localScope);\n\n return assembleDiscoveredSkills({ globalPlugins, globalLocal, projectPlugins, projectLocal });\n}\n\nasync function discoverGlobalPluginSkills(projectDir: string): Promise<SkillDefinitionMap> {\n const skills = await discoverAllPluginSkills(\n globalInstallRoot(),\n inheritedGlobalProvider(projectDir),\n );\n const count = skillCount(skills);\n if (count > 0) verbose(` Found ${count} skills from global plugins`);\n return skills;\n}\n\nasync function discoverGlobalLocalSkills(projectDir: string): Promise<LoadedSkills> {\n const loaded = await discoverLocalProjectSkills(projectDir, \"global\");\n const count = skillCount(loaded.skills);\n if (count > 0) {\n verbose(` Found ${count} global local skills from ${skillsRootAt(projectDir, \"global\")}`);\n }\n return loaded;\n}\n\nasync function discoverProjectPluginSkills(projectDir: string): Promise<SkillDefinitionMap> {\n const skills = await discoverAllPluginSkills(projectDir);\n verbose(` Found ${skillCount(skills)} skills from installed plugins`);\n return skills;\n}\n\nasync function discoverLocalSkillsAt(projectDir: string, scope: SkillScope): Promise<LoadedSkills> {\n const loaded = await discoverLocalProjectSkills(projectDir, scope);\n verbose(\n ` Found ${skillCount(loaded.skills)} local skills from ${skillsRootAt(projectDir, scope)}`,\n );\n return loaded;\n}\n\ntype SkillsByOrigin = {\n globalPlugins: SkillDefinitionMap;\n globalLocal: LoadedSkills;\n projectPlugins: SkillDefinitionMap;\n projectLocal: LoadedSkills;\n};\n\nfunction assembleDiscoveredSkills(found: SkillsByOrigin): DiscoveredSkills {\n const { globalPlugins, globalLocal, projectPlugins, projectLocal } = found;\n const allSkills = mergeSkills(\n globalPlugins,\n globalLocal.skills,\n projectPlugins,\n projectLocal.skills,\n );\n // A plugin installed at both scopes is listed by both, but is one skill.\n const distinctPluginSkills = mergeSkills(globalPlugins, projectPlugins);\n\n return {\n allSkills,\n totalSkillCount: skillCount(allSkills),\n pluginSkillCount: skillCount(distinctPluginSkills),\n globalPluginSkillCount: skillCount(globalPlugins),\n globalLocalSkillCount: skillCount(globalLocal.skills),\n unusableMetadata: [...globalLocal.unusableMetadata, ...projectLocal.unusableMetadata],\n };\n}\n\nfunction skillCount(skills: SkillDefinitionMap): number {\n return typedKeys<SkillId>(skills).length;\n}\n","import path from \"path\";\nimport { resolveInstallPaths } from \"../../installation/index.js\";\nimport { copySkillsToLocalFlattened, type CopiedSkill } from \"../../skills/index.js\";\nimport { ensureDir, listDirectories, remove } from \"../../../utils/fs.js\";\nimport type { SkillConfig } from \"../../../types/config.js\";\nimport type { SourceLoadResult } from \"../../loading/source-loader.js\";\n\nexport type SkillCopyResult = {\n projectCopied: CopiedSkill[];\n globalCopied: CopiedSkill[];\n totalCopied: number;\n};\n\nasync function copyScopedLocalSkills(\n scopeSkills: SkillConfig[],\n skillsDir: string,\n sourceResult: SourceLoadResult,\n): Promise<CopiedSkill[]> {\n if (scopeSkills.length === 0) return [];\n\n await ensureDir(skillsDir);\n\n return copySkillsToLocalFlattened(\n scopeSkills.map((s) => s.id),\n skillsDir,\n sourceResult,\n );\n}\n\nexport async function copyLocalSkills(\n skills: SkillConfig[],\n projectDir: string,\n sourceResult: SourceLoadResult,\n): Promise<SkillCopyResult> {\n const projectLocalSkills = skills.filter((s) => s.scope !== \"global\");\n const globalLocalSkills = skills.filter((s) => s.scope === \"global\");\n\n const projectPaths = resolveInstallPaths(projectDir, \"project\");\n const globalPaths = resolveInstallPaths(projectDir, \"global\");\n\n const projectCopied = await copyScopedLocalSkills(\n projectLocalSkills,\n projectPaths.skillsDir,\n sourceResult,\n );\n const globalCopied = await copyScopedLocalSkills(\n globalLocalSkills,\n globalPaths.skillsDir,\n sourceResult,\n );\n\n return {\n projectCopied,\n globalCopied,\n totalCopied: projectCopied.length + globalCopied.length,\n };\n}\n\n/** Every skill folder at both scopes, as a full path. */\nexport async function skillFoldersAt(projectDir: string): Promise<ReadonlySet<string>> {\n const skillsDirs = [\n resolveInstallPaths(projectDir, \"project\").skillsDir,\n resolveInstallPaths(projectDir, \"global\").skillsDir,\n ];\n const folders = await Promise.all(skillsDirs.map(foldersIn));\n return new Set(folders.flat());\n}\n\nasync function foldersIn(dir: string): Promise<string[]> {\n return (await listDirectories(dir)).map((name) => path.join(dir, name));\n}\n\n/** A folder already in `before` stays, whatever was written into it since. */\nexport async function removeSkillFoldersCreatedSince(\n before: ReadonlySet<string>,\n projectDir: string,\n): Promise<ReadonlySet<string>> {\n const created = [...(await skillFoldersAt(projectDir))].filter((folder) => !before.has(folder));\n await Promise.all(created.map(remove));\n return new Set(created);\n}\n","import { hostAt } from \"../../hosts/host-for.js\";\nimport type { PluginHost, PluginRemovalOutcome } from \"../../hosts/plugin-host.js\";\nimport { buildMarketplacePluginRef } from \"../../plugins/index.js\";\nimport { EJECT_SOURCE } from \"../../../consts.js\";\nimport { getErrorMessage } from \"../../../utils/errors.js\";\nimport type { SkillId } from \"../../../types/index.js\";\nimport type { SkillConfig, SkillScope } from \"../../../types/config.js\";\n\n/** The safe default: a project removal cannot take a plugin from every project under one HOME. */\nconst SCOPE_OF_AN_UNRECORDED_SKILL: SkillScope = \"project\";\n\nexport type PluginUninstallResult = {\n /** Only plugins the host reported `removed`; an already-absent plugin is not listed. */\n uninstalled: SkillId[];\n failed: Array<{ id: SkillId; error: string }>;\n};\n\nexport async function uninstallPluginSkills(\n skillIds: SkillId[],\n oldSkills: SkillConfig[],\n marketplace: string,\n projectDir: string,\n): Promise<PluginUninstallResult> {\n const host = hostAt(projectDir);\n const uninstalled: SkillId[] = [];\n const failed: PluginUninstallResult[\"failed\"] = [];\n\n for (const skillId of skillIds) {\n const oldSkill = oldSkills.find((s) => s.id === skillId);\n const pluginScope = oldSkill?.scope ?? SCOPE_OF_AN_UNRECORDED_SKILL;\n try {\n const outcome = await removeUnderFirstNameHeld(\n host,\n pluginRefsOf(skillId, oldSkill?.origin, marketplace),\n pluginScope,\n projectDir,\n );\n if (outcome === \"removed\") uninstalled.push(skillId);\n } catch (error) {\n failed.push({ id: skillId, error: getErrorMessage(error) });\n }\n }\n\n return { uninstalled, failed };\n}\n\n/**\n * The name its install recorded, then the installation's marketplace's, as `uninstall` asks: a\n * project can leave a plugin from its own marketplace at global scope.\n */\nexport function pluginRefsOf(\n skillId: SkillId,\n origin: string | undefined,\n marketplace: string,\n): string[] {\n const marketplaceRef = buildMarketplacePluginRef(skillId, marketplace);\n if (origin === undefined || origin === marketplace || origin === EJECT_SOURCE) {\n return [marketplaceRef];\n }\n return [buildMarketplacePluginRef(skillId, origin), marketplaceRef];\n}\n\n/** `absent` passes the ask to the next name; a throw is a real failure and ends it. */\nexport async function removeUnderFirstNameHeld(\n host: PluginHost,\n pluginRefs: string[],\n scope: SkillScope,\n projectDir: string,\n): Promise<PluginRemovalOutcome> {\n for (const pluginRef of pluginRefs) {\n const outcome = await host.uninstallPlugin(pluginRef, scope, projectDir);\n if (outcome === \"removed\") return outcome;\n }\n return \"absent\";\n}\n","import type { MergedSkillsMatrix } from \"../../types\";\nimport { initializeMatrix, matrix } from \"../matrix/matrix-provider.js\";\nimport { loadSkillsMatrixFromSource } from \"./source-loader.js\";\n\n/**\n * Runs `body` against `projectDir`'s own skills catalogue, then restores the caller's. The load\n * stays outside the `try`: a failed load seats nothing, so there is nothing to restore.\n */\nexport async function withCatalogueSeatedFor<T>(\n projectDir: string,\n body: (catalogue: MergedSkillsMatrix) => Promise<T>,\n): Promise<T> {\n const callersCatalogue = matrix;\n const { matrix: seated } = await loadSkillsMatrixFromSource({\n projectDir,\n purpose: \"upkeep\",\n skipExtraSources: true,\n matrixOnly: true,\n });\n try {\n return await body(seated);\n } finally {\n initializeMatrix(callersCatalogue);\n }\n}\n","import path from \"path\";\nimport { pruneStaleCompiledAgents } from \"../../agents/list-compiled-agents.js\";\nimport { type AgentCodec, agentCodec } from \"../../installation/install-layout.js\";\nimport { getErrorMessage } from \"../../../utils/errors.js\";\nimport { remove, removeDirIfEmpty } from \"../../../utils/fs.js\";\nimport type { AgentName } from \"../../../types/index.js\";\n\nexport type RemoveCompiledAgentsOptions = {\n agentsDir: string;\n agents: readonly AgentName[];\n};\n\nexport type PruneCompiledAgentsOptions = {\n agentsDir: string;\n /** The COMPLETE set of agents that belong in `agentsDir`; every other compiled agent is stale. */\n keep: ReadonlySet<AgentName>;\n codec?: AgentCodec;\n};\n\nexport type RemoveCompiledAgentsResult = {\n /** An absent file counts as removed. */\n removed: AgentName[];\n failed: Array<{ name: AgentName; error: string }>;\n};\n\ntype RemovalOutcome = { name: AgentName; ok: true } | { name: AgentName; ok: false; error: string };\n\n/**\n * Also removes `agentsDir` when nothing at all is left in it; the `.claude/` above is uninstall's.\n */\nexport async function removeCompiledAgents(\n options: RemoveCompiledAgentsOptions,\n): Promise<RemoveCompiledAgentsResult> {\n const outcomes = await Promise.all(\n options.agents.map((name) => removeCompiledAgentFile(options.agentsDir, name)),\n );\n await removeDirIfEmpty(options.agentsDir);\n\n return {\n removed: outcomes.flatMap((outcome) => (outcome.ok ? [outcome.name] : [])),\n failed: outcomes.flatMap((outcome) =>\n outcome.ok ? [] : [{ name: outcome.name, error: outcome.error }],\n ),\n };\n}\n\n/** Hand-authored agents survive; the directory goes only when nothing at all remains. */\nexport async function pruneCompiledAgents(options: PruneCompiledAgentsOptions): Promise<void> {\n await pruneStaleCompiledAgents(options.agentsDir, options.keep, options.codec);\n await removeDirIfEmpty(options.agentsDir);\n}\n\nasync function removeCompiledAgentFile(\n agentsDir: string,\n name: AgentName,\n): Promise<RemovalOutcome> {\n try {\n await remove(path.join(agentsDir, `${name}${agentCodec(\"claude\").extension}`));\n return { name, ok: true };\n } catch (error) {\n return { name, ok: false, error: getErrorMessage(error) };\n }\n}\n","import { pruneCompiledAgents } from \"./remove-compiled-agents.js\";\nimport { recompileAgents } from \"../../agents/index.js\";\nimport { loadProjectConfigFromDir } from \"../../configuration/project-config.js\";\nimport { buildAgentScopeMap } from \"../../installation/index.js\";\nimport { agentCodec, providerInUse } from \"../../installation/install-layout.js\";\nimport type { Provider } from \"../../../consts.js\";\nimport type { AgentName, SkillDefinitionMap, SkillScope } from \"../../../types/index.js\";\n\nexport type CompileAgentsOptions = {\n projectDir: string;\n /** The installation compiled, where `projectDir` holds two; the default is the one in use. */\n provider?: Provider;\n sourcePath: string;\n pluginDir?: string;\n skills?: SkillDefinitionMap;\n agentScopeMap?: Map<AgentName, SkillScope>;\n agents?: AgentName[];\n scopeFilter?: SkillScope;\n outputDir?: string;\n};\n\nexport type CompilationResult = {\n compiled: AgentName[];\n /** The subset of `compiled` whose file this pass actually wrote. */\n rewritten: AgentName[];\n failed: AgentName[];\n warnings: string[];\n};\n\nexport async function compileAgents(options: CompileAgentsOptions): Promise<CompilationResult> {\n const provider = options.provider ?? providerInUse(options.projectDir);\n const roster = await rosterForPass(options, provider);\n\n const recompileResult = await recompileAgents({\n pluginDir: options.pluginDir ?? options.projectDir,\n sourcePath: options.sourcePath,\n ...(roster.agents !== undefined && { agents: roster.agents }),\n ...(options.skills !== undefined && { skills: options.skills }),\n projectDir: options.projectDir,\n provider,\n ...(options.outputDir !== undefined && { outputDir: options.outputDir }),\n ...(roster.agentScopeMap !== undefined && { agentScopeMap: roster.agentScopeMap }),\n });\n\n await pruneStaleAgentsForPass(options, provider, recompileResult);\n\n return {\n compiled: recompileResult.compiled,\n rewritten: recompileResult.rewritten,\n failed: recompileResult.failed,\n warnings: recompileResult.warnings,\n };\n}\n\ntype PassRoster = {\n agents: AgentName[] | undefined;\n agentScopeMap: Map<AgentName, SkillScope> | undefined;\n};\n\nasync function rosterForPass(\n options: CompileAgentsOptions,\n provider: Provider,\n): Promise<PassRoster> {\n if (!options.scopeFilter) return { agents: options.agents, agentScopeMap: options.agentScopeMap };\n return rosterForScope(options, options.scopeFilter, provider);\n}\n\nasync function rosterForScope(\n options: CompileAgentsOptions,\n scope: SkillScope,\n provider: Provider,\n): Promise<PassRoster> {\n const config = (await loadProjectConfigFromDir(options.projectDir, provider))?.config;\n const activeAtScope = config?.agents\n .filter((agent) => !agent.excluded && agent.scope === scope)\n .map((agent) => agent.name);\n\n return {\n agents: requestedAgentsAmong(options.agents, activeAtScope),\n agentScopeMap: options.agentScopeMap ?? (config ? buildAgentScopeMap(config) : undefined),\n };\n}\n\nfunction requestedAgentsAmong(\n requested: AgentName[] | undefined,\n activeAtScope: AgentName[] | undefined,\n): AgentName[] | undefined {\n if (activeAtScope === undefined) return requested;\n if (requested === undefined) return activeAtScope;\n\n const atScope = new Set(activeAtScope);\n return requested.filter((name) => atScope.has(name));\n}\n\n/**\n * Only an unfiltered pass owns its whole `outputDir`, so only it prunes agents no longer compiled\n * there; a scope-filtered pass must never delete another scope's files.\n */\nasync function pruneStaleAgentsForPass(\n options: CompileAgentsOptions,\n provider: Provider,\n recompileResult: CompilationResult,\n): Promise<void> {\n if (options.scopeFilter || !options.outputDir) return;\n\n const compiledForDir = new Set<AgentName>([\n ...recompileResult.compiled,\n ...recompileResult.failed,\n ]);\n await pruneCompiledAgents({\n agentsDir: options.outputDir,\n keep: compiledForDir,\n // A Codex role is a `.toml`, so the prune must know the host's extension.\n codec: agentCodec(provider),\n });\n}\n"],"mappings":"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","names":["path","skillsDir","path","path","path"]}
@@ -6,7 +6,7 @@ import {
6
6
  hostFor,
7
7
  loadProjectConfigFromDir,
8
8
  refuseUnofferedPlacements
9
- } from "./chunk-YM3VEDAP.js";
9
+ } from "./chunk-ENET4IF6.js";
10
10
 
11
11
  // src/cli/lib/hosts/configured-placements.ts
12
12
  async function unofferablePlacementsFound(cwd) {
@@ -36,4 +36,4 @@ async function configuredSkillsAt({ dir, provider }) {
36
36
  export {
37
37
  unofferablePlacementsFound
38
38
  };
39
- //# sourceMappingURL=chunk-YLFKFVQP.js.map
39
+ //# sourceMappingURL=chunk-ZBI6GFJD.js.map
@@ -2,7 +2,8 @@
2
2
  import {
3
3
  BaseCommand,
4
4
  EXIT_CODES
5
- } from "../../chunk-37QFHJUW.js";
5
+ } from "../../chunk-JTMSFBCA.js";
6
+ import "../../chunk-FACDJH6O.js";
6
7
  import {
7
8
  NO_VALID_DEFAULT_EXPORT,
8
9
  configLoadFailure,
@@ -23,10 +24,10 @@ import {
23
24
  warn,
24
25
  writeFile,
25
26
  writeMarketplace
26
- } from "../../chunk-YM3VEDAP.js";
27
+ } from "../../chunk-ENET4IF6.js";
27
28
  import {
28
29
  plural
29
- } from "../../chunk-TG3SPPZY.js";
30
+ } from "../../chunk-UE4Z3YMB.js";
30
31
  import {
31
32
  CATALOG_JSON,
32
33
  CLI_INVOKE_COMMAND,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cli/commands/build/marketplace.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { sortBy } from \"remeda\";\nimport { z } from \"zod\";\n\nimport { BaseCommand } from \"../../base-command\";\nimport { setVerbose, warn } from \"../../utils/logger\";\nimport {\n configUnreadableError,\n marketplaceHasNoVersion,\n marketplaceNameNotPublishable,\n marketplaceOwnerHasNoName,\n} from \"../../utils/messages\";\nimport { readFile, writeFile } from \"../../utils/fs\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { EXIT_CODES } from \"../../lib/exit-codes\";\nimport { readSourceRepoConfig } from \"../../lib/configuration/config\";\nimport { configLoadFailure, NO_VALID_DEFAULT_EXPORT } from \"../../lib/configuration/config-loader\";\nimport { loadMarketplaceMatrix } from \"../../lib/loading\";\nimport {\n generateMarketplace,\n writeMarketplace,\n getMarketplaceStats,\n validateMarketplaceName,\n validateSkillIdNamespace,\n} from \"../../lib/marketplace-generator\";\nimport {\n CATALOG_JSON,\n CLI_INVOKE_COMMAND,\n GENERATED_AT_BUILD,\n MARKETPLACE_JSON,\n PLUGIN_MANIFEST_DIR,\n PLUGINS_DIST_PATH,\n STANDARD_FILES,\n} from \"../../consts\";\nimport type { Marketplace, MergedSkillsMatrix } from \"../../types\";\nimport { validateKebabCaseName } from \"../../lib/validate-kebab-name.js\";\nimport { plural } from \"../../utils/string.js\";\n\nconst DEFAULT_OUTPUT_FILE = `${PLUGIN_MANIFEST_DIR}/${MARKETPLACE_JSON}`;\n\nconst AUTHOR_STRING_PATTERN = /^(.*?)\\s*<([^>]+)>\\s*(?:\\(([^)]+)\\))?\\s*$/;\n\nconst MARKETPLACE_NOUN = \"Marketplace\";\n\nconst RESERVED_NAME_WAY_OUT = \"set package.json 'name', or pass --name\";\n\nconst packageAuthorObjectSchema = z.object({\n name: z.string(),\n email: z.string().exactOptional(),\n url: z.string().exactOptional(),\n});\n\nconst packageJsonSchema = z\n .object({\n name: z.string(),\n version: z.string(),\n description: z.string(),\n author: z.union([z.string(), packageAuthorObjectSchema]).exactOptional(),\n })\n .passthrough();\n\ntype PackageJson = z.infer<typeof packageJsonSchema>;\ntype MarketplaceIdentity = Pick<PackageJson, \"name\" | \"version\" | \"description\"> & {\n ownerName: string;\n ownerEmail?: string;\n};\n\nexport default class BuildMarketplace extends BaseCommand {\n static summary = \"Generate marketplace.json from built plugins (requires skills repo)\";\n\n static description =\n \"Generate marketplace.json from built plugins. This command scans the plugins directory and generates a marketplace manifest file. Reads marketplace identity (name, version, description, author) from package.json in the current working directory. Use --name to override the marketplace name when package.json uses an npm scoped name (e.g. @scope/pkg), which is not a valid marketplace name.\";\n\n static examples = [\n {\n description: \"Generate marketplace.json from the default plugins directory\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Generate marketplace.json from a custom plugins directory\",\n command: \"<%= config.bin %> <%= command.id %> --plugins-dir dist/stacks\",\n },\n {\n description: \"Write marketplace.json to a custom output path\",\n command: \"<%= config.bin %> <%= command.id %> --output .claude-plugin/market.json\",\n },\n {\n description:\n \"Override the marketplace name (use when package.json has an npm scoped name like @scope/pkg)\",\n command: \"<%= config.bin %> <%= command.id %> --name my-marketplace\",\n },\n ];\n\n static flags = {\n name: Flags.string({\n description:\n \"Override the marketplace name (defaults to package.json 'name'). Must be kebab-case.\",\n }),\n \"plugins-dir\": Flags.string({\n char: \"p\",\n description: \"Plugins directory\",\n default: PLUGINS_DIST_PATH,\n }),\n output: Flags.string({\n char: \"o\",\n description: \"Output file\",\n default: DEFAULT_OUTPUT_FILE,\n }),\n verbose: Flags.boolean({\n char: \"v\",\n description: \"Enable verbose logging\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(BuildMarketplace);\n setVerbose(flags.verbose);\n\n const projectRoot = process.cwd();\n const pluginsDir = path.resolve(projectRoot, flags[\"plugins-dir\"]);\n const outputPath = path.resolve(projectRoot, flags.output);\n const identity = await this.loadMarketplaceIdentity(projectRoot, flags.name);\n\n this.printHeader(pluginsDir, outputPath);\n\n try {\n // Read and refuse everything before the first write, so manifest and catalogue always agree.\n const marketplace = await this.scanPlugins(pluginsDir, flags[\"plugins-dir\"], identity);\n const catalog = await this.readCatalog(projectRoot);\n\n await this.writeManifest(outputPath, marketplace);\n await this.writeCatalog(outputPath, catalog);\n this.printStats(marketplace);\n this.printSample(marketplace);\n\n this.log(\"\");\n this.logSuccess(\n `Marketplace generated with ${plural(getMarketplaceStats(marketplace).total, \"plugin\")}!`,\n );\n this.log(\"\");\n } catch (error) {\n this.log(\"Generation failed\");\n this.handleError(error);\n }\n }\n\n private async loadMarketplaceIdentity(\n projectRoot: string,\n nameOverride?: string,\n ): Promise<MarketplaceIdentity> {\n const packageJsonPath = path.join(projectRoot, STANDARD_FILES.PACKAGE_JSON);\n const { name, version, description, author } = await this.readPackageJson(\n projectRoot,\n packageJsonPath,\n );\n\n if (version.trim() === \"\") {\n this.error(marketplaceHasNoVersion(packageJsonPath), { exit: EXIT_CODES.ERROR });\n }\n\n const owner = parseAuthor(author);\n if (owner.name.trim() === \"\") {\n this.error(marketplaceOwnerHasNoName(packageJsonPath), { exit: EXIT_CODES.ERROR });\n }\n\n const resolvedName = this.resolvePublishableName(name, nameOverride, packageJsonPath);\n\n const reservedError = validateMarketplaceName(resolvedName, name, RESERVED_NAME_WAY_OUT);\n if (reservedError) {\n this.error(reservedError, { exit: EXIT_CODES.ERROR });\n }\n\n return {\n name: resolvedName,\n version,\n description,\n ownerName: owner.name,\n ...(owner.email !== undefined && { ownerEmail: owner.email }),\n };\n }\n\n private async readPackageJson(\n projectRoot: string,\n packageJsonPath: string,\n ): Promise<PackageJson> {\n let rawContent: string;\n try {\n rawContent = await readFile(packageJsonPath);\n } catch {\n this.error(\n `Missing package.json at ${projectRoot}. build marketplace reads marketplace identity from package.json.`,\n { exit: EXIT_CODES.ERROR },\n );\n }\n\n let parsedJson: unknown;\n try {\n parsedJson = JSON.parse(rawContent);\n } catch (error) {\n this.error(`Failed to parse package.json at ${packageJsonPath}: ${getErrorMessage(error)}`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n const parseResult = packageJsonSchema.safeParse(parsedJson);\n if (!parseResult.success) {\n const missingFields = parseResult.error.issues.map((i) => i.path.join(\".\")).join(\", \");\n this.error(\n `package.json at ${packageJsonPath} is missing required fields: ${missingFields}. build marketplace reads marketplace identity from package.json.`,\n { exit: EXIT_CODES.ERROR },\n );\n }\n\n return parseResult.data;\n }\n\n /** A package.json name that fails gets a different refusal: its way out is `--name`. */\n private resolvePublishableName(\n packageName: string,\n nameOverride: string | undefined,\n packageJsonPath: string,\n ): string {\n if (nameOverride !== undefined) {\n const invalidOverride = validateKebabCaseName(nameOverride, MARKETPLACE_NOUN);\n if (invalidOverride) {\n this.error(`Invalid --name '${nameOverride}': ${invalidOverride}`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n return nameOverride;\n }\n\n if (validateKebabCaseName(packageName, MARKETPLACE_NOUN)) {\n this.error(marketplaceNameNotPublishable(packageName, packageJsonPath), {\n exit: EXIT_CODES.ERROR,\n });\n }\n return packageName;\n }\n\n private printHeader(pluginsDir: string, outputPath: string): void {\n this.log(\"\");\n this.log(\"Generating marketplace.json\");\n this.log(` Plugins directory: ${pluginsDir}`);\n this.log(` Output file: ${outputPath}`);\n this.log(\"\");\n }\n\n private async scanPlugins(\n pluginsDir: string,\n pluginsDirFlag: string,\n identity: MarketplaceIdentity,\n ): Promise<Marketplace> {\n this.log(\"Scanning plugins...\");\n\n const marketplace = await generateMarketplace(pluginsDir, {\n name: identity.name,\n version: identity.version,\n description: identity.description,\n ownerName: identity.ownerName,\n ...(identity.ownerEmail !== undefined && { ownerEmail: identity.ownerEmail }),\n pluginRoot: `./${pluginsDirFlag}`,\n });\n\n const stats = getMarketplaceStats(marketplace);\n this.log(`Found ${plural(stats.total, \"plugin\")}`);\n\n if (marketplace.plugins.length === 0) {\n this.error(noPluginsToPublish(pluginsDir, pluginsDirFlag), { exit: EXIT_CODES.ERROR });\n }\n\n const namespaceError = validateSkillIdNamespace(marketplace);\n if (namespaceError) {\n this.error(namespaceError, { exit: EXIT_CODES.ERROR });\n }\n\n return marketplace;\n }\n\n /** Unconditional: consumers must be able to read an absent catalogue as a broken marketplace. */\n private async readCatalog(projectRoot: string): Promise<MergedSkillsMatrix> {\n this.log(`Reading the skills for ${CATALOG_JSON}...`);\n await this.refuseAConfigDeclaringNothing(projectRoot);\n const matrix = await loadMarketplaceMatrix(projectRoot);\n return { ...matrix, generatedAt: GENERATED_AT_BUILD };\n }\n\n /** Every other reader takes such a file as absent; the build is where its author can fix it. */\n private async refuseAConfigDeclaringNothing(projectRoot: string): Promise<void> {\n const read = await readSourceRepoConfig(projectRoot);\n if (read.kind !== \"declares-nothing\") return;\n\n this.error(configUnreadableError(configLoadFailure(read.configPath, NO_VALID_DEFAULT_EXPORT)), {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n private async writeManifest(outputPath: string, marketplace: Marketplace): Promise<void> {\n this.log(`Writing ${MARKETPLACE_JSON}...`);\n await writeMarketplace(outputPath, marketplace);\n this.log(`Wrote ${outputPath}`);\n }\n\n private async writeCatalog(outputPath: string, catalog: MergedSkillsMatrix): Promise<void> {\n const catalogPath = path.join(path.dirname(outputPath), CATALOG_JSON);\n\n this.log(`Writing ${CATALOG_JSON}...`);\n await writeFile(catalogPath, `${JSON.stringify(catalog, null, 2)}\\n`);\n this.log(`Wrote ${catalogPath}`);\n }\n\n private printStats(marketplace: Marketplace): void {\n this.log(\"\");\n this.log(\"Category breakdown:\");\n const sortedCategories = sortBy(\n Object.entries(getMarketplaceStats(marketplace).byCategory),\n ([, count]) => -count,\n );\n for (const [category, count] of sortedCategories) {\n this.log(` ${category}: ${count}`);\n }\n }\n\n private printSample(marketplace: Marketplace): void {\n this.log(\"\");\n this.log(\"Sample plugins:\");\n const sampleSize = 5;\n for (const plugin of marketplace.plugins.slice(0, sampleSize)) {\n const version = plugin.version ? `v${plugin.version}` : \"\";\n const category = plugin.category ? `[${plugin.category}]` : \"\";\n this.log(` ${plugin.name} ${version} ${category}`);\n if (plugin.description) {\n this.log(` ${plugin.description}`);\n }\n }\n if (marketplace.plugins.length > sampleSize) {\n this.log(` ... and ${marketplace.plugins.length - sampleSize} more`);\n }\n }\n}\n\ntype ParsedAuthor = {\n name: string;\n email?: string;\n};\n\n/** The marketplace schema requires at least one plugin, so an empty manifest is never written. */\nfunction noPluginsToPublish(pluginsDir: string, pluginsDirFlag: string): string {\n return (\n `No plugins found in ${pluginsDir}. A marketplace with no plugins is refused when it is read ` +\n `back, so none was written. Run '${CLI_INVOKE_COMMAND} build plugins' first, or point ` +\n `--plugins-dir at the directory holding them (it is '${pluginsDirFlag}' for this run).`\n );\n}\n\n/** Accepts `\"Name <email> (url)\"` or `{ name, email, url }`; the caller refuses an empty name. */\nfunction parseAuthor(author: string | { name: string; email?: string } | undefined): ParsedAuthor {\n if (!author) return { name: \"\" };\n\n if (typeof author === \"object\") {\n return { name: author.name, ...(author.email !== undefined && { email: author.email }) };\n }\n\n const [, matchedName, matchedEmail] = author.match(AUTHOR_STRING_PATTERN) ?? [];\n if (matchedName !== undefined && matchedEmail !== undefined) {\n return { name: matchedName.trim(), email: matchedEmail.trim() };\n }\n\n warn(\n `package.json 'author' field \"${author}\" has no parseable email — marketplace owner.email will be empty`,\n );\n return { name: author.trim() };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/cli/commands/build/marketplace.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { sortBy } from \"remeda\";\nimport { z } from \"zod\";\n\nimport { BaseCommand } from \"../../base-command\";\nimport { setVerbose, warn } from \"../../utils/logger\";\nimport {\n configUnreadableError,\n marketplaceHasNoVersion,\n marketplaceNameNotPublishable,\n marketplaceOwnerHasNoName,\n} from \"../../utils/messages\";\nimport { readFile, writeFile } from \"../../utils/fs\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { EXIT_CODES } from \"../../lib/exit-codes\";\nimport { readSourceRepoConfig } from \"../../lib/configuration/config\";\nimport { configLoadFailure, NO_VALID_DEFAULT_EXPORT } from \"../../lib/configuration/config-loader\";\nimport { loadMarketplaceMatrix } from \"../../lib/loading\";\nimport {\n generateMarketplace,\n writeMarketplace,\n getMarketplaceStats,\n validateMarketplaceName,\n validateSkillIdNamespace,\n} from \"../../lib/marketplace-generator\";\nimport {\n CATALOG_JSON,\n CLI_INVOKE_COMMAND,\n GENERATED_AT_BUILD,\n MARKETPLACE_JSON,\n PLUGIN_MANIFEST_DIR,\n PLUGINS_DIST_PATH,\n STANDARD_FILES,\n} from \"../../consts\";\nimport type { Marketplace, MergedSkillsMatrix } from \"../../types\";\nimport { validateKebabCaseName } from \"../../lib/validate-kebab-name.js\";\nimport { plural } from \"../../utils/string.js\";\n\nconst DEFAULT_OUTPUT_FILE = `${PLUGIN_MANIFEST_DIR}/${MARKETPLACE_JSON}`;\n\nconst AUTHOR_STRING_PATTERN = /^(.*?)\\s*<([^>]+)>\\s*(?:\\(([^)]+)\\))?\\s*$/;\n\nconst MARKETPLACE_NOUN = \"Marketplace\";\n\nconst RESERVED_NAME_WAY_OUT = \"set package.json 'name', or pass --name\";\n\nconst packageAuthorObjectSchema = z.object({\n name: z.string(),\n email: z.string().exactOptional(),\n url: z.string().exactOptional(),\n});\n\nconst packageJsonSchema = z\n .object({\n name: z.string(),\n version: z.string(),\n description: z.string(),\n author: z.union([z.string(), packageAuthorObjectSchema]).exactOptional(),\n })\n .passthrough();\n\ntype PackageJson = z.infer<typeof packageJsonSchema>;\ntype MarketplaceIdentity = Pick<PackageJson, \"name\" | \"version\" | \"description\"> & {\n ownerName: string;\n ownerEmail?: string;\n};\n\nexport default class BuildMarketplace extends BaseCommand {\n static summary = \"Generate marketplace.json from built plugins (requires skills repo)\";\n\n static description =\n \"Generate marketplace.json from built plugins. This command scans the plugins directory and generates a marketplace manifest file. Reads marketplace identity (name, version, description, author) from package.json in the current working directory. Use --name to override the marketplace name when package.json uses an npm scoped name (e.g. @scope/pkg), which is not a valid marketplace name.\";\n\n static examples = [\n {\n description: \"Generate marketplace.json from the default plugins directory\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Generate marketplace.json from a custom plugins directory\",\n command: \"<%= config.bin %> <%= command.id %> --plugins-dir dist/stacks\",\n },\n {\n description: \"Write marketplace.json to a custom output path\",\n command: \"<%= config.bin %> <%= command.id %> --output .claude-plugin/market.json\",\n },\n {\n description:\n \"Override the marketplace name (use when package.json has an npm scoped name like @scope/pkg)\",\n command: \"<%= config.bin %> <%= command.id %> --name my-marketplace\",\n },\n ];\n\n static flags = {\n name: Flags.string({\n description:\n \"Override the marketplace name (defaults to package.json 'name'). Must be kebab-case.\",\n }),\n \"plugins-dir\": Flags.string({\n char: \"p\",\n description: \"Plugins directory\",\n default: PLUGINS_DIST_PATH,\n }),\n output: Flags.string({\n char: \"o\",\n description: \"Output file\",\n default: DEFAULT_OUTPUT_FILE,\n }),\n verbose: Flags.boolean({\n char: \"v\",\n description: \"Enable verbose logging\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(BuildMarketplace);\n setVerbose(flags.verbose);\n\n const projectRoot = process.cwd();\n const pluginsDir = path.resolve(projectRoot, flags[\"plugins-dir\"]);\n const outputPath = path.resolve(projectRoot, flags.output);\n const identity = await this.loadMarketplaceIdentity(projectRoot, flags.name);\n\n this.printHeader(pluginsDir, outputPath);\n\n try {\n // Read and refuse everything before the first write, so manifest and catalogue always agree.\n const marketplace = await this.scanPlugins(pluginsDir, flags[\"plugins-dir\"], identity);\n const catalog = await this.readCatalog(projectRoot);\n\n await this.writeManifest(outputPath, marketplace);\n await this.writeCatalog(outputPath, catalog);\n this.printStats(marketplace);\n this.printSample(marketplace);\n\n this.log(\"\");\n this.logSuccess(\n `Marketplace generated with ${plural(getMarketplaceStats(marketplace).total, \"plugin\")}!`,\n );\n this.log(\"\");\n } catch (error) {\n this.log(\"Generation failed\");\n this.handleError(error);\n }\n }\n\n private async loadMarketplaceIdentity(\n projectRoot: string,\n nameOverride?: string,\n ): Promise<MarketplaceIdentity> {\n const packageJsonPath = path.join(projectRoot, STANDARD_FILES.PACKAGE_JSON);\n const { name, version, description, author } = await this.readPackageJson(\n projectRoot,\n packageJsonPath,\n );\n\n if (version.trim() === \"\") {\n this.error(marketplaceHasNoVersion(packageJsonPath), { exit: EXIT_CODES.ERROR });\n }\n\n const owner = parseAuthor(author);\n if (owner.name.trim() === \"\") {\n this.error(marketplaceOwnerHasNoName(packageJsonPath), { exit: EXIT_CODES.ERROR });\n }\n\n const resolvedName = this.resolvePublishableName(name, nameOverride, packageJsonPath);\n\n const reservedError = validateMarketplaceName(resolvedName, name, RESERVED_NAME_WAY_OUT);\n if (reservedError) {\n this.error(reservedError, { exit: EXIT_CODES.ERROR });\n }\n\n return {\n name: resolvedName,\n version,\n description,\n ownerName: owner.name,\n ...(owner.email !== undefined && { ownerEmail: owner.email }),\n };\n }\n\n private async readPackageJson(\n projectRoot: string,\n packageJsonPath: string,\n ): Promise<PackageJson> {\n let rawContent: string;\n try {\n rawContent = await readFile(packageJsonPath);\n } catch {\n this.error(\n `Missing package.json at ${projectRoot}. build marketplace reads marketplace identity from package.json.`,\n { exit: EXIT_CODES.ERROR },\n );\n }\n\n let parsedJson: unknown;\n try {\n parsedJson = JSON.parse(rawContent);\n } catch (error) {\n this.error(`Failed to parse package.json at ${packageJsonPath}: ${getErrorMessage(error)}`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n const parseResult = packageJsonSchema.safeParse(parsedJson);\n if (!parseResult.success) {\n const missingFields = parseResult.error.issues.map((i) => i.path.join(\".\")).join(\", \");\n this.error(\n `package.json at ${packageJsonPath} is missing required fields: ${missingFields}. build marketplace reads marketplace identity from package.json.`,\n { exit: EXIT_CODES.ERROR },\n );\n }\n\n return parseResult.data;\n }\n\n /** A package.json name that fails gets a different refusal: its way out is `--name`. */\n private resolvePublishableName(\n packageName: string,\n nameOverride: string | undefined,\n packageJsonPath: string,\n ): string {\n if (nameOverride !== undefined) {\n const invalidOverride = validateKebabCaseName(nameOverride, MARKETPLACE_NOUN);\n if (invalidOverride) {\n this.error(`Invalid --name '${nameOverride}': ${invalidOverride}`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n return nameOverride;\n }\n\n if (validateKebabCaseName(packageName, MARKETPLACE_NOUN)) {\n this.error(marketplaceNameNotPublishable(packageName, packageJsonPath), {\n exit: EXIT_CODES.ERROR,\n });\n }\n return packageName;\n }\n\n private printHeader(pluginsDir: string, outputPath: string): void {\n this.log(\"\");\n this.log(\"Generating marketplace.json\");\n this.log(` Plugins directory: ${pluginsDir}`);\n this.log(` Output file: ${outputPath}`);\n this.log(\"\");\n }\n\n private async scanPlugins(\n pluginsDir: string,\n pluginsDirFlag: string,\n identity: MarketplaceIdentity,\n ): Promise<Marketplace> {\n this.log(\"Scanning plugins...\");\n\n const marketplace = await generateMarketplace(pluginsDir, {\n name: identity.name,\n version: identity.version,\n description: identity.description,\n ownerName: identity.ownerName,\n ...(identity.ownerEmail !== undefined && { ownerEmail: identity.ownerEmail }),\n pluginRoot: `./${pluginsDirFlag}`,\n });\n\n const stats = getMarketplaceStats(marketplace);\n this.log(`Found ${plural(stats.total, \"plugin\")}`);\n\n if (marketplace.plugins.length === 0) {\n this.error(noPluginsToPublish(pluginsDir, pluginsDirFlag), { exit: EXIT_CODES.ERROR });\n }\n\n const namespaceError = validateSkillIdNamespace(marketplace);\n if (namespaceError) {\n this.error(namespaceError, { exit: EXIT_CODES.ERROR });\n }\n\n return marketplace;\n }\n\n /** Unconditional: consumers must be able to read an absent catalogue as a broken marketplace. */\n private async readCatalog(projectRoot: string): Promise<MergedSkillsMatrix> {\n this.log(`Reading the skills for ${CATALOG_JSON}...`);\n await this.refuseAConfigDeclaringNothing(projectRoot);\n const matrix = await loadMarketplaceMatrix(projectRoot);\n return { ...matrix, generatedAt: GENERATED_AT_BUILD };\n }\n\n /** Every other reader takes such a file as absent; the build is where its author can fix it. */\n private async refuseAConfigDeclaringNothing(projectRoot: string): Promise<void> {\n const read = await readSourceRepoConfig(projectRoot);\n if (read.kind !== \"declares-nothing\") return;\n\n this.error(configUnreadableError(configLoadFailure(read.configPath, NO_VALID_DEFAULT_EXPORT)), {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n private async writeManifest(outputPath: string, marketplace: Marketplace): Promise<void> {\n this.log(`Writing ${MARKETPLACE_JSON}...`);\n await writeMarketplace(outputPath, marketplace);\n this.log(`Wrote ${outputPath}`);\n }\n\n private async writeCatalog(outputPath: string, catalog: MergedSkillsMatrix): Promise<void> {\n const catalogPath = path.join(path.dirname(outputPath), CATALOG_JSON);\n\n this.log(`Writing ${CATALOG_JSON}...`);\n await writeFile(catalogPath, `${JSON.stringify(catalog, null, 2)}\\n`);\n this.log(`Wrote ${catalogPath}`);\n }\n\n private printStats(marketplace: Marketplace): void {\n this.log(\"\");\n this.log(\"Category breakdown:\");\n const sortedCategories = sortBy(\n Object.entries(getMarketplaceStats(marketplace).byCategory),\n ([, count]) => -count,\n );\n for (const [category, count] of sortedCategories) {\n this.log(` ${category}: ${count}`);\n }\n }\n\n private printSample(marketplace: Marketplace): void {\n this.log(\"\");\n this.log(\"Sample plugins:\");\n const sampleSize = 5;\n for (const plugin of marketplace.plugins.slice(0, sampleSize)) {\n const version = plugin.version ? `v${plugin.version}` : \"\";\n const category = plugin.category ? `[${plugin.category}]` : \"\";\n this.log(` ${plugin.name} ${version} ${category}`);\n if (plugin.description) {\n this.log(` ${plugin.description}`);\n }\n }\n if (marketplace.plugins.length > sampleSize) {\n this.log(` ... and ${marketplace.plugins.length - sampleSize} more`);\n }\n }\n}\n\ntype ParsedAuthor = {\n name: string;\n email?: string;\n};\n\n/** The marketplace schema requires at least one plugin, so an empty manifest is never written. */\nfunction noPluginsToPublish(pluginsDir: string, pluginsDirFlag: string): string {\n return (\n `No plugins found in ${pluginsDir}. A marketplace with no plugins is refused when it is read ` +\n `back, so none was written. Run '${CLI_INVOKE_COMMAND} build plugins' first, or point ` +\n `--plugins-dir at the directory holding them (it is '${pluginsDirFlag}' for this run).`\n );\n}\n\n/** Accepts `\"Name <email> (url)\"` or `{ name, email, url }`; the caller refuses an empty name. */\nfunction parseAuthor(author: string | { name: string; email?: string } | undefined): ParsedAuthor {\n if (!author) return { name: \"\" };\n\n if (typeof author === \"object\") {\n return { name: author.name, ...(author.email !== undefined && { email: author.email }) };\n }\n\n const [, matchedName, matchedEmail] = author.match(AUTHOR_STRING_PATTERN) ?? [];\n if (matchedName !== undefined && matchedEmail !== undefined) {\n return { name: matchedName.trim(), email: matchedEmail.trim() };\n }\n\n warn(\n `package.json 'author' field \"${author}\" has no parseable email — marketplace owner.email will be empty`,\n );\n return { name: author.trim() };\n}\n"],"mappings":"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","names":[]}
@@ -2,11 +2,12 @@
2
2
  import {
3
3
  compileAllAgentPlugins,
4
4
  printAgentCompilationSummary
5
- } from "../../chunk-SI2LLEIR.js";
6
- import "../../chunk-GNMRXXRY.js";
5
+ } from "../../chunk-EC3JXT23.js";
6
+ import "../../chunk-MQZNDK5F.js";
7
7
  import {
8
8
  BaseCommand
9
- } from "../../chunk-37QFHJUW.js";
9
+ } from "../../chunk-JTMSFBCA.js";
10
+ import "../../chunk-FACDJH6O.js";
10
11
  import {
11
12
  compileAllSkillPlugins,
12
13
  compileSkillPlugin,
@@ -15,10 +16,10 @@ import {
15
16
  readPluginManifest,
16
17
  remove,
17
18
  setVerbose
18
- } from "../../chunk-YM3VEDAP.js";
19
+ } from "../../chunk-ENET4IF6.js";
19
20
  import {
20
21
  plural
21
- } from "../../chunk-TG3SPPZY.js";
22
+ } from "../../chunk-UE4Z3YMB.js";
22
23
  import {
23
24
  DIRS,
24
25
  PLUGINS_DIST_PATH
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cli/commands/build/plugins.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport path from \"path\";\n\nimport { BaseCommand } from \"../../base-command\";\nimport { setVerbose } from \"../../utils/logger\";\nimport { listDirectories, remove } from \"../../utils/fs\";\nimport { DIRS, PLUGINS_DIST_PATH } from \"../../consts\";\nimport {\n compileAllSkillPlugins,\n compileSkillPlugin,\n printCompilationSummary,\n} from \"../../lib/skills\";\nimport { compileAllAgentPlugins, printAgentCompilationSummary } from \"../../lib/agents\";\nimport { readPluginManifest } from \"../../lib/plugins\";\nimport { plural } from \"../../utils/string\";\n\nexport default class BuildPlugins extends BaseCommand {\n static summary = \"Build skills and agents into standalone plugins\";\n\n static description =\n \"Build skills and agents into standalone plugins. By default, compiles all skills. Use --skill to compile a specific skill only. Use --agents-dir to also compile agents.\";\n\n static examples = [\n {\n description: \"Compile every skill into plugins\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Compile a single skill by name\",\n command: \"<%= config.bin %> <%= command.id %> --skill cli-commander\",\n },\n {\n description: \"Write plugins to a custom output directory\",\n command: \"<%= config.bin %> <%= command.id %> --output-dir ./plugins\",\n },\n {\n description: \"Also compile agents from a directory\",\n command: \"<%= config.bin %> <%= command.id %> --agents-dir ./agents\",\n },\n {\n description: \"Compile with verbose logging\",\n command: \"<%= config.bin %> <%= command.id %> --verbose\",\n },\n ];\n\n static flags = {\n \"agents-dir\": Flags.string({\n char: \"a\",\n description: \"Agents source directory (builds one plugin per agent)\",\n }),\n \"output-dir\": Flags.string({\n char: \"o\",\n description: \"Output directory\",\n default: PLUGINS_DIST_PATH,\n }),\n skill: Flags.string({\n description: \"Compile only a specific skill (path to skill directory)\",\n }),\n verbose: Flags.boolean({\n char: \"v\",\n description: \"Enable verbose logging\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(BuildPlugins);\n setVerbose(flags.verbose);\n\n const projectRoot = process.cwd();\n const skillsDir = path.resolve(projectRoot, DIRS.skills);\n const outputDir = path.resolve(projectRoot, flags[\"output-dir\"]);\n\n this.printHeader(skillsDir, outputDir);\n\n try {\n const expectedSkillPlugins = await this.compileSkills(flags.skill, skillsDir, outputDir);\n\n if (flags[\"agents-dir\"]) {\n await this.compileAgents(projectRoot, flags[\"agents-dir\"], outputDir);\n }\n\n if (expectedSkillPlugins) {\n await this.pruneStaleSkillPlugins(outputDir, expectedSkillPlugins);\n }\n\n this.log(\"\");\n this.logSuccess(\"Plugin compilation complete!\");\n } catch (error) {\n this.log(\"Compilation failed\");\n this.handleError(error);\n }\n }\n\n private printHeader(skillsDir: string, outputDir: string): void {\n this.log(\"\");\n this.log(\"Compiling skill plugins\");\n this.log(` Skills directory: ${skillsDir}`);\n this.log(` Output directory: ${outputDir}`);\n this.log(\"\");\n }\n\n /**\n * Returns the plugin names that should remain, or `null` to skip pruning: in single-skill mode,\n * or after a failure, since a failed skill is indistinguishable from a removed one.\n */\n private async compileSkills(\n skillFlag: string | undefined,\n skillsDir: string,\n outputDir: string,\n ): Promise<Set<string> | null> {\n if (skillFlag) {\n await this.compileOneSkill(path.resolve(skillsDir, skillFlag), outputDir);\n return null;\n }\n\n return this.compileEverySkill(skillsDir, outputDir);\n }\n\n private async compileOneSkill(skillPath: string, outputDir: string): Promise<void> {\n this.log(`Compiling skill at ${skillPath}...`);\n\n const result = await compileSkillPlugin({\n skillPath,\n outputDir,\n });\n\n this.log(`Compiled ${result.skillName}`);\n this.log(` Plugin path: ${result.pluginPath}`);\n }\n\n private async compileEverySkill(\n skillsDir: string,\n outputDir: string,\n ): Promise<Set<string> | null> {\n this.log(\"Finding and compiling all skills...\");\n\n const { compiled, failed } = await compileAllSkillPlugins(skillsDir, outputDir);\n\n this.log(`Compiled ${plural(compiled.length, \"skill plugin\")}`);\n printCompilationSummary(compiled);\n\n if (failed.length > 0) {\n this.warn(\n `Skipping stale-plugin pruning: ${failed.length} skill(s) failed to compile ` +\n `(${failed.join(\", \")}). A failed skill is indistinguishable from a removed one.`,\n );\n return null;\n }\n\n return new Set(compiled.map((result) => result.skillName));\n }\n\n private async compileAgents(\n projectRoot: string,\n agentsDir: string,\n outputDir: string,\n ): Promise<void> {\n const resolvedAgentsDir = path.resolve(projectRoot, agentsDir);\n\n this.log(\"\");\n this.log(\"Compiling agent plugins\");\n this.log(` Agents directory: ${resolvedAgentsDir}`);\n this.log(\"\");\n\n this.log(\"Finding and compiling all agents...\");\n\n const agentResults = await compileAllAgentPlugins(resolvedAgentsDir, outputDir);\n\n this.log(`Compiled ${plural(agentResults.length, \"agent plugin\")}`);\n printAgentCompilationSummary(agentResults);\n }\n\n /** Prunes skill plugins only; agent plugins and non-plugin directories are left alone. */\n private async pruneStaleSkillPlugins(\n outputDir: string,\n expectedSkillPlugins: ReadonlySet<string>,\n ): Promise<void> {\n const dirNames = await listDirectories(outputDir);\n\n for (const dirName of dirNames) {\n if (expectedSkillPlugins.has(dirName)) continue;\n\n const pluginDir = path.join(outputDir, dirName);\n const manifest = await readPluginManifest(pluginDir);\n if (!manifest) continue;\n if (manifest.agents !== undefined) continue;\n\n await remove(pluginDir);\n this.log(` Pruned stale plugin: ${dirName}`);\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/cli/commands/build/plugins.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport path from \"path\";\n\nimport { BaseCommand } from \"../../base-command\";\nimport { setVerbose } from \"../../utils/logger\";\nimport { listDirectories, remove } from \"../../utils/fs\";\nimport { DIRS, PLUGINS_DIST_PATH } from \"../../consts\";\nimport {\n compileAllSkillPlugins,\n compileSkillPlugin,\n printCompilationSummary,\n} from \"../../lib/skills\";\nimport { compileAllAgentPlugins, printAgentCompilationSummary } from \"../../lib/agents\";\nimport { readPluginManifest } from \"../../lib/plugins\";\nimport { plural } from \"../../utils/string\";\n\nexport default class BuildPlugins extends BaseCommand {\n static summary = \"Build skills and agents into standalone plugins\";\n\n static description =\n \"Build skills and agents into standalone plugins. By default, compiles all skills. Use --skill to compile a specific skill only. Use --agents-dir to also compile agents.\";\n\n static examples = [\n {\n description: \"Compile every skill into plugins\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Compile a single skill by name\",\n command: \"<%= config.bin %> <%= command.id %> --skill cli-commander\",\n },\n {\n description: \"Write plugins to a custom output directory\",\n command: \"<%= config.bin %> <%= command.id %> --output-dir ./plugins\",\n },\n {\n description: \"Also compile agents from a directory\",\n command: \"<%= config.bin %> <%= command.id %> --agents-dir ./agents\",\n },\n {\n description: \"Compile with verbose logging\",\n command: \"<%= config.bin %> <%= command.id %> --verbose\",\n },\n ];\n\n static flags = {\n \"agents-dir\": Flags.string({\n char: \"a\",\n description: \"Agents source directory (builds one plugin per agent)\",\n }),\n \"output-dir\": Flags.string({\n char: \"o\",\n description: \"Output directory\",\n default: PLUGINS_DIST_PATH,\n }),\n skill: Flags.string({\n description: \"Compile only a specific skill (path to skill directory)\",\n }),\n verbose: Flags.boolean({\n char: \"v\",\n description: \"Enable verbose logging\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(BuildPlugins);\n setVerbose(flags.verbose);\n\n const projectRoot = process.cwd();\n const skillsDir = path.resolve(projectRoot, DIRS.skills);\n const outputDir = path.resolve(projectRoot, flags[\"output-dir\"]);\n\n this.printHeader(skillsDir, outputDir);\n\n try {\n const expectedSkillPlugins = await this.compileSkills(flags.skill, skillsDir, outputDir);\n\n if (flags[\"agents-dir\"]) {\n await this.compileAgents(projectRoot, flags[\"agents-dir\"], outputDir);\n }\n\n if (expectedSkillPlugins) {\n await this.pruneStaleSkillPlugins(outputDir, expectedSkillPlugins);\n }\n\n this.log(\"\");\n this.logSuccess(\"Plugin compilation complete!\");\n } catch (error) {\n this.log(\"Compilation failed\");\n this.handleError(error);\n }\n }\n\n private printHeader(skillsDir: string, outputDir: string): void {\n this.log(\"\");\n this.log(\"Compiling skill plugins\");\n this.log(` Skills directory: ${skillsDir}`);\n this.log(` Output directory: ${outputDir}`);\n this.log(\"\");\n }\n\n /**\n * Returns the plugin names that should remain, or `null` to skip pruning: in single-skill mode,\n * or after a failure, since a failed skill is indistinguishable from a removed one.\n */\n private async compileSkills(\n skillFlag: string | undefined,\n skillsDir: string,\n outputDir: string,\n ): Promise<Set<string> | null> {\n if (skillFlag) {\n await this.compileOneSkill(path.resolve(skillsDir, skillFlag), outputDir);\n return null;\n }\n\n return this.compileEverySkill(skillsDir, outputDir);\n }\n\n private async compileOneSkill(skillPath: string, outputDir: string): Promise<void> {\n this.log(`Compiling skill at ${skillPath}...`);\n\n const result = await compileSkillPlugin({\n skillPath,\n outputDir,\n });\n\n this.log(`Compiled ${result.skillName}`);\n this.log(` Plugin path: ${result.pluginPath}`);\n }\n\n private async compileEverySkill(\n skillsDir: string,\n outputDir: string,\n ): Promise<Set<string> | null> {\n this.log(\"Finding and compiling all skills...\");\n\n const { compiled, failed } = await compileAllSkillPlugins(skillsDir, outputDir);\n\n this.log(`Compiled ${plural(compiled.length, \"skill plugin\")}`);\n printCompilationSummary(compiled);\n\n if (failed.length > 0) {\n this.warn(\n `Skipping stale-plugin pruning: ${failed.length} skill(s) failed to compile ` +\n `(${failed.join(\", \")}). A failed skill is indistinguishable from a removed one.`,\n );\n return null;\n }\n\n return new Set(compiled.map((result) => result.skillName));\n }\n\n private async compileAgents(\n projectRoot: string,\n agentsDir: string,\n outputDir: string,\n ): Promise<void> {\n const resolvedAgentsDir = path.resolve(projectRoot, agentsDir);\n\n this.log(\"\");\n this.log(\"Compiling agent plugins\");\n this.log(` Agents directory: ${resolvedAgentsDir}`);\n this.log(\"\");\n\n this.log(\"Finding and compiling all agents...\");\n\n const agentResults = await compileAllAgentPlugins(resolvedAgentsDir, outputDir);\n\n this.log(`Compiled ${plural(agentResults.length, \"agent plugin\")}`);\n printAgentCompilationSummary(agentResults);\n }\n\n /** Prunes skill plugins only; agent plugins and non-plugin directories are left alone. */\n private async pruneStaleSkillPlugins(\n outputDir: string,\n expectedSkillPlugins: ReadonlySet<string>,\n ): Promise<void> {\n const dirNames = await listDirectories(outputDir);\n\n for (const dirName of dirNames) {\n if (expectedSkillPlugins.has(dirName)) continue;\n\n const pluginDir = path.join(outputDir, dirName);\n const manifest = await readPluginManifest(pluginDir);\n if (!manifest) continue;\n if (manifest.agents !== undefined) continue;\n\n await remove(pluginDir);\n this.log(` Pruned stale plugin: ${dirName}`);\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,30 +1,33 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  unofferablePlacementsFound
4
- } from "../chunk-YLFKFVQP.js";
4
+ } from "../chunk-ZBI6GFJD.js";
5
5
  import {
6
6
  hostCompileNotices
7
- } from "../chunk-EHEBN4NB.js";
7
+ } from "../chunk-U672FZVC.js";
8
8
  import {
9
9
  detectBothInstallations,
10
10
  reconcileTypesFromDisk
11
- } from "../chunk-SNXEYAFP.js";
11
+ } from "../chunk-CKBWEWHZ.js";
12
12
  import {
13
13
  compileAgents,
14
14
  discoverInstalledSkills
15
- } from "../chunk-Q4NWATGH.js";
15
+ } from "../chunk-XMQIWPIR.js";
16
16
  import {
17
17
  loadAgentDefs
18
- } from "../chunk-DQB3E2SX.js";
19
- import "../chunk-SI2LLEIR.js";
20
- import "../chunk-GNMRXXRY.js";
18
+ } from "../chunk-JNRACLNS.js";
19
+ import "../chunk-EC3JXT23.js";
20
+ import "../chunk-MQZNDK5F.js";
21
21
  import {
22
22
  BaseCommand,
23
23
  EXIT_CODES,
24
24
  providerFlag,
25
25
  providerNamedBy,
26
26
  refuseAnAmbiguousInstallation
27
- } from "../chunk-37QFHJUW.js";
27
+ } from "../chunk-JTMSFBCA.js";
28
+ import {
29
+ namedByActiveEntries
30
+ } from "../chunk-FACDJH6O.js";
28
31
  import {
29
32
  ConfigLoadError,
30
33
  ERROR_MESSAGES,
@@ -47,10 +50,10 @@ import {
47
50
  skillMetadataUnusableDetail,
48
51
  skillMetadataUnusableError,
49
52
  verbose
50
- } from "../chunk-YM3VEDAP.js";
53
+ } from "../chunk-ENET4IF6.js";
51
54
  import {
52
55
  plural
53
- } from "../chunk-TG3SPPZY.js";
56
+ } from "../chunk-UE4Z3YMB.js";
54
57
  import {
55
58
  STANDARD_FILES,
56
59
  effectivelyExcludedSkillIds,
@@ -202,8 +205,9 @@ var Compile = class _Compile extends BaseCommand {
202
205
  async warnScopeDroppedStackPairs(projectDir) {
203
206
  const loaded = await loadProjectConfig(projectDir);
204
207
  if (!loaded?.config.stack) return;
208
+ const namedBy = namedByActiveEntries(loaded.config.skills);
205
209
  for (const [skillId, agentNames] of findScopeDroppedStackPairs(loaded.config)) {
206
- this.warn(scopeBlockedStackAssignment(agentNames, skillId));
210
+ this.warn(scopeBlockedStackAssignment(agentNames, skillId, namedBy));
207
211
  }
208
212
  }
209
213
  /** Points at global-scope agents so "No agents to recompile" doesn't read as a silent no-op. */