| 122 | }, timeout * 1000); |
| 123 | |
| 124 | async function handleFeedback(req: Request): Promise<Response> { |
| 125 | let body: any; |
| 126 | try { |
| 127 | body = await req.json(); |
| 128 | } catch { |
| 129 | return Response.json({ error: "Invalid JSON" }, { status: 400 }); |
| 130 | } |
| 131 | |
| 132 | // Validate expected shape |
| 133 | if (typeof body !== "object" || body === null) { |
| 134 | return Response.json({ error: "Expected JSON object" }, { status: 400 }); |
| 135 | } |
| 136 | |
| 137 | const isSubmit = body.regenerated === false; |
| 138 | const isRegenerate = body.regenerated === true; |
| 139 | const action = isSubmit |
| 140 | ? "submitted" |
| 141 | : body.regenerateAction || "regenerate"; |
| 142 | |
| 143 | console.error(`SERVE_FEEDBACK_RECEIVED: type=${action}`); |
| 144 | |
| 145 | // Print feedback JSON to stdout (for foreground mode) |
| 146 | console.log(JSON.stringify(body)); |
| 147 | |
| 148 | // ALWAYS write feedback to disk so the agent can poll for it |
| 149 | // (agent typically backgrounds $D serve, can't read stdout) |
| 150 | const feedbackDir = path.dirname(html); |
| 151 | const feedbackFile = isSubmit ? "feedback.json" : "feedback-pending.json"; |
| 152 | const feedbackPath = path.join(feedbackDir, feedbackFile); |
| 153 | fs.writeFileSync(feedbackPath, JSON.stringify(body, null, 2)); |
| 154 | |
| 155 | if (isSubmit) { |
| 156 | state = "done"; |
| 157 | if (timeoutTimer) clearTimeout(timeoutTimer); |
| 158 | |
| 159 | // Give the response time to send before exiting |
| 160 | setTimeout(() => { |
| 161 | server.stop(); |
| 162 | process.exit(0); |
| 163 | }, 100); |
| 164 | |
| 165 | return Response.json({ received: true, action: "submitted" }); |
| 166 | } |
| 167 | |
| 168 | if (isRegenerate) { |
| 169 | state = "regenerating"; |
| 170 | // Reset timeout for regeneration (agent needs time to generate new variants) |
| 171 | if (timeoutTimer) clearTimeout(timeoutTimer); |
| 172 | timeoutTimer = setTimeout(() => { |
| 173 | console.error(`SERVE_TIMEOUT: after=${timeout}s (during regeneration)`); |
| 174 | server.stop(); |
| 175 | process.exit(1); |
| 176 | }, timeout * 1000); |
| 177 | |
| 178 | return Response.json({ received: true, action: "regenerate" }); |
| 179 | } |
| 180 | |
| 181 | return Response.json({ received: true, action: "unknown" }); |