agents-inc 0.170.2 → 0.172.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 (91) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/{chunk-PSUTNOQ2.js → chunk-255DGUCH.js} +2 -2
  3. package/dist/chunk-33JICQD5.js +196 -0
  4. package/dist/chunk-33JICQD5.js.map +1 -0
  5. package/dist/{chunk-3ED3KHHD.js → chunk-3R3LHA4Q.js} +2 -2
  6. package/dist/{chunk-YXKTY5WM.js → chunk-5MGRHS2G.js} +94 -58
  7. package/dist/chunk-5MGRHS2G.js.map +1 -0
  8. package/dist/{chunk-PLFANHRZ.js → chunk-5PPB6HT6.js} +2 -2
  9. package/dist/{chunk-66AEVERM.js → chunk-6CRA46YO.js} +14 -14
  10. package/dist/{chunk-ELV5WDS3.js → chunk-6LUTY35Q.js} +25 -14
  11. package/dist/chunk-6LUTY35Q.js.map +1 -0
  12. package/dist/{chunk-AUNRHWH4.js → chunk-7OG635DK.js} +26 -4
  13. package/dist/chunk-7OG635DK.js.map +1 -0
  14. package/dist/{chunk-GEMW5RQ2.js → chunk-7ZOWSCAO.js} +29 -102
  15. package/dist/chunk-7ZOWSCAO.js.map +1 -0
  16. package/dist/{chunk-YGDWHDOY.js → chunk-A3ZAXL5T.js} +4 -5
  17. package/dist/{chunk-YGDWHDOY.js.map → chunk-A3ZAXL5T.js.map} +1 -1
  18. package/dist/chunk-G7NUK3BF.js +253 -0
  19. package/dist/chunk-G7NUK3BF.js.map +1 -0
  20. package/dist/{chunk-THO7LO5B.js → chunk-KCLBLK3F.js} +3 -3
  21. package/dist/{chunk-2YA4DDRM.js → chunk-LUKDDHSI.js} +8 -6
  22. package/dist/{chunk-2YA4DDRM.js.map → chunk-LUKDDHSI.js.map} +1 -1
  23. package/dist/{chunk-OCAVW6N5.js → chunk-MBIOZ5LW.js} +12 -3
  24. package/dist/{chunk-OCAVW6N5.js.map → chunk-MBIOZ5LW.js.map} +1 -1
  25. package/dist/{chunk-7C3PFRBU.js → chunk-MHAQWMNJ.js} +35 -5
  26. package/dist/{chunk-7C3PFRBU.js.map → chunk-MHAQWMNJ.js.map} +1 -1
  27. package/dist/{chunk-HACRR422.js → chunk-MOL2J5HS.js} +2 -2
  28. package/dist/{chunk-BBDGYJHX.js → chunk-N33AKFLR.js} +2 -2
  29. package/dist/{chunk-5BNX73OU.js → chunk-NISWBQNS.js} +52 -31
  30. package/dist/chunk-NISWBQNS.js.map +1 -0
  31. package/dist/{chunk-GAKVZNTX.js → chunk-VILFCMRN.js} +420 -316
  32. package/dist/chunk-VILFCMRN.js.map +1 -0
  33. package/dist/{chunk-IWY5IR4F.js → chunk-Y23MP2OC.js} +8 -8
  34. package/dist/commands/build/marketplace.js +16 -14
  35. package/dist/commands/build/marketplace.js.map +1 -1
  36. package/dist/commands/build/plugins.js +6 -6
  37. package/dist/commands/compile.js +12 -12
  38. package/dist/commands/doctor.js +64 -81
  39. package/dist/commands/doctor.js.map +1 -1
  40. package/dist/commands/edit.js +150 -152
  41. package/dist/commands/edit.js.map +1 -1
  42. package/dist/commands/eject.js +10 -10
  43. package/dist/commands/init.js +19 -16
  44. package/dist/commands/list.js +14 -17
  45. package/dist/commands/list.js.map +1 -1
  46. package/dist/commands/new/marketplace.js +4 -4
  47. package/dist/commands/search.js +15 -13
  48. package/dist/commands/search.js.map +1 -1
  49. package/dist/commands/share.js +11 -11
  50. package/dist/commands/uninstall.js +109 -98
  51. package/dist/commands/uninstall.js.map +1 -1
  52. package/dist/commands/update.js +6 -6
  53. package/dist/components/common/scroll-affordance.js +2 -2
  54. package/dist/components/common/select-list.js +2 -2
  55. package/dist/components/common/skill-agent-summary.js +3 -4
  56. package/dist/components/common/summary-panel.js +11 -146
  57. package/dist/components/common/summary-panel.js.map +1 -1
  58. package/dist/hooks/init.js +22 -19
  59. package/dist/hooks/init.js.map +1 -1
  60. package/dist/load-agent-defs-54VIKN4T.js +14 -0
  61. package/dist/{recompile-project-agents-I33KQJFB.js → recompile-project-agents-5A44NJRD.js} +8 -8
  62. package/dist/{source-loader-TTJVW2ER.js → source-loader-LQNRI5UZ.js} +4 -4
  63. package/dist/src/agents/tester/web-tester/playbook.md +1 -1
  64. package/package.json +1 -1
  65. package/src/agents/tester/web-tester/playbook.md +1 -1
  66. package/dist/chunk-5BNX73OU.js.map +0 -1
  67. package/dist/chunk-AUNRHWH4.js.map +0 -1
  68. package/dist/chunk-ELV5WDS3.js.map +0 -1
  69. package/dist/chunk-GAKVZNTX.js.map +0 -1
  70. package/dist/chunk-GEMW5RQ2.js.map +0 -1
  71. package/dist/chunk-O4LN3HFI.js +0 -69
  72. package/dist/chunk-O4LN3HFI.js.map +0 -1
  73. package/dist/chunk-PMUZR4XO.js +0 -108
  74. package/dist/chunk-PMUZR4XO.js.map +0 -1
  75. package/dist/chunk-RIK45Q4I.js +0 -103
  76. package/dist/chunk-RIK45Q4I.js.map +0 -1
  77. package/dist/chunk-YXKTY5WM.js.map +0 -1
  78. package/dist/components/common/removal-plan-confirm.js +0 -10
  79. package/dist/load-agent-defs-6QUUMGHK.js +0 -14
  80. package/dist/source-loader-TTJVW2ER.js.map +0 -1
  81. /package/dist/{chunk-PSUTNOQ2.js.map → chunk-255DGUCH.js.map} +0 -0
  82. /package/dist/{chunk-3ED3KHHD.js.map → chunk-3R3LHA4Q.js.map} +0 -0
  83. /package/dist/{chunk-PLFANHRZ.js.map → chunk-5PPB6HT6.js.map} +0 -0
  84. /package/dist/{chunk-66AEVERM.js.map → chunk-6CRA46YO.js.map} +0 -0
  85. /package/dist/{chunk-THO7LO5B.js.map → chunk-KCLBLK3F.js.map} +0 -0
  86. /package/dist/{chunk-HACRR422.js.map → chunk-MOL2J5HS.js.map} +0 -0
  87. /package/dist/{chunk-BBDGYJHX.js.map → chunk-N33AKFLR.js.map} +0 -0
  88. /package/dist/{chunk-IWY5IR4F.js.map → chunk-Y23MP2OC.js.map} +0 -0
  89. /package/dist/{components/common/removal-plan-confirm.js.map → load-agent-defs-54VIKN4T.js.map} +0 -0
  90. /package/dist/{recompile-project-agents-I33KQJFB.js.map → recompile-project-agents-5A44NJRD.js.map} +0 -0
  91. /package/dist/{load-agent-defs-6QUUMGHK.js.map → source-loader-LQNRI5UZ.js.map} +0 -0
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  pruneStaleCompiledAgents,
4
4
  recompileAgents
