agents-inc 0.171.0 → 0.173.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 (93) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/{chunk-W4KAY26P.js → chunk-2RTBSLSR.js} +12 -3
  3. package/dist/{chunk-W4KAY26P.js.map → chunk-2RTBSLSR.js.map} +1 -1
  4. package/dist/{chunk-WM2N2D6Q.js → chunk-3N4FSTVX.js} +12 -6
  5. package/dist/{chunk-WM2N2D6Q.js.map → chunk-3N4FSTVX.js.map} +1 -1
  6. package/dist/{chunk-ZC6GC66J.js → chunk-3R3LHA4Q.js} +2 -2
  7. package/dist/{chunk-24OD7IP4.js → chunk-7OG635DK.js} +26 -4
  8. package/dist/chunk-7OG635DK.js.map +1 -0
  9. package/dist/{chunk-WDH6HHA3.js → chunk-A3ZAXL5T.js} +4 -5
  10. package/dist/{chunk-WDH6HHA3.js.map → chunk-A3ZAXL5T.js.map} +1 -1
  11. package/dist/{chunk-KMOCMVK5.js → chunk-AARQBW5L.js} +106 -60
  12. package/dist/chunk-AARQBW5L.js.map +1 -0
  13. package/dist/{chunk-WII6GOPM.js → chunk-BRZA7ZCX.js} +52 -31
  14. package/dist/chunk-BRZA7ZCX.js.map +1 -0
  15. package/dist/{chunk-AWWCRL5A.js → chunk-EHJIQDXR.js} +8 -6
  16. package/dist/{chunk-AWWCRL5A.js.map → chunk-EHJIQDXR.js.map} +1 -1
  17. package/dist/{chunk-RDXY4GRO.js → chunk-F437ICEG.js} +2 -2
  18. package/dist/chunk-G7NUK3BF.js +253 -0
  19. package/dist/chunk-G7NUK3BF.js.map +1 -0
  20. package/dist/{chunk-7IVLVEHX.js → chunk-ITQF35UQ.js} +3 -3
  21. package/dist/{chunk-QIR56IDM.js → chunk-LJQXQTFC.js} +29 -102
  22. package/dist/chunk-LJQXQTFC.js.map +1 -0
  23. package/dist/{chunk-A6OWEJGC.js → chunk-MHAQWMNJ.js} +35 -5
  24. package/dist/{chunk-A6OWEJGC.js.map → chunk-MHAQWMNJ.js.map} +1 -1
  25. package/dist/{chunk-YLUOGAW7.js → chunk-N33AKFLR.js} +2 -2
  26. package/dist/{chunk-TNFYBKVD.js → chunk-Q4UNHVPX.js} +25 -14
  27. package/dist/chunk-Q4UNHVPX.js.map +1 -0
  28. package/dist/chunk-Q6WRR4BN.js +195 -0
  29. package/dist/chunk-Q6WRR4BN.js.map +1 -0
  30. package/dist/{chunk-JGPE4RRE.js → chunk-SPQSNZMM.js} +2 -2
  31. package/dist/{chunk-EOKNEGRD.js → chunk-VR6QTK5Z.js} +8 -8
  32. package/dist/{chunk-S2SKVJT2.js → chunk-VSPC74SS.js} +48 -26
  33. package/dist/chunk-VSPC74SS.js.map +1 -0
  34. package/dist/{chunk-3YYHL76L.js → chunk-WVFBBZEP.js} +648 -394
  35. package/dist/chunk-WVFBBZEP.js.map +1 -0
  36. package/dist/commands/build/marketplace.js +16 -14
  37. package/dist/commands/build/marketplace.js.map +1 -1
  38. package/dist/commands/build/plugins.js +6 -6
  39. package/dist/commands/compile.js +12 -12
  40. package/dist/commands/doctor.js +87 -86
  41. package/dist/commands/doctor.js.map +1 -1
  42. package/dist/commands/edit.js +150 -152
  43. package/dist/commands/edit.js.map +1 -1
  44. package/dist/commands/eject.js +25 -30
  45. package/dist/commands/eject.js.map +1 -1
  46. package/dist/commands/init.js +19 -16
  47. package/dist/commands/list.js +14 -17
  48. package/dist/commands/list.js.map +1 -1
  49. package/dist/commands/new/marketplace.js +4 -4
  50. package/dist/commands/search.js +15 -13
  51. package/dist/commands/search.js.map +1 -1
  52. package/dist/commands/share.js +11 -11
  53. package/dist/commands/uninstall.js +145 -130
  54. package/dist/commands/uninstall.js.map +1 -1
  55. package/dist/commands/update.js +6 -6
  56. package/dist/components/common/scroll-affordance.js +2 -2
  57. package/dist/components/common/select-list.js +2 -2
  58. package/dist/components/common/skill-agent-summary.js +3 -4
  59. package/dist/components/common/summary-panel.js +11 -146
  60. package/dist/components/common/summary-panel.js.map +1 -1
  61. package/dist/hooks/init.js +39 -27
  62. package/dist/hooks/init.js.map +1 -1
  63. package/dist/load-agent-defs-E67DSYTN.js +14 -0
  64. package/dist/{recompile-project-agents-IQANWGOP.js → recompile-project-agents-6G6M2RS6.js} +8 -8
  65. package/dist/{source-loader-YGG7DY2W.js → source-loader-W7XCNKNA.js} +4 -4
  66. package/dist/src/agents/tester/web-tester/playbook.md +1 -1
  67. package/package.json +1 -1
  68. package/src/agents/tester/web-tester/playbook.md +1 -1
  69. package/dist/chunk-24OD7IP4.js.map +0 -1
  70. package/dist/chunk-3YYHL76L.js.map +0 -1
  71. package/dist/chunk-4RQKCV6I.js +0 -103
  72. package/dist/chunk-4RQKCV6I.js.map +0 -1
  73. package/dist/chunk-5FM77WKW.js +0 -69
  74. package/dist/chunk-5FM77WKW.js.map +0 -1
  75. package/dist/chunk-KMOCMVK5.js.map +0 -1
  76. package/dist/chunk-QIR56IDM.js.map +0 -1
  77. package/dist/chunk-R572RLTI.js +0 -108
  78. package/dist/chunk-R572RLTI.js.map +0 -1
  79. package/dist/chunk-S2SKVJT2.js.map +0 -1
  80. package/dist/chunk-TNFYBKVD.js.map +0 -1
  81. package/dist/chunk-WII6GOPM.js.map +0 -1
  82. package/dist/components/common/removal-plan-confirm.js +0 -10
  83. package/dist/load-agent-defs-UBWITIEI.js +0 -14
  84. package/dist/source-loader-YGG7DY2W.js.map +0 -1
  85. /package/dist/{chunk-ZC6GC66J.js.map → chunk-3R3LHA4Q.js.map} +0 -0
  86. /package/dist/{chunk-RDXY4GRO.js.map → chunk-F437ICEG.js.map} +0 -0
  87. /package/dist/{chunk-7IVLVEHX.js.map → chunk-ITQF35UQ.js.map} +0 -0
  88. /package/dist/{chunk-YLUOGAW7.js.map → chunk-N33AKFLR.js.map} +0 -0
  89. /package/dist/{chunk-JGPE4RRE.js.map → chunk-SPQSNZMM.js.map} +0 -0
  90. /package/dist/{chunk-EOKNEGRD.js.map → chunk-VR6QTK5Z.js.map} +0 -0
  91. /package/dist/{components/common/removal-plan-confirm.js.map → load-agent-defs-E67DSYTN.js.map} +0 -0
  92. /package/dist/{recompile-project-agents-IQANWGOP.js.map → recompile-project-agents-6G6M2RS6.js.map} +0 -0
  93. /package/dist/{load-agent-defs-UBWITIEI.js.map → source-loader-W7XCNKNA.js.map} +0 -0
