cmux NEXT: Settings > Retry After Errors sets the automatic retry loop (on/off, seconds between tries, tries per error)

Merged
TE
4d ago
+1261-15

Leo-ask: ask-082cdbe456

Leo, passing on Lawrence's notes (2026-10-28): "leo make sure font size everywhere (like text input area) is customizable", "should have retry button + configurable timer loop retry", "needs more left padding".

This PR builds the one part that was still missing: the configurable timer loop retry. Where the other parts stand:

  • Font size in the text input area: done in #26523 (merged 2026-10-28), which makes the composer follow Settings > Agent Chat > Chat Font Size (agentPane.display.font.size).
  • Retry button: done in 9e836df4 (2026-10-29). Continue or Retry leads the rate-limit and capacity error card.
  • Left padding on the prompt rail: handled in its own small PR.

What changes

acpmux already retries a turn that a rate limit, a capacity error or a lost connection ended (#25232, #27924), waiting 10 s, 1 min, 5 min and 20 min. Until now, only acpmux's own config.json (autoResumeDelaysMs) could change that loop. Three new settings under Settings > General > Retry After Errors now set it:

keydefaultmeaning
agents.autoRetry.enabledtrueOff: no automatic retry. The card's Retry still works.
agents.autoRetry.intervalSeconds0 (0–3600)0 keeps today's growing waits. N waits N seconds before every try.
agents.autoRetry.attempts4 (1–12)Tries per failed turn.
  • acpmux reads them from the settings file at each retry (hub/auto_resume/settings.rs, through user_settings, as Sub-sessions does), so a change applies to the next failed turn. autoResumeDelaysMs in config.json, when set, still comes first, so the dev slot's [] keeps working. The defaults give exactly today's waits, and a test pins the section JSON's defaults and ranges to the daemon's constants.
  • Every reader of the loop goes through effective_delays: the turn retry, a restored wait, a chain of restarts, held agent messages and subagent retries.
  • The schema source is schemas/settings/source/agent-retry.json, generated into Swift by gen-settings-sources.py. Through the schema, the settings appear in Settings, the palette, cmux settings and MCP. MCP refuses all three as user-only (SettingsSchema+AgentPolicy), like sessions.resumeAgents. settings-schema.json and the settings reference are regenerated by base autofix.
  • Strings: 7 new keys in the CmuxNextSettings catalog, translated into all 21 locales.
  • The phone parity row is in cmux-next-ios/verify/parity-mac.md: the loop runs in acpmux, so phone chats get it, but the keys can only be edited on the Mac.

Timers: no new timer. The existing per-attempt sleep reads its wait from these settings, and Stop or close still ends it (auto_resume.rs).

risk: normal (a settings row plus where the daemon reads its existing waits).

Changelog

  • Added: Settings > Retry After Errors: turn automatic retries after a rate limit or lost connection on or off, and set the seconds between tries and how many run.

Observed / Not run

  • Ran: gen-settings-sources.py (writes the generated Swift), rustfmt, the pre-push gate. The settings.rs unit tests and the acpmux auto_resume tests run through cmux-ci; their result is posted below.
  • Not run yet: a tagged-build check of the palette row, cmux settings get|set agents.autoRetry.intervalSeconds and the MCP refusal.

Agent session: agent session

šŸ¤– Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Makes acpmux's automatic retry loop after rate limits, capacity errors, or lost connections configurable from Settings > Retry After Errors, instead of only via the daemon's config.json.

  • Adds three agents.autoRetry.* keys: enabled (on/off), intervalSeconds (0 keeps today's growing waits), and attempts (1–12 per failed turn), read from the settings file at each retry.
  • autoResumeDelaysMs in config.json still takes precedence when set, so the dev slot's [] (retry off) keeps working.
  • Disabling auto-retry still leaves the error card's Retry button working; changes apply to the next failed turn, and Stop or closing the chat still ends the loop.
  • All three keys are user-only in MCP, appearing in Settings, the palette, and cmux settings; the phone gets the retry behavior but has no editor for the keys.
  • The schema source in schemas/settings/source/agent-retry.json generates the Swift descriptors, with settings strings translated into all 21 locales.

Migration

  • No action needed; defaults reproduce exactly today's waits (10 s, 1 min, 5 min, then 20 min, 4 attempts).