5
- } from "./chunk-2YA4DDRM.js";
5
+ } from "./chunk-LUKDDHSI.js";
6
6
  import {
7
7
  agentCodec,
8
8
  buildAgentScopeMap,
@@ -24,17 +24,17 @@ import {
24
24
  sayingEachWarningOnce,
25
25
  skillsDir,
26
26
  skillsPathPrefix,
27
- typedEntries,
28
- typedKeys,
29
27
  verbose
30
- } from "./chunk-GAKVZNTX.js";
28
+ } from "./chunk-VILFCMRN.js";
31
29
  import {
32
30
  initializeMatrix,
33
- matrix
34
- } from "./chunk-AUNRHWH4.js";
31
+ matrix,
32
+ typedEntries,
33
+ typedKeys
34
+ } from "./chunk-7OG635DK.js";
35
35
  import {
36
36
  globalInstallRoot
37
- } from "./chunk-7C3PFRBU.js";
37
+ } from "./chunk-MHAQWMNJ.js";
38
38
 
39
39
  // src/cli/lib/operations/skills/discover-skills.ts
40
40
  var NO_LOCAL_SKILLS = { skills: {}, unusableMetadata: [] };
@@ -274,4 +274,4 @@ export {
274
274
  removeCompiledAgents,
275
275
  compileAgents
276
276
  };
277
- //# sourceMappingURL=chunk-IWY5IR4F.js.map
277
+ //# sourceMappingURL=chunk-Y23MP2OC.js.map
@@ -2,8 +2,11 @@
2
2
  import {
3
3
  BaseCommand,
4
4
  EXIT_CODES
5
- } from "../../chunk-GEMW5RQ2.js";
5
+ } from "../../chunk-7ZOWSCAO.js";
6
6
  import {
7
+ NO_VALID_DEFAULT_EXPORT,
8
+ configLoadFailure,
9
+ configUnreadableError,
7
10
  generateMarketplace,
8
11
  getErrorMessage,
9
12
  getMarketplaceStats,
@@ -20,10 +23,10 @@ import {
20
23
  warn,
21
24
  writeFile,
22
25
  writeMarketplace
23
- } from "../../chunk-GAKVZNTX.js";
26
+ } from "../../chunk-VILFCMRN.js";
24
27
  import {
25
28
  plural
26
- } from "../../chunk-AUNRHWH4.js";
29
+ } from "../../chunk-7OG635DK.js";
27
30
  import {
28
31
  CATALOG_JSON,
29
32
  CLI_INVOKE_COMMAND,
@@ -32,7 +35,7 @@ import {
32
35
  PLUGINS_DIST_PATH,
33
36
  PLUGIN_MANIFEST_DIR,
34
37
  STANDARD_FILES
35
- } from "../../chunk-7C3PFRBU.js";
38
+ } from "../../chunk-MHAQWMNJ.js";
36
39
  import "../../chunk-GHHJYNAN.js";
37
40
 
38
41
  // src/cli/commands/build/marketplace.ts
@@ -224,10 +227,18 @@ var BuildMarketplace = class _BuildMarketplace extends BaseCommand {
224
227
  /** Unconditional: consumers must be able to read an absent catalogue as a broken marketplace. */
225
228
  async readCatalog(projectRoot) {
226
229
  this.log(`Reading the skills for ${CATALOG_JSON}...`);
227
- await warnOfAConfigDeclaringNothing(projectRoot);
230
+ await this.refuseAConfigDeclaringNothing(projectRoot);
228
231
  const matrix = await loadMarketplaceMatrix(projectRoot);
229
232
  return { ...matrix, generatedAt: GENERATED_AT_BUILD };
230
233
  }
234
+ /** Every other reader takes such a file as absent; the build is where its author can fix it. */
235
+ async refuseAConfigDeclaringNothing(projectRoot) {
236
+ const read = await readSourceRepoConfig(projectRoot);
237
+ if (read.kind !== "declares-nothing") return;
238
+ this.error(configUnreadableError(configLoadFailure(read.configPath, NO_VALID_DEFAULT_EXPORT)), {
239
+ exit: EXIT_CODES.ERROR
240
+ });
241
+ }
231
242
  async writeManifest(outputPath, marketplace) {
232
243
  this.log(`Writing ${MARKETPLACE_JSON}...`);
233
244
  await writeMarketplace(outputPath, marketplace);
@@ -268,15 +279,6 @@ var BuildMarketplace = class _BuildMarketplace extends BaseCommand {
268
279
  }
269
280
  }
270
281
  };
