diff --git a/browse/src/cli.ts b/browse/src/cli.ts index bca3ca0fd..9732053c7 100644 --- a/browse/src/cli.ts +++ b/browse/src/cli.ts @@ -21,7 +21,32 @@ import { spawnTerminalAgent } from './terminal-agent-control'; const config = resolveConfig(); const IS_WINDOWS = process.platform === 'win32'; -const MAX_START_WAIT = IS_WINDOWS ? 15000 : (process.env.CI ? 30000 : 8000); // Node+Chromium takes longer on Windows + +/** + * Startup health-probe budget (ms) for a freshly spawned server. The daemon is + * detached + unref'd, so it keeps booting regardless of how long the CLI is + * willing to poll — this constant only bounds how long `startServer` waits + * before reporting failure. + * + * Overridable via `BROWSE_START_TIMEOUT` (ms) for hosts where even the platform + * ceiling isn't enough — e.g. Windows under heavy load (#1846), where the 15s + * budget can still elapse before a busy box finishes booting Node+Chromium. + * Mirrors the `BROWSE_*` tunable convention used throughout server.ts + * (BROWSE_PORT, BROWSE_IDLE_TIMEOUT, ...). A non-positive or unparseable value + * falls back to the platform default. Pure + exported for tests. + */ +export function resolveStartTimeout(env: NodeJS.ProcessEnv = process.env): number { + // Cold Chromium launch measured ~5.7s at load avg 10 on a dev machine running + // many servers; at load 12+ it exceeds the old 8s budget, so the CLI gave up + // while the (detached) daemon was still booting → "Server failed to start + // within 8s". 15s matches the Windows budget and gives real headroom; the poll + // loop returns the instant the daemon is healthy, so this only costs time in a + // genuine-failure case. + const platformDefault = IS_WINDOWS ? 15000 : (env.CI ? 30000 : 15000); // Node+Chromium takes longer on Windows + const override = parseInt(env.BROWSE_START_TIMEOUT || '', 10); + return Number.isFinite(override) && override > 0 ? override : platformDefault; +} +const MAX_START_WAIT = resolveStartTimeout(); export function resolveServerScript( env: Record = process.env, @@ -358,6 +383,17 @@ async function startServer(extraEnv?: Record): Promise