Summary
The agent's main loop (WebAgent.runMainLoop / execute) has no overarching watchdog: a single hung operation in any iteration blocks the entire task forever, with no upper bound on wall-clock time.
Individual hangs are being fixed point-by-point (aria-tree frame.evaluate in #511; see also the unbounded waitForLoadState and streamText stream issues), but a defense-in-depth backstop would catch the next unbounded operation we haven't found yet.
Suggested approach
Add a per-iteration (and/or per-task) timeout via an AbortController + timer that aborts the iteration and surfaces a clear, recoverable error (or moves to the next step) instead of hanging indefinitely. Make the bound configurable, generous by default.
Why it matters
Turns "indefinite freeze" failure modes into bounded, observable errors — better UX and far easier to diagnose than a silent hang.
Context
Identified while diagnosing #511. This is the defense-in-depth complement to the targeted per-operation timeouts.
Summary
The agent's main loop (
WebAgent.runMainLoop/execute) has no overarching watchdog: a single hung operation in any iteration blocks the entire task forever, with no upper bound on wall-clock time.Individual hangs are being fixed point-by-point (aria-tree
frame.evaluatein #511; see also the unboundedwaitForLoadStateandstreamTextstream issues), but a defense-in-depth backstop would catch the next unbounded operation we haven't found yet.Suggested approach
Add a per-iteration (and/or per-task) timeout via an
AbortController+ timer that aborts the iteration and surfaces a clear, recoverable error (or moves to the next step) instead of hanging indefinitely. Make the bound configurable, generous by default.Why it matters
Turns "indefinite freeze" failure modes into bounded, observable errors — better UX and far easier to diagnose than a silent hang.
Context
Identified while diagnosing #511. This is the defense-in-depth complement to the targeted per-operation timeouts.