271
- async function warnOfAConfigDeclaringNothing(projectRoot) {
272
- const read = await readSourceRepoConfig(projectRoot);
273
- if (read.kind === "declares-nothing") {
274
- warn(configDeclaresNothing(path.relative(projectRoot, read.configPath)));
275
- }
276
- }
277
- function configDeclaresNothing(configPath) {
278
- return `${configPath} is empty or exports nothing, so this build reads the marketplace with the default layout. Give it a default export, or delete it.`;
279
- }
280
282
  function noPluginsToPublish(pluginsDir, pluginsDirFlag) {
281
283
  return `No plugins found in ${pluginsDir}. A marketplace with no plugins is refused when it is read back, so none was written. Run '${CLI_INVOKE_COMMAND} build plugins' first, or point --plugins-dir at the directory holding them (it is '${pluginsDirFlag}' for this run).`;
282
284
  }
@@ -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 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 { 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 warnOfAConfigDeclaringNothing(projectRoot);\n const matrix = await loadMarketplaceMatrix(projectRoot);\n return { ...matrix, generatedAt: GENERATED_AT_BUILD };\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 loader reads such a file as absent, so without this the build would say nothing of it. */\nasync function warnOfAConfigDeclaringNothing(projectRoot: string): Promise<void> {\n const read = await readSourceRepoConfig(projectRoot);\n if (read.kind === \"declares-nothing\") {\n warn(configDeclaresNothing(path.relative(projectRoot, read.configPath)));\n }\n}\n\nfunction configDeclaresNothing(configPath: string): string {\n return (\n `${configPath} is empty or exports nothing, so this build reads the marketplace with the ` +\n `default layout. Give it a default export, or delete it.`\n );\n}\n\n/** The marketplace schema requires at least one plugin, so an empty manifest is never written. */\nfunction noPluginsToPublish(pluginsDir: string, pluginsDirFlag: string): string {\n return (\n `No plugins found in ${pluginsDir}. A marketplace with no plugins is refused when it is read ` +\n `back, so none was written. Run '${CLI_INVOKE_COMMAND} build plugins' first, or point ` +\n `--plugins-dir at the directory holding them (it is '${pluginsDirFlag}' for this run).`\n );\n}\n\n/** Accepts `\"Name <email> (url)\"` or `{ name, email, url }`; the caller refuses an empty name. */\nfunction parseAuthor(author: string | { name: string; email?: string } | undefined): ParsedAuthor {\n if (!author) return { name: \"\" };\n\n if (typeof author === \"object\") {\n return { name: author.name, ...(author.email !== undefined && { email: author.email }) };\n }\n\n const [, matchedName, matchedEmail] = author.match(AUTHOR_STRING_PATTERN) ?? [];\n if (matchedName !== undefined && matchedEmail !== undefined) {\n return { name: matchedName.trim(), email: matchedEmail.trim() };\n }\n\n warn(\n `package.json 'author' field \"${author}\" has no parseable email — marketplace owner.email will be empty`,\n );\n return { name: author.trim() };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/cli/commands/build/marketplace.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { sortBy } from \"remeda\";\nimport { z } from \"zod\";\n\nimport { BaseCommand } from \"../../base-command\";\nimport { setVerbose, warn } from \"../../utils/logger\";\nimport {\n configUnreadableError,\n marketplaceHasNoVersion,\n marketplaceNameNotPublishable,\n marketplaceOwnerHasNoName,\n} from \"../../utils/messages\";\nimport { readFile, writeFile } from \"../../utils/fs\";\nimport { getErrorMessage } from \"../../utils/errors\";\nimport { EXIT_CODES } from \"../../lib/exit-codes\";\nimport { readSourceRepoConfig } from \"../../lib/configuration/config\";\nimport { configLoadFailure, NO_VALID_DEFAULT_EXPORT } from \"../../lib/configuration/config-loader\";\nimport { loadMarketplaceMatrix } from \"../../lib/loading\";\nimport {\n generateMarketplace,\n writeMarketplace,\n getMarketplaceStats,\n validateMarketplaceName,\n validateSkillIdNamespace,\n} from \"../../lib/marketplace-generator\";\nimport {\n CATALOG_JSON,\n CLI_INVOKE_COMMAND,\n GENERATED_AT_BUILD,\n MARKETPLACE_JSON,\n PLUGIN_MANIFEST_DIR,\n PLUGINS_DIST_PATH,\n STANDARD_FILES,\n} from \"../../consts\";\nimport type { Marketplace, MergedSkillsMatrix } from \"../../types\";\nimport { validateKebabCaseName } from \"../../lib/validate-kebab-name.js\";\nimport { plural } from \"../../utils/string.js\";\n\nconst DEFAULT_OUTPUT_FILE = `${PLUGIN_MANIFEST_DIR}/${MARKETPLACE_JSON}`;\n\nconst AUTHOR_STRING_PATTERN = /^(.*?)\\s*<([^>]+)>\\s*(?:\\(([^)]+)\\))?\\s*$/;\n\nconst MARKETPLACE_NOUN = \"Marketplace\";\n\nconst RESERVED_NAME_WAY_OUT = \"set package.json 'name', or pass --name\";\n\nconst packageAuthorObjectSchema = z.object({\n name: z.string(),\n email: z.string().exactOptional(),\n url: z.string().exactOptional(),\n});\n\nconst packageJsonSchema = z\n .object({\n name: z.string(),\n version: z.string(),\n description: z.string(),\n author: z.union([z.string(), packageAuthorObjectSchema]).exactOptional(),\n })\n .passthrough();\n\ntype PackageJson = z.infer<typeof packageJsonSchema>;\ntype MarketplaceIdentity = Pick<PackageJson, \"name\" | \"version\" | \"description\"> & {\n ownerName: string;\n ownerEmail?: string;\n};\n\nexport default class BuildMarketplace extends BaseCommand {\n static summary = \"Generate marketplace.json from built plugins (requires skills repo)\";\n\n static description =\n \"Generate marketplace.json from built plugins. This command scans the plugins directory and generates a marketplace manifest file. Reads marketplace identity (name, version, description, author) from package.json in the current working directory. Use --name to override the marketplace name when package.json uses an npm scoped name (e.g. @scope/pkg), which is not a valid marketplace name.\";\n\n static examples = [\n {\n description: \"Generate marketplace.json from the default plugins directory\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Generate marketplace.json from a custom plugins directory\",\n command: \"<%= config.bin %> <%= command.id %> --plugins-dir dist/stacks\",\n },\n {\n description: \"Write marketplace.json to a custom output path\",\n command: \"<%= config.bin %> <%= command.id %> --output .claude-plugin/market.json\",\n },\n {\n description:\n \"Override the marketplace name (use when package.json has an npm scoped name like @scope/pkg)\",\n command: \"<%= config.bin %> <%= command.id %> --name my-marketplace\",\n },\n ];\n\n static flags = {\n name: Flags.string({\n description:\n \"Override the marketplace name (defaults to package.json 'name'). Must be kebab-case.\",\n }),\n \"plugins-dir\": Flags.string({\n char: \"p\",\n description: \"Plugins directory\",\n default: PLUGINS_DIST_PATH,\n }),\n output: Flags.string({\n char: \"o\",\n description: \"Output file\",\n default: DEFAULT_OUTPUT_FILE,\n }),\n verbose: Flags.boolean({\n char: \"v\",\n description: \"Enable verbose logging\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(BuildMarketplace);\n setVerbose(flags.verbose);\n\n const projectRoot = process.cwd();\n const pluginsDir = path.resolve(projectRoot, flags[\"plugins-dir\"]);\n const outputPath = path.resolve(projectRoot, flags.output);\n const identity = await this.loadMarketplaceIdentity(projectRoot, flags.name);\n\n this.printHeader(pluginsDir, outputPath);\n\n try {\n // Read and refuse everything before the first write, so manifest and catalogue always agree.\n const marketplace = await this.scanPlugins(pluginsDir, flags[\"plugins-dir\"], identity);\n const catalog = await this.readCatalog(projectRoot);\n\n await this.writeManifest(outputPath, marketplace);\n await this.writeCatalog(outputPath, catalog);\n this.printStats(marketplace);\n this.printSample(marketplace);\n\n this.log(\"\");\n this.logSuccess(\n `Marketplace generated with ${plural(getMarketplaceStats(marketplace).total, \"plugin\")}!`,\n );\n this.log(\"\");\n } catch (error) {\n this.log(\"Generation failed\");\n this.handleError(error);\n }\n }\n\n private async loadMarketplaceIdentity(\n projectRoot: string,\n nameOverride?: string,\n ): Promise<MarketplaceIdentity> {\n const packageJsonPath = path.join(projectRoot, STANDARD_FILES.PACKAGE_JSON);\n const { name, version, description, author } = await this.readPackageJson(\n projectRoot,\n packageJsonPath,\n );\n\n if (version.trim() === \"\") {\n this.error(marketplaceHasNoVersion(packageJsonPath), { exit: EXIT_CODES.ERROR });\n }\n\n const owner = parseAuthor(author);\n if (owner.name.trim() === \"\") {\n this.error(marketplaceOwnerHasNoName(packageJsonPath), { exit: EXIT_CODES.ERROR });\n }\n\n const resolvedName = this.resolvePublishableName(name, nameOverride, packageJsonPath);\n\n const reservedError = validateMarketplaceName(resolvedName, name, RESERVED_NAME_WAY_OUT);\n if (reservedError) {\n this.error(reservedError, { exit: EXIT_CODES.ERROR });\n }\n\n return {\n name: resolvedName,\n version,\n description,\n ownerName: owner.name,\n ...(owner.email !== undefined && { ownerEmail: owner.email }),\n };\n }\n\n private async readPackageJson(\n projectRoot: string,\n packageJsonPath: string,\n ): Promise<PackageJson> {\n let rawContent: string;\n try {\n rawContent = await readFile(packageJsonPath);\n } catch {\n this.error(\n `Missing package.json at ${projectRoot}. build marketplace reads marketplace identity from package.json.`,\n { exit: EXIT_CODES.ERROR },\n );\n }\n\n let parsedJson: unknown;\n try {\n parsedJson = JSON.parse(rawContent);\n } catch (error) {\n this.error(`Failed to parse package.json at ${packageJsonPath}: ${getErrorMessage(error)}`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n const parseResult = packageJsonSchema.safeParse(parsedJson);\n if (!parseResult.success) {\n const missingFields = parseResult.error.issues.map((i) => i.path.join(\".\")).join(\", \");\n this.error(\n `package.json at ${packageJsonPath} is missing required fields: ${missingFields}. build marketplace reads marketplace identity from package.json.`,\n { exit: EXIT_CODES.ERROR },\n );\n }\n\n return parseResult.data;\n }\n\n /** A package.json name that fails gets a different refusal: its way out is `--name`. */\n private resolvePublishableName(\n packageName: string,\n nameOverride: string | undefined,\n packageJsonPath: string,\n ): string {\n if (nameOverride !== undefined) {\n const invalidOverride = validateKebabCaseName(nameOverride, MARKETPLACE_NOUN);\n if (invalidOverride) {\n this.error(`Invalid --name '${nameOverride}': ${invalidOverride}`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n return nameOverride;\n }\n\n if (validateKebabCaseName(packageName, MARKETPLACE_NOUN)) {\n this.error(marketplaceNameNotPublishable(packageName, packageJsonPath), {\n exit: EXIT_CODES.ERROR,\n });\n }\n return packageName;\n }\n\n private printHeader(pluginsDir: string, outputPath: string): void {\n this.log(\"\");\n this.log(\"Generating marketplace.json\");\n this.log(` Plugins directory: ${pluginsDir}`);\n this.log(` Output file: ${outputPath}`);\n this.log(\"\");\n }\n\n private async scanPlugins(\n pluginsDir: string,\n pluginsDirFlag: string,\n identity: MarketplaceIdentity,\n ): Promise<Marketplace> {\n this.log(\"Scanning plugins...\");\n\n const marketplace = await generateMarketplace(pluginsDir, {\n name: identity.name,\n version: identity.version,\n description: identity.description,\n ownerName: identity.ownerName,\n ...(identity.ownerEmail !== undefined && { ownerEmail: identity.ownerEmail }),\n pluginRoot: `./${pluginsDirFlag}`,\n });\n\n const stats = getMarketplaceStats(marketplace);\n this.log(`Found ${plural(stats.total, \"plugin\")}`);\n\n if (marketplace.plugins.length === 0) {\n this.error(noPluginsToPublish(pluginsDir, pluginsDirFlag), { exit: EXIT_CODES.ERROR });\n }\n\n const namespaceError = validateSkillIdNamespace(marketplace);\n if (namespaceError) {\n this.error(namespaceError, { exit: EXIT_CODES.ERROR });\n }\n\n return marketplace;\n }\n\n /** Unconditional: consumers must be able to read an absent catalogue as a broken marketplace. */\n private async readCatalog(projectRoot: string): Promise<MergedSkillsMatrix> {\n this.log(`Reading the skills for ${CATALOG_JSON}...`);\n await this.refuseAConfigDeclaringNothing(projectRoot);\n const matrix = await loadMarketplaceMatrix(projectRoot);\n return { ...matrix, generatedAt: GENERATED_AT_BUILD };\n }\n\n /** Every other reader takes such a file as absent; the build is where its author can fix it. */\n private async refuseAConfigDeclaringNothing(projectRoot: string): Promise<void> {\n const read = await readSourceRepoConfig(projectRoot);\n if (read.kind !== \"declares-nothing\") return;\n\n this.error(configUnreadableError(configLoadFailure(read.configPath, NO_VALID_DEFAULT_EXPORT)), {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n private async writeManifest(outputPath: string, marketplace: Marketplace): Promise<void> {\n this.log(`Writing ${MARKETPLACE_JSON}...`);\n await writeMarketplace(outputPath, marketplace);\n this.log(`Wrote ${outputPath}`);\n }\n\n private async writeCatalog(outputPath: string, catalog: MergedSkillsMatrix): Promise<void> {\n const catalogPath = path.join(path.dirname(outputPath), CATALOG_JSON);\n\n this.log(`Writing ${CATALOG_JSON}...`);\n await writeFile(catalogPath, `${JSON.stringify(catalog, null, 2)}\\n`);\n this.log(`Wrote ${catalogPath}`);\n }\n\n private printStats(marketplace: Marketplace): void {\n this.log(\"\");\n this.log(\"Category breakdown:\");\n const sortedCategories = sortBy(\n Object.entries(getMarketplaceStats(marketplace).byCategory),\n ([, count]) => -count,\n );\n for (const [category, count] of sortedCategories) {\n this.log(` ${category}: ${count}`);\n }\n }\n\n private printSample(marketplace: Marketplace): void {\n this.log(\"\");\n this.log(\"Sample plugins:\");\n const sampleSize = 5;\n for (const plugin of marketplace.plugins.slice(0, sampleSize)) {\n const version = plugin.version ? `v${plugin.version}` : \"\";\n const category = plugin.category ? `[${plugin.category}]` : \"\";\n this.log(` ${plugin.name} ${version} ${category}`);\n if (plugin.description) {\n this.log(` ${plugin.description}`);\n }\n }\n if (marketplace.plugins.length > sampleSize) {\n this.log(` ... and ${marketplace.plugins.length - sampleSize} more`);\n }\n }\n}\n\ntype ParsedAuthor = {\n name: string;\n email?: string;\n};\n\n/** The marketplace schema requires at least one plugin, so an empty manifest is never written. */\nfunction noPluginsToPublish(pluginsDir: string, pluginsDirFlag: string): string {\n return (\n `No plugins found in ${pluginsDir}. A marketplace with no plugins is refused when it is read ` +\n `back, so none was written. Run '${CLI_INVOKE_COMMAND} build plugins' first, or point ` +\n `--plugins-dir at the directory holding them (it is '${pluginsDirFlag}' for this run).`\n );\n}\n\n/** Accepts `\"Name <email> (url)\"` or `{ name, email, url }`; the caller refuses an empty name. */\nfunction parseAuthor(author: string | { name: string; email?: string } | undefined): ParsedAuthor {\n if (!author) return { name: \"\" };\n\n if (typeof author === \"object\") {\n return { name: author.name, ...(author.email !== undefined && { email: author.email }) };\n }\n\n const [, matchedName, matchedEmail] = author.match(AUTHOR_STRING_PATTERN) ?? [];\n if (matchedName !== undefined && matchedEmail !== undefined) {\n return { name: matchedName.trim(), email: matchedEmail.trim() };\n }\n\n warn(\n `package.json 'author' field \"${author}\" has no parseable email — marketplace owner.email will be empty`,\n );\n return { name: author.trim() };\n}\n"],"mappings":"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","names":[]}
@@ -2,11 +2,11 @@
2
2
  import {
3
3
  compileAllAgentPlugins,
4
4
  printAgentCompilationSummary
5
- } from "../../chunk-5BNX73OU.js";
6
- import "../../chunk-2YA4DDRM.js";
5
+ } from "../../chunk-NISWBQNS.js";
6
+ import "../../chunk-LUKDDHSI.js";
7
7
  import {
8
8
  BaseCommand
9
- } from "../../chunk-GEMW5RQ2.js";
9
+ } from "../../chunk-7ZOWSCAO.js";
10
10
  import {
11
11
  compileAllSkillPlugins,
12
12
  compileSkillPlugin,
@@ -15,14 +15,14 @@ import {
15
15
  readPluginManifest,
16
16
  remove,
17
17
  setVerbose
18
- } from "../../chunk-GAKVZNTX.js";
18
+ } from "../../chunk-VILFCMRN.js";
19
19
  import {
20
20
  plural
21
- } from "../../chunk-AUNRHWH4.js";
21
+ } from "../../chunk-7OG635DK.js";
22
22
  import {
23
23
  DIRS,
24
24
  PLUGINS_DIST_PATH
25
- } from "../../chunk-7C3PFRBU.js";
25
+ } from "../../chunk-MHAQWMNJ.js";
26
26
  import "../../chunk-GHHJYNAN.js";
