agents-inc 0.174.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 (90) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/dist/{chunk-APWMMZOK.js → chunk-3F5LT433.js} +157 -53
  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-3PJZ4QNJ.js → chunk-B7AVWSK2.js} +21 -11
  7. package/dist/chunk-B7AVWSK2.js.map +1 -0
  8. package/dist/{chunk-H5E6IO2L.js → chunk-C2BSCEDN.js} +9 -11
  9. package/dist/chunk-C2BSCEDN.js.map +1 -0
  10. package/dist/{chunk-R7GKQBZJ.js → chunk-CKBWEWHZ.js} +96 -52
  11. package/dist/chunk-CKBWEWHZ.js.map +1 -0
  12. package/dist/{chunk-IXVGBUWI.js → chunk-EC3JXT23.js} +5 -5
  13. package/dist/{chunk-E45IT3HC.js → chunk-ENET4IF6.js} +998 -472
  14. package/dist/chunk-ENET4IF6.js.map +1 -0
  15. package/dist/{chunk-FQF6VHO3.js → chunk-FACDJH6O.js} +12 -105
  16. package/dist/chunk-FACDJH6O.js.map +1 -0
  17. package/dist/{chunk-TVEDNGVP.js → chunk-H6WUOW5F.js} +2 -2
  18. package/dist/{chunk-7BHDKEGK.js → chunk-JNRACLNS.js} +3 -3
  19. package/dist/{chunk-IAQFZFWD.js → chunk-JTMSFBCA.js} +231 -24
  20. package/dist/chunk-JTMSFBCA.js.map +1 -0
  21. package/dist/{chunk-EFXVYQGT.js → chunk-MQZNDK5F.js} +39 -40
  22. package/dist/chunk-MQZNDK5F.js.map +1 -0
  23. package/dist/{chunk-QCX66KBM.js → chunk-SN64WNWE.js} +3 -3
  24. package/dist/{chunk-WUSEZFER.js → chunk-U46LYYRA.js} +3 -2
  25. package/dist/{chunk-WUSEZFER.js.map → chunk-U46LYYRA.js.map} +1 -1
  26. package/dist/{chunk-6PGXTLA4.js → chunk-U672FZVC.js} +2 -2
  27. package/dist/{chunk-AIBVAYHS.js → chunk-UE4Z3YMB.js} +2 -2
  28. package/dist/chunk-UE4Z3YMB.js.map +1 -0
  29. package/dist/{chunk-REHVGFJE.js → chunk-XMQIWPIR.js} +84 -32
  30. package/dist/chunk-XMQIWPIR.js.map +1 -0
  31. package/dist/{chunk-I3WF6L43.js → chunk-XYBHH3M5.js} +2 -2
  32. package/dist/{chunk-ECPFYHDX.js → chunk-ZBI6GFJD.js} +11 -11
  33. package/dist/chunk-ZBI6GFJD.js.map +1 -0
  34. package/dist/commands/build/marketplace.js +5 -4
  35. package/dist/commands/build/marketplace.js.map +1 -1
  36. package/dist/commands/build/plugins.js +7 -6
  37. package/dist/commands/build/plugins.js.map +1 -1
  38. package/dist/commands/compile.js +20 -16
  39. package/dist/commands/compile.js.map +1 -1
  40. package/dist/commands/doctor.js +106 -87
  41. package/dist/commands/doctor.js.map +1 -1
  42. package/dist/commands/edit.js +76 -48
  43. package/dist/commands/edit.js.map +1 -1
  44. package/dist/commands/eject.js +31 -18
  45. package/dist/commands/eject.js.map +1 -1
  46. package/dist/commands/init.js +17 -17
  47. package/dist/commands/list.js +10 -9
  48. package/dist/commands/list.js.map +1 -1
  49. package/dist/commands/new/marketplace.js +5 -4
  50. package/dist/commands/new/marketplace.js.map +1 -1
  51. package/dist/commands/search.js +14 -9
  52. package/dist/commands/search.js.map +1 -1
  53. package/dist/commands/share.js +20 -22
  54. package/dist/commands/share.js.map +1 -1
  55. package/dist/commands/uninstall.js +24 -19
  56. package/dist/commands/uninstall.js.map +1 -1
  57. package/dist/commands/update.js +110 -31
  58. package/dist/commands/update.js.map +1 -1
  59. package/dist/components/common/select-list.js +2 -2
  60. package/dist/components/common/skill-agent-summary.js +4 -3
  61. package/dist/components/common/summary-panel.js +5 -4
  62. package/dist/hooks/init.js +24 -25
  63. package/dist/hooks/init.js.map +1 -1
  64. package/dist/load-agent-defs-5BSECHE6.js +14 -0
  65. package/dist/{recompile-project-agents-KYK44C24.js → recompile-project-agents-U3UGHPWG.js} +8 -8
  66. package/dist/{source-loader-G5I4RNUP.js → source-loader-E2Y5MMN5.js} +4 -4
  67. package/package.json +1 -1
  68. package/dist/chunk-3PJZ4QNJ.js.map +0 -1
  69. package/dist/chunk-AIBVAYHS.js.map +0 -1
  70. package/dist/chunk-APWMMZOK.js.map +0 -1
  71. package/dist/chunk-E45IT3HC.js.map +0 -1
  72. package/dist/chunk-ECPFYHDX.js.map +0 -1
  73. package/dist/chunk-EFXVYQGT.js.map +0 -1
  74. package/dist/chunk-FQF6VHO3.js.map +0 -1
  75. package/dist/chunk-H5E6IO2L.js.map +0 -1
  76. package/dist/chunk-IAQFZFWD.js.map +0 -1
  77. package/dist/chunk-ORO2T4K2.js +0 -96
  78. package/dist/chunk-ORO2T4K2.js.map +0 -1
  79. package/dist/chunk-R7GKQBZJ.js.map +0 -1
  80. package/dist/chunk-REHVGFJE.js.map +0 -1
  81. package/dist/load-agent-defs-5U5KAURA.js +0 -14
  82. /package/dist/{chunk-IXVGBUWI.js.map → chunk-EC3JXT23.js.map} +0 -0
  83. /package/dist/{chunk-TVEDNGVP.js.map → chunk-H6WUOW5F.js.map} +0 -0
  84. /package/dist/{chunk-7BHDKEGK.js.map → chunk-JNRACLNS.js.map} +0 -0
  85. /package/dist/{chunk-QCX66KBM.js.map → chunk-SN64WNWE.js.map} +0 -0
  86. /package/dist/{chunk-6PGXTLA4.js.map → chunk-U672FZVC.js.map} +0 -0
  87. /package/dist/{chunk-I3WF6L43.js.map → chunk-XYBHH3M5.js.map} +0 -0
  88. /package/dist/{load-agent-defs-5U5KAURA.js.map → load-agent-defs-5BSECHE6.js.map} +0 -0
  89. /package/dist/{recompile-project-agents-KYK44C24.js.map → recompile-project-agents-U3UGHPWG.js.map} +0 -0
  90. /package/dist/{source-loader-G5I4RNUP.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-EFXVYQGT.js";
5
+ } from "./chunk-MQZNDK5F.js";
6
6
  import {
7
7
  agentCodec,
8
8
  buildAgentScopeMap,
@@ -12,11 +12,13 @@ import {
12
12
  ensureDir,
13
13
  getErrorMessage,
14
14
  hostAt,
15
- installBaseDir,
15
+ inheritedGlobalProvider,
16
16
  isHomeDirectory,
17
- loadInstalledConfig,
17
+ listDirectories,
18
+ loadProjectConfigFromDir,
18
19
  loadSkillsFromDir,
19
20
  loadSkillsMatrixFromSource,
21
+ providerAtScope,
20
22
  providerInUse,
21
23
  remove,
22
24
  removeDirIfEmpty,
@@ -25,33 +27,37 @@ import {
25
27
  skillsDir,
26
28
  skillsPathPrefix,
27
29
  verbose
28
- } from "./chunk-E45IT3HC.js";
30
+ } from "./chunk-ENET4IF6.js";
29
31
  import {
30
32
  initializeMatrix,
31
33
  matrix,
32
34
  typedEntries,
33
35
  typedKeys
34
- } from "./chunk-AIBVAYHS.js";
36
+ } from "./chunk-UE4Z3YMB.js";
35
37
  import {
38
+ EJECT_SOURCE,
36
39
  globalInstallRoot
37
- } from "./chunk-WUSEZFER.js";
40
+ } from "./chunk-U46LYYRA.js";
38
41
 
