fix(headless): use long idle timeout for auto/next/discuss/plan

The 15s IDLE_TIMEOUT_MS was killing auto-mode prematurely. Symptom: sf
headless auto would dispatch a task, the LLM would make 1-2 tool calls,
pause to reason about the next step, exceed 15s of "no events", and
headless would declare "Status: complete" — exiting at ~35s with the task
barely started (123 events but only 2 tool calls).

The 120s NEW_MILESTONE_IDLE_TIMEOUT_MS already exists for the same reason
("LLM may pause between tool calls e.g. after mkdir, before writing
files"). The same applies to auto/next/discuss/plan — all multi-turn
commands where the LLM thinks longer between actions, especially on
non-trivial tasks. isMultiTurnCommand was already defined for related
logic; this just wires it into the idle-timeout decision.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Mikael Hugo 2026-04-29 15:13:43 +02:00
parent 6e342a8875
commit c239ad6c9d

View file

@ -753,11 +753,17 @@ async function runHeadlessOnce(
resolveCompletion = resolve;
});
// Idle timeout — fallback completion detection
// Idle timeout — fallback completion detection.
// Multi-turn commands (auto, next, discuss, plan) involve LLM thinking
// pauses between tool calls that can exceed 15s. Use the longer
// new-milestone timeout for those too — without this, headless killed
// auto-mode after 2 tool calls when the LLM paused to reason about the
// next step (~35s total run, exit "complete" while task barely started).
let idleTimer: ReturnType<typeof setTimeout> | null = null;
const effectiveIdleTimeout = isNewMilestone
? NEW_MILESTONE_IDLE_TIMEOUT_MS
: IDLE_TIMEOUT_MS;
const effectiveIdleTimeout =
isNewMilestone || isMultiTurnCommand
? NEW_MILESTONE_IDLE_TIMEOUT_MS
: IDLE_TIMEOUT_MS;
function resetIdleTimer(): void {
if (idleTimer) clearTimeout(idleTimer);