@laitszkin/apollo-toolkit 3.2.1 → 3.3.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/AGENTS.md +11 -4
- package/CHANGELOG.md +19 -1
- package/README.md +35 -8
- 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/implement-specs-with-worktree/SKILL.md +3 -1
- package/katex/scripts/__pycache__/render_katex.cpython-312.pyc +0 -0
- package/lib/cli.js +190 -9
- package/lib/installer.js +147 -8
- 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/scripts/install_skills.ps1 +488 -108
- package/scripts/install_skills.sh +429 -15
- package/text-to-short-video/scripts/__pycache__/enforce_video_aspect_ratio.cpython-312.pyc +0 -0
package/lib/installer.js
CHANGED
|
@@ -13,6 +13,7 @@ const TARGET_DEFINITIONS = Object.freeze([
|
|
|
13
13
|
const VALID_MODES = TARGET_DEFINITIONS.map(({ id }) => id);
|
|
14
14
|
const COPY_FILES = new Set(['AGENTS.md', 'CHANGELOG.md', 'LICENSE', 'README.md', 'package.json']);
|
|
15
15
|
const COPY_DIRS = new Set(['scripts']);
|
|
16
|
+
const MANIFEST_FILENAME = '.apollo-toolkit-manifest.json';
|
|
16
17
|
|
|
17
18
|
function resolveHomeDirectory(env = process.env) {
|
|
18
19
|
return env.HOME || env.USERPROFILE || os.homedir();
|
|
@@ -82,7 +83,6 @@ async function listSkillNames(rootDir, modes = []) {
|
|
|
82
83
|
}
|
|
83
84
|
}
|
|
84
85
|
|
|
85
|
-
// For codex mode, also include codex-specific skills
|
|
86
86
|
if (modes.includes('codex')) {
|
|
87
87
|
const codexDir = path.join(rootDir, 'codex');
|
|
88
88
|
if (fs.existsSync(codexDir)) {
|
|
@@ -111,8 +111,62 @@ async function listCodexSkillNames(rootDir) {
|
|
|
111
111
|
.sort();
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
|
|
115
|
-
|
|
114
|
+
// Read manifest from a target directory, returning { skills, historicalSkills, linkMode } or null.
|
|
115
|
+
async function readManifest(targetRoot) {
|
|
116
|
+
const manifestPath = path.join(targetRoot, MANIFEST_FILENAME);
|
|
117
|
+
try {
|
|
118
|
+
const raw = await fsp.readFile(manifestPath, 'utf8');
|
|
119
|
+
return JSON.parse(raw);
|
|
120
|
+
} catch {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Write manifest to a target directory.
|
|
126
|
+
async function writeManifest(targetRoot, { version, linkMode, skills, previousSkills = [] }) {
|
|
127
|
+
const historicalSkills = [...new Set([...previousSkills, ...skills])].sort();
|
|
128
|
+
const manifest = {
|
|
129
|
+
version,
|
|
130
|
+
installedAt: new Date().toISOString(),
|
|
131
|
+
linkMode,
|
|
132
|
+
skills: [...skills].sort(),
|
|
133
|
+
historicalSkills,
|
|
134
|
+
};
|
|
135
|
+
await fsp.mkdir(targetRoot, { recursive: true });
|
|
136
|
+
await fsp.writeFile(
|
|
137
|
+
path.join(targetRoot, MANIFEST_FILENAME),
|
|
138
|
+
`${JSON.stringify(manifest, null, 2)}\n`,
|
|
139
|
+
'utf8',
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Read all current + historically appeared skill names with deduplication.
|
|
144
|
+
async function listAllKnownSkillNames({ toolkitHome, modes = [], env = process.env }) {
|
|
145
|
+
const allNames = new Set();
|
|
146
|
+
|
|
147
|
+
// Current skills from toolkit home
|
|
148
|
+
const currentSkills = await listSkillNames(toolkitHome, modes);
|
|
149
|
+
for (const name of currentSkills) {
|
|
150
|
+
allNames.add(name);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Historical skills from all target manifests
|
|
154
|
+
const targets = await getTargetRoots(modes, env).catch(() => []);
|
|
155
|
+
for (const target of targets) {
|
|
156
|
+
const manifest = await readManifest(target.root);
|
|
157
|
+
if (manifest && manifest.historicalSkills) {
|
|
158
|
+
for (const name of manifest.historicalSkills) {
|
|
159
|
+
allNames.add(name);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return [...allNames].sort();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function getTargetSkillNames({ targetMode, sharedSkillNames, codexSkillNames, includeExclusiveSkills = false }) {
|
|
168
|
+
const includeCodexSkills = targetMode === 'codex' || includeExclusiveSkills;
|
|
169
|
+
if (!includeCodexSkills || codexSkillNames.length === 0) {
|
|
116
170
|
return sharedSkillNames;
|
|
117
171
|
}
|
|
118
172
|
|
|
@@ -299,10 +353,23 @@ async function replaceWithCopy(sourcePath, targetPath) {
|
|
|
299
353
|
await fsp.cp(sourcePath, targetPath, { recursive: true, force: true });
|
|
300
354
|
}
|
|
301
355
|
|
|
302
|
-
async function
|
|
356
|
+
async function replaceWithSymlink(sourcePath, targetPath) {
|
|
357
|
+
await fsp.rm(targetPath, { recursive: true, force: true });
|
|
358
|
+
await ensureDirectory(path.dirname(targetPath));
|
|
359
|
+
await fsp.symlink(sourcePath, targetPath, process.platform === 'win32' ? 'junction' : 'dir');
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Install skills into target directories.
|
|
363
|
+
// linkMode: 'copy' (default) or 'symlink'
|
|
364
|
+
// includeExclusiveSkills: when true, non-codex targets also receive codex-exclusive skills.
|
|
365
|
+
async function installLinks({ toolkitHome, modes, env = process.env, previousSkillNames = [], linkMode = 'copy', includeExclusiveSkills = false }) {
|
|
303
366
|
const normalizedModes = normalizeModes(modes);
|
|
367
|
+
// Always collect codex skill names (needed when includeExclusiveSkills is true even
|
|
368
|
+
// when codex isn't in the target list).
|
|
369
|
+
const codexSkillNames = (normalizedModes.includes('codex') || includeExclusiveSkills)
|
|
370
|
+
? await listCodexSkillNames(toolkitHome)
|
|
371
|
+
: [];
|
|
304
372
|
const sharedSkillNames = await listSkillNames(toolkitHome);
|
|
305
|
-
const codexSkillNames = normalizedModes.includes('codex') ? await listCodexSkillNames(toolkitHome) : [];
|
|
306
373
|
const skillNames = normalizedModes.includes('codex')
|
|
307
374
|
? [...new Set([...sharedSkillNames, ...codexSkillNames])].sort()
|
|
308
375
|
: sharedSkillNames;
|
|
@@ -314,8 +381,18 @@ async function installLinks({ toolkitHome, modes, env = process.env, previousSki
|
|
|
314
381
|
targetMode: target.mode,
|
|
315
382
|
sharedSkillNames,
|
|
316
383
|
codexSkillNames,
|
|
384
|
+
includeExclusiveSkills,
|
|
317
385
|
});
|
|
318
|
-
|
|
386
|
+
|
|
387
|
+
// Read existing manifest to carry forward historical skills
|
|
388
|
+
const existingManifest = await readManifest(target.root);
|
|
389
|
+
const allPreviousSkills = existingManifest
|
|
390
|
+
? [...new Set([...existingManifest.historicalSkills, ...previousSkillNames])]
|
|
391
|
+
: previousSkillNames;
|
|
392
|
+
|
|
393
|
+
const staleSkillNames = allPreviousSkills.filter(
|
|
394
|
+
(skillName) => !targetSkillNames.includes(skillName),
|
|
395
|
+
);
|
|
319
396
|
|
|
320
397
|
await ensureDirectory(target.root);
|
|
321
398
|
for (const staleSkillName of staleSkillNames) {
|
|
@@ -329,27 +406,89 @@ async function installLinks({ toolkitHome, modes, env = process.env, previousSki
|
|
|
329
406
|
codexSkillNames,
|
|
330
407
|
});
|
|
331
408
|
const targetPath = path.join(target.root, skillName);
|
|
332
|
-
|
|
333
|
-
|
|
409
|
+
|
|
410
|
+
if (linkMode === 'symlink') {
|
|
411
|
+
await replaceWithSymlink(sourcePath, targetPath);
|
|
412
|
+
} else {
|
|
413
|
+
await replaceWithCopy(sourcePath, targetPath);
|
|
414
|
+
}
|
|
415
|
+
copiedPaths.push({ target: target.label, path: targetPath, skillName, linkMode });
|
|
334
416
|
}
|
|
417
|
+
|
|
418
|
+
// Persist manifest for future uninstall / dedup
|
|
419
|
+
await writeManifest(target.root, {
|
|
420
|
+
version: existingManifest?.version || 'unknown',
|
|
421
|
+
linkMode,
|
|
422
|
+
skills: targetSkillNames,
|
|
423
|
+
previousSkills: allPreviousSkills,
|
|
424
|
+
});
|
|
335
425
|
}
|
|
336
426
|
|
|
337
427
|
return {
|
|
338
428
|
skillNames,
|
|
339
429
|
targets,
|
|
340
430
|
copiedPaths,
|
|
431
|
+
linkMode,
|
|
341
432
|
};
|
|
342
433
|
}
|
|
343
434
|
|
|
435
|
+
// Uninstall all skills from all target directories that have manifests.
|
|
436
|
+
async function uninstallSkills({ env = process.env, modes = null } = {}) {
|
|
437
|
+
const normalizedModes = modes ? normalizeModes(modes) : VALID_MODES;
|
|
438
|
+
const targets = await getTargetRoots(normalizedModes, env).catch(() => []);
|
|
439
|
+
const results = [];
|
|
440
|
+
|
|
441
|
+
for (const target of targets) {
|
|
442
|
+
const manifest = await readManifest(target.root);
|
|
443
|
+
if (!manifest || !manifest.skills || manifest.skills.length === 0) {
|
|
444
|
+
continue;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
const removedSkills = [];
|
|
448
|
+
for (const skillName of manifest.skills) {
|
|
449
|
+
const skillPath = path.join(target.root, skillName);
|
|
450
|
+
try {
|
|
451
|
+
await fsp.rm(skillPath, { recursive: true, force: true });
|
|
452
|
+
removedSkills.push(skillName);
|
|
453
|
+
} catch {
|
|
454
|
+
// Skip skills that couldn't be removed
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Remove the manifest itself
|
|
459
|
+
try {
|
|
460
|
+
await fsp.rm(path.join(target.root, MANIFEST_FILENAME), { force: true });
|
|
461
|
+
} catch {
|
|
462
|
+
// ok if already gone
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
if (removedSkills.length > 0) {
|
|
466
|
+
results.push({
|
|
467
|
+
target: target.label,
|
|
468
|
+
root: target.root,
|
|
469
|
+
removedSkills,
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
return results;
|
|
475
|
+
}
|
|
476
|
+
|
|
344
477
|
module.exports = {
|
|
345
478
|
expandUserPath,
|
|
346
479
|
TARGET_DEFINITIONS,
|
|
347
480
|
VALID_MODES,
|
|
481
|
+
MANIFEST_FILENAME,
|
|
348
482
|
getTargetRoots,
|
|
349
483
|
installLinks,
|
|
484
|
+
listAllKnownSkillNames,
|
|
485
|
+
listCodexSkillNames,
|
|
350
486
|
listSkillNames,
|
|
351
487
|
normalizeModes,
|
|
488
|
+
readManifest,
|
|
352
489
|
resolveHomeDirectory,
|
|
353
490
|
resolveToolkitHome,
|
|
354
491
|
syncToolkitHome,
|
|
492
|
+
uninstallSkills,
|
|
493
|
+
writeManifest,
|
|
355
494
|
};
|
|
Binary file
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|