@laitszkin/apollo-toolkit 3.13.2 → 3.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/AGENTS.md +7 -7
  2. package/CHANGELOG.md +27 -0
  3. package/CLAUDE.md +8 -8
  4. package/analyse-app-logs/SKILL.md +3 -3
  5. package/bin/apollo-toolkit.ts +7 -0
  6. package/codex/codex-memory-manager/SKILL.md +2 -2
  7. package/codex/learn-skill-from-conversations/SKILL.md +3 -3
  8. package/dist/bin/apollo-toolkit.d.ts +2 -0
  9. package/dist/bin/apollo-toolkit.js +7 -0
  10. package/dist/lib/cli.d.ts +41 -0
  11. package/dist/lib/cli.js +655 -0
  12. package/dist/lib/installer.d.ts +59 -0
  13. package/dist/lib/installer.js +404 -0
  14. package/dist/lib/tool-runner.d.ts +19 -0
  15. package/dist/lib/tool-runner.js +536 -0
  16. package/dist/lib/tools/architecture.d.ts +2 -0
  17. package/dist/lib/tools/architecture.js +34 -0
  18. package/dist/lib/tools/create-specs.d.ts +2 -0
  19. package/dist/lib/tools/create-specs.js +175 -0
  20. package/dist/lib/tools/docs-to-voice.d.ts +2 -0
  21. package/dist/lib/tools/docs-to-voice.js +705 -0
  22. package/dist/lib/tools/enforce-video-aspect-ratio.d.ts +2 -0
  23. package/dist/lib/tools/enforce-video-aspect-ratio.js +312 -0
  24. package/dist/lib/tools/extract-conversations.d.ts +2 -0
  25. package/dist/lib/tools/extract-conversations.js +105 -0
  26. package/dist/lib/tools/extract-pdf-text.d.ts +2 -0
  27. package/dist/lib/tools/extract-pdf-text.js +92 -0
  28. package/dist/lib/tools/filter-logs.d.ts +2 -0
  29. package/dist/lib/tools/filter-logs.js +94 -0
  30. package/dist/lib/tools/find-github-issues.d.ts +2 -0
  31. package/dist/lib/tools/find-github-issues.js +176 -0
  32. package/dist/lib/tools/generate-storyboard-images.d.ts +2 -0
  33. package/dist/lib/tools/generate-storyboard-images.js +419 -0
  34. package/dist/lib/tools/log-cli-utils.d.ts +35 -0
  35. package/dist/lib/tools/log-cli-utils.js +233 -0
  36. package/dist/lib/tools/open-github-issue.d.ts +2 -0
  37. package/dist/lib/tools/open-github-issue.js +750 -0
  38. package/dist/lib/tools/read-github-issue.d.ts +2 -0
  39. package/dist/lib/tools/read-github-issue.js +134 -0
  40. package/dist/lib/tools/render-error-book.d.ts +2 -0
  41. package/dist/lib/tools/render-error-book.js +265 -0
  42. package/dist/lib/tools/render-katex.d.ts +2 -0
  43. package/dist/lib/tools/render-katex.js +294 -0
  44. package/dist/lib/tools/review-threads.d.ts +2 -0
  45. package/dist/lib/tools/review-threads.js +491 -0
  46. package/dist/lib/tools/search-logs.d.ts +2 -0
  47. package/dist/lib/tools/search-logs.js +164 -0
  48. package/dist/lib/tools/sync-memory-index.d.ts +2 -0
  49. package/dist/lib/tools/sync-memory-index.js +113 -0
  50. package/dist/lib/tools/validate-openai-agent-config.d.ts +2 -0
  51. package/dist/lib/tools/validate-openai-agent-config.js +184 -0
  52. package/dist/lib/tools/validate-skill-frontmatter.d.ts +2 -0
  53. package/dist/lib/tools/validate-skill-frontmatter.js +118 -0
  54. package/dist/lib/types.d.ts +82 -0
  55. package/dist/lib/types.js +2 -0
  56. package/dist/lib/updater.d.ts +34 -0
  57. package/dist/lib/updater.js +112 -0
  58. package/dist/lib/utils/format.d.ts +2 -0
  59. package/dist/lib/utils/format.js +6 -0
  60. package/dist/lib/utils/terminal.d.ts +12 -0
  61. package/dist/lib/utils/terminal.js +26 -0
  62. package/docs-to-voice/SKILL.md +0 -1
  63. package/generate-spec/SKILL.md +1 -1
  64. package/katex/SKILL.md +1 -2
  65. package/lib/cli.ts +780 -0
  66. package/lib/installer.ts +466 -0
  67. package/lib/tool-runner.ts +561 -0
  68. package/lib/tools/architecture.ts +34 -0
  69. package/lib/tools/create-specs.ts +204 -0
  70. package/lib/tools/docs-to-voice.ts +799 -0
  71. package/lib/tools/enforce-video-aspect-ratio.ts +368 -0
  72. package/lib/tools/extract-conversations.ts +114 -0
  73. package/lib/tools/extract-pdf-text.ts +99 -0
  74. package/lib/tools/filter-logs.ts +118 -0
  75. package/lib/tools/find-github-issues.ts +211 -0
  76. package/lib/tools/generate-storyboard-images.ts +455 -0
  77. package/lib/tools/log-cli-utils.ts +262 -0
  78. package/lib/tools/open-github-issue.ts +930 -0
  79. package/lib/tools/read-github-issue.ts +179 -0
  80. package/lib/tools/render-error-book.ts +300 -0
  81. package/lib/tools/render-katex.ts +325 -0
  82. package/lib/tools/review-threads.ts +590 -0
  83. package/lib/tools/search-logs.ts +200 -0
  84. package/lib/tools/sync-memory-index.ts +114 -0
  85. package/lib/tools/validate-openai-agent-config.ts +209 -0
  86. package/lib/tools/validate-skill-frontmatter.ts +124 -0
  87. package/lib/types.ts +90 -0
  88. package/lib/updater.ts +165 -0
  89. package/lib/utils/format.ts +7 -0
  90. package/lib/utils/terminal.ts +22 -0
  91. package/open-github-issue/SKILL.md +2 -2
  92. package/optimise-skill/SKILL.md +1 -1
  93. package/package.json +13 -4
  94. package/resources/project-architecture/assets/architecture.css +764 -0
  95. package/resources/project-architecture/assets/viewer.client.js +144 -0
  96. package/resources/project-architecture/index.html +42 -0
  97. package/review-spec-related-changes/SKILL.md +1 -1
  98. package/solve-issues-found-during-review/SKILL.md +2 -1
  99. package/tsconfig.json +28 -0
  100. package/analyse-app-logs/scripts/__pycache__/filter_logs_by_time.cpython-312.pyc +0 -0
  101. package/analyse-app-logs/scripts/__pycache__/log_cli_utils.cpython-312.pyc +0 -0
  102. package/analyse-app-logs/scripts/__pycache__/search_logs.cpython-312.pyc +0 -0
  103. package/analyse-app-logs/scripts/filter_logs_by_time.py +0 -64
  104. package/analyse-app-logs/scripts/log_cli_utils.py +0 -112
  105. package/analyse-app-logs/scripts/search_logs.py +0 -137
  106. package/analyse-app-logs/tests/test_filter_logs_by_time.py +0 -95
  107. package/analyse-app-logs/tests/test_search_logs.py +0 -100
  108. package/codex/codex-memory-manager/scripts/extract_recent_conversations.py +0 -369
  109. package/codex/codex-memory-manager/scripts/sync_memory_index.py +0 -130
  110. package/codex/codex-memory-manager/tests/test_extract_recent_conversations.py +0 -177
  111. package/codex/codex-memory-manager/tests/test_memory_template.py +0 -37
  112. package/codex/codex-memory-manager/tests/test_sync_memory_index.py +0 -84
  113. package/codex/learn-skill-from-conversations/scripts/extract_recent_conversations.py +0 -369
  114. package/codex/learn-skill-from-conversations/tests/test_extract_recent_conversations.py +0 -177
  115. package/docs-to-voice/scripts/__pycache__/docs_to_voice.cpython-312.pyc +0 -0
  116. package/docs-to-voice/scripts/docs_to_voice.py +0 -1385
  117. package/docs-to-voice/scripts/docs_to_voice.sh +0 -11
  118. package/docs-to-voice/tests/test_docs_to_voice_api_max_chars.py +0 -210
  119. package/docs-to-voice/tests/test_docs_to_voice_sentence_timeline.py +0 -115
  120. package/docs-to-voice/tests/test_docs_to_voice_settings.py +0 -43
  121. package/docs-to-voice/tests/test_docs_to_voice_shell_wrapper.py +0 -51
  122. package/docs-to-voice/tests/test_docs_to_voice_speech_rate.py +0 -57
  123. package/generate-spec/scripts/__pycache__/create-specscpython-312.pyc +0 -0
  124. package/generate-spec/scripts/create-specs +0 -215
  125. package/generate-spec/tests/test_create_specs.py +0 -200
  126. package/init-project-html/scripts/architecture-bootstrap-render.js +0 -16
  127. package/init-project-html/scripts/architecture.js +0 -296
  128. package/katex/scripts/__pycache__/render_katex.cpython-312.pyc +0 -0
  129. package/katex/scripts/render_katex.py +0 -247
  130. package/katex/scripts/render_katex.sh +0 -11
  131. package/katex/tests/test_render_katex.py +0 -174
  132. package/learning-error-book/scripts/render_error_book_json_to_pdf.py +0 -590
  133. package/learning-error-book/tests/test_render_error_book_json_to_pdf.py +0 -134
  134. package/open-github-issue/scripts/__pycache__/open_github_issue.cpython-312.pyc +0 -0
  135. package/open-github-issue/scripts/open_github_issue.py +0 -705
  136. package/open-github-issue/tests/test_open_github_issue.py +0 -381
  137. package/openai-text-to-image-storyboard/scripts/generate_storyboard_images.py +0 -763
  138. package/openai-text-to-image-storyboard/tests/test_generate_storyboard_images.py +0 -177
  139. package/read-github-issue/scripts/__pycache__/find_issues.cpython-312.pyc +0 -0
  140. package/read-github-issue/scripts/__pycache__/read_issue.cpython-312.pyc +0 -0
  141. package/read-github-issue/scripts/find_issues.py +0 -148
  142. package/read-github-issue/scripts/read_issue.py +0 -108
  143. package/read-github-issue/tests/test_find_issues.py +0 -127
  144. package/read-github-issue/tests/test_read_issue.py +0 -109
  145. package/resolve-review-comments/scripts/__pycache__/review_threads.cpython-312.pyc +0 -0
  146. package/resolve-review-comments/scripts/review_threads.py +0 -425
  147. package/resolve-review-comments/tests/test_review_threads.py +0 -74
  148. package/scripts/validate_openai_agent_config.py +0 -209
  149. package/scripts/validate_skill_frontmatter.py +0 -131
  150. package/text-to-short-video/scripts/__pycache__/enforce_video_aspect_ratio.cpython-312.pyc +0 -0
  151. package/text-to-short-video/scripts/enforce_video_aspect_ratio.py +0 -350
  152. package/text-to-short-video/tests/test_enforce_video_aspect_ratio.py +0 -194
  153. package/weekly-financial-event-report/scripts/extract_pdf_text_pdfkit.swift +0 -99
  154. 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 };