@laitszkin/apollo-toolkit 4.1.3 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +45 -0
- package/bin/apollo-toolkit.ts +4 -0
- package/dist/bin/apollo-toolkit.js +4 -0
- package/package.json +7 -2
- package/packages/cli/dist/help-text-builder.d.ts +23 -0
- package/packages/cli/dist/help-text-builder.js +166 -0
- package/packages/cli/dist/index.d.ts +6 -17
- package/packages/cli/dist/index.js +52 -246
- package/packages/cli/dist/installer.d.ts +1 -0
- package/packages/cli/dist/installer.js +20 -7
- package/packages/cli/dist/parsers/install-parser.d.ts +15 -0
- package/packages/cli/dist/parsers/install-parser.js +87 -0
- package/packages/cli/dist/parsers/parser-utils.d.ts +9 -0
- package/packages/cli/dist/parsers/parser-utils.js +16 -0
- package/packages/cli/dist/parsers/tool-parser.d.ts +16 -0
- package/packages/cli/dist/parsers/tool-parser.js +58 -0
- package/packages/cli/dist/parsers/types.d.ts +50 -0
- package/packages/cli/dist/parsers/types.js +1 -0
- package/packages/cli/dist/parsers/uninstall-parser.d.ts +15 -0
- package/packages/cli/dist/parsers/uninstall-parser.js +67 -0
- package/packages/cli/dist/tool-registration.d.ts +2 -0
- package/packages/cli/dist/tool-registration.js +2 -0
- package/packages/cli/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/cli/dist/types.d.ts +3 -1
- package/packages/cli/dist/updater.js +11 -5
- package/packages/cli/help-text-builder.ts +180 -0
- package/packages/cli/index.ts +59 -251
- package/packages/cli/installer.ts +19 -7
- package/packages/cli/package.json +6 -3
- package/packages/cli/parsers/install-parser.ts +94 -0
- package/packages/cli/parsers/parser-utils.ts +17 -0
- package/packages/cli/parsers/tool-parser.ts +65 -0
- package/packages/cli/parsers/types.ts +56 -0
- package/packages/cli/parsers/uninstall-parser.ts +75 -0
- package/packages/cli/tool-registration.ts +3 -0
- package/packages/cli/types.ts +6 -1
- package/packages/cli/updater.ts +11 -5
- package/packages/tool-registry/dist/registry.js +3 -4
- package/packages/tool-registry/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tool-registry/dist/types.d.ts +2 -9
- package/packages/tool-registry/package.json +3 -3
- package/packages/tool-registry/registry.ts +3 -4
- package/packages/tool-registry/tsconfig.json +6 -2
- package/packages/tool-registry/types.ts +3 -9
- package/packages/tool-utils/app-error.ts +97 -0
- package/packages/tool-utils/dist/app-error.d.ts +49 -0
- package/packages/tool-utils/dist/app-error.js +80 -0
- package/packages/tool-utils/dist/index.d.ts +5 -0
- package/packages/tool-utils/dist/index.js +3 -0
- package/packages/tool-utils/dist/platform-adapter.d.ts +48 -0
- package/packages/tool-utils/dist/platform-adapter.js +73 -0
- package/packages/tool-utils/dist/schema.d.ts +68 -0
- package/packages/tool-utils/dist/schema.js +67 -0
- package/packages/tool-utils/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tool-utils/index.ts +12 -0
- package/packages/tool-utils/package.json +3 -3
- package/packages/tool-utils/platform-adapter.ts +112 -0
- package/packages/tool-utils/schema.ts +122 -0
- package/packages/tools/architecture/dist/index.d.ts +13 -0
- package/packages/tools/architecture/dist/index.js +55 -57
- package/packages/tools/architecture/dist/index.test.js +17 -4
- package/packages/tools/architecture/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tools/architecture/index.test.ts +27 -14
- package/packages/tools/architecture/index.ts +85 -88
- package/packages/tools/architecture/package.json +3 -3
- package/packages/tools/codegraph/dist/index.js +21 -17
- package/packages/tools/codegraph/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tools/codegraph/index.ts +21 -17
- package/packages/tools/codegraph/package.json +3 -3
- package/packages/tools/create-review-report/dist/index.d.ts +1 -2
- package/packages/tools/create-review-report/dist/index.js +46 -77
- package/packages/tools/create-review-report/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tools/create-review-report/index.ts +52 -81
- package/packages/tools/create-review-report/package.json +3 -3
- package/packages/tools/create-specs/dist/index.d.ts +1 -2
- package/packages/tools/create-specs/dist/index.js +70 -123
- package/packages/tools/create-specs/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tools/create-specs/index.ts +82 -128
- package/packages/tools/create-specs/package.json +3 -3
- package/packages/tools/docs-to-voice/dist/index.d.ts +1 -2
- package/packages/tools/docs-to-voice/dist/index.js +116 -219
- package/packages/tools/docs-to-voice/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tools/docs-to-voice/index.ts +265 -385
- package/packages/tools/docs-to-voice/package.json +3 -3
- package/packages/tools/enforce-video-aspect-ratio/dist/index.d.ts +1 -2
- package/packages/tools/enforce-video-aspect-ratio/dist/index.js +77 -154
- package/packages/tools/enforce-video-aspect-ratio/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tools/enforce-video-aspect-ratio/index.ts +87 -172
- package/packages/tools/enforce-video-aspect-ratio/package.json +3 -3
- package/packages/tools/eval/dist/index.js +7 -0
- package/packages/tools/eval/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tools/eval/index.ts +8 -0
- package/packages/tools/eval/package.json +3 -3
- package/packages/tools/extract-conversations/dist/index.d.ts +1 -2
- package/packages/tools/extract-conversations/dist/index.js +31 -29
- package/packages/tools/extract-conversations/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tools/extract-conversations/index.ts +37 -30
- package/packages/tools/extract-conversations/package.json +3 -3
- package/packages/tools/extract-pdf-text/dist/index.d.ts +1 -2
- package/packages/tools/extract-pdf-text/dist/index.js +44 -65
- package/packages/tools/extract-pdf-text/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tools/extract-pdf-text/index.ts +55 -74
- package/packages/tools/extract-pdf-text/package.json +3 -3
- package/packages/tools/filter-logs/dist/index.js +60 -84
- package/packages/tools/filter-logs/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tools/filter-logs/index.ts +67 -97
- package/packages/tools/filter-logs/package.json +3 -3
- package/packages/tools/find-github-issues/dist/index.d.ts +10 -0
- package/packages/tools/find-github-issues/dist/index.js +34 -5
- package/packages/tools/find-github-issues/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tools/find-github-issues/index.ts +37 -5
- package/packages/tools/find-github-issues/package.json +3 -3
- package/packages/tools/generate-storyboard-images/dist/index.d.ts +1 -2
- package/packages/tools/generate-storyboard-images/dist/index.js +98 -173
- package/packages/tools/generate-storyboard-images/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tools/generate-storyboard-images/index.ts +100 -188
- package/packages/tools/generate-storyboard-images/package.json +3 -3
- package/packages/tools/open-github-issue/dist/index.d.ts +13 -0
- package/packages/tools/open-github-issue/dist/index.js +67 -68
- package/packages/tools/open-github-issue/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tools/open-github-issue/index.ts +71 -72
- package/packages/tools/open-github-issue/package.json +3 -3
- package/packages/tools/read-github-issue/dist/index.d.ts +16 -1
- package/packages/tools/read-github-issue/dist/index.js +32 -40
- package/packages/tools/read-github-issue/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tools/read-github-issue/index.ts +32 -45
- package/packages/tools/read-github-issue/package.json +3 -3
- package/packages/tools/render-error-book/dist/index.d.ts +1 -2
- package/packages/tools/render-error-book/dist/index.js +74 -95
- package/packages/tools/render-error-book/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tools/render-error-book/index.ts +88 -103
- package/packages/tools/render-error-book/package.json +3 -3
- package/packages/tools/render-katex/dist/index.d.ts +1 -2
- package/packages/tools/render-katex/dist/index.js +70 -157
- package/packages/tools/render-katex/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tools/render-katex/index.ts +138 -222
- package/packages/tools/render-katex/package.json +3 -3
- package/packages/tools/review-threads/dist/index.d.ts +12 -0
- package/packages/tools/review-threads/dist/index.js +83 -86
- package/packages/tools/review-threads/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tools/review-threads/index.ts +90 -84
- package/packages/tools/review-threads/package.json +3 -3
- package/packages/tools/search-logs/dist/index.js +100 -136
- package/packages/tools/search-logs/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tools/search-logs/index.ts +113 -145
- package/packages/tools/search-logs/package.json +3 -3
- package/packages/tools/sync-memory-index/dist/index.js +34 -28
- package/packages/tools/sync-memory-index/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tools/sync-memory-index/index.ts +37 -28
- package/packages/tools/sync-memory-index/package.json +3 -3
- package/packages/tools/validate-openai-agent-config/dist/index.js +13 -7
- package/packages/tools/validate-openai-agent-config/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tools/validate-openai-agent-config/index.ts +13 -7
- package/packages/tools/validate-openai-agent-config/package.json +3 -3
- package/packages/tools/validate-skill-frontmatter/dist/index.js +12 -6
- package/packages/tools/validate-skill-frontmatter/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tools/validate-skill-frontmatter/index.ts +12 -6
- package/packages/tools/validate-skill-frontmatter/package.json +3 -3
- package/packages/tui/dist/index.d.ts +2 -1
- package/packages/tui/dist/index.js +1 -0
- package/packages/tui/dist/stdio-adapter.d.ts +36 -0
- package/packages/tui/dist/stdio-adapter.js +69 -0
- package/packages/tui/dist/terminal.js +3 -1
- package/packages/tui/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/tui/dist/types.d.ts +17 -0
- package/packages/tui/index.ts +2 -1
- package/packages/tui/package.json +6 -5
- package/packages/tui/stdio-adapter.ts +85 -0
- package/packages/tui/terminal.ts +3 -1
- package/packages/tui/tsconfig.json +5 -2
- package/packages/tui/types.ts +19 -0
- package/resources/project-architecture/assets/architecture.css +2 -1
- package/resources/project-architecture/atlas/atlas.history.log +1 -0
- package/resources/project-architecture/atlas/atlas.history.undo.json +13 -2
- package/resources/project-architecture/atlas/atlas.history.undo.stack.json +610 -0
- package/resources/project-architecture/atlas/atlas.index.yaml +81 -5
- package/resources/project-architecture/atlas/features/cli-dispatch.yaml +43 -0
- package/resources/project-architecture/atlas/features/terminal-ui.yaml +29 -0
- package/resources/project-architecture/atlas/features/tool-registry.yaml +22 -0
- package/resources/project-architecture/atlas/features/tool-utils.yaml +22 -0
- package/resources/project-architecture/features/cli-dispatch/arg-parser.html +40 -0
- package/resources/project-architecture/features/cli-dispatch/help-builder.html +40 -0
- package/resources/project-architecture/features/cli-dispatch/index.html +64 -0
- package/resources/project-architecture/features/cli-dispatch/installer-core.html +40 -0
- package/resources/project-architecture/features/cli-dispatch/tool-discovery.html +40 -0
- package/resources/project-architecture/features/cli-dispatch/update-checker.html +40 -0
- package/resources/project-architecture/features/terminal-ui/banner-display.html +40 -0
- package/resources/project-architecture/features/terminal-ui/index.html +50 -0
- package/resources/project-architecture/features/terminal-ui/interactive-prompts.html +40 -0
- package/resources/project-architecture/features/terminal-ui/terminal-detection.html +40 -0
- package/resources/project-architecture/features/tool-registry/formatter.html +40 -0
- package/resources/project-architecture/features/tool-registry/index.html +43 -0
- package/resources/project-architecture/features/tool-registry/registry-core.html +40 -0
- package/resources/project-architecture/features/tool-utils/index.html +43 -0
- package/resources/project-architecture/features/tool-utils/log-utils.html +40 -0
- package/resources/project-architecture/features/tool-utils/skill-discovery.html +40 -0
- package/resources/project-architecture/index.html +365 -121
- package/scripts/rewrite-imports.mjs +2 -2
- package/scripts/test.sh +144 -8
- package/skills/design/SKILL.md +57 -64
- package/skills/design/assets/templates/DESIGN.md +12 -0
- package/skills/design/references/code-smells.md +94 -0
- package/skills/design/references/module-boundary-adjustment.md +126 -0
- package/skills/design/references/module-internal-restructuring.md +132 -0
- package/skills/design/references/module-internal-simplification.md +164 -0
|
@@ -4,110 +4,7 @@ import https from 'node:https';
|
|
|
4
4
|
import http from 'node:http';
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
6
|
import type { ToolDefinition, ToolContext } from '@laitszkin/tool-registry';
|
|
7
|
-
|
|
8
|
-
interface StoryboardArgs {
|
|
9
|
-
contentName: string | null;
|
|
10
|
-
projectDir: string;
|
|
11
|
-
envFile: string | null;
|
|
12
|
-
apiUrl: string | null;
|
|
13
|
-
apiKey: string | null;
|
|
14
|
-
promptsFile: string | null;
|
|
15
|
-
prompts: string[];
|
|
16
|
-
imageModel: string | null;
|
|
17
|
-
aspectRatio: string | null;
|
|
18
|
-
imageSize: string | null;
|
|
19
|
-
quality: string | null;
|
|
20
|
-
style: string | null;
|
|
21
|
-
help: boolean;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function parseArgs(args: string[]): StoryboardArgs {
|
|
25
|
-
const parsed: StoryboardArgs = {
|
|
26
|
-
contentName: null,
|
|
27
|
-
projectDir: '.',
|
|
28
|
-
envFile: null,
|
|
29
|
-
apiUrl: null,
|
|
30
|
-
apiKey: null,
|
|
31
|
-
promptsFile: null,
|
|
32
|
-
prompts: [],
|
|
33
|
-
imageModel: null,
|
|
34
|
-
aspectRatio: null,
|
|
35
|
-
imageSize: null,
|
|
36
|
-
quality: null,
|
|
37
|
-
style: null,
|
|
38
|
-
help: false,
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
for (let i = 0; i < args.length; i++) {
|
|
42
|
-
const arg = args[i];
|
|
43
|
-
if (arg === '--help' || arg === '-h') {
|
|
44
|
-
parsed.help = true;
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
if (arg.startsWith('--')) {
|
|
48
|
-
const eqIndex = arg.indexOf('=');
|
|
49
|
-
let key: string;
|
|
50
|
-
let value: string;
|
|
51
|
-
|
|
52
|
-
if (eqIndex !== -1) {
|
|
53
|
-
key = arg.slice(2, eqIndex);
|
|
54
|
-
value = arg.slice(eqIndex + 1);
|
|
55
|
-
} else {
|
|
56
|
-
key = arg.slice(2);
|
|
57
|
-
if (key === 'prompt') {
|
|
58
|
-
// --prompt can be multiple
|
|
59
|
-
value = args[++i] || '';
|
|
60
|
-
parsed.prompts.push(value);
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
value = args[++i] || '';
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
switch (key) {
|
|
67
|
-
case 'input':
|
|
68
|
-
case 'content-name':
|
|
69
|
-
parsed.contentName = value;
|
|
70
|
-
break;
|
|
71
|
-
case 'project-dir':
|
|
72
|
-
parsed.projectDir = value;
|
|
73
|
-
break;
|
|
74
|
-
case 'env-file':
|
|
75
|
-
parsed.envFile = value;
|
|
76
|
-
break;
|
|
77
|
-
case 'api-url':
|
|
78
|
-
parsed.apiUrl = value;
|
|
79
|
-
break;
|
|
80
|
-
case 'api-key':
|
|
81
|
-
parsed.apiKey = value;
|
|
82
|
-
break;
|
|
83
|
-
case 'prompts-file':
|
|
84
|
-
parsed.promptsFile = value;
|
|
85
|
-
break;
|
|
86
|
-
case 'image-model':
|
|
87
|
-
parsed.imageModel = value;
|
|
88
|
-
break;
|
|
89
|
-
case 'aspect-ratio':
|
|
90
|
-
parsed.aspectRatio = value;
|
|
91
|
-
break;
|
|
92
|
-
case 'image-size':
|
|
93
|
-
case 'size':
|
|
94
|
-
parsed.imageSize = value;
|
|
95
|
-
break;
|
|
96
|
-
case 'quality':
|
|
97
|
-
parsed.quality = value;
|
|
98
|
-
break;
|
|
99
|
-
case 'style':
|
|
100
|
-
parsed.style = value;
|
|
101
|
-
break;
|
|
102
|
-
}
|
|
103
|
-
} else if (!parsed.contentName && !arg.startsWith('-')) {
|
|
104
|
-
// positional: content name
|
|
105
|
-
parsed.contentName = arg;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
return parsed;
|
|
110
|
-
}
|
|
7
|
+
import { UserInputError, createToolRunner } from '@laitszkin/tool-utils';
|
|
111
8
|
|
|
112
9
|
function sanitizeComponent(name: string, fallback: string): string {
|
|
113
10
|
return name
|
|
@@ -194,19 +91,19 @@ function parsePromptEntries(raw: unknown[]): Array<{ title: string; prompt: stri
|
|
|
194
91
|
const item = raw[i];
|
|
195
92
|
if (typeof item === 'string') {
|
|
196
93
|
const prompt = item.trim();
|
|
197
|
-
if (!prompt) throw new
|
|
94
|
+
if (!prompt) throw new UserInputError(`Empty prompt at index ${i}`);
|
|
198
95
|
items.push({ title: `scene-${i + 1}`, prompt });
|
|
199
96
|
} else if (item && typeof item === 'object') {
|
|
200
97
|
const obj = item as Record<string, unknown>;
|
|
201
98
|
const prompt = String(obj.prompt || '').trim();
|
|
202
99
|
const title = String(obj.title || `scene-${i + 1}`).trim() || `scene-${i + 1}`;
|
|
203
|
-
if (!prompt) throw new
|
|
100
|
+
if (!prompt) throw new UserInputError(`Empty prompt in object at index ${i}`);
|
|
204
101
|
items.push({ title, prompt });
|
|
205
102
|
} else {
|
|
206
|
-
throw new
|
|
103
|
+
throw new UserInputError(`Invalid item type at index ${i}: expected string or object`);
|
|
207
104
|
}
|
|
208
105
|
}
|
|
209
|
-
if (items.length === 0) throw new
|
|
106
|
+
if (items.length === 0) throw new UserInputError('No prompts found.');
|
|
210
107
|
return items;
|
|
211
108
|
}
|
|
212
109
|
|
|
@@ -220,7 +117,7 @@ function parsePromptsFile(filePath: string): Array<{ title: string; prompt: stri
|
|
|
220
117
|
if (raw && typeof raw === 'object') {
|
|
221
118
|
const scenes = raw.scenes;
|
|
222
119
|
if (!Array.isArray(scenes) || scenes.length === 0) {
|
|
223
|
-
throw new
|
|
120
|
+
throw new UserInputError('Object mode requires a top-level "scenes" array.');
|
|
224
121
|
}
|
|
225
122
|
|
|
226
123
|
const characters: Record<string, Record<string, string>> = {};
|
|
@@ -244,12 +141,12 @@ function parsePromptsFile(filePath: string): Array<{ title: string; prompt: stri
|
|
|
244
141
|
for (let si = 0; si < scenes.length; si++) {
|
|
245
142
|
const scene = scenes[si] as Record<string, unknown>;
|
|
246
143
|
if (!scene || typeof scene !== 'object') {
|
|
247
|
-
throw new
|
|
144
|
+
throw new UserInputError(`Invalid scene at index ${si}: expected object.`);
|
|
248
145
|
}
|
|
249
146
|
|
|
250
147
|
const title = String(scene.title || `scene-${si + 1}`).trim() || `scene-${si + 1}`;
|
|
251
148
|
const description = String(scene.description || '').trim();
|
|
252
|
-
if (!description) throw new
|
|
149
|
+
if (!description) throw new UserInputError(`Scene ${si}: 'description' is required.`);
|
|
253
150
|
|
|
254
151
|
let promptPayload: Record<string, unknown> = {
|
|
255
152
|
scene_title: title,
|
|
@@ -281,50 +178,67 @@ function parsePromptsFile(filePath: string): Array<{ title: string; prompt: stri
|
|
|
281
178
|
return items;
|
|
282
179
|
}
|
|
283
180
|
|
|
284
|
-
throw new
|
|
181
|
+
throw new UserInputError('Top-level JSON must be an array or an object.');
|
|
285
182
|
}
|
|
286
183
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
184
|
+
const schema = {
|
|
185
|
+
options: {
|
|
186
|
+
'input': { type: 'string' as const },
|
|
187
|
+
'content-name': { type: 'string' as const },
|
|
188
|
+
'project-dir': { type: 'string' as const, default: '.' },
|
|
189
|
+
'env-file': { type: 'string' as const },
|
|
190
|
+
'api-url': { type: 'string' as const },
|
|
191
|
+
'api-key': { type: 'string' as const },
|
|
192
|
+
'prompts-file': { type: 'string' as const },
|
|
193
|
+
'prompt': { type: 'string' as const, multiple: true },
|
|
194
|
+
'image-model': { type: 'string' as const },
|
|
195
|
+
'aspect-ratio': { type: 'string' as const },
|
|
196
|
+
'image-size': { type: 'string' as const },
|
|
197
|
+
'size': { type: 'string' as const },
|
|
198
|
+
'quality': { type: 'string' as const },
|
|
199
|
+
'style': { type: 'string' as const },
|
|
200
|
+
},
|
|
201
|
+
allowPositionals: true,
|
|
202
|
+
usage: 'apltk generate-storyboard-images --input <name> [options]',
|
|
203
|
+
description: 'Generate storyboard images from prompts via OpenAI-compatible API.',
|
|
204
|
+
handler: async (
|
|
205
|
+
values: Record<string, unknown>,
|
|
206
|
+
positionals: string[],
|
|
207
|
+
context: ToolContext,
|
|
208
|
+
): Promise<number> => {
|
|
209
|
+
const stdout = context.stdout || process.stdout;
|
|
210
|
+
const stderr = context.stderr || process.stderr;
|
|
211
|
+
|
|
212
|
+
const contentName = (values['input'] as string | undefined) ||
|
|
213
|
+
(values['content-name'] as string | undefined) ||
|
|
214
|
+
positionals[0] ||
|
|
215
|
+
null;
|
|
216
|
+
|
|
217
|
+
const projectDir = (values['project-dir'] as string) || '.';
|
|
218
|
+
const envFile = (values['env-file'] as string | undefined) ?? null;
|
|
219
|
+
const apiUrl = (values['api-url'] as string | undefined) ?? null;
|
|
220
|
+
const apiKey = (values['api-key'] as string | undefined) ?? null;
|
|
221
|
+
const promptsFile = (values['prompts-file'] as string | undefined) ?? null;
|
|
222
|
+
const prompts = (values['prompt'] as string[] | undefined) || [];
|
|
223
|
+
const imageModel = (values['image-model'] as string | undefined) ?? null;
|
|
224
|
+
const aspectRatio = (values['aspect-ratio'] as string | undefined) ?? null;
|
|
225
|
+
const imageSize = (values['image-size'] as string | undefined) || (values['size'] as string | undefined) || null;
|
|
226
|
+
const quality = (values['quality'] as string | undefined) ?? null;
|
|
227
|
+
const style = (values['style'] as string | undefined) ?? null;
|
|
228
|
+
|
|
229
|
+
if (!contentName) {
|
|
230
|
+
throw new UserInputError('--input or --content-name is required.');
|
|
316
231
|
}
|
|
317
232
|
|
|
318
|
-
const
|
|
319
|
-
const contentName = opts.contentName;
|
|
233
|
+
const resolvedProjectDir = path.resolve(projectDir);
|
|
320
234
|
|
|
321
235
|
// Resolve API config
|
|
322
236
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
323
237
|
const sourceRoot = context.sourceRoot || path.resolve(__dirname, '..', '..');
|
|
324
238
|
|
|
325
239
|
// Try loading env file
|
|
326
|
-
const envFilePath =
|
|
327
|
-
? path.resolve(
|
|
240
|
+
const envFilePath = envFile
|
|
241
|
+
? path.resolve(envFile)
|
|
328
242
|
: path.join(sourceRoot, 'openai-text-to-image-storyboard', '.env');
|
|
329
243
|
if (fs.existsSync(envFilePath)) {
|
|
330
244
|
const envContent = fs.readFileSync(envFilePath, 'utf-8');
|
|
@@ -346,43 +260,40 @@ Either --prompts-file or at least one --prompt is required.
|
|
|
346
260
|
}
|
|
347
261
|
}
|
|
348
262
|
|
|
349
|
-
const
|
|
350
|
-
const
|
|
351
|
-
const
|
|
352
|
-
const
|
|
353
|
-
const
|
|
354
|
-
const
|
|
355
|
-
const
|
|
356
|
-
|
|
357
|
-
if (!
|
|
358
|
-
|
|
359
|
-
return 1;
|
|
263
|
+
const resolvedApiUrl = apiUrl || process.env.OPENAI_API_URL || '';
|
|
264
|
+
const resolvedApiKey = apiKey || process.env.OPENAI_API_KEY || '';
|
|
265
|
+
const resolvedImageModel = imageModel || process.env.OPENAI_IMAGE_MODEL || 'gpt-image-1';
|
|
266
|
+
const resolvedAspectRatio = aspectRatio || process.env.OPENAI_IMAGE_RATIO || process.env.OPENAI_IMAGE_ASPECT_RATIO || null;
|
|
267
|
+
const resolvedImageSize = imageSize || process.env.OPENAI_IMAGE_SIZE || null;
|
|
268
|
+
const resolvedQuality = quality || process.env.OPENAI_IMAGE_QUALITY || null;
|
|
269
|
+
const resolvedStyle = style || process.env.OPENAI_IMAGE_STYLE || null;
|
|
270
|
+
|
|
271
|
+
if (!resolvedApiUrl) {
|
|
272
|
+
throw new UserInputError('Missing API URL. Set --api-url or OPENAI_API_URL.');
|
|
360
273
|
}
|
|
361
|
-
if (!
|
|
362
|
-
|
|
363
|
-
return 1;
|
|
274
|
+
if (!resolvedApiKey) {
|
|
275
|
+
throw new UserInputError('Missing API key. Set --api-key or OPENAI_API_KEY.');
|
|
364
276
|
}
|
|
365
277
|
|
|
366
278
|
// Build prompt items
|
|
367
279
|
let promptItems: Array<{ title: string; prompt: string }>;
|
|
368
|
-
if (
|
|
369
|
-
promptItems = parsePromptsFile(path.resolve(
|
|
370
|
-
} else if (
|
|
371
|
-
promptItems =
|
|
280
|
+
if (promptsFile) {
|
|
281
|
+
promptItems = parsePromptsFile(path.resolve(promptsFile));
|
|
282
|
+
} else if (prompts.length > 0) {
|
|
283
|
+
promptItems = prompts.map((p, i) => ({ title: `scene-${i + 1}`, prompt: p.trim() }));
|
|
372
284
|
} else {
|
|
373
|
-
|
|
374
|
-
return 1;
|
|
285
|
+
throw new UserInputError('Either --prompts-file or at least one --prompt is required.');
|
|
375
286
|
}
|
|
376
287
|
|
|
377
288
|
if (promptItems.length === 0) {
|
|
378
|
-
|
|
379
|
-
return 1;
|
|
289
|
+
throw new UserInputError('No prompts provided.');
|
|
380
290
|
}
|
|
381
291
|
|
|
382
|
-
const outputDir = path.join(
|
|
292
|
+
const outputDir = path.join(resolvedProjectDir, 'pictures', sanitizeComponent(contentName, 'untitled-content'));
|
|
383
293
|
fs.mkdirSync(outputDir, { recursive: true });
|
|
384
294
|
|
|
385
295
|
const records: Array<Record<string, unknown>> = [];
|
|
296
|
+
let failures = 0;
|
|
386
297
|
|
|
387
298
|
for (let i = 0; i < promptItems.length; i++) {
|
|
388
299
|
const item = promptItems[i];
|
|
@@ -390,19 +301,20 @@ Either --prompts-file or at least one --prompt is required.
|
|
|
390
301
|
const imagePath = uniquePath(path.join(outputDir, `${String(i + 1).padStart(2, '0')}_${titleSlug}.png`));
|
|
391
302
|
|
|
392
303
|
const payload: Record<string, unknown> = {
|
|
393
|
-
model:
|
|
304
|
+
model: resolvedImageModel,
|
|
394
305
|
prompt: item.prompt,
|
|
395
306
|
};
|
|
396
|
-
if (
|
|
397
|
-
if (
|
|
398
|
-
if (
|
|
399
|
-
if (
|
|
307
|
+
if (resolvedAspectRatio) payload.aspect_ratio = resolvedAspectRatio;
|
|
308
|
+
if (resolvedImageSize) payload.size = resolvedImageSize;
|
|
309
|
+
if (resolvedQuality) payload.quality = resolvedQuality;
|
|
310
|
+
if (resolvedStyle) payload.style = resolvedStyle;
|
|
400
311
|
|
|
401
|
-
const response = await postJson(
|
|
312
|
+
const response = await postJson(resolvedApiUrl, '/images/generations', resolvedApiKey, payload);
|
|
402
313
|
|
|
403
314
|
const data = response.data;
|
|
404
315
|
if (!Array.isArray(data) || data.length === 0) {
|
|
405
|
-
stderr.write(`
|
|
316
|
+
stderr.write(`No image data returned for prompt ${i + 1}.\n`);
|
|
317
|
+
failures++;
|
|
406
318
|
continue;
|
|
407
319
|
}
|
|
408
320
|
|
|
@@ -414,7 +326,8 @@ Either --prompts-file or at least one --prompt is required.
|
|
|
414
326
|
} else if (typeof first.url === 'string') {
|
|
415
327
|
imageBytes = await fetchBinary(first.url);
|
|
416
328
|
} else {
|
|
417
|
-
stderr.write(`
|
|
329
|
+
stderr.write(`Image payload missing b64_json/url for prompt ${i + 1}.\n`);
|
|
330
|
+
failures++;
|
|
418
331
|
continue;
|
|
419
332
|
}
|
|
420
333
|
|
|
@@ -436,29 +349,28 @@ Either --prompts-file or at least one --prompt is required.
|
|
|
436
349
|
// Write summary
|
|
437
350
|
const summary: Record<string, unknown> = {
|
|
438
351
|
content_name: contentName,
|
|
439
|
-
project_dir:
|
|
352
|
+
project_dir: resolvedProjectDir,
|
|
440
353
|
output_dir: outputDir,
|
|
441
|
-
image_model:
|
|
354
|
+
image_model: resolvedImageModel,
|
|
442
355
|
images: records,
|
|
443
356
|
};
|
|
444
|
-
if (
|
|
445
|
-
if (
|
|
357
|
+
if (resolvedAspectRatio) summary.aspect_ratio = resolvedAspectRatio;
|
|
358
|
+
if (resolvedImageSize) summary.image_size = resolvedImageSize;
|
|
446
359
|
|
|
447
360
|
const summaryPath = path.join(outputDir, 'storyboard.json');
|
|
448
361
|
fs.writeFileSync(summaryPath, JSON.stringify(summary, null, 2), 'utf-8');
|
|
449
362
|
stdout.write(`[OK] Wrote plan to ${summaryPath}\n`);
|
|
450
363
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
}
|
|
364
|
+
if (failures > 0) {
|
|
365
|
+
stderr.write(`Warning: ${failures} out of ${promptItems.length} prompts failed to generate images.\n`);
|
|
366
|
+
}
|
|
367
|
+
return failures > 0 ? 1 : 0;
|
|
368
|
+
},
|
|
369
|
+
};
|
|
458
370
|
|
|
459
371
|
export const tool: ToolDefinition = {
|
|
460
372
|
name: 'generate-storyboard-images',
|
|
461
373
|
category: 'media',
|
|
462
374
|
description: 'Generate storyboard images from prompts via OpenAI-compatible API.',
|
|
463
|
-
handler:
|
|
375
|
+
handler: createToolRunner(schema),
|
|
464
376
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@laitszkin/tool-generate-storyboard-images",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Apollo Toolkit
|
|
3
|
+
"version": "5.0.0",
|
|
4
|
+
"description": "Apollo Toolkit \u2014 CLI tool",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|
|
@@ -19,4 +19,4 @@
|
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@laitszkin/tool-registry": "*"
|
|
21
21
|
}
|
|
22
|
-
}
|
|
22
|
+
}
|
|
@@ -1,3 +1,16 @@
|
|
|
1
1
|
import type { ToolDefinition, ToolContext } from '@laitszkin/tool-registry';
|
|
2
|
+
/**
|
|
3
|
+
* openGitHubIssueHandler — Known carryover from createToolRunner migration.
|
|
4
|
+
*
|
|
5
|
+
* Reason for not using createToolRunner:
|
|
6
|
+
* - Positional subcommand architecture (create/draft) with 15+ tool-specific
|
|
7
|
+
* flags doesn't map cleanly to createToolRunner's options schema.
|
|
8
|
+
* - Error handling follows the AppError convention (UserInputError/SystemError
|
|
9
|
+
* throws) which is handled by the CLI boundary's formatAppError.
|
|
10
|
+
* - Argument parsing and help text are handled manually — 83-line parseArgs().
|
|
11
|
+
*
|
|
12
|
+
* See DESIGN.md §2.3 for the full architecture discussion.
|
|
13
|
+
* --help is now supported.
|
|
14
|
+
*/
|
|
2
15
|
export declare function openGitHubIssueHandler(argv: string[], context: ToolContext): Promise<number>;
|
|
3
16
|
export declare const tool: ToolDefinition;
|