agents-inc 0.170.1 → 0.170.2

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 (163) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/{chunk-BMRUNMPV.js → chunk-2YA4DDRM.js} +35 -35
  3. package/dist/chunk-2YA4DDRM.js.map +1 -0
  4. package/dist/{chunk-44TE3RKH.js → chunk-3ED3KHHD.js} +5 -4
  5. package/dist/chunk-3ED3KHHD.js.map +1 -0
  6. package/dist/{chunk-3G7X2WKI.js → chunk-5BNX73OU.js} +18 -38
  7. package/dist/chunk-5BNX73OU.js.map +1 -0
  8. package/dist/{chunk-7RDMTR64.js → chunk-66AEVERM.js} +785 -256
  9. package/dist/chunk-66AEVERM.js.map +1 -0
  10. package/dist/{chunk-PJWGTNOX.js → chunk-7C3PFRBU.js} +144 -186
  11. package/dist/chunk-7C3PFRBU.js.map +1 -0
  12. package/dist/{chunk-52HDHJ7I.js → chunk-AUNRHWH4.js} +32 -21
  13. package/dist/chunk-AUNRHWH4.js.map +1 -0
  14. package/dist/{chunk-KOLDW6SF.js → chunk-BBDGYJHX.js} +2 -2
  15. package/dist/chunk-BBDGYJHX.js.map +1 -0
  16. package/dist/{chunk-SZYQISA2.js → chunk-ELV5WDS3.js} +43 -29
  17. package/dist/chunk-ELV5WDS3.js.map +1 -0
  18. package/dist/{chunk-MQ6CGZNJ.js → chunk-GAKVZNTX.js} +1879 -2019
  19. package/dist/chunk-GAKVZNTX.js.map +1 -0
  20. package/dist/chunk-GEMW5RQ2.js +1169 -0
  21. package/dist/chunk-GEMW5RQ2.js.map +1 -0
  22. package/dist/{chunk-NQW25DCF.js → chunk-GHHJYNAN.js} +1 -7
  23. package/dist/chunk-GHHJYNAN.js.map +1 -0
  24. package/dist/{chunk-WTWMGH2C.js → chunk-HACRR422.js} +2 -2
  25. package/dist/chunk-HACRR422.js.map +1 -0
  26. package/dist/{chunk-F2BHT5C4.js → chunk-IWY5IR4F.js} +129 -151
  27. package/dist/chunk-IWY5IR4F.js.map +1 -0
  28. package/dist/{chunk-JFLVEFFP.js → chunk-KIK5EZYD.js} +1 -1
  29. package/dist/chunk-KIK5EZYD.js.map +1 -0
  30. package/dist/{chunk-USVBYQSQ.js → chunk-O4LN3HFI.js} +16 -6
  31. package/dist/chunk-O4LN3HFI.js.map +1 -0
  32. package/dist/{chunk-RIPSGNLU.js → chunk-OCAVW6N5.js} +3 -3
  33. package/dist/chunk-OCAVW6N5.js.map +1 -0
  34. package/dist/{chunk-4AAOOAIN.js → chunk-P6CYS4JK.js} +2 -2
  35. package/dist/chunk-P6CYS4JK.js.map +1 -0
  36. package/dist/chunk-PLFANHRZ.js +35 -0
  37. package/dist/chunk-PLFANHRZ.js.map +1 -0
  38. package/dist/{chunk-6ZRH5RHC.js → chunk-PMUZR4XO.js} +4 -4
  39. package/dist/chunk-PMUZR4XO.js.map +1 -0
  40. package/dist/{chunk-F5EBEATU.js → chunk-PSUTNOQ2.js} +34 -46
  41. package/dist/chunk-PSUTNOQ2.js.map +1 -0
  42. package/dist/chunk-RIK45Q4I.js +103 -0
  43. package/dist/chunk-RIK45Q4I.js.map +1 -0
  44. package/dist/{chunk-HED2DAXZ.js → chunk-THO7LO5B.js} +5 -5
  45. package/dist/chunk-THO7LO5B.js.map +1 -0
  46. package/dist/{chunk-OYJQUA3D.js → chunk-YGDWHDOY.js} +31 -13
  47. package/dist/chunk-YGDWHDOY.js.map +1 -0
  48. package/dist/{chunk-NCWDK6L7.js → chunk-YXKTY5WM.js} +254 -379
  49. package/dist/chunk-YXKTY5WM.js.map +1 -0
  50. package/dist/{chunk-NEZ4OAOL.js → chunk-ZEGM3MVR.js} +3 -5
  51. package/dist/chunk-ZEGM3MVR.js.map +1 -0
  52. package/dist/commands/build/marketplace.js +46 -46
  53. package/dist/commands/build/marketplace.js.map +1 -1
  54. package/dist/commands/build/plugins.js +25 -28
  55. package/dist/commands/build/plugins.js.map +1 -1
  56. package/dist/commands/compile.js +87 -178
  57. package/dist/commands/compile.js.map +1 -1
  58. package/dist/commands/doctor.js +510 -360
  59. package/dist/commands/doctor.js.map +1 -1
  60. package/dist/commands/edit.js +451 -357
  61. package/dist/commands/edit.js.map +1 -1
  62. package/dist/commands/eject.js +144 -125
  63. package/dist/commands/eject.js.map +1 -1
  64. package/dist/commands/init.js +20 -27
  65. package/dist/commands/list.js +39 -55
  66. package/dist/commands/list.js.map +1 -1
  67. package/dist/commands/new/marketplace.js +6 -11
  68. package/dist/commands/new/marketplace.js.map +1 -1
  69. package/dist/commands/search.js +35 -32
  70. package/dist/commands/search.js.map +1 -1
  71. package/dist/commands/share.js +17 -77
  72. package/dist/commands/share.js.map +1 -1
  73. package/dist/commands/uninstall.js +159 -222
  74. package/dist/commands/uninstall.js.map +1 -1
  75. package/dist/commands/update.js +9 -32
  76. package/dist/commands/update.js.map +1 -1
  77. package/dist/components/common/prompt-confirm.js +2 -2
  78. package/dist/components/common/removal-plan-confirm.js +2 -2
  79. package/dist/components/common/scroll-affordance.js +2 -2
  80. package/dist/components/common/select-list.js +2 -2
  81. package/dist/components/common/skill-agent-summary.js +4 -4
  82. package/dist/components/common/spinner.js +2 -4
  83. package/dist/components/common/summary-panel.js +5 -5
  84. package/dist/components/common/summary-panel.js.map +1 -1
  85. package/dist/config-exports.js +7 -3
  86. package/dist/config-exports.js.map +1 -1
  87. package/dist/hooks/init.js +18 -19
  88. package/dist/hooks/init.js.map +1 -1
  89. package/dist/index.js.map +1 -1
  90. package/dist/load-agent-defs-6QUUMGHK.js +14 -0
  91. package/dist/recompile-project-agents-I33KQJFB.js +65 -0
  92. package/dist/recompile-project-agents-I33KQJFB.js.map +1 -0
  93. package/dist/{source-loader-C5SQXZXI.js → source-loader-TTJVW2ER.js} +5 -5
  94. package/dist/src/agents/developer/ai-developer/playbook.md +2 -5
  95. package/dist/src/agents/developer/api-developer/playbook.md +2 -5
  96. package/dist/src/agents/developer/cli-developer/playbook.md +2 -5
  97. package/dist/src/agents/developer/web-developer/playbook.md +2 -5
  98. package/dist/src/agents/meta/agent-summoner/output.md +2 -2
  99. package/dist/src/agents/meta/agent-summoner/playbook.md +1 -13
  100. package/dist/src/agents/meta/codex-keeper/critical-requirements.md +2 -5
  101. package/dist/src/agents/meta/convention-keeper/critical-requirements.md +2 -4
  102. package/dist/src/agents/tester/ai-tester/critical-requirements.md +1 -2
  103. package/dist/src/agents/tester/ai-tester/playbook.md +2 -0
  104. package/dist/src/agents/tester/api-tester/critical-requirements.md +1 -2
  105. package/dist/src/agents/tester/api-tester/playbook.md +2 -0
  106. package/dist/src/agents/tester/cli-tester/critical-requirements.md +1 -2
  107. package/dist/src/agents/tester/cli-tester/playbook.md +2 -0
  108. package/dist/src/agents/tester/web-tester/critical-requirements.md +1 -2
  109. package/dist/src/agents/tester/web-tester/playbook.md +2 -0
  110. package/package.json +9 -8
  111. package/src/agents/developer/ai-developer/playbook.md +2 -5
  112. package/src/agents/developer/api-developer/playbook.md +2 -5
  113. package/src/agents/developer/cli-developer/playbook.md +2 -5
  114. package/src/agents/developer/web-developer/playbook.md +2 -5
  115. package/src/agents/meta/agent-summoner/output.md +2 -2
  116. package/src/agents/meta/agent-summoner/playbook.md +1 -13
  117. package/src/agents/meta/codex-keeper/critical-requirements.md +2 -5
  118. package/src/agents/meta/convention-keeper/critical-requirements.md +2 -4
  119. package/src/agents/tester/ai-tester/critical-requirements.md +1 -2
  120. package/src/agents/tester/ai-tester/playbook.md +2 -0
  121. package/src/agents/tester/api-tester/critical-requirements.md +1 -2
  122. package/src/agents/tester/api-tester/playbook.md +2 -0
  123. package/src/agents/tester/cli-tester/critical-requirements.md +1 -2
  124. package/src/agents/tester/cli-tester/playbook.md +2 -0
  125. package/src/agents/tester/web-tester/critical-requirements.md +1 -2
  126. package/src/agents/tester/web-tester/playbook.md +2 -0
  127. package/src/schemas/project-config.schema.json +0 -3
  128. package/src/schemas/project-source-config.schema.json +0 -6
  129. package/dist/chunk-3G7X2WKI.js.map +0 -1
  130. package/dist/chunk-44TE3RKH.js.map +0 -1
  131. package/dist/chunk-4AAOOAIN.js.map +0 -1
  132. package/dist/chunk-52HDHJ7I.js.map +0 -1
  133. package/dist/chunk-6HNXYYVF.js +0 -373
  134. package/dist/chunk-6HNXYYVF.js.map +0 -1
  135. package/dist/chunk-6ZRH5RHC.js.map +0 -1
  136. package/dist/chunk-7RDMTR64.js.map +0 -1
  137. package/dist/chunk-BMRUNMPV.js.map +0 -1
  138. package/dist/chunk-CLPUWOSA.js +0 -46
  139. package/dist/chunk-CLPUWOSA.js.map +0 -1
  140. package/dist/chunk-F2BHT5C4.js.map +0 -1
  141. package/dist/chunk-F5EBEATU.js.map +0 -1
  142. package/dist/chunk-HED2DAXZ.js.map +0 -1
  143. package/dist/chunk-JFLVEFFP.js.map +0 -1
  144. package/dist/chunk-KOLDW6SF.js.map +0 -1
  145. package/dist/chunk-MQ6CGZNJ.js.map +0 -1
  146. package/dist/chunk-NCWDK6L7.js.map +0 -1
  147. package/dist/chunk-NEZ4OAOL.js.map +0 -1
  148. package/dist/chunk-NIHUOWE4.js +0 -106
  149. package/dist/chunk-NIHUOWE4.js.map +0 -1
  150. package/dist/chunk-NQW25DCF.js.map +0 -1
  151. package/dist/chunk-OYJQUA3D.js.map +0 -1
  152. package/dist/chunk-PJWGTNOX.js.map +0 -1
  153. package/dist/chunk-RIPSGNLU.js.map +0 -1
  154. package/dist/chunk-SZYQISA2.js.map +0 -1
  155. package/dist/chunk-USVBYQSQ.js.map +0 -1
  156. package/dist/chunk-V3KTSP3Q.js +0 -940
  157. package/dist/chunk-V3KTSP3Q.js.map +0 -1
  158. package/dist/chunk-WTWMGH2C.js.map +0 -1
  159. package/dist/load-agent-defs-YMDWBFDP.js +0 -14
  160. package/dist/recompile-project-agents-SZ76WNTW.js +0 -18
  161. package/dist/source-loader-C5SQXZXI.js.map +0 -1
  162. /package/dist/{load-agent-defs-YMDWBFDP.js.map → load-agent-defs-6QUUMGHK.js.map} +0 -0
  163. /package/dist/{recompile-project-agents-SZ76WNTW.js.map → source-loader-TTJVW2ER.js.map} +0 -0
