Repository navigation
Pause agents and warn in UI when Claude usage limit is reached - #301
zwanski-start wants to merge 2 commits into
Conversation
The 'Limit reached · resets 6pm (America/New_York)' message from Claude Code did not match any rate-limit pattern, so agents treated it as a normal session and immediately started new ones. - rate_limit_utils: match usage-limit messages, add parse_limit_reset() (time-of-day + timezone, legacy epoch format) and a [RATE_LIMIT] marker used to report limits to the orchestrator - agent: print a prominent warning; single-session (orchestrated) agents emit the marker and exit instead of being respawned; standalone runs sleep until the reset time Refs AutoForgeAI#19 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Orchestrator parses the agents' [RATE_LIMIT] marker and stops spawning coding and testing agents until the limit resets (exponential backoff when the reset time is unknown), then resumes automatically - OrchestratorTracker emits a sticky 'rate_limited' state with the resume time; Mission Control shows a warning banner and badge Closes AutoForgeAI#19 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🔍 QA report: ✅ PassedTester: Barbara (cubefarm agent, in a fresh session) · Round: 1 · Author: Ada The PR fixes issue #19. The exact 'Limit reached · resets 6pm (America/New_York)' message is now detected, feature and testing agents print a warning plus a [RATE_LIMIT] marker and exit instead of auto-continuing, and the orchestrator stops spawning coding and testing agents until the parsed reset time, then resumes on its own. The UI shows a red 'Usage limit - paused' badge and a warning banner with the resume time, which clear on resume. Lint and build pass; pytest failures and mypy errors match master. Minor non-blocking notes: Stop during a pause can wait up to 60s before reacting to SIGTERM, exception-path limits don't parse the reset time, and the banner is cramped on phone widths because of the existing Maestro card layout.
🧪 Commands run
No browser screenshots were taken in this round. Posted by cubefarm · merges automatically once GitHub's checks pass |
…tive (AutoForgeAI#19) Adaptations: the [RATE_LIMIT] marker counts only as a whole line (anchored regex, matched on the stripped line), so model text quoting it no longer pauses every agent; _note_rate_limit clamps retry_in to MAX_LIMIT_RESET_SECONDS (an oversized value raised OverflowError in the output reader thread). Kept my-features' _print_system_message/_print_result_message next to _print_limit_warning in agent.py. New tests: marker mid-line ignored, oversized retry_in clamped, tracker rate_limited state, feature agent emits the marker and stops. Integrates AutoForgeAI#301 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AeH26pcsqoxPb3CDs8g1VN
Closes #19
Problem
When a Claude subscription limit is hit, Claude Code returns text like
Limit reached · resets 6pm (America/New_York) · /upgrade to Max or turn on /extra-usage.None of the existing rate-limit patterns matched that, so the agent treated it as a normal session and printed "auto-continue in 3s". On top of that, agents spawned by the orchestrator (the UI path) run a single session and exit, so the orchestrator kept respawning new sessions that failed right away.
Changes
Detection (
rate_limit_utils.py)limit reached · resets …,You've hit your limit …,Claude (AI) usage limit reached. A bare "limit reached" still doesn't match (existing false-positive tests like "File size limit reached" still pass).parse_limit_reset()turnsresets 6pm (America/New_York)/reset at 6:30 PM (TZ)/ the legacyusage limit reached|<epoch>into seconds until reset. It uses local time when there's no timezone, rolls to tomorrow if the time has already passed, and caps the wait at 7 days. This replaces the inline regex inagent.py.format_rate_limit_marker()/parse_rate_limit_marker()produce and read a small[RATE_LIMIT] retry_in=<s|unknown>line that agents send to the orchestrator.Agent (
agent.py)Orchestrator (
parallel_orchestrator.py)Rate limit pause over - resuming agents.UI warning
OrchestratorTracker(server/websocket.py) turns the orchestrator's pause and resume lines into anorchestrator_updatewith staterate_limitedand arateLimitedUntilfield. The state stays set while other events (such as agents exiting) come in.Verification
ruff check .is clean.mypyreports no new errors in the changed files; the existing errors are in other files.pytest test_rate_limit_utils.py test_client.py test_dependency_resolver.py test_ws_security.py: 77 passed, including new tests for the usage-limit patterns, reset-time parsing (timezones, 12am/pm, rollover, epoch) and the marker round-trip.python test_security.pypasses.npm run lintshows 0 errors (only the existing warnings).npm run buildpasses.ParallelOrchestrator._read_outputon a real subprocess that prints the marker sets a pause of about 1234s, and a laterunknownmarker does not shorten it.OrchestratorTrackeremitsrate_limitedand keeps it throughFeature #3 completed, then clears it on resume.rate_limit_pauseupdate on the project WebSocket. The Mission Control badge and the warning banner both render.Assumptions / notes
MAX_FEATURE_RETRIES. The feature'sin_progressflag is cleared as usual and the feature is picked up again after the pause.🤖 Generated with Claude Code