@laitszkin/apollo-toolkit 3.13.2 → 3.14.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 +7 -7
- package/CHANGELOG.md +36 -0
- package/CLAUDE.md +8 -8
- package/analyse-app-logs/SKILL.md +3 -3
- package/bin/apollo-toolkit.ts +7 -0
- package/codex/codex-memory-manager/SKILL.md +2 -2
- package/codex/learn-skill-from-conversations/SKILL.md +3 -3
- package/dist/bin/apollo-toolkit.d.ts +2 -0
- package/dist/bin/apollo-toolkit.js +7 -0
- package/dist/lib/cli.d.ts +41 -0
- package/dist/lib/cli.js +655 -0
- package/dist/lib/installer.d.ts +59 -0
- package/dist/lib/installer.js +404 -0
- package/dist/lib/tool-runner.d.ts +19 -0
- package/dist/lib/tool-runner.js +536 -0
- package/dist/lib/tools/architecture.d.ts +2 -0
- package/dist/lib/tools/architecture.js +23 -0
- package/dist/lib/tools/create-specs.d.ts +2 -0
- package/dist/lib/tools/create-specs.js +175 -0
- package/dist/lib/tools/docs-to-voice.d.ts +2 -0
- package/dist/lib/tools/docs-to-voice.js +705 -0
- package/dist/lib/tools/enforce-video-aspect-ratio.d.ts +2 -0
- package/dist/lib/tools/enforce-video-aspect-ratio.js +312 -0
- package/dist/lib/tools/extract-conversations.d.ts +2 -0
- package/dist/lib/tools/extract-conversations.js +105 -0
- package/dist/lib/tools/extract-pdf-text.d.ts +2 -0
- package/dist/lib/tools/extract-pdf-text.js +92 -0
- package/dist/lib/tools/filter-logs.d.ts +2 -0
- package/dist/lib/tools/filter-logs.js +94 -0
- package/dist/lib/tools/find-github-issues.d.ts +2 -0
- package/dist/lib/tools/find-github-issues.js +176 -0
- package/dist/lib/tools/generate-storyboard-images.d.ts +2 -0
- package/dist/lib/tools/generate-storyboard-images.js +419 -0
- package/dist/lib/tools/log-cli-utils.d.ts +35 -0
- package/dist/lib/tools/log-cli-utils.js +233 -0
- package/dist/lib/tools/open-github-issue.d.ts +2 -0
- package/dist/lib/tools/open-github-issue.js +750 -0
- package/dist/lib/tools/read-github-issue.d.ts +2 -0
- package/dist/lib/tools/read-github-issue.js +134 -0
- package/dist/lib/tools/render-error-book.d.ts +2 -0
- package/dist/lib/tools/render-error-book.js +265 -0
- package/dist/lib/tools/render-katex.d.ts +2 -0
- package/dist/lib/tools/render-katex.js +294 -0
- package/dist/lib/tools/review-threads.d.ts +2 -0
- package/dist/lib/tools/review-threads.js +491 -0
- package/dist/lib/tools/search-logs.d.ts +2 -0
- package/dist/lib/tools/search-logs.js +164 -0
- package/dist/lib/tools/sync-memory-index.d.ts +2 -0
- package/dist/lib/tools/sync-memory-index.js +113 -0
- package/dist/lib/tools/validate-openai-agent-config.d.ts +2 -0
- package/dist/lib/tools/validate-openai-agent-config.js +190 -0
- package/dist/lib/tools/validate-skill-frontmatter.d.ts +2 -0
- package/dist/lib/tools/validate-skill-frontmatter.js +118 -0
- package/dist/lib/types.d.ts +82 -0
- package/dist/lib/types.js +2 -0
- package/dist/lib/updater.d.ts +34 -0
- package/dist/lib/updater.js +112 -0
- package/dist/lib/utils/format.d.ts +2 -0
- package/dist/lib/utils/format.js +6 -0
- package/dist/lib/utils/terminal.d.ts +12 -0
- package/dist/lib/utils/terminal.js +26 -0
- package/docs-to-voice/SKILL.md +0 -1
- package/generate-spec/SKILL.md +1 -1
- package/katex/SKILL.md +1 -2
- package/lib/cli.ts +780 -0
- package/lib/installer.ts +466 -0
- package/lib/tool-runner.ts +561 -0
- package/lib/tools/architecture.ts +20 -0
- package/lib/tools/create-specs.ts +204 -0
- package/lib/tools/docs-to-voice.ts +799 -0
- package/lib/tools/enforce-video-aspect-ratio.ts +368 -0
- package/lib/tools/extract-conversations.ts +114 -0
- package/lib/tools/extract-pdf-text.ts +99 -0
- package/lib/tools/filter-logs.ts +118 -0
- package/lib/tools/find-github-issues.ts +211 -0
- package/lib/tools/generate-storyboard-images.ts +455 -0
- package/lib/tools/log-cli-utils.ts +262 -0
- package/lib/tools/open-github-issue.ts +930 -0
- package/lib/tools/read-github-issue.ts +179 -0
- package/lib/tools/render-error-book.ts +300 -0
- package/lib/tools/render-katex.ts +325 -0
- package/lib/tools/review-threads.ts +590 -0
- package/lib/tools/search-logs.ts +200 -0
- package/lib/tools/sync-memory-index.ts +114 -0
- package/lib/tools/validate-openai-agent-config.ts +213 -0
- package/lib/tools/validate-skill-frontmatter.ts +124 -0
- package/lib/types.ts +90 -0
- package/lib/updater.ts +165 -0
- package/lib/utils/format.ts +7 -0
- package/lib/utils/terminal.ts +22 -0
- package/open-github-issue/SKILL.md +2 -2
- package/optimise-skill/SKILL.md +1 -1
- package/package.json +13 -4
- package/resources/project-architecture/assets/architecture.css +764 -0
- package/resources/project-architecture/assets/viewer.client.js +144 -0
- package/resources/project-architecture/index.html +42 -0
- package/review-spec-related-changes/SKILL.md +1 -1
- package/solve-issues-found-during-review/SKILL.md +2 -1
- package/tsconfig.json +28 -0
- 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/analyse-app-logs/scripts/filter_logs_by_time.py +0 -64
- package/analyse-app-logs/scripts/log_cli_utils.py +0 -112
- package/analyse-app-logs/scripts/search_logs.py +0 -137
- package/analyse-app-logs/tests/test_filter_logs_by_time.py +0 -95
- package/analyse-app-logs/tests/test_search_logs.py +0 -100
- package/codex/codex-memory-manager/scripts/extract_recent_conversations.py +0 -369
- package/codex/codex-memory-manager/scripts/sync_memory_index.py +0 -130
- package/codex/codex-memory-manager/tests/test_extract_recent_conversations.py +0 -177
- package/codex/codex-memory-manager/tests/test_memory_template.py +0 -37
- package/codex/codex-memory-manager/tests/test_sync_memory_index.py +0 -84
- package/codex/learn-skill-from-conversations/scripts/extract_recent_conversations.py +0 -369
- package/codex/learn-skill-from-conversations/tests/test_extract_recent_conversations.py +0 -177
- package/docs-to-voice/scripts/__pycache__/docs_to_voice.cpython-312.pyc +0 -0
- package/docs-to-voice/scripts/docs_to_voice.py +0 -1385
- package/docs-to-voice/scripts/docs_to_voice.sh +0 -11
- package/docs-to-voice/tests/test_docs_to_voice_api_max_chars.py +0 -210
- package/docs-to-voice/tests/test_docs_to_voice_sentence_timeline.py +0 -115
- package/docs-to-voice/tests/test_docs_to_voice_settings.py +0 -43
- package/docs-to-voice/tests/test_docs_to_voice_shell_wrapper.py +0 -51
- package/docs-to-voice/tests/test_docs_to_voice_speech_rate.py +0 -57
- package/generate-spec/scripts/__pycache__/create-specscpython-312.pyc +0 -0
- package/generate-spec/scripts/create-specs +0 -215
- package/generate-spec/tests/test_create_specs.py +0 -200
- package/init-project-html/scripts/architecture-bootstrap-render.js +0 -16
- package/init-project-html/scripts/architecture.js +0 -296
- package/katex/scripts/__pycache__/render_katex.cpython-312.pyc +0 -0
- package/katex/scripts/render_katex.py +0 -247
- package/katex/scripts/render_katex.sh +0 -11
- package/katex/tests/test_render_katex.py +0 -174
- package/learning-error-book/scripts/render_error_book_json_to_pdf.py +0 -590
- package/learning-error-book/tests/test_render_error_book_json_to_pdf.py +0 -134
- package/open-github-issue/scripts/__pycache__/open_github_issue.cpython-312.pyc +0 -0
- package/open-github-issue/scripts/open_github_issue.py +0 -705
- package/open-github-issue/tests/test_open_github_issue.py +0 -381
- package/openai-text-to-image-storyboard/scripts/generate_storyboard_images.py +0 -763
- package/openai-text-to-image-storyboard/tests/test_generate_storyboard_images.py +0 -177
- 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/read-github-issue/scripts/find_issues.py +0 -148
- package/read-github-issue/scripts/read_issue.py +0 -108
- package/read-github-issue/tests/test_find_issues.py +0 -127
- package/read-github-issue/tests/test_read_issue.py +0 -109
- package/resolve-review-comments/scripts/__pycache__/review_threads.cpython-312.pyc +0 -0
- package/resolve-review-comments/scripts/review_threads.py +0 -425
- package/resolve-review-comments/tests/test_review_threads.py +0 -74
- package/scripts/validate_openai_agent_config.py +0 -209
- package/scripts/validate_skill_frontmatter.py +0 -131
- package/text-to-short-video/scripts/__pycache__/enforce_video_aspect_ratio.cpython-312.pyc +0 -0
- package/text-to-short-video/scripts/enforce_video_aspect_ratio.py +0 -350
- package/text-to-short-video/tests/test_enforce_video_aspect_ratio.py +0 -194
- package/weekly-financial-event-report/scripts/extract_pdf_text_pdfkit.swift +0 -99
- package/weekly-financial-event-report/tests/test_extract_pdf_text_pdfkit.py +0 -64
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { InstallMode, InstallTarget, ManifestData, SyncResult } from './types';
|
|
2
|
+
export interface TargetDefinition {
|
|
3
|
+
id: InstallMode;
|
|
4
|
+
label: string;
|
|
5
|
+
description: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const TARGET_DEFINITIONS: readonly TargetDefinition[];
|
|
8
|
+
export declare const VALID_MODES: readonly InstallMode[];
|
|
9
|
+
export declare const MANIFEST_FILENAME = ".apollo-toolkit-manifest.json";
|
|
10
|
+
export declare function resolveHomeDirectory(env?: NodeJS.ProcessEnv): string;
|
|
11
|
+
export declare function expandUserPath(inputPath: string, env?: NodeJS.ProcessEnv): string;
|
|
12
|
+
export declare function resolveToolkitHome(env?: NodeJS.ProcessEnv): string;
|
|
13
|
+
export declare function normalizeModes(inputModes: string[]): InstallMode[];
|
|
14
|
+
export declare function listSkillNames(rootDir: string, modes?: InstallMode[]): Promise<string[]>;
|
|
15
|
+
export declare function listCodexSkillNames(rootDir: string): Promise<string[]>;
|
|
16
|
+
export declare function readManifest(targetRoot: string): Promise<ManifestData | null>;
|
|
17
|
+
export declare function writeManifest(targetRoot: string, { version, linkMode, skills, previousSkills }: {
|
|
18
|
+
version: string;
|
|
19
|
+
linkMode: string;
|
|
20
|
+
skills: string[];
|
|
21
|
+
previousSkills?: string[];
|
|
22
|
+
}): Promise<void>;
|
|
23
|
+
export declare function listAllKnownSkillNames({ toolkitHome, modes, env }: {
|
|
24
|
+
toolkitHome: string;
|
|
25
|
+
modes?: InstallMode[];
|
|
26
|
+
env?: NodeJS.ProcessEnv;
|
|
27
|
+
}): Promise<string[]>;
|
|
28
|
+
export declare function syncToolkitHome({ sourceRoot, toolkitHome, version, modes }: {
|
|
29
|
+
sourceRoot: string;
|
|
30
|
+
toolkitHome: string;
|
|
31
|
+
version: string;
|
|
32
|
+
modes?: InstallMode[];
|
|
33
|
+
}): Promise<SyncResult & {
|
|
34
|
+
toolkitHome: string;
|
|
35
|
+
skillNames: string[];
|
|
36
|
+
}>;
|
|
37
|
+
export declare function getTargetRoots(modes: string[], env?: NodeJS.ProcessEnv): Promise<InstallTarget[]>;
|
|
38
|
+
export declare function getUninstallTargetRoots(modes?: string[], env?: NodeJS.ProcessEnv): Promise<InstallTarget[]>;
|
|
39
|
+
export declare function installLinks({ toolkitHome, modes, env, previousSkillNames, linkMode, includeExclusiveSkills }: {
|
|
40
|
+
toolkitHome: string;
|
|
41
|
+
modes: InstallMode[];
|
|
42
|
+
env?: NodeJS.ProcessEnv;
|
|
43
|
+
previousSkillNames?: string[];
|
|
44
|
+
linkMode?: 'copy' | 'symlink';
|
|
45
|
+
includeExclusiveSkills?: boolean;
|
|
46
|
+
}): Promise<{
|
|
47
|
+
skillNames: string[];
|
|
48
|
+
targets: InstallTarget[];
|
|
49
|
+
copiedPaths: any[];
|
|
50
|
+
linkMode: string;
|
|
51
|
+
}>;
|
|
52
|
+
export declare function uninstallSkills({ env, modes }?: {
|
|
53
|
+
env?: NodeJS.ProcessEnv;
|
|
54
|
+
modes?: InstallMode[] | null;
|
|
55
|
+
}): Promise<{
|
|
56
|
+
target: string;
|
|
57
|
+
root: string;
|
|
58
|
+
removedSkills: string[];
|
|
59
|
+
}[]>;
|
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MANIFEST_FILENAME = exports.VALID_MODES = exports.TARGET_DEFINITIONS = void 0;
|
|
7
|
+
exports.resolveHomeDirectory = resolveHomeDirectory;
|
|
8
|
+
exports.expandUserPath = expandUserPath;
|
|
9
|
+
exports.resolveToolkitHome = resolveToolkitHome;
|
|
10
|
+
exports.normalizeModes = normalizeModes;
|
|
11
|
+
exports.listSkillNames = listSkillNames;
|
|
12
|
+
exports.listCodexSkillNames = listCodexSkillNames;
|
|
13
|
+
exports.readManifest = readManifest;
|
|
14
|
+
exports.writeManifest = writeManifest;
|
|
15
|
+
exports.listAllKnownSkillNames = listAllKnownSkillNames;
|
|
16
|
+
exports.syncToolkitHome = syncToolkitHome;
|
|
17
|
+
exports.getTargetRoots = getTargetRoots;
|
|
18
|
+
exports.getUninstallTargetRoots = getUninstallTargetRoots;
|
|
19
|
+
exports.installLinks = installLinks;
|
|
20
|
+
exports.uninstallSkills = uninstallSkills;
|
|
21
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
22
|
+
const promises_1 = __importDefault(require("node:fs/promises"));
|
|
23
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
24
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
25
|
+
exports.TARGET_DEFINITIONS = Object.freeze([
|
|
26
|
+
{ id: 'codex', label: 'Codex', description: '~/.codex/skills' },
|
|
27
|
+
{ id: 'openclaw', label: 'OpenClaw', description: '~/.openclaw/workspace*/skills' },
|
|
28
|
+
{ id: 'trae', label: 'Trae', description: '~/.trae/skills' },
|
|
29
|
+
{ id: 'agents', label: 'Agents', description: '~/.agents/skills' },
|
|
30
|
+
{ id: 'claude-code', label: 'Claude Code', description: '~/.claude/skills' },
|
|
31
|
+
]);
|
|
32
|
+
exports.VALID_MODES = exports.TARGET_DEFINITIONS.map(({ id }) => id);
|
|
33
|
+
const COPY_FILES = new Set(['AGENTS.md', 'CHANGELOG.md', 'LICENSE', 'README.md', 'package.json']);
|
|
34
|
+
const COPY_DIRS = new Set();
|
|
35
|
+
exports.MANIFEST_FILENAME = '.apollo-toolkit-manifest.json';
|
|
36
|
+
function resolveHomeDirectory(env = process.env) {
|
|
37
|
+
return env.HOME || env.USERPROFILE || node_os_1.default.homedir();
|
|
38
|
+
}
|
|
39
|
+
function expandUserPath(inputPath, env = process.env) {
|
|
40
|
+
if (!inputPath)
|
|
41
|
+
return inputPath;
|
|
42
|
+
if (inputPath === '~')
|
|
43
|
+
return resolveHomeDirectory(env);
|
|
44
|
+
if (inputPath.startsWith('~/') || inputPath.startsWith('~\\')) {
|
|
45
|
+
return node_path_1.default.join(resolveHomeDirectory(env), inputPath.slice(2));
|
|
46
|
+
}
|
|
47
|
+
return inputPath;
|
|
48
|
+
}
|
|
49
|
+
function resolveToolkitHome(env = process.env) {
|
|
50
|
+
if (env.APOLLO_TOOLKIT_HOME) {
|
|
51
|
+
return node_path_1.default.resolve(expandUserPath(env.APOLLO_TOOLKIT_HOME, env));
|
|
52
|
+
}
|
|
53
|
+
return node_path_1.default.join(resolveHomeDirectory(env), '.apollo-toolkit');
|
|
54
|
+
}
|
|
55
|
+
function normalizeModes(inputModes) {
|
|
56
|
+
const modes = [];
|
|
57
|
+
for (const rawMode of inputModes) {
|
|
58
|
+
const mode = String(rawMode).toLowerCase();
|
|
59
|
+
if (mode === 'all') {
|
|
60
|
+
for (const candidate of exports.VALID_MODES) {
|
|
61
|
+
if (!modes.includes(candidate)) {
|
|
62
|
+
modes.push(candidate);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (!exports.VALID_MODES.includes(mode)) {
|
|
68
|
+
throw new Error(`Invalid mode: ${rawMode}`);
|
|
69
|
+
}
|
|
70
|
+
if (!modes.includes(mode)) {
|
|
71
|
+
modes.push(mode);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return modes;
|
|
75
|
+
}
|
|
76
|
+
async function listSkillNames(rootDir, modes = []) {
|
|
77
|
+
const entries = await promises_1.default.readdir(rootDir, { withFileTypes: true });
|
|
78
|
+
const skillNames = new Set();
|
|
79
|
+
for (const entry of entries) {
|
|
80
|
+
if (!entry.isDirectory())
|
|
81
|
+
continue;
|
|
82
|
+
if (node_fs_1.default.existsSync(node_path_1.default.join(rootDir, entry.name, 'SKILL.md'))) {
|
|
83
|
+
skillNames.add(entry.name);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (modes.includes('codex')) {
|
|
87
|
+
const codexDir = node_path_1.default.join(rootDir, 'codex');
|
|
88
|
+
if (node_fs_1.default.existsSync(codexDir)) {
|
|
89
|
+
const codexEntries = await promises_1.default.readdir(codexDir, { withFileTypes: true });
|
|
90
|
+
for (const entry of codexEntries) {
|
|
91
|
+
if (entry.isDirectory() && node_fs_1.default.existsSync(node_path_1.default.join(codexDir, entry.name, 'SKILL.md'))) {
|
|
92
|
+
skillNames.add(entry.name);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return [...skillNames].sort();
|
|
98
|
+
}
|
|
99
|
+
async function listCodexSkillNames(rootDir) {
|
|
100
|
+
const codexDir = node_path_1.default.join(rootDir, 'codex');
|
|
101
|
+
if (!node_fs_1.default.existsSync(codexDir))
|
|
102
|
+
return [];
|
|
103
|
+
const entries = await promises_1.default.readdir(codexDir, { withFileTypes: true });
|
|
104
|
+
return entries
|
|
105
|
+
.filter((entry) => entry.isDirectory() && node_fs_1.default.existsSync(node_path_1.default.join(codexDir, entry.name, 'SKILL.md')))
|
|
106
|
+
.map((entry) => entry.name)
|
|
107
|
+
.sort();
|
|
108
|
+
}
|
|
109
|
+
async function readManifest(targetRoot) {
|
|
110
|
+
const manifestPath = node_path_1.default.join(targetRoot, exports.MANIFEST_FILENAME);
|
|
111
|
+
try {
|
|
112
|
+
const raw = await promises_1.default.readFile(manifestPath, 'utf8');
|
|
113
|
+
return JSON.parse(raw);
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function isSafeSkillName(skillName) {
|
|
120
|
+
return typeof skillName === 'string'
|
|
121
|
+
&& skillName.length > 0
|
|
122
|
+
&& !skillName.includes('\0')
|
|
123
|
+
&& !skillName.includes('/')
|
|
124
|
+
&& !skillName.includes('\\')
|
|
125
|
+
&& !node_path_1.default.isAbsolute(skillName)
|
|
126
|
+
&& skillName !== '.'
|
|
127
|
+
&& skillName !== '..';
|
|
128
|
+
}
|
|
129
|
+
function getManifestSkillNames(manifest) {
|
|
130
|
+
return [...new Set([
|
|
131
|
+
...(Array.isArray(manifest.historicalSkills) ? manifest.historicalSkills : []),
|
|
132
|
+
...(Array.isArray(manifest.skills) ? manifest.skills : []),
|
|
133
|
+
])].filter(isSafeSkillName).sort();
|
|
134
|
+
}
|
|
135
|
+
async function writeManifest(targetRoot, { version, linkMode, skills, previousSkills = [] }) {
|
|
136
|
+
const historicalSkills = [...new Set([...previousSkills, ...skills])].sort();
|
|
137
|
+
const manifest = {
|
|
138
|
+
version,
|
|
139
|
+
installedAt: new Date().toISOString(),
|
|
140
|
+
linkMode,
|
|
141
|
+
skills: [...skills].sort(),
|
|
142
|
+
historicalSkills,
|
|
143
|
+
};
|
|
144
|
+
await promises_1.default.mkdir(targetRoot, { recursive: true });
|
|
145
|
+
await promises_1.default.writeFile(node_path_1.default.join(targetRoot, exports.MANIFEST_FILENAME), `${JSON.stringify(manifest, null, 2)}\n`, 'utf8');
|
|
146
|
+
}
|
|
147
|
+
async function listAllKnownSkillNames({ toolkitHome, modes = [], env = process.env }) {
|
|
148
|
+
const allNames = new Set();
|
|
149
|
+
const currentSkills = await listSkillNames(toolkitHome, modes).catch(() => []);
|
|
150
|
+
for (const name of currentSkills)
|
|
151
|
+
allNames.add(name);
|
|
152
|
+
const targets = await getUninstallTargetRoots(modes, env);
|
|
153
|
+
for (const target of targets) {
|
|
154
|
+
if (!target.root)
|
|
155
|
+
continue;
|
|
156
|
+
const manifest = await readManifest(target.root);
|
|
157
|
+
if (manifest && manifest.historicalSkills) {
|
|
158
|
+
for (const name of getManifestSkillNames(manifest)) {
|
|
159
|
+
allNames.add(name);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return [...allNames].sort();
|
|
164
|
+
}
|
|
165
|
+
function getTargetSkillNames({ targetMode, sharedSkillNames, codexSkillNames, includeExclusiveSkills = false }) {
|
|
166
|
+
const includeCodexSkills = targetMode === 'codex' || includeExclusiveSkills;
|
|
167
|
+
if (!includeCodexSkills || codexSkillNames.length === 0)
|
|
168
|
+
return sharedSkillNames;
|
|
169
|
+
return [...new Set([...sharedSkillNames, ...codexSkillNames])].sort();
|
|
170
|
+
}
|
|
171
|
+
function resolveInstallSourcePath({ toolkitHome, targetMode, skillName, codexSkillNames }) {
|
|
172
|
+
if (targetMode === 'codex' && codexSkillNames.includes(skillName)) {
|
|
173
|
+
return node_path_1.default.join(toolkitHome, 'codex', skillName);
|
|
174
|
+
}
|
|
175
|
+
return node_path_1.default.join(toolkitHome, skillName);
|
|
176
|
+
}
|
|
177
|
+
function shouldCopyEntry(sourceRoot, entry) {
|
|
178
|
+
if (entry.isFile())
|
|
179
|
+
return COPY_FILES.has(entry.name);
|
|
180
|
+
if (!entry.isDirectory())
|
|
181
|
+
return false;
|
|
182
|
+
if (COPY_DIRS.has(entry.name))
|
|
183
|
+
return true;
|
|
184
|
+
return node_fs_1.default.existsSync(node_path_1.default.join(sourceRoot, entry.name, 'SKILL.md'));
|
|
185
|
+
}
|
|
186
|
+
function shouldCopyCodexContainer({ sourceRoot, entry, modes = [] }) {
|
|
187
|
+
if (entry.name !== 'codex' || !entry.isDirectory() || !modes.includes('codex'))
|
|
188
|
+
return false;
|
|
189
|
+
const codexDir = node_path_1.default.join(sourceRoot, entry.name);
|
|
190
|
+
if (!node_fs_1.default.existsSync(codexDir))
|
|
191
|
+
return false;
|
|
192
|
+
const childNames = node_fs_1.default.readdirSync(codexDir);
|
|
193
|
+
return childNames.some((childName) => node_fs_1.default.existsSync(node_path_1.default.join(codexDir, childName, 'SKILL.md')));
|
|
194
|
+
}
|
|
195
|
+
async function stageToolkitContents({ sourceRoot, destinationRoot, version, modes = [] }) {
|
|
196
|
+
const entries = await promises_1.default.readdir(sourceRoot, { withFileTypes: true });
|
|
197
|
+
const copiedEntries = [];
|
|
198
|
+
await promises_1.default.mkdir(destinationRoot, { recursive: true });
|
|
199
|
+
for (const entry of entries) {
|
|
200
|
+
if (!shouldCopyEntry(sourceRoot, entry) && !shouldCopyCodexContainer({ sourceRoot, entry, modes }))
|
|
201
|
+
continue;
|
|
202
|
+
const sourcePath = node_path_1.default.join(sourceRoot, entry.name);
|
|
203
|
+
const destinationPath = node_path_1.default.join(destinationRoot, entry.name);
|
|
204
|
+
await promises_1.default.cp(sourcePath, destinationPath, { recursive: true, force: true });
|
|
205
|
+
copiedEntries.push(entry.name);
|
|
206
|
+
}
|
|
207
|
+
const metadata = { version, installedAt: new Date().toISOString(), source: 'npm-package' };
|
|
208
|
+
await promises_1.default.writeFile(node_path_1.default.join(destinationRoot, '.apollo-toolkit-install.json'), `${JSON.stringify(metadata, null, 2)}\n`, 'utf8');
|
|
209
|
+
return copiedEntries.sort();
|
|
210
|
+
}
|
|
211
|
+
async function syncToolkitHome({ sourceRoot, toolkitHome, version, modes = [] }) {
|
|
212
|
+
const parentDir = node_path_1.default.dirname(toolkitHome);
|
|
213
|
+
const tempDir = node_path_1.default.join(parentDir, `.apollo-toolkit.tmp-${process.pid}-${Date.now()}`);
|
|
214
|
+
const previousSkillNames = await listSkillNames(toolkitHome, modes).catch(() => []);
|
|
215
|
+
await promises_1.default.rm(tempDir, { recursive: true, force: true });
|
|
216
|
+
await stageToolkitContents({ sourceRoot, destinationRoot: tempDir, version, modes });
|
|
217
|
+
const stat = await promises_1.default.lstat(toolkitHome).catch(() => null);
|
|
218
|
+
if (stat && !stat.isDirectory()) {
|
|
219
|
+
throw new Error(`Apollo Toolkit home exists but is not a directory: ${toolkitHome}`);
|
|
220
|
+
}
|
|
221
|
+
await promises_1.default.rm(toolkitHome, { recursive: true, force: true });
|
|
222
|
+
await promises_1.default.mkdir(parentDir, { recursive: true });
|
|
223
|
+
await promises_1.default.rename(tempDir, toolkitHome);
|
|
224
|
+
return {
|
|
225
|
+
toolkitHome,
|
|
226
|
+
previousSkillNames,
|
|
227
|
+
skillNames: await listSkillNames(toolkitHome, modes),
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
async function getTargetRoots(modes, env = process.env) {
|
|
231
|
+
const homeDir = resolveHomeDirectory(env);
|
|
232
|
+
const targets = [];
|
|
233
|
+
for (const mode of normalizeModes(modes)) {
|
|
234
|
+
if (mode === 'codex') {
|
|
235
|
+
targets.push({
|
|
236
|
+
id: mode,
|
|
237
|
+
label: 'Codex',
|
|
238
|
+
root: env.CODEX_SKILLS_DIR
|
|
239
|
+
? node_path_1.default.resolve(expandUserPath(env.CODEX_SKILLS_DIR, env))
|
|
240
|
+
: node_path_1.default.join(homeDir, '.codex', 'skills'),
|
|
241
|
+
});
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
if (mode === 'trae') {
|
|
245
|
+
targets.push({
|
|
246
|
+
id: mode,
|
|
247
|
+
label: 'Trae',
|
|
248
|
+
root: env.TRAE_SKILLS_DIR
|
|
249
|
+
? node_path_1.default.resolve(expandUserPath(env.TRAE_SKILLS_DIR, env))
|
|
250
|
+
: node_path_1.default.join(homeDir, '.trae', 'skills'),
|
|
251
|
+
});
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
if (mode === 'agents') {
|
|
255
|
+
targets.push({
|
|
256
|
+
id: mode,
|
|
257
|
+
label: 'Agents',
|
|
258
|
+
root: env.AGENTS_SKILLS_DIR
|
|
259
|
+
? node_path_1.default.resolve(expandUserPath(env.AGENTS_SKILLS_DIR, env))
|
|
260
|
+
: node_path_1.default.join(homeDir, '.agents', 'skills'),
|
|
261
|
+
});
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
if (mode === 'openclaw') {
|
|
265
|
+
const openclawHome = env.OPENCLAW_HOME
|
|
266
|
+
? node_path_1.default.resolve(expandUserPath(env.OPENCLAW_HOME, env))
|
|
267
|
+
: node_path_1.default.join(homeDir, '.openclaw');
|
|
268
|
+
const entries = await promises_1.default.readdir(openclawHome, { withFileTypes: true }).catch(() => []);
|
|
269
|
+
const workspaceNames = entries
|
|
270
|
+
.filter((entry) => entry.isDirectory() && entry.name.startsWith('workspace'))
|
|
271
|
+
.map((entry) => entry.name)
|
|
272
|
+
.sort();
|
|
273
|
+
if (workspaceNames.length === 0) {
|
|
274
|
+
throw new Error(`No workspace directories found under: ${openclawHome}`);
|
|
275
|
+
}
|
|
276
|
+
for (const workspaceName of workspaceNames) {
|
|
277
|
+
targets.push({
|
|
278
|
+
id: mode,
|
|
279
|
+
label: `OpenClaw (${workspaceName})`,
|
|
280
|
+
root: node_path_1.default.join(openclawHome, workspaceName, 'skills'),
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
if (mode === 'claude-code') {
|
|
286
|
+
targets.push({
|
|
287
|
+
id: mode,
|
|
288
|
+
label: 'Claude Code',
|
|
289
|
+
root: env.CLAUDE_CODE_SKILLS_DIR
|
|
290
|
+
? node_path_1.default.resolve(expandUserPath(env.CLAUDE_CODE_SKILLS_DIR, env))
|
|
291
|
+
: node_path_1.default.join(homeDir, '.claude', 'skills'),
|
|
292
|
+
});
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return targets;
|
|
297
|
+
}
|
|
298
|
+
async function getUninstallTargetRoots(modes = [...exports.VALID_MODES], env = process.env) {
|
|
299
|
+
const targets = [];
|
|
300
|
+
for (const mode of normalizeModes(modes)) {
|
|
301
|
+
try {
|
|
302
|
+
targets.push(...await getTargetRoots([mode], env));
|
|
303
|
+
}
|
|
304
|
+
catch {
|
|
305
|
+
// Uninstall is best-effort across agents
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return targets;
|
|
309
|
+
}
|
|
310
|
+
async function ensureDirectory(dirPath) {
|
|
311
|
+
await promises_1.default.mkdir(dirPath, { recursive: true });
|
|
312
|
+
}
|
|
313
|
+
async function replaceWithCopy(sourcePath, targetPath) {
|
|
314
|
+
await promises_1.default.rm(targetPath, { recursive: true, force: true });
|
|
315
|
+
await ensureDirectory(node_path_1.default.dirname(targetPath));
|
|
316
|
+
await promises_1.default.cp(sourcePath, targetPath, { recursive: true, force: true });
|
|
317
|
+
}
|
|
318
|
+
async function replaceWithSymlink(sourcePath, targetPath) {
|
|
319
|
+
await promises_1.default.rm(targetPath, { recursive: true, force: true });
|
|
320
|
+
await ensureDirectory(node_path_1.default.dirname(targetPath));
|
|
321
|
+
await promises_1.default.symlink(sourcePath, targetPath, process.platform === 'win32' ? 'junction' : 'dir');
|
|
322
|
+
}
|
|
323
|
+
async function installLinks({ toolkitHome, modes, env = process.env, previousSkillNames = [], linkMode = 'copy', includeExclusiveSkills = false }) {
|
|
324
|
+
const normalizedModes = normalizeModes(modes);
|
|
325
|
+
const codexSkillNames = (normalizedModes.includes('codex') || includeExclusiveSkills)
|
|
326
|
+
? await listCodexSkillNames(toolkitHome)
|
|
327
|
+
: [];
|
|
328
|
+
const sharedSkillNames = await listSkillNames(toolkitHome);
|
|
329
|
+
const skillNames = normalizedModes.includes('codex')
|
|
330
|
+
? [...new Set([...sharedSkillNames, ...codexSkillNames])].sort()
|
|
331
|
+
: sharedSkillNames;
|
|
332
|
+
const targets = await getTargetRoots(normalizedModes, env);
|
|
333
|
+
const copiedPaths = [];
|
|
334
|
+
for (const target of targets) {
|
|
335
|
+
const targetSkillNames = getTargetSkillNames({
|
|
336
|
+
targetMode: target.id,
|
|
337
|
+
sharedSkillNames,
|
|
338
|
+
codexSkillNames,
|
|
339
|
+
includeExclusiveSkills,
|
|
340
|
+
});
|
|
341
|
+
const existingManifest = await readManifest(target.root);
|
|
342
|
+
const allPreviousSkills = existingManifest
|
|
343
|
+
? [...new Set([...getManifestSkillNames(existingManifest), ...previousSkillNames.filter(isSafeSkillName)])]
|
|
344
|
+
: previousSkillNames.filter(isSafeSkillName);
|
|
345
|
+
const staleSkillNames = allPreviousSkills.filter((skillName) => !targetSkillNames.includes(skillName));
|
|
346
|
+
await ensureDirectory(target.root);
|
|
347
|
+
for (const staleSkillName of staleSkillNames) {
|
|
348
|
+
await promises_1.default.rm(node_path_1.default.join(target.root, staleSkillName), { recursive: true, force: true });
|
|
349
|
+
}
|
|
350
|
+
for (const skillName of targetSkillNames) {
|
|
351
|
+
const sourcePath = resolveInstallSourcePath({
|
|
352
|
+
toolkitHome,
|
|
353
|
+
targetMode: target.id,
|
|
354
|
+
skillName,
|
|
355
|
+
codexSkillNames,
|
|
356
|
+
});
|
|
357
|
+
const targetPath = node_path_1.default.join(target.root, skillName);
|
|
358
|
+
if (linkMode === 'symlink') {
|
|
359
|
+
await replaceWithSymlink(sourcePath, targetPath);
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
await replaceWithCopy(sourcePath, targetPath);
|
|
363
|
+
}
|
|
364
|
+
copiedPaths.push({ target: target.label, path: targetPath, skillName, linkMode });
|
|
365
|
+
}
|
|
366
|
+
await writeManifest(target.root, {
|
|
367
|
+
version: existingManifest?.version || 'unknown',
|
|
368
|
+
linkMode,
|
|
369
|
+
skills: targetSkillNames,
|
|
370
|
+
previousSkills: allPreviousSkills,
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
return { skillNames, targets, copiedPaths, linkMode };
|
|
374
|
+
}
|
|
375
|
+
async function uninstallSkills({ env = process.env, modes = null } = {}) {
|
|
376
|
+
const normalizedModes = modes ? normalizeModes(modes) : [...exports.VALID_MODES];
|
|
377
|
+
const targets = await getUninstallTargetRoots(normalizedModes, env);
|
|
378
|
+
const results = [];
|
|
379
|
+
for (const target of targets) {
|
|
380
|
+
const manifest = await readManifest(target.root);
|
|
381
|
+
if (!manifest)
|
|
382
|
+
continue;
|
|
383
|
+
const skillNames = getManifestSkillNames(manifest);
|
|
384
|
+
const removedSkills = [];
|
|
385
|
+
for (const skillName of skillNames) {
|
|
386
|
+
const skillPath = node_path_1.default.join(target.root, skillName);
|
|
387
|
+
try {
|
|
388
|
+
await promises_1.default.rm(skillPath, { recursive: true, force: true });
|
|
389
|
+
removedSkills.push(skillName);
|
|
390
|
+
}
|
|
391
|
+
catch {
|
|
392
|
+
// skip
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
try {
|
|
396
|
+
await promises_1.default.rm(node_path_1.default.join(target.root, exports.MANIFEST_FILENAME), { force: true });
|
|
397
|
+
}
|
|
398
|
+
catch {
|
|
399
|
+
// ok
|
|
400
|
+
}
|
|
401
|
+
results.push({ target: target.label, root: target.root, removedSkills });
|
|
402
|
+
}
|
|
403
|
+
return results;
|
|
404
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { formatExamples } from './utils/format';
|
|
2
|
+
import type { ToolContext, ToolDefinition } from './types';
|
|
3
|
+
export declare function getToolCommand(name: string): ToolDefinition | null;
|
|
4
|
+
export declare function listToolCommands(): ToolDefinition[];
|
|
5
|
+
export declare function resolveToolCommand(name: string, sourceRoot: string): (ToolDefinition & {
|
|
6
|
+
scriptPath?: string;
|
|
7
|
+
}) | null;
|
|
8
|
+
export declare function formatToolList(): string;
|
|
9
|
+
declare function buildToolOverview(name: string): string | null;
|
|
10
|
+
declare function buildToolExamples(name: string): string;
|
|
11
|
+
export declare function buildToolDiscoveryHelp(): string;
|
|
12
|
+
declare function isTopLevelToolHelpRequest(toolArgs: string[]): boolean;
|
|
13
|
+
declare function captureCommandOutput(tool: ToolDefinition, toolArgs: string[], context?: ToolContext): Promise<{
|
|
14
|
+
exitCode: number;
|
|
15
|
+
stdout: string;
|
|
16
|
+
stderr: string;
|
|
17
|
+
}>;
|
|
18
|
+
export declare function runTool(toolName: string, toolArgs: string[], context?: ToolContext): Promise<number>;
|
|
19
|
+
export { formatExamples, buildToolOverview, buildToolExamples, isTopLevelToolHelpRequest, captureCommandOutput };
|