agents-inc 0.174.0 → 0.175.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 (82) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/dist/{chunk-IAQFZFWD.js → chunk-37QFHJUW.js} +142 -13
  3. package/dist/chunk-37QFHJUW.js.map +1 -0
  4. package/dist/{chunk-H5E6IO2L.js → chunk-6HJVH27C.js} +9 -11
  5. package/dist/chunk-6HJVH27C.js.map +1 -0
  6. package/dist/{chunk-7BHDKEGK.js → chunk-DQB3E2SX.js} +3 -3
  7. package/dist/{chunk-APWMMZOK.js → chunk-EGC7PNDI.js} +31 -24
  8. package/dist/chunk-EGC7PNDI.js.map +1 -0
  9. package/dist/{chunk-6PGXTLA4.js → chunk-EHEBN4NB.js} +2 -2
  10. package/dist/{chunk-EFXVYQGT.js → chunk-GNMRXXRY.js} +39 -40
  11. package/dist/chunk-GNMRXXRY.js.map +1 -0
  12. package/dist/{chunk-FQF6VHO3.js → chunk-ICHWAFAC.js} +3 -3
  13. package/dist/{chunk-FQF6VHO3.js.map → chunk-ICHWAFAC.js.map} +1 -1
  14. package/dist/{chunk-3PJZ4QNJ.js → chunk-MFCZARV2.js} +9 -9
  15. package/dist/chunk-MFCZARV2.js.map +1 -0
  16. package/dist/{chunk-TVEDNGVP.js → chunk-P5XEK7HC.js} +2 -2
  17. package/dist/{chunk-REHVGFJE.js → chunk-Q4NWATGH.js} +31 -27
  18. package/dist/chunk-Q4NWATGH.js.map +1 -0
  19. package/dist/{chunk-IXVGBUWI.js → chunk-SI2LLEIR.js} +5 -5
  20. package/dist/{chunk-R7GKQBZJ.js → chunk-SNXEYAFP.js} +44 -30
  21. package/dist/chunk-SNXEYAFP.js.map +1 -0
  22. package/dist/{chunk-QCX66KBM.js → chunk-SRII2GMF.js} +3 -3
  23. package/dist/{chunk-AIBVAYHS.js → chunk-TG3SPPZY.js} +2 -2
  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-I3WF6L43.js → chunk-XYBHH3M5.js} +2 -2
  27. package/dist/{chunk-ECPFYHDX.js → chunk-YLFKFVQP.js} +11 -11
  28. package/dist/chunk-YLFKFVQP.js.map +1 -0
  29. package/dist/{chunk-E45IT3HC.js → chunk-YM3VEDAP.js} +585 -307
  30. package/dist/chunk-YM3VEDAP.js.map +1 -0
  31. package/dist/commands/build/marketplace.js +4 -4
  32. package/dist/commands/build/plugins.js +6 -6
  33. package/dist/commands/compile.js +16 -16
  34. package/dist/commands/compile.js.map +1 -1
  35. package/dist/commands/doctor.js +73 -78
  36. package/dist/commands/doctor.js.map +1 -1
  37. package/dist/commands/edit.js +45 -38
  38. package/dist/commands/edit.js.map +1 -1
  39. package/dist/commands/eject.js +27 -18
  40. package/dist/commands/eject.js.map +1 -1
  41. package/dist/commands/init.js +16 -17
  42. package/dist/commands/list.js +7 -8
  43. package/dist/commands/list.js.map +1 -1
  44. package/dist/commands/new/marketplace.js +4 -4
  45. package/dist/commands/search.js +9 -9
  46. package/dist/commands/share.js +13 -13
  47. package/dist/commands/share.js.map +1 -1
  48. package/dist/commands/uninstall.js +16 -15
  49. package/dist/commands/uninstall.js.map +1 -1
  50. package/dist/commands/update.js +17 -18
  51. package/dist/commands/update.js.map +1 -1
  52. package/dist/components/common/select-list.js +2 -2
  53. package/dist/components/common/skill-agent-summary.js +3 -3
  54. package/dist/components/common/summary-panel.js +4 -4
  55. package/dist/hooks/init.js +23 -25
  56. package/dist/hooks/init.js.map +1 -1
  57. package/dist/load-agent-defs-BJ4KBKBA.js +14 -0
  58. package/dist/{recompile-project-agents-KYK44C24.js → recompile-project-agents-2QTFMYDC.js} +8 -8
  59. package/dist/{source-loader-G5I4RNUP.js → source-loader-I6SWWDUF.js} +4 -4
  60. package/package.json +1 -1
  61. package/dist/chunk-3PJZ4QNJ.js.map +0 -1
  62. package/dist/chunk-APWMMZOK.js.map +0 -1
  63. package/dist/chunk-E45IT3HC.js.map +0 -1
  64. package/dist/chunk-ECPFYHDX.js.map +0 -1
  65. package/dist/chunk-EFXVYQGT.js.map +0 -1
  66. package/dist/chunk-H5E6IO2L.js.map +0 -1
  67. package/dist/chunk-IAQFZFWD.js.map +0 -1
  68. package/dist/chunk-ORO2T4K2.js +0 -96
  69. package/dist/chunk-ORO2T4K2.js.map +0 -1
  70. package/dist/chunk-R7GKQBZJ.js.map +0 -1
  71. package/dist/chunk-REHVGFJE.js.map +0 -1
  72. package/dist/load-agent-defs-5U5KAURA.js +0 -14
  73. /package/dist/{chunk-7BHDKEGK.js.map → chunk-DQB3E2SX.js.map} +0 -0
  74. /package/dist/{chunk-6PGXTLA4.js.map → chunk-EHEBN4NB.js.map} +0 -0
  75. /package/dist/{chunk-TVEDNGVP.js.map → chunk-P5XEK7HC.js.map} +0 -0
  76. /package/dist/{chunk-IXVGBUWI.js.map → chunk-SI2LLEIR.js.map} +0 -0
  77. /package/dist/{chunk-QCX66KBM.js.map → chunk-SRII2GMF.js.map} +0 -0
  78. /package/dist/{chunk-AIBVAYHS.js.map → chunk-TG3SPPZY.js.map} +0 -0
  79. /package/dist/{chunk-I3WF6L43.js.map → chunk-XYBHH3M5.js.map} +0 -0
  80. /package/dist/{load-agent-defs-5U5KAURA.js.map → load-agent-defs-BJ4KBKBA.js.map} +0 -0
  81. /package/dist/{recompile-project-agents-KYK44C24.js.map → recompile-project-agents-2QTFMYDC.js.map} +0 -0
  82. /package/dist/{source-loader-G5I4RNUP.js.map → source-loader-I6SWWDUF.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/commands/eject.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport os from \"os\";\nimport { BaseCommand } from \"../base-command.js\";\nimport {\n copy,\n ensureDir,\n directoryExists,\n fileExists,\n isSymlink,\n listDirectories,\n} from \"../utils/fs.js\";\nimport { DIRS, PROJECT_ROOT } from \"../consts.js\";\nimport {\n providerInUse,\n relativeConfigPath,\n sourceFolderInUse,\n} from \"../lib/installation/install-layout.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { type SourceLoadResult } from \"../lib/loading/index.js\";\nimport { loadSource } from \"../lib/operations/index.js\";\nimport { matrix } from \"../lib/matrix/matrix-provider\";\nimport { resolveSource, getProjectConfigPath } from \"../lib/configuration/index.js\";\nimport {\n ensureBlankPair,\n lazyGateDeps,\n mutateGlobal,\n writeProjectPartial,\n} from \"../lib/config-gate/index.js\";\nimport { isHomeDirectory, resolveInstallPaths } from \"../lib/installation/index.js\";\nimport {\n providerFlag,\n providerNamedBy,\n refuseAnAmbiguousInstallation,\n} from \"../lib/installation/provider-flag.js\";\nimport { copySkillsToLocalFlattened, type CopiedSkill } from \"../lib/skills/index.js\";\nimport { INCOMPLETE_WORK_RECOVERY, INFO_MESSAGES } from \"../utils/messages.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { bytewise, plural } from \"../utils/string.js\";\nimport type { MergedSkillsMatrix } from \"../types/index.js\";\n\nconst EJECT_TYPES = [\"agent-partials\", \"templates\", \"skills\", \"all\"] as const;\ntype EjectType = (typeof EJECT_TYPES)[number];\n\nfunction isEjectType(value: string): value is EjectType {\n return (EJECT_TYPES as readonly string[]).includes(value);\n}\n\n/** Skills come from the marketplace this installation reads, so only their ejects load it. */\ntype EjectPlan =\n | { type: \"agent-partials\" | \"templates\" }\n | { type: \"skills\" | \"all\"; sourceResult: SourceLoadResult };\n\nfunction loadedSourceOf(plan: EjectPlan): SourceLoadResult | undefined {\n return \"sourceResult\" in plan ? plan.sourceResult : undefined;\n}\n\nexport default class Eject extends BaseCommand {\n static summary = \"Eject skills, agent partials, or templates for local customization\";\n static description =\n \"Copy agent partials, templates, or skills to your project for customization. \" +\n \"Agent partials and templates are always copied from the CLI. \" +\n \"Skills are copied from the marketplace this installation is configured to read \" +\n \"(the public one by default).\";\n\n static examples = [\n {\n description: \"Eject agent partials for customization\",\n command: \"<%= config.bin %> <%= command.id %> agent-partials\",\n },\n {\n description: \"Eject only agent templates\",\n command: \"<%= config.bin %> <%= command.id %> templates\",\n },\n {\n description: \"Eject skills to local directory\",\n command: \"<%= config.bin %> <%= command.id %> skills\",\n },\n {\n description: \"Eject everything with force overwrite\",\n command: \"<%= config.bin %> <%= command.id %> all --force\",\n },\n {\n description: \"Eject to a custom output directory\",\n command: \"<%= config.bin %> <%= command.id %> skills -o ./custom-dir\",\n },\n ];\n\n static args = {\n type: Args.string({\n description: \"What to eject: agent-partials, templates, skills, all\",\n required: false,\n options: [...EJECT_TYPES],\n }),\n };\n\n static flags = {\n provider: providerFlag(),\n force: Flags.boolean({\n char: \"f\",\n description: \"Overwrite existing files\",\n default: false,\n }),\n output: Flags.string({\n char: \"o\",\n // No default: each eject type has its own destination and this replaces all three.\n description:\n \"Write everything into this directory instead of each eject type's own destination\",\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Eject);\n const projectDir = process.cwd();\n\n // Before the layout settle: this decides which installation that refusal is about.\n await refuseAnAmbiguousInstallation(\n projectDir,\n \"eject\",\n providerNamedBy(flags.provider),\n (message) => this.error(message, { exit: EXIT_CODES.INVALID_ARGS }),\n );\n\n // Before anything is copied, so a refusal never follows files already written.\n await this.ensureConfigReadable(projectDir);\n const ejectType = this.validateEjectType(args.type);\n const outputBase = await this.resolveOutputBase(flags, projectDir);\n\n this.printHeader(\n await this.resolveBrandingName(projectDir),\n flags.output ? outputBase : undefined,\n );\n\n const plan = await this.planEject(ejectType, projectDir);\n await this.executeEject(plan, outputBase, flags, projectDir);\n await this.ensureConfig(projectDir, loadedSourceOf(plan));\n\n this.reportEnding();\n }\n\n /** Withholds `Eject complete!` when part of the eject did not land. */\n private reportEnding(): void {\n this.log(\"\");\n if (!this.hasIncompleteWork) this.logSuccess(\"Eject complete!\");\n this.log(\"\");\n\n this.exitIfWorkIncomplete();\n }\n\n private validateEjectType(typeArg: string | undefined): EjectType {\n if (!typeArg) {\n this.error(\"Please specify what to eject: agent-partials, templates, skills, or all\", {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n\n if (!isEjectType(typeArg)) {\n this.error(`Unknown eject type: ${typeArg}`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n\n return typeArg;\n }\n\n private async resolveOutputBase(\n flags: { output: string | undefined },\n projectDir: string,\n ): Promise<string> {\n if (!flags.output) return sourceFolderInUse(projectDir, providerInUse(projectDir)).dir;\n\n const outputBase = path.resolve(projectDir, expandHome(flags.output));\n await this.refuseUnwritableOutput(outputBase);\n return outputBase;\n }\n\n private async refuseUnwritableOutput(outputBase: string): Promise<void> {\n // First, as the checks below follow a link, and so would every write.\n if (await isSymlink(outputBase)) {\n this.error(`Output path is a link: ${outputBase}. Name the folder it points to instead.`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n\n // `fileExists` is true of a directory too; an existing directory is written into, and each\n // kind then skips what it would write there already unless --force.\n const namesAFile = (await fileExists(outputBase)) && !(await directoryExists(outputBase));\n if (namesAFile) {\n this.error(`Output path exists as a file: ${outputBase}`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n }\n\n private printHeader(brandingName: string, outputBase?: string): void {\n this.log(\"\");\n this.log(`${brandingName} Eject`);\n this.log(\"\");\n\n if (outputBase) {\n this.log(`Output directory: ${outputBase}`);\n }\n }\n\n private async planEject(type: EjectType, projectDir: string): Promise<EjectPlan> {\n if (type === \"agent-partials\" || type === \"templates\") return { type };\n\n const { sourceResult } = await loadSource({ projectDir });\n return { type, sourceResult };\n }\n\n private async executeEject(\n plan: EjectPlan,\n outputBase: string,\n flags: { force: boolean; output: string | undefined },\n projectDir: string,\n ): Promise<void> {\n const directOutput = !!flags.output;\n\n switch (plan.type) {\n case \"agent-partials\":\n await this.handleAgentPartials(outputBase, flags.force, directOutput, false);\n break;\n case \"templates\":\n await this.handleAgentPartials(outputBase, flags.force, directOutput, true);\n break;\n case \"skills\":\n await this.handleSkills(\n skillsDestination(projectDir, directOutput, outputBase),\n flags.force,\n plan.sourceResult,\n );\n break;\n case \"all\": {\n // The partials carry the templates as one unit, so they arrive once and obey --force.\n await this.handleAgentPartials(outputBase, flags.force, directOutput, false);\n await this.handleSkills(\n skillsDestination(projectDir, directOutput, outputBase),\n flags.force,\n plan.sourceResult,\n );\n break;\n }\n default: {\n const _exhaustive: never = plan;\n return _exhaustive;\n }\n }\n }\n\n /**\n * Writes a minimal config so `compile` works afterwards. A refusal is reported as incomplete\n * work rather than thrown, because the ejection has already landed.\n */\n private async ensureConfig(\n projectDir: string,\n sourceResult: SourceLoadResult | undefined,\n ): Promise<void> {\n // Named before the write, which may create the provider folder.\n const configTsRel = relativeConfigPath(projectDir, providerInUse(projectDir));\n\n try {\n const configResult = await ensureMinimalConfig({\n projectDir,\n ...(sourceResult !== undefined && { sourceResult }),\n });\n if (configResult.created) {\n this.logSuccess(`Created ${configTsRel}`);\n }\n } catch (error) {\n this.reportIncompleteWork(\n `Could not create ${configTsRel}: ${getErrorMessage(error)}`,\n INCOMPLETE_WORK_RECOVERY.INSPECT_INSTALLATION,\n );\n }\n }\n\n private async handleAgentPartials(\n outputBase: string,\n force: boolean,\n directOutput: boolean,\n templatesOnly: boolean,\n ): Promise<void> {\n const result = await ejectAgentPartials({\n outputBase,\n force,\n directOutput,\n templatesOnly,\n });\n\n if (result.skipped) {\n this.warn(result.skipReason);\n return;\n }\n\n if (result.skippedSubAgents.length > 0) {\n this.warn(subAgentsAlreadyThere(result.destDir, result.skippedSubAgents));\n }\n\n if (result.templatesSkipped) {\n this.warn(\n \"Agent templates already exist — skipping templates, only ejecting agent partials.\",\n );\n }\n\n this.logSuccess(\n `${templatesOnly ? \"Agent templates\" : \"Agent partials\"} ejected to ${result.destDir}`,\n );\n this.log(\n templatesOnly\n ? \"You can now customize agent templates locally.\"\n : INFO_MESSAGES.AGENT_PARTIALS_CUSTOMIZABLE,\n );\n }\n\n private async handleSkills(\n destinationDir: string,\n force: boolean,\n sourceResult: SourceLoadResult,\n ): Promise<void> {\n const result = await ejectSkills({ destinationDir, force, sourceResult, matrix });\n\n if (result.skipped) {\n this.warn(result.skipReason);\n return;\n }\n\n if (result.skippedSkillCount > 0) {\n this.warn(skillsAlreadyThere(destinationDir, result.skippedSkillCount));\n }\n\n this.logSuccess(\n `${plural(result.copiedSkills.length, \"skill\")} ejected to ${destinationDir} from ${result.sourceLabel}`,\n );\n this.log(\"You can now customize skill content locally.\");\n }\n}\n\nfunction expandHome(outputPath: string): string {\n return outputPath.startsWith(\"~\") ? path.join(os.homedir(), outputPath.slice(1)) : outputPath;\n}\n\n/** Some of what an eject copies was already there: named, with the rest copied beside it. */\nfunction subAgentsAlreadyThere(destDir: string, subAgents: readonly string[]): string {\n return `Agent partials already exist at ${destDir} — skipped ${plural(subAgents.length, \"sub-agent\")}: ${subAgents.join(\", \")}. Use --force to overwrite them.`;\n}\n\n/** Counted rather than named: a re-run into a nearly full folder skips most of the marketplace. */\nfunction skillsAlreadyThere(destinationDir: string, skippedCount: number): string {\n return `Skills already exist at ${destinationDir} — skipped ${plural(skippedCount, \"skill\")}. Use --force to overwrite them.`;\n}\n\n/** Those of `names` already at `dir`, file or folder: what an eject without --force leaves. */\nasync function alreadyIn<Name extends string>(\n dir: string,\n names: readonly Name[],\n): Promise<Name[]> {\n const checked = await Promise.all(\n names.map(async (name) => ({ name, there: await fileExists(path.join(dir, name)) })),\n );\n return checked.filter(({ there }) => there).map(({ name }) => name);\n}\n\ntype EjectAgentPartialsOptions = {\n outputBase: string;\n force: boolean;\n directOutput?: boolean;\n templatesOnly?: boolean;\n};\n\ntype EjectAgentPartialsResult =\n | {\n skipped: true;\n skipReason: string;\n }\n | {\n skipped: false;\n destDir: string;\n /** The sub-agents left as they were, by name, bytewise-sorted. */\n skippedSubAgents: string[];\n templatesSkipped: boolean;\n };\n\nfunction resolveEjectDestDir(\n outputBase: string,\n directOutput: boolean,\n templatesOnly: boolean,\n): string {\n if (directOutput) return outputBase;\n const agentsDir = path.join(outputBase, path.basename(DIRS.agents));\n return templatesOnly ? path.join(agentsDir, path.basename(DIRS.templates)) : agentsDir;\n}\n\nasync function ejectAgentPartials(\n options: EjectAgentPartialsOptions,\n): Promise<EjectAgentPartialsResult> {\n const { outputBase, force, directOutput = false, templatesOnly = false } = options;\n const destDir = resolveEjectDestDir(outputBase, directOutput, templatesOnly);\n\n return templatesOnly ? ejectTemplates(destDir, force) : ejectSubAgentPartials(destDir, force);\n}\n\n/** Whole or not at all: a templates folder already there is kept unless --force. */\nasync function ejectTemplates(destDir: string, force: boolean): Promise<EjectAgentPartialsResult> {\n const sourceDir = path.join(PROJECT_ROOT, DIRS.templates);\n\n if (!(await directoryExists(sourceDir))) {\n return { skipped: true, skipReason: \"No agent templates found in CLI.\" };\n }\n\n if ((await directoryExists(destDir)) && !force) {\n return {\n skipped: true,\n skipReason: `Agent templates already exist at ${destDir}. Use --force to overwrite.`,\n };\n }\n\n await ensureDir(destDir);\n await copy(sourceDir, destDir);\n return { skipped: false, destDir, skippedSubAgents: [], templatesSkipped: false };\n}\n\n/** Unit by unit: one already there is kept unless --force, and the rest are copied beside it. */\nasync function ejectSubAgentPartials(\n destDir: string,\n force: boolean,\n): Promise<EjectAgentPartialsResult> {\n const sourceDir = path.join(PROJECT_ROOT, DIRS.agents);\n\n if (!(await directoryExists(sourceDir))) {\n return { skipped: true, skipReason: \"No agent partials found in CLI.\" };\n }\n\n const units = await partialUnitsIn(sourceDir);\n const present = force ? [] : await alreadyIn(destDir, units);\n const absent = units.filter((unit) => !present.includes(unit));\n\n if (absent.length === 0) {\n return {\n skipped: true,\n skipReason: `Agent partials already exist at ${destDir}. Use --force to overwrite.`,\n };\n }\n\n await copyUnits(absent, sourceDir, destDir);\n\n return {\n skipped: false,\n destDir,\n skippedSubAgents: subAgentNames(present),\n templatesSkipped: present.some(isTemplatesUnit),\n };\n}\n\nconst TEMPLATES_UNIT = path.basename(DIRS.templates);\n\nfunction isTemplatesUnit(unit: string): boolean {\n return unit === TEMPLATES_UNIT;\n}\n\n/**\n * What a re-eject keeps or copies whole: each sub-agent's directory, as `<category>/<agent>`, and\n * the templates. A category folder is not one, so a file of the user's in it is written beside.\n */\nasync function partialUnitsIn(agentsSourceDir: string): Promise<string[]> {\n const entries = await listDirectories(agentsSourceDir);\n const categories = entries.filter((entry) => !isTemplatesUnit(entry));\n const subAgentDirs = await Promise.all(\n categories.map((category) => subAgentDirsOf(agentsSourceDir, category)),\n );\n return [...entries.filter(isTemplatesUnit), ...subAgentDirs.flat()];\n}\n\nasync function subAgentDirsOf(agentsSourceDir: string, category: string): Promise<string[]> {\n const agents = await listDirectories(path.join(agentsSourceDir, category));\n return agents.map((agent) => path.join(category, agent));\n}\n\n/** As the skipped-list warning names them: by directory name, bytewise-sorted. */\nfunction subAgentNames(units: readonly string[]): string[] {\n return units\n .filter((unit) => !isTemplatesUnit(unit))\n .map((unit) => path.basename(unit))\n .sort(bytewise);\n}\n\n/** `copy` makes the folders above each unit. */\nasync function copyUnits(\n units: readonly string[],\n sourceDir: string,\n destDir: string,\n): Promise<void> {\n for (const unit of units) {\n await copy(path.join(sourceDir, unit), path.join(destDir, unit));\n }\n}\n\nfunction skillsDestination(projectDir: string, directOutput: boolean, outputBase: string): string {\n return directOutput ? outputBase : installedSkillsDir(projectDir);\n}\n\ntype EjectSkillsOptions = {\n destinationDir: string;\n force: boolean;\n sourceResult: SourceLoadResult;\n matrix: MergedSkillsMatrix;\n};\n\ntype EjectSkillsResult =\n | {\n skipped: true;\n skipReason: string;\n }\n | {\n skipped: false;\n copiedSkills: CopiedSkill[];\n /** How many skills were left as they were. */\n skippedSkillCount: number;\n sourceLabel: string;\n };\n\n/**\n * Only the loaded marketplace's own non-local skills: others' skills are not on disk here. One\n * already in the destination is skipped first, as the local copy may be the one there.\n */\nasync function ejectSkills(options: EjectSkillsOptions): Promise<EjectSkillsResult> {\n const { destinationDir, force, sourceResult, matrix } = options;\n\n const marketplaceSkillIds = [...sourceResult.marketplaceSkillIds];\n const alreadyThere = force ? [] : await alreadyIn(destinationDir, marketplaceSkillIds);\n const notThere = marketplaceSkillIds.filter((skillId) => !alreadyThere.includes(skillId));\n const skillIds = notThere.filter((skillId) => !matrix.skills[skillId]?.local);\n\n if (skillIds.length === 0 && alreadyThere.length > 0) {\n return {\n skipped: true,\n skipReason: `Skills already exist at ${destinationDir}. Use --force to overwrite.`,\n };\n }\n\n if (skillIds.length === 0) {\n return { skipped: true, skipReason: \"No skills found in the marketplace to eject.\" };\n }\n\n await ensureDir(destinationDir);\n\n const copiedSkills = await copySkillsToLocalFlattened(skillIds, destinationDir, sourceResult);\n\n const sourceLabel = sourceResult.isLocal\n ? sourceResult.sourcePath\n : sourceResult.marketplace || sourceResult.sourceConfig.source;\n\n return {\n skipped: false,\n copiedSkills,\n skippedSkillCount: alreadyThere.length,\n sourceLabel,\n };\n}\n\n/** Where the host of the installation `projectDir` roots reads skills. */\nfunction installedSkillsDir(projectDir: string): string {\n const scope = isHomeDirectory(projectDir) ? \"global\" : \"project\";\n return resolveInstallPaths(projectDir, scope).skillsDir;\n}\n\ntype EnsureMinimalConfigOptions = {\n projectDir: string;\n sourceResult?: SourceLoadResult;\n};\n\ntype EnsureMinimalConfigResult = {\n configPath: string;\n created: boolean;\n};\n\nasync function ensureMinimalConfig(\n options: EnsureMinimalConfigOptions,\n): Promise<EnsureMinimalConfigResult> {\n const { projectDir, sourceResult } = options;\n\n const provider = providerInUse(projectDir);\n const tsConfigPath = getProjectConfigPath(projectDir, provider);\n\n if (await fileExists(tsConfigPath)) {\n return { configPath: tsConfigPath, created: false };\n }\n\n // ABORT on an unreadable global config: the invented file would record a marketplace from nowhere.\n const resolvedConfig =\n sourceResult?.sourceConfig ?? (await resolveSource({ caller: \"stored\", projectDir }));\n const source = resolvedConfig.source || undefined;\n\n // At home the invented config is the global manifest, which needs its config-types sibling.\n if (isHomeDirectory(projectDir)) {\n await ensureBlankPair(provider);\n if (source) await recordSourceInGlobal(projectDir, source);\n return { configPath: tsConfigPath, created: true };\n }\n\n await writeProjectPartial(\n projectDir,\n {\n skills: [],\n agents: [],\n ...(source ? { marketplace: source } : {}),\n ...(resolvedConfig.marketplace ? { marketplaceName: resolvedConfig.marketplace } : {}),\n },\n { fallbackName: path.basename(projectDir) },\n );\n\n return { configPath: tsConfigPath, created: true };\n}\n\n/** At home the config is the global manifest projects inline from, so it goes through the gate. */\nasync function recordSourceInGlobal(projectDir: string, source: string): Promise<void> {\n await mutateGlobal(\n { kind: \"set-source\", source, fallbackName: path.basename(projectDir) },\n lazyGateDeps(projectDir),\n );\n}\n"],"mappings":"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","names":["matrix"]}