27
27
 
28
28
  // src/cli/commands/build/plugins.ts
@@ -1,32 +1,32 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  unofferablePlacementsFound
4
- } from "../chunk-HACRR422.js";
4
+ } from "../chunk-MOL2J5HS.js";
5
5
  import {
6
6
  hostCompileNotices
7
- } from "../chunk-PSUTNOQ2.js";
7
+ } from "../chunk-255DGUCH.js";
8
8
  import {
9
9
  detectBothInstallations,
10
10
  reconcileTypesFromDisk
11
- } from "../chunk-66AEVERM.js";
11
+ } from "../chunk-6CRA46YO.js";
12
12
  import {
13
13
  compileAgents,
14
14
  discoverInstalledSkills
15
- } from "../chunk-IWY5IR4F.js";
15
+ } from "../chunk-Y23MP2OC.js";
16
16
  import {
17
17
  loadAgentDefs
18
- } from "../chunk-THO7LO5B.js";
19
- import "../chunk-5BNX73OU.js";
20
- import "../chunk-2YA4DDRM.js";
18
+ } from "../chunk-KCLBLK3F.js";
19
+ import "../chunk-NISWBQNS.js";
20
+ import "../chunk-LUKDDHSI.js";
21
21
  import {
22
22
  providerFlag,
23
23
  providerNamedBy,
24
24
  refuseAnAmbiguousInstallation
25
- } from "../chunk-OCAVW6N5.js";
25
+ } from "../chunk-MBIOZ5LW.js";
26
26
  import {
27
27
  BaseCommand,
28
28
  EXIT_CODES
29
- } from "../chunk-GEMW5RQ2.js";
29
+ } from "../chunk-7ZOWSCAO.js";
30
30
  import {
31
31
  ConfigLoadError,
32
32
  ERROR_MESSAGES,
@@ -49,15 +49,15 @@ import {
49
49
  skillMetadataUnusableDetail,
50
50
  skillMetadataUnusableError,
51
51
  verbose
52
- } from "../chunk-GAKVZNTX.js";
52
+ } from "../chunk-VILFCMRN.js";
53
53
  import {
54
54
  plural
55
- } from "../chunk-AUNRHWH4.js";
55
+ } from "../chunk-7OG635DK.js";
56
56
  import {
57
57
  STANDARD_FILES,
58
58
  effectivelyExcludedSkillIds,
59
59
  isActiveAt
60
- } from "../chunk-7C3PFRBU.js";
60
+ } from "../chunk-MHAQWMNJ.js";
61
61
  import "../chunk-GHHJYNAN.js";