@@ -1,59 +1,62 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- RemovalPlanConfirm
4
- } from "../chunk-5FM77WKW.js";
3
+ Confirm
4
+ } from "../chunk-OZXAJNLA.js";
5
5
  import {
6
6
  promptConfirm
7
7
  } from "../chunk-P6CYS4JK.js";
8
- import "../chunk-OZXAJNLA.js";
8
+ import {
9
+ summaryPanelBlock
10
+ } from "../chunk-Q6WRR4BN.js";
11
+ import "../chunk-N33AKFLR.js";
9
12
  import {
10
13
  lazyGateDeps,
11
14
  mutateGlobal,
12
15
  propagateGlobalRemoval
13
- } from "../chunk-S2SKVJT2.js";
14
- import "../chunk-EOKNEGRD.js";
16
+ } from "../chunk-VSPC74SS.js";
17
+ import "../chunk-VR6QTK5Z.js";
15
18
  import {
16
19
  loadAgentDefs
17
- } from "../chunk-7IVLVEHX.js";
18
- import "../chunk-WII6GOPM.js";
20
+ } from "../chunk-ITQF35UQ.js";
21
+ import "../chunk-BRZA7ZCX.js";
19
22
  import {
20
23
  listAgentFilesOf,
21
24
  splitAgentsByProvenance
22
- } from "../chunk-AWWCRL5A.js";
25
+ } from "../chunk-EHJIQDXR.js";
23
26
  import "../chunk-KIK5EZYD.js";