1
+ {"version":3,"sources":["../../src/cli/commands/eject.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport os from \"os\";\nimport { BaseCommand } from \"../base-command.js\";\nimport {\n copy,\n ensureDir,\n directoryExists,\n fileExists,\n isSymlink,\n listDirectories,\n} from \"../utils/fs.js\";\nimport { DIRS, PROJECT_ROOT } from \"../consts.js\";\nimport {\n providerInUse,\n relativeConfigPath,\n sourceFolderInUse,\n} from \"../lib/installation/install-layout.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { type SourceLoadResult } from \"../lib/loading/index.js\";\nimport { loadSource } from \"../lib/operations/index.js\";\nimport { matrix } from \"../lib/matrix/matrix-provider\";\nimport { resolveSource, getProjectConfigPath } from \"../lib/configuration/index.js\";\nimport {\n ensureBlankPair,\n lazyGateDeps,\n mutateGlobal,\n writeProjectPartial,\n} from \"../lib/config-gate/index.js\";\nimport { isHomeDirectory, resolveInstallPaths } from \"../lib/installation/index.js\";\nimport {\n providerFlag,\n providerNamedBy,\n refuseAnAmbiguousInstallation,\n} from \"../lib/installation/provider-flag.js\";\nimport { copyMarketplaceSkillsToLocalFlattened, type CopiedSkill } from \"../lib/skills/index.js\";\nimport { INCOMPLETE_WORK_RECOVERY, INFO_MESSAGES } from \"../utils/messages.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { bytewise, plural } from \"../utils/string.js\";\nimport type { MergedSkillsMatrix, ResolvedSkill } from \"../types/index.js\";\n\nconst EJECT_TYPES = [\"agent-partials\", \"templates\", \"skills\", \"all\"] as const;\ntype EjectType = (typeof EJECT_TYPES)[number];\n\nfunction isEjectType(value: string): value is EjectType {\n return (EJECT_TYPES as readonly string[]).includes(value);\n}\n\n/** Skills come from the marketplace this installation reads, so only their ejects load it. */\ntype EjectPlan =\n | { type: \"agent-partials\" | \"templates\" }\n | { type: \"skills\" | \"all\"; sourceResult: SourceLoadResult };\n\nfunction loadedSourceOf(plan: EjectPlan): SourceLoadResult | undefined {\n return \"sourceResult\" in plan ? plan.sourceResult : undefined;\n}\n\nexport default class Eject extends BaseCommand {\n static summary = \"Eject skills, agent partials, or templates for local customization\";\n static description =\n \"Copy agent partials, templates, or skills to your project for customization. \" +\n \"Agent partials and templates are always copied from the CLI. \" +\n \"Skills are copied from the marketplace this installation is configured to read \" +\n \"(the public one by default).\";\n\n static examples = [\n {\n description: \"Eject agent partials for customization\",\n command: \"<%= config.bin %> <%= command.id %> agent-partials\",\n },\n {\n description: \"Eject only agent templates\",\n command: \"<%= config.bin %> <%= command.id %> templates\",\n },\n {\n description: \"Eject skills to local directory\",\n command: \"<%= config.bin %> <%= command.id %> skills\",\n },\n {\n description: \"Eject everything with force overwrite\",\n command: \"<%= config.bin %> <%= command.id %> all --force\",\n },\n {\n description: \"Eject to a custom output directory\",\n command: \"<%= config.bin %> <%= command.id %> skills -o ./custom-dir\",\n },\n ];\n\n static args = {\n type: Args.string({\n description: \"What to eject: agent-partials, templates, skills, all\",\n required: false,\n options: [...EJECT_TYPES],\n }),\n };\n\n static flags = {\n provider: providerFlag(),\n force: Flags.boolean({\n char: \"f\",\n description: \"Overwrite existing files\",\n default: false,\n }),\n output: Flags.string({\n char: \"o\",\n // No default: each eject type has its own destination and this replaces all three.\n description:\n \"Write everything into this directory instead of each eject type's own destination\",\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Eject);\n const projectDir = process.cwd();\n\n // Before the layout settle: this decides which installation that refusal is about.\n await refuseAnAmbiguousInstallation(\n projectDir,\n \"eject\",\n providerNamedBy(flags.provider),\n (message) => this.error(message, { exit: EXIT_CODES.INVALID_ARGS }),\n );\n\n // Before anything is copied, so a refusal never follows files already written.\n await this.ensureConfigReadable(projectDir);\n const ejectType = this.validateEjectType(args.type);\n const outputBase = await this.resolveOutputBase(flags, projectDir);\n\n this.printHeader(\n await this.resolveBrandingName(projectDir),\n flags.output ? outputBase : undefined,\n );\n\n const plan = await this.planEject(ejectType, projectDir);\n await this.executeEject(plan, outputBase, flags, projectDir);\n await this.ensureConfig(projectDir, loadedSourceOf(plan));\n\n this.reportEnding();\n }\n\n /** Withholds `Eject complete!` when part of the eject did not land. */\n private reportEnding(): void {\n this.log(\"\");\n if (!this.hasIncompleteWork) this.logSuccess(\"Eject complete!\");\n this.log(\"\");\n\n this.exitIfWorkIncomplete();\n }\n\n private validateEjectType(typeArg: string | undefined): EjectType {\n if (!typeArg) {\n this.error(\"Please specify what to eject: agent-partials, templates, skills, or all\", {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n\n if (!isEjectType(typeArg)) {\n this.error(`Unknown eject type: ${typeArg}`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n\n return typeArg;\n }\n\n private async resolveOutputBase(\n flags: { output: string | undefined },\n projectDir: string,\n ): Promise<string> {\n if (!flags.output) return sourceFolderInUse(projectDir, providerInUse(projectDir)).dir;\n\n const outputBase = path.resolve(projectDir, expandHome(flags.output));\n await this.refuseUnwritableOutput(outputBase);\n return outputBase;\n }\n\n private async refuseUnwritableOutput(outputBase: string): Promise<void> {\n // First, as the checks below follow a link, and so would every write.\n if (await isSymlink(outputBase)) {\n this.error(`Output path is a link: ${outputBase}. Name the folder it points to instead.`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n\n // `fileExists` is true of a directory too; an existing directory is written into, and each\n // kind then skips what it would write there already unless --force.\n const namesAFile = (await fileExists(outputBase)) && !(await directoryExists(outputBase));\n if (namesAFile) {\n this.error(`Output path exists as a file: ${outputBase}`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n }\n\n private printHeader(brandingName: string, outputBase?: string): void {\n this.log(\"\");\n this.log(`${brandingName} Eject`);\n this.log(\"\");\n\n if (outputBase) {\n this.log(`Output directory: ${outputBase}`);\n }\n }\n\n private async planEject(type: EjectType, projectDir: string): Promise<EjectPlan> {\n if (type === \"agent-partials\" || type === \"templates\") return { type };\n\n const { sourceResult } = await loadSource({ projectDir });\n return { type, sourceResult };\n }\n\n private async executeEject(\n plan: EjectPlan,\n outputBase: string,\n flags: { force: boolean; output: string | undefined },\n projectDir: string,\n ): Promise<void> {\n const directOutput = !!flags.output;\n\n switch (plan.type) {\n case \"agent-partials\":\n await this.handleAgentPartials(outputBase, flags.force, directOutput, false);\n break;\n case \"templates\":\n await this.handleAgentPartials(outputBase, flags.force, directOutput, true);\n break;\n case \"skills\":\n await this.handleSkills(\n skillsDestination(projectDir, directOutput, outputBase),\n flags.force,\n plan.sourceResult,\n );\n break;\n case \"all\": {\n // The partials carry the templates as one unit, so they arrive once and obey --force.\n await this.handleAgentPartials(outputBase, flags.force, directOutput, false);\n await this.handleSkills(\n skillsDestination(projectDir, directOutput, outputBase),\n flags.force,\n plan.sourceResult,\n );\n break;\n }\n default: {\n const _exhaustive: never = plan;\n return _exhaustive;\n }\n }\n }\n\n /**\n * Writes a minimal config where there is none. A refusal is reported as incomplete work rather\n * than thrown, because the ejection has already landed.\n */\n private async ensureConfig(\n projectDir: string,\n sourceResult: SourceLoadResult | undefined,\n ): Promise<void> {\n // Named before the write, which may create the provider folder.\n const configTsRel = relativeConfigPath(projectDir, providerInUse(projectDir));\n\n try {\n const configResult = await ensureMinimalConfig({\n projectDir,\n ...(sourceResult !== undefined && { sourceResult }),\n });\n if (configResult.created) {\n this.logSuccess(`Created ${configTsRel}`);\n }\n } catch (error) {\n this.reportIncompleteWork(\n `Could not create ${configTsRel}: ${getErrorMessage(error)}`,\n INCOMPLETE_WORK_RECOVERY.INSPECT_INSTALLATION,\n );\n }\n }\n\n private async handleAgentPartials(\n outputBase: string,\n force: boolean,\n directOutput: boolean,\n templatesOnly: boolean,\n ): Promise<void> {\n const result = await ejectAgentPartials({\n outputBase,\n force,\n directOutput,\n templatesOnly,\n });\n\n if (result.skipped) {\n this.warn(result.skipReason);\n return;\n }\n\n if (result.skippedSubAgents.length > 0) {\n this.warn(subAgentsAlreadyThere(result.destDir, result.skippedSubAgents));\n }\n\n if (result.templatesSkipped) {\n this.warn(\n \"Agent templates already exist — skipping templates, only ejecting agent partials.\",\n );\n }\n\n this.logSuccess(\n `${templatesOnly ? \"Agent templates\" : \"Agent partials\"} ejected to ${result.destDir}`,\n );\n this.log(\n templatesOnly\n ? \"You can now customize agent templates locally.\"\n : INFO_MESSAGES.AGENT_PARTIALS_CUSTOMIZABLE,\n );\n }\n\n private async handleSkills(\n destinationDir: string,\n force: boolean,\n sourceResult: SourceLoadResult,\n ): Promise<void> {\n const result = await ejectSkills({ destinationDir, force, sourceResult, matrix });\n\n if (result.skipped) {\n this.warn(result.skipReason);\n return;\n }\n\n if (result.skippedSkillCount > 0) {\n this.warn(skillsAlreadyThere(destinationDir, result.skippedSkillCount));\n }\n\n this.logSuccess(\n `${plural(result.copiedSkills.length, \"skill\")} ejected to ${destinationDir} from ${result.sourceLabel}`,\n );\n this.log(\"You can now customize skill content locally.\");\n }\n}\n\nfunction expandHome(outputPath: string): string {\n return outputPath.startsWith(\"~\") ? path.join(os.homedir(), outputPath.slice(1)) : outputPath;\n}\n\n/** Some of what an eject copies was already there: named, with the rest copied beside it. */\nfunction subAgentsAlreadyThere(destDir: string, subAgents: readonly string[]): string {\n return `Agent partials already exist at ${destDir} — skipped ${plural(subAgents.length, \"sub-agent\")}: ${subAgents.join(\", \")}. Use --force to overwrite them.`;\n}\n\n/** Counted rather than named: a re-run into a nearly full folder skips most of the marketplace. */\nfunction skillsAlreadyThere(destinationDir: string, skippedCount: number): string {\n return `Skills already exist at ${destinationDir} — skipped ${plural(skippedCount, \"skill\")}. Use --force to overwrite them.`;\n}\n\n/** Those of `names` already at `dir`, file or folder: what an eject without --force leaves. */\nasync function alreadyIn<Name extends string>(\n dir: string,\n names: readonly Name[],\n): Promise<Name[]> {\n const checked = await Promise.all(\n names.map(async (name) => ({ name, there: await fileExists(path.join(dir, name)) })),\n );\n return checked.filter(({ there }) => there).map(({ name }) => name);\n}\n\ntype EjectAgentPartialsOptions = {\n outputBase: string;\n force: boolean;\n directOutput?: boolean;\n templatesOnly?: boolean;\n};\n\ntype EjectAgentPartialsResult =\n | {\n skipped: true;\n skipReason: string;\n }\n | {\n skipped: false;\n destDir: string;\n /** The sub-agents left as they were, by name, bytewise-sorted. */\n skippedSubAgents: string[];\n templatesSkipped: boolean;\n };\n\nfunction resolveEjectDestDir(\n outputBase: string,\n directOutput: boolean,\n templatesOnly: boolean,\n): string {\n if (directOutput) return outputBase;\n const agentsDir = path.join(outputBase, path.basename(DIRS.agents));\n return templatesOnly ? path.join(agentsDir, path.basename(DIRS.templates)) : agentsDir;\n}\n\nasync function ejectAgentPartials(\n options: EjectAgentPartialsOptions,\n): Promise<EjectAgentPartialsResult> {\n const { outputBase, force, directOutput = false, templatesOnly = false } = options;\n const destDir = resolveEjectDestDir(outputBase, directOutput, templatesOnly);\n\n return templatesOnly ? ejectTemplates(destDir, force) : ejectSubAgentPartials(destDir, force);\n}\n\n/** Whole or not at all: a templates folder already there is kept unless --force. */\nasync function ejectTemplates(destDir: string, force: boolean): Promise<EjectAgentPartialsResult> {\n const sourceDir = path.join(PROJECT_ROOT, DIRS.templates);\n\n if (!(await directoryExists(sourceDir))) {\n return { skipped: true, skipReason: \"No agent templates found in CLI.\" };\n }\n\n if ((await directoryExists(destDir)) && !force) {\n return {\n skipped: true,\n skipReason: `Agent templates already exist at ${destDir}. Use --force to overwrite.`,\n };\n }\n\n await ensureDir(destDir);\n await copy(sourceDir, destDir);\n return { skipped: false, destDir, skippedSubAgents: [], templatesSkipped: false };\n}\n\n/** Unit by unit: one already there is kept unless --force, and the rest are copied beside it. */\nasync function ejectSubAgentPartials(\n destDir: string,\n force: boolean,\n): Promise<EjectAgentPartialsResult> {\n const sourceDir = path.join(PROJECT_ROOT, DIRS.agents);\n\n if (!(await directoryExists(sourceDir))) {\n return { skipped: true, skipReason: \"No agent partials found in CLI.\" };\n }\n\n const units = await partialUnitsIn(sourceDir);\n const present = force ? [] : await alreadyIn(destDir, units);\n const absent = units.filter((unit) => !present.includes(unit));\n\n if (absent.length === 0) {\n return {\n skipped: true,\n skipReason: `Agent partials already exist at ${destDir}. Use --force to overwrite.`,\n };\n }\n\n await copyUnits(absent, sourceDir, destDir);\n\n return {\n skipped: false,\n destDir,\n skippedSubAgents: subAgentNames(present),\n templatesSkipped: present.some(isTemplatesUnit),\n };\n}\n\nconst TEMPLATES_UNIT = path.basename(DIRS.templates);\n\nfunction isTemplatesUnit(unit: string): boolean {\n return unit === TEMPLATES_UNIT;\n}\n\n/**\n * What a re-eject keeps or copies whole: each sub-agent's directory, as `<category>/<agent>`, and\n * the templates. A category folder is not one, so a file of the user's in it is written beside.\n */\nasync function partialUnitsIn(agentsSourceDir: string): Promise<string[]> {\n const entries = await listDirectories(agentsSourceDir);\n const categories = entries.filter((entry) => !isTemplatesUnit(entry));\n const subAgentDirs = await Promise.all(\n categories.map((category) => subAgentDirsOf(agentsSourceDir, category)),\n );\n return [...entries.filter(isTemplatesUnit), ...subAgentDirs.flat()];\n}\n\nasync function subAgentDirsOf(agentsSourceDir: string, category: string): Promise<string[]> {\n const agents = await listDirectories(path.join(agentsSourceDir, category));\n return agents.map((agent) => path.join(category, agent));\n}\n\n/** As the skipped-list warning names them: by directory name, bytewise-sorted. */\nfunction subAgentNames(units: readonly string[]): string[] {\n return units\n .filter((unit) => !isTemplatesUnit(unit))\n .map((unit) => path.basename(unit))\n .sort(bytewise);\n}\n\n/** `copy` makes the folders above each unit. */\nasync function copyUnits(\n units: readonly string[],\n sourceDir: string,\n destDir: string,\n): Promise<void> {\n for (const unit of units) {\n await copy(path.join(sourceDir, unit), path.join(destDir, unit));\n }\n}\n\nfunction skillsDestination(projectDir: string, directOutput: boolean, outputBase: string): string {\n return directOutput ? outputBase : installedSkillsDir(projectDir);\n}\n\ntype EjectSkillsOptions = {\n destinationDir: string;\n force: boolean;\n sourceResult: SourceLoadResult;\n matrix: MergedSkillsMatrix;\n};\n\ntype EjectSkillsResult =\n | {\n skipped: true;\n skipReason: string;\n }\n | {\n skipped: false;\n copiedSkills: CopiedSkill[];\n /** How many skills were left as they were. */\n skippedSkillCount: number;\n sourceLabel: string;\n };\n\n/**\n * Only the loaded marketplace's own skills, each copied from the marketplace: others' are not on\n * disk here. One already in the destination is skipped unless --force; a local copy anywhere else\n * is the user's own and is left out either way.\n */\nasync function ejectSkills(options: EjectSkillsOptions): Promise<EjectSkillsResult> {\n const { destinationDir, force, sourceResult, matrix } = options;\n\n const marketplaceSkillIds = [...sourceResult.marketplaceSkillIds];\n const alreadyThere = force ? [] : await alreadyIn(destinationDir, marketplaceSkillIds);\n const notThere = marketplaceSkillIds.filter((skillId) => !alreadyThere.includes(skillId));\n const skillIds = notThere.filter(\n (skillId) => !isLocalCopyElsewhere(matrix.skills[skillId], destinationDir),\n );\n\n if (skillIds.length === 0 && alreadyThere.length > 0) {\n return {\n skipped: true,\n skipReason: `Skills already exist at ${destinationDir}. Use --force to overwrite.`,\n };\n }\n\n if (skillIds.length === 0) {\n return { skipped: true, skipReason: \"No skills found in the marketplace to eject.\" };\n }\n\n await ensureDir(destinationDir);\n\n const copiedSkills = await copyMarketplaceSkillsToLocalFlattened(\n skillIds,\n destinationDir,\n sourceResult,\n );\n\n const sourceLabel = sourceResult.isLocal\n ? sourceResult.sourcePath\n : sourceResult.marketplace || sourceResult.sourceConfig.source;\n\n return {\n skipped: false,\n copiedSkills,\n skippedSkillCount: alreadyThere.length,\n sourceLabel,\n };\n}\n\n/** Local, and not the copy at `<destinationDir>/<id>`, which is where an eject writes the skill. */\nfunction isLocalCopyElsewhere(skill: ResolvedSkill | undefined, destinationDir: string): boolean {\n if (!skill?.local) return false;\n if (!skill.localPath) return true;\n return path.resolve(skill.localPath) !== path.resolve(destinationDir, skill.id);\n}\n\n/** Where the host of the installation `projectDir` roots reads skills. */\nfunction installedSkillsDir(projectDir: string): string {\n const scope = isHomeDirectory(projectDir) ? \"global\" : \"project\";\n return resolveInstallPaths(projectDir, scope).skillsDir;\n}\n\ntype EnsureMinimalConfigOptions = {\n projectDir: string;\n sourceResult?: SourceLoadResult;\n};\n\ntype EnsureMinimalConfigResult = {\n configPath: string;\n created: boolean;\n};\n\nasync function ensureMinimalConfig(\n options: EnsureMinimalConfigOptions,\n): Promise<EnsureMinimalConfigResult> {\n const { projectDir, sourceResult } = options;\n\n const provider = providerInUse(projectDir);\n const tsConfigPath = getProjectConfigPath(projectDir, provider);\n\n if (await fileExists(tsConfigPath)) {\n return { configPath: tsConfigPath, created: false };\n }\n\n // ABORT on an unreadable global config: the invented file would record a marketplace from nowhere.\n const resolvedConfig =\n sourceResult?.sourceConfig ?? (await resolveSource({ caller: \"stored\", projectDir }));\n const source = resolvedConfig.source || undefined;\n\n // At home the invented config is the global manifest, which needs its config-types sibling.\n if (isHomeDirectory(projectDir)) {\n await ensureBlankPair(provider);\n if (source) await recordSourceInGlobal(projectDir, source);\n return { configPath: tsConfigPath, created: true };\n }\n\n await writeProjectPartial(\n projectDir,\n {\n skills: [],\n agents: [],\n ...(source ? { marketplace: source } : {}),\n ...(resolvedConfig.marketplace ? { marketplaceName: resolvedConfig.marketplace } : {}),\n },\n { fallbackName: path.basename(projectDir) },\n );\n\n return { configPath: tsConfigPath, created: true };\n}\n\n/** At home the config is the global manifest projects inline from, so it goes through the gate. */\nasync function recordSourceInGlobal(projectDir: string, source: string): Promise<void> {\n await mutateGlobal(\n { kind: \"set-source\", source, fallbackName: path.basename(projectDir) },\n lazyGateDeps(projectDir),\n );\n}\n"],"mappings":"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","names":["matrix"]}
@@ -4,26 +4,25 @@ import {
4
4
  Init,
5
5
  formatDashboardText,
6
6
  runDashboardFlow
7
- } from "../chunk-APWMMZOK.js";
8
- import "../chunk-I3WF6L43.js";
9
- import "../chunk-TVEDNGVP.js";
10
- import "../chunk-QCX66KBM.js";
7
+ } from "../chunk-EGC7PNDI.js";
8
+ import "../chunk-XYBHH3M5.js";
9
+ import "../chunk-P5XEK7HC.js";
10
+ import "../chunk-SRII2GMF.js";
11
11
  import "../chunk-OZXAJNLA.js";
