= $maxAttempts || !$this->shouldRetry($exception, $retryStatuses, $retryErrorCodes)) { throw $exception; } usleep($this->delayMs($attempt, $baseDelayMs, $maxDelayMs) * 1000); } } } private function shouldRetry(Throwable $exception, array $retryStatuses, array $retryErrorCodes): bool { if (!$exception instanceof LLMRequestException) { return false; } if ($exception->statusCode() !== null && in_array($exception->statusCode(), $retryStatuses, true)) { return true; } return $exception->providerCode() !== null && in_array($exception->providerCode(), $retryErrorCodes, true); } private function delayMs(int $attempt, int $baseDelayMs, int $maxDelayMs): int { $delay = min($maxDelayMs, $baseDelayMs * (2 ** max(0, $attempt - 1))); $jitter = $delay > 0 ? random_int(0, min(500, $delay)) : 0; return $delay + $jitter; } }