27
+ import "../chunk-G7NUK3BF.js";
24
28
  import {
25
29
  providerFlag,
26
30
  providerNamedBy,
27
31
  refuseAnAmbiguousInstallation
28
- } from "../chunk-W4KAY26P.js";
32
+ } from "../chunk-2RTBSLSR.js";
29
33
  import {
30
34
  BaseCommand,
31
35
  EXIT_CODES
32
- } from "../chunk-QIR56IDM.js";
36
+ } from "../chunk-LJQXQTFC.js";
33
37
  import {
34
38
  ConfigLoadError,
35
39
  INFO_MESSAGES,
36
40
  SUCCESS_MESSAGES,
37
- UNINSTALL_PLAN,
38
41
  agentCodec,
39
42
  buildMarketplacePluginRef,
40
- compiledAgentsRemoval,
43
+ configFileRemoved,
41
44
  directoryExists,
42
45
  fileExists,
43
46
  getErrorMessage,
44
47
  getProjectPluginsDir,
45
48
  hostAt,
49
+ isAgentName,
46
50
  isHomeDirectory,
47
51
  listDirectories,
48
52
  listPluginNames,
49
53
  loadProjectConfigAt,
50
54
  loadSkillsMatrixFromSource,
51
- localSkillsRemoval,
52
55
  notInstalledHere,
53
56
  parseMarketplacePluginRef,
54
57
  pluginLeftRegistered,
55
58
  providerInUse,
56
- readForkedFromMetadata,
59
+ readLocalSkillMetadata,
57
60
  registeredProjectUpdateSkipped,
58
61
  registeredProjectsUpdateFailed,
59
62
  registeredProjectsUpdated,
@@ -66,21 +69,22 @@ import {
66
69
  uninstallNeedsTerminal,
67
70
  uninstallSkillMetadataUnreadable,
68
71
  unmarkedAgentsKept
69
- } from "../chunk-3YYHL76L.js";
72
+ } from "../chunk-WVFBBZEP.js";
70
73
  import {
71
74
  plural
72
- } from "../chunk-24OD7IP4.js";
75
+ } from "../chunk-7OG635DK.js";
73
76
  import {
74
77
  CLAUDE_DIR,
75
78
  DEFAULT_BRANDING,
76
79
  EJECT_SOURCE,
77
- STANDARD_FILES
78
- } from "../chunk-A6OWEJGC.js";
80
+ STANDARD_FILES,
81
+ isActiveAt
82
+ } from "../chunk-MHAQWMNJ.js";
79
83
  import "../chunk-GHHJYNAN.js";
80
84
 
81
85
  // src/cli/commands/uninstall.tsx
82
86
  import "react";
83
- import { unique } from "remeda";
87
+ import { unique, uniqueBy } from "remeda";
84
88
  import path from "path";
85
89
  import { Flags } from "@oclif/core";
86
90
  import { jsx } from "react/jsx-runtime";
@@ -96,16 +100,73 @@ function buildRemovalPlan(target) {
96
100
  kept: keptStatements(target, agents)
97
101
  };
98
102
  }