@@ -1,36 +1,35 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  RemovalPlanConfirm
4
- } from "../chunk-USVBYQSQ.js";
4
+ } from "../chunk-O4LN3HFI.js";
5
5
  import {
6
6
  promptConfirm
7
- } from "../chunk-4AAOOAIN.js";
7
+ } from "../chunk-P6CYS4JK.js";
8
8
  import "../chunk-OZXAJNLA.js";
9
9
  import {
10
10
  lazyGateDeps,
11
11
  mutateGlobal,
12
12
  propagateGlobalRemoval
13
- } from "../chunk-7RDMTR64.js";
14
- import "../chunk-F2BHT5C4.js";
13
+ } from "../chunk-66AEVERM.js";
14
+ import "../chunk-IWY5IR4F.js";
15
15
  import {
16
16
  loadAgentDefs
17
- } from "../chunk-HED2DAXZ.js";
18
- import "../chunk-3G7X2WKI.js";
17
+ } from "../chunk-THO7LO5B.js";
18
+ import "../chunk-5BNX73OU.js";
19
19
  import {
20
20
  listAgentFilesOf,
21
21
  splitAgentsByProvenance
22
- } from "../chunk-BMRUNMPV.js";
23
- import "../chunk-JFLVEFFP.js";
22
+ } from "../chunk-2YA4DDRM.js";
23
+ import "../chunk-KIK5EZYD.js";
24
24
  import {
25
25
  providerFlag,
26
26
  providerNamedBy,
27
27
  refuseAnAmbiguousInstallation
28
- } from "../chunk-RIPSGNLU.js";
28
+ } from "../chunk-OCAVW6N5.js";
29
29
  import {
30
30
  BaseCommand,
31
31
  EXIT_CODES
32
- } from "../chunk-V3KTSP3Q.js";
33
- import "../chunk-CLPUWOSA.js";
32
+ } from "../chunk-GEMW5RQ2.js";
34
33
  import {
35
34
  ConfigLoadError,
36
35
  INFO_MESSAGES,
@@ -52,6 +51,7 @@ import {
52
51
  localSkillsRemoval,
53
52
  notInstalledHere,
54
53
  parseMarketplacePluginRef,
54
+ pluginLeftRegistered,
55
55
  providerInUse,
56
56
  readForkedFromMetadata,
57
57
  registeredProjectUpdateSkipped,
@@ -64,20 +64,23 @@ import {
64
64
  sourceRootOf,
65
65
  uninstallConfigUnreadable,
66
66
  uninstallNeedsTerminal,
67
+ uninstallSkillMetadataUnreadable,
67
68
  unmarkedAgentsKept
68
- } from "../chunk-MQ6CGZNJ.js";
69
- import "../chunk-52HDHJ7I.js";
69
+ } from "../chunk-GAKVZNTX.js";
70
+ import {
71
+ plural
72
+ } from "../chunk-AUNRHWH4.js";
70
73
  import {
71
74
  CLAUDE_DIR,
72
75
  DEFAULT_BRANDING,
73
76
  EJECT_SOURCE,
74
77
  STANDARD_FILES
75
- } from "../chunk-PJWGTNOX.js";
76
- import "../chunk-NQW25DCF.js";
78
+ } from "../chunk-7C3PFRBU.js";
79
+ import "../chunk-GHHJYNAN.js";
77
80
 
