refactor(auth): remove unused Refresh methods from authenticators

- Deleted `Refresh` implementations in Codex, Claude, Gemini, Qwen, and Gemini-web authenticators.
- Updated the `Authenticator` interface to exclude `Refresh` for cleaner design.
- Revised `Manager` and related components to handle refresh logic improvements.
- Simplified token refresh behavior and eliminated redundant code paths.
This commit is contained in:
Luis Pater
2025-09-22 21:11:53 +08:00
parent 837ae1b1b3
commit 053134f66e
10 changed files with 27 additions and 156 deletions

View File

@@ -15,6 +15,7 @@ import (
cliproxyauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth"
cliproxyexecutor "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/executor"
sdktranslator "github.com/router-for-me/CLIProxyAPI/v6/sdk/translator"
log "github.com/sirupsen/logrus"
"github.com/tidwall/sjson"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
@@ -255,7 +256,7 @@ func (e *GeminiCLIExecutor) ExecuteStream(ctx context.Context, auth *cliproxyaut
}
func (e *GeminiCLIExecutor) Refresh(ctx context.Context, auth *cliproxyauth.Auth) (*cliproxyauth.Auth, error) {
// log.Debugf("gemini cli executor: refresh called")
log.Debugf("gemini cli executor: refresh called")
_ = ctx
return auth, nil
}

View File

@@ -143,36 +143,3 @@ func (a *ClaudeAuthenticator) Login(ctx context.Context, cfg *config.Config, opt
Metadata: metadata,
}, nil
}
func (a *ClaudeAuthenticator) Refresh(ctx context.Context, cfg *config.Config, record *TokenRecord) (*TokenRecord, error) {
if record == nil || record.Storage == nil {
return nil, fmt.Errorf("cliproxy auth: empty token record for claude refresh")
}
if cfg == nil {
return nil, fmt.Errorf("cliproxy auth: configuration is required")
}
if ctx == nil {
ctx = context.Background()
}
storage, ok := record.Storage.(*claude.ClaudeTokenStorage)
if !ok {
return nil, fmt.Errorf("cliproxy auth: unexpected token storage type for claude refresh")
}
// Refresh via auth service directly (no legacy client)
svc := claude.NewClaudeAuth(cfg)
td, err := svc.RefreshTokensWithRetry(ctx, storage.RefreshToken, 3)
if err != nil {
return nil, err
}
svc.UpdateTokenStorage(storage, td)
result := &TokenRecord{
Provider: a.Provider(),
FileName: record.FileName,
Storage: storage,
Metadata: record.Metadata,
}
return result, nil
}

View File

@@ -142,35 +142,3 @@ func (a *CodexAuthenticator) Login(ctx context.Context, cfg *config.Config, opts
Metadata: metadata,
}, nil
}
func (a *CodexAuthenticator) Refresh(ctx context.Context, cfg *config.Config, record *TokenRecord) (*TokenRecord, error) {
if record == nil || record.Storage == nil {
return nil, fmt.Errorf("cliproxy auth: empty token record for codex refresh")
}
if cfg == nil {
return nil, fmt.Errorf("cliproxy auth: configuration is required")
}
if ctx == nil {
ctx = context.Background()
}
storage, ok := record.Storage.(*codex.CodexTokenStorage)
if !ok {
return nil, fmt.Errorf("cliproxy auth: unexpected token storage type for codex refresh")
}
svc := codex.NewCodexAuth(cfg)
td, err := svc.RefreshTokensWithRetry(ctx, storage.RefreshToken, 3)
if err != nil {
return nil, err
}
svc.UpdateTokenStorage(storage, td)
result := &TokenRecord{
Provider: a.Provider(),
FileName: record.FileName,
Storage: storage,
Metadata: record.Metadata,
}
return result, nil
}

View File

@@ -23,13 +23,6 @@ func (a *GeminiWebAuthenticator) Login(ctx context.Context, cfg *config.Config,
return nil, fmt.Errorf("gemini-web authenticator does not support scripted login; use CLI --gemini-web-auth")
}
func (a *GeminiWebAuthenticator) Refresh(ctx context.Context, cfg *config.Config, record *TokenRecord) (*TokenRecord, error) {
_ = ctx
_ = cfg
_ = record
return nil, ErrRefreshNotSupported
}
func (a *GeminiWebAuthenticator) RefreshLead() *time.Duration {
d := 9 * time.Minute
return &d

View File

@@ -66,7 +66,3 @@ func (a *GeminiAuthenticator) Login(ctx context.Context, cfg *config.Config, opt
Metadata: metadata,
}, nil
}
func (a *GeminiAuthenticator) Refresh(ctx context.Context, cfg *config.Config, record *TokenRecord) (*TokenRecord, error) {
return nil, ErrRefreshNotSupported
}

View File

