diff --git a/internal/runtime/executor/antigravity_executor.go b/internal/runtime/executor/antigravity_executor.go index 9ade4fbb..38dc0b84 100644 --- a/internal/runtime/executor/antigravity_executor.go +++ b/internal/runtime/executor/antigravity_executor.go @@ -155,7 +155,13 @@ func (e *AntigravityExecutor) Execute(ctx context.Context, auth *cliproxyauth.Au log.Debugf("antigravity executor: rate limited on base url %s, retrying with fallback base url: %s", baseURL, baseURLs[idx+1]) continue } - err = statusErr{code: httpResp.StatusCode, msg: string(bodyBytes)} + sErr := statusErr{code: httpResp.StatusCode, msg: string(bodyBytes)} + if httpResp.StatusCode == http.StatusTooManyRequests { + if retryAfter, parseErr := parseRetryDelay(bodyBytes); parseErr == nil && retryAfter != nil { + sErr.retryAfter = retryAfter + } + } + err = sErr return resp, err } @@ -169,7 +175,13 @@ func (e *AntigravityExecutor) Execute(ctx context.Context, auth *cliproxyauth.Au switch { case lastStatus != 0: - err = statusErr{code: lastStatus, msg: string(lastBody)} + sErr := statusErr{code: lastStatus, msg: string(lastBody)} + if lastStatus == http.StatusTooManyRequests { + if retryAfter, parseErr := parseRetryDelay(lastBody); parseErr == nil && retryAfter != nil { + sErr.retryAfter = retryAfter + } + } + err = sErr case lastErr != nil: err = lastErr default: @@ -259,7 +271,13 @@ func (e *AntigravityExecutor) executeClaudeNonStream(ctx context.Context, auth * log.Debugf("antigravity executor: rate limited on base url %s, retrying with fallback base url: %s", baseURL, baseURLs[idx+1]) continue } - err = statusErr{code: httpResp.StatusCode, msg: string(bodyBytes)} + sErr := statusErr{code: httpResp.StatusCode, msg: string(bodyBytes)} + if httpResp.StatusCode == http.StatusTooManyRequests { + if retryAfter, parseErr := parseRetryDelay(bodyBytes); parseErr == nil && retryAfter != nil { + sErr.retryAfter = retryAfter + } + } + err = sErr return resp, err } @@ -324,7 +342,13 @@ func (e *AntigravityExecutor) executeClaudeNonStream(ctx context.Context, auth * switch { case lastStatus != 0: - err = statusErr{code: lastStatus, msg: string(lastBody)} + sErr := statusErr{code: lastStatus, msg: string(lastBody)} + if lastStatus == http.StatusTooManyRequests { + if retryAfter, parseErr := parseRetryDelay(lastBody); parseErr == nil && retryAfter != nil { + sErr.retryAfter = retryAfter + } + } + err = sErr case lastErr != nil: err = lastErr default: @@ -599,7 +623,13 @@ func (e *AntigravityExecutor) ExecuteStream(ctx context.Context, auth *cliproxya log.Debugf("antigravity executor: rate limited on base url %s, retrying with fallback base url: %s", baseURL, baseURLs[idx+1]) continue } - err = statusErr{code: httpResp.StatusCode, msg: string(bodyBytes)} + sErr := statusErr{code: httpResp.StatusCode, msg: string(bodyBytes)} + if httpResp.StatusCode == http.StatusTooManyRequests { + if retryAfter, parseErr := parseRetryDelay(bodyBytes); parseErr == nil && retryAfter != nil { + sErr.retryAfter = retryAfter + } + } + err = sErr return nil, err } @@ -654,7 +684,13 @@ func (e *AntigravityExecutor) ExecuteStream(ctx context.Context, auth *cliproxya switch { case lastStatus != 0: - err = statusErr{code: lastStatus, msg: string(lastBody)} + sErr := statusErr{code: lastStatus, msg: string(lastBody)} + if lastStatus == http.StatusTooManyRequests { + if retryAfter, parseErr := parseRetryDelay(lastBody); parseErr == nil && retryAfter != nil { + sErr.retryAfter = retryAfter + } + } + err = sErr case lastErr != nil: err = lastErr default: @@ -795,12 +831,24 @@ func (e *AntigravityExecutor) CountTokens(ctx context.Context, auth *cliproxyaut log.Debugf("antigravity executor: rate limited on base url %s, retrying with fallback base url: %s", baseURL, baseURLs[idx+1]) continue } - return cliproxyexecutor.Response{}, statusErr{code: httpResp.StatusCode, msg: string(bodyBytes)} + sErr := statusErr{code: httpResp.StatusCode, msg: string(bodyBytes)} + if httpResp.StatusCode == http.StatusTooManyRequests { + if retryAfter, parseErr := parseRetryDelay(bodyBytes); parseErr == nil && retryAfter != nil { + sErr.retryAfter = retryAfter + } + } + return cliproxyexecutor.Response{}, sErr } switch { case lastStatus != 0: - return cliproxyexecutor.Response{}, statusErr{code: lastStatus, msg: string(lastBody)} + sErr := statusErr{code: lastStatus, msg: string(lastBody)} + if lastStatus == http.StatusTooManyRequests { + if retryAfter, parseErr := parseRetryDelay(lastBody); parseErr == nil && retryAfter != nil { + sErr.retryAfter = retryAfter + } + } + return cliproxyexecutor.Response{}, sErr case lastErr != nil: return cliproxyexecutor.Response{}, lastErr default: @@ -963,7 +1011,13 @@ func (e *AntigravityExecutor) refreshToken(ctx context.Context, auth *cliproxyau } if httpResp.StatusCode < http.StatusOK || httpResp.StatusCode >= http.StatusMultipleChoices { - return auth, statusErr{code: httpResp.StatusCode, msg: string(bodyBytes)} + sErr := statusErr{code: httpResp.StatusCode, msg: string(bodyBytes)} + if httpResp.StatusCode == http.StatusTooManyRequests { + if retryAfter, parseErr := parseRetryDelay(bodyBytes); parseErr == nil && retryAfter != nil { + sErr.retryAfter = retryAfter + } + } + return auth, sErr } var tokenResp struct {