From 7c0889674d16e607f1522dc833104626ab494cb4 Mon Sep 17 00:00:00 2001 From: ionianFury <09_wintry.carhops@icloud.com> Date: Thu, 21 May 2026 15:36:26 +0200 Subject: [PATCH] design: bump per-image OpenAI timeout from 120s to 240s MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hardcoded 120-second abort in design/src/{generate,iterate,variants,evolve}.ts fires too often against the gpt-image-1 image_generation tool at the default quality:"high" + size:"1536x1024". A real session today had all 3 `variants` calls timeout at exactly 120s while the OpenAI API was actively processing — direct curl with max-time 240s returned 200 in 33s. Bumping each call to 240s gives ~2x headroom over typical worst-case (60-180s observed) while staying under user patience. Quality default unchanged — high is what produces the polished mockups users expect; the timeout was the cliff, not the quality. Touches 5 sites: - design/src/generate.ts:40 - design/src/iterate.ts:85, 133 - design/src/variants.ts:61 - design/src/evolve.ts:55 All carry an inline comment explaining the picked value. A future follow-up could promote this to an env var (GSTACK_DESIGN_TIMEOUT_MS) or a shared constant in design/src/constants.ts, but I'm keeping this PR small. Verified: bun install + bun build --compile design/src/cli.ts succeeds. --- design/src/evolve.ts | 3 ++- design/src/generate.ts | 5 ++++- design/src/iterate.ts | 6 ++++-- design/src/variants.ts | 3 ++- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/design/src/evolve.ts b/design/src/evolve.ts index c88ae6c660..f23b759445 100644 --- a/design/src/evolve.ts +++ b/design/src/evolve.ts @@ -52,7 +52,8 @@ export async function evolve(options: EvolveOptions): Promise { ].join("\n"); const controller = new AbortController(); - const timeout = setTimeout(() => controller.abort(), 120_000); + // 240s — matches generate.ts; see comment there for rationale. + const timeout = setTimeout(() => controller.abort(), 240_000); try { const response = await fetch("https://api.openai.com/v1/responses", { diff --git a/design/src/generate.ts b/design/src/generate.ts index 383c51aeeb..fa18cc5220 100644 --- a/design/src/generate.ts +++ b/design/src/generate.ts @@ -37,7 +37,10 @@ async function callImageGeneration( quality: string, ): Promise<{ responseId: string; imageData: string }> { const controller = new AbortController(); - const timeout = setTimeout(() => controller.abort(), 120_000); + // 240s: gpt-image-1 at quality:"high" size:"1536x1024" routinely takes + // 60-180s and can spike past 120s under provider load (observed in + // production). 240s gives ~2x headroom while staying under user patience. + const timeout = setTimeout(() => controller.abort(), 240_000); try { const response = await fetch("https://api.openai.com/v1/responses", { diff --git a/design/src/iterate.ts b/design/src/iterate.ts index c85eacee9b..bca3f7c752 100644 --- a/design/src/iterate.ts +++ b/design/src/iterate.ts @@ -82,7 +82,8 @@ async function callWithThreading( feedback: string, ): Promise<{ responseId: string; imageData: string }> { const controller = new AbortController(); - const timeout = setTimeout(() => controller.abort(), 120_000); + // 240s — matches generate.ts; see comment there for rationale. + const timeout = setTimeout(() => controller.abort(), 240_000); try { const response = await fetch("https://api.openai.com/v1/responses", { @@ -130,7 +131,8 @@ async function callFresh( prompt: string, ): Promise<{ responseId: string; imageData: string }> { const controller = new AbortController(); - const timeout = setTimeout(() => controller.abort(), 120_000); + // 240s — matches generate.ts; see comment there for rationale. + const timeout = setTimeout(() => controller.abort(), 240_000); try { const response = await fetch("https://api.openai.com/v1/responses", { diff --git a/design/src/variants.ts b/design/src/variants.ts index d52eb22829..c5c7df27e4 100644 --- a/design/src/variants.ts +++ b/design/src/variants.ts @@ -58,7 +58,8 @@ export async function generateVariant( skipLeadingDelay = false; const controller = new AbortController(); - const timeout = setTimeout(() => controller.abort(), 120_000); + // 240s — matches generate.ts; see comment there for rationale. + const timeout = setTimeout(() => controller.abort(), 240_000); try { const response = await fetchFn("https://api.openai.com/v1/responses", {