103
+ function removalPanel(plan, target) {
104
+ const kept = target.scope === "project" ? globalEntriesOf(target.config) : NOTHING_KEPT;
105
+ return {
106
+ skillConfigs: kept.skills,
107
+ agentConfigs: kept.agents,
108
+ installedSkillConfigs: [...removedSkills(plan, target), ...kept.skills],
109
+ installedAgentConfigs: [...namedAgentRemovals(plan, target.scope).named, ...kept.agents],
110
+ isInitMode: false,
111
+ skillNames: namesTheCopiesRecord(target.cliSkills),
112
+ stackName: void 0
113
+ };
114
+ }
115
+ function namesTheCopiesRecord(cliSkills) {
116
+ return new Map(
117
+ cliSkills.flatMap(
118
+ ({ skillId, displayName }) => displayName === void 0 ? [] : [[skillId, displayName]]
119
+ )
120
+ );
121
+ }
122
+ var NOTHING_KEPT = { skills: [], agents: [] };
123
+ function globalEntriesOf(config) {
124
+ if (config === null) return NOTHING_KEPT;
125
+ return {
126
+ skills: config.skills.filter((skill) => isActiveAt(skill, "global")),
127
+ agents: config.agents.filter((agent) => isActiveAt(agent, "global"))
128
+ };
129
+ }
130
+ function removedSkills(plan, target) {
131
+ const copied = new Set(planEntries(plan, "skills").flatMap((entry) => entry.skillNames));
132
+ const plugins = new Set(planEntries(plan, "plugins").flatMap((entry) => entry.names));
133
+ const marketplaceName = target.config?.marketplaceName;
134
+ const copies = target.cliSkills.filter(({ dirName }) => copied.has(dirName)).map(({ skillId }) => ({ id: skillId, scope: target.scope, origin: EJECT_SOURCE }));
135
+ const pluginSkills = (target.config?.skills ?? []).filter((skill) => !skill.excluded).filter((skill) => pluginRefsOf(skill, marketplaceName).some((ref) => plugins.has(ref))).map((skill) => ({ ...skill, scope: target.scope }));
136
+ return uniqueBy([...copies, ...pluginSkills], (skill) => skill.id);
137
+ }
138
+ function namedAgentRemovals(plan, scope) {
139
+ const entries = planEntries(plan, "agents");
140
+ const names = entries.flatMap((entry) => entry.agentNames);
141
+ return {
142
+ named: names.filter(isAgentName).map((name) => ({ name, scope })),
143
+ files: entries.flatMap(
144
+ (entry) => entry.agentNames.filter((name) => !isAgentName(name)).map((name) => path.join(entry.agentsDir, `${name}${entry.codec.extension}`))
145
+ )
146
+ };
147
+ }
99
148
  function hasAnythingToRemove(plan) {
100
149
  return plan.entries.length > 0;
101
150
  }
151
+ function removedFileLines(plan, scope) {
152
+ const configFiles = planEntries(plan, "config").flatMap(
153
+ (entry) => entry.fileNames.map((fileName) => `${entry.sourceDir}/${fileName}`)
154
+ );
155
+ return [...namedAgentRemovals(plan, scope).files, ...configFiles].map(configFileRemoved);
156
+ }
102
157
  function pluginsEntry(target) {
103
158
  if (!target.hasPlugins) return [];
104
159
  return [{ kind: "plugins", pluginsDir: target.pluginsDir, names: [...target.cliPluginNames] }];
105
160
  }
106
161
  function localSkillsEntry(target) {
107
162
  if (target.cliSkills.length === 0) return [];
108
- return [{ kind: "skills", skillsDir: target.skillsDir, skillNames: [...target.cliSkills] }];
163
+ return [
164
+ {
165
+ kind: "skills",
166
+ skillsDir: target.skillsDir,
167
+ skillNames: target.cliSkills.map(({ dirName }) => dirName)
168
+ }
169
+ ];
109
170
  }
110
171
  function compiledAgentsEntry(target) {
111
172
  const agentNames = identifiableAgents(target);
@@ -138,49 +199,6 @@ function planEntry(plan, kind) {
138
199
  (entry) => entry.kind === kind
139
200
  );
140
201
  }