39
42
  // src/cli/lib/operations/skills/discover-skills.ts
43
+ import path from "path";
40
44
  var NO_LOCAL_SKILLS = { skills: {}, unusableMetadata: [] };
41
45
  async function discoverLocalProjectSkills(projectDir, scope) {
42
- const provider = providerInUse(installBaseDir(projectDir, scope));
46
+ const provider = providerAtScope(projectDir, scope);
47
+ const pathPrefix = skillsPathPrefix(provider, scope, projectDir);
43
48
  const scan = () => loadSkillsFromDir(skillsDir(provider, scope, projectDir), {
44
- pathPrefix: skillsPathPrefix(provider, scope, projectDir),
45
- requireMetadata: true
49
+ pathPrefix,
50
+ requireMetadata: true,
51
+ folderLabel: folderLabelAt(pathPrefix, scope)
46
52
  });
47
53
  return scope === "global" ? sayingEachWarningOnce(scan) : scan();
48
54
  }
49
- function globalSkillsRoot() {
50
- const home = globalInstallRoot();
51
- return skillsDir(providerInUse(home), "global", home);
55
+ function folderLabelAt(pathPrefix, scope) {
56
+ const underHome = scope === "global" && !path.isAbsolute(pathPrefix);
57
+ return underHome ? `~/${pathPrefix}/` : `${pathPrefix}/`;
52
58
  }
53
- function projectSkillsRoot(projectDir, scope) {
54
- return skillsDir(providerInUse(installBaseDir(projectDir, scope)), scope, projectDir);
59
+ function skillsRootAt(projectDir, scope) {
60
+ return skillsDir(providerAtScope(projectDir, scope), scope, projectDir);
55
61
  }
56
62
  function mergeSkills(...skillSources) {
57
63
  const merged = {};
@@ -66,15 +72,18 @@ function mergeSkills(...skillSources) {
66
72
  }
67
73
  async function discoverInstalledSkills(projectDir) {
68
74
  const isGlobalProject = isHomeDirectory(projectDir);
69
- const globalPlugins = isGlobalProject ? {} : await discoverGlobalPluginSkills();
75
+ const globalPlugins = isGlobalProject ? {} : await discoverGlobalPluginSkills(projectDir);
70
76
  const globalLocal = isGlobalProject ? NO_LOCAL_SKILLS : await discoverGlobalLocalSkills(projectDir);
71
77
  const projectPlugins = await discoverProjectPluginSkills(projectDir);
72
78
  const localScope = isGlobalProject ? "global" : "project";
73
79
  const projectLocal = await discoverLocalSkillsAt(projectDir, localScope);
74
80
  return assembleDiscoveredSkills({ globalPlugins, globalLocal, projectPlugins, projectLocal });
75
81
  }
76
- async function discoverGlobalPluginSkills() {
77
- const skills = await discoverAllPluginSkills(globalInstallRoot());
82
+ async function discoverGlobalPluginSkills(projectDir) {
83
+ const skills = await discoverAllPluginSkills(
84
+ globalInstallRoot(),
85
+ inheritedGlobalProvider(projectDir)
86
+ );
78
87
  const count = skillCount(skills);
79
88
  if (count > 0) verbose(` Found ${count} skills from global plugins`);
80
89
  return skills;
@@ -82,7 +91,9 @@ async function discoverGlobalPluginSkills() {
82
91
  async function discoverGlobalLocalSkills(projectDir) {
83
92
  const loaded = await discoverLocalProjectSkills(projectDir, "global");
84
93
  const count = skillCount(loaded.skills);
85
- if (count > 0) verbose(` Found ${count} global local skills from ${globalSkillsRoot()}`);
94
+ if (count > 0) {
95
+ verbose(` Found ${count} global local skills from ${skillsRootAt(projectDir, "global")}`);
96
+ }
86
97
  return loaded;
87
98
  }
88
99
  async function discoverProjectPluginSkills(projectDir) {
@@ -93,7 +104,7 @@ async function discoverProjectPluginSkills(projectDir) {
93
104
  async function discoverLocalSkillsAt(projectDir, scope) {
94
105
  const loaded = await discoverLocalProjectSkills(projectDir, scope);
95
106
  verbose(
96
- ` Found ${skillCount(loaded.skills)} local skills from ${projectSkillsRoot(projectDir, scope)}`
107
+ ` Found ${skillCount(loaded.skills)} local skills from ${skillsRootAt(projectDir, scope)}`
97
108
  );
98
109
  return loaded;
99
110
  }
@@ -120,6 +131,7 @@ function skillCount(skills) {
120
131
  }
121
132
 
122
133
  // src/cli/lib/operations/skills/copy-local-skills.ts
134
+ import path2 from "path";
123
135
  async function copyScopedLocalSkills(scopeSkills, skillsDir2, sourceResult) {
124
136
  if (scopeSkills.length === 0) return [];
125
137
  await ensureDir(skillsDir2);
@@ -150,6 +162,22 @@ async function copyLocalSkills(skills, projectDir, sourceResult) {
150
162
  totalCopied: projectCopied.length + globalCopied.length
151
163
  };
152
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
+ }
153
181
 
154
182
  // src/cli/lib/operations/skills/uninstall-plugin-skills.ts
155
183
  var SCOPE_OF_AN_UNRECORDED_SKILL = "project";
@@ -160,9 +188,13 @@ async function uninstallPluginSkills(skillIds, oldSkills, marketplace, projectDi
160
188
  for (const skillId of skillIds) {
161
189
  const oldSkill = oldSkills.find((s) => s.id === skillId);
162
190
  const pluginScope = oldSkill?.scope ?? SCOPE_OF_AN_UNRECORDED_SKILL;
163
- const pluginRef = buildMarketplacePluginRef(skillId, marketplace);
164
191
  try {
165
- 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
+ );
166
198
  if (outcome === "removed") uninstalled.push(skillId);
167
199
  } catch (error) {
168
200
  failed.push({ id: skillId, error: getErrorMessage(error) });
@@ -170,6 +202,20 @@ async function uninstallPluginSkills(skillIds, oldSkills, marketplace, projectDi
170
202
  }
171
203
  return { uninstalled, failed };
172
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
+ }
173
219
 
174
220
  // src/cli/lib/loading/catalogue-seat.ts
175
221
  async function withCatalogueSeatedFor(projectDir, body) {
@@ -188,7 +234,7 @@ async function withCatalogueSeatedFor(projectDir, body) {
188
234
  }
189
235
 
190
236
  // src/cli/lib/operations/project/remove-compiled-agents.ts
191
- import path from "path";
237
+ import path3 from "path";
192
238
  async function removeCompiledAgents(options) {
193
239
  const outcomes = await Promise.all(
194
240
  options.agents.map((name) => removeCompiledAgentFile(options.agentsDir, name))
@@ -207,7 +253,7 @@ async function pruneCompiledAgents(options) {
207
253
  }
208
254
  async function removeCompiledAgentFile(agentsDir, name) {
209
255
  try {
210
- await remove(path.join(agentsDir, `${name}${agentCodec("claude").extension}`));
256
+ await remove(path3.join(agentsDir, `${name}${agentCodec("claude").extension}`));
211
257
  return { name, ok: true };
212
258
  } catch (error) {
213
259
  return { name, ok: false, error: getErrorMessage(error) };
@@ -216,17 +262,19 @@ async function removeCompiledAgentFile(agentsDir, name) {
216
262
 
217
263
  // src/cli/lib/operations/project/compile-agents.ts
218
264
  async function compileAgents(options) {
219
- const roster = await rosterForPass(options);
265
+ const provider = options.provider ?? providerInUse(options.projectDir);
266
+ const roster = await rosterForPass(options, provider);
220
267
  const recompileResult = await recompileAgents({
221
268
  pluginDir: options.pluginDir ?? options.projectDir,
222
269
  sourcePath: options.sourcePath,
223
270
  ...roster.agents !== void 0 && { agents: roster.agents },
224
271
  ...options.skills !== void 0 && { skills: options.skills },
225
272
  projectDir: options.projectDir,
273
+ provider,
226
274
  ...options.outputDir !== void 0 && { outputDir: options.outputDir },
227
275
  ...roster.agentScopeMap !== void 0 && { agentScopeMap: roster.agentScopeMap }
228
276
  });
229
- await pruneStaleAgentsForPass(options, recompileResult);
277
+ await pruneStaleAgentsForPass(options, provider, recompileResult);
230
278
  return {
231
279
  compiled: recompileResult.compiled,
232
280
  rewritten: recompileResult.rewritten,
@@ -234,12 +282,12 @@ async function compileAgents(options) {
234
282
  warnings: recompileResult.warnings
235
283
  };
236
284
  }
237
- async function rosterForPass(options) {
285
+ async function rosterForPass(options, provider) {
238
286
  if (!options.scopeFilter) return { agents: options.agents, agentScopeMap: options.agentScopeMap };
239
- return rosterForScope(options, options.scopeFilter);
287
+ return rosterForScope(options, options.scopeFilter, provider);
240
288
  }
241
- async function rosterForScope(options, scope) {
242
- const config = (await loadInstalledConfig(options.projectDir))?.config;
289
+ async function rosterForScope(options, scope, provider) {
290
+ const config = (await loadProjectConfigFromDir(options.projectDir, provider))?.config;
243
291
  const activeAtScope = config?.agents.filter((agent) => !agent.excluded && agent.scope === scope).map((agent) => agent.name);
244
292
  return {
245
293
  agents: requestedAgentsAmong(options.agents, activeAtScope),
@@ -252,7 +300,7 @@ function requestedAgentsAmong(requested, activeAtScope) {
252
300
  const atScope = new Set(activeAtScope);
253
301
  return requested.filter((name) => atScope.has(name));
254
302
  }
255
- async function pruneStaleAgentsForPass(options, recompileResult) {
303
+ async function pruneStaleAgentsForPass(options, provider, recompileResult) {
256
304
  if (options.scopeFilter || !options.outputDir) return;
257
305
  const compiledForDir = /* @__PURE__ */ new Set([
258
306
  ...recompileResult.compiled,
@@ -262,16 +310,20 @@ async function pruneStaleAgentsForPass(options, recompileResult) {
262
310
  agentsDir: options.outputDir,
263
311
  keep: compiledForDir,
264
312
  // A Codex role is a `.toml`, so the prune must know the host's extension.
265
- codec: agentCodec(providerInUse(options.projectDir))
313
+ codec: agentCodec(provider)
266
314
  });
267
315
  }
268
316
 
269
317
  export {
270
318
  discoverInstalledSkills,
271
319
  copyLocalSkills,
320
+ skillFoldersAt,
321
+ removeSkillFoldersCreatedSince,
272
322
  uninstallPluginSkills,
323
+ pluginRefsOf,
324
+ removeUnderFirstNameHeld,
273
325
  withCatalogueSeatedFor,
274
326
  removeCompiledAgents,
275
327
  compileAgents
276
328
  };
277
- //# sourceMappingURL=chunk-REHVGFJE.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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,UAAU;AAgCjB,IAAM,kBAAgC,EAAE,QAAQ,CAAC,GAAG,kBAAkB,CAAC,EAAE;AAMzE,eAAe,2BACb,YACA,OACuB;AACvB,QAAM,WAAW,gBAAgB,YAAY,KAAK;AAClD,QAAM,aAAa,iBAAiB,UAAU,OAAO,UAAU;AAC/D,QAAM,OAAO,MACX,kBAAkB,UAAU,UAAU,OAAO,UAAU,GAAG;AAAA,IACxD;AAAA,IACA,iBAAiB;AAAA,IACjB,aAAa,cAAc,YAAY,KAAK;AAAA,EAC9C,CAAC;AAEH,SAAO,UAAU,WAAW,sBAAsB,IAAI,IAAI,KAAK;AACjE;AAGA,SAAS,cAAc,YAAoB,OAA2B;AACpE,QAAM,YAAY,UAAU,YAAY,CAAC,KAAK,WAAW,UAAU;AACnE,SAAO,YAAY,KAAK,UAAU,MAAM,GAAG,UAAU;AACvD;AAEA,SAAS,aAAa,YAAoB,OAA2B;AACnE,SAAO,UAAU,gBAAgB,YAAY,KAAK,GAAG,OAAO,UAAU;AACxE;AAGA,SAAS,eAAe,cAAwD;AAC9E,QAAM,SAA6B,CAAC;AAEpC,aAAW,UAAU,cAAc;AACjC,eAAW,CAAC,IAAI,KAAK,KAAK,aAAmD,MAAM,GAAG;AACpF,UAAI,OAAO;AACT,eAAO,EAAE,IAAI;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAGA,eAAsB,wBAAwB,YAA+C;AAC3F,QAAM,kBAAkB,gBAAgB,UAAU;AAElD,QAAM,gBAAgB,kBAAkB,CAAC,IAAI,MAAM,2BAA2B,UAAU;AACxF,QAAM,cAAc,kBAChB,kBACA,MAAM,0BAA0B,UAAU;AAC9C,QAAM,iBAAiB,MAAM,4BAA4B,UAAU;AAEnE,QAAM,aAAyB,kBAAkB,WAAW;AAC5D,QAAM,eAAe,MAAM,sBAAsB,YAAY,UAAU;AAEvE,SAAO,yBAAyB,EAAE,eAAe,aAAa,gBAAgB,aAAa,CAAC;AAC9F;AAEA,eAAe,2BAA2B,YAAiD;AACzF,QAAM,SAAS,MAAM;AAAA,IACnB,kBAAkB;AAAA,IAClB,wBAAwB,UAAU;AAAA,EACpC;AACA,QAAM,QAAQ,WAAW,MAAM;AAC/B,MAAI,QAAQ,EAAG,SAAQ,WAAW,KAAK,6BAA6B;AACpE,SAAO;AACT;AAEA,eAAe,0BAA0B,YAA2C;AAClF,QAAM,SAAS,MAAM,2BAA2B,YAAY,QAAQ;AACpE,QAAM,QAAQ,WAAW,OAAO,MAAM;AACtC,MAAI,QAAQ,GAAG;AACb,YAAQ,WAAW,KAAK,6BAA6B,aAAa,YAAY,QAAQ,CAAC,EAAE;AAAA,EAC3F;AACA,SAAO;AACT;AAEA,eAAe,4BAA4B,YAAiD;AAC1F,QAAM,SAAS,MAAM,wBAAwB,UAAU;AACvD,UAAQ,WAAW,WAAW,MAAM,CAAC,gCAAgC;AACrE,SAAO;AACT;AAEA,eAAe,sBAAsB,YAAoB,OAA0C;AACjG,QAAM,SAAS,MAAM,2BAA2B,YAAY,KAAK;AACjE;AAAA,IACE,WAAW,WAAW,OAAO,MAAM,CAAC,sBAAsB,aAAa,YAAY,KAAK,CAAC;AAAA,EAC3F;AACA,SAAO;AACT;AASA,SAAS,yBAAyB,OAAyC;AACzE,QAAM,EAAE,eAAe,aAAa,gBAAgB,aAAa,IAAI;AACrE,QAAM,YAAY;AAAA,IAChB;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA,aAAa;AAAA,EACf;AAEA,QAAM,uBAAuB,YAAY,eAAe,cAAc;AAEtE,SAAO;AAAA,IACL;AAAA,IACA,iBAAiB,WAAW,SAAS;AAAA,IACrC,kBAAkB,WAAW,oBAAoB;AAAA,IACjD,wBAAwB,WAAW,aAAa;AAAA,IAChD,uBAAuB,WAAW,YAAY,MAAM;AAAA,IACpD,kBAAkB,CAAC,GAAG,YAAY,kBAAkB,GAAG,aAAa,gBAAgB;AAAA,EACtF;AACF;AAEA,SAAS,WAAW,QAAoC;AACtD,SAAO,UAAmB,MAAM,EAAE;AACpC;;;AC9JA,OAAOA,WAAU;AAajB,eAAe,sBACb,aACAC,YACA,cACwB;AACxB,MAAI,YAAY,WAAW,EAAG,QAAO,CAAC;AAEtC,QAAM,UAAUA,UAAS;AAEzB,SAAO;AAAA,IACL,YAAY,IAAI,CAAC,MAAM,EAAE,EAAE;AAAA,IAC3BA;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAsB,gBACpB,QACA,YACA,cAC0B;AAC1B,QAAM,qBAAqB,OAAO,OAAO,CAAC,MAAM,EAAE,UAAU,QAAQ;AACpE,QAAM,oBAAoB,OAAO,OAAO,CAAC,MAAM,EAAE,UAAU,QAAQ;AAEnE,QAAM,eAAe,oBAAoB,YAAY,SAAS;AAC9D,QAAM,cAAc,oBAAoB,YAAY,QAAQ;AAE5D,QAAM,gBAAgB,MAAM;AAAA,IAC1B;AAAA,IACA,aAAa;AAAA,IACb;AAAA,EACF;AACA,QAAM,eAAe,MAAM;AAAA,IACzB;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,aAAa,cAAc,SAAS,aAAa;AAAA,EACnD;AACF;AAGA,eAAsB,eAAe,YAAkD;AACrF,QAAM,aAAa;AAAA,IACjB,oBAAoB,YAAY,SAAS,EAAE;AAAA,IAC3C,oBAAoB,YAAY,QAAQ,EAAE;AAAA,EAC5C;AACA,QAAM,UAAU,MAAM,QAAQ,IAAI,WAAW,IAAI,SAAS,CAAC;AAC3D,SAAO,IAAI,IAAI,QAAQ,KAAK,CAAC;AAC/B;AAEA,eAAe,UAAU,KAAgC;AACvD,UAAQ,MAAM,gBAAgB,GAAG,GAAG,IAAI,CAAC,SAASC,MAAK,KAAK,KAAK,IAAI,CAAC;AACxE;AAGA,eAAsB,+BACpB,QACA,YAC8B;AAC9B,QAAM,UAAU,CAAC,GAAI,MAAM,eAAe,UAAU,CAAE,EAAE,OAAO,CAAC,WAAW,CAAC,OAAO,IAAI,MAAM,CAAC;AAC9F,QAAM,QAAQ,IAAI,QAAQ,IAAI,MAAM,CAAC;AACrC,SAAO,IAAI,IAAI,OAAO;AACxB;;;ACvEA,IAAM,+BAA2C;AAQjD,eAAsB,sBACpB,UACA,WACA,aACA,YACgC;AAChC,QAAM,OAAO,OAAO,UAAU;AAC9B,QAAM,cAAyB,CAAC;AAChC,QAAM,SAA0C,CAAC;AAEjD,aAAW,WAAW,UAAU;AAC9B,UAAM,WAAW,UAAU,KAAK,CAAC,MAAM,EAAE,OAAO,OAAO;AACvD,UAAM,cAAc,UAAU,SAAS;AACvC,QAAI;AACF,YAAM,UAAU,MAAM;AAAA,QACpB;AAAA,QACA,aAAa,SAAS,UAAU,QAAQ,WAAW;AAAA,QACnD;AAAA,QACA;AAAA,MACF;AACA,UAAI,YAAY,UAAW,aAAY,KAAK,OAAO;AAAA,IACrD,SAAS,OAAO;AACd,aAAO,KAAK,EAAE,IAAI,SAAS,OAAO,gBAAgB,KAAK,EAAE,CAAC;AAAA,IAC5D;AAAA,EACF;AAEA,SAAO,EAAE,aAAa,OAAO;AAC/B;AAMO,SAAS,aACd,SACA,QACA,aACU;AACV,QAAM,iBAAiB,0BAA0B,SAAS,WAAW;AACrE,MAAI,WAAW,UAAa,WAAW,eAAe,WAAW,cAAc;AAC7E,WAAO,CAAC,cAAc;AAAA,EACxB;AACA,SAAO,CAAC,0BAA0B,SAAS,MAAM,GAAG,cAAc;AACpE;AAGA,eAAsB,yBACpB,MACA,YACA,OACA,YAC+B;AAC/B,aAAW,aAAa,YAAY;AAClC,UAAM,UAAU,MAAM,KAAK,gBAAgB,WAAW,OAAO,UAAU;AACvE,QAAI,YAAY,UAAW,QAAO;AAAA,EACpC;AACA,SAAO;AACT;;;AClEA,eAAsB,uBACpB,YACA,MACY;AACZ,QAAM,mBAAmB;AACzB,QAAM,EAAE,QAAQ,OAAO,IAAI,MAAM,2BAA2B;AAAA,IAC1D;AAAA,IACA,SAAS;AAAA,IACT,kBAAkB;AAAA,IAClB,YAAY;AAAA,EACd,CAAC;AACD,MAAI;AACF,WAAO,MAAM,KAAK,MAAM;AAAA,EAC1B,UAAE;AACA,qBAAiB,gBAAgB;AAAA,EACnC;AACF;;;ACxBA,OAAOC,WAAU;AA8BjB,eAAsB,qBACpB,SACqC;AACrC,QAAM,WAAW,MAAM,QAAQ;AAAA,IAC7B,QAAQ,OAAO,IAAI,CAAC,SAAS,wBAAwB,QAAQ,WAAW,IAAI,CAAC;AAAA,EAC/E;AACA,QAAM,iBAAiB,QAAQ,SAAS;AAExC,SAAO;AAAA,IACL,SAAS,SAAS,QAAQ,CAAC,YAAa,QAAQ,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAE;AAAA,IACzE,QAAQ,SAAS;AAAA,MAAQ,CAAC,YACxB,QAAQ,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,QAAQ,MAAM,OAAO,QAAQ,MAAM,CAAC;AAAA,IACjE;AAAA,EACF;AACF;AAGA,eAAsB,oBAAoB,SAAoD;AAC5F,QAAM,yBAAyB,QAAQ,WAAW,QAAQ,MAAM,QAAQ,KAAK;AAC7E,QAAM,iBAAiB,QAAQ,SAAS;AAC1C;AAEA,eAAe,wBACb,WACA,MACyB;AACzB,MAAI;AACF,UAAM,OAAOC,MAAK,KAAK,WAAW,GAAG,IAAI,GAAG,WAAW,QAAQ,EAAE,SAAS,EAAE,CAAC;AAC7E,WAAO,EAAE,MAAM,IAAI,KAAK;AAAA,EAC1B,SAAS,OAAO;AACd,WAAO,EAAE,MAAM,IAAI,OAAO,OAAO,gBAAgB,KAAK,EAAE;AAAA,EAC1D;AACF;;;ACjCA,eAAsB,cAAc,SAA2D;AAC7F,QAAM,WAAW,QAAQ,YAAY,cAAc,QAAQ,UAAU;AACrE,QAAM,SAAS,MAAM,cAAc,SAAS,QAAQ;AAEpD,QAAM,kBAAkB,MAAM,gBAAgB;AAAA,IAC5C,WAAW,QAAQ,aAAa,QAAQ;AAAA,IACxC,YAAY,QAAQ;AAAA,IACpB,GAAI,OAAO,WAAW,UAAa,EAAE,QAAQ,OAAO,OAAO;AAAA,IAC3D,GAAI,QAAQ,WAAW,UAAa,EAAE,QAAQ,QAAQ,OAAO;AAAA,IAC7D,YAAY,QAAQ;AAAA,IACpB;AAAA,IACA,GAAI,QAAQ,cAAc,UAAa,EAAE,WAAW,QAAQ,UAAU;AAAA,IACtE,GAAI,OAAO,kBAAkB,UAAa,EAAE,eAAe,OAAO,cAAc;AAAA,EAClF,CAAC;AAED,QAAM,wBAAwB,SAAS,UAAU,eAAe;AAEhE,SAAO;AAAA,IACL,UAAU,gBAAgB;AAAA,IAC1B,WAAW,gBAAgB;AAAA,IAC3B,QAAQ,gBAAgB;AAAA,IACxB,UAAU,gBAAgB;AAAA,EAC5B;AACF;AAOA,eAAe,cACb,SACA,UACqB;AACrB,MAAI,CAAC,QAAQ,YAAa,QAAO,EAAE,QAAQ,QAAQ,QAAQ,eAAe,QAAQ,cAAc;AAChG,SAAO,eAAe,SAAS,QAAQ,aAAa,QAAQ;AAC9D;AAEA,eAAe,eACb,SACA,OACA,UACqB;AACrB,QAAM,UAAU,MAAM,yBAAyB,QAAQ,YAAY,QAAQ,IAAI;AAC/E,QAAM,gBAAgB,QAAQ,OAC3B,OAAO,CAAC,UAAU,CAAC,MAAM,YAAY,MAAM,UAAU,KAAK,EAC1D,IAAI,CAAC,UAAU,MAAM,IAAI;AAE5B,SAAO;AAAA,IACL,QAAQ,qBAAqB,QAAQ,QAAQ,aAAa;AAAA,IAC1D,eAAe,QAAQ,kBAAkB,SAAS,mBAAmB,MAAM,IAAI;AAAA,EACjF;AACF;AAEA,SAAS,qBACP,WACA,eACyB;AACzB,MAAI,kBAAkB,OAAW,QAAO;AACxC,MAAI,cAAc,OAAW,QAAO;AAEpC,QAAM,UAAU,IAAI,IAAI,aAAa;AACrC,SAAO,UAAU,OAAO,CAAC,SAAS,QAAQ,IAAI,IAAI,CAAC;AACrD;AAMA,eAAe,wBACb,SACA,UACA,iBACe;AACf,MAAI,QAAQ,eAAe,CAAC,QAAQ,UAAW;AAE/C,QAAM,iBAAiB,oBAAI,IAAe;AAAA,IACxC,GAAG,gBAAgB;AAAA,IACnB,GAAG,gBAAgB;AAAA,EACrB,CAAC;AACD,QAAM,oBAAoB;AAAA,IACxB,WAAW,QAAQ;AAAA,IACnB,MAAM;AAAA;AAAA,IAEN,OAAO,WAAW,QAAQ;AAAA,EAC5B,CAAC;AACH;","names":["path","skillsDir","path","path","path"]}
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  CLI_COLORS,
4
4
  UI_SYMBOLS
5
- } from "./chunk-WUSEZFER.js";
5
+ } from "./chunk-U46LYYRA.js";
6
6
 
7
7
  // src/cli/components/common/select-list.tsx
8
8
  import { useCallback as useCallback2 } from "react";
@@ -103,4 +103,4 @@ function SelectList({
103
103
  export {
104
104
  SelectList
105
105
  };
106
- //# sourceMappingURL=chunk-I3WF6L43.js.map
106
+ //# sourceMappingURL=chunk-XYBHH3M5.js.map
@@ -1,31 +1,31 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ConfigLoadError,
4
- configDirsInPlay,
4
+ configsInPlay,
5
5
  getErrorMessage,
6
- hostAt,
7
- loadInstalledConfig,
6
+ hostFor,
7
+ loadProjectConfigFromDir,
8
8
  refuseUnofferedPlacements
9
- } from "./chunk-E45IT3HC.js";
9
+ } from "./chunk-ENET4IF6.js";
10
10
 
11
11
  // src/cli/lib/hosts/configured-placements.ts
12
12
  async function unofferablePlacementsFound(cwd) {
13
- const findings = await Promise.all(configDirsInPlay(cwd).map(unofferablePlacementIn));
13
+ const findings = await Promise.all(configsInPlay(cwd).map(unofferablePlacementIn));
14
14
  return findings.filter((finding) => finding !== null);
15
15
  }
16
- async function unofferablePlacementIn(root) {
17
- const skills = await configuredSkillsAt(root);
16
+ async function unofferablePlacementIn(config) {
17
+ const skills = await configuredSkillsAt(config);
18
18
  if (skills === null) return null;
19
19
  try {
20
- refuseUnofferedPlacements(skills, hostAt(root));
20
+ refuseUnofferedPlacements(skills, hostFor(config.provider));
21
21
  return null;
22
22
  } catch (error) {
23
23
  return getErrorMessage(error);
24
24
  }
25
25
  }
26
- async function configuredSkillsAt(root) {
26
+ async function configuredSkillsAt({ dir, provider }) {
27
27
  try {
28
- const loaded = await loadInstalledConfig(root);
28
+ const loaded = await loadProjectConfigFromDir(dir, provider);
29
29
  return loaded?.config.skills ?? null;
30
30
  } catch (error) {
31
31
  if (error instanceof ConfigLoadError) return null;
@@ -36,4 +36,4 @@ async function configuredSkillsAt(root) {
36
36
  export {
37
37
  unofferablePlacementsFound
38
38
  };
39
- //# sourceMappingURL=chunk-ECPFYHDX.js.map
39
+ //# sourceMappingURL=chunk-ZBI6GFJD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/lib/hosts/configured-placements.ts"],"sourcesContent":["/**\n * The placement refusal on the read path: `config.ts` carries no provider, so a config copied into\n * another provider's folder never met that host's pre-flight. Not run by `uninstall`, which must\n * still be able to remove such an installation.\n */\n\nimport {\n ConfigLoadError,\n configsInPlay,\n loadProjectConfigFromDir,\n type ConfigInPlay,\n} from \"../configuration/project-config.js\";\nimport { getErrorMessage } from \"../../utils/errors.js\";\nimport type { SkillConfig } from \"../../types/config.js\";\nimport { hostFor } from \"./host-for.js\";\nimport { refuseUnofferedPlacements } from \"./offered-placements.js\";\n\n/** Both scopes, each asked of its OWN host: the two scopes can be on different providers. */\nexport async function unofferablePlacementsFound(cwd: string): Promise<string[]> {\n const findings = await Promise.all(configsInPlay(cwd).map(unofferablePlacementIn));\n return findings.filter((finding): finding is string => finding !== null);\n}\n\nasync function unofferablePlacementIn(config: ConfigInPlay): Promise<string | null> {\n const skills = await configuredSkillsAt(config);\n if (skills === null) return null;\n\n try {\n refuseUnofferedPlacements(skills, hostFor(config.provider));\n return null;\n } catch (error) {\n return getErrorMessage(error);\n }\n}\n\n/** Degrades on `ConfigLoadError` only, which `ensureConfigReadable` and doctor report by name. */\nasync function configuredSkillsAt({ dir, provider }: ConfigInPlay): Promise<SkillConfig[] | null> {\n try {\n const loaded = await loadProjectConfigFromDir(dir, provider);\n return loaded?.config.skills ?? null;\n } catch (error) {\n if (error instanceof ConfigLoadError) return null;\n throw error;\n }\n}\n"],"mappings":";;;;;;;;;;;AAkBA,eAAsB,2BAA2B,KAAgC;AAC/E,QAAM,WAAW,MAAM,QAAQ,IAAI,cAAc,GAAG,EAAE,IAAI,sBAAsB,CAAC;AACjF,SAAO,SAAS,OAAO,CAAC,YAA+B,YAAY,IAAI;AACzE;AAEA,eAAe,uBAAuB,QAA8C;AAClF,QAAM,SAAS,MAAM,mBAAmB,MAAM;AAC9C,MAAI,WAAW,KAAM,QAAO;AAE5B,MAAI;AACF,8BAA0B,QAAQ,QAAQ,OAAO,QAAQ,CAAC;AAC1D,WAAO;AAAA,EACT,SAAS,OAAO;AACd,WAAO,gBAAgB,KAAK;AAAA,EAC9B;AACF;AAGA,eAAe,mBAAmB,EAAE,KAAK,SAAS,GAAgD;AAChG,MAAI;AACF,UAAM,SAAS,MAAM,yBAAyB,KAAK,QAAQ;AAC3D,WAAO,QAAQ,OAAO,UAAU;AAAA,EAClC,SAAS,OAAO;AACd,QAAI,iBAAiB,gBAAiB,QAAO;AAC7C,UAAM;AAAA,EACR;AACF;","names":[]}
@@ -2,7 +2,8 @@
2
2
  import {
3
3
  BaseCommand,
4
4
  EXIT_CODES
5
- } from "../../chunk-IAQFZFWD.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-E45IT3HC.js";
27
+ } from "../../chunk-ENET4IF6.js";
27
28
  import {
28
29
  plural
29
- } from "../../chunk-AIBVAYHS.js";
30
+ } from "../../chunk-UE4Z3YMB.js";
30
31
  import {
31
32
  CATALOG_JSON,
32
33
  CLI_INVOKE_COMMAND,
@@ -35,7 +36,7 @@ import {
35
36
  PLUGINS_DIST_PATH,
36
37
  PLUGIN_MANIFEST_DIR,
37
38
  STANDARD_FILES
38
- } from "../../chunk-WUSEZFER.js";
39
+ } from "../../chunk-U46LYYRA.js";
39
40
  import "../../chunk-GHHJYNAN.js";
40
41
 
41
42
  // src/cli/commands/build/marketplace.ts
@@ -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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,aAAa;AACtB,OAAO,UAAU;AACjB,SAAS,cAAc;AACvB,SAAS,SAAS;AAoClB,IAAM,sBAAsB,GAAG,mBAAmB,IAAI,gBAAgB;AAEtE,IAAM,wBAAwB;AAE9B,IAAM,mBAAmB;AAEzB,IAAM,wBAAwB;AAE9B,IAAM,4BAA4B,EAAE,OAAO;AAAA,EACzC,MAAM,EAAE,OAAO;AAAA,EACf,OAAO,EAAE,OAAO,EAAE,cAAc;AAAA,EAChC,KAAK,EAAE,OAAO,EAAE,cAAc;AAChC,CAAC;AAED,IAAM,oBAAoB,EACvB,OAAO;AAAA,EACN,MAAM,EAAE,OAAO;AAAA,EACf,SAAS,EAAE,OAAO;AAAA,EAClB,aAAa,EAAE,OAAO;AAAA,EACtB,QAAQ,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,yBAAyB,CAAC,EAAE,cAAc;AACzE,CAAC,EACA,YAAY;AAQf,IAAqB,mBAArB,MAAqB,0BAAyB,YAAY;AAAA,EACxD,OAAO,UAAU;AAAA,EAEjB,OAAO,cACL;AAAA,EAEF,OAAO,WAAW;AAAA,IAChB;AAAA,MACE,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,aACE;AAAA,MACF,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EAEA,OAAO,QAAQ;AAAA,IACb,MAAM,MAAM,OAAO;AAAA,MACjB,aACE;AAAA,IACJ,CAAC;AAAA,IACD,eAAe,MAAM,OAAO;AAAA,MAC1B,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,IACD,QAAQ,MAAM,OAAO;AAAA,MACnB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,IACD,SAAS,MAAM,QAAQ;AAAA,MACrB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,iBAAgB;AACnD,eAAW,MAAM,OAAO;AAExB,UAAM,cAAc,QAAQ,IAAI;AAChC,UAAM,aAAa,KAAK,QAAQ,aAAa,MAAM,aAAa,CAAC;AACjE,UAAM,aAAa,KAAK,QAAQ,aAAa,MAAM,MAAM;AACzD,UAAM,WAAW,MAAM,KAAK,wBAAwB,aAAa,MAAM,IAAI;AAE3E,SAAK,YAAY,YAAY,UAAU;AAEvC,QAAI;AAEF,YAAM,cAAc,MAAM,KAAK,YAAY,YAAY,MAAM,aAAa,GAAG,QAAQ;AACrF,YAAM,UAAU,MAAM,KAAK,YAAY,WAAW;AAElD,YAAM,KAAK,cAAc,YAAY,WAAW;AAChD,YAAM,KAAK,aAAa,YAAY,OAAO;AAC3C,WAAK,WAAW,WAAW;AAC3B,WAAK,YAAY,WAAW;AAE5B,WAAK,IAAI,EAAE;AACX,WAAK;AAAA,QACH,8BAA8B,OAAO,oBAAoB,WAAW,EAAE,OAAO,QAAQ,CAAC;AAAA,MACxF;AACA,WAAK,IAAI,EAAE;AAAA,IACb,SAAS,OAAO;AACd,WAAK,IAAI,mBAAmB;AAC5B,WAAK,YAAY,KAAK;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,MAAc,wBACZ,aACA,cAC8B;AAC9B,UAAM,kBAAkB,KAAK,KAAK,aAAa,eAAe,YAAY;AAC1E,UAAM,EAAE,MAAM,SAAS,aAAa,OAAO,IAAI,MAAM,KAAK;AAAA,MACxD;AAAA,MACA;AAAA,IACF;AAEA,QAAI,QAAQ,KAAK,MAAM,IAAI;AACzB,WAAK,MAAM,wBAAwB,eAAe,GAAG,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IACjF;AAEA,UAAM,QAAQ,YAAY,MAAM;AAChC,QAAI,MAAM,KAAK,KAAK,MAAM,IAAI;AAC5B,WAAK,MAAM,0BAA0B,eAAe,GAAG,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IACnF;AAEA,UAAM,eAAe,KAAK,uBAAuB,MAAM,cAAc,eAAe;AAEpF,UAAM,gBAAgB,wBAAwB,cAAc,MAAM,qBAAqB;AACvF,QAAI,eAAe;AACjB,WAAK,MAAM,eAAe,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IACtD;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,WAAW,MAAM;AAAA,MACjB,GAAI,MAAM,UAAU,UAAa,EAAE,YAAY,MAAM,MAAM;AAAA,IAC7D;AAAA,EACF;AAAA,EAEA,MAAc,gBACZ,aACA,iBACsB;AACtB,QAAI;AACJ,QAAI;AACF,mBAAa,MAAM,SAAS,eAAe;AAAA,IAC7C,QAAQ;AACN,WAAK;AAAA,QACH,2BAA2B,WAAW;AAAA,QACtC,EAAE,MAAM,WAAW,MAAM;AAAA,MAC3B;AAAA,IACF;AAEA,QAAI;AACJ,QAAI;AACF,mBAAa,KAAK,MAAM,UAAU;AAAA,IACpC,SAAS,OAAO;AACd,WAAK,MAAM,mCAAmC,eAAe,KAAK,gBAAgB,KAAK,CAAC,IAAI;AAAA,QAC1F,MAAM,WAAW;AAAA,MACnB,CAAC;AAAA,IACH;AAEA,UAAM,cAAc,kBAAkB,UAAU,UAAU;AAC1D,QAAI,CAAC,YAAY,SAAS;AACxB,YAAM,gBAAgB,YAAY,MAAM,OAAO,IAAI,CAAC,MAAM,EAAE,KAAK,KAAK,GAAG,CAAC,EAAE,KAAK,IAAI;AACrF,WAAK;AAAA,QACH,mBAAmB,eAAe,gCAAgC,aAAa;AAAA,QAC/E,EAAE,MAAM,WAAW,MAAM;AAAA,MAC3B;AAAA,IACF;AAEA,WAAO,YAAY;AAAA,EACrB;AAAA;AAAA,EAGQ,uBACN,aACA,cACA,iBACQ;AACR,QAAI,iBAAiB,QAAW;AAC9B,YAAM,kBAAkB,sBAAsB,cAAc,gBAAgB;AAC5E,UAAI,iBAAiB;AACnB,aAAK,MAAM,mBAAmB,YAAY,MAAM,eAAe,IAAI;AAAA,UACjE,MAAM,WAAW;AAAA,QACnB,CAAC;AAAA,MACH;AACA,aAAO;AAAA,IACT;AAEA,QAAI,sBAAsB,aAAa,gBAAgB,GAAG;AACxD,WAAK,MAAM,8BAA8B,aAAa,eAAe,GAAG;AAAA,QACtE,MAAM,WAAW;AAAA,MACnB,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,YAAY,YAAoB,YAA0B;AAChE,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,6BAA6B;AACtC,SAAK,IAAI,wBAAwB,UAAU,EAAE;AAC7C,SAAK,IAAI,kBAAkB,UAAU,EAAE;AACvC,SAAK,IAAI,EAAE;AAAA,EACb;AAAA,EAEA,MAAc,YACZ,YACA,gBACA,UACsB;AACtB,SAAK,IAAI,qBAAqB;AAE9B,UAAM,cAAc,MAAM,oBAAoB,YAAY;AAAA,MACxD,MAAM,SAAS;AAAA,MACf,SAAS,SAAS;AAAA,MAClB,aAAa,SAAS;AAAA,MACtB,WAAW,SAAS;AAAA,MACpB,GAAI,SAAS,eAAe,UAAa,EAAE,YAAY,SAAS,WAAW;AAAA,MAC3E,YAAY,KAAK,cAAc;AAAA,IACjC,CAAC;AAED,UAAM,QAAQ,oBAAoB,WAAW;AAC7C,SAAK,IAAI,SAAS,OAAO,MAAM,OAAO,QAAQ,CAAC,EAAE;AAEjD,QAAI,YAAY,QAAQ,WAAW,GAAG;AACpC,WAAK,MAAM,mBAAmB,YAAY,cAAc,GAAG,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IACvF;AAEA,UAAM,iBAAiB,yBAAyB,WAAW;AAC3D,QAAI,gBAAgB;AAClB,WAAK,MAAM,gBAAgB,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IACvD;AAEA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAc,YAAY,aAAkD;AAC1E,SAAK,IAAI,0BAA0B,YAAY,KAAK;AACpD,UAAM,KAAK,8BAA8B,WAAW;AACpD,UAAM,SAAS,MAAM,sBAAsB,WAAW;AACtD,WAAO,EAAE,GAAG,QAAQ,aAAa,mBAAmB;AAAA,EACtD;AAAA;AAAA,EAGA,MAAc,8BAA8B,aAAoC;AAC9E,UAAM,OAAO,MAAM,qBAAqB,WAAW;AACnD,QAAI,KAAK,SAAS,mBAAoB;AAEtC,SAAK,MAAM,sBAAsB,kBAAkB,KAAK,YAAY,uBAAuB,CAAC,GAAG;AAAA,MAC7F,MAAM,WAAW;AAAA,IACnB,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,cAAc,YAAoB,aAAyC;AACvF,SAAK,IAAI,WAAW,gBAAgB,KAAK;AACzC,UAAM,iBAAiB,YAAY,WAAW;AAC9C,SAAK,IAAI,SAAS,UAAU,EAAE;AAAA,EAChC;AAAA,EAEA,MAAc,aAAa,YAAoB,SAA4C;AACzF,UAAM,cAAc,KAAK,KAAK,KAAK,QAAQ,UAAU,GAAG,YAAY;AAEpE,SAAK,IAAI,WAAW,YAAY,KAAK;AACrC,UAAM,UAAU,aAAa,GAAG,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAAA,CAAI;AACpE,SAAK,IAAI,SAAS,WAAW,EAAE;AAAA,EACjC;AAAA,EAEQ,WAAW,aAAgC;AACjD,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,qBAAqB;AAC9B,UAAM,mBAAmB;AAAA,MACvB,OAAO,QAAQ,oBAAoB,WAAW,EAAE,UAAU;AAAA,MAC1D,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC;AAAA,IAClB;AACA,eAAW,CAAC,UAAU,KAAK,KAAK,kBAAkB;AAChD,WAAK,IAAI,KAAK,QAAQ,KAAK,KAAK,EAAE;AAAA,IACpC;AAAA,EACF;AAAA,EAEQ,YAAY,aAAgC;AAClD,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,iBAAiB;AAC1B,UAAM,aAAa;AACnB,eAAW,UAAU,YAAY,QAAQ,MAAM,GAAG,UAAU,GAAG;AAC7D,YAAM,UAAU,OAAO,UAAU,IAAI,OAAO,OAAO,KAAK;AACxD,YAAM,WAAW,OAAO,WAAW,IAAI,OAAO,QAAQ,MAAM;AAC5D,WAAK,IAAI,KAAK,OAAO,IAAI,IAAI,OAAO,IAAI,QAAQ,EAAE;AAClD,UAAI,OAAO,aAAa;AACtB,aAAK,IAAI,OAAO,OAAO,WAAW,EAAE;AAAA,MACtC;AAAA,IACF;AACA,QAAI,YAAY,QAAQ,SAAS,YAAY;AAC3C,WAAK,IAAI,aAAa,YAAY,QAAQ,SAAS,UAAU,OAAO;AAAA,IACtE;AAAA,EACF;AACF;AAQA,SAAS,mBAAmB,YAAoB,gBAAgC;AAC9E,SACE,uBAAuB,UAAU,8FACE,kBAAkB,uFACE,cAAc;AAEzE;AAGA,SAAS,YAAY,QAA6E;AAChG,MAAI,CAAC,OAAQ,QAAO,EAAE,MAAM,GAAG;AAE/B,MAAI,OAAO,WAAW,UAAU;AAC9B,WAAO,EAAE,MAAM,OAAO,MAAM,GAAI,OAAO,UAAU,UAAa,EAAE,OAAO,OAAO,MAAM,EAAG;AAAA,EACzF;AAEA,QAAM,CAAC,EAAE,aAAa,YAAY,IAAI,OAAO,MAAM,qBAAqB,KAAK,CAAC;AAC9E,MAAI,gBAAgB,UAAa,iBAAiB,QAAW;AAC3D,WAAO,EAAE,MAAM,YAAY,KAAK,GAAG,OAAO,aAAa,KAAK,EAAE;AAAA,EAChE;AAEA;AAAA,IACE,gCAAgC,MAAM;AAAA,EACxC;AACA,SAAO,EAAE,MAAM,OAAO,KAAK,EAAE;AAC/B;","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-IXVGBUWI.js";
6
- import "../../chunk-EFXVYQGT.js";
5
+ } from "../../chunk-EC3JXT23.js";
6
+ import "../../chunk-MQZNDK5F.js";
7
7
  import {
8
8
  BaseCommand
9
- } from "../../chunk-IAQFZFWD.js";
9
+ } from "../../chunk-JTMSFBCA.js";
10
+ import "../../chunk-FACDJH6O.js";
10
11
  import {
11
12
  compileAllSkillPlugins,
12
13
  compileSkillPlugin,
@@ -15,14 +16,14 @@ import {
15
16
  readPluginManifest,
16
17
  remove,
17
18
  setVerbose
18
- } from "../../chunk-E45IT3HC.js";
19
+ } from "../../chunk-ENET4IF6.js";
19
20
  import {
20
21
  plural
21
- } from "../../chunk-AIBVAYHS.js";
22
+ } from "../../chunk-UE4Z3YMB.js";
22
23
  import {
23
24
  DIRS,
24
25
  PLUGINS_DIST_PATH
25
- } from "../../chunk-WUSEZFER.js";
26
+ } from "../../chunk-U46LYYRA.js";
26
27
  import "../../chunk-GHHJYNAN.js";
27
28
 
28
29
  // src/cli/commands/build/plugins.ts
@@ -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":[]}