(auths []*Auth, provider, model string, now time.Time)
| 217 | } |
| 218 | |
| 219 | func getAvailableAuths(auths []*Auth, provider, model string, now time.Time) ([]*Auth, error) { |
| 220 | if len(auths) == 0 { |
| 221 | return nil, &Error{Code: "auth_not_found", Message: "no auth candidates"} |
| 222 | } |
| 223 | |
| 224 | availableByPriority, cooldownCount, earliest := collectAvailableByPriority(auths, model, now) |
| 225 | if len(availableByPriority) == 0 { |
| 226 | if cooldownCount == len(auths) && !earliest.IsZero() { |
| 227 | providerForError := provider |
| 228 | if providerForError == "mixed" { |
| 229 | providerForError = "" |
| 230 | } |
| 231 | resetIn := earliest.Sub(now) |
| 232 | if resetIn < 0 { |
| 233 | resetIn = 0 |
| 234 | } |
| 235 | return nil, newModelCooldownError(model, providerForError, resetIn) |
| 236 | } |
| 237 | return nil, &Error{Code: "auth_unavailable", Message: "no auth available"} |
| 238 | } |
| 239 | |
| 240 | bestPriority := 0 |
| 241 | found := false |
| 242 | for priority := range availableByPriority { |
| 243 | if !found || priority > bestPriority { |
| 244 | bestPriority = priority |
| 245 | found = true |
| 246 | } |
| 247 | } |
| 248 | |
| 249 | available := availableByPriority[bestPriority] |
| 250 | if len(available) > 1 { |
| 251 | sort.Slice(available, func(i, j int) bool { return available[i].ID < available[j].ID }) |
| 252 | } |
| 253 | return available, nil |
| 254 | } |
| 255 | |
| 256 | // Pick selects the next available auth for the provider in a round-robin manner. |
| 257 | func (s *RoundRobinSelector) Pick(ctx context.Context, provider, model string, opts cliproxyexecutor.Options, auths []*Auth) (*Auth, error) { |
no test coverage detected