141
- function describeEntry(entry) {
142
- switch (entry.kind) {
143
- case "plugins":
144
- return { label: UNINSTALL_PLAN.PLUGINS_HEADING, items: entry.names };
145
- case "skills":
146
- return {
147
- label: UNINSTALL_PLAN.CLI_MANAGED_FILES_HEADING,
148
- items: [localSkillsRemoval(entry.skillsDir)]
149
- };
150
- case "agents":
151
- return {
152
- label: UNINSTALL_PLAN.CLI_MANAGED_FILES_HEADING,
153
- items: [compiledAgentsRemoval(entry.agentsDir)]
154
- };
155
- case "config":
156
- return {
157
- label: UNINSTALL_PLAN.CONFIG_HEADING,
158
- items: entry.fileNames.map((fileName) => `${entry.sourceDir}/${fileName}`)
159
- };
160
- default: {
161
- const _exhaustive = entry;
162
- return _exhaustive;
163
- }
164
- }
165
- }
166
- var PLAN_SECTION_ORDER = [
167
- UNINSTALL_PLAN.PLUGINS_HEADING,
168
- UNINSTALL_PLAN.CLI_MANAGED_FILES_HEADING,
169
- UNINSTALL_PLAN.CONFIG_HEADING
170
- ];
171
- function planSections(entries) {
172
- const described = entries.map(describeEntry);
173
- return PLAN_SECTION_ORDER.flatMap(
174
- (label) => sectionWithItems(label, itemsUnder(described, label))
175
- );
176
- }
177
- function itemsUnder(described, label) {
178
- return described.filter((section) => section.label === label).flatMap((section) => section.items);
179
- }
180
- function sectionWithItems(label, items) {
181
- if (items.length === 0) return [];
182
- return [{ label, items }];
183
- }
184
202
  var UNINSTALL_CONFIRM_MESSAGE = "Are you sure you want to uninstall?";