12
12
  import "../chunk-P6CYS4JK.js";
13
- import "../chunk-H5E6IO2L.js";
14
- import "../chunk-6PGXTLA4.js";
15
- import "../chunk-R7GKQBZJ.js";
16
- import "../chunk-REHVGFJE.js";
17
- import "../chunk-7BHDKEGK.js";
18
- import "../chunk-IXVGBUWI.js";
19
- import "../chunk-EFXVYQGT.js";
13
+ import "../chunk-6HJVH27C.js";
14
+ import "../chunk-EHEBN4NB.js";
15
+ import "../chunk-SNXEYAFP.js";
16
+ import "../chunk-Q4NWATGH.js";
17
+ import "../chunk-DQB3E2SX.js";
18
+ import "../chunk-SI2LLEIR.js";
19
+ import "../chunk-GNMRXXRY.js";
20
20
  import "../chunk-KIK5EZYD.js";
21
- import "../chunk-FQF6VHO3.js";
22
- import "../chunk-ORO2T4K2.js";
23
- import "../chunk-IAQFZFWD.js";
24
- import "../chunk-E45IT3HC.js";
25
- import "../chunk-AIBVAYHS.js";
26
- import "../chunk-WUSEZFER.js";
21
+ import "../chunk-ICHWAFAC.js";
22
+ import "../chunk-37QFHJUW.js";
23
+ import "../chunk-YM3VEDAP.js";
24
+ import "../chunk-TG3SPPZY.js";
25
+ import "../chunk-U46LYYRA.js";
27
26
  import "../chunk-GHHJYNAN.js";
