diff options
Diffstat (limited to 'internal/executor')
| -rw-r--r-- | internal/executor/classifier.go | 3 | ||||
| -rw-r--r-- | internal/executor/claude.go | 4 | ||||
| -rw-r--r-- | internal/executor/executor.go | 20 | ||||
| -rw-r--r-- | internal/executor/ratelimit.go | 4 |
4 files changed, 22 insertions, 9 deletions
diff --git a/internal/executor/classifier.go b/internal/executor/classifier.go index 123f92d..efd2acb 100644 --- a/internal/executor/classifier.go +++ b/internal/executor/classifier.go @@ -43,7 +43,8 @@ Gemini: - gemini-2.5-pro (most powerful Gemini, larger context) Selection Criteria: -- Agent: You MUST prefer an agent that is NOT rate limited. If an agent is rate limited, do NOT select it unless all available agents are rate limited. +- Agent: CRITICAL: You MUST select an agent where "Rate Limited: false". DO NOT select an agent where "Rate Limited: true" if any other agent is available and NOT rate limited. + Check the "System Status" section below. If it says "- Agent claude: ... Rate Limited: true", you MUST NOT select claude. Use gemini instead. - Model: Select based on task complexity. Use powerful models (opus, pro, pro-preview) for complex reasoning/coding, flash-lite/flash/haiku for simple tasks. Task: diff --git a/internal/executor/claude.go b/internal/executor/claude.go index ad1c4e3..9184333 100644 --- a/internal/executor/claude.go +++ b/internal/executor/claude.go @@ -433,7 +433,9 @@ func parseStream(r io.Reader, w io.Writer, logger *slog.Logger) (float64, error) if info, ok := msg["rate_limit_info"].(map[string]interface{}); ok { status, _ := info["status"].(string) if status == "rejected" { - streamErr = fmt.Errorf("claude rate limit reached: %v", msg) + streamErr = fmt.Errorf("claude rate limit reached (rejected): %v", msg) + // Immediately break since we can't continue anyway + break } } case "assistant": diff --git a/internal/executor/executor.go b/internal/executor/executor.go index 1c9e667..4bb1f2c 100644 --- a/internal/executor/executor.go +++ b/internal/executor/executor.go @@ -234,14 +234,18 @@ func (p *Pool) executeResume(ctx context.Context, t *task.Task, exec *storage.Ex exec.EndTime = time.Now().UTC() if err != nil { - if isRateLimitError(err) { + if isRateLimitError(err) || isQuotaExhausted(err) { p.mu.Lock() retryAfter := parseRetryAfter(err.Error()) if retryAfter == 0 { - retryAfter = 1 * time.Minute + if isQuotaExhausted(err) { + retryAfter = 5 * time.Hour + } else { + retryAfter = 1 * time.Minute + } } p.rateLimited[agentType] = time.Now().Add(retryAfter) - p.logger.Info("agent rate limited", "agent", agentType, "retryAfter", retryAfter) + p.logger.Info("agent rate limited", "agent", agentType, "retryAfter", retryAfter, "quotaExhausted", isQuotaExhausted(err)) p.mu.Unlock() } @@ -445,14 +449,18 @@ func (p *Pool) execute(ctx context.Context, t *task.Task) { exec.EndTime = time.Now().UTC() if err != nil { - if isRateLimitError(err) { + if isRateLimitError(err) || isQuotaExhausted(err) { p.mu.Lock() retryAfter := parseRetryAfter(err.Error()) if retryAfter == 0 { - retryAfter = 1 * time.Minute + if isQuotaExhausted(err) { + retryAfter = 5 * time.Hour + } else { + retryAfter = 1 * time.Minute + } } p.rateLimited[agentType] = time.Now().Add(retryAfter) - p.logger.Info("agent rate limited", "agent", agentType, "retryAfter", retryAfter) + p.logger.Info("agent rate limited", "agent", agentType, "retryAfter", retryAfter, "quotaExhausted", isQuotaExhausted(err)) p.mu.Unlock() } diff --git a/internal/executor/ratelimit.go b/internal/executor/ratelimit.go index deaad18..aa9df99 100644 --- a/internal/executor/ratelimit.go +++ b/internal/executor/ratelimit.go @@ -34,7 +34,9 @@ func isQuotaExhausted(err error) bool { } msg := strings.ToLower(err.Error()) return strings.Contains(msg, "hit your limit") || - strings.Contains(msg, "you've hit your limit") + strings.Contains(msg, "you've hit your limit") || + strings.Contains(msg, "you have hit your limit") || + strings.Contains(msg, "rate limit reached (rejected)") } // parseRetryAfter extracts a Retry-After duration from an error message. |
