(ctx context.Context, providers []string, req cliproxyexecutor.Request, opts cliproxyexecutor.Options, maxRetryCredentials int)
| 2468 | } |
| 2469 | |
| 2470 | func (m *Manager) executeMixedOnce(ctx context.Context, providers []string, req cliproxyexecutor.Request, opts cliproxyexecutor.Options, maxRetryCredentials int) (cliproxyexecutor.Response, error) { |
| 2471 | if len(providers) == 0 { |
| 2472 | return cliproxyexecutor.Response{}, &Error{Code: "provider_not_found", Message: "no provider supplied"} |
| 2473 | } |
| 2474 | routeModel := req.Model |
| 2475 | opts = ensureRequestedModelMetadata(opts, routeModel) |
| 2476 | homeMode := m.HomeEnabled() |
| 2477 | homeAuthCount := 1 |
| 2478 | tried := make(map[string]struct{}) |
| 2479 | attempted := make(map[string]struct{}) |
| 2480 | var lastErr error |
| 2481 | for { |
| 2482 | if !homeMode && maxRetryCredentials > 0 && len(attempted) >= maxRetryCredentials { |
| 2483 | if lastErr != nil { |
| 2484 | return cliproxyexecutor.Response{}, lastErr |
| 2485 | } |
| 2486 | return cliproxyexecutor.Response{}, &Error{Code: "auth_not_found", Message: "no auth available"} |
| 2487 | } |
| 2488 | pickOpts := opts |
| 2489 | if homeMode { |
| 2490 | pickOpts = withHomeAuthCount(opts, homeAuthCount) |
| 2491 | } |
| 2492 | auth, executor, provider, errPick := m.pickNextMixed(ctx, providers, routeModel, pickOpts, tried) |
| 2493 | if errPick != nil { |
| 2494 | if shouldReturnLastErrorOnPickFailure(homeMode, lastErr, errPick) { |
| 2495 | return cliproxyexecutor.Response{}, lastErr |
| 2496 | } |
| 2497 | return cliproxyexecutor.Response{}, errPick |
| 2498 | } |
| 2499 | |
| 2500 | entry := logEntryWithRequestID(ctx) |
| 2501 | debugLogAuthSelection(entry, auth, provider, req.Model) |
| 2502 | publishSelectedAuthMetadata(opts.Metadata, auth.ID) |
| 2503 | |
| 2504 | tried[auth.ID] = struct{}{} |
| 2505 | execCtx := ctx |
| 2506 | if rt := m.roundTripperFor(auth); rt != nil { |
| 2507 | execCtx = context.WithValue(execCtx, roundTripperContextKey{}, rt) |
| 2508 | execCtx = context.WithValue(execCtx, "cliproxy.roundtripper", rt) |
| 2509 | } |
| 2510 | execCtx = contextWithRequestedModelAlias(execCtx, opts, routeModel) |
| 2511 | |
| 2512 | models, pooled, aliasResult := m.preparedExecutionModelsWithAlias(auth, routeModel) |
| 2513 | if len(models) == 0 { |
| 2514 | continue |
| 2515 | } |
| 2516 | attempted[auth.ID] = struct{}{} |
| 2517 | var errPrepare error |
| 2518 | auth, errPrepare = m.prepareRequestAuth(execCtx, executor, auth) |
| 2519 | if errPrepare != nil { |
| 2520 | result := Result{AuthID: auth.ID, Provider: provider, Model: routeModel, Success: false, Error: &Error{Message: errPrepare.Error()}} |
| 2521 | if se, ok := errors.AsType[cliproxyexecutor.StatusError](errPrepare); ok && se != nil { |
| 2522 | result.Error.HTTPStatus = se.StatusCode() |
| 2523 | } |
| 2524 | m.MarkResult(execCtx, result) |
| 2525 | lastErr = errPrepare |
| 2526 | continue |
| 2527 | } |
no test coverage detected