mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-06-05 02:34:59 +08:00
Move credits handling from executor-level retry to conductor-level orchestration. When all free-tier auths are exhausted (429/503), the conductor discovers auths with available Google One AI credits and retries with enabledCreditTypes injected via context flag. Key changes: - Add AntigravityCreditsHint system for tracking per-auth credits state - Conductor tries credits fallback after all auths fail (Execute/Stream/Count) - Executor injects enabledCreditTypes only when conductor sets context flag - Credits fallback respects provider scope (requires antigravity in providers) - Add context cancellation check in credits fallback to avoid wasted requests - Remove executor-level attemptCreditsFallback and preferCredits machinery - Restructure 429 decision logic (parse details first, keyword fallback) - Expand shouldAbort to cover INVALID_ARGUMENT/FAILED_PRECONDITION/500+UNKNOWN - Support human-readable retry delay parsing (e.g. "1h43m56s")
91 lines
2.4 KiB
Go
91 lines
2.4 KiB
Go
package auth
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type antigravityUseCreditsContextKey struct{}
|
|
|
|
// WithAntigravityCredits returns a child context that signals the executor to
|
|
// inject enabledCreditTypes into the request payload.
|
|
func WithAntigravityCredits(ctx context.Context) context.Context {
|
|
return context.WithValue(ctx, antigravityUseCreditsContextKey{}, true)
|
|
}
|
|
|
|
// AntigravityCreditsRequested reports whether the context carries the credits flag.
|
|
func AntigravityCreditsRequested(ctx context.Context) bool {
|
|
if ctx == nil {
|
|
return false
|
|
}
|
|
v, _ := ctx.Value(antigravityUseCreditsContextKey{}).(bool)
|
|
return v
|
|
}
|
|
|
|
// AntigravityCreditsHint stores the latest known AI credits state for one auth.
|
|
type AntigravityCreditsHint struct {
|
|
Known bool
|
|
Available bool
|
|
CreditAmount float64
|
|
MinCreditAmount float64
|
|
PaidTierID string
|
|
UpdatedAt time.Time
|
|
}
|
|
|
|
var antigravityCreditsHintByAuth sync.Map
|
|
|
|
// SetAntigravityCreditsHint updates the latest known AI credits state for an auth.
|
|
func SetAntigravityCreditsHint(authID string, hint AntigravityCreditsHint) {
|
|
authID = strings.TrimSpace(authID)
|
|
if authID == "" {
|
|
return
|
|
}
|
|
if hint.UpdatedAt.IsZero() {
|
|
hint.UpdatedAt = time.Now()
|
|
}
|
|
antigravityCreditsHintByAuth.Store(authID, hint)
|
|
}
|
|
|
|
// GetAntigravityCreditsHint returns the latest known AI credits state for an auth.
|
|
func GetAntigravityCreditsHint(authID string) (AntigravityCreditsHint, bool) {
|
|
authID = strings.TrimSpace(authID)
|
|
if authID == "" {
|
|
return AntigravityCreditsHint{}, false
|
|
}
|
|
value, ok := antigravityCreditsHintByAuth.Load(authID)
|
|
if !ok {
|
|
return AntigravityCreditsHint{}, false
|
|
}
|
|
hint, ok := value.(AntigravityCreditsHint)
|
|
if !ok {
|
|
antigravityCreditsHintByAuth.Delete(authID)
|
|
return AntigravityCreditsHint{}, false
|
|
}
|
|
return hint, true
|
|
}
|
|
|
|
// HasKnownAntigravityCreditsHint reports whether credits state has been discovered for an auth.
|
|
func HasKnownAntigravityCreditsHint(authID string) bool {
|
|
hint, ok := GetAntigravityCreditsHint(authID)
|
|
return ok && hint.Known
|
|
}
|
|
|
|
func antigravityCreditsAvailableForModel(auth *Auth, model string) bool {
|
|
if auth == nil {
|
|
return false
|
|
}
|
|
if !strings.EqualFold(strings.TrimSpace(auth.Provider), "antigravity") {
|
|
return false
|
|
}
|
|
if !strings.Contains(strings.ToLower(strings.TrimSpace(model)), "claude") {
|
|
return false
|
|
}
|
|
hint, ok := GetAntigravityCreditsHint(auth.ID)
|
|
if !ok || !hint.Known {
|
|
return false
|
|
}
|
|
return hint.Available
|
|
}
|