Skip to content

feat(desktop): retry overloaded turns and wait for the internet - #3491

Merged
LHagfoss merged 3 commits into
mainfrom
feat/3388-3389-auto-retry-overload-restart
Nov 11, 2026
Merged

LHagfoss merged 3 commits into
mainfrom
feat/3388-3389-auto-retry-overload-restart

Conversation

@LHagfoss

Copy link
Copy Markdown
Owner

What

Two more causes for a turn the user does not have to restart by hand, in the
same code path as the usage-limit wait (state/limitResume.ts).

  • Provider overload (feat(desktop): retry a turn after a provider overload and continue after a restart mid-turn #3388): a turn that stopped on HTTP 529/503 or
    overloaded_error is tried again after a doubling backoff — 30 s, 1 m, 2 m,
    4 m — with up to a quarter of it added at random so an account's threads do
    not wake together. Never a fifth time, and a credit or spend limit is never
    retried. The classifier, the backoff and the attempt cap are pure
    (overloadStop, overloadDelay, nextWait).
  • A restart mid-turn (feat(desktop): retry a turn after a provider overload and continue after a restart mid-turn #3388): already shipped — store.ts resumeInterrupted
    sends "Continue where you left off" to the threads a quit, an update or an
    engine restart cut off. It is reused as it stands; nothing was duplicated.
  • No network (feat(desktop): resume threads that failed because the internet dropped #3389): a turn that failed because the machine had no network
    (Claude Code "Can't reach the API server", Codex's dropped stream, Pi's
    "fetch failed"; classified in state/turnError.ts networkFailure, never one
    a provider answered) waits for the connection instead of dying. While any
    thread waits the app asks the webview every 5 s, and at once on online or a
    wake, then sends "Please continue." once the connection has stayed up for
    5 s, 30 s, 2 m and then 5 m on later retries, so flaky Wi-Fi cannot burn them.
    After 6 h it gives up and says so. The schedule is pure (state/internetWait.ts).

Both waits show the same row over the composer, now with Send now and
Cancel, in the existing type and colours. Both hold queued messages, both
end when the thread moves to another harness or account or when the user sends
anything, and both survive an app restart. Settings › General's row is renamed
"Continue threads on their own", since it now covers all three causes.

Changelog

A turn a provider overload stopped retries itself with a doubling backoff, and a turn the network killed waits for the connection instead of failing for good.

Testing

  • bun run check in apps/desktop: typecheck, lint, 2068 tests, build — all pass.
  • New unit tests: the overload classifier per harness message (and that credit
    and spend limits never retry), backoff and jitter bounds, the 4-attempt cap, a
    stop that changes kind, the network classifier (positive per harness, negative
    for 401/429/503/529, a limit and a spend limit), the stable-period escalation
    (5 s, 30 s, 2 m, 5 m) and the 6 h cap.
  • New store tests: an overload error creates the wait with a ~30 s backoff and
    sends the resume turn when it falls due; a credit limit creates no wait; a
    network error waits, and sends "Please continue." only once the connection has
    been up 5 s.
  • No app, browser or mock window was launched.

Closes #3388
Closes #3389

A turn a provider overload stopped is tried again after 30 s, 1 m, 2 m and
4 m, with up to a quarter added at random so an account's threads do not wake
together, and never a fifth time; a credit or spend limit is never retried. A
turn whose machine had no network waits for it instead of dying: the app asks
the webview every 5 s, and at once on online or a wake, and sends "Please
continue." once the connection has stayed up for 5 s, 30 s, 2 m and then 5 m on
later retries, giving up after 6 h. Both show the queue's row over the composer
with Send now and Cancel, and both survive a restart.

The classifier for a lost network and the two schedules are pure modules with
their own tests, and store tests send the resume turn once a wait is due.
@github-actions github-actions Bot added the feature New feature or request label Nov 11, 2026
@LHagfoss
LHagfoss merged commit 2e4ccc2 into main Nov 11, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or request

Projects

None yet

1 participant