@agents-inc/cli 0.85.0 → 0.87.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.
- package/CHANGELOG.md +20 -0
- package/dist/{chunk-6VGBO6SZ.js → chunk-5M6Q5UQO.js} +2 -2
- package/dist/chunk-5UJJQFET.js +564 -0
- package/dist/chunk-5UJJQFET.js.map +1 -0
- package/dist/{chunk-TXW257CU.js → chunk-7FFNNDJQ.js} +181 -202
- package/dist/chunk-7FFNNDJQ.js.map +1 -0
- package/dist/{chunk-YJ2URWF7.js → chunk-B6MYECV6.js} +2 -2
- package/dist/{chunk-G2MINRWX.js → chunk-C5IYJ42F.js} +2 -2
- package/dist/{chunk-7UZUDHP7.js → chunk-CXWBVBDM.js} +2 -2
- package/dist/{chunk-CYPCJ536.js → chunk-FBZR46GC.js} +92 -92
- package/dist/chunk-FBZR46GC.js.map +1 -0
- package/dist/{chunk-LTFGEVTM.js → chunk-HH3AWXF4.js} +3 -3
- package/dist/{chunk-2XVLQDNI.js → chunk-HSLVCKVQ.js} +3 -3
- package/dist/{chunk-TAQGYJIS.js → chunk-HZ2IBXVQ.js} +3 -3
- package/dist/{chunk-LN76TJJP.js → chunk-HZQOFFKA.js} +10 -10
- package/dist/{chunk-W7LHI54P.js → chunk-I44YG6VI.js} +2 -2
- package/dist/{chunk-FT46LN7K.js → chunk-I5AZKNNL.js} +7 -8
- package/dist/chunk-I5AZKNNL.js.map +1 -0
- package/dist/chunk-J6PI73YV.js +68 -0
- package/dist/chunk-J6PI73YV.js.map +1 -0
- package/dist/{chunk-L7COG2EX.js → chunk-LZ7XQ3IU.js} +2 -2
- package/dist/{chunk-LMR7VAP3.js → chunk-MMTMXLI4.js} +2 -2
- package/dist/chunk-N6A7A4RA.js +16 -0
- package/dist/chunk-N6A7A4RA.js.map +1 -0
- package/dist/{chunk-WJKD6EGK.js → chunk-NUU3U43A.js} +5 -6
- package/dist/chunk-NUU3U43A.js.map +1 -0
- package/dist/{chunk-YYIWB42G.js → chunk-Q4DMIPZB.js} +2 -2
- package/dist/{chunk-YSLDMYWP.js → chunk-SGZOFIFF.js} +2 -2
- package/dist/{chunk-FKXD3EXJ.js → chunk-TMTUTUEV.js} +42 -228
- package/dist/chunk-TMTUTUEV.js.map +1 -0
- package/dist/{chunk-WCCWQ56J.js → chunk-UNEJKTLP.js} +3 -3
- package/dist/{chunk-ZGD7PLLC.js → chunk-ZOWRO7UQ.js} +3 -3
- package/dist/commands/build/marketplace.js +3 -3
- package/dist/commands/build/plugins.js +5 -5
- package/dist/commands/build/stack.js +5 -5
- package/dist/commands/compile.js +77 -171
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/config/index.js +5 -5
- package/dist/commands/config/path.js +4 -4
- package/dist/commands/config/show.js +5 -5
- package/dist/commands/diff.js +161 -167
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/doctor.js +68 -83
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +275 -209
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +206 -124
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/import/skill.js +175 -144
- package/dist/commands/import/skill.js.map +1 -1
- package/dist/commands/info.js +58 -102
- package/dist/commands/info.js.map +1 -1
- package/dist/commands/init.js +19 -16
- package/dist/commands/list.js +4 -4
- package/dist/commands/new/agent.js +124 -102
- package/dist/commands/new/agent.js.map +1 -1
- package/dist/commands/new/marketplace.js +6 -6
- package/dist/commands/new/marketplace.js.map +1 -1
- package/dist/commands/new/skill.js +328 -15
- package/dist/commands/new/skill.js.map +1 -1
- package/dist/commands/outdated.js +16 -24
- package/dist/commands/outdated.js.map +1 -1
- package/dist/commands/search.js +166 -132
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/uninstall.js +269 -189
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +238 -219
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/validate.js +4 -4
- package/dist/components/skill-search/skill-search.js +2 -1
- package/dist/components/wizard/category-grid.test.js +4 -4
- package/dist/components/wizard/domain-selection.js +5 -5
- package/dist/components/wizard/help-modal.js +5 -5
- package/dist/components/wizard/source-grid.test.js +4 -4
- package/dist/components/wizard/stack-selection.js +5 -5
- package/dist/components/wizard/step-agents.js +5 -5
- package/dist/components/wizard/step-agents.test.js +5 -5
- package/dist/components/wizard/step-build.js +5 -5
- package/dist/components/wizard/step-build.test.js +5 -5
- package/dist/components/wizard/step-confirm.test.js +4 -4
- package/dist/components/wizard/step-settings.js +4 -4
- package/dist/components/wizard/step-settings.test.js +7 -7
- package/dist/components/wizard/step-sources.js +5 -5
- package/dist/components/wizard/step-sources.test.js +5 -5
- package/dist/components/wizard/step-stack.js +6 -6
- package/dist/components/wizard/step-stack.test.js +6 -6
- package/dist/components/wizard/wizard-layout.js +6 -6
- package/dist/components/wizard/wizard.js +14 -14
- package/dist/hooks/init.js +19 -16
- package/dist/hooks/init.js.map +1 -1
- package/dist/{loader-GT2A7R7U.js → loader-GSEGPK64.js} +3 -3
- package/dist/{source-loader-TNQW4P47.js → source-loader-OGFTIRIX.js} +4 -4
- package/dist/{source-manager-INRXRFJE.js → source-manager-FMMDDVZA.js} +4 -4
- package/dist/stores/wizard-store.js +4 -4
- package/dist/stores/wizard-store.test.js +4 -4
- package/package.json +1 -1
- package/dist/chunk-AABH2HSE.js +0 -340
- package/dist/chunk-AABH2HSE.js.map +0 -1
- package/dist/chunk-CYPCJ536.js.map +0 -1
- package/dist/chunk-FKXD3EXJ.js.map +0 -1
- package/dist/chunk-FT46LN7K.js.map +0 -1
- package/dist/chunk-TXW257CU.js.map +0 -1
- package/dist/chunk-WJKD6EGK.js.map +0 -1
- /package/dist/{chunk-6VGBO6SZ.js.map → chunk-5M6Q5UQO.js.map} +0 -0
- /package/dist/{chunk-YJ2URWF7.js.map → chunk-B6MYECV6.js.map} +0 -0
- /package/dist/{chunk-G2MINRWX.js.map → chunk-C5IYJ42F.js.map} +0 -0
- /package/dist/{chunk-7UZUDHP7.js.map → chunk-CXWBVBDM.js.map} +0 -0
- /package/dist/{chunk-LTFGEVTM.js.map → chunk-HH3AWXF4.js.map} +0 -0
- /package/dist/{chunk-2XVLQDNI.js.map → chunk-HSLVCKVQ.js.map} +0 -0
- /package/dist/{chunk-TAQGYJIS.js.map → chunk-HZ2IBXVQ.js.map} +0 -0
- /package/dist/{chunk-LN76TJJP.js.map → chunk-HZQOFFKA.js.map} +0 -0
- /package/dist/{chunk-W7LHI54P.js.map → chunk-I44YG6VI.js.map} +0 -0
- /package/dist/{chunk-L7COG2EX.js.map → chunk-LZ7XQ3IU.js.map} +0 -0
- /package/dist/{chunk-LMR7VAP3.js.map → chunk-MMTMXLI4.js.map} +0 -0
- /package/dist/{chunk-YYIWB42G.js.map → chunk-Q4DMIPZB.js.map} +0 -0
- /package/dist/{chunk-YSLDMYWP.js.map → chunk-SGZOFIFF.js.map} +0 -0
- /package/dist/{chunk-WCCWQ56J.js.map → chunk-UNEJKTLP.js.map} +0 -0
- /package/dist/{chunk-ZGD7PLLC.js.map → chunk-ZOWRO7UQ.js.map} +0 -0
- /package/dist/{loader-GT2A7R7U.js.map → loader-GSEGPK64.js.map} +0 -0
- /package/dist/{source-loader-TNQW4P47.js.map → source-loader-OGFTIRIX.js.map} +0 -0
- /package/dist/{source-manager-INRXRFJE.js.map → source-manager-FMMDDVZA.js.map} +0 -0
|
@@ -13,19 +13,19 @@ import {
|
|
|
13
13
|
listPluginNames,
|
|
14
14
|
loadProjectConfigFromDir,
|
|
15
15
|
readForkedFromMetadata
|
|
16
|
-
} from "../chunk-
|
|
17
|
-
import "../chunk-
|
|
16
|
+
} from "../chunk-TMTUTUEV.js";
|
|
17
|
+
import "../chunk-B6MYECV6.js";
|
|
18
18
|
import "../chunk-ANXHMG32.js";
|
|
19
19
|
import {
|
|
20
20
|
BaseCommand,
|
|
21
21
|
EXIT_CODES
|
|
22
|
-
} from "../chunk-
|
|
22
|
+
} from "../chunk-MMTMXLI4.js";
|
|
23
23
|
import {
|
|
24
24
|
directoryExists,
|
|
25
25
|
getErrorMessage,
|
|
26
26
|
listDirectories,
|
|
27
27
|
remove
|
|
28
|
-
} from "../chunk-
|
|
28
|
+
} from "../chunk-NUU3U43A.js";
|
|
29
29
|
import "../chunk-6XWHJHNZ.js";
|
|
30
30
|
import {
|
|
31
31
|
CLAUDE_DIR,
|
|
@@ -40,58 +40,11 @@ import {
|
|
|
40
40
|
|
|
41
41
|
// src/cli/commands/uninstall.tsx
|
|
42
42
|
init_esm_shims();
|
|
43
|
+
import path from "path";
|
|
44
|
+
import { readdir } from "fs/promises";
|
|
43
45
|
import { Flags } from "@oclif/core";
|
|
44
46
|
import { render, Box, Text, useApp } from "ink";
|
|
45
|
-
import path from "path";
|
|
46
47
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
47
|
-
function collectConfiguredAgents(config) {
|
|
48
|
-
if (!config?.agents) return [];
|
|
49
|
-
return config.agents.map((a) => a.name);
|
|
50
|
-
}
|
|
51
|
-
function getCliInstalledPluginKeys(config) {
|
|
52
|
-
if (!config?.skills) return /* @__PURE__ */ new Set();
|
|
53
|
-
return new Set(config.skills.map((skill) => `${skill.id}@${skill.source}`));
|
|
54
|
-
}
|
|
55
|
-
async function detectUninstallTarget(projectDir) {
|
|
56
|
-
const pluginsDir = getProjectPluginsDir(projectDir);
|
|
57
|
-
const skillsDir = path.join(projectDir, CLAUDE_DIR, "skills");
|
|
58
|
-
const agentsDir = path.join(projectDir, CLAUDE_DIR, "agents");
|
|
59
|
-
const claudeDir = path.join(projectDir, CLAUDE_DIR);
|
|
60
|
-
const claudeSrcDir = path.join(projectDir, CLAUDE_SRC_DIR);
|
|
61
|
-
const [hasLocalSkills, hasLocalAgents, hasClaudeDir, hasClaudeSrcDir, config] = await Promise.all(
|
|
62
|
-
[
|
|
63
|
-
directoryExists(skillsDir),
|
|
64
|
-
directoryExists(agentsDir),
|
|
65
|
-
directoryExists(claudeDir),
|
|
66
|
-
directoryExists(claudeSrcDir),
|
|
67
|
-
loadProjectConfigFromDir(projectDir).then((result) => result?.config ?? null)
|
|
68
|
-
]
|
|
69
|
-
);
|
|
70
|
-
let pluginNames = [];
|
|
71
|
-
try {
|
|
72
|
-
pluginNames = await listPluginNames(projectDir);
|
|
73
|
-
} catch {
|
|
74
|
-
}
|
|
75
|
-
const configuredAgents = collectConfiguredAgents(config);
|
|
76
|
-
const cliInstalledKeys = getCliInstalledPluginKeys(config);
|
|
77
|
-
const cliPluginNames = pluginNames.filter((name) => cliInstalledKeys.has(name));
|
|
78
|
-
return {
|
|
79
|
-
hasPlugins: cliPluginNames.length > 0,
|
|
80
|
-
pluginNames,
|
|
81
|
-
cliPluginNames,
|
|
82
|
-
hasLocalSkills,
|
|
83
|
-
hasLocalAgents,
|
|
84
|
-
hasClaudeDir,
|
|
85
|
-
hasClaudeSrcDir,
|
|
86
|
-
pluginsDir,
|
|
87
|
-
skillsDir,
|
|
88
|
-
agentsDir,
|
|
89
|
-
claudeDir,
|
|
90
|
-
claudeSrcDir,
|
|
91
|
-
config,
|
|
92
|
-
configuredAgents
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
48
|
var UninstallConfirm = ({
|
|
96
49
|
target,
|
|
97
50
|
removeAll,
|
|
@@ -148,18 +101,6 @@ var UninstallConfirm = ({
|
|
|
148
101
|
)
|
|
149
102
|
] });
|
|
150
103
|
};
|
|
151
|
-
async function isDirectoryEmpty(dirPath) {
|
|
152
|
-
const { readdir } = await import("fs/promises");
|
|
153
|
-
try {
|
|
154
|
-
const allEntries = await readdir(dirPath);
|
|
155
|
-
return allEntries.length === 0;
|
|
156
|
-
} catch {
|
|
157
|
-
return true;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
function shouldRemoveSkill(forkedFrom) {
|
|
161
|
-
return forkedFrom !== null;
|
|
162
|
-
}
|
|
163
104
|
var Uninstall = class _Uninstall extends BaseCommand {
|
|
164
105
|
static summary = `Remove ${DEFAULT_BRANDING.NAME} from this project`;
|
|
165
106
|
static description = `Uninstall ${DEFAULT_BRANDING.NAME} from this project. Removes CLI-managed skills (matched by source), compiled agents, and plugins. User-created content is preserved.`;
|
|
@@ -183,83 +124,85 @@ var Uninstall = class _Uninstall extends BaseCommand {
|
|
|
183
124
|
async run() {
|
|
184
125
|
const { flags } = await this.parse(_Uninstall);
|
|
185
126
|
const projectDir = process.cwd();
|
|
186
|
-
this.
|
|
187
|
-
this.log(`${DEFAULT_BRANDING.NAME} Uninstall`);
|
|
188
|
-
this.log("");
|
|
127
|
+
this.printHeader();
|
|
189
128
|
const target = await detectUninstallTarget(projectDir);
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
this.warn("Nothing to uninstall.");
|
|
193
|
-
this.log("");
|
|
194
|
-
this.log(INFO_MESSAGES.NOT_INSTALLED);
|
|
195
|
-
this.log("");
|
|
196
|
-
this.log(INFO_MESSAGES.NO_CHANGES_MADE);
|
|
129
|
+
if (!hasAnythingToRemove(target, flags.all)) {
|
|
130
|
+
this.reportNothingToUninstall();
|
|
197
131
|
return;
|
|
198
132
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
const { waitUntilExit } = render(
|
|
202
|
-
/* @__PURE__ */ jsx(
|
|
203
|
-
UninstallConfirm,
|
|
204
|
-
{
|
|
205
|
-
target,
|
|
206
|
-
removeAll: flags.all,
|
|
207
|
-
onConfirm: () => resolve(true),
|
|
208
|
-
onCancel: () => resolve(false)
|
|
209
|
-
}
|
|
210
|
-
)
|
|
211
|
-
);
|
|
212
|
-
waitUntilExit().catch(() => resolve(false));
|
|
213
|
-
});
|
|
214
|
-
if (!confirmed) {
|
|
215
|
-
this.log("");
|
|
216
|
-
this.log("Uninstall cancelled");
|
|
217
|
-
this.exit(EXIT_CODES.CANCELLED);
|
|
218
|
-
}
|
|
219
|
-
} else {
|
|
220
|
-
this.log("The following will be removed:");
|
|
133
|
+
const confirmed = flags.yes ? this.printRemovalPlan(target, flags.all) : await this.confirmRemoval(target, flags.all);
|
|
134
|
+
if (!confirmed) {
|
|
221
135
|
this.log("");
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
136
|
+
this.log("Uninstall cancelled");
|
|
137
|
+
this.exit(EXIT_CODES.CANCELLED);
|
|
138
|
+
}
|
|
139
|
+
await this.executeUninstall(target, projectDir, flags.all);
|
|
140
|
+
this.reportSuccess();
|
|
141
|
+
}
|
|
142
|
+
printHeader() {
|
|
143
|
+
this.log("");
|
|
144
|
+
this.log(`${DEFAULT_BRANDING.NAME} Uninstall`);
|
|
145
|
+
this.log("");
|
|
146
|
+
}
|
|
147
|
+
reportNothingToUninstall() {
|
|
148
|
+
this.warn("Nothing to uninstall.");
|
|
149
|
+
this.log("");
|
|
150
|
+
this.log(INFO_MESSAGES.NOT_INSTALLED);
|
|
151
|
+
this.log("");
|
|
152
|
+
this.log(INFO_MESSAGES.NO_CHANGES_MADE);
|
|
153
|
+
}
|
|
154
|
+
printRemovalPlan(target, removeAll) {
|
|
155
|
+
this.log("The following will be removed:");
|
|
156
|
+
this.log("");
|
|
157
|
+
if (target.hasPlugins) {
|
|
158
|
+
this.log(" Plugins:");
|
|
159
|
+
for (const pluginName of target.cliPluginNames) {
|
|
160
|
+
this.log(` ${pluginName}`);
|
|
227
161
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
}
|
|
233
|
-
if (target.hasLocalAgents) {
|
|
234
|
-
this.log(` ${target.agentsDir}/ (CLI-compiled)`);
|
|
235
|
-
}
|
|
162
|
+
}
|
|
163
|
+
if (target.hasLocalSkills || target.hasLocalAgents) {
|
|
164
|
+
this.log(" CLI-managed files:");
|
|
165
|
+
if (target.hasLocalSkills) {
|
|
166
|
+
this.log(` ${target.skillsDir}/ (matching sources)`);
|
|
236
167
|
}
|
|
237
|
-
if (
|
|
238
|
-
this.log(
|
|
239
|
-
this.log(` ${target.claudeSrcDir}/`);
|
|
168
|
+
if (target.hasLocalAgents) {
|
|
169
|
+
this.log(` ${target.agentsDir}/ (CLI-compiled)`);
|
|
240
170
|
}
|
|
241
|
-
this.log("");
|
|
242
171
|
}
|
|
172
|
+
if (removeAll && target.hasClaudeSrcDir) {
|
|
173
|
+
this.log(" Config:");
|
|
174
|
+
this.log(` ${target.claudeSrcDir}/`);
|
|
175
|
+
}
|
|
176
|
+
this.log("");
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
async confirmRemoval(target, removeAll) {
|
|
180
|
+
return new Promise((resolve) => {
|
|
181
|
+
const { waitUntilExit } = render(
|
|
182
|
+
/* @__PURE__ */ jsx(
|
|
183
|
+
UninstallConfirm,
|
|
184
|
+
{
|
|
185
|
+
target,
|
|
186
|
+
removeAll,
|
|
187
|
+
onConfirm: () => resolve(true),
|
|
188
|
+
onCancel: () => resolve(false)
|
|
189
|
+
}
|
|
190
|
+
)
|
|
191
|
+
);
|
|
192
|
+
waitUntilExit().catch(() => resolve(false));
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
async executeUninstall(target, projectDir, removeAll) {
|
|
243
196
|
if (target.hasPlugins) {
|
|
244
197
|
this.log("Uninstalling plugins...");
|
|
245
198
|
try {
|
|
246
|
-
const
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
const skillConfig = target.config?.skills?.find((s) => s.id === skillId);
|
|
252
|
-
const pluginScope = skillConfig?.scope === "global" ? "user" : "project";
|
|
253
|
-
await claudePluginUninstall(pluginName, pluginScope, projectDir);
|
|
254
|
-
} catch {
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
const pluginPath = path.join(target.pluginsDir, pluginName);
|
|
258
|
-
await remove(pluginPath);
|
|
259
|
-
this.log(` Uninstalled plugin '${pluginName}'`);
|
|
260
|
-
}
|
|
199
|
+
const pluginResult = await uninstallPlugins(
|
|
200
|
+
target,
|
|
201
|
+
projectDir,
|
|
202
|
+
(name) => this.log(` Uninstalled plugin '${name}'`)
|
|
203
|
+
);
|
|
261
204
|
this.logSuccess(
|
|
262
|
-
`Uninstalled ${
|
|
205
|
+
`Uninstalled ${pluginResult.totalUninstalled} ${pluginResult.totalUninstalled === 1 ? "plugin" : "plugins"}`
|
|
263
206
|
);
|
|
264
207
|
} catch (error) {
|
|
265
208
|
this.log("Plugin uninstall failed");
|
|
@@ -269,13 +212,15 @@ var Uninstall = class _Uninstall extends BaseCommand {
|
|
|
269
212
|
}
|
|
270
213
|
}
|
|
271
214
|
try {
|
|
272
|
-
await this.removeLocalFiles(target,
|
|
215
|
+
await this.removeLocalFiles(target, removeAll);
|
|
273
216
|
} catch (error) {
|
|
274
217
|
this.log("Failed to remove local files");
|
|
275
218
|
this.error(getErrorMessage(error), {
|
|
276
219
|
exit: EXIT_CODES.ERROR
|
|
277
220
|
});
|
|
278
221
|
}
|
|
222
|
+
}
|
|
223
|
+
reportSuccess() {
|
|
279
224
|
this.log("");
|
|
280
225
|
this.log(`${DEFAULT_BRANDING.NAME} has been uninstalled.`);
|
|
281
226
|
this.log("");
|
|
@@ -283,83 +228,218 @@ var Uninstall = class _Uninstall extends BaseCommand {
|
|
|
283
228
|
this.log("");
|
|
284
229
|
}
|
|
285
230
|
async removeLocalFiles(target, removeAll) {
|
|
286
|
-
await
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
if (!target.hasLocalSkills) return;
|
|
296
|
-
const skillDirNames = await listDirectories(target.skillsDir);
|
|
297
|
-
let removedCount = 0;
|
|
298
|
-
let skippedCount = 0;
|
|
299
|
-
for (const skillDirName of skillDirNames) {
|
|
300
|
-
const skillDir = path.join(target.skillsDir, skillDirName);
|
|
301
|
-
const forkedFrom = await readForkedFromMetadata(skillDir);
|
|
302
|
-
if (shouldRemoveSkill(forkedFrom)) {
|
|
303
|
-
await remove(skillDir);
|
|
304
|
-
removedCount++;
|
|
305
|
-
this.log(` Uninstalled skill '${skillDirName}'`);
|
|
306
|
-
} else {
|
|
307
|
-
this.warn(`Skipping '${skillDirName}': not created by ${DEFAULT_BRANDING.NAME} CLI`);
|
|
308
|
-
skippedCount++;
|
|
309
|
-
}
|
|
231
|
+
const skillResult = await removeMatchingSkills(
|
|
232
|
+
target,
|
|
233
|
+
(dirName) => this.log(` Uninstalled skill '${dirName}'`),
|
|
234
|
+
(dirName) => this.warn(`Skipping '${dirName}': not created by ${DEFAULT_BRANDING.NAME} CLI`)
|
|
235
|
+
);
|
|
236
|
+
if (skillResult.removedCount > 0) {
|
|
237
|
+
this.logSuccess(
|
|
238
|
+
`Removed ${skillResult.removedCount} CLI-installed ${skillResult.removedCount === 1 ? "skill" : "skills"}`
|
|
239
|
+
);
|
|
310
240
|
}
|
|
311
|
-
|
|
241
|
+
const agentResult = await removeMatchingAgents(
|
|
242
|
+
target,
|
|
243
|
+
(agentName) => this.log(` Uninstalled agent '${agentName}'`)
|
|
244
|
+
);
|
|
245
|
+
if (agentResult.removedCount > 0) {
|
|
312
246
|
this.logSuccess(
|
|
313
|
-
`Removed ${removedCount}
|
|
247
|
+
`Removed ${agentResult.removedCount} compiled ${agentResult.removedCount === 1 ? "agent" : "agents"}`
|
|
314
248
|
);
|
|
315
249
|
}
|
|
316
|
-
|
|
317
|
-
if (
|
|
318
|
-
|
|
319
|
-
await remove(target.skillsDir);
|
|
250
|
+
const cleanup = await cleanupEmptyDirs(target, removeAll);
|
|
251
|
+
if (cleanup.claudeSrcDirRemoved) {
|
|
252
|
+
this.logSuccess(`Removed ${CLAUDE_SRC_DIR}/`);
|
|
320
253
|
}
|
|
254
|
+
if (cleanup.claudeDirRemoved) {
|
|
255
|
+
this.logSuccess(`Removed ${CLAUDE_DIR}/`);
|
|
256
|
+
} else if (cleanup.claudeDirKept) {
|
|
257
|
+
this.log(`Kept ${CLAUDE_DIR}/ (contains user content)`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
function hasAnythingToRemove(target, removeAll) {
|
|
262
|
+
return target.hasPlugins || target.hasLocalSkills || target.hasLocalAgents || removeAll && target.hasClaudeSrcDir;
|
|
263
|
+
}
|
|
264
|
+
function collectConfiguredAgents(config) {
|
|
265
|
+
if (!config?.agents) return [];
|
|
266
|
+
return config.agents.map((a) => a.name);
|
|
267
|
+
}
|
|
268
|
+
function getCliInstalledPluginKeys(config) {
|
|
269
|
+
if (!config?.skills) return /* @__PURE__ */ new Set();
|
|
270
|
+
return new Set(config.skills.map((skill) => `${skill.id}@${skill.source}`));
|
|
271
|
+
}
|
|
272
|
+
async function detectUninstallTarget(projectDir) {
|
|
273
|
+
const pluginsDir = getProjectPluginsDir(projectDir);
|
|
274
|
+
const skillsDir = path.join(projectDir, CLAUDE_DIR, "skills");
|
|
275
|
+
const agentsDir = path.join(projectDir, CLAUDE_DIR, "agents");
|
|
276
|
+
const claudeDir = path.join(projectDir, CLAUDE_DIR);
|
|
277
|
+
const claudeSrcDir = path.join(projectDir, CLAUDE_SRC_DIR);
|
|
278
|
+
const [hasLocalSkills, hasLocalAgents, hasClaudeDir, hasClaudeSrcDir, config] = await Promise.all(
|
|
279
|
+
[
|
|
280
|
+
directoryExists(skillsDir),
|
|
281
|
+
directoryExists(agentsDir),
|
|
282
|
+
directoryExists(claudeDir),
|
|
283
|
+
directoryExists(claudeSrcDir),
|
|
284
|
+
loadProjectConfigFromDir(projectDir).then((result) => result?.config ?? null)
|
|
285
|
+
]
|
|
286
|
+
);
|
|
287
|
+
let pluginNames = [];
|
|
288
|
+
try {
|
|
289
|
+
pluginNames = await listPluginNames(projectDir);
|
|
290
|
+
} catch {
|
|
291
|
+
}
|
|
292
|
+
const configuredAgents = collectConfiguredAgents(config);
|
|
293
|
+
const cliInstalledKeys = getCliInstalledPluginKeys(config);
|
|
294
|
+
const cliPluginNames = pluginNames.filter((name) => cliInstalledKeys.has(name));
|
|
295
|
+
return {
|
|
296
|
+
hasPlugins: cliPluginNames.length > 0,
|
|
297
|
+
pluginNames,
|
|
298
|
+
cliPluginNames,
|
|
299
|
+
hasLocalSkills,
|
|
300
|
+
hasLocalAgents,
|
|
301
|
+
hasClaudeDir,
|
|
302
|
+
hasClaudeSrcDir,
|
|
303
|
+
pluginsDir,
|
|
304
|
+
skillsDir,
|
|
305
|
+
agentsDir,
|
|
306
|
+
claudeDir,
|
|
307
|
+
claudeSrcDir,
|
|
308
|
+
config,
|
|
309
|
+
configuredAgents
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
function shouldRemoveSkill(forkedFrom) {
|
|
313
|
+
return forkedFrom !== null;
|
|
314
|
+
}
|
|
315
|
+
async function removeMatchingSkills(target, onRemoved, onSkipped) {
|
|
316
|
+
if (!target.hasLocalSkills) {
|
|
317
|
+
return {
|
|
318
|
+
removedCount: 0,
|
|
319
|
+
skippedCount: 0,
|
|
320
|
+
removedNames: [],
|
|
321
|
+
skippedNames: [],
|
|
322
|
+
dirCleaned: false
|
|
323
|
+
};
|
|
321
324
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
325
|
+
const skillDirNames = await listDirectories(target.skillsDir);
|
|
326
|
+
const removedNames = [];
|
|
327
|
+
const skippedNames = [];
|
|
328
|
+
for (const skillDirName of skillDirNames) {
|
|
329
|
+
const skillDir = path.join(target.skillsDir, skillDirName);
|
|
330
|
+
const forkedFrom = await readForkedFromMetadata(skillDir);
|
|
331
|
+
if (shouldRemoveSkill(forkedFrom)) {
|
|
332
|
+
await remove(skillDir);
|
|
333
|
+
removedNames.push(skillDirName);
|
|
334
|
+
onRemoved?.(skillDirName);
|
|
335
|
+
} else {
|
|
336
|
+
skippedNames.push(skillDirName);
|
|
337
|
+
onSkipped?.(skillDirName);
|
|
333
338
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
339
|
+
}
|
|
340
|
+
let dirCleaned = false;
|
|
341
|
+
if (skippedNames.length === 0 && await directoryExists(target.skillsDir)) {
|
|
342
|
+
if (await isDirectoryEmpty(target.skillsDir)) {
|
|
343
|
+
await remove(target.skillsDir);
|
|
344
|
+
dirCleaned = true;
|
|
338
345
|
}
|
|
339
|
-
|
|
346
|
+
}
|
|
347
|
+
return {
|
|
348
|
+
removedCount: removedNames.length,
|
|
349
|
+
skippedCount: skippedNames.length,
|
|
350
|
+
removedNames,
|
|
351
|
+
skippedNames,
|
|
352
|
+
dirCleaned
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
async function removeMatchingAgents(target, onRemoved) {
|
|
356
|
+
if (!target.hasLocalAgents) {
|
|
357
|
+
return { removedCount: 0, removedNames: [], dirCleaned: false };
|
|
358
|
+
}
|
|
359
|
+
if (target.configuredAgents.length === 0) {
|
|
360
|
+
return { removedCount: 0, removedNames: [], dirCleaned: false };
|
|
361
|
+
}
|
|
362
|
+
const agentFiles = await listAgentFiles(target.agentsDir);
|
|
363
|
+
const removedNames = [];
|
|
364
|
+
for (const agentFile of agentFiles) {
|
|
365
|
+
const agentName = agentFile.replace(/\.md$/, "");
|
|
366
|
+
if (!target.configuredAgents.includes(agentName)) continue;
|
|
367
|
+
await remove(path.join(target.agentsDir, agentFile));
|
|
368
|
+
removedNames.push(agentName);
|
|
369
|
+
onRemoved?.(agentName);
|
|
370
|
+
}
|
|
371
|
+
let dirCleaned = false;
|
|
372
|
+
if (await directoryExists(target.agentsDir)) {
|
|
340
373
|
if (await isDirectoryEmpty(target.agentsDir)) {
|
|
341
374
|
await remove(target.agentsDir);
|
|
375
|
+
dirCleaned = true;
|
|
342
376
|
}
|
|
343
377
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
378
|
+
return {
|
|
379
|
+
removedCount: removedNames.length,
|
|
380
|
+
removedNames,
|
|
381
|
+
dirCleaned
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
async function uninstallPlugins(target, projectDir, onUninstalled) {
|
|
385
|
+
if (!target.hasPlugins) {
|
|
386
|
+
return { uninstalledNames: [], totalUninstalled: 0 };
|
|
387
|
+
}
|
|
388
|
+
const cliAvailable = await isClaudeCLIAvailable();
|
|
389
|
+
const uninstalledNames = [];
|
|
390
|
+
for (const pluginName of target.cliPluginNames) {
|
|
391
|
+
if (cliAvailable) {
|
|
392
|
+
try {
|
|
393
|
+
const skillId = pluginName.split("@")[0];
|
|
394
|
+
const skillConfig = target.config?.skills?.find((s) => s.id === skillId);
|
|
395
|
+
const pluginScope = skillConfig?.scope === "global" ? "user" : "project";
|
|
396
|
+
await claudePluginUninstall(pluginName, pluginScope, projectDir);
|
|
397
|
+
} catch {
|
|
398
|
+
}
|
|
350
399
|
}
|
|
400
|
+
const pluginPath = path.join(target.pluginsDir, pluginName);
|
|
401
|
+
await remove(pluginPath);
|
|
402
|
+
uninstalledNames.push(pluginName);
|
|
403
|
+
onUninstalled?.(pluginName);
|
|
351
404
|
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
405
|
+
return {
|
|
406
|
+
uninstalledNames,
|
|
407
|
+
totalUninstalled: uninstalledNames.length
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
async function cleanupEmptyDirs(target, removeAll) {
|
|
411
|
+
let claudeSrcDirRemoved = false;
|
|
412
|
+
if (removeAll && target.hasClaudeSrcDir) {
|
|
413
|
+
await remove(target.claudeSrcDir);
|
|
414
|
+
claudeSrcDirRemoved = true;
|
|
415
|
+
}
|
|
416
|
+
let claudeDirRemoved = false;
|
|
417
|
+
let claudeDirKept = false;
|
|
418
|
+
if (target.hasClaudeDir && await directoryExists(target.claudeDir)) {
|
|
355
419
|
if (await isDirectoryEmpty(target.claudeDir)) {
|
|
356
420
|
await remove(target.claudeDir);
|
|
357
|
-
|
|
421
|
+
claudeDirRemoved = true;
|
|
358
422
|
} else {
|
|
359
|
-
|
|
423
|
+
claudeDirKept = true;
|
|
360
424
|
}
|
|
361
425
|
}
|
|
362
|
-
};
|
|
426
|
+
return { claudeDirRemoved, claudeSrcDirRemoved, claudeDirKept };
|
|
427
|
+
}
|
|
428
|
+
async function isDirectoryEmpty(dirPath) {
|
|
429
|
+
try {
|
|
430
|
+
const allEntries = await readdir(dirPath);
|
|
431
|
+
return allEntries.length === 0;
|
|
432
|
+
} catch {
|
|
433
|
+
return true;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
async function listAgentFiles(agentsDir) {
|
|
437
|
+
try {
|
|
438
|
+
return (await readdir(agentsDir)).filter((f) => f.endsWith(".md"));
|
|
439
|
+
} catch {
|
|
440
|
+
return [];
|
|
441
|
+
}
|
|
442
|
+
}
|
|
363
443
|
export {
|
|
364
444
|
Uninstall as default
|
|
365
445
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/commands/uninstall.tsx"],"sourcesContent":["import React from \"react\";\n\nimport { Flags } from \"@oclif/core\";\nimport { render, Box, Text, useApp } from \"ink\";\nimport path from \"path\";\n\nimport { BaseCommand } from \"../base-command\";\nimport { Confirm } from \"../components/common/confirm\";\nimport { getErrorMessage } from \"../utils/errors\";\nimport { directoryExists, listDirectories, remove } from \"../utils/fs\";\nimport { claudePluginUninstall, isClaudeCLIAvailable } from \"../utils/exec\";\nimport { listPluginNames, getProjectPluginsDir } from \"../lib/plugins\";\nimport { readForkedFromMetadata } from \"../lib/skills\";\nimport { loadProjectConfigFromDir } from \"../lib/configuration/project-config\";\nimport type { ProjectConfig } from \"../types\";\nimport { CLAUDE_DIR, CLAUDE_SRC_DIR, CLI_COLORS, DEFAULT_BRANDING } from \"../consts\";\nimport { EXIT_CODES } from \"../lib/exit-codes\";\nimport { SUCCESS_MESSAGES, INFO_MESSAGES } from \"../utils/messages\";\n\ntype UninstallTarget = {\n hasPlugins: boolean;\n pluginNames: string[];\n /** Plugin names filtered to only those installed by this CLI (matched against config skills) */\n cliPluginNames: string[];\n hasLocalSkills: boolean;\n hasLocalAgents: boolean;\n hasClaudeDir: boolean;\n hasClaudeSrcDir: boolean;\n pluginsDir: string;\n skillsDir: string;\n agentsDir: string;\n claudeDir: string;\n claudeSrcDir: string;\n /** Resolved project source config from .claude-src/config.ts */\n config: Partial<ProjectConfig> | null;\n /** Agent names from the generated config (e.g., [\"web-developer\"]) */\n configuredAgents: string[];\n};\n\nfunction collectConfiguredAgents(config: Partial<ProjectConfig> | null): string[] {\n if (!config?.agents) return [];\n return config.agents.map((a) => a.name);\n}\n\nfunction getCliInstalledPluginKeys(config: Partial<ProjectConfig> | null): Set<string> {\n if (!config?.skills) return new Set();\n return new Set(config.skills.map((skill) => `${skill.id}@${skill.source}`));\n}\n\nasync function detectUninstallTarget(projectDir: string): Promise<UninstallTarget> {\n const pluginsDir = getProjectPluginsDir(projectDir);\n const skillsDir = path.join(projectDir, CLAUDE_DIR, \"skills\");\n const agentsDir = path.join(projectDir, CLAUDE_DIR, \"agents\");\n const claudeDir = path.join(projectDir, CLAUDE_DIR);\n const claudeSrcDir = path.join(projectDir, CLAUDE_SRC_DIR);\n\n const [hasLocalSkills, hasLocalAgents, hasClaudeDir, hasClaudeSrcDir, config] = await Promise.all(\n [\n directoryExists(skillsDir),\n directoryExists(agentsDir),\n directoryExists(claudeDir),\n directoryExists(claudeSrcDir),\n loadProjectConfigFromDir(projectDir).then((result) => result?.config ?? null),\n ],\n );\n\n let pluginNames: string[] = [];\n try {\n pluginNames = await listPluginNames(projectDir);\n } catch {\n // Best-effort: plugin detection may fail\n }\n\n const configuredAgents = collectConfiguredAgents(config);\n const cliInstalledKeys = getCliInstalledPluginKeys(config);\n const cliPluginNames = pluginNames.filter((name) => cliInstalledKeys.has(name));\n\n return {\n hasPlugins: cliPluginNames.length > 0,\n pluginNames,\n cliPluginNames,\n hasLocalSkills,\n hasLocalAgents,\n hasClaudeDir,\n hasClaudeSrcDir,\n pluginsDir,\n skillsDir,\n agentsDir,\n claudeDir,\n claudeSrcDir,\n config,\n configuredAgents,\n };\n}\n\ntype UninstallConfirmProps = {\n target: UninstallTarget;\n removeAll: boolean;\n onConfirm: () => void;\n onCancel: () => void;\n};\n\nconst UninstallConfirm: React.FC<UninstallConfirmProps> = ({\n target,\n removeAll,\n onConfirm,\n onCancel,\n}) => {\n const { exit } = useApp();\n\n return (\n <Box flexDirection=\"column\">\n <Text bold>The following will be removed:</Text>\n <Text> </Text>\n\n {target.hasPlugins && (\n <Box flexDirection=\"column\">\n <Text color={CLI_COLORS.ERROR}> Plugins:</Text>\n {target.cliPluginNames.map((name) => (\n <Text key={name} dimColor>\n {\" \"}\n {name}\n </Text>\n ))}\n </Box>\n )}\n\n {(target.hasLocalSkills || target.hasLocalAgents) && (\n <Box flexDirection=\"column\">\n <Text color={CLI_COLORS.ERROR}> CLI-managed files:</Text>\n {target.hasLocalSkills && <Text dimColor> {target.skillsDir}/ (matching sources)</Text>}\n {target.hasLocalAgents && <Text dimColor> {target.agentsDir}/ (CLI-compiled)</Text>}\n </Box>\n )}\n\n {removeAll && target.hasClaudeSrcDir && (\n <Box flexDirection=\"column\">\n <Text color={CLI_COLORS.ERROR}> Config:</Text>\n <Text dimColor> {target.claudeSrcDir}/</Text>\n </Box>\n )}\n\n <Text> </Text>\n <Confirm\n message=\"Are you sure you want to uninstall?\"\n onConfirm={() => {\n onConfirm();\n exit();\n }}\n onCancel={() => {\n onCancel();\n exit();\n }}\n defaultValue={false}\n />\n </Box>\n );\n};\n\nasync function isDirectoryEmpty(dirPath: string): Promise<boolean> {\n const { readdir } = await import(\"fs/promises\");\n try {\n const allEntries = await readdir(dirPath);\n return allEntries.length === 0;\n } catch {\n return true;\n }\n}\n\nfunction shouldRemoveSkill(forkedFrom: { source?: string } | null): boolean {\n return forkedFrom !== null;\n}\n\nexport default class Uninstall extends BaseCommand {\n static summary = `Remove ${DEFAULT_BRANDING.NAME} from this project`;\n\n static description = `Uninstall ${DEFAULT_BRANDING.NAME} from this project. Removes CLI-managed skills (matched by source), compiled agents, and plugins. User-created content is preserved.`;\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"<%= config.bin %> <%= command.id %> --yes\",\n \"<%= config.bin %> <%= command.id %> --all\",\n ];\n\n static flags = {\n ...BaseCommand.baseFlags,\n yes: Flags.boolean({\n char: \"y\",\n description: \"Skip confirmation prompt\",\n default: false,\n }),\n all: Flags.boolean({\n description: \"Also remove .claude-src/ config directory\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Uninstall);\n const projectDir = process.cwd();\n\n this.log(\"\");\n this.log(`${DEFAULT_BRANDING.NAME} Uninstall`);\n this.log(\"\");\n\n const target = await detectUninstallTarget(projectDir);\n\n const hasAnythingToRemove =\n target.hasPlugins ||\n target.hasLocalSkills ||\n target.hasLocalAgents ||\n (flags.all && target.hasClaudeSrcDir);\n\n if (!hasAnythingToRemove) {\n this.warn(\"Nothing to uninstall.\");\n this.log(\"\");\n this.log(INFO_MESSAGES.NOT_INSTALLED);\n this.log(\"\");\n this.log(INFO_MESSAGES.NO_CHANGES_MADE);\n return;\n }\n\n if (!flags.yes) {\n const confirmed = await new Promise<boolean>((resolve) => {\n const { waitUntilExit } = render(\n <UninstallConfirm\n target={target}\n removeAll={flags.all}\n onConfirm={() => resolve(true)}\n onCancel={() => resolve(false)}\n />,\n );\n\n waitUntilExit().catch(() => resolve(false));\n });\n\n if (!confirmed) {\n this.log(\"\");\n this.log(\"Uninstall cancelled\");\n this.exit(EXIT_CODES.CANCELLED);\n }\n } else {\n this.log(\"The following will be removed:\");\n this.log(\"\");\n\n if (target.hasPlugins) {\n this.log(\" Plugins:\");\n for (const pluginName of target.cliPluginNames) {\n this.log(` ${pluginName}`);\n }\n }\n\n if (target.hasLocalSkills || target.hasLocalAgents) {\n this.log(\" CLI-managed files:\");\n if (target.hasLocalSkills) {\n this.log(` ${target.skillsDir}/ (matching sources)`);\n }\n if (target.hasLocalAgents) {\n this.log(` ${target.agentsDir}/ (CLI-compiled)`);\n }\n }\n\n if (flags.all && target.hasClaudeSrcDir) {\n this.log(\" Config:\");\n this.log(` ${target.claudeSrcDir}/`);\n }\n\n this.log(\"\");\n }\n\n if (target.hasPlugins) {\n this.log(\"Uninstalling plugins...\");\n\n try {\n const cliAvailable = await isClaudeCLIAvailable();\n\n for (const pluginName of target.cliPluginNames) {\n if (cliAvailable) {\n try {\n // Derive scope from per-skill config; fall back to project-level heuristic\n const skillId = pluginName.split(\"@\")[0];\n const skillConfig = target.config?.skills?.find((s) => s.id === skillId);\n const pluginScope = skillConfig?.scope === \"global\" ? \"user\" : \"project\";\n await claudePluginUninstall(pluginName, pluginScope, projectDir);\n } catch {\n // Best-effort: plugin may not be registered with Claude CLI\n }\n }\n\n const pluginPath = path.join(target.pluginsDir, pluginName);\n await remove(pluginPath);\n this.log(` Uninstalled plugin '${pluginName}'`);\n }\n\n this.logSuccess(\n `Uninstalled ${target.cliPluginNames.length} ${target.cliPluginNames.length === 1 ? \"plugin\" : \"plugins\"}`,\n );\n } catch (error) {\n this.log(\"Plugin uninstall failed\");\n this.error(getErrorMessage(error), {\n exit: EXIT_CODES.ERROR,\n });\n }\n }\n\n try {\n await this.removeLocalFiles(target, flags.all);\n } catch (error) {\n this.log(\"Failed to remove local files\");\n this.error(getErrorMessage(error), {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n this.log(\"\");\n this.log(`${DEFAULT_BRANDING.NAME} has been uninstalled.`);\n this.log(\"\");\n this.logSuccess(SUCCESS_MESSAGES.UNINSTALL_COMPLETE);\n this.log(\"\");\n }\n\n private async removeLocalFiles(target: UninstallTarget, removeAll: boolean): Promise<void> {\n await this.removeMatchingSkills(target);\n await this.removeMatchingAgents(target);\n\n if (removeAll && target.hasClaudeSrcDir) {\n await remove(target.claudeSrcDir);\n this.logSuccess(`Removed ${CLAUDE_SRC_DIR}/`);\n }\n\n await this.removeEmptyClaudeDir(target);\n }\n\n private async removeMatchingSkills(target: UninstallTarget): Promise<void> {\n if (!target.hasLocalSkills) return;\n\n const skillDirNames = await listDirectories(target.skillsDir);\n let removedCount = 0;\n let skippedCount = 0;\n\n for (const skillDirName of skillDirNames) {\n const skillDir = path.join(target.skillsDir, skillDirName);\n const forkedFrom = await readForkedFromMetadata(skillDir);\n\n if (shouldRemoveSkill(forkedFrom)) {\n await remove(skillDir);\n removedCount++;\n this.log(` Uninstalled skill '${skillDirName}'`);\n } else {\n this.warn(`Skipping '${skillDirName}': not created by ${DEFAULT_BRANDING.NAME} CLI`);\n skippedCount++;\n }\n }\n\n if (removedCount > 0) {\n this.logSuccess(\n `Removed ${removedCount} CLI-installed ${removedCount === 1 ? \"skill\" : \"skills\"}`,\n );\n }\n\n if (skippedCount > 0) return;\n if (!(await directoryExists(target.skillsDir))) return;\n if (await isDirectoryEmpty(target.skillsDir)) {\n await remove(target.skillsDir);\n }\n }\n\n private async removeMatchingAgents(target: UninstallTarget): Promise<void> {\n if (!target.hasLocalAgents) return;\n if (target.configuredAgents.length === 0) return;\n\n const agentFiles = await this.listAgentFiles(target.agentsDir);\n let removedCount = 0;\n\n for (const agentFile of agentFiles) {\n const agentName = agentFile.replace(/\\.md$/, \"\");\n if (!target.configuredAgents.includes(agentName)) continue;\n\n await remove(path.join(target.agentsDir, agentFile));\n this.log(` Uninstalled agent '${agentName}'`);\n removedCount++;\n }\n\n if (removedCount > 0) {\n this.logSuccess(\n `Removed ${removedCount} compiled ${removedCount === 1 ? \"agent\" : \"agents\"}`,\n );\n }\n\n if (!(await directoryExists(target.agentsDir))) return;\n if (await isDirectoryEmpty(target.agentsDir)) {\n await remove(target.agentsDir);\n }\n }\n\n private async listAgentFiles(agentsDir: string): Promise<string[]> {\n try {\n const { readdir } = await import(\"fs/promises\");\n return (await readdir(agentsDir)).filter((f) => f.endsWith(\".md\"));\n } catch {\n return [];\n }\n }\n\n private async removeEmptyClaudeDir(target: UninstallTarget): Promise<void> {\n if (!target.hasClaudeDir) return;\n if (!(await directoryExists(target.claudeDir))) return;\n\n if (await isDirectoryEmpty(target.claudeDir)) {\n await remove(target.claudeDir);\n this.logSuccess(`Removed ${CLAUDE_DIR}/`);\n } else {\n this.log(`Kept ${CLAUDE_DIR}/ (contains user content)`);\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/uninstall.tsx"],"sourcesContent":["import React from \"react\";\nimport path from \"path\";\nimport { readdir } from \"fs/promises\";\n\nimport { Flags } from \"@oclif/core\";\nimport { render, Box, Text, useApp } from \"ink\";\n\nimport { BaseCommand } from \"../base-command\";\nimport { Confirm } from \"../components/common/confirm\";\nimport { getErrorMessage } from \"../utils/errors\";\nimport { directoryExists, listDirectories, remove } from \"../utils/fs\";\nimport { claudePluginUninstall, isClaudeCLIAvailable } from \"../utils/exec\";\nimport { listPluginNames, getProjectPluginsDir } from \"../lib/plugins/index\";\nimport { readForkedFromMetadata } from \"../lib/skills/index\";\nimport { loadProjectConfigFromDir } from \"../lib/configuration/project-config\";\nimport { CLAUDE_DIR, CLAUDE_SRC_DIR, CLI_COLORS, DEFAULT_BRANDING } from \"../consts\";\nimport { EXIT_CODES } from \"../lib/exit-codes\";\nimport { SUCCESS_MESSAGES, INFO_MESSAGES } from \"../utils/messages\";\nimport type { ProjectConfig } from \"../types/index\";\n\ntype UninstallConfirmProps = {\n target: UninstallTarget;\n removeAll: boolean;\n onConfirm: () => void;\n onCancel: () => void;\n};\n\nconst UninstallConfirm: React.FC<UninstallConfirmProps> = ({\n target,\n removeAll,\n onConfirm,\n onCancel,\n}) => {\n const { exit } = useApp();\n\n return (\n <Box flexDirection=\"column\">\n <Text bold>The following will be removed:</Text>\n <Text> </Text>\n\n {target.hasPlugins && (\n <Box flexDirection=\"column\">\n <Text color={CLI_COLORS.ERROR}> Plugins:</Text>\n {target.cliPluginNames.map((name) => (\n <Text key={name} dimColor>\n {\" \"}\n {name}\n </Text>\n ))}\n </Box>\n )}\n\n {(target.hasLocalSkills || target.hasLocalAgents) && (\n <Box flexDirection=\"column\">\n <Text color={CLI_COLORS.ERROR}> CLI-managed files:</Text>\n {target.hasLocalSkills && <Text dimColor> {target.skillsDir}/ (matching sources)</Text>}\n {target.hasLocalAgents && <Text dimColor> {target.agentsDir}/ (CLI-compiled)</Text>}\n </Box>\n )}\n\n {removeAll && target.hasClaudeSrcDir && (\n <Box flexDirection=\"column\">\n <Text color={CLI_COLORS.ERROR}> Config:</Text>\n <Text dimColor> {target.claudeSrcDir}/</Text>\n </Box>\n )}\n\n <Text> </Text>\n <Confirm\n message=\"Are you sure you want to uninstall?\"\n onConfirm={() => {\n onConfirm();\n exit();\n }}\n onCancel={() => {\n onCancel();\n exit();\n }}\n defaultValue={false}\n />\n </Box>\n );\n};\n\nexport default class Uninstall extends BaseCommand {\n static summary = `Remove ${DEFAULT_BRANDING.NAME} from this project`;\n\n static description = `Uninstall ${DEFAULT_BRANDING.NAME} from this project. Removes CLI-managed skills (matched by source), compiled agents, and plugins. User-created content is preserved.`;\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"<%= config.bin %> <%= command.id %> --yes\",\n \"<%= config.bin %> <%= command.id %> --all\",\n ];\n\n static flags = {\n ...BaseCommand.baseFlags,\n yes: Flags.boolean({\n char: \"y\",\n description: \"Skip confirmation prompt\",\n default: false,\n }),\n all: Flags.boolean({\n description: \"Also remove .claude-src/ config directory\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Uninstall);\n const projectDir = process.cwd();\n\n this.printHeader();\n\n const target = await detectUninstallTarget(projectDir);\n if (!hasAnythingToRemove(target, flags.all)) {\n this.reportNothingToUninstall();\n return;\n }\n\n const confirmed = flags.yes\n ? this.printRemovalPlan(target, flags.all)\n : await this.confirmRemoval(target, flags.all);\n if (!confirmed) {\n this.log(\"\");\n this.log(\"Uninstall cancelled\");\n this.exit(EXIT_CODES.CANCELLED);\n }\n\n await this.executeUninstall(target, projectDir, flags.all);\n this.reportSuccess();\n }\n\n private printHeader(): void {\n this.log(\"\");\n this.log(`${DEFAULT_BRANDING.NAME} Uninstall`);\n this.log(\"\");\n }\n\n private reportNothingToUninstall(): void {\n this.warn(\"Nothing to uninstall.\");\n this.log(\"\");\n this.log(INFO_MESSAGES.NOT_INSTALLED);\n this.log(\"\");\n this.log(INFO_MESSAGES.NO_CHANGES_MADE);\n }\n\n private printRemovalPlan(target: UninstallTarget, removeAll: boolean): true {\n this.log(\"The following will be removed:\");\n this.log(\"\");\n\n if (target.hasPlugins) {\n this.log(\" Plugins:\");\n for (const pluginName of target.cliPluginNames) {\n this.log(` ${pluginName}`);\n }\n }\n\n if (target.hasLocalSkills || target.hasLocalAgents) {\n this.log(\" CLI-managed files:\");\n if (target.hasLocalSkills) {\n this.log(` ${target.skillsDir}/ (matching sources)`);\n }\n if (target.hasLocalAgents) {\n this.log(` ${target.agentsDir}/ (CLI-compiled)`);\n }\n }\n\n if (removeAll && target.hasClaudeSrcDir) {\n this.log(\" Config:\");\n this.log(` ${target.claudeSrcDir}/`);\n }\n\n this.log(\"\");\n return true;\n }\n\n private async confirmRemoval(target: UninstallTarget, removeAll: boolean): Promise<boolean> {\n return new Promise<boolean>((resolve) => {\n const { waitUntilExit } = render(\n <UninstallConfirm\n target={target}\n removeAll={removeAll}\n onConfirm={() => resolve(true)}\n onCancel={() => resolve(false)}\n />,\n );\n\n waitUntilExit().catch(() => resolve(false));\n });\n }\n\n private async executeUninstall(\n target: UninstallTarget,\n projectDir: string,\n removeAll: boolean,\n ): Promise<void> {\n if (target.hasPlugins) {\n this.log(\"Uninstalling plugins...\");\n\n try {\n const pluginResult = await uninstallPlugins(target, projectDir, (name) =>\n this.log(` Uninstalled plugin '${name}'`),\n );\n\n this.logSuccess(\n `Uninstalled ${pluginResult.totalUninstalled} ${pluginResult.totalUninstalled === 1 ? \"plugin\" : \"plugins\"}`,\n );\n } catch (error) {\n this.log(\"Plugin uninstall failed\");\n this.error(getErrorMessage(error), {\n exit: EXIT_CODES.ERROR,\n });\n }\n }\n\n try {\n await this.removeLocalFiles(target, removeAll);\n } catch (error) {\n this.log(\"Failed to remove local files\");\n this.error(getErrorMessage(error), {\n exit: EXIT_CODES.ERROR,\n });\n }\n }\n\n private reportSuccess(): void {\n this.log(\"\");\n this.log(`${DEFAULT_BRANDING.NAME} has been uninstalled.`);\n this.log(\"\");\n this.logSuccess(SUCCESS_MESSAGES.UNINSTALL_COMPLETE);\n this.log(\"\");\n }\n\n private async removeLocalFiles(target: UninstallTarget, removeAll: boolean): Promise<void> {\n const skillResult = await removeMatchingSkills(\n target,\n (dirName) => this.log(` Uninstalled skill '${dirName}'`),\n (dirName) => this.warn(`Skipping '${dirName}': not created by ${DEFAULT_BRANDING.NAME} CLI`),\n );\n\n if (skillResult.removedCount > 0) {\n this.logSuccess(\n `Removed ${skillResult.removedCount} CLI-installed ${skillResult.removedCount === 1 ? \"skill\" : \"skills\"}`,\n );\n }\n\n const agentResult = await removeMatchingAgents(target, (agentName) =>\n this.log(` Uninstalled agent '${agentName}'`),\n );\n\n if (agentResult.removedCount > 0) {\n this.logSuccess(\n `Removed ${agentResult.removedCount} compiled ${agentResult.removedCount === 1 ? \"agent\" : \"agents\"}`,\n );\n }\n\n const cleanup = await cleanupEmptyDirs(target, removeAll);\n\n if (cleanup.claudeSrcDirRemoved) {\n this.logSuccess(`Removed ${CLAUDE_SRC_DIR}/`);\n }\n\n if (cleanup.claudeDirRemoved) {\n this.logSuccess(`Removed ${CLAUDE_DIR}/`);\n } else if (cleanup.claudeDirKept) {\n this.log(`Kept ${CLAUDE_DIR}/ (contains user content)`);\n }\n }\n}\n\ntype UninstallTarget = {\n hasPlugins: boolean;\n pluginNames: string[];\n /** Plugin names filtered to only those installed by this CLI (matched against config skills) */\n cliPluginNames: string[];\n hasLocalSkills: boolean;\n hasLocalAgents: boolean;\n hasClaudeDir: boolean;\n hasClaudeSrcDir: boolean;\n pluginsDir: string;\n skillsDir: string;\n agentsDir: string;\n claudeDir: string;\n claudeSrcDir: string;\n /** Resolved project source config from .claude-src/config.ts */\n config: Partial<ProjectConfig> | null;\n /** Agent names from the generated config (e.g., [\"web-developer\"]) */\n configuredAgents: string[];\n};\n\ntype SkillRemovalResult = {\n removedCount: number;\n skippedCount: number;\n removedNames: string[];\n skippedNames: string[];\n /** Whether the skills directory was cleaned up (empty after removal) */\n dirCleaned: boolean;\n};\n\ntype AgentRemovalResult = {\n removedCount: number;\n removedNames: string[];\n /** Whether the agents directory was cleaned up (empty after removal) */\n dirCleaned: boolean;\n};\n\ntype UninstallPluginsResult = {\n uninstalledNames: string[];\n totalUninstalled: number;\n};\n\ntype CleanupResult = {\n claudeDirRemoved: boolean;\n claudeSrcDirRemoved: boolean;\n /** Whether .claude/ still exists with user content after cleanup */\n claudeDirKept: boolean;\n};\n\nfunction hasAnythingToRemove(target: UninstallTarget, removeAll: boolean): boolean {\n return (\n target.hasPlugins ||\n target.hasLocalSkills ||\n target.hasLocalAgents ||\n (removeAll && target.hasClaudeSrcDir)\n );\n}\n\nfunction collectConfiguredAgents(config: Partial<ProjectConfig> | null): string[] {\n if (!config?.agents) return [];\n return config.agents.map((a) => a.name);\n}\n\nfunction getCliInstalledPluginKeys(config: Partial<ProjectConfig> | null): Set<string> {\n if (!config?.skills) return new Set();\n return new Set(config.skills.map((skill) => `${skill.id}@${skill.source}`));\n}\n\n/**\n * Detects what's installed in a project directory for uninstallation.\n *\n * Checks for plugins, local skills, agents, config directories, and\n * resolves which plugins were installed by this CLI.\n */\nasync function detectUninstallTarget(projectDir: string): Promise<UninstallTarget> {\n const pluginsDir = getProjectPluginsDir(projectDir);\n const skillsDir = path.join(projectDir, CLAUDE_DIR, \"skills\");\n const agentsDir = path.join(projectDir, CLAUDE_DIR, \"agents\");\n const claudeDir = path.join(projectDir, CLAUDE_DIR);\n const claudeSrcDir = path.join(projectDir, CLAUDE_SRC_DIR);\n\n const [hasLocalSkills, hasLocalAgents, hasClaudeDir, hasClaudeSrcDir, config] = await Promise.all(\n [\n directoryExists(skillsDir),\n directoryExists(agentsDir),\n directoryExists(claudeDir),\n directoryExists(claudeSrcDir),\n loadProjectConfigFromDir(projectDir).then((result) => result?.config ?? null),\n ],\n );\n\n let pluginNames: string[] = [];\n try {\n pluginNames = await listPluginNames(projectDir);\n } catch {\n // Best-effort: plugin detection may fail\n }\n\n const configuredAgents = collectConfiguredAgents(config);\n const cliInstalledKeys = getCliInstalledPluginKeys(config);\n const cliPluginNames = pluginNames.filter((name) => cliInstalledKeys.has(name));\n\n return {\n hasPlugins: cliPluginNames.length > 0,\n pluginNames,\n cliPluginNames,\n hasLocalSkills,\n hasLocalAgents,\n hasClaudeDir,\n hasClaudeSrcDir,\n pluginsDir,\n skillsDir,\n agentsDir,\n claudeDir,\n claudeSrcDir,\n config,\n configuredAgents,\n };\n}\n\nfunction shouldRemoveSkill(forkedFrom: { source?: string } | null): boolean {\n return forkedFrom !== null;\n}\n\n/**\n * Removes local skills that were installed by the CLI (have forked-from metadata).\n *\n * Scans the skills directory, checks each skill for CLI-installed metadata,\n * and removes matching skills. User-created skills (without metadata) are preserved.\n *\n * @param onRemoved - Called for each removed skill directory name (for logging)\n * @param onSkipped - Called for each skipped skill directory name (for logging)\n */\nasync function removeMatchingSkills(\n target: Pick<UninstallTarget, \"hasLocalSkills\" | \"skillsDir\">,\n onRemoved?: (dirName: string) => void,\n onSkipped?: (dirName: string) => void,\n): Promise<SkillRemovalResult> {\n if (!target.hasLocalSkills) {\n return {\n removedCount: 0,\n skippedCount: 0,\n removedNames: [],\n skippedNames: [],\n dirCleaned: false,\n };\n }\n\n const skillDirNames = await listDirectories(target.skillsDir);\n const removedNames: string[] = [];\n const skippedNames: string[] = [];\n\n for (const skillDirName of skillDirNames) {\n const skillDir = path.join(target.skillsDir, skillDirName);\n const forkedFrom = await readForkedFromMetadata(skillDir);\n\n if (shouldRemoveSkill(forkedFrom)) {\n await remove(skillDir);\n removedNames.push(skillDirName);\n onRemoved?.(skillDirName);\n } else {\n skippedNames.push(skillDirName);\n onSkipped?.(skillDirName);\n }\n }\n\n let dirCleaned = false;\n if (skippedNames.length === 0 && (await directoryExists(target.skillsDir))) {\n if (await isDirectoryEmpty(target.skillsDir)) {\n await remove(target.skillsDir);\n dirCleaned = true;\n }\n }\n\n return {\n removedCount: removedNames.length,\n skippedCount: skippedNames.length,\n removedNames,\n skippedNames,\n dirCleaned,\n };\n}\n\n/**\n * Removes compiled agent .md files that match configured agent names.\n *\n * Only removes agents that are listed in the project config (CLI-compiled).\n * Cleans up the agents directory if empty after removal.\n *\n * @param onRemoved - Called for each removed agent name (for logging)\n */\nasync function removeMatchingAgents(\n target: Pick<UninstallTarget, \"hasLocalAgents\" | \"agentsDir\" | \"configuredAgents\">,\n onRemoved?: (agentName: string) => void,\n): Promise<AgentRemovalResult> {\n if (!target.hasLocalAgents) {\n return { removedCount: 0, removedNames: [], dirCleaned: false };\n }\n\n if (target.configuredAgents.length === 0) {\n return { removedCount: 0, removedNames: [], dirCleaned: false };\n }\n\n const agentFiles = await listAgentFiles(target.agentsDir);\n const removedNames: string[] = [];\n\n for (const agentFile of agentFiles) {\n const agentName = agentFile.replace(/\\.md$/, \"\");\n if (!target.configuredAgents.includes(agentName)) continue;\n\n await remove(path.join(target.agentsDir, agentFile));\n removedNames.push(agentName);\n onRemoved?.(agentName);\n }\n\n let dirCleaned = false;\n if (await directoryExists(target.agentsDir)) {\n if (await isDirectoryEmpty(target.agentsDir)) {\n await remove(target.agentsDir);\n dirCleaned = true;\n }\n }\n\n return {\n removedCount: removedNames.length,\n removedNames,\n dirCleaned,\n };\n}\n\n/**\n * Uninstalls CLI-managed plugins by removing them from the Claude CLI\n * and deleting their local directories.\n *\n * Derives scope from per-skill config when available; falls back to project-level.\n *\n * @param onUninstalled - Called for each successfully uninstalled plugin name (for logging)\n */\nasync function uninstallPlugins(\n target: Pick<UninstallTarget, \"hasPlugins\" | \"cliPluginNames\" | \"pluginsDir\" | \"config\">,\n projectDir: string,\n onUninstalled?: (pluginName: string) => void,\n): Promise<UninstallPluginsResult> {\n if (!target.hasPlugins) {\n return { uninstalledNames: [], totalUninstalled: 0 };\n }\n\n const cliAvailable = await isClaudeCLIAvailable();\n const uninstalledNames: string[] = [];\n\n for (const pluginName of target.cliPluginNames) {\n if (cliAvailable) {\n try {\n // Derive scope from per-skill config; fall back to project-level heuristic\n const skillId = pluginName.split(\"@\")[0];\n const skillConfig = target.config?.skills?.find((s) => s.id === skillId);\n const pluginScope = skillConfig?.scope === \"global\" ? \"user\" : \"project\";\n await claudePluginUninstall(pluginName, pluginScope, projectDir);\n } catch {\n // Best-effort: plugin may not be registered with Claude CLI\n }\n }\n\n const pluginPath = path.join(target.pluginsDir, pluginName);\n await remove(pluginPath);\n uninstalledNames.push(pluginName);\n onUninstalled?.(pluginName);\n }\n\n return {\n uninstalledNames,\n totalUninstalled: uninstalledNames.length,\n };\n}\n\n/**\n * Removes empty .claude/ and .claude-src/ directories after uninstall.\n *\n * Only removes .claude-src/ when `removeAll` is true.\n * Only removes .claude/ when it's completely empty.\n */\nasync function cleanupEmptyDirs(\n target: Pick<UninstallTarget, \"hasClaudeDir\" | \"hasClaudeSrcDir\" | \"claudeDir\" | \"claudeSrcDir\">,\n removeAll: boolean,\n): Promise<CleanupResult> {\n let claudeSrcDirRemoved = false;\n if (removeAll && target.hasClaudeSrcDir) {\n await remove(target.claudeSrcDir);\n claudeSrcDirRemoved = true;\n }\n\n let claudeDirRemoved = false;\n let claudeDirKept = false;\n if (target.hasClaudeDir && (await directoryExists(target.claudeDir))) {\n if (await isDirectoryEmpty(target.claudeDir)) {\n await remove(target.claudeDir);\n claudeDirRemoved = true;\n } else {\n claudeDirKept = true;\n }\n }\n\n return { claudeDirRemoved, claudeSrcDirRemoved, claudeDirKept };\n}\n\nasync function isDirectoryEmpty(dirPath: string): Promise<boolean> {\n try {\n const allEntries = await readdir(dirPath);\n return allEntries.length === 0;\n } catch {\n return true;\n }\n}\n\nasync function listAgentFiles(agentsDir: string): Promise<string[]> {\n try {\n return (await readdir(agentsDir)).filter((f) => f.endsWith(\".md\"));\n } catch {\n return [];\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AACA,OAAO,UAAU;AACjB,SAAS,eAAe;AAExB,SAAS,aAAa;AACtB,SAAS,QAAQ,KAAK,MAAM,cAAc;AAgCpC,cAOM,YAPN;AAVN,IAAM,mBAAoD,CAAC;AAAA,EACzD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,EAAE,KAAK,IAAI,OAAO;AAExB,SACE,qBAAC,OAAI,eAAc,UACjB;AAAA,wBAAC,QAAK,MAAI,MAAC,4CAA8B;AAAA,IACzC,oBAAC,QAAK,eAAC;AAAA,IAEN,OAAO,cACN,qBAAC,OAAI,eAAc,UACjB;AAAA,0BAAC,QAAK,OAAO,WAAW,OAAO,uBAAS;AAAA,MACvC,OAAO,eAAe,IAAI,CAAC,SAC1B,qBAAC,QAAgB,UAAQ,MACtB;AAAA;AAAA,QACA;AAAA,WAFQ,IAGX,CACD;AAAA,OACH;AAAA,KAGA,OAAO,kBAAkB,OAAO,mBAChC,qBAAC,OAAI,eAAc,UACjB;AAAA,0BAAC,QAAK,OAAO,WAAW,OAAO,iCAAmB;AAAA,MACjD,OAAO,kBAAkB,qBAAC,QAAK,UAAQ,MAAC;AAAA;AAAA,QAAE,OAAO;AAAA,QAAU;AAAA,SAAoB;AAAA,MAC/E,OAAO,kBAAkB,qBAAC,QAAK,UAAQ,MAAC;AAAA;AAAA,QAAE,OAAO;AAAA,QAAU;AAAA,SAAgB;AAAA,OAC9E;AAAA,IAGD,aAAa,OAAO,mBACnB,qBAAC,OAAI,eAAc,UACjB;AAAA,0BAAC,QAAK,OAAO,WAAW,OAAO,sBAAQ;AAAA,MACvC,qBAAC,QAAK,UAAQ,MAAC;AAAA;AAAA,QAAE,OAAO;AAAA,QAAa;AAAA,SAAC;AAAA,OACxC;AAAA,IAGF,oBAAC,QAAK,eAAC;AAAA,IACP;AAAA,MAAC;AAAA;AAAA,QACC,SAAQ;AAAA,QACR,WAAW,MAAM;AACf,oBAAU;AACV,eAAK;AAAA,QACP;AAAA,QACA,UAAU,MAAM;AACd,mBAAS;AACT,eAAK;AAAA,QACP;AAAA,QACA,cAAc;AAAA;AAAA,IAChB;AAAA,KACF;AAEJ;AAEA,IAAqB,YAArB,MAAqB,mBAAkB,YAAY;AAAA,EACjD,OAAO,UAAU,UAAU,iBAAiB,IAAI;AAAA,EAEhD,OAAO,cAAc,aAAa,iBAAiB,IAAI;AAAA,EAEvD,OAAO,WAAW;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EAEA,OAAO,QAAQ;AAAA,IACb,GAAG,YAAY;AAAA,IACf,KAAK,MAAM,QAAQ;AAAA,MACjB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,IACD,KAAK,MAAM,QAAQ;AAAA,MACjB,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,UAAS;AAC5C,UAAM,aAAa,QAAQ,IAAI;AAE/B,SAAK,YAAY;AAEjB,UAAM,SAAS,MAAM,sBAAsB,UAAU;AACrD,QAAI,CAAC,oBAAoB,QAAQ,MAAM,GAAG,GAAG;AAC3C,WAAK,yBAAyB;AAC9B;AAAA,IACF;AAEA,UAAM,YAAY,MAAM,MACpB,KAAK,iBAAiB,QAAQ,MAAM,GAAG,IACvC,MAAM,KAAK,eAAe,QAAQ,MAAM,GAAG;AAC/C,QAAI,CAAC,WAAW;AACd,WAAK,IAAI,EAAE;AACX,WAAK,IAAI,qBAAqB;AAC9B,WAAK,KAAK,WAAW,SAAS;AAAA,IAChC;AAEA,UAAM,KAAK,iBAAiB,QAAQ,YAAY,MAAM,GAAG;AACzD,SAAK,cAAc;AAAA,EACrB;AAAA,EAEQ,cAAoB;AAC1B,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,GAAG,iBAAiB,IAAI,YAAY;AAC7C,SAAK,IAAI,EAAE;AAAA,EACb;AAAA,EAEQ,2BAAiC;AACvC,SAAK,KAAK,uBAAuB;AACjC,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,cAAc,aAAa;AACpC,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,cAAc,eAAe;AAAA,EACxC;AAAA,EAEQ,iBAAiB,QAAyB,WAA0B;AAC1E,SAAK,IAAI,gCAAgC;AACzC,SAAK,IAAI,EAAE;AAEX,QAAI,OAAO,YAAY;AACrB,WAAK,IAAI,YAAY;AACrB,iBAAW,cAAc,OAAO,gBAAgB;AAC9C,aAAK,IAAI,OAAO,UAAU,EAAE;AAAA,MAC9B;AAAA,IACF;AAEA,QAAI,OAAO,kBAAkB,OAAO,gBAAgB;AAClD,WAAK,IAAI,sBAAsB;AAC/B,UAAI,OAAO,gBAAgB;AACzB,aAAK,IAAI,OAAO,OAAO,SAAS,sBAAsB;AAAA,MACxD;AACA,UAAI,OAAO,gBAAgB;AACzB,aAAK,IAAI,OAAO,OAAO,SAAS,kBAAkB;AAAA,MACpD;AAAA,IACF;AAEA,QAAI,aAAa,OAAO,iBAAiB;AACvC,WAAK,IAAI,WAAW;AACpB,WAAK,IAAI,OAAO,OAAO,YAAY,GAAG;AAAA,IACxC;AAEA,SAAK,IAAI,EAAE;AACX,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,eAAe,QAAyB,WAAsC;AAC1F,WAAO,IAAI,QAAiB,CAAC,YAAY;AACvC,YAAM,EAAE,cAAc,IAAI;AAAA,QACxB;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA;AAAA,YACA,WAAW,MAAM,QAAQ,IAAI;AAAA,YAC7B,UAAU,MAAM,QAAQ,KAAK;AAAA;AAAA,QAC/B;AAAA,MACF;AAEA,oBAAc,EAAE,MAAM,MAAM,QAAQ,KAAK,CAAC;AAAA,IAC5C,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,iBACZ,QACA,YACA,WACe;AACf,QAAI,OAAO,YAAY;AACrB,WAAK,IAAI,yBAAyB;AAElC,UAAI;AACF,cAAM,eAAe,MAAM;AAAA,UAAiB;AAAA,UAAQ;AAAA,UAAY,CAAC,SAC/D,KAAK,IAAI,yBAAyB,IAAI,GAAG;AAAA,QAC3C;AAEA,aAAK;AAAA,UACH,eAAe,aAAa,gBAAgB,IAAI,aAAa,qBAAqB,IAAI,WAAW,SAAS;AAAA,QAC5G;AAAA,MACF,SAAS,OAAO;AACd,aAAK,IAAI,yBAAyB;AAClC,aAAK,MAAM,gBAAgB,KAAK,GAAG;AAAA,UACjC,MAAM,WAAW;AAAA,QACnB,CAAC;AAAA,MACH;AAAA,IACF;AAEA,QAAI;AACF,YAAM,KAAK,iBAAiB,QAAQ,SAAS;AAAA,IAC/C,SAAS,OAAO;AACd,WAAK,IAAI,8BAA8B;AACvC,WAAK,MAAM,gBAAgB,KAAK,GAAG;AAAA,QACjC,MAAM,WAAW;AAAA,MACnB,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEQ,gBAAsB;AAC5B,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,GAAG,iBAAiB,IAAI,wBAAwB;AACzD,SAAK,IAAI,EAAE;AACX,SAAK,WAAW,iBAAiB,kBAAkB;AACnD,SAAK,IAAI,EAAE;AAAA,EACb;AAAA,EAEA,MAAc,iBAAiB,QAAyB,WAAmC;AACzF,UAAM,cAAc,MAAM;AAAA,MACxB;AAAA,MACA,CAAC,YAAY,KAAK,IAAI,wBAAwB,OAAO,GAAG;AAAA,MACxD,CAAC,YAAY,KAAK,KAAK,aAAa,OAAO,qBAAqB,iBAAiB,IAAI,MAAM;AAAA,IAC7F;AAEA,QAAI,YAAY,eAAe,GAAG;AAChC,WAAK;AAAA,QACH,WAAW,YAAY,YAAY,kBAAkB,YAAY,iBAAiB,IAAI,UAAU,QAAQ;AAAA,MAC1G;AAAA,IACF;AAEA,UAAM,cAAc,MAAM;AAAA,MAAqB;AAAA,MAAQ,CAAC,cACtD,KAAK,IAAI,wBAAwB,SAAS,GAAG;AAAA,IAC/C;AAEA,QAAI,YAAY,eAAe,GAAG;AAChC,WAAK;AAAA,QACH,WAAW,YAAY,YAAY,aAAa,YAAY,iBAAiB,IAAI,UAAU,QAAQ;AAAA,MACrG;AAAA,IACF;AAEA,UAAM,UAAU,MAAM,iBAAiB,QAAQ,SAAS;AAExD,QAAI,QAAQ,qBAAqB;AAC/B,WAAK,WAAW,WAAW,cAAc,GAAG;AAAA,IAC9C;AAEA,QAAI,QAAQ,kBAAkB;AAC5B,WAAK,WAAW,WAAW,UAAU,GAAG;AAAA,IAC1C,WAAW,QAAQ,eAAe;AAChC,WAAK,IAAI,QAAQ,UAAU,2BAA2B;AAAA,IACxD;AAAA,EACF;AACF;AAkDA,SAAS,oBAAoB,QAAyB,WAA6B;AACjF,SACE,OAAO,cACP,OAAO,kBACP,OAAO,kBACN,aAAa,OAAO;AAEzB;AAEA,SAAS,wBAAwB,QAAiD;AAChF,MAAI,CAAC,QAAQ,OAAQ,QAAO,CAAC;AAC7B,SAAO,OAAO,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI;AACxC;AAEA,SAAS,0BAA0B,QAAoD;AACrF,MAAI,CAAC,QAAQ,OAAQ,QAAO,oBAAI,IAAI;AACpC,SAAO,IAAI,IAAI,OAAO,OAAO,IAAI,CAAC,UAAU,GAAG,MAAM,EAAE,IAAI,MAAM,MAAM,EAAE,CAAC;AAC5E;AAQA,eAAe,sBAAsB,YAA8C;AACjF,QAAM,aAAa,qBAAqB,UAAU;AAClD,QAAM,YAAY,KAAK,KAAK,YAAY,YAAY,QAAQ;AAC5D,QAAM,YAAY,KAAK,KAAK,YAAY,YAAY,QAAQ;AAC5D,QAAM,YAAY,KAAK,KAAK,YAAY,UAAU;AAClD,QAAM,eAAe,KAAK,KAAK,YAAY,cAAc;AAEzD,QAAM,CAAC,gBAAgB,gBAAgB,cAAc,iBAAiB,MAAM,IAAI,MAAM,QAAQ;AAAA,IAC5F;AAAA,MACE,gBAAgB,SAAS;AAAA,MACzB,gBAAgB,SAAS;AAAA,MACzB,gBAAgB,SAAS;AAAA,MACzB,gBAAgB,YAAY;AAAA,MAC5B,yBAAyB,UAAU,EAAE,KAAK,CAAC,WAAW,QAAQ,UAAU,IAAI;AAAA,IAC9E;AAAA,EACF;AAEA,MAAI,cAAwB,CAAC;AAC7B,MAAI;AACF,kBAAc,MAAM,gBAAgB,UAAU;AAAA,EAChD,QAAQ;AAAA,EAER;AAEA,QAAM,mBAAmB,wBAAwB,MAAM;AACvD,QAAM,mBAAmB,0BAA0B,MAAM;AACzD,QAAM,iBAAiB,YAAY,OAAO,CAAC,SAAS,iBAAiB,IAAI,IAAI,CAAC;AAE9E,SAAO;AAAA,IACL,YAAY,eAAe,SAAS;AAAA,IACpC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,kBAAkB,YAAiD;AAC1E,SAAO,eAAe;AACxB;AAWA,eAAe,qBACb,QACA,WACA,WAC6B;AAC7B,MAAI,CAAC,OAAO,gBAAgB;AAC1B,WAAO;AAAA,MACL,cAAc;AAAA,MACd,cAAc;AAAA,MACd,cAAc,CAAC;AAAA,MACf,cAAc,CAAC;AAAA,MACf,YAAY;AAAA,IACd;AAAA,EACF;AAEA,QAAM,gBAAgB,MAAM,gBAAgB,OAAO,SAAS;AAC5D,QAAM,eAAyB,CAAC;AAChC,QAAM,eAAyB,CAAC;AAEhC,aAAW,gBAAgB,eAAe;AACxC,UAAM,WAAW,KAAK,KAAK,OAAO,WAAW,YAAY;AACzD,UAAM,aAAa,MAAM,uBAAuB,QAAQ;AAExD,QAAI,kBAAkB,UAAU,GAAG;AACjC,YAAM,OAAO,QAAQ;AACrB,mBAAa,KAAK,YAAY;AAC9B,kBAAY,YAAY;AAAA,IAC1B,OAAO;AACL,mBAAa,KAAK,YAAY;AAC9B,kBAAY,YAAY;AAAA,IAC1B;AAAA,EACF;AAEA,MAAI,aAAa;AACjB,MAAI,aAAa,WAAW,KAAM,MAAM,gBAAgB,OAAO,SAAS,GAAI;AAC1E,QAAI,MAAM,iBAAiB,OAAO,SAAS,GAAG;AAC5C,YAAM,OAAO,OAAO,SAAS;AAC7B,mBAAa;AAAA,IACf;AAAA,EACF;AAEA,SAAO;AAAA,IACL,cAAc,aAAa;AAAA,IAC3B,cAAc,aAAa;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAUA,eAAe,qBACb,QACA,WAC6B;AAC7B,MAAI,CAAC,OAAO,gBAAgB;AAC1B,WAAO,EAAE,cAAc,GAAG,cAAc,CAAC,GAAG,YAAY,MAAM;AAAA,EAChE;AAEA,MAAI,OAAO,iBAAiB,WAAW,GAAG;AACxC,WAAO,EAAE,cAAc,GAAG,cAAc,CAAC,GAAG,YAAY,MAAM;AAAA,EAChE;AAEA,QAAM,aAAa,MAAM,eAAe,OAAO,SAAS;AACxD,QAAM,eAAyB,CAAC;AAEhC,aAAW,aAAa,YAAY;AAClC,UAAM,YAAY,UAAU,QAAQ,SAAS,EAAE;AAC/C,QAAI,CAAC,OAAO,iBAAiB,SAAS,SAAS,EAAG;AAElD,UAAM,OAAO,KAAK,KAAK,OAAO,WAAW,SAAS,CAAC;AACnD,iBAAa,KAAK,SAAS;AAC3B,gBAAY,SAAS;AAAA,EACvB;AAEA,MAAI,aAAa;AACjB,MAAI,MAAM,gBAAgB,OAAO,SAAS,GAAG;AAC3C,QAAI,MAAM,iBAAiB,OAAO,SAAS,GAAG;AAC5C,YAAM,OAAO,OAAO,SAAS;AAC7B,mBAAa;AAAA,IACf;AAAA,EACF;AAEA,SAAO;AAAA,IACL,cAAc,aAAa;AAAA,IAC3B;AAAA,IACA;AAAA,EACF;AACF;AAUA,eAAe,iBACb,QACA,YACA,eACiC;AACjC,MAAI,CAAC,OAAO,YAAY;AACtB,WAAO,EAAE,kBAAkB,CAAC,GAAG,kBAAkB,EAAE;AAAA,EACrD;AAEA,QAAM,eAAe,MAAM,qBAAqB;AAChD,QAAM,mBAA6B,CAAC;AAEpC,aAAW,cAAc,OAAO,gBAAgB;AAC9C,QAAI,cAAc;AAChB,UAAI;AAEF,cAAM,UAAU,WAAW,MAAM,GAAG,EAAE,CAAC;AACvC,cAAM,cAAc,OAAO,QAAQ,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,OAAO;AACvE,cAAM,cAAc,aAAa,UAAU,WAAW,SAAS;AAC/D,cAAM,sBAAsB,YAAY,aAAa,UAAU;AAAA,MACjE,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,UAAM,aAAa,KAAK,KAAK,OAAO,YAAY,UAAU;AAC1D,UAAM,OAAO,UAAU;AACvB,qBAAiB,KAAK,UAAU;AAChC,oBAAgB,UAAU;AAAA,EAC5B;AAEA,SAAO;AAAA,IACL;AAAA,IACA,kBAAkB,iBAAiB;AAAA,EACrC;AACF;AAQA,eAAe,iBACb,QACA,WACwB;AACxB,MAAI,sBAAsB;AAC1B,MAAI,aAAa,OAAO,iBAAiB;AACvC,UAAM,OAAO,OAAO,YAAY;AAChC,0BAAsB;AAAA,EACxB;AAEA,MAAI,mBAAmB;AACvB,MAAI,gBAAgB;AACpB,MAAI,OAAO,gBAAiB,MAAM,gBAAgB,OAAO,SAAS,GAAI;AACpE,QAAI,MAAM,iBAAiB,OAAO,SAAS,GAAG;AAC5C,YAAM,OAAO,OAAO,SAAS;AAC7B,yBAAmB;AAAA,IACrB,OAAO;AACL,sBAAgB;AAAA,IAClB;AAAA,EACF;AAEA,SAAO,EAAE,kBAAkB,qBAAqB,cAAc;AAChE;AAEA,eAAe,iBAAiB,SAAmC;AACjE,MAAI;AACF,UAAM,aAAa,MAAM,QAAQ,OAAO;AACxC,WAAO,WAAW,WAAW;AAAA,EAC/B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,eAAe,WAAsC;AAClE,MAAI;AACF,YAAQ,MAAM,QAAQ,SAAS,GAAG,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC;AAAA,EACnE,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;","names":[]}
|