78
81
  // src/cli/commands/uninstall.tsx
79
82
  import "react";
80
- import { partition } from "remeda";
83
+ import { unique } from "remeda";
81
84
  import path from "path";
82
85
  import { Flags } from "@oclif/core";
83
86
  import { jsx } from "react/jsx-runtime";
@@ -101,18 +104,18 @@ function pluginsEntry(target) {
101
104
  return [{ kind: "plugins", pluginsDir: target.pluginsDir, names: [...target.cliPluginNames] }];
102
105
  }
103
106
  function localSkillsEntry(target) {
104
- if (!target.hasLocalSkills) return [];
105
- return [{ kind: "skills", skillsDir: target.skillsDir }];
107
+ if (target.cliSkills.length === 0) return [];
108
+ return [{ kind: "skills", skillsDir: target.skillsDir, skillNames: [...target.cliSkills] }];
106
109
  }
107
110
  function compiledAgentsEntry(target) {
108
- if (!target.hasLocalAgents) return [];
109
111
  const agentNames = identifiableAgents(target);
110
112
  if (agentNames.length === 0) return [];
111
113
  return [{ kind: "agents", agentsDir: target.agentsDir, agentNames, codec: target.agentCodec }];
112
114
  }
113
115
  function identifiableAgents(target) {
114
- if (target.configuredAgents.length > 0) return target.configuredAgents;
115
- return target.markedAgents;
116
+ const agentFiles = /* @__PURE__ */ new Set([...target.markedAgents, ...target.unmarkedAgents]);
117
+ const configuredWithAFile = target.configuredAgents.filter((name) => agentFiles.has(name));
118
+ return unique([...configuredWithAFile, ...target.markedAgents]);
116
119
  }