185
203
  var Uninstall = class _Uninstall extends BaseCommand {
186
204
  /** Replaced in `run` before anything prints. */
@@ -223,7 +241,7 @@ var Uninstall = class _Uninstall extends BaseCommand {
223
241
  this.reportNothingToUninstall();
224
242
  return;
225
243
  }
226
- const approved = await this.removalApproved(plan, flags.yes, namedProvider);
244
+ const approved = await this.removalApproved(plan, target, flags.yes, namedProvider);
227
245
  if (!approved) this.cancelUninstall();
228
246
  await this.executeUninstall(plan, target, projectDir);
229
247
  this.reportSuccess();
@@ -240,9 +258,10 @@ var Uninstall = class _Uninstall extends BaseCommand {
240
258
  this.log("");
241
259
  this.log(INFO_MESSAGES.NO_CHANGES_MADE);
242
260
  }
243
- async removalApproved(plan, skipConfirmation, namedProvider) {
244
- if (!skipConfirmation) return this.confirmRemoval(plan, namedProvider);
245
- this.printRemovalPlan(plan);
261
+ /** With `--yes` nothing is asked, so the plan prints where the question would be. */
262
+ async removalApproved(plan, target, skipConfirmation, namedProvider) {
263
+ if (!skipConfirmation) return this.confirmRemoval(plan, target, namedProvider);
264
+ this.showRemovalPlan(plan, target);
246
265
  return true;
247
266
  }
248
267
  cancelUninstall() {
@@ -250,36 +269,22 @@ var Uninstall = class _Uninstall extends BaseCommand {
250
269
  this.log("Uninstall cancelled");
251
270
  this.exit(EXIT_CODES.CANCELLED);
252
271
  }
253
- printRemovalPlan(plan) {
254
- this.log(UNINSTALL_PLAN.PREVIEW_HEADING);
255
- this.log("");
256
- for (const section of planSections(plan.entries)) {
257
- this.log(` ${section.label}`);
258
- for (const item of section.items) {
259
- this.log(` ${item}`);
260
- }
261
- }
262
- for (const statement of plan.kept) {
263
- this.log("");
264
- this.log(statement);
272
+ showRemovalPlan(plan, target) {
273
+ const lines = summaryPanelBlock(
274
+ removalPanel(plan, target),
275
+ removedFileLines(plan, target.scope),
276
+ plan.kept
277
+ );
278
+ for (const line of lines) {
279
+ this.log(line);
265
280
  }
266
- this.log("");
267
281
  }
268
- async confirmRemoval(plan, namedProvider) {
282
+ async confirmRemoval(plan, target, namedProvider) {
269
283
  if (!process.stdin.isTTY) {
270
284
  this.error(uninstallNeedsTerminal(namedProvider), { exit: EXIT_CODES.ERROR });
271
285
  }
272
- const outcome = await promptConfirm(({ onConfirm, onCancel }) => /* @__PURE__ */ jsx(
273
- RemovalPlanConfirm,
274
- {
275
- heading: UNINSTALL_PLAN.PREVIEW_HEADING,
276
- sections: planSections(plan.entries),
277
- statements: plan.kept,
278
- message: UNINSTALL_CONFIRM_MESSAGE,
279
- onConfirm,
280
- onCancel
281
- }
282
- ));
286
+ this.showRemovalPlan(plan, target);
287
+ const outcome = await promptConfirm(({ onConfirm, onCancel }) => /* @__PURE__ */ jsx(Confirm, { message: UNINSTALL_CONFIRM_MESSAGE, onConfirm, onCancel }));
283
288
  return outcome === "confirmed";
284
289
  }
285
290
  async executeUninstall(plan, target, projectDir) {
@@ -288,15 +293,18 @@ var Uninstall = class _Uninstall extends BaseCommand {
288
293
  await this.removePlannedPlugins(planEntry(plan, "plugins"), target.config, projectDir);
289
294
  await this.removeLocalFilesOrFail(plan, target);
290
295
  if (!isGlobalUninstall) {
291
- await this.deregisterProject(projectDir);
296
+ await this.deregisterProject(projectDir, target.provider);
292
297
  return;
293
298
  }
294
299
  if (propagation) await this.updateRegisteredProjects(propagation);
295
300
  }
296
301
  /** Degrades: a missing or corrupt global config must never fail the uninstall. */
297
- async deregisterProject(projectDir) {
302
+ async deregisterProject(projectDir, provider) {
298
303
  try {
299
- await mutateGlobal({ kind: "deregister-project", projectDir }, lazyGateDeps(projectDir));
304
+ await mutateGlobal(
305
+ { kind: "deregister-project", projectDir, provider },
306
+ lazyGateDeps(projectDir)
307
+ );
300
308
  } catch (error) {
301
309
  this.warn(`Could not update the global project registry: ${getErrorMessage(error)}`);
302
310
  }
@@ -380,22 +388,27 @@ var Uninstall = class _Uninstall extends BaseCommand {
380
388
  this.reportDirCleanup(target.sourceRoot.relName, cleanup.sourceRoot);
381
389
  this.reportDirCleanup(CLAUDE_DIR, cleanup.claudeDir);
382
390
  }
383
- reportSourceFolderCleanup(folder) {
384
- if (folder.dirRemoved) {
385
- this.logSuccess(`Removed ${folder.relName}/`);
386
- } else if (folder.manifestRemoved) {
387
- this.logSuccess(`Removed CLI config from ${folder.relName}/`);
388
- } else if (folder.kept) {
389
- this.log(`Kept ${folder.relName}/ (contains user content)`);
391
+ reportSourceFolderCleanup({ relName, outcome }) {
392
+ if (outcome === "config-removed") {
393
+ this.logSuccess(`Removed CLI config from ${relName}/`);
394
+ return;
390
395
  }
396
+ this.reportDirCleanup(relName, outcome);
391
397
  }
392
398
  reportDirCleanup(relName, cleanup) {
393
- if (cleanup.removed) {
394
- this.logSuccess(`Removed ${relName}/`);
395
- return;
396
- }
397
- if (cleanup.kept) {
398
- this.log(`Kept ${relName}/ (contains user content)`);
399
+ switch (cleanup) {
400
+ case "removed":
401
+ this.logSuccess(`Removed ${relName}/`);
402
+ return;
403
+ case "kept":
404
+ this.log(`Kept ${relName}/ (contains user content)`);
405
+ return;
406
+ case "untouched":
407
+ return;
408
+ default: {
409
+ const _exhaustive = cleanup;
410
+ return _exhaustive;
411
+ }
399
412
  }
400
413
  }
401
414
  async removePlannedPlugins(entry, config, projectDir) {
@@ -508,6 +521,8 @@ async function detectUninstallTarget(projectDir, handlers) {
508
521
  const activeConfig = config === null ? null : activeConfigOf(config);
509
522
  const cliPluginNames = await pluginsThisRunRemoves(projectDir, activeConfig);
510
523
  return {
524
+ scope: isHomeDirectory(projectDir) ? "global" : "project",
525
+ provider,
511
526
  hasPlugins: cliPluginNames.length > 0,
512
527
  cliPluginNames,
513
528
  cliSkills,
@@ -539,17 +554,22 @@ function thisRunOwnsAnyPlugin(projectDir) {
539
554
  async function skillsThisCliInstalled(skillsDir, onMetadataUnreadable) {
540
555
  const dirNames = await listDirectories(skillsDir);
541
556
  const skills = await Promise.all(
542
- dirNames.map(async (name) => ({
543
- name,
544
- forkedFrom: await readSkillProvenance(skillsDir, name, onMetadataUnreadable)
557
+ dirNames.map(async (dirName) => ({
558
+ dirName,
559
+ metadata: await readCopyMetadata(skillsDir, dirName, onMetadataUnreadable)
545
560
  }))
546
561
  );
547
- return skills.filter((skill) => skill.forkedFrom !== null).map((skill) => skill.name);
562
+ return skills.flatMap(
563
+ ({ dirName, metadata }) => metadata?.forkedFrom === void 0 ? [] : [{ dirName, skillId: metadata.forkedFrom.skillId, displayName: recordedName(metadata) }]
564
+ );
548
565
  }
549
- async function readSkillProvenance(skillsDir, dirName, onUnreadable) {
566
+ function recordedName(metadata) {
567
+ return typeof metadata.displayName === "string" ? metadata.displayName : void 0;
568
+ }
569
+ async function readCopyMetadata(skillsDir, dirName, onUnreadable) {
550
570
  const skillDir = path.join(skillsDir, dirName);
551
571
  try {
552
- return await readForkedFromMetadata(skillDir);
572
+ return await readLocalSkillMetadata(skillDir);
553
573
  } catch {
554
574
  return onUnreadable(path.join(skillDir, STANDARD_FILES.METADATA_YAML));
555
575
  }
@@ -619,11 +639,11 @@ function nothingWasObserved() {
619
639
  return "absent";
620
640
  }
621
641
  async function removeConfigManifest(entry) {
622
- if (!entry) return { manifestRemoved: false, dirRemoved: false };
642
+ if (!entry) return false;
623
643
  await Promise.all(
624
644
  entry.fileNames.map((fileName) => remove(path.join(entry.sourceDir, fileName)))
625
645
  );
626
- return { manifestRemoved: true, dirRemoved: await removeDirIfEmpty(entry.sourceDir) };
646
+ return true;
627
647
  }
628
648
  async function cleanupEmptyDirs(target, manifestEntries) {
629
649
  await removeDirIfEmpty(target.skillsDir);
@@ -632,32 +652,27 @@ async function cleanupEmptyDirs(target, manifestEntries) {
632
652
  target.sourceFolder,
633
653
  manifestEntries.find((entry) => entry.sourceDir === target.sourceFolder.dir)
634
654
  );
635
- const sourceRoot = await cleanupSourceRoot(target.sourceRoot, sourceFolder.dirRemoved);
655
+ const sourceRoot = await cleanupSourceRoot(target.sourceRoot, sourceFolder.outcome === "removed");
636
656
  const claudeDir = await cleanupClaudeDir(target);
637
657
  return { sourceFolder, sourceRoot, claudeDir };
638
658
  }
639
659
  async function cleanupSourceFolder(folder, entry) {
640
- const manifest = await removeConfigManifest(entry);
641
- const dirRemoved = manifest.dirRemoved || await removeDirIfEmpty(folder.dir);
642
- const kept = !dirRemoved && await directoryExists(folder.dir);
643
- return {
644
- relName: folder.relName,
645
- manifestRemoved: manifest.manifestRemoved,
646
- dirRemoved,
647
- kept
648
- };
660
+ const manifestRemoved = await removeConfigManifest(entry);
661
+ const dir = await removeDirUnlessUserContent(folder.dir);
662
+ const outcome = manifestRemoved && dir !== "removed" ? "config-removed" : dir;
663
+ return { relName: folder.relName, outcome };
649
664
  }
650
665
  async function cleanupSourceRoot(sourceRoot, providerDirRemoved) {
651
- if (!providerDirRemoved) return { removed: false, kept: false };
666
+ if (!providerDirRemoved) return "untouched";
652
667
  return removeDirUnlessUserContent(sourceRoot.dir);
653
668
  }
654
669
  async function cleanupClaudeDir(target) {
655
- if (!target.hasClaudeDir) return { removed: false, kept: false };
670
+ if (!target.hasClaudeDir) return "untouched";
656
671
  return removeDirUnlessUserContent(target.claudeDir);
657
672
  }
658
673
  async function removeDirUnlessUserContent(dir) {
659
- const removed = await removeDirIfEmpty(dir);
660
- return { removed, kept: !removed && await directoryExists(dir) };
674
+ if (await removeDirIfEmpty(dir)) return "removed";
675
+ return await directoryExists(dir) ? "kept" : "untouched";
661
676
  }
662
677
  async function listAgentFiles(agentsDir, codec) {
663
678
  try {