(options: GenerateOptions)
| 96 | * Generate a single mockup from a brief. |
| 97 | */ |
| 98 | export async function generate(options: GenerateOptions): Promise<GenerateResult> { |
| 99 | const apiKey = requireApiKey(); |
| 100 | |
| 101 | // Parse the brief |
| 102 | const prompt = options.briefFile |
| 103 | ? parseBrief(options.briefFile, true) |
| 104 | : parseBrief(options.brief!, false); |
| 105 | |
| 106 | const size = options.size || "1536x1024"; |
| 107 | const quality = options.quality || "high"; |
| 108 | const maxRetries = options.retry ?? 0; |
| 109 | |
| 110 | let lastResult: GenerateResult | null = null; |
| 111 | |
| 112 | for (let attempt = 0; attempt <= maxRetries; attempt++) { |
| 113 | if (attempt > 0) { |
| 114 | console.error(`Retry ${attempt}/${maxRetries}...`); |
| 115 | } |
| 116 | |
| 117 | // Generate the image |
| 118 | const startTime = Date.now(); |
| 119 | const { responseId, imageData } = await callImageGeneration(apiKey, prompt, size, quality); |
| 120 | const elapsed = ((Date.now() - startTime) / 1000).toFixed(1); |
| 121 | |
| 122 | // Write to disk |
| 123 | const outputDir = path.dirname(options.output); |
| 124 | fs.mkdirSync(outputDir, { recursive: true }); |
| 125 | const imageBuffer = Buffer.from(imageData, "base64"); |
| 126 | fs.writeFileSync(options.output, imageBuffer); |
| 127 | |
| 128 | // Create session |
| 129 | const session = createSession(responseId, prompt, options.output); |
| 130 | |
| 131 | console.error(`Generated (${elapsed}s, ${(imageBuffer.length / 1024).toFixed(0)}KB) → ${options.output}`); |
| 132 | |
| 133 | lastResult = { |
| 134 | outputPath: options.output, |
| 135 | sessionFile: sessionPath(session.id), |
| 136 | responseId, |
| 137 | }; |
| 138 | |
| 139 | // Quality check if requested |
| 140 | if (options.check) { |
| 141 | const checkResult = await checkMockup(options.output, prompt); |
| 142 | lastResult.checkResult = checkResult; |
| 143 | |
| 144 | if (checkResult.pass) { |
| 145 | console.error(`Quality check: PASS`); |
| 146 | break; |
| 147 | } else { |
| 148 | console.error(`Quality check: FAIL — ${checkResult.issues}`); |
| 149 | if (attempt < maxRetries) { |
| 150 | console.error("Will retry..."); |
| 151 | } |
| 152 | } |
| 153 | } else { |
| 154 | break; |
| 155 | } |
no test coverage detected