on main help sign in
fix: improve retry
fa82290Carlos Alexandro Becker
internal/llm/provider/anthropic.go+12−1
@@ -509,7 +509,18 @@ func (a *anthropicClient) shouldRetry(attempts int, err error) (bool, int64, err
509 isOverloaded := strings.Contains(apiErr.Error(), "overloaded") || strings.Contains(apiErr.Error(), "rate limit exceeded")
509 isOverloaded := strings.Contains(apiErr.Error(), "overloaded") || strings.Contains(apiErr.Error(), "rate limit exceeded")
510 // 529 (unofficial): The service is overloaded
510 // 529 (unofficial): The service is overloaded
511 if apiErr.StatusCode != http.StatusTooManyRequests && apiErr.StatusCode != 529 && !isOverloaded {
511 if apiErr.StatusCode != http.StatusTooManyRequests && apiErr.StatusCode != 529 && !isOverloaded {
512− return false, 0, err
512+ prev := a.providerOptions.apiKey
513+ // in case the key comes from a script, we try to re-evaluate it.
514+ a.providerOptions.apiKey, err = config.Get().Resolve(a.providerOptions.config.APIKey)
515+ if err != nil {
516+ return false, 0, fmt.Errorf("failed to resolve API key: %w", err)
517+ }
518+ // if it didn't change, do not retry.
519+ if prev == a.providerOptions.apiKey {
520+ return false, 0, err
521+ }
522+ a.client = createAnthropicClient(a.providerOptions, a.tp)
523+ return true, 0, nil
513 }
524 }
514
525
515 retryMs := 0
526 retryMs := 0
internal/llm/provider/gemini.go+15−1
@@ -436,7 +436,21 @@ func (g *geminiClient) shouldRetry(attempts int, err error) (bool, int64, error)
436
436
437 // Check for token expiration (401 Unauthorized)
437 // Check for token expiration (401 Unauthorized)
438 if contains(errMsg, "unauthorized", "invalid api key", "api key expired") {
438 if contains(errMsg, "unauthorized", "invalid api key", "api key expired") {
439+ prev := g.providerOptions.apiKey
440+ // in case the key comes from a script, we try to re-evaluate it.
441+ g.providerOptions.apiKey, err = config.Get().Resolve(g.providerOptions.config.APIKey)
442+ if err != nil {
443+ return false, 0, fmt.Errorf("failed to resolve API key: %w", err)
444+ }
445+ // if it didn't change, do not retry.
446+ if prev == g.providerOptions.apiKey {
439− return false, 0, err
447+ return false, 0, err
448+ }
449+ g.client, err = createGeminiClient(g.providerOptions)
450+ if err != nil {
451+ return false, 0, fmt.Errorf("failed to create Gemini client after API key refresh: %w", err)
452+ }
453+ return true, 0, nil
440 }
454 }
441
455
442 // Check for common rate limit error messages
456 // Check for common rate limit error messages
internal/llm/provider/openai.go+12−1
@@ -515,7 +515,18 @@ func (o *openaiClient) shouldRetry(attempts int, err error) (bool, int64, error)
515 if errors.As(err, &apiErr) {
515 if errors.As(err, &apiErr) {
516 // Check for token expiration (401 Unauthorized)
516 // Check for token expiration (401 Unauthorized)
517 if apiErr.StatusCode == http.StatusUnauthorized {
517 if apiErr.StatusCode == http.StatusUnauthorized {
518+ prev := o.providerOptions.apiKey
519+ // in case the key comes from a script, we try to re-evaluate it.
520+ o.providerOptions.apiKey, err = config.Get().Resolve(o.providerOptions.config.APIKey)
521+ if err != nil {
522+ return false, 0, fmt.Errorf("failed to resolve API key: %w", err)
523+ }
524+ // if it didn't change, do not retry.
525+ if prev == o.providerOptions.apiKey {
518− return false, 0, err
526+ return false, 0, err
527+ }
528+ o.client = createOpenAIClient(o.providerOptions)
529+ return true, 0, nil
519 }
530 }
520
531
521 if apiErr.StatusCode != http.StatusTooManyRequests && apiErr.StatusCode != http.StatusInternalServerError {
532 if apiErr.StatusCode != http.StatusTooManyRequests && apiErr.StatusCode != http.StatusInternalServerError {