28
27
  export {
29
28
  Dashboard,
@@ -5,15 +5,13 @@ import {
5
5
  import {
6
6
  SkillAgentSummary,
7
7
  computeScopeDiff
8
- } from "../chunk-FQF6VHO3.js";
8
+ } from "../chunk-ICHWAFAC.js";
9
9
  import {
10
+ BaseCommand,
10
11
  otherInstallationsInThisScope,
11
12
  providerFlag,
12
13
  providerNamedBy
13
- } from "../chunk-ORO2T4K2.js";
14
- import {
15
- BaseCommand
16
- } from "../chunk-IAQFZFWD.js";
14
+ } from "../chunk-37QFHJUW.js";
17
15
  import {
18
16
  INSTALL_MODE_LABELS,
19
17
  chooseProviderForThisRun,
@@ -21,15 +19,15 @@ import {
21
19
  formatInstallationDisplay,
22
20
  getInstallationInfo,
23
21
  loadProjectConfig
24
- } from "../chunk-E45IT3HC.js";
22
+ } from "../chunk-YM3VEDAP.js";
25
23
  import {
26
24
  getSkillEntryDisplayName
27
- } from "../chunk-AIBVAYHS.js";
25
+ } from "../chunk-TG3SPPZY.js";
28
26
  import {
29
27
  CLI_COLORS,
30
28
  CLI_INVOKE_COMMAND,
31
29
  DEFAULT_BRANDING
32
- } from "../chunk-WUSEZFER.js";
30
+ } from "../chunk-U46LYYRA.js";
33
31
  import "../chunk-GHHJYNAN.js";
