From 9b80820b172007f3f6496250ee821d9ff9c2e19e Mon Sep 17 00:00:00 2001 From: hkfires <10558748+hkfires@users.noreply.github.com> Date: Fri, 26 Sep 2025 10:50:15 +0800 Subject: [PATCH] refactor(auth): Move candidate sorting to RoundRobinSelector --- sdk/cliproxy/auth/manager.go | 7 ------- sdk/cliproxy/auth/selector.go | 5 +++++ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/sdk/cliproxy/auth/manager.go b/sdk/cliproxy/auth/manager.go index 75c21991..edda9273 100644 --- a/sdk/cliproxy/auth/manager.go +++ b/sdk/cliproxy/auth/manager.go @@ -15,7 +15,6 @@ import ( "github.com/router-for-me/CLIProxyAPI/v6/internal/util" cliproxyexecutor "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/executor" log "github.com/sirupsen/logrus" - "sort" ) // ProviderExecutor defines the contract required by Manager to execute provider calls. @@ -797,12 +796,6 @@ func (m *Manager) pickNext(ctx context.Context, provider, model string, opts cli } candidates = append(candidates, auth.Clone()) } - // Ensure stable iteration order across requests to make round-robin deterministic. - // Go map iteration order is randomized; without sorting, the selector's index-based - // rotation may appear non-round-robin. - if len(candidates) > 1 { - sort.Slice(candidates, func(i, j int) bool { return candidates[i].ID < candidates[j].ID }) - } m.mu.RUnlock() if len(candidates) == 0 { return nil, nil, &Error{Code: "auth_not_found", Message: "no auth available"} diff --git a/sdk/cliproxy/auth/selector.go b/sdk/cliproxy/auth/selector.go index 71c33eb7..83d5d90d 100644 --- a/sdk/cliproxy/auth/selector.go +++ b/sdk/cliproxy/auth/selector.go @@ -2,6 +2,7 @@ package auth import ( "context" + "sort" "sync" "time" @@ -36,6 +37,10 @@ func (s *RoundRobinSelector) Pick(ctx context.Context, provider, model string, o if len(available) == 0 { return nil, &Error{Code: "auth_unavailable", Message: "no auth available"} } + // Make round-robin deterministic even if caller's candidate order is unstable. + if len(available) > 1 { + sort.Slice(available, func(i, j int) bool { return available[i].ID < available[j].ID }) + } key := provider + ":" + model s.mu.Lock() index := s.cursors[key]