62
62
 
63
63
  // src/cli/commands/compile.ts
@@ -1,28 +1,30 @@
1
1
  #!/usr/bin/env node
2
- import "../chunk-5BNX73OU.js";
2
+ import "../chunk-NISWBQNS.js";
3
3
  import {
4
4
  filterExcludedEntries,
5
5
  listAgentFilesOf,
6
6
  listAgentMdFiles,
7
7
  splitAgentsByProvenance
8
- } from "../chunk-2YA4DDRM.js";
8
+ } from "../chunk-LUKDDHSI.js";
9
9
  import {
10
10
  ambiguityFinding
11
- } from "../chunk-OCAVW6N5.js";
11
+ } from "../chunk-MBIOZ5LW.js";
12
12
  import {
13
13
  BaseCommand,
14
14
  EXIT_CODES
15
- } from "../chunk-GEMW5RQ2.js";
15
+ } from "../chunk-7ZOWSCAO.js";
16
16
  import {
17
17
  ConfigDefaultExportError,
18
18
  ConfigLoadError,
19
19
  MarketplaceManifestRequiredError,
20
20
  MarketplaceNameRefusedError,
21
21
  MarketplaceRefusedError,
22
+ MarketplaceUnreachableError,
22
23
  SOURCE_ENV_VAR,
23
24
  agentCodec,
24
25
  agentYamlGenerationSchema,
25
26
  agentsDir,
27
+ askingEachMarketplaceItself,
26
28
  configDirsInPlay,
27
29
  declaresNoContent,
28
30
  detectInstallations,
@@ -80,7 +82,6 @@ import {
80
82
  splitMetadataValidationIssues,
81
83
  stackConfigValidationSchema,
82
84
  stacksConfigSchema,
83
- typedValues,
84
85
  validResult,
85
86
  validateAgentFrontmatter,
86
87
  validateAllPlugins,
@@ -89,11 +90,12 @@ import {
89
90
  validateSkillFrontmatter,
90
91
  validateSkillMetadata,
91
92
  verbose
92
- } from "../chunk-GAKVZNTX.js";
93
+ } from "../chunk-VILFCMRN.js";
93
94
  import {
94
95
  matrix,
95
- plural
96
- } from "../chunk-AUNRHWH4.js";
96
+ plural,
97
+ typedValues
98
+ } from "../chunk-7OG635DK.js";
97
99
  import {
98
100
  CLI_INVOKE_COMMAND,
99
101
  DEFAULT_BRANDING,
@@ -108,7 +110,7 @@ import {
108
110
  STANDARD_FILES,
109
111
  UI_SYMBOLS,
110
112
  effectivelyExcludedSkillIds
111
- } from "../chunk-7C3PFRBU.js";
113
+ } from "../chunk-MHAQWMNJ.js";
112
114
  import "../chunk-GHHJYNAN.js";
