@laitszkin/apollo-toolkit 3.3.0 → 3.3.1
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/AGENTS.md +3 -2
- package/CHANGELOG.md +11 -0
- package/README.md +6 -2
- package/analyse-app-logs/scripts/__pycache__/filter_logs_by_time.cpython-312.pyc +0 -0
- package/analyse-app-logs/scripts/__pycache__/log_cli_utils.cpython-312.pyc +0 -0
- package/analyse-app-logs/scripts/__pycache__/search_logs.cpython-312.pyc +0 -0
- package/docs-to-voice/scripts/__pycache__/docs_to_voice.cpython-312.pyc +0 -0
- package/generate-spec/scripts/__pycache__/create-specscpython-312.pyc +0 -0
- package/katex/scripts/__pycache__/render_katex.cpython-312.pyc +0 -0
- package/lib/cli.js +77 -22
- package/lib/installer.js +49 -15
- package/open-github-issue/scripts/__pycache__/open_github_issue.cpython-312.pyc +0 -0
- package/package.json +1 -1
- package/read-github-issue/scripts/__pycache__/find_issues.cpython-312.pyc +0 -0
- package/read-github-issue/scripts/__pycache__/read_issue.cpython-312.pyc +0 -0
- package/resolve-review-comments/scripts/__pycache__/review_threads.cpython-312.pyc +0 -0
- package/text-to-short-video/scripts/__pycache__/enforce_video_aspect_ratio.cpython-312.pyc +0 -0
package/AGENTS.md
CHANGED
|
@@ -22,7 +22,7 @@ This repository enables users to install and run a curated set of reusable agent
|
|
|
22
22
|
- Users can research the latest completed market week and produce a PDF watchlist of tradeable instruments for the coming week.
|
|
23
23
|
- Users can turn a marked weekly finance PDF into a concise evidence-based financial event report.
|
|
24
24
|
- Users can install Apollo Toolkit through npm or npx and interactively choose one or more target skill directories to populate with copied or symlinked skills, with the option to include codex-exclusive skills in non-codex targets.
|
|
25
|
-
- Users can uninstall
|
|
25
|
+
- Users can uninstall Apollo Toolkit-installed skills through an interactive target selector or specific non-interactive targets via `apltk uninstall`.
|
|
26
26
|
- Users can choose between symlink mode (auto-update via git pull) and copy mode (stable snapshot) with `--symlink` / `--copy` flags.
|
|
27
27
|
- Users can run bundled helper tools through `apltk tools` and direct `apltk <tool>` commands for selected packaged skill scripts.
|
|
28
28
|
- Users can design and implement new features through a spec-first workflow.
|
|
@@ -79,7 +79,8 @@ This repository enables users to install and run a curated set of reusable agent
|
|
|
79
79
|
- `./scripts/install_skills.sh all --copy` - 以複製模式安裝到所有支援目標。
|
|
80
80
|
- `./scripts/install_skills.sh uninstall` - 從所有目標移除已安裝的技能。
|
|
81
81
|
- `./scripts/install_skills.sh uninstall codex` - 只從 codex 目標移除。
|
|
82
|
-
- `node bin/apollo-toolkit.js uninstall` - 透過 CLI
|
|
82
|
+
- `node bin/apollo-toolkit.js uninstall` - 透過 CLI 互動選擇要移除的 agent target 技能。
|
|
83
|
+
- `node bin/apollo-toolkit.js uninstall codex --yes` - 以非互動方式移除指定 target 的已安裝技能。
|
|
83
84
|
|
|
84
85
|
## Core Project Purpose
|
|
85
86
|
|
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,17 @@ All notable changes to this repository are documented in this file.
|
|
|
7
7
|
### Added
|
|
8
8
|
- (None yet)
|
|
9
9
|
|
|
10
|
+
## [v3.3.1] - 2026-04-26
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Add an interactive `apltk uninstall` target selector so users can choose which agent skill directories to remove.
|
|
14
|
+
- Add `apltk uninstall --yes` for non-interactive uninstall confirmation.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
- Fix default `apltk uninstall` cleanup so a missing OpenClaw workspace no longer prevents uninstalling Codex, Trae, Agents, or Claude Code targets.
|
|
18
|
+
- Remove manifest-tracked historical skills during CLI uninstall so renamed or removed skills do not remain behind.
|
|
19
|
+
- Ignore unsafe manifest skill names during install and uninstall cleanup so removals remain scoped to direct child skill directories.
|
|
20
|
+
|
|
10
21
|
## [v3.3.0] - 2026-04-26
|
|
11
22
|
|
|
12
23
|
### Added
|
package/README.md
CHANGED
|
@@ -82,10 +82,14 @@ The interactive installer:
|
|
|
82
82
|
### Uninstall
|
|
83
83
|
|
|
84
84
|
```bash
|
|
85
|
-
apltk uninstall
|
|
86
|
-
apltk uninstall codex
|
|
85
|
+
apltk uninstall # Choose which agent targets to uninstall
|
|
86
|
+
apltk uninstall codex # Remove only from codex
|
|
87
|
+
apltk uninstall codex agents --yes # Non-interactive cleanup for selected targets
|
|
87
88
|
```
|
|
88
89
|
|
|
90
|
+
The uninstall flow removes the manifest-tracked current and historical skill
|
|
91
|
+
directories for the selected targets, then removes each target manifest.
|
|
92
|
+
|
|
89
93
|
### Global install
|
|
90
94
|
|
|
91
95
|
```bash
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/lib/cli.js
CHANGED
|
@@ -13,12 +13,13 @@ const {
|
|
|
13
13
|
syncToolkitHome,
|
|
14
14
|
uninstallSkills,
|
|
15
15
|
getTargetRoots,
|
|
16
|
+
getUninstallTargetRoots,
|
|
16
17
|
} = require('./installer');
|
|
17
18
|
const { formatToolList, getToolCommand, runTool } = require('./tool-runner');
|
|
18
19
|
const { checkForPackageUpdate } = require('./updater');
|
|
19
20
|
|
|
20
21
|
const TARGET_OPTIONS = [
|
|
21
|
-
{ id: 'all', label: 'All', description: '
|
|
22
|
+
{ id: 'all', label: 'All', description: 'Select every supported target below' },
|
|
22
23
|
...TARGET_DEFINITIONS,
|
|
23
24
|
];
|
|
24
25
|
|
|
@@ -137,7 +138,7 @@ function buildHelpText({ version, colorEnabled }) {
|
|
|
137
138
|
'Usage:',
|
|
138
139
|
` apltk [install] [${buildModeUsagePattern()}]...`,
|
|
139
140
|
` apollo-toolkit [install] [${buildModeUsagePattern()}]...`,
|
|
140
|
-
|
|
141
|
+
` apltk uninstall [${buildModeUsagePattern()}]... [--yes]`,
|
|
141
142
|
' apltk tools',
|
|
142
143
|
' apltk <tool> [...args]',
|
|
143
144
|
' apltk tools <tool> [...args]',
|
|
@@ -148,6 +149,7 @@ function buildHelpText({ version, colorEnabled }) {
|
|
|
148
149
|
' apltk',
|
|
149
150
|
' apltk codex openclaw',
|
|
150
151
|
' apltk uninstall',
|
|
152
|
+
' apltk uninstall codex agents --yes',
|
|
151
153
|
' npx @laitszkin/apollo-toolkit',
|
|
152
154
|
' npx @laitszkin/apollo-toolkit codex openclaw',
|
|
153
155
|
' npm i -g @laitszkin/apollo-toolkit',
|
|
@@ -164,6 +166,7 @@ function buildHelpText({ version, colorEnabled }) {
|
|
|
164
166
|
'',
|
|
165
167
|
'Options:',
|
|
166
168
|
' --home <path> Override Apollo Toolkit home directory',
|
|
169
|
+
' --yes, -y Skip uninstall confirmation',
|
|
167
170
|
' --help Show this help text',
|
|
168
171
|
].join('\n');
|
|
169
172
|
}
|
|
@@ -200,16 +203,24 @@ function parseArguments(argv) {
|
|
|
200
203
|
toolName: null,
|
|
201
204
|
toolArgs: [],
|
|
202
205
|
linkMode: null, // 'copy' | 'symlink' | null (prompt)
|
|
206
|
+
assumeYes: false,
|
|
203
207
|
};
|
|
204
208
|
|
|
205
209
|
if (args[0] === 'uninstall') {
|
|
206
210
|
result.command = 'uninstall';
|
|
207
211
|
args.shift();
|
|
208
|
-
// remaining args could be specific modes
|
|
209
212
|
while (args.length > 0) {
|
|
210
213
|
const arg = args.shift();
|
|
211
214
|
if (arg === '--help' || arg === '-h') {
|
|
212
215
|
result.showHelp = true;
|
|
216
|
+
} else if (arg === '--yes' || arg === '-y') {
|
|
217
|
+
result.assumeYes = true;
|
|
218
|
+
} else if (arg === '--home') {
|
|
219
|
+
const toolkitHome = args.shift();
|
|
220
|
+
if (!toolkitHome) {
|
|
221
|
+
throw new Error('Missing value for --home');
|
|
222
|
+
}
|
|
223
|
+
result.toolkitHome = path.resolve(toolkitHome);
|
|
213
224
|
} else {
|
|
214
225
|
result.modes.push(arg);
|
|
215
226
|
}
|
|
@@ -281,13 +292,21 @@ function clearScreen(output) {
|
|
|
281
292
|
}
|
|
282
293
|
}
|
|
283
294
|
|
|
284
|
-
function renderSelectionScreen({
|
|
295
|
+
function renderSelectionScreen({
|
|
296
|
+
output,
|
|
297
|
+
version,
|
|
298
|
+
cursor,
|
|
299
|
+
selected,
|
|
300
|
+
message,
|
|
301
|
+
env,
|
|
302
|
+
intro = 'Choose where Apollo Toolkit should copy managed skills.',
|
|
303
|
+
}) {
|
|
285
304
|
const colorEnabled = supportsColor(output, env);
|
|
286
305
|
const allSelected = VALID_MODES.every((mode) => selected.has(mode));
|
|
287
306
|
|
|
288
307
|
clearScreen(output);
|
|
289
308
|
output.write(`${buildBanner({ version, colorEnabled })}\n\n`);
|
|
290
|
-
output.write(
|
|
309
|
+
output.write(`${intro}\n`);
|
|
291
310
|
output.write(`${color('Use Up/Down', '1;33', colorEnabled)} (or ${color('j/k', '1;33', colorEnabled)}) to move, ${color('Space', '1;33', colorEnabled)} to toggle, ${color('Enter', '1;33', colorEnabled)} to continue.\n`);
|
|
292
311
|
output.write(`Press ${color('a', '1;33', colorEnabled)} to toggle all, ${color('q', '1;33', colorEnabled)} to cancel.\n\n`);
|
|
293
312
|
|
|
@@ -308,13 +327,11 @@ function renderSelectionScreen({ output, version, cursor, selected, message, env
|
|
|
308
327
|
}
|
|
309
328
|
}
|
|
310
329
|
|
|
311
|
-
async function
|
|
330
|
+
async function promptForSelectableModes({ stdin, stdout, version, env, intro, ttyError, cancelMessage }) {
|
|
312
331
|
if (!stdin.isTTY || !stdout.isTTY) {
|
|
313
|
-
throw new Error(
|
|
332
|
+
throw new Error(ttyError);
|
|
314
333
|
}
|
|
315
334
|
|
|
316
|
-
await animateWelcomeScreen({ output: stdout, version, env });
|
|
317
|
-
|
|
318
335
|
return new Promise((resolve, reject) => {
|
|
319
336
|
let cursor = 0;
|
|
320
337
|
let message = '';
|
|
@@ -348,48 +365,48 @@ async function promptForModes({ stdin, stdout, version, env }) {
|
|
|
348
365
|
const value = chunk.toString('utf8');
|
|
349
366
|
if (value === '') {
|
|
350
367
|
cleanup();
|
|
351
|
-
reject(new Error(
|
|
368
|
+
reject(new Error(cancelMessage));
|
|
352
369
|
return;
|
|
353
370
|
}
|
|
354
371
|
|
|
355
372
|
if (value === '[A' || value === 'k') {
|
|
356
373
|
cursor = (cursor - 1 + TARGET_OPTIONS.length) % TARGET_OPTIONS.length;
|
|
357
374
|
message = '';
|
|
358
|
-
renderSelectionScreen({ output: stdout, version, cursor, selected, message, env });
|
|
375
|
+
renderSelectionScreen({ output: stdout, version, cursor, selected, message, env, intro });
|
|
359
376
|
return;
|
|
360
377
|
}
|
|
361
378
|
|
|
362
379
|
if (value === '[B' || value === 'j') {
|
|
363
380
|
cursor = (cursor + 1) % TARGET_OPTIONS.length;
|
|
364
381
|
message = '';
|
|
365
|
-
renderSelectionScreen({ output: stdout, version, cursor, selected, message, env });
|
|
382
|
+
renderSelectionScreen({ output: stdout, version, cursor, selected, message, env, intro });
|
|
366
383
|
return;
|
|
367
384
|
}
|
|
368
385
|
|
|
369
386
|
if (value === ' ') {
|
|
370
387
|
toggleMode(TARGET_OPTIONS[cursor].id);
|
|
371
388
|
message = '';
|
|
372
|
-
renderSelectionScreen({ output: stdout, version, cursor, selected, message, env });
|
|
389
|
+
renderSelectionScreen({ output: stdout, version, cursor, selected, message, env, intro });
|
|
373
390
|
return;
|
|
374
391
|
}
|
|
375
392
|
|
|
376
393
|
if (value.toLowerCase() === 'a') {
|
|
377
394
|
toggleMode('all');
|
|
378
395
|
message = '';
|
|
379
|
-
renderSelectionScreen({ output: stdout, version, cursor, selected, message, env });
|
|
396
|
+
renderSelectionScreen({ output: stdout, version, cursor, selected, message, env, intro });
|
|
380
397
|
return;
|
|
381
398
|
}
|
|
382
399
|
|
|
383
400
|
if (value.toLowerCase() === 'q' || value === '') {
|
|
384
401
|
cleanup();
|
|
385
|
-
reject(new Error(
|
|
402
|
+
reject(new Error(cancelMessage));
|
|
386
403
|
return;
|
|
387
404
|
}
|
|
388
405
|
|
|
389
406
|
if (value === '\r') {
|
|
390
407
|
if (selected.size === 0) {
|
|
391
408
|
message = 'Select at least one target before continuing.';
|
|
392
|
-
renderSelectionScreen({ output: stdout, version, cursor, selected, message, env });
|
|
409
|
+
renderSelectionScreen({ output: stdout, version, cursor, selected, message, env, intro });
|
|
393
410
|
return;
|
|
394
411
|
}
|
|
395
412
|
|
|
@@ -401,7 +418,32 @@ async function promptForModes({ stdin, stdout, version, env }) {
|
|
|
401
418
|
stdin.setRawMode(true);
|
|
402
419
|
stdin.resume();
|
|
403
420
|
stdin.on('data', onData);
|
|
404
|
-
renderSelectionScreen({ output: stdout, version, cursor, selected, message, env });
|
|
421
|
+
renderSelectionScreen({ output: stdout, version, cursor, selected, message, env, intro });
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
async function promptForModes({ stdin, stdout, version, env }) {
|
|
426
|
+
await animateWelcomeScreen({ output: stdout, version, env });
|
|
427
|
+
return promptForSelectableModes({
|
|
428
|
+
stdin,
|
|
429
|
+
stdout,
|
|
430
|
+
version,
|
|
431
|
+
env,
|
|
432
|
+
intro: 'Choose where Apollo Toolkit should copy managed skills.',
|
|
433
|
+
ttyError: `Interactive install requires a TTY. Re-run with targets like ${buildInteractiveModeHint()}.`,
|
|
434
|
+
cancelMessage: 'Installation cancelled.',
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
async function promptForUninstallModes({ stdin, stdout, version, env }) {
|
|
439
|
+
return promptForSelectableModes({
|
|
440
|
+
stdin,
|
|
441
|
+
stdout,
|
|
442
|
+
version,
|
|
443
|
+
env,
|
|
444
|
+
intro: 'Choose which agent skill targets Apollo Toolkit should uninstall.',
|
|
445
|
+
ttyError: `Interactive uninstall requires a TTY. Re-run with targets like ${buildInteractiveModeHint()}.`,
|
|
446
|
+
cancelMessage: 'Uninstall cancelled.',
|
|
405
447
|
});
|
|
406
448
|
}
|
|
407
449
|
|
|
@@ -525,7 +567,7 @@ function printUninstallSummary({ stdout, uninstallResult, env }) {
|
|
|
525
567
|
stdout.write('\n\n');
|
|
526
568
|
for (const result of uninstallResult) {
|
|
527
569
|
stdout.write(`${color(result.target, '1', colorEnabled)} (${result.root})\n`);
|
|
528
|
-
stdout.write(` Removed: ${result.removedSkills.join(', ')}\n`);
|
|
570
|
+
stdout.write(` Removed: ${result.removedSkills.length > 0 ? result.removedSkills.join(', ') : '(manifest only)'}\n`);
|
|
529
571
|
}
|
|
530
572
|
}
|
|
531
573
|
|
|
@@ -563,17 +605,29 @@ async function run(argv, context = {}) {
|
|
|
563
605
|
// --- Uninstall flow ---
|
|
564
606
|
if (parsed.command === 'uninstall') {
|
|
565
607
|
const toolkitHome = parsed.toolkitHome || resolveToolkitHome(env);
|
|
566
|
-
const modes = parsed.modes.length > 0
|
|
608
|
+
const modes = parsed.modes.length > 0
|
|
609
|
+
? normalizeModes(parsed.modes)
|
|
610
|
+
: (stdin.isTTY && stdout.isTTY
|
|
611
|
+
? normalizeModes(await promptForUninstallModes({ stdin, stdout, version: packageJson.version, env }))
|
|
612
|
+
: null);
|
|
613
|
+
const modesForLookup = modes || VALID_MODES;
|
|
614
|
+
const targets = await getUninstallTargetRoots(modesForLookup, env);
|
|
567
615
|
|
|
568
616
|
// Show what will be removed
|
|
569
|
-
const allKnown = await listAllKnownSkillNames({ toolkitHome, modes:
|
|
617
|
+
const allKnown = await listAllKnownSkillNames({ toolkitHome, modes: modesForLookup, env });
|
|
570
618
|
stdout.write(color(`Apollo Toolkit home: ${toolkitHome}\n`, '2', supportsColor(stdout, env)));
|
|
619
|
+
if (targets.length > 0) {
|
|
620
|
+
stdout.write('Targets:\n');
|
|
621
|
+
for (const target of targets) {
|
|
622
|
+
stdout.write(`- ${target.label}: ${target.root}\n`);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
571
625
|
|
|
572
|
-
const confirmed = await promptYesNo({
|
|
626
|
+
const confirmed = parsed.assumeYes || await promptYesNo({
|
|
573
627
|
stdin,
|
|
574
628
|
stdout,
|
|
575
629
|
env,
|
|
576
|
-
question: `This will remove
|
|
630
|
+
question: `This will remove Apollo Toolkit-installed skills${modes ? ` from: ${modes.join(', ')}` : ' from all targets'}. Continue?`,
|
|
577
631
|
defaultYes: false,
|
|
578
632
|
});
|
|
579
633
|
|
|
@@ -688,6 +742,7 @@ module.exports = {
|
|
|
688
742
|
buildToolsHelp,
|
|
689
743
|
parseArguments,
|
|
690
744
|
promptForModes,
|
|
745
|
+
promptForUninstallModes,
|
|
691
746
|
promptSymlinkChoice,
|
|
692
747
|
promptIncludeExclusiveSkills,
|
|
693
748
|
readPackageJson,
|
package/lib/installer.js
CHANGED
|
@@ -122,6 +122,25 @@ async function readManifest(targetRoot) {
|
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
function isSafeSkillName(skillName) {
|
|
126
|
+
return typeof skillName === 'string'
|
|
127
|
+
&& skillName.length > 0
|
|
128
|
+
&& !skillName.includes('\0')
|
|
129
|
+
&& !skillName.includes('/')
|
|
130
|
+
&& !skillName.includes('\\')
|
|
131
|
+
&& !path.isAbsolute(skillName)
|
|
132
|
+
&& !path.win32.isAbsolute(skillName)
|
|
133
|
+
&& skillName !== '.'
|
|
134
|
+
&& skillName !== '..';
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function getManifestSkillNames(manifest) {
|
|
138
|
+
return [...new Set([
|
|
139
|
+
...(Array.isArray(manifest.historicalSkills) ? manifest.historicalSkills : []),
|
|
140
|
+
...(Array.isArray(manifest.skills) ? manifest.skills : []),
|
|
141
|
+
])].filter(isSafeSkillName).sort();
|
|
142
|
+
}
|
|
143
|
+
|
|
125
144
|
// Write manifest to a target directory.
|
|
126
145
|
async function writeManifest(targetRoot, { version, linkMode, skills, previousSkills = [] }) {
|
|
127
146
|
const historicalSkills = [...new Set([...previousSkills, ...skills])].sort();
|
|
@@ -145,17 +164,17 @@ async function listAllKnownSkillNames({ toolkitHome, modes = [], env = process.e
|
|
|
145
164
|
const allNames = new Set();
|
|
146
165
|
|
|
147
166
|
// Current skills from toolkit home
|
|
148
|
-
const currentSkills = await listSkillNames(toolkitHome, modes);
|
|
167
|
+
const currentSkills = await listSkillNames(toolkitHome, modes).catch(() => []);
|
|
149
168
|
for (const name of currentSkills) {
|
|
150
169
|
allNames.add(name);
|
|
151
170
|
}
|
|
152
171
|
|
|
153
172
|
// Historical skills from all target manifests
|
|
154
|
-
const targets = await
|
|
173
|
+
const targets = await getUninstallTargetRoots(modes, env);
|
|
155
174
|
for (const target of targets) {
|
|
156
175
|
const manifest = await readManifest(target.root);
|
|
157
176
|
if (manifest && manifest.historicalSkills) {
|
|
158
|
-
for (const name of manifest
|
|
177
|
+
for (const name of getManifestSkillNames(manifest)) {
|
|
159
178
|
allNames.add(name);
|
|
160
179
|
}
|
|
161
180
|
}
|
|
@@ -343,6 +362,21 @@ async function getTargetRoots(modes, env = process.env) {
|
|
|
343
362
|
return targets;
|
|
344
363
|
}
|
|
345
364
|
|
|
365
|
+
async function getUninstallTargetRoots(modes = VALID_MODES, env = process.env) {
|
|
366
|
+
const targets = [];
|
|
367
|
+
|
|
368
|
+
for (const mode of normalizeModes(modes)) {
|
|
369
|
+
try {
|
|
370
|
+
targets.push(...await getTargetRoots([mode], env));
|
|
371
|
+
} catch {
|
|
372
|
+
// Uninstall is best-effort across agents. A missing OpenClaw workspace
|
|
373
|
+
// must not prevent cleanup from Codex, Trae, Agents, or Claude Code.
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
return targets;
|
|
378
|
+
}
|
|
379
|
+
|
|
346
380
|
async function ensureDirectory(dirPath) {
|
|
347
381
|
await fsp.mkdir(dirPath, { recursive: true });
|
|
348
382
|
}
|
|
@@ -387,8 +421,8 @@ async function installLinks({ toolkitHome, modes, env = process.env, previousSki
|
|
|
387
421
|
// Read existing manifest to carry forward historical skills
|
|
388
422
|
const existingManifest = await readManifest(target.root);
|
|
389
423
|
const allPreviousSkills = existingManifest
|
|
390
|
-
? [...new Set([...existingManifest
|
|
391
|
-
: previousSkillNames;
|
|
424
|
+
? [...new Set([...getManifestSkillNames(existingManifest), ...previousSkillNames.filter(isSafeSkillName)])]
|
|
425
|
+
: previousSkillNames.filter(isSafeSkillName);
|
|
392
426
|
|
|
393
427
|
const staleSkillNames = allPreviousSkills.filter(
|
|
394
428
|
(skillName) => !targetSkillNames.includes(skillName),
|
|
@@ -435,17 +469,18 @@ async function installLinks({ toolkitHome, modes, env = process.env, previousSki
|
|
|
435
469
|
// Uninstall all skills from all target directories that have manifests.
|
|
436
470
|
async function uninstallSkills({ env = process.env, modes = null } = {}) {
|
|
437
471
|
const normalizedModes = modes ? normalizeModes(modes) : VALID_MODES;
|
|
438
|
-
const targets = await
|
|
472
|
+
const targets = await getUninstallTargetRoots(normalizedModes, env);
|
|
439
473
|
const results = [];
|
|
440
474
|
|
|
441
475
|
for (const target of targets) {
|
|
442
476
|
const manifest = await readManifest(target.root);
|
|
443
|
-
if (!manifest
|
|
477
|
+
if (!manifest) {
|
|
444
478
|
continue;
|
|
445
479
|
}
|
|
446
480
|
|
|
481
|
+
const skillNames = getManifestSkillNames(manifest);
|
|
447
482
|
const removedSkills = [];
|
|
448
|
-
for (const skillName of
|
|
483
|
+
for (const skillName of skillNames) {
|
|
449
484
|
const skillPath = path.join(target.root, skillName);
|
|
450
485
|
try {
|
|
451
486
|
await fsp.rm(skillPath, { recursive: true, force: true });
|
|
@@ -462,13 +497,11 @@ async function uninstallSkills({ env = process.env, modes = null } = {}) {
|
|
|
462
497
|
// ok if already gone
|
|
463
498
|
}
|
|
464
499
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
});
|
|
471
|
-
}
|
|
500
|
+
results.push({
|
|
501
|
+
target: target.label,
|
|
502
|
+
root: target.root,
|
|
503
|
+
removedSkills,
|
|
504
|
+
});
|
|
472
505
|
}
|
|
473
506
|
|
|
474
507
|
return results;
|
|
@@ -480,6 +513,7 @@ module.exports = {
|
|
|
480
513
|
VALID_MODES,
|
|
481
514
|
MANIFEST_FILENAME,
|
|
482
515
|
getTargetRoots,
|
|
516
|
+
getUninstallTargetRoots,
|
|
483
517
|
installLinks,
|
|
484
518
|
listAllKnownSkillNames,
|
|
485
519
|
listCodexSkillNames,
|
|
Binary file
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|