feat(antigravity): conductor-level credits fallback for Claude models
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")
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user