113
115
 
114
116
  // src/cli/commands/doctor.ts
@@ -202,7 +204,7 @@ async function configuredSkillsAt(root, provider) {
202
204
 
203
205
  // src/cli/lib/doctor/ownership.ts
204
206
  import path3 from "path";
205
- import { groupBy } from "remeda";
207
+ import { groupBy, unique } from "remeda";
206
208
 
207
209
  // src/cli/lib/content-validator.ts
208
210
  import os2 from "os";
@@ -780,12 +782,12 @@ async function validateInstalledSkillMetadata(metadataPath) {
780
782
  // src/cli/lib/doctor/ownership.ts
781
783
  async function judgeOwnership(state, config, installation) {
782
784
  const agentFolders = agentFoldersToJudge(state, config, installation);
783
- const skillFolders = skillFoldersToJudge(state, config, installation);
784
- const [unowned, orphans] = await Promise.all([
785
- unownedIn(agentFolders, skillFolders),
786
- orphansIn(agentFolders, skillFolders)
785
+ const [skills, agents, orphanedAgentFiles] = await Promise.all([
786
+ unownedSkillDirs(state, installation),
787
+ unownedAgentFiles(agentFolders),
788
+ Promise.all(agentFolders.map(unclaimedAgentFiles))
787
789
  ]);
788
- return { unowned, orphans };
790
+ return { unowned: { skills, agents }, orphanedAgentFiles: orphanedAgentFiles.flat() };
789
791
  }
790
792
  function agentFoldersToJudge(state, config, { projectDir, hosts }) {
791
793
  return oncePerFolder(
@@ -796,13 +798,13 @@ function agentFoldersToJudge(state, config, { projectDir, hosts }) {
796
798
  }))
797
799
  );
798
800
  }
799
- function skillFoldersToJudge(state, config, { projectDir, hosts }) {
800
- return oncePerFolder(
801
- scopesToJudge(state, hosts).map((scope) => ({
802
- dir: skillsDir(hosts[scope], scope, projectDir),
803
- claimed: claimed(state, scope, config && skillIdsClaimedIn(config, scope))
804
- }))
801
+ async function unownedSkillDirs(state, { projectDir, hosts }) {
802
+ if (state.kind !== "absent") return [];
803
+ const dirs = unique(
804
+ scopesToJudge(state, hosts).map((scope) => skillsDir(hosts[scope], scope, projectDir))
805
805
  );
806
+ const listed = await Promise.all(dirs.map(skillDirsWithOurProvenanceIn));
807
+ return listed.flat();
806
808
  }
807
809
  function scopesToJudge(state, hosts) {
808
810
  const ownConfig = state.kind !== "absent" && !inherits(state);
@@ -819,9 +821,6 @@ function claimed(state, scope, names) {
819
821
  function agentNamesClaimedIn(config, scope) {
820
822
  return config.agents.filter((agent) => claimsAt(agent, scope)).map((agent) => agent.name);
821
823
  }
822
- function skillIdsClaimedIn(config, scope) {
823
- return config.skills.filter((skill) => claimsAt(skill, scope)).map((skill) => skill.id);
824
- }
825
824
  function claimsAt(entry, scope) {
826
825
  return entry.scope === scope && (scope === "global" || !entry.excluded);
827
826
  }
@@ -835,31 +834,11 @@ function joinClaims(into, from) {
835
834
  if (from.claimed === null) return into;
836
835
  return { ...into, claimed: /* @__PURE__ */ new Set([...into.claimed, ...from.claimed]) };
837
836
  }
838
- async function unownedIn(agentFolders, skillFolders) {
839
- const [skills, agents] = await Promise.all([
840
- Promise.all(
841
- skillFolders.filter(isUnclaimed).map(({ dir }) => skillDirsWithOurProvenanceIn(dir))
842
- ),
843
- Promise.all(
844
- agentFolders.filter(isUnclaimed).map(({ dir, codec }) => agentFilesWithOurProvenanceIn(dir, codec))
845
- )
846
- ]);
847
- return { skills: skills.flat(), agents: agents.flat() };
848
- }
849
- async function orphansIn(agentFolders, skillFolders) {
850
- const [skills, agents] = await Promise.all([
851
- Promise.all(skillFolders.map(unclaimedSkillDirs)),
852
- Promise.all(agentFolders.map(unclaimedAgentFiles))
853
- ]);
854
- return { skills: skills.flat(), agents: agents.flat() };
855
- }
856
- function isUnclaimed(folder) {
857
- return folder.claimed === null;
858
- }
859
- async function unclaimedSkillDirs({ dir, claimed: claimed2 }) {
860
- if (claimed2 === null) return [];
861
- const ours = await listSkillDirsWithOurProvenance(dir);
862
- return ours.filter((name) => !claimed2.has(name));
837
+ async function unownedAgentFiles(agentFolders) {
838
+ const listed = await Promise.all(
839
+ agentFolders.filter((folder) => folder.claimed === null).map(({ dir, codec }) => agentFilesWithOurProvenanceIn(dir, codec))
840
+ );
841
+ return listed.flat();
863
842
  }
864
843
  async function unclaimedAgentFiles({ dir, codec, claimed: claimed2 }) {
865
844
  if (claimed2 === null || !await directoryExists(dir)) return [];
@@ -868,7 +847,7 @@ async function unclaimedAgentFiles({ dir, codec, claimed: claimed2 }) {
868
847
  }
869
848
 
870
849
  // src/cli/commands/doctor.ts
871
- import { countBy, unique } from "remeda";
850
+ import { countBy, unique as unique2 } from "remeda";
872
851
  function checkConfigValid(state, installation) {
873
852
  const theConfig = (verdict) => configRowMessage(state, installation, verdict);
874
853
  if (state.kind === "absent") {
@@ -985,7 +964,7 @@ function checkSkillsResolved(config, matrix2) {
985
964
  function skillIdsToResolve(config) {
986
965
  const excludedIds = effectivelyExcludedSkillIds(config.skills);
987
966
  const stackIds = config.stack ? getStackSkillIds(config.stack) : [];
988
- return unique([...stackIds, ...config.skills.map((s) => s.id)]).filter(
967
+ return unique2([...stackIds, ...config.skills.map((s) => s.id)]).filter(
989
968
  (id) => !excludedIds.has(id)
990
969
  );
991
970
  }
@@ -1003,7 +982,7 @@ async function checkAgentsCompiled(config, installation) {
1003
982
  const unrenderable = agentChecks.filter((c) => c.state === "unrenderable");
1004
983
  const missingAgents = agentChecks.filter((c) => c.state === "missing").map((c) => c.name);
1005
984
  if (unrenderable.length === config.agents.length) {
1006
- const hostsLeavingThemOut = unique(unrenderable.map((a) => a.provider)).join(" or ");
985
+ const hostsLeavingThemOut = unique2(unrenderable.map((a) => a.provider)).join(" or ");
1007
986
  return {
1008
987
  kind: "agents",
1009
988
  status: "pass",
@@ -1041,33 +1020,30 @@ async function agentCompileCheck(agent, { projectDir, hosts }) {
1041
1020
  async function checkNoOrphans(state, config, installation) {
1042
1021
  return ownershipResult(state, await judgeOwnership(state, config, installation));
1043
1022
  }
1044
- function ownershipResult(state, { unowned, orphans }) {
1023
+ function ownershipResult(state, { unowned, orphanedAgentFiles }) {
1045
1024
  if (unowned.skills.length > 0 || unowned.agents.length > 0) {
1046
1025
  return {
1047
1026
  kind: "orphans-unowned",
1048
1027
  status: "fail",
1049
1028
  message: `${countedArtifacts(unowned.skills, unowned.agents)} installed here, and no configuration declares them`,
1050
- details: [...unowned.skills, ...unowned.agents, ...orphanLines(orphans)].map(
1029
+ details: [...unowned.skills, ...unowned.agents, ...orphanLines(orphanedAgentFiles)].map(
1051
1030
  (line) => `- ${line}`
1052
1031
  )
1053
1032
  };
1054
1033
  }
1055
- if (orphans.skills.length > 0 || orphans.agents.length > 0) {
1034
+ if (orphanedAgentFiles.length > 0) {
1056
1035
  return {
1057
1036
  kind: "orphans",
1058
1037
  status: "warn",
1059
- message: countedOrphans(orphans),
1060
- details: orphanLines(orphans).map((line) => `- ${line}`)
1038
+ message: plural(orphanedAgentFiles.length, "orphaned agent file"),
1039
+ details: orphanLines(orphanedAgentFiles).map((line) => `- ${line}`)
1061
1040
  };
1062
1041
  }
1063
1042
  if (state.kind === "absent") return skippedResult("orphans");
1064
- return { kind: "orphans", status: "pass", message: "No orphaned skills or agent files" };
1065
- }
1066
- function orphanLines({ skills, agents }) {
1067
- return [...skills, ...agents].map((name) => `${name} (not in config)`);
1043
+ return { kind: "orphans", status: "pass", message: "No orphaned agent files" };
1068
1044
  }
1069
- function countedOrphans({ skills, agents }) {
1070
- return nonZeroCounts([skills.length, "orphaned skill"], [agents.length, "orphaned agent file"]);
1045
+ function orphanLines(fileNames) {
1046
+ return fileNames.map((name) => `${name} (not in config)`);
1071
1047
  }
1072
1048
  function ratio(found, total, noun) {
1073
1049
  return `${found}/${plural(total, noun)}`;
@@ -1124,7 +1100,7 @@ async function checkPluginSkillsInstalled(config, installation) {
1124
1100
  message: "No plugin-mode skills configured"
1125
1101
  };
1126
1102
  }
1127
- const scopes = unique(pluginSkills.map((s) => s.scope));
1103
+ const scopes = unique2(pluginSkills.map((s) => s.scope));
1128
1104
  const missingPerScope = await Promise.all(
1129
1105
  scopes.map((scope) => pluginSkillsMissingAt(scope, pluginSkills, installation))
1130
1106
  );
@@ -1158,25 +1134,18 @@ var MARKETPLACE_CHOSEN_BY = {
1158
1134
  default: "nothing here names one, so this is the default"
1159
1135
  };
1160
1136
  function howItWasReached(source, isLocal) {
1161
- return isLocal ? `Read ${source} from disk` : `Fetched ${source} over the network`;
1137
+ return isLocal ? `Read ${source} from disk` : `Reached ${source} over the network`;
1162
1138
  }
1163
1139
  function reachedMarketplace(result) {
1164
1140
  const { source, sourceOrigin } = result.sourceConfig;
1165
- const available = `${plural(result.marketplaceSkillIds.size, "skill")} available`;
1166
- const chosenBy = MARKETPLACE_CHOSEN_BY[sourceOrigin];
1167
- if (result.unreachable) {
1168
- return {
1169
- kind: "source",
1170
- status: "warn",
1171
- message: `Could not reach ${source} \u2014 read its cached copy instead`,
1172
- details: [available, `The copy at ${result.sourcePath} may be out of date \u2014 ${chosenBy}`]
1173
- };
1174
- }
1175
1141
  return {
1176
1142
  kind: "source",
1177
1143
  status: "pass",
1178
1144
  message: `Connected to ${result.isLocal ? "local" : "remote"}: ${result.sourcePath}`,
1179
- details: [available, `${howItWasReached(source, result.isLocal)} \u2014 ${chosenBy}`]
1145
+ details: [
1146
+ `${plural(result.marketplaceSkillIds.size, "skill")} available`,
1147
+ `${howItWasReached(source, result.isLocal)} \u2014 ${MARKETPLACE_CHOSEN_BY[sourceOrigin]}`
1148
+ ]
1180
1149
  };
1181
1150
  }
1182
1151
  async function checkSourceReachable({
@@ -1185,16 +1154,30 @@ async function checkSourceReachable({
1185
1154
  }) {
1186
1155
  try {
1187
1156
  return reachedMarketplace(
1188
- await loadSkillsMatrixFromSource({ projectDir, provider: hosts.project })
1157
+ await askingEachMarketplaceItself(
1158
+ () => loadSkillsMatrixFromSource({ projectDir, provider: hosts.project })
1159
+ )
1189
1160
  );
1190
1161
  } catch (error) {
1162
+ return marketplaceNotLoaded(error);
1163
+ }
1164
+ }
1165
+ var NO_SAVED_COPY_READ = "Doctor asks the marketplace itself, not the saved copy, which other commands still read offline";
1166
+ function marketplaceNotLoaded(error) {
1167
+ if (error instanceof MarketplaceUnreachableError) {
1191
1168
  return {
1192
1169
  kind: "source",
1193
1170
  status: "fail",
1194
- message: refusedOr(error, "Failed to load marketplace"),
1195
- details: [getErrorMessage(error)]
1171
+ message: `Could not reach ${error.source}`,
1172
+ details: [error.reason, NO_SAVED_COPY_READ]
1196
1173
  };
1197
1174
  }
1175
+ return {
1176
+ kind: "source",
1177
+ status: "fail",
1178
+ message: refusedOr(error, "Failed to load marketplace"),
1179
+ details: [getErrorMessage(error)]
1180
+ };
1198
1181
  }
1199
1182
  var CONFIG_CHECK = {
1200
1183
  kind: "content-config",
@@ -1354,7 +1337,7 @@ function commandActingOn(provider, command) {
1354
1337
  return `${CLI_INVOKE_COMMAND} ${command}${providerArgument(provider)}`;
1355
1338
  }
1356
1339
  function formatTips(results) {
1357
- return unique(TIPS.flatMap((tip) => linesOf(tip, results)));
1340
+ return unique2(TIPS.flatMap((tip) => linesOf(tip, results)));
1358
1341
  }
1359
1342
  function linesOf(tip, results) {
1360
1343
  return results.filter((result) => answers(tip, result)).map((result) => tip.line(result.provider));
@@ -1374,7 +1357,7 @@ async function checkInstallationsInPlay(projectDir, providers) {
1374
1357
  const finding = await ambiguityFinding(projectDir);
1375
1358
  return {
1376
1359
  kind: "installations",
1377
- status: "fail",
1360
+ status: "pass",
1378
1361
  message: `${providers.length} installations here, each checked below`,
1379
1362
  details: finding === null ? [] : [`- ${finding}`]
1380
1363
  };