34
32
 
35
33
  // src/cli/commands/list.tsx
@@ -86,6 +84,7 @@ var List = class _List extends BaseCommand {
86
84
  }
87
85
  async run() {
88
86
  const { flags } = await this.parse(_List);
87
+ await this.sayWhenTheGlobalInstallationStandsIn(providerNamedBy(flags.provider));
89
88
  await this.sayWhichInstallationThisIs(flags.provider);
90
89
  await this.ensureConfigReadable(process.cwd());
91
90
  const installation = await detectInstallation();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/commands/list.tsx"],"sourcesContent":["import React, { useEffect } from \"react\";\n\nimport { Box, Text, useApp } from \"ink\";\nimport { render } from \"../components/render.js\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { CLI_INVOKE_COMMAND, CLI_COLORS, DEFAULT_BRANDING } from \"../consts.js\";\nimport { chooseProviderForThisRun } from \"../lib/installation/install-layout.js\";\nimport {\n otherInstallationsInThisScope,\n providerFlag,\n providerNamedBy,\n} from \"../lib/installation/provider-flag.js\";\nimport { getInstallationInfo, formatInstallationDisplay } from \"../lib/plugins/index.js\";\nimport {\n detectInstallation,\n INSTALL_MODE_LABELS,\n type Installation,\n} from \"../lib/installation/installation.js\";\nimport { loadProjectConfig } from \"../lib/configuration/project-config.js\";\nimport { computeScopeDiff, type SkillDiffRow } from \"../lib/configuration/scope-diff.js\";\nimport { getSkillEntryDisplayName } from \"../lib/matrix/matrix-provider.js\";\nimport { SkillAgentSummary } from \"../components/common/skill-agent-summary.js\";\nimport type { AgentScopeConfig, ProjectConfig, SkillConfig, SkillScope } from \"../types/config.js\";\n\ntype ListViewProps = {\n mode: string;\n source?: string | undefined;\n skillConfigs: SkillConfig[];\n agentConfigs: AgentScopeConfig[];\n};\n\ntype ActiveRoster = Pick<ListViewProps, \"skillConfigs\" | \"agentConfigs\">;\n\n/** The label never shrinks: a value too long for the line wraps beside it instead. */\nconst HeaderRow: React.FC<{ label: string; value: string }> = ({ label, value }) => (\n <Box flexDirection=\"row\" columnGap={1}>\n <Box flexShrink={0}>\n <Text color={CLI_COLORS.WARNING} bold>\n {label}\n </Text>\n </Box>\n <Text color={CLI_COLORS.NEUTRAL}>{value}</Text>\n </Box>\n);\n\nconst ListView: React.FC<ListViewProps> = ({ mode, source, skillConfigs, agentConfigs }) => {\n const { exit } = useApp();\n\n useEffect(() => {\n const timer = setTimeout(() => exit(), 0);\n return () => clearTimeout(timer);\n }, [exit]);\n\n return (\n <Box flexDirection=\"column\" paddingX={1} paddingY={1}>\n <Box flexDirection=\"column\" marginBottom={1}>\n <HeaderRow label=\"Mode\" value={mode} />\n {source && <HeaderRow label=\"Marketplace\" value={source} />}\n </Box>\n\n {/* Installed and current are one configuration, so every row reads unchanged. */}\n <SkillAgentSummary\n skillConfigs={skillConfigs}\n agentConfigs={agentConfigs}\n installedSkillConfigs={skillConfigs}\n installedAgentConfigs={agentConfigs}\n isInitMode={false}\n />\n </Box>\n );\n};\n\nexport default class List extends BaseCommand {\n static summary = \"Show installation information\";\n static description = `Display details about the ${DEFAULT_BRANDING.NAME} installation (local or plugin mode)`;\n static aliases = [\"ls\"];\n\n static flags = { provider: providerFlag() };\n\n static examples = [\n {\n description: \"Show current installation details\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n ];\n\n /** Names the other installation in this scope; reports rather than refuses, like `doctor`. */\n private async sayWhichInstallationThisIs(providerFlagValue: string | undefined): Promise<void> {\n const named = providerNamedBy(providerFlagValue);\n if (named !== undefined) {\n chooseProviderForThisRun(named);\n return;\n }\n\n const line = await otherInstallationsInThisScope(process.cwd());\n if (line !== null) this.log(line);\n }\n\n async run(): Promise<void> {\n const { flags } = await this.parse(List);\n await this.sayWhichInstallationThisIs(flags.provider);\n await this.ensureConfigReadable(process.cwd());\n\n const installation = await detectInstallation();\n if (!installation) return this.reportNoInstallation();\n\n const loaded = await loadProjectConfig(installation.projectDir);\n if (loaded === null) return this.printInstallationInfo([]);\n if (!process.stdin.isTTY) {\n return this.printInstallationInfo(skillLinesOf(activeRosterOf(loaded.config)));\n }\n\n await showListView(installation, loaded.config);\n }\n\n private reportNoInstallation(): void {\n this.log(\"No installation found.\");\n this.log(`Run '${CLI_INVOKE_COMMAND} init' to create one.`);\n }\n\n private async printInstallationInfo(skillLines: string[]): Promise<void> {\n const info = await getInstallationInfo();\n if (!info) return;\n\n this.log(\"\");\n this.log(formatInstallationDisplay(info, skillLines));\n this.log(\"\");\n }\n}\n\nasync function showListView(installation: Installation, config: ProjectConfig): Promise<void> {\n const { waitUntilExit, clear } = render(\n <ListView\n mode={INSTALL_MODE_LABELS[installation.mode]}\n source={config.marketplace}\n {...activeRosterOf(config)}\n />,\n );\n\n await waitUntilExit();\n clear();\n}\n\nfunction activeRosterOf(config: ProjectConfig): ActiveRoster {\n return {\n skillConfigs: config.skills.filter((skill) => !skill.excluded),\n agentConfigs: config.agents.filter((agent) => !agent.excluded),\n };\n}\n\n/** The panel's skill rows, read as it reads them: project rows first, each under the panel's name. */\nfunction skillLinesOf({ skillConfigs, agentConfigs }: ActiveRoster): string[] {\n const { projectSkillRows, globalSkillRows } = computeScopeDiff({\n currentSkills: skillConfigs,\n currentAgents: agentConfigs,\n installedSkillConfigs: skillConfigs,\n installedAgentConfigs: agentConfigs,\n isInitMode: false,\n });\n\n return [\n ...projectSkillRows.map((row) => skillLine(row, \"project\")),\n ...globalSkillRows.map((row) => skillLine(row, \"global\")),\n ];\n}\n\nfunction skillLine(row: SkillDiffRow, scope: SkillScope): string {\n return `${getSkillEntryDisplayName(row)} (${scope})`;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/cli/commands/list.tsx"],"sourcesContent":["import React, { useEffect } from \"react\";\n\nimport { Box, Text, useApp } from \"ink\";\nimport { render } from \"../components/render.js\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { CLI_INVOKE_COMMAND, CLI_COLORS, DEFAULT_BRANDING } from \"../consts.js\";\nimport { chooseProviderForThisRun } from \"../lib/installation/install-layout.js\";\nimport {\n otherInstallationsInThisScope,\n providerFlag,\n providerNamedBy,\n} from \"../lib/installation/provider-flag.js\";\nimport { getInstallationInfo, formatInstallationDisplay } from \"../lib/plugins/index.js\";\nimport {\n detectInstallation,\n INSTALL_MODE_LABELS,\n type Installation,\n} from \"../lib/installation/installation.js\";\nimport { loadProjectConfig } from \"../lib/configuration/project-config.js\";\nimport { computeScopeDiff, type SkillDiffRow } from \"../lib/configuration/scope-diff.js\";\nimport { getSkillEntryDisplayName } from \"../lib/matrix/matrix-provider.js\";\nimport { SkillAgentSummary } from \"../components/common/skill-agent-summary.js\";\nimport type { AgentScopeConfig, ProjectConfig, SkillConfig, SkillScope } from \"../types/config.js\";\n\ntype ListViewProps = {\n mode: string;\n source?: string | undefined;\n skillConfigs: SkillConfig[];\n agentConfigs: AgentScopeConfig[];\n};\n\ntype ActiveRoster = Pick<ListViewProps, \"skillConfigs\" | \"agentConfigs\">;\n\n/** The label never shrinks: a value too long for the line wraps beside it instead. */\nconst HeaderRow: React.FC<{ label: string; value: string }> = ({ label, value }) => (\n <Box flexDirection=\"row\" columnGap={1}>\n <Box flexShrink={0}>\n <Text color={CLI_COLORS.WARNING} bold>\n {label}\n </Text>\n </Box>\n <Text color={CLI_COLORS.NEUTRAL}>{value}</Text>\n </Box>\n);\n\nconst ListView: React.FC<ListViewProps> = ({ mode, source, skillConfigs, agentConfigs }) => {\n const { exit } = useApp();\n\n useEffect(() => {\n const timer = setTimeout(() => exit(), 0);\n return () => clearTimeout(timer);\n }, [exit]);\n\n return (\n <Box flexDirection=\"column\" paddingX={1} paddingY={1}>\n <Box flexDirection=\"column\" marginBottom={1}>\n <HeaderRow label=\"Mode\" value={mode} />\n {source && <HeaderRow label=\"Marketplace\" value={source} />}\n </Box>\n\n {/* Installed and current are one configuration, so every row reads unchanged. */}\n <SkillAgentSummary\n skillConfigs={skillConfigs}\n agentConfigs={agentConfigs}\n installedSkillConfigs={skillConfigs}\n installedAgentConfigs={agentConfigs}\n isInitMode={false}\n />\n </Box>\n );\n};\n\nexport default class List extends BaseCommand {\n static summary = \"Show installation information\";\n static description = `Display details about the ${DEFAULT_BRANDING.NAME} installation (local or plugin mode)`;\n static aliases = [\"ls\"];\n\n static flags = { provider: providerFlag() };\n\n static examples = [\n {\n description: \"Show current installation details\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n ];\n\n /** Names the other installation in this scope; reports rather than refuses, like `doctor`. */\n private async sayWhichInstallationThisIs(providerFlagValue: string | undefined): Promise<void> {\n const named = providerNamedBy(providerFlagValue);\n if (named !== undefined) {\n chooseProviderForThisRun(named);\n return;\n }\n\n const line = await otherInstallationsInThisScope(process.cwd());\n if (line !== null) this.log(line);\n }\n\n async run(): Promise<void> {\n const { flags } = await this.parse(List);\n await this.sayWhenTheGlobalInstallationStandsIn(providerNamedBy(flags.provider));\n await this.sayWhichInstallationThisIs(flags.provider);\n await this.ensureConfigReadable(process.cwd());\n\n const installation = await detectInstallation();\n if (!installation) return this.reportNoInstallation();\n\n const loaded = await loadProjectConfig(installation.projectDir);\n if (loaded === null) return this.printInstallationInfo([]);\n if (!process.stdin.isTTY) {\n return this.printInstallationInfo(skillLinesOf(activeRosterOf(loaded.config)));\n }\n\n await showListView(installation, loaded.config);\n }\n\n private reportNoInstallation(): void {\n this.log(\"No installation found.\");\n this.log(`Run '${CLI_INVOKE_COMMAND} init' to create one.`);\n }\n\n private async printInstallationInfo(skillLines: string[]): Promise<void> {\n const info = await getInstallationInfo();\n if (!info) return;\n\n this.log(\"\");\n this.log(formatInstallationDisplay(info, skillLines));\n this.log(\"\");\n }\n}\n\nasync function showListView(installation: Installation, config: ProjectConfig): Promise<void> {\n const { waitUntilExit, clear } = render(\n <ListView\n mode={INSTALL_MODE_LABELS[installation.mode]}\n source={config.marketplace}\n {...activeRosterOf(config)}\n />,\n );\n\n await waitUntilExit();\n clear();\n}\n\nfunction activeRosterOf(config: ProjectConfig): ActiveRoster {\n return {\n skillConfigs: config.skills.filter((skill) => !skill.excluded),\n agentConfigs: config.agents.filter((agent) => !agent.excluded),\n };\n}\n\n/** The panel's skill rows, read as it reads them: project rows first, each under the panel's name. */\nfunction skillLinesOf({ skillConfigs, agentConfigs }: ActiveRoster): string[] {\n const { projectSkillRows, globalSkillRows } = computeScopeDiff({\n currentSkills: skillConfigs,\n currentAgents: agentConfigs,\n installedSkillConfigs: skillConfigs,\n installedAgentConfigs: agentConfigs,\n isInitMode: false,\n });\n\n return [\n ...projectSkillRows.map((row) => skillLine(row, \"project\")),\n ...globalSkillRows.map((row) => skillLine(row, \"global\")),\n ];\n}\n\nfunction skillLine(row: SkillDiffRow, scope: SkillScope): string {\n return `${getSkillEntryDisplayName(row)} (${scope})`;\n}\n"],"mappings":"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","names":[]}
