mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 22:26:38 +03:00
Paul's design, three pieces: serve-question.mjs: the world decision presented as a themed page instead of a text prompt. The script serves an impeccable-styled option board (assigned direction leading with THE ROLL badge, dealt challengers as alternates carrying their QUALITY BAR cards, re-roll and steer built in), prints the URL, opens the browser, and blocks until the user chooses; the answer lands on stdout as ANSWER JSON, so the shell call itself is the wait and no harness machinery is needed. Local images are served by the ephemeral server; nothing leaves the machine. generate-image.mjs + context.mjs IMAGE_GEN_AVAILABLE: when an OpenAI key is in the environment, context reports that image generation works even without a harness-native tool (gpt-image-2, billed to the user's key, stated before first use; Google skipped by decision). Harness-native tools always win when present. new-work.md: visualize-before-build is now the default whenever any image generation exists, not a codex.md special case; the attended presentation prefers the visual decision page and falls back to the structured question tool. Evals keep the unattended path untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
55 lines
2.1 KiB
JavaScript
55 lines
2.1 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* API image generation fallback: renders a mock or world board with the
|
|
* user's own OpenAI key when the harness has no native image generation.
|
|
*
|
|
* context.mjs reports availability (it checks OPENAI_API_KEY); harness-native
|
|
* generation always wins when present. This uses gpt-image-2 and spends the
|
|
* user's API credit (roughly $0.05-0.25 per image at default quality), so the
|
|
* skill states that before the first call in a session.
|
|
*
|
|
* node generate-image.mjs --prompt "..." --out mock.png [--size 1536x1024] [--quality medium]
|
|
* node generate-image.mjs --prompt-file prompt.txt --out mock.png
|
|
*/
|
|
import fs from 'node:fs';
|
|
|
|
function arg(name, fallback = null) {
|
|
const i = process.argv.indexOf(`--${name}`);
|
|
if (i === -1) return fallback;
|
|
const v = process.argv[i + 1];
|
|
return v && !v.startsWith('--') ? v : fallback;
|
|
}
|
|
|
|
const key = process.env.OPENAI_API_KEY;
|
|
if (!key) {
|
|
console.error('generate-image: OPENAI_API_KEY is not set; use the harness-native image tool instead.');
|
|
process.exit(1);
|
|
}
|
|
const promptFile = arg('prompt-file');
|
|
const prompt = promptFile ? fs.readFileSync(promptFile, 'utf8') : arg('prompt');
|
|
const out = arg('out');
|
|
if (!prompt || !out) {
|
|
console.error('generate-image: --prompt (or --prompt-file) and --out are required.');
|
|
process.exit(1);
|
|
}
|
|
const size = arg('size', '1536x1024');
|
|
const quality = arg('quality', 'medium');
|
|
|
|
const response = await fetch('https://api.openai.com/v1/images/generations', {
|
|
method: 'POST',
|
|
headers: { Authorization: `Bearer ${key}`, 'content-type': 'application/json' },
|
|
body: JSON.stringify({ model: 'gpt-image-2', prompt, size, quality, n: 1 }),
|
|
});
|
|
if (!response.ok) {
|
|
console.error(`generate-image: API error ${response.status}: ${(await response.text()).slice(0, 300)}`);
|
|
process.exit(1);
|
|
}
|
|
const json = await response.json();
|
|
const b64 = json?.data?.[0]?.b64_json;
|
|
if (!b64) {
|
|
console.error('generate-image: no image in response');
|
|
process.exit(1);
|
|
}
|
|
fs.writeFileSync(out, Buffer.from(b64, 'base64'));
|
|
console.log(`IMAGE: ${out} (${size}, ${quality}, gpt-image-2, billed to your OpenAI key)`);
|