#!/usr/bin/env node // Prints the image-edit request for a food photo upgrade. It calls no API. // Usage: node scripts/build-input.mjs --image https://... --dish "cheeseburger with fries on a white plate" \ // [--style dark-moody|menu-white|bright-cafe] [--orientation landscape|portrait|square] [--keep "extra things that must not change"] import { readFileSync } from 'node:fs' import { dirname, join } from 'node:path' import { fileURLToPath } from 'node:url' function parseArgs(argv, known) { const out = {} for (let i = 0; i < argv.length; i += 1) { const k = argv[i] if (!k.startsWith('--')) fail(`Unexpected argument '${k}'.`) const name = k.slice(2) if (!known.includes(name)) fail(`Unknown flag --${name}. Known: ${known.map((x) => '--' + x).join(', ')}`) const v = argv[i + 1] if (v === undefined || v.startsWith('--')) fail(`Flag --${name} needs a value.`) out[name] = v i += 1 } return out } function fail(message) { console.error(message); process.exit(1) } function checkImage(value) { if (!/^https:\/\//.test(value) && !/^data:image\//.test(value)) fail('--image must be a public https URL or an image data URI.') } const root = join(dirname(fileURLToPath(import.meta.url)), '..') const o = parseArgs(process.argv.slice(2), ['image', 'dish', 'style', 'orientation', 'keep']) if (!o.image || !o.dish) fail('Usage: node scripts/build-input.mjs --image https://... --dish "what is on the plate and the camera angle, e.g. side-on cheeseburger with fries on a white plate" [--style dark-moody|menu-white|bright-cafe] [--orientation landscape|portrait|square (match the input photo)] [--keep "things that must not change"]') checkImage(o.image) const settings = JSON.parse(readFileSync(join(root, 'assets/generation-input.json'), 'utf8')) const styleName = o.style ?? 'dark-moody' const style = settings.styles[styleName] if (!style) fail('--style must be one of: ' + Object.keys(settings.styles).join(', ')) const orientation = o.orientation ?? 'landscape' const size = settings.sizes[orientation] if (!size) fail('--orientation must be landscape, portrait or square') const template = readFileSync(join(root, 'assets/prompt-template.md'), 'utf8').trim() const prompt = template .replace('{{dish}}', () => o.dish) .replace('{{keep}}', () => o.keep ? ' Also keep exactly the same: ' + o.keep + '.' : '') .replace('{{style}}', () => style) console.log(JSON.stringify({ model: settings.model, input: { ...settings.input, image_size: size, image_urls: [o.image], prompt }, }, null, 2))