117
120
  function configManifestEntries(target) {
118
121
  const { dir, manifestFiles } = target.sourceFolder;
@@ -180,17 +183,7 @@ function sectionWithItems(label, items) {
180
183
  }
181
184
  var UNINSTALL_CONFIRM_MESSAGE = "Are you sure you want to uninstall?";
182
185
  var Uninstall = class _Uninstall extends BaseCommand {
183
- /**
184
- * The name this run prints itself under, resolved once in {@link run} because three separate
185
- * lines carry it: the heading, the sign-off, and the warning naming the tool a preserved
186
- * directory was not created by. The last of those sits three calls below the resolution, and
187
- * threading a display string through `executeUninstall` -> `removeLocalFiles` ->
188
- * `removePlannedSkills` would widen three signatures to deliver one word.
189
- *
190
- * A plain `string` holding the shipped default rather than an optional every reader would have
191
- * to answer for. `run` replaces it before the first line is printed, so what a user sees is
192
- * always what their configuration says.
193
- */
186
+ /** Replaced in `run` before anything prints. */
194
187
  brandingName = DEFAULT_BRANDING.NAME;
195
188
  static summary = `Remove ${DEFAULT_BRANDING.NAME} from this project`;
196
189
  static description = `Uninstall ${DEFAULT_BRANDING.NAME} from this project. Removes CLI-managed skills (matched by marketplace), compiled agents, plugins, and the config manifest (config.ts + config-types.ts) this project keeps. User-created content is preserved.`;
@@ -206,38 +199,32 @@ var Uninstall = class _Uninstall extends BaseCommand {
206
199
  }),
207
200
  provider: providerFlag()
208
201
  };
209
- /**
210
- * Starts at any terminal size: a plan and a one-line confirm fit any terminal, and this command
211
- * is the way out of every state, so a small window must not hold up an uninstall.
212
- */
213
202
  async ensureTerminalSize() {
214
203
  }
215
204
  async run() {
216
205
  const { flags } = await this.parse(_Uninstall);
217
206
  const projectDir = process.cwd();
207
+ const namedProvider = providerNamedBy(flags.provider);
218
208
  await refuseAnAmbiguousInstallation(
219
209
  projectDir,
220
210
  "uninstall",
221
- providerNamedBy(flags.provider),
211
+ namedProvider,
222
212
  (message) => this.error(message, { exit: EXIT_CODES.INVALID_ARGS })
223
213
  );
224
214
  this.brandingName = await this.resolveBrandingName(projectDir);
225
215
  this.printHeader();
226
- const target = await detectUninstallTarget(
227
- projectDir,
228
- (failure) => this.warn(uninstallConfigUnreadable(failure))
229
- );
216
+ const target = await detectUninstallTarget(projectDir, {
217
+ onConfigLoadFailed: (failure) => this.warn(uninstallConfigUnreadable(failure)),
218
+ // Aborts: guessing would either remove the user's skill or keep this CLI's.
219
+ onSkillMetadataUnreadable: (metadataPath) => this.error(uninstallSkillMetadataUnreadable(metadataPath), { exit: EXIT_CODES.ERROR })
220
+ });
230
221
  const plan = buildRemovalPlan(target);
231
222
  if (!hasAnythingToRemove(plan)) {
232
223
  this.reportNothingToUninstall();
233
224
  return;
234
225
  }
235
- const confirmed = flags.yes ? this.printRemovalPlan(plan) : await this.confirmRemoval(plan);
236
- if (!confirmed) {
237
- this.log("");
238
- this.log("Uninstall cancelled");
239
- this.exit(EXIT_CODES.CANCELLED);
240
- }
226
+ const approved = await this.removalApproved(plan, flags.yes, namedProvider);
227
+ if (!approved) this.cancelUninstall();
241
228
  await this.executeUninstall(plan, target, projectDir);
242
229
  this.reportSuccess();
243
230
  }
@@ -253,6 +240,16 @@ var Uninstall = class _Uninstall extends BaseCommand {
253
240
  this.log("");
254
241
  this.log(INFO_MESSAGES.NO_CHANGES_MADE);
255
242
  }
243
+ async removalApproved(plan, skipConfirmation, namedProvider) {
244
+ if (!skipConfirmation) return this.confirmRemoval(plan, namedProvider);
245
+ this.printRemovalPlan(plan);
246
+ return true;
247
+ }
248
+ cancelUninstall() {
249
+ this.log("");
250
+ this.log("Uninstall cancelled");
251
+ this.exit(EXIT_CODES.CANCELLED);
252
+ }
256
253
  printRemovalPlan(plan) {
257
254
  this.log(UNINSTALL_PLAN.PREVIEW_HEADING);
258
255
  this.log("");
@@ -267,11 +264,10 @@ var Uninstall = class _Uninstall extends BaseCommand {
267
264
  this.log(statement);
268
265
  }
269
266
  this.log("");
270
- return true;
271
267
  }