@@ -37,6 +37,5 @@ type TokenStore interface {
type Authenticator interface {
Provider() string
Login(ctx context.Context, cfg *config.Config, opts *LoginOptions) (*TokenRecord, error)
Refresh(ctx context.Context, cfg *config.Config, record *TokenRecord) (*TokenRecord, error)
RefreshLead() *time.Duration
}

View File

@@ -67,29 +67,3 @@ func (m *Manager) Login(ctx context.Context, provider string, cfg *config.Config
}
return record, savedPath, nil
}
// Refresh delegates to the provider-specific refresh implementation and persists the result.
func (m *Manager) Refresh(ctx context.Context, provider string, cfg *config.Config, record *TokenRecord) (*TokenRecord, string, error) {
auth, ok := m.authenticators[provider]
if !ok {
return nil, "", fmt.Errorf("cliproxy auth: authenticator %s not registered", provider)
}
updated, err := auth.Refresh(ctx, cfg, record)
if err != nil {
return nil, "", err
}
if updated == nil {
updated = record
}
if m.store == nil {
return updated, "", nil
}
savedPath, err := m.store.Save(ctx, cfg, updated)
if err != nil {
return updated, "", err
}
return updated, savedPath, nil
}

View File

@@ -110,38 +110,3 @@ func (a *QwenAuthenticator) Login(ctx context.Context, cfg *config.Config, opts
Metadata: metadata,
}, nil
}
func (a *QwenAuthenticator) Refresh(ctx context.Context, cfg *config.Config, record *TokenRecord) (*TokenRecord, error) {
if record == nil || record.Storage == nil {
return nil, fmt.Errorf("cliproxy auth: empty token record for qwen refresh")
}
if cfg == nil {
return nil, fmt.Errorf("cliproxy auth: configuration is required")
}
if ctx == nil {
ctx = context.Background()
}
storage, ok := record.Storage.(*qwen.QwenTokenStorage)
if !ok {
return nil, fmt.Errorf("cliproxy auth: unexpected token storage type for qwen refresh")
}
svc := qwen.NewQwenAuth(cfg)
td, err := svc.RefreshTokens(ctx, storage.RefreshToken)
if err != nil {
return nil, err
}
storage.AccessToken = td.AccessToken
storage.RefreshToken = td.RefreshToken
storage.ResourceURL = td.ResourceURL
storage.Expire = td.Expire
result := &TokenRecord{
Provider: a.Provider(),
FileName: record.FileName,
Storage: storage,
Metadata: record.Metadata,
}
return result, nil
}

View File

@@ -585,10 +585,13 @@ func (m *Manager) checkRefreshes(ctx context.Context) {
now := time.Now()
snapshot := m.snapshotAuths()
for _, a := range snapshot {
log.Debugf("checking refresh for %s, %s", a.Provider, a.ID)
typ, _ := a.AccountInfo()
if typ != "api_key" {
if !m.shouldRefresh(a, now) {
continue
}
log.Debugf("checking refresh for %s, %s, %s", a.Provider, a.ID, typ)
if exec := m.executorFor(a.Provider); exec == nil {
continue
}
@@ -597,6 +600,7 @@ func (m *Manager) checkRefreshes(ctx context.Context) {
}
go m.refreshAuth(ctx, a.ID)
}
}
}
func (m *Manager) snapshotAuths() []*Auth {
@@ -646,17 +650,20 @@ func (m *Manager) shouldRefresh(a *Auth, now time.Time) bool {
provider := strings.ToLower(a.Provider)
lead := ProviderRefreshLead(provider, a.Runtime)
if lead <= 0 {
if lead == nil {
return false
}
if *lead <= 0 {
if hasExpiry && !expiry.IsZero() {
return now.After(expiry)
}
return false
}
if hasExpiry && !expiry.IsZero() {
return time.Until(expiry) <= lead
return time.Until(expiry) <= *lead
}
if !lastRefresh.IsZero() {
return now.Sub(lastRefresh) >= lead
return now.Sub(lastRefresh) >= *lead
}
return true
}
@@ -839,6 +846,7 @@ func (m *Manager) refreshAuth(ctx context.Context, id string) {
}
cloned := auth.Clone()
updated, err := exec.Refresh(ctx, cloned)
log.Debugf("refreshed %s, %s, %v", auth.Provider, auth.ID, err)
now := time.Now()
if err != nil {
m.mu.Lock()

View File

@@ -169,23 +169,23 @@ func expirationFromMap(meta map[string]any) (time.Time, bool) {
return time.Time{}, false
}
func ProviderRefreshLead(provider string, runtime any) time.Duration {
func ProviderRefreshLead(provider string, runtime any) *time.Duration {
provider = strings.ToLower(provider)
if runtime != nil {
if eval, ok := runtime.(interface{ RefreshLead() *time.Duration }); ok {
if lead := eval.RefreshLead(); lead != nil && *lead > 0 {
return *lead
return lead
}
}
}
if factory, ok := defaultAuthenticatorFactories[provider]; ok {
if auth := factory(); auth != nil {
if lead := auth.RefreshLead(); lead != nil && *lead > 0 {
return *lead
return lead
}
}
}
return 0
return nil
}
func parseTimeValue(v any) (time.Time, bool) {