Files
pikasTech-HWLAB/docs/reference
Lyon f7731d1421 fix(web): v0.2 remove all total-timeout / hard cap on Code Agent turn (HWLAB #795 final) (#798)
Follow-up to PR #797: drop every wall-clock or attempt-count ceiling from
`state/runner-trace.ts` so the Web UI's Code Agent inactivity-timeout
contract is total-cap-free. The previous PR kept a
`max(totalTimeoutMs * 4, totalTimeoutMs + 60s)` outer-loop safety net
plus a `TRACE_HARD_CAP_ATTEMPTS = 120` poll-count cap, which would
re-introduce the same regression class that #795 was filed against: a
long-running operation that keeps emitting trace events could still be
killed by the outer ceiling even with an active `activityRef`. The
"Code Agent Timeout Model" section of
`docs/reference/spec-v02-hwlab-cloud-web.md` now pins the contract:

- The sole abort signal is per-poll `fetchJson` inactivity-timeout,
  driven by `activityRef`.
- The outer `waitForAgentResult` / `pollRunnerTrace` loops are
  `for (;;)`. They only exit when the upstream returns a terminal
  status, the request fails with a non-5xx, or the inactivity window
  fires inside `fetchJson`.
- The per-poll `getAgentChatResult` call passes the full
  `totalTimeoutMs`; the inactivity window is **not** shrunk by
  wall-clock elapsed time.
- `TRACE_HARD_CAP_ATTEMPTS` and the 4x / +60s outer cap are deleted.
- Runaway protection is the caller's responsibility: Web users have
  cancel / steer / close-tab; CLI has `--timeout-ms`. The browser does
  not introduce an implicit cap.

Changes

- `web/hwlab-cloud-web/src/state/runner-trace.ts`:
  - Drop `const hardCapMs = Math.max(totalTimeoutMs * 4, totalTimeoutMs + 60_000)`
    and the `if (Date.now() - startedAt >= hardCapMs) break;` checks in
    both `waitForAgentResult` and `pollRunnerTrace`.
  - Replace `while (Date.now() - startedAt < hardCapMs)` with
    `for (;;)`. Drop the now-unused `startedAt` locals and the
    `let attempt = 0; attempt > TRACE_HARD_CAP_ATTEMPTS` guard.
  - Pass `totalTimeoutMs` directly to `api.getAgentChatResult` instead
    of `totalTimeoutMs - (Date.now() - startedAt)` so the per-poll
    inactivity window is stable.
  - Delete `const TRACE_HARD_CAP_ATTEMPTS = 120;` (no longer referenced).

- `web/hwlab-cloud-web/scripts/fetchJson-inactivity.test.ts`:
  - Replace the "1.5s cadence 6.5s" case with a stricter "200ms cadence
    10s" case: `timeoutMs=3000` inactivity window, continuous 200ms
    activity for 10s, then stop. Assert `elapsed >= 10_000` and that
    the abort is the inactivity-timeout error. This pins the
    `elapsed >= 10000` invariant in the spec.

- `docs/reference/spec-v02-hwlab-cloud-web.md`:
  - Strengthen the existing bullet in "在系统中的职责划分" to
    explicitly forbid total-timeout, hard cap, `codeAgentTimeoutMs * N`,
    poll-count cap, and wall-clock-shrunk per-poll windows.
  - Add a dedicated "Code Agent Timeout Model" section after "## 内部架构"
    that distils the contract, lists the three invariants, and records
    the history of #775 / #777 / #791 / #795 leading to the final state.

Verification

- `bun run scripts/tsc-check.ts` → strict React TSX, 0 explicit any
- `bun run check` → 5 pass / 0 fail (3 inactivity + 2 dist-contract)
- `bun run build` → 9 dist files verified fresh; `app.js` 241802 → 238460 B
  (delta reflects the deleted hardCap / TRACE_HARD_CAP_ATTEMPTS code)
- New 200ms-cadence 10s inactivity test runs for ~13s and asserts the
  request lives the full window — proving the outer cap is gone.

Refs: HWLAB #795 (final), #777, #791, #775

Co-authored-by: Codex <codex@local>
2026-06-04 09:36:29 +08:00
..
2026-05-28 20:57:22 +08:00