272
- async confirmRemoval(plan) {
268
+ async confirmRemoval(plan, namedProvider) {
273
269
  if (!process.stdin.isTTY) {
274
- this.error(uninstallNeedsTerminal(), { exit: EXIT_CODES.ERROR });
270
+ this.error(uninstallNeedsTerminal(namedProvider), { exit: EXIT_CODES.ERROR });
275
271
  }
276
272
  const outcome = await promptConfirm(({ onConfirm, onCancel }) => /* @__PURE__ */ jsx(
277
273
  RemovalPlanConfirm,
@@ -290,20 +286,15 @@ var Uninstall = class _Uninstall extends BaseCommand {
290
286
  const isGlobalUninstall = isHomeDirectory(projectDir);
291
287
  const propagation = isGlobalUninstall ? await this.prepareGlobalPropagation(target, projectDir) : null;
292
288
  await this.removePlannedPlugins(planEntry(plan, "plugins"), target.config, projectDir);
293
- try {
294
- await this.removeLocalFiles(plan, target);
295
- } catch (error) {
296
- this.log("Failed to remove local files");
297
- this.error(getErrorMessage(error), {
298
- exit: EXIT_CODES.ERROR
299
- });
300
- }
301
- if (isGlobalUninstall) {
302
- if (propagation) {
303
- await this.updateRegisteredProjects(propagation);
304
- }
289
+ await this.removeLocalFilesOrFail(plan, target);
290
+ if (!isGlobalUninstall) {
291
+ await this.deregisterProject(projectDir);
305
292
  return;
306
293
  }
294
+ if (propagation) await this.updateRegisteredProjects(propagation);
295
+ }
296
+ /** Degrades: a missing or corrupt global config must never fail the uninstall. */
297
+ async deregisterProject(projectDir) {
307
298
  try {
308
299
  await mutateGlobal({ kind: "deregister-project", projectDir }, lazyGateDeps(projectDir));
309
300
  } catch (error) {
@@ -311,25 +302,8 @@ var Uninstall = class _Uninstall extends BaseCommand {
311
302
  }
312
303
  }
313
304
  /**
314
- * Loads what updating registered projects needs (global config with its
315
- * projects[] registry, skills matrix, agent definitions) BEFORE the global
316
- * the config manifest is deleted — source resolution reads that config.
317
- * Returns null when nothing is registered or loading fails; a load failure
318
- * warns and never aborts the uninstall.
319
- *
320
- * `skipExtraSources: true` is NOT a divergence from a full multi-source
321
- * load: extra-source loading only annotates each skill's
322
- * `availableSources`/`activeSource` — it never adds
323
- * skills or categories to the matrix, and the config-types writer never reads
324
- * those annotations, so the regenerated project types are byte-identical
325
- * either way (pinned by the skipExtraSources parity test in
326
- * local-installer.test.ts). Skipping avoids fetching every registered extra
327
- * source (network on a cold cache, plus unreachable-remote warnings) during
328
- * an uninstall that must never hang or noise-fail on remote state.
329
- *
330
- * `purpose: "upkeep"` because the prune only rewrites projects that are already installed: a
331
- * marketplace that has since lost its manifest must not leave every registered project naming
332
- * the global content this uninstall deletes.
305
+ * A load failure warns and never aborts. `skipExtraSources` cannot change the output (extra
306
+ * sources only annotate skills) and keeps the uninstall off the network.
333
307
  */
334
308
  async prepareGlobalPropagation(target, projectDir) {
335
309
  if (target.config === null || target.registeredProjects.length === 0) return null;
@@ -355,14 +329,7 @@ var Uninstall = class _Uninstall extends BaseCommand {
355
329
  return null;
356
330
  }
357
331
  }
358
- /**
359
- * Prunes the inlined global-scoped config entries from every registered
360
- * project and regenerates its config-types.ts. Runs AFTER the global manifest
361
- * removal so the regenerated project types fall back to the standalone form
362
- * instead of importing from the deleted global config-types.ts. Best-effort:
363
- * unreachable projects are warned and skipped, and no failure here may abort
364
- * the uninstall.
365
- */
332
+ /** Runs after the global manifest is gone, so regenerated types use the standalone form. */
366
333
  async updateRegisteredProjects(propagation) {
367
334
  try {
368
335
  const report = await propagateGlobalRemoval(
@@ -370,18 +337,21 @@ var Uninstall = class _Uninstall extends BaseCommand {
370
337
  { matrix: propagation.matrix, agents: propagation.agents },
371
338
  propagation.provider
372
339
  );
373
- const { updated, unreadable, failed } = report.propagated;
374
- this.reportProjectsOutOfReach(report.propagated);
375
- for (const skippedPath of [...unreadable, ...failed]) {
376
- this.warn(registeredProjectUpdateSkipped(skippedPath));
377
- }
378
- if (updated.length === 0) return;
379
- this.logSuccess(registeredProjectsUpdated(updated.length));
380
- this.reportPropagatedRecompile(report);
340
+ this.reportRegisteredProjectsUpdate(report);
381
341
  } catch (error) {
382
342
  this.warn(registeredProjectsUpdateFailed(getErrorMessage(error)));
383
343
  }
384
344
  }
345
+ reportRegisteredProjectsUpdate(report) {
346
+ const { updated, unreadable, failed } = report.propagated;
347
+ this.reportProjectsOutOfReach(report.propagated);
348
+ for (const skippedPath of [...unreadable, ...failed]) {
349
+ this.warn(registeredProjectUpdateSkipped(skippedPath));
350
+ }
351
+ if (updated.length === 0) return;
352
+ this.logSuccess(registeredProjectsUpdated(updated.length));
353
+ this.reportPropagatedRecompile(report);
354
+ }
385
355
  reportSuccess() {
386
356
  this.log("");
387
357
  this.log(`${this.brandingName} has been uninstalled.`);
@@ -389,10 +359,16 @@ var Uninstall = class _Uninstall extends BaseCommand {
389
359
  this.logSuccess(SUCCESS_MESSAGES.UNINSTALL_COMPLETE);
390
360
  this.log("");
391
361
  }
392
- /**
393
- * Each step acts only when the plan carries its entry, so what the user was shown and
394
- * what this run removes are the same list read twice.
395
- */
362
+ async removeLocalFilesOrFail(plan, target) {
363
+ try {
364
+ await this.removeLocalFiles(plan, target);
365
+ } catch (error) {
366
+ this.log("Failed to remove local files");
367
+ this.error(getErrorMessage(error), {
368
+ exit: EXIT_CODES.ERROR
369
+ });
370
+ }
371
+ }
396
372
  async removeLocalFiles(plan, target) {
397
373
  await this.removePlannedSkills(planEntry(plan, "skills"));
398
374
  await this.removePlannedAgents(planEntry(plan, "agents"));
@@ -401,14 +377,9 @@ var Uninstall = class _Uninstall extends BaseCommand {
401
377
  }
402
378
  const cleanup = await cleanupEmptyDirs(target, planEntries(plan, "config"));
403
379
  this.reportSourceFolderCleanup(cleanup.sourceFolder);
404
- this.reportSourceRootCleanup(target.sourceRoot, cleanup);
405
- if (cleanup.claudeDirRemoved) {
406
- this.logSuccess(`Removed ${CLAUDE_DIR}/`);
407
- } else if (cleanup.claudeDirKept) {
408
- this.log(`Kept ${CLAUDE_DIR}/ (contains user content)`);
409
- }
380
+ this.reportDirCleanup(target.sourceRoot.relName, cleanup.sourceRoot);
381
+ this.reportDirCleanup(CLAUDE_DIR, cleanup.claudeDir);
410
382
  }
411
- /** What became of one source folder: gone, emptied of the CLI's files, or kept for the user's. */
412
383
  reportSourceFolderCleanup(folder) {
413
384
  if (folder.dirRemoved) {
414
385
  this.logSuccess(`Removed ${folder.relName}/`);
@@ -418,30 +389,25 @@ var Uninstall = class _Uninstall extends BaseCommand {
418
389
  this.log(`Kept ${folder.relName}/ (contains user content)`);
419
390
  }
420
391
  }
421
- /** What became of the `.agents-inc/` parent, said out loud in both directions. */
422
- reportSourceRootCleanup(sourceRoot, cleanup) {
423
- if (cleanup.sourceRootRemoved) {
424
- this.logSuccess(`Removed ${sourceRoot.relName}/`);
392
+ reportDirCleanup(relName, cleanup) {
393
+ if (cleanup.removed) {
394
+ this.logSuccess(`Removed ${relName}/`);
425
395
  return;
426
396
  }
427
- if (cleanup.sourceRootKept) {
428
- this.log(`Kept ${sourceRoot.relName}/ (contains user content)`);
397
+ if (cleanup.kept) {
398
+ this.log(`Kept ${relName}/ (contains user content)`);
429
399
  }
430
400
  }
431
401
  async removePlannedPlugins(entry, config, projectDir) {
432
402
  if (!entry) return;
433
403
  this.log("Uninstalling plugins...");
434
404
  try {
435
- const pluginResult = await uninstallPlugins(
436
- entry,
437
- config,
438
- projectDir,
439
- (name) => this.log(` Uninstalled plugin '${name}'`)
440
- );
405
+ const pluginResult = await uninstallPlugins(entry, config, projectDir, {
406
+ onUninstalled: (name) => this.log(` Uninstalled plugin '${name}'`),
407
+ onLeftRegistered: (name, provider) => this.warn(pluginLeftRegistered(name, provider))
408
+ });
441
409
  if (pluginResult.totalUninstalled > 0) {
442
- this.logSuccess(
443
- `Uninstalled ${pluginResult.totalUninstalled} ${pluginResult.totalUninstalled === 1 ? "plugin" : "plugins"}`
444
- );
410
+ this.logSuccess(`Uninstalled ${plural(pluginResult.totalUninstalled, "plugin")}`);
445
411
  }
446
412
  } catch (error) {
447
413
  this.log("Plugin uninstall failed");
@@ -452,26 +418,21 @@ var Uninstall = class _Uninstall extends BaseCommand {
452
418
  }
453
419
  async removePlannedSkills(entry) {
454
420
  if (!entry) return;
455
- const result = await removeMatchingSkills(
421
+ const removedNames = await removeMatchingSkills(
456
422
  entry,
457
- (dirName) => this.log(` Uninstalled skill '${dirName}'`),
458
- (dirName) => this.warn(`Skipping '${dirName}': not created by ${this.brandingName} CLI`)
459
- );
460
- if (result.removedCount === 0) return;
461
- this.logSuccess(
462
- `Removed ${result.removedCount} CLI-installed ${result.removedCount === 1 ? "skill" : "skills"}`
423
+ (dirName) => this.log(` Uninstalled skill '${dirName}'`)
463
424
  );
425
+ if (removedNames.length === 0) return;
426
+ this.logSuccess(`Removed ${plural(removedNames.length, "CLI-installed skill")}`);
464
427
  }
465
428
  async removePlannedAgents(entry) {
466
429
  if (!entry) return;
467
- const result = await removeMatchingAgents(
430
+ const removedNames = await removeMatchingAgents(
468
431
  entry,
469
432
  (agentName) => this.log(` Uninstalled agent '${agentName}'`)
470
433
  );
471
- if (result.removedCount === 0) return;
472
- this.logSuccess(
473
- `Removed ${result.removedCount} compiled ${result.removedCount === 1 ? "agent" : "agents"}`
474
- );
434
+ if (removedNames.length === 0) return;
435
+ this.logSuccess(`Removed ${plural(removedNames.length, "compiled agent")}`);
475
436
  }
476
437
  };
477
438
  function collectConfiguredAgents(config) {
@@ -481,15 +442,14 @@ function collectConfiguredAgents(config) {
481
442
  function getCliInstalledPluginKeys(config) {
482
443
  if (!config?.skills) return /* @__PURE__ */ new Set();
483
444
  const { marketplaceName } = config;
484
- return new Set(
485
- config.skills.flatMap((skill) => [
486
- // Primary key: skill.id@skill.origin
487
- buildMarketplacePluginRef(skill.id, skill.origin),
488
- // Marketplace variant for plugins installed via marketplace where
489
- // skill.origin may differ (e.g., "eject" vs the marketplace name)
490
- ...marketplaceName && skill.origin !== marketplaceName && skill.origin !== EJECT_SOURCE ? [buildMarketplacePluginRef(skill.id, marketplaceName)] : []
491
- ])
492
- );
445
+ return new Set(config.skills.flatMap((skill) => pluginRefsOf(skill, marketplaceName)));
446
+ }
447
+ function pluginRefsOf(skill, marketplaceName) {
448
+ const ownRef = buildMarketplacePluginRef(skill.id, skill.origin);
449
+ if (!marketplaceName || skill.origin === marketplaceName || skill.origin === EJECT_SOURCE) {
450
+ return [ownRef];
451
+ }
452
+ return [ownRef, buildMarketplacePluginRef(skill.id, marketplaceName)];
493
453
  }
494
454
  async function loadUninstallConfig(configPath, projectDir, provider, onLoadFailed) {
495
455
  try {
@@ -527,39 +487,30 @@ function activeConfigOf(config) {
527
487
  agents: config.agents.filter((a) => !a.excluded)
528
488
  };
529
489
  }
530
- async function detectUninstallTarget(projectDir, onConfigLoadFailed) {
490
+ async function detectUninstallTarget(projectDir, handlers) {
531
491
  const pluginsDir = getProjectPluginsDir(projectDir);
532
492
  const { skillsDir, agentsDir } = resolveInstallPaths(projectDir);
533
493
  const claudeDir = path.join(projectDir, CLAUDE_DIR);
534
494
  const provider = providerInUse(projectDir);
535
- const [hasLocalSkills, hasLocalAgents, hasClaudeDir, sourceFolder, agentProvenance] = await Promise.all([
536
- directoryExists(skillsDir),
537
- directoryExists(agentsDir),
495
+ const codec = agentCodec(provider);
496
+ const [cliSkills, hasClaudeDir, sourceFolder, agentProvenance] = await Promise.all([
497
+ skillsThisCliInstalled(skillsDir, handlers.onSkillMetadataUnreadable),
538
498
  directoryExists(claudeDir),
539
499
  readSourceFolder(
540
500
  sourceFolderInUse(projectDir, provider),
541
501
  projectDir,
542
502
  provider,
543
- onConfigLoadFailed
503
+ handlers.onConfigLoadFailed
544
504
  ),
545
- splitAgentsByProvenance(agentsDir, agentCodec(provider))
505
+ splitAgentsByProvenance(agentsDir, codec)
546
506
  ]);
547
507
  const { config } = sourceFolder;
548
- let pluginNames = [];
549
- try {
550
- pluginNames = await listPluginNames(projectDir);
551
- } catch {
552
- }
553
508
  const activeConfig = config === null ? null : activeConfigOf(config);
554
- const configuredAgents = collectConfiguredAgents(activeConfig);
555
- const cliInstalledKeys = getCliInstalledPluginKeys(activeConfig);
556
- const cliPluginNames = thisRunOwnsAnyPlugin(projectDir) ? pluginNames.filter((name) => cliInstalledKeys.has(name)) : [];
509
+ const cliPluginNames = await pluginsThisRunRemoves(projectDir, activeConfig);
557
510
  return {
558
511
  hasPlugins: cliPluginNames.length > 0,
559
- pluginNames,
560
512
  cliPluginNames,
561
- hasLocalSkills,
562
- hasLocalAgents,
513
+ cliSkills,
563
514
  hasClaudeDir,
564
515
  pluginsDir,
565
516
  skillsDir,
@@ -569,71 +520,57 @@ async function detectUninstallTarget(projectDir, onConfigLoadFailed) {
569
520
  sourceRoot: sourceRootOf(projectDir),
570
521
  config,
571
522
  registeredProjects: config?.projects ?? [],
572
- configuredAgents,
573
- agentCodec: agentCodec(provider),
523
+ configuredAgents: collectConfiguredAgents(activeConfig),
524
+ agentCodec: codec,
574
525
  markedAgents: agentProvenance.marked,
575
526
  unmarkedAgents: agentProvenance.unmarked
576
527
  };
577
528
  }
529
+ async function pluginsThisRunRemoves(projectDir, activeConfig) {
530
+ const installed = await listPluginNames(projectDir);
531
+ if (!thisRunOwnsAnyPlugin(projectDir)) return [];
532
+ const cliInstalledKeys = getCliInstalledPluginKeys(activeConfig);
533
+ return installed.filter((name) => cliInstalledKeys.has(name));
534
+ }
578
535
  function thisRunOwnsAnyPlugin(projectDir) {
579
536
  if (isHomeDirectory(projectDir)) return true;
580
537
  return hostAt(projectDir).installsProjectScopedPlugins;
581
538
  }
582
- function shouldRemoveSkill(forkedFrom) {
583
- return forkedFrom !== null;
584
- }
585
- async function removeMatchingSkills(entry, onRemoved, onSkipped) {
586
- const classified = await classifySkillDirs(entry.skillsDir);
587
- const removedNames = await removeClassifiedSkills(
588
- classified.toRemove,
589
- entry.skillsDir,
590
- onRemoved
591
- );
592
- classified.toSkip.forEach((name) => onSkipped?.(name));
593
- const dirCleaned = await cleanupSkillsDir(entry.skillsDir, classified.toSkip.length === 0);
594
- return {
595
- removedCount: removedNames.length,
596
- skippedCount: classified.toSkip.length,
597
- removedNames,
598
- skippedNames: classified.toSkip,
599
- dirCleaned
600
- };
601
- }
602
- async function classifySkillDirs(skillsDir) {
539
+ async function skillsThisCliInstalled(skillsDir, onMetadataUnreadable) {
603
540
  const dirNames = await listDirectories(skillsDir);
604
- const entries = await Promise.all(
541
+ const skills = await Promise.all(
605
542
  dirNames.map(async (name) => ({
606
543
  name,
607
- forkedFrom: await readForkedFromMetadata(path.join(skillsDir, name))
544
+ forkedFrom: await readSkillProvenance(skillsDir, name, onMetadataUnreadable)
608
545
  }))
609
546
  );
610
- const [removable, skippable] = partition(entries, (entry) => shouldRemoveSkill(entry.forkedFrom));
611
- return { toRemove: removable.map((e) => e.name), toSkip: skippable.map((e) => e.name) };
547
+ return skills.filter((skill) => skill.forkedFrom !== null).map((skill) => skill.name);
612
548
  }
613
- async function removeClassifiedSkills(names, skillsDir, onRemoved) {
614
- for (const name of names) {
615
- await remove(path.join(skillsDir, name));
616
- onRemoved?.(name);
549
+ async function readSkillProvenance(skillsDir, dirName, onUnreadable) {
550
+ const skillDir = path.join(skillsDir, dirName);
551
+ try {
552
+ return await readForkedFromMetadata(skillDir);
553
+ } catch {
554
+ return onUnreadable(path.join(skillDir, STANDARD_FILES.METADATA_YAML));
617
555
  }
618
- return names;
619
556
  }
620
- async function cleanupSkillsDir(dir, allRemoved) {
621
- if (!allRemoved) return false;
622
- return removeDirIfEmpty(dir);
557
+ async function removeMatchingSkills(entry, onRemoved) {
558
+ const present = await listDirectories(entry.skillsDir);
559
+ const removedNames = present.filter((name) => entry.skillNames.includes(name));
560
+ for (const name of removedNames) {
561
+ await remove(path.join(entry.skillsDir, name));
562
+ onRemoved(name);
563
+ }
564
+ return removedNames;
623
565
  }
624
566
  async function removeMatchingAgents(entry, onRemoved) {
625
567
  const agentFiles = await listAgentFiles(entry.agentsDir, entry.codec);
626
568
  const removedNames = agentFiles.map((agentFile) => path.basename(agentFile, entry.codec.extension)).filter((agentName) => entry.agentNames.includes(agentName));
627
569
  for (const agentName of removedNames) {
628
570
  await remove(path.join(entry.agentsDir, `${agentName}${entry.codec.extension}`));
629
- onRemoved?.(agentName);
571
+ onRemoved(agentName);
630
572
  }
631
- const dirCleaned = await removeDirIfEmpty(entry.agentsDir);
632
- return {
633
- removedCount: removedNames.length,
634
- removedNames,
635
- dirCleaned
636
- };
573
+ return removedNames;
637
574
  }
638
575
  var SCOPE_OF_AN_UNRECORDED_SKILL = "project";
639
576
  function pluginScopesToSweep(host, primary) {
@@ -652,10 +589,13 @@ async function removePluginWhereverItIsFiled(host, pluginRef, primaryScope, proj
652
589
  }
653
590
  return outcome;
654
591
  }
655
- async function uninstallPlugins(entry, config, projectDir, onUninstalled) {
592
+ async function uninstallPlugins(entry, config, projectDir, { onUninstalled, onLeftRegistered } = {}) {
656
593
  const host = hostAt(projectDir);
657
594
  const hostAvailable = await host.isAvailable();
658
595
  const observed = [];
596
+ if (!hostAvailable) {
597
+ for (const pluginName of entry.names) onLeftRegistered?.(pluginName, host.provider);
598
+ }
659
599
  for (const pluginName of entry.names) {
660
600
  const removal = hostAvailable ? await removePluginWhereverItIsFiled(
661
601
  host,
@@ -669,10 +609,7 @@ async function uninstallPlugins(entry, config, projectDir, onUninstalled) {
669
609
  onUninstalled?.(pluginName);
670
610
  }
671
611
  }
672
- return {
673
- uninstalledNames: observed,
674
- totalUninstalled: observed.length
675
- };
612
+ return { totalUninstalled: observed.length };
676
613
  }
677
614
  function scopeThePluginIsFiledUnder(config, pluginName) {
678
615
  const skillId = parseMarketplacePluginRef(pluginName);
@@ -689,20 +626,15 @@ async function removeConfigManifest(entry) {
689
626
  return { manifestRemoved: true, dirRemoved: await removeDirIfEmpty(entry.sourceDir) };
690
627
  }
691
628
  async function cleanupEmptyDirs(target, manifestEntries) {
629
+ await removeDirIfEmpty(target.skillsDir);
630
+ await removeDirIfEmpty(target.agentsDir);
692
631
  const sourceFolder = await cleanupSourceFolder(
693
632
  target.sourceFolder,
694
633
  manifestEntries.find((entry) => entry.sourceDir === target.sourceFolder.dir)
695
634
  );
696
635
  const sourceRoot = await cleanupSourceRoot(target.sourceRoot, sourceFolder.dirRemoved);
697
- const claudeDirRemoved = target.hasClaudeDir && await removeDirIfEmpty(target.claudeDir);
698
- const claudeDirKept = !claudeDirRemoved && target.hasClaudeDir && await directoryExists(target.claudeDir);
699
- return {
700
- claudeDirRemoved,
701
- sourceFolder,
702
- sourceRootRemoved: sourceRoot.removed,
703
- sourceRootKept: sourceRoot.kept,
704
- claudeDirKept
705
- };
636
+ const claudeDir = await cleanupClaudeDir(target);
637
+ return { sourceFolder, sourceRoot, claudeDir };
706
638
  }
707
639
  async function cleanupSourceFolder(folder, entry) {
708
640
  const manifest = await removeConfigManifest(entry);
@@ -717,8 +649,15 @@ async function cleanupSourceFolder(folder, entry) {
717
649
  }
718
650
  async function cleanupSourceRoot(sourceRoot, providerDirRemoved) {
719
651
  if (!providerDirRemoved) return { removed: false, kept: false };
720
- const removed = await removeDirIfEmpty(sourceRoot.dir);
721
- return { removed, kept: !removed && await directoryExists(sourceRoot.dir) };
652
+ return removeDirUnlessUserContent(sourceRoot.dir);
653
+ }
654
+ async function cleanupClaudeDir(target) {
655
+ if (!target.hasClaudeDir) return { removed: false, kept: false };
656
+ return removeDirUnlessUserContent(target.claudeDir);
657
+ }
658
+ async function removeDirUnlessUserContent(dir) {
659
+ const removed = await removeDirIfEmpty(dir);
660
+ return { removed, kept: !removed && await directoryExists(dir) };
722
661
  }
723
662
  async function listAgentFiles(agentsDir, codec) {
724
663
  try {
@@ -728,8 +667,6 @@ async function listAgentFiles(agentsDir, codec) {
728
667
  }
729
668
  }
730
669
  export {
731
- Uninstall as default,
732
- getCliInstalledPluginKeys,
733
- uninstallPlugins
670
+ Uninstall as default
734
671
  };
735
672
  //# sourceMappingURL=uninstall.js.map