classifyAttemptError handles an error from a stream attempt: checks for context cancellation, classifies the error, and returns either a per-iteration decision (retry the same model or skip to the next) or a non-nil retErr that the caller must return immediately. This consolidates the identical err
( ctx context.Context, err error, a *agent.Agent, modelEntry modelWithFallback, attempt int, hasFallbacks bool, primaryFailedWithNonRetryable *bool, )
| 186 | // This consolidates the identical error-handling block that used to |
| 187 | // follow both CreateChatCompletionStream and handleStream calls. |
| 188 | func (e *fallbackExecutor) classifyAttemptError( |
| 189 | ctx context.Context, |
| 190 | err error, |
| 191 | a *agent.Agent, |
| 192 | modelEntry modelWithFallback, |
| 193 | attempt int, |
| 194 | hasFallbacks bool, |
| 195 | primaryFailedWithNonRetryable *bool, |
| 196 | ) (decision retryDecision, retErr error) { |
| 197 | // Context cancellation is never retryable; bubble up the original |
| 198 | // error to preserve any cause/wrapping. The returned decision is |
| 199 | // irrelevant when retErr != nil — by contract the caller returns |
| 200 | // immediately — but use retryDecisionContinue rather than a magic |
| 201 | // zero so the value is at least typed and consistent. |
| 202 | if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) { |
| 203 | return retryDecisionContinue, err |
| 204 | } |
| 205 | decision = e.handleModelError(ctx, err, a, modelEntry, attempt, hasFallbacks, primaryFailedWithNonRetryable) |
| 206 | if decision == retryDecisionReturn { |
| 207 | return retryDecisionContinue, ctx.Err() |
| 208 | } |
| 209 | return decision, nil |
| 210 | } |
| 211 | |
| 212 | // execute attempts to create a stream and get a response using the primary model, |
| 213 | // falling back to configured fallback models if the primary fails. |
no test coverage detected