import process from "node:process"; import { DEFAULT_IMAGE_DIR, DEFAULT_MODEL, buildBaseUrl, buildDefaultImagePath, ensureFilesExist, extractGeneratedBytes, loadAmbientEnv, printJson, readPromptInput, resolveOutput, saveImage, savePrompt, postJson, slugify, } from "./shared.js"; function printHelp() { console.log(`Usage: node scripts/generate.js --prompt "A cute baby sea otter" --image out/otter.png Options: --prompt Prompt text --promptfile Load prompt from a file --prompt-output Save the final prompt to a specific file --image Output image path (default: ${DEFAULT_IMAGE_DIR}/-.png) --model Model override (default: ${DEFAULT_MODEL}) --size Output size --n Number of images --quality auto | high | medium | low --background transparent | opaque | auto --moderation low | auto --output-format png | jpeg | webp --output-compression <0-100> Compression for jpeg/webp --json Print structured output -h, --help Show help`); } function parseCli(argv) { const cfg = { prompt: null, promptFile: null, promptOutput: null, imagePath: null, model: null, size: null, n: null, quality: null, background: null, moderation: null, outputFormat: null, outputCompression: null, json: false, help: false, }; for (let i = 0; i < argv.length; i += 1) { const arg = argv[i]; if (arg === "-h" || arg === "--help") { cfg.help = true; continue; } if (arg === "--json") { cfg.json = true; continue; } if (arg === "--prompt") { cfg.prompt = argv[++i] || null; if (!cfg.prompt) throw new Error("Missing value for --prompt"); continue; } if (arg === "--promptfile") { cfg.promptFile = argv[++i] || null; if (!cfg.promptFile) throw new Error("Missing value for --promptfile"); continue; } if (arg === "--prompt-output") { cfg.promptOutput = argv[++i] || null; if (!cfg.promptOutput) throw new Error("Missing value for --prompt-output"); continue; } if (arg === "--image") { cfg.imagePath = argv[++i] || null; if (!cfg.imagePath) throw new Error("Missing value for --image"); continue; } if (arg === "--model") { cfg.model = argv[++i] || null; if (!cfg.model) throw new Error("Missing value for --model"); continue; } if (arg === "--size") { cfg.size = argv[++i] || null; if (!cfg.size) throw new Error("Missing value for --size"); continue; } if (arg === "--n") { cfg.n = argv[++i] || null; if (!cfg.n) throw new Error("Missing value for --n"); continue; } if (arg === "--quality") { cfg.quality = argv[++i] || null; if (!cfg.quality) throw new Error("Missing value for --quality"); continue; } if (arg === "--background") { cfg.background = argv[++i] || null; if (!cfg.background) throw new Error("Missing value for --background"); continue; } if (arg === "--moderation") { cfg.moderation = argv[++i] || null; if (!cfg.moderation) throw new Error("Missing value for --moderation"); continue; } if (arg === "--output-format") { cfg.outputFormat = argv[++i] || null; if (!cfg.outputFormat) throw new Error("Missing value for --output-format"); continue; } if (arg === "--output-compression") { cfg.outputCompression = argv[++i] || null; if (!cfg.outputCompression) throw new Error("Missing value for --output-compression"); continue; } throw new Error(`Unknown option: ${arg}`); } return cfg; } function buildPayload(cfg, prompt) { const payload = { prompt, model: cfg.model || process.env.OPENAI_IMAGE_MODEL || DEFAULT_MODEL, }; if (cfg.size) payload.size = cfg.size; if (cfg.n) payload.n = Number(cfg.n); if (cfg.quality) payload.quality = cfg.quality; if (cfg.background) payload.background = cfg.background; if (cfg.moderation) payload.moderation = cfg.moderation; if (cfg.outputFormat) payload.output_format = cfg.outputFormat; if (cfg.outputCompression) payload.output_compression = Number(cfg.outputCompression); return payload; } function buildRequestUrl() { return `${buildBaseUrl()}/images/generations`; } async function run() { const cfg = parseCli(process.argv.slice(2)); if (cfg.help) { printHelp(); return; } await loadAmbientEnv(); const prompt = await readPromptInput(cfg.prompt, cfg.promptFile); const nameHint = slugify(prompt.split(/\s+/).slice(0, 8).join(" "), "generated-image"); const promptPath = await savePrompt(prompt, cfg.promptOutput, nameHint); const outputPath = resolveOutput(cfg.imagePath, buildDefaultImagePath("generate", nameHint)); await ensureFilesExist([], "input"); const payload = buildPayload(cfg, prompt); const url = buildRequestUrl(); const json = await postJson(url, payload); const bytes = await extractGeneratedBytes(json); await saveImage(outputPath, bytes); if (cfg.json) { printJson({ savedImage: outputPath, savedPrompt: promptPath, model: payload.model, requestUrl: url, apiResponse: json, }); return; } console.log(outputPath); } run().catch((error) => { const message = error instanceof Error ? error.message : String(error); console.error(message); process.exit(1); });