@@ -2,14 +2,14 @@
2
2
  import {
3
3
  BaseCommand,
4
4
  EXIT_CODES
5
- } from "../../chunk-IAQFZFWD.js";
5
+ } from "../../chunk-37QFHJUW.js";
6
6
  import {
7
7
  isDirectoryEmpty,
8
8
  validateKebabCaseName,
9
9
  validateMarketplaceName,
10
10
  writeFile
11
- } from "../../chunk-E45IT3HC.js";
12
- import "../../chunk-AIBVAYHS.js";
11
+ } from "../../chunk-YM3VEDAP.js";
12
+ import "../../chunk-TG3SPPZY.js";
13
13
  import {
14
14
  CLI_INVOKE_COMMAND,
15
15
  DEFAULT_VERSION,
@@ -19,7 +19,7 @@ import {
19
19
  SKILL_RULES_PATH,
20
20
  STACKS_FILE_PATH,
21
21
  STANDARD_FILES
22
- } from "../../chunk-WUSEZFER.js";
22
+ } from "../../chunk-U46LYYRA.js";
23
23
  import "../../chunk-GHHJYNAN.js";
24
24
 
25
25
  // src/cli/commands/new/marketplace.ts
@@ -1,26 +1,26 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  loadSource
4
- } from "../chunk-R7GKQBZJ.js";
5
- import "../chunk-REHVGFJE.js";
6
- import "../chunk-7BHDKEGK.js";
7
- import "../chunk-IXVGBUWI.js";
8
- import "../chunk-EFXVYQGT.js";
4
+ } from "../chunk-SNXEYAFP.js";
5
+ import "../chunk-Q4NWATGH.js";
6
+ import "../chunk-DQB3E2SX.js";
7
+ import "../chunk-SI2LLEIR.js";
8
+ import "../chunk-GNMRXXRY.js";
9
9
  import {
10
10
  BaseCommand
11
- } from "../chunk-IAQFZFWD.js";
11
+ } from "../chunk-37QFHJUW.js";
12
12
  import {
13
13
  STATUS_MESSAGES
14
- } from "../chunk-E45IT3HC.js";
14
+ } from "../chunk-YM3VEDAP.js";
15
15
  import {
16
16
  plural,
17
17
  stripTerminalControls,
18
18
  truncateText,
19
19
  typedValues
20
- } from "../chunk-AIBVAYHS.js";
20
+ } from "../chunk-TG3SPPZY.js";
21
21
  import {
22
22
  EDITOR_ADDRESS
23
- } from "../chunk-WUSEZFER.js";
23
+ } from "../chunk-U46LYYRA.js";
24
24
  import "../chunk-GHHJYNAN.js";
25
25
 
26
26
  // src/cli/commands/search.ts
@@ -2,21 +2,19 @@
2
2
  import {
3
3
  publishSeedConfig,
4
4
  seedPayloadForInstallation
5
- } from "../chunk-3PJZ4QNJ.js";
5
+ } from "../chunk-MFCZARV2.js";
6
6
  import {
7
7
  unofferablePlacementsFound
8
- } from "../chunk-ECPFYHDX.js";
9
- import "../chunk-QCX66KBM.js";
10
- import "../chunk-EFXVYQGT.js";
8
+ } from "../chunk-YLFKFVQP.js";
9
+ import "../chunk-SRII2GMF.js";
10
+ import "../chunk-GNMRXXRY.js";
11
11
  import {
12
+ BaseCommand,
13
+ EXIT_CODES,
12
14
  providerFlag,
13
15
  providerNamedBy,
14
16
  refuseAnAmbiguousInstallation
15
- } from "../chunk-ORO2T4K2.js";
16
- import {
17
- BaseCommand,
18
- EXIT_CODES
19
- } from "../chunk-IAQFZFWD.js";
17
+ } from "../chunk-37QFHJUW.js";
20
18
  import {
21
19
  formatZodErrors,
22
20
  getErrorMessage,
@@ -26,15 +24,15 @@ import {
26
24
  sharedIdNamesAFolder,
27
25
  sharedSkillsLeftBehind,
28
26
  warn
29
- } from "../chunk-E45IT3HC.js";
27
+ } from "../chunk-YM3VEDAP.js";
30
28
  import {
31
29
  stripTerminalControls,
32
30
  truncateText,
33
31
  typedEntries
34
- } from "../chunk-AIBVAYHS.js";
32
+ } from "../chunk-TG3SPPZY.js";
35
33
  import {
36
34
  installableSeedPayloadSchema
37
- } from "../chunk-WUSEZFER.js";
35
+ } from "../chunk-U46LYYRA.js";
38
36
  import "../chunk-GHHJYNAN.js";
39
37
 
40
38
  // src/cli/commands/share.ts
@@ -117,10 +115,12 @@ var Share = class _Share extends BaseCommand {
117
115
  async run() {
118
116
  const { flags } = await this.parse(_Share);
119
117
  if (!flags.stdin) {
118
+ const namedProvider = providerNamedBy(flags.provider);
119
+ await this.sayWhenTheGlobalInstallationStandsIn(namedProvider);
120
120
  await refuseAnAmbiguousInstallation(
121
121
  process.cwd(),
122
122
  "share",
123
- providerNamedBy(flags.provider),
123
+ namedProvider,
124
124
  (message) => this.error(message, { exit: EXIT_CODES.INVALID_ARGS })
125
125
  );
126
126
  await this.ensureConfigReadable(process.cwd());
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/commands/share.ts","../../src/cli/lib/seed/read-piped-payload.ts","../../src/cli/utils/read-stream.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { isLocalSource } from \"../lib/configuration/config.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { unofferablePlacementsFound } from \"../lib/hosts/configured-placements.js\";\nimport { seedPayloadForInstallation } from \"../lib/seed/installation-payload.js\";\nimport { publishSeedConfig } from \"../lib/seed/publish-seed.js\";\nimport {\n readPipedPayload,\n STDIN_IS_A_TERMINAL,\n type PipedPayload,\n} from \"../lib/seed/read-piped-payload.js\";\nimport {\n providerFlag,\n providerNamedBy,\n refuseAnAmbiguousInstallation,\n} from \"../lib/installation/provider-flag.js\";\nimport { warn } from \"../utils/logger.js\";\nimport { readAllOf } from \"../utils/read-stream.js\";\nimport {\n sharedConfigDestinations,\n sharedIdNamesAFolder,\n sharedSkillsLeftBehind,\n shareRefusesEjectedSkills,\n} from \"../utils/messages.js\";\nimport { typedEntries } from \"../utils/typed-object.js\";\nimport type { SkillId } from \"../types/index.js\";\nimport type { SeedPayload } from \"@workspace/matrix/seed\";\n\ntype ShareablePayload = { payload: SeedPayload; caveats: string[] };\n\n/** What the id will not do everywhere — warned after the id rather than refused. */\nfunction caveatsAbout(payload: SeedPayload, leftBehind: readonly SkillId[]): string[] {\n const { marketplace } = payload;\n return [\n ...(isAFolder(marketplace) ? [sharedIdNamesAFolder(marketplace)] : []),\n ...(leftBehind.length > 0 ? [sharedSkillsLeftBehind(leftBehind)] : []),\n ];\n}\n\nfunction isAFolder(marketplace: string | undefined): marketplace is string {\n return marketplace !== undefined && isLocalSource(marketplace);\n}\n\nfunction ejectedSkillsIn(payload: SeedPayload): string[] {\n return typedEntries(payload.skills)\n .filter(([, skill]) => skill.install === \"eject\")\n .map(([id]) => id);\n}\n\nexport default class Share extends BaseCommand {\n static summary = \"Share this installation as an id anyone can install\";\n\n static description =\n \"Turns the skills, sub-agents and per-agent curation installed here into a configuration the agentsinc.sh store holds, and prints the id it was given. Install it elsewhere with 'init --from <id>', or open it in the editor. The id is the configuration's own hash, so sharing an unchanged installation returns the id it already had.\";\n\n static flags = {\n stdin: Flags.boolean({\n description:\n \"Share a configuration piped in on standard input instead of the one installed here\",\n default: false,\n }),\n provider: providerFlag(),\n };\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"cat proposal.json | <%= config.bin %> <%= command.id %> --stdin\",\n ];\n\n /** Everything that can fail locally fails before the POST: store writes are the scarce quota. */\n async run(): Promise<void> {\n const { flags } = await this.parse(Share);\n\n // A piped payload never reads this directory, so its state must not refuse it.\n if (!flags.stdin) {\n await refuseAnAmbiguousInstallation(\n process.cwd(),\n \"share\",\n providerNamedBy(flags.provider),\n (message) => this.error(message, { exit: EXIT_CODES.INVALID_ARGS }),\n );\n await this.ensureConfigReadable(process.cwd());\n await this.refuseUnofferablePlacements(process.cwd());\n }\n\n const { payload, caveats } = flags.stdin\n ? await this.payloadFromPipe()\n : await this.payloadFromInstallation();\n\n const published = await publishSeedConfig(payload);\n if (!published.ok) {\n this.error(published.error, { exit: EXIT_CODES.ERROR });\n }\n\n this.reportShared(published.id);\n // Not `this.warn`: oclif hard-wraps, which breaks the folder paths caveats name.\n for (const caveat of caveats) warn(caveat);\n }\n\n /** A placement the host cannot fill was never installed here, so the id would misdescribe it. */\n private async refuseUnofferablePlacements(cwd: string): Promise<void> {\n const [finding] = await unofferablePlacementsFound(cwd);\n if (finding !== undefined) this.error(finding, { exit: EXIT_CODES.ERROR });\n }\n\n private async payloadFromInstallation(): Promise<ShareablePayload> {\n const prepared = await seedPayloadForInstallation(process.cwd());\n if (!prepared.ok) {\n this.error(prepared.error, { exit: EXIT_CODES.ERROR });\n }\n\n this.refuseEjectedSkills(prepared.payload);\n this.log(`Sharing ${prepared.skills} skill(s) across ${prepared.agents} sub-agent(s)...`);\n\n return {\n payload: prepared.payload,\n caveats: caveatsAbout(prepared.payload, prepared.leftBehind),\n };\n }\n\n /** A share carries plugins only: an ejected skill is a local copy the user may have edited. */\n private refuseEjectedSkills(payload: SeedPayload): void {\n const ejected = ejectedSkillsIn(payload);\n if (ejected.length > 0) {\n this.error(shareRefusesEjectedSkills(ejected), { exit: EXIT_CODES.ERROR });\n }\n }\n\n /** The caller's configuration; no installation is read, so it owes no caveats. */\n private async payloadFromPipe(): Promise<ShareablePayload> {\n if (process.stdin.isTTY) {\n this.error(STDIN_IS_A_TERMINAL, { exit: EXIT_CODES.ERROR });\n }\n\n const read: PipedPayload = readPipedPayload(await readAllOf(process.stdin));\n if (!read.ok) {\n this.error(read.error, { exit: EXIT_CODES.ERROR });\n }\n\n return { payload: read.payload, caveats: [] };\n }\n\n private reportShared(id: string): void {\n this.logSuccess(`Shared as ${id}`);\n for (const destination of sharedConfigDestinations(id)) {\n this.log(destination);\n }\n }\n}\n","import { installableSeedPayloadSchema, type SeedPayload } from \"@workspace/matrix/seed\";\n\nimport { formatZodErrors } from \"../schema-validator.js\";\nimport { getErrorMessage } from \"../../utils/errors.js\";\nimport { stripTerminalControls, truncateText } from \"../../utils/string.js\";\n\nexport type PipedPayload =\n | { readonly ok: true; readonly payload: SeedPayload }\n | { readonly ok: false; readonly error: string };\n\nexport const NOTHING_PIPED =\n \"--stdin expects a configuration on standard input and none arrived. Pipe one in, as 'cat proposal.json | agents-inc share --stdin'.\";\n\nexport const STDIN_IS_A_TERMINAL =\n \"--stdin expects a configuration on standard input, but standard input is a terminal. Pipe one in rather than typing it.\";\n\n/** Characters of a non-JSON body to quote back, enough for the caller to recognise it. */\nconst EXCERPT = 80;\n\n/**\n * The scope rule raises one issue per (skill, sub-agent) pair, so the list can run to hundreds.\n * A count, not a character cut, so no name is left half-printed.\n */\nconst PROBLEMS_NAMED = 4;\n\n/**\n * Fails locally before a write is spent. Uses the installable schema the store's POST validates\n * with, not the lenient read schema, so nothing passes here and fails at the edge.\n */\nexport function readPipedPayload(body: string): PipedPayload {\n if (body.trim() === \"\") return { ok: false, error: NOTHING_PIPED };\n\n const read = readJson(body);\n if (!read.parsed) return { ok: false, error: notJsonMessage(body, read.reason) };\n\n const result = installableSeedPayloadSchema.safeParse(read.value);\n if (!result.success) {\n return { ok: false, error: refusedByContract(formatZodErrors(result.error)) };\n }\n\n return { ok: true, payload: result.data };\n}\n\ntype JsonRead =\n | { readonly parsed: true; readonly value: unknown }\n | { readonly parsed: false; readonly reason: string };\n\nfunction readJson(body: string): JsonRead {\n try {\n return { parsed: true, value: JSON.parse(body) };\n } catch (error) {\n return { parsed: false, reason: getErrorMessage(error) };\n }\n}\n\n/** The parse reason is stripped too: V8 quotes the offending input verbatim in it. */\nfunction notJsonMessage(body: string, reason: string): string {\n const opening = truncateText(body.trim(), EXCERPT);\n const said = stripTerminalControls(reason);\n return `What arrived on standard input is not JSON: ${said}. It began: ${opening}`;\n}\n\nfunction refusedByContract(problems: string[]): string {\n return `The configuration on standard input is not one this store accepts: ${namedProblems(problems)}`;\n}\n\n/** The count tells a clipped list from a complete one. */\nfunction namedProblems(problems: string[]): string {\n const named = problems.slice(0, PROBLEMS_NAMED).join(\"; \");\n const elided = problems.length - PROBLEMS_NAMED;\n return elided > 0 ? `${named} (and ${elided} more)` : named;\n}\n","import type { Readable } from \"node:stream\";\n\n/** Async iteration rather than `readFileSync(\"/dev/stdin\")`, which is not portable. */\nexport async function readAllOf(stream: Readable): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of stream) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));\n }\n\n return Buffer.concat(chunks).toString(\"utf-8\");\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/cli/commands/share.ts","../../src/cli/lib/seed/read-piped-payload.ts","../../src/cli/utils/read-stream.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { isLocalSource } from \"../lib/configuration/config.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { unofferablePlacementsFound } from \"../lib/hosts/configured-placements.js\";\nimport { seedPayloadForInstallation } from \"../lib/seed/installation-payload.js\";\nimport { publishSeedConfig } from \"../lib/seed/publish-seed.js\";\nimport {\n readPipedPayload,\n STDIN_IS_A_TERMINAL,\n type PipedPayload,\n} from \"../lib/seed/read-piped-payload.js\";\nimport {\n providerFlag,\n providerNamedBy,\n refuseAnAmbiguousInstallation,\n} from \"../lib/installation/provider-flag.js\";\nimport { warn } from \"../utils/logger.js\";\nimport { readAllOf } from \"../utils/read-stream.js\";\nimport {\n sharedConfigDestinations,\n sharedIdNamesAFolder,\n sharedSkillsLeftBehind,\n shareRefusesEjectedSkills,\n} from \"../utils/messages.js\";\nimport { typedEntries } from \"../utils/typed-object.js\";\nimport type { SkillId } from \"../types/index.js\";\nimport type { SeedPayload } from \"@workspace/matrix/seed\";\n\ntype ShareablePayload = { payload: SeedPayload; caveats: string[] };\n\n/** What the id will not do everywhere — warned after the id rather than refused. */\nfunction caveatsAbout(payload: SeedPayload, leftBehind: readonly SkillId[]): string[] {\n const { marketplace } = payload;\n return [\n ...(isAFolder(marketplace) ? [sharedIdNamesAFolder(marketplace)] : []),\n ...(leftBehind.length > 0 ? [sharedSkillsLeftBehind(leftBehind)] : []),\n ];\n}\n\nfunction isAFolder(marketplace: string | undefined): marketplace is string {\n return marketplace !== undefined && isLocalSource(marketplace);\n}\n\nfunction ejectedSkillsIn(payload: SeedPayload): string[] {\n return typedEntries(payload.skills)\n .filter(([, skill]) => skill.install === \"eject\")\n .map(([id]) => id);\n}\n\nexport default class Share extends BaseCommand {\n static summary = \"Share this installation as an id anyone can install\";\n\n static description =\n \"Turns the skills, sub-agents and per-agent curation installed here into a configuration the agentsinc.sh store holds, and prints the id it was given. Install it elsewhere with 'init --from <id>', or open it in the editor. The id is the configuration's own hash, so sharing an unchanged installation returns the id it already had.\";\n\n static flags = {\n stdin: Flags.boolean({\n description:\n \"Share a configuration piped in on standard input instead of the one installed here\",\n default: false,\n }),\n provider: providerFlag(),\n };\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"cat proposal.json | <%= config.bin %> <%= command.id %> --stdin\",\n ];\n\n /** Everything that can fail locally fails before the POST: store writes are the scarce quota. */\n async run(): Promise<void> {\n const { flags } = await this.parse(Share);\n\n // A piped payload never reads this directory, so its state must not refuse it.\n if (!flags.stdin) {\n const namedProvider = providerNamedBy(flags.provider);\n await this.sayWhenTheGlobalInstallationStandsIn(namedProvider);\n await refuseAnAmbiguousInstallation(process.cwd(), \"share\", namedProvider, (message) =>\n this.error(message, { exit: EXIT_CODES.INVALID_ARGS }),\n );\n await this.ensureConfigReadable(process.cwd());\n await this.refuseUnofferablePlacements(process.cwd());\n }\n\n const { payload, caveats } = flags.stdin\n ? await this.payloadFromPipe()\n : await this.payloadFromInstallation();\n\n const published = await publishSeedConfig(payload);\n if (!published.ok) {\n this.error(published.error, { exit: EXIT_CODES.ERROR });\n }\n\n this.reportShared(published.id);\n // Not `this.warn`: oclif hard-wraps, which breaks the folder paths caveats name.\n for (const caveat of caveats) warn(caveat);\n }\n\n /** A placement the host cannot fill was never installed here, so the id would misdescribe it. */\n private async refuseUnofferablePlacements(cwd: string): Promise<void> {\n const [finding] = await unofferablePlacementsFound(cwd);\n if (finding !== undefined) this.error(finding, { exit: EXIT_CODES.ERROR });\n }\n\n private async payloadFromInstallation(): Promise<ShareablePayload> {\n const prepared = await seedPayloadForInstallation(process.cwd());\n if (!prepared.ok) {\n this.error(prepared.error, { exit: EXIT_CODES.ERROR });\n }\n\n this.refuseEjectedSkills(prepared.payload);\n this.log(`Sharing ${prepared.skills} skill(s) across ${prepared.agents} sub-agent(s)...`);\n\n return {\n payload: prepared.payload,\n caveats: caveatsAbout(prepared.payload, prepared.leftBehind),\n };\n }\n\n /** A share carries plugins only: an ejected skill is a local copy the user may have edited. */\n private refuseEjectedSkills(payload: SeedPayload): void {\n const ejected = ejectedSkillsIn(payload);\n if (ejected.length > 0) {\n this.error(shareRefusesEjectedSkills(ejected), { exit: EXIT_CODES.ERROR });\n }\n }\n\n /** The caller's configuration; no installation is read, so it owes no caveats. */\n private async payloadFromPipe(): Promise<ShareablePayload> {\n if (process.stdin.isTTY) {\n this.error(STDIN_IS_A_TERMINAL, { exit: EXIT_CODES.ERROR });\n }\n\n const read: PipedPayload = readPipedPayload(await readAllOf(process.stdin));\n if (!read.ok) {\n this.error(read.error, { exit: EXIT_CODES.ERROR });\n }\n\n return { payload: read.payload, caveats: [] };\n }\n\n private reportShared(id: string): void {\n this.logSuccess(`Shared as ${id}`);\n for (const destination of sharedConfigDestinations(id)) {\n this.log(destination);\n }\n }\n}\n","import { installableSeedPayloadSchema, type SeedPayload } from \"@workspace/matrix/seed\";\n\nimport { formatZodErrors } from \"../schema-validator.js\";\nimport { getErrorMessage } from \"../../utils/errors.js\";\nimport { stripTerminalControls, truncateText } from \"../../utils/string.js\";\n\nexport type PipedPayload =\n | { readonly ok: true; readonly payload: SeedPayload }\n | { readonly ok: false; readonly error: string };\n\nexport const NOTHING_PIPED =\n \"--stdin expects a configuration on standard input and none arrived. Pipe one in, as 'cat proposal.json | agents-inc share --stdin'.\";\n\nexport const STDIN_IS_A_TERMINAL =\n \"--stdin expects a configuration on standard input, but standard input is a terminal. Pipe one in rather than typing it.\";\n\n/** Characters of a non-JSON body to quote back, enough for the caller to recognise it. */\nconst EXCERPT = 80;\n\n/**\n * The scope rule raises one issue per (skill, sub-agent) pair, so the list can run to hundreds.\n * A count, not a character cut, so no name is left half-printed.\n */\nconst PROBLEMS_NAMED = 4;\n\n/**\n * Fails locally before a write is spent. Uses the installable schema the store's POST validates\n * with, not the lenient read schema, so nothing passes here and fails at the edge.\n */\nexport function readPipedPayload(body: string): PipedPayload {\n if (body.trim() === \"\") return { ok: false, error: NOTHING_PIPED };\n\n const read = readJson(body);\n if (!read.parsed) return { ok: false, error: notJsonMessage(body, read.reason) };\n\n const result = installableSeedPayloadSchema.safeParse(read.value);\n if (!result.success) {\n return { ok: false, error: refusedByContract(formatZodErrors(result.error)) };\n }\n\n return { ok: true, payload: result.data };\n}\n\ntype JsonRead =\n | { readonly parsed: true; readonly value: unknown }\n | { readonly parsed: false; readonly reason: string };\n\nfunction readJson(body: string): JsonRead {\n try {\n return { parsed: true, value: JSON.parse(body) };\n } catch (error) {\n return { parsed: false, reason: getErrorMessage(error) };\n }\n}\n\n/** The parse reason is stripped too: V8 quotes the offending input verbatim in it. */\nfunction notJsonMessage(body: string, reason: string): string {\n const opening = truncateText(body.trim(), EXCERPT);\n const said = stripTerminalControls(reason);\n return `What arrived on standard input is not JSON: ${said}. It began: ${opening}`;\n}\n\nfunction refusedByContract(problems: string[]): string {\n return `The configuration on standard input is not one this store accepts: ${namedProblems(problems)}`;\n}\n\n/** The count tells a clipped list from a complete one. */\nfunction namedProblems(problems: string[]): string {\n const named = problems.slice(0, PROBLEMS_NAMED).join(\"; \");\n const elided = problems.length - PROBLEMS_NAMED;\n return elided > 0 ? `${named} (and ${elided} more)` : named;\n}\n","import type { Readable } from \"node:stream\";\n\n/** Async iteration rather than `readFileSync(\"/dev/stdin\")`, which is not portable. */\nexport async function readAllOf(stream: Readable): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of stream) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));\n }\n\n return Buffer.concat(chunks).toString(\"utf-8\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,aAAa;;;ACUf,IAAM,gBACX;AAEK,IAAM,sBACX;AAGF,IAAM,UAAU;AAMhB,IAAM,iBAAiB;AAMhB,SAAS,iBAAiB,MAA4B;AAC3D,MAAI,KAAK,KAAK,MAAM,GAAI,QAAO,EAAE,IAAI,OAAO,OAAO,cAAc;AAEjE,QAAM,OAAO,SAAS,IAAI;AAC1B,MAAI,CAAC,KAAK,OAAQ,QAAO,EAAE,IAAI,OAAO,OAAO,eAAe,MAAM,KAAK,MAAM,EAAE;AAE/E,QAAM,SAAS,6BAA6B,UAAU,KAAK,KAAK;AAChE,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO,EAAE,IAAI,OAAO,OAAO,kBAAkB,gBAAgB,OAAO,KAAK,CAAC,EAAE;AAAA,EAC9E;AAEA,SAAO,EAAE,IAAI,MAAM,SAAS,OAAO,KAAK;AAC1C;AAMA,SAAS,SAAS,MAAwB;AACxC,MAAI;AACF,WAAO,EAAE,QAAQ,MAAM,OAAO,KAAK,MAAM,IAAI,EAAE;AAAA,EACjD,SAAS,OAAO;AACd,WAAO,EAAE,QAAQ,OAAO,QAAQ,gBAAgB,KAAK,EAAE;AAAA,EACzD;AACF;AAGA,SAAS,eAAe,MAAc,QAAwB;AAC5D,QAAM,UAAU,aAAa,KAAK,KAAK,GAAG,OAAO;AACjD,QAAM,OAAO,sBAAsB,MAAM;AACzC,SAAO,+CAA+C,IAAI,eAAe,OAAO;AAClF;AAEA,SAAS,kBAAkB,UAA4B;AACrD,SAAO,sEAAsE,cAAc,QAAQ,CAAC;AACtG;AAGA,SAAS,cAAc,UAA4B;AACjD,QAAM,QAAQ,SAAS,MAAM,GAAG,cAAc,EAAE,KAAK,IAAI;AACzD,QAAM,SAAS,SAAS,SAAS;AACjC,SAAO,SAAS,IAAI,GAAG,KAAK,SAAS,MAAM,WAAW;AACxD;;;ACpEA,eAAsB,UAAU,QAAmC;AACjE,QAAM,SAAmB,CAAC;AAC1B,mBAAiB,SAAS,QAAQ;AAChC,WAAO,KAAK,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,KAAK,OAAO,KAAK,CAAC,CAAC;AAAA,EACzE;AAEA,SAAO,OAAO,OAAO,MAAM,EAAE,SAAS,OAAO;AAC/C;;;AFuBA,SAAS,aAAa,SAAsB,YAA0C;AACpF,QAAM,EAAE,YAAY,IAAI;AACxB,SAAO;AAAA,IACL,GAAI,UAAU,WAAW,IAAI,CAAC,qBAAqB,WAAW,CAAC,IAAI,CAAC;AAAA,IACpE,GAAI,WAAW,SAAS,IAAI,CAAC,uBAAuB,UAAU,CAAC,IAAI,CAAC;AAAA,EACtE;AACF;AAEA,SAAS,UAAU,aAAwD;AACzE,SAAO,gBAAgB,UAAa,cAAc,WAAW;AAC/D;AAEA,SAAS,gBAAgB,SAAgC;AACvD,SAAO,aAAa,QAAQ,MAAM,EAC/B,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM,MAAM,YAAY,OAAO,EAC/C,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE;AACrB;AAEA,IAAqB,QAArB,MAAqB,eAAc,YAAY;AAAA,EAC7C,OAAO,UAAU;AAAA,EAEjB,OAAO,cACL;AAAA,EAEF,OAAO,QAAQ;AAAA,IACb,OAAO,MAAM,QAAQ;AAAA,MACnB,aACE;AAAA,MACF,SAAS;AAAA,IACX,CAAC;AAAA,IACD,UAAU,aAAa;AAAA,EACzB;AAAA,EAEA,OAAO,WAAW;AAAA,IAChB;AAAA,IACA;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,MAAK;AAGxC,QAAI,CAAC,MAAM,OAAO;AAChB,YAAM,gBAAgB,gBAAgB,MAAM,QAAQ;AACpD,YAAM,KAAK,qCAAqC,aAAa;AAC7D,YAAM;AAAA,QAA8B,QAAQ,IAAI;AAAA,QAAG;AAAA,QAAS;AAAA,QAAe,CAAC,YAC1E,KAAK,MAAM,SAAS,EAAE,MAAM,WAAW,aAAa,CAAC;AAAA,MACvD;AACA,YAAM,KAAK,qBAAqB,QAAQ,IAAI,CAAC;AAC7C,YAAM,KAAK,4BAA4B,QAAQ,IAAI,CAAC;AAAA,IACtD;AAEA,UAAM,EAAE,SAAS,QAAQ,IAAI,MAAM,QAC/B,MAAM,KAAK,gBAAgB,IAC3B,MAAM,KAAK,wBAAwB;AAEvC,UAAM,YAAY,MAAM,kBAAkB,OAAO;AACjD,QAAI,CAAC,UAAU,IAAI;AACjB,WAAK,MAAM,UAAU,OAAO,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IACxD;AAEA,SAAK,aAAa,UAAU,EAAE;AAE9B,eAAW,UAAU,QAAS,MAAK,MAAM;AAAA,EAC3C;AAAA;AAAA,EAGA,MAAc,4BAA4B,KAA4B;AACpE,UAAM,CAAC,OAAO,IAAI,MAAM,2BAA2B,GAAG;AACtD,QAAI,YAAY,OAAW,MAAK,MAAM,SAAS,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,EAC3E;AAAA,EAEA,MAAc,0BAAqD;AACjE,UAAM,WAAW,MAAM,2BAA2B,QAAQ,IAAI,CAAC;AAC/D,QAAI,CAAC,SAAS,IAAI;AAChB,WAAK,MAAM,SAAS,OAAO,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IACvD;AAEA,SAAK,oBAAoB,SAAS,OAAO;AACzC,SAAK,IAAI,WAAW,SAAS,MAAM,oBAAoB,SAAS,MAAM,kBAAkB;AAExF,WAAO;AAAA,MACL,SAAS,SAAS;AAAA,MAClB,SAAS,aAAa,SAAS,SAAS,SAAS,UAAU;AAAA,IAC7D;AAAA,EACF;AAAA;AAAA,EAGQ,oBAAoB,SAA4B;AACtD,UAAM,UAAU,gBAAgB,OAAO;AACvC,QAAI,QAAQ,SAAS,GAAG;AACtB,WAAK,MAAM,0BAA0B,OAAO,GAAG,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IAC3E;AAAA,EACF;AAAA;AAAA,EAGA,MAAc,kBAA6C;AACzD,QAAI,QAAQ,MAAM,OAAO;AACvB,WAAK,MAAM,qBAAqB,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IAC5D;AAEA,UAAM,OAAqB,iBAAiB,MAAM,UAAU,QAAQ,KAAK,CAAC;AAC1E,QAAI,CAAC,KAAK,IAAI;AACZ,WAAK,MAAM,KAAK,OAAO,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IACnD;AAEA,WAAO,EAAE,SAAS,KAAK,SAAS,SAAS,CAAC,EAAE;AAAA,EAC9C;AAAA,EAEQ,aAAa,IAAkB;AACrC,SAAK,WAAW,aAAa,EAAE,EAAE;AACjC,eAAW,eAAe,yBAAyB,EAAE,GAAG;AACtD,WAAK,IAAI,WAAW;AAAA,IACtB;AAAA,EACF;AACF;","names":[]}
@@ -7,32 +7,30 @@ import {
7
7
  } from "../chunk-P6CYS4JK.js";
8
8
  import {
9
9
  summaryPanelBlock
10
- } from "../chunk-H5E6IO2L.js";
10
+ } from "../chunk-6HJVH27C.js";
11
11
  import {
12
12
  lazyGateDeps,
13
13
  mutateGlobal,
14
14
  propagateGlobalRemoval
15
- } from "../chunk-R7GKQBZJ.js";
16
- import "../chunk-REHVGFJE.js";
15
+ } from "../chunk-SNXEYAFP.js";
16
+ import "../chunk-Q4NWATGH.js";
17
17
  import {
18
18
  loadAgentDefs
19
- } from "../chunk-7BHDKEGK.js";
20
- import "../chunk-IXVGBUWI.js";
19
+ } from "../chunk-DQB3E2SX.js";
20
+ import "../chunk-SI2LLEIR.js";
21
21
  import {
22
22
  listAgentFilesOf,
23
23
  splitAgentsByProvenance
24
- } from "../chunk-EFXVYQGT.js";
24
+ } from "../chunk-GNMRXXRY.js";
25
25
  import "../chunk-KIK5EZYD.js";
26
- import "../chunk-FQF6VHO3.js";
26
+ import "../chunk-ICHWAFAC.js";
27
27
  import {
28
+ BaseCommand,
29
+ EXIT_CODES,
28
30
  providerFlag,
29
31
  providerNamedBy,
30
32
  refuseAnAmbiguousInstallation
31
- } from "../chunk-ORO2T4K2.js";
32
- import {
33
- BaseCommand,
34
- EXIT_CODES
35
- } from "../chunk-IAQFZFWD.js";
33
+ } from "../chunk-37QFHJUW.js";
36
34
  import {
37
35
  ConfigLoadError,
38
36
  INFO_MESSAGES,
@@ -40,6 +38,7 @@ import {
40
38
  agentCodec,
41
39
  buildMarketplacePluginRef,
42
40
  configFileRemoved,
41
+ declaresNoContent,
43
42
  directoryExists,
44
43
  fileExists,
45
44
  getErrorMessage,
@@ -68,17 +67,17 @@ import {
68
67
  uninstallNeedsTerminal,
69
68
  uninstallSkillMetadataUnreadable,
70
69
  unmarkedAgentsKept
71
- } from "../chunk-E45IT3HC.js";
70
+ } from "../chunk-YM3VEDAP.js";
72
71
  import {
73
72
  plural
74
- } from "../chunk-AIBVAYHS.js";
73
+ } from "../chunk-TG3SPPZY.js";
75
74
  import {
76
75
  CLAUDE_DIR,
77
76
  DEFAULT_BRANDING,
78
77
  EJECT_SOURCE,
79
78
  STANDARD_FILES,
80
79
  isActiveAt
81
- } from "../chunk-WUSEZFER.js";
80
+ } from "../chunk-U46LYYRA.js";
82
81
  import "../chunk-GHHJYNAN.js";
83
82
 
84
83
  // src/cli/commands/uninstall.tsx
@@ -485,6 +484,8 @@ async function readSourceFolder(folder, projectDir, provider, onConfigLoadFailed
485
484
  onConfigLoadFailed
486
485
  )
487
486
  ]);
487
+ const isTheUsersFile = config !== null && declaresNoContent(config) && !isHomeDirectory(projectDir);
488
+ if (isTheUsersFile) return { ...folder, manifestFiles: [], config: null };
488
489
  return { ...folder, manifestFiles, config };
489
490
  }
490
491
  async function manifestFilesIn(dir) {