@@ -77,6 +77,7 @@ import {
7777} from "./accounts/rate-limits.js" ;
7878
7979const log = createLogger ( "accounts" ) ;
80+ const ACCOUNT_SELECTION_FRESH_WINDOW_MS = 5 * 60_000 ;
8081
8182function initFamilyState ( defaultValue : number ) : Record < ModelFamily , number > {
8283 return Object . fromEntries (
@@ -490,12 +491,45 @@ export class AccountManager {
490491 return account ?? null ;
491492 }
492493
494+ private hasFreshAccessToken ( account : ManagedAccount ) : boolean {
495+ if ( ! account . access ) return false ;
496+ if ( typeof account . expires !== "number" || ! Number . isFinite ( account . expires ) ) {
497+ return false ;
498+ }
499+ return account . expires > nowMs ( ) + ACCOUNT_SELECTION_FRESH_WINDOW_MS ;
500+ }
501+
502+ private isAccountSelectableForFamily (
503+ account : ManagedAccount ,
504+ family : ModelFamily ,
505+ model ?: string | null ,
506+ requireFresh = false ,
507+ ) : boolean {
508+ if ( account . enabled === false ) return false ;
509+ clearExpiredRateLimits ( account ) ;
510+ if ( isRateLimitedForFamily ( account , family , model ) || this . isAccountCoolingDown ( account ) ) {
511+ return false ;
512+ }
513+ return ! requireFresh || this . hasFreshAccessToken ( account ) ;
514+ }
515+
516+ private hasFreshAvailableAccountForFamily (
517+ family : ModelFamily ,
518+ model ?: string | null ,
519+ ) : boolean {
520+ return this . accounts . some (
521+ ( account ) =>
522+ Boolean ( account ) &&
523+ this . isAccountSelectableForFamily ( account , family , model ) &&
524+ this . hasFreshAccessToken ( account ) ,
525+ ) ;
526+ }
527+
493528 isAccountAvailableForFamily ( index : number , family : ModelFamily , model ?: string | null ) : boolean {
494529 const account = this . getAccountByIndex ( index ) ;
495530 if ( ! account ) return false ;
496- if ( account . enabled === false ) return false ;
497- clearExpiredRateLimits ( account ) ;
498- return ! isRateLimitedForFamily ( account , family , model ) && ! this . isAccountCoolingDown ( account ) ;
531+ const requireFresh = this . hasFreshAvailableAccountForFamily ( family , model ) ;
532+ return this . isAccountSelectableForFamily ( account , family , model , requireFresh ) ;
499533 }
500534
501535 setActiveIndex ( index : number ) : ManagedAccount | null {
@@ -555,15 +589,13 @@ export class AccountManager {
555589 if ( count === 0 ) return null ;
556590
557591 const cursor = this . cursorByFamily [ family ] ;
592+ const requireFresh = this . hasFreshAvailableAccountForFamily ( family , model ) ;
558593
559594 for ( let i = 0 ; i < count ; i ++ ) {
560595 const idx = ( cursor + i ) % count ;
561596 const account = this . accounts [ idx ] ;
562597 if ( ! account ) continue ;
563- if ( account . enabled === false ) continue ;
564-
565- clearExpiredRateLimits ( account ) ;
566- if ( isRateLimitedForFamily ( account , family , model ) || this . isAccountCoolingDown ( account ) ) {
598+ if ( ! this . isAccountSelectableForFamily ( account , family , model , requireFresh ) ) {
567599 continue ;
568600 }
569601
@@ -581,15 +613,13 @@ export class AccountManager {
581613 if ( count === 0 ) return null ;
582614
583615 const cursor = this . cursorByFamily [ family ] ;
616+ const requireFresh = this . hasFreshAvailableAccountForFamily ( family , model ) ;
584617
585618 for ( let i = 0 ; i < count ; i ++ ) {
586619 const idx = ( cursor + i ) % count ;
587620 const account = this . accounts [ idx ] ;
588621 if ( ! account ) continue ;
589- if ( account . enabled === false ) continue ;
590-
591- clearExpiredRateLimits ( account ) ;
592- if ( isRateLimitedForFamily ( account , family , model ) || this . isAccountCoolingDown ( account ) ) {
622+ if ( ! this . isAccountSelectableForFamily ( account , family , model , requireFresh ) ) {
593623 continue ;
594624 }
595625
@@ -604,6 +634,7 @@ export class AccountManager {
604634 getCurrentOrNextForFamilyHybrid ( family : ModelFamily , model ?: string | null , options ?: HybridSelectionOptions ) : ManagedAccount | null {
605635 const count = this . accounts . length ;
606636 if ( count === 0 ) return null ;
637+ const requireFresh = this . hasFreshAvailableAccountForFamily ( family , model ) ;
607638
608639 const currentIndex = this . currentAccountIndexByFamily [ family ] ;
609640 if ( currentIndex >= 0 && currentIndex < count ) {
@@ -612,10 +643,13 @@ export class AccountManager {
612643 if ( currentAccount . enabled === false ) {
613644 // Fall through to hybrid selection.
614645 } else {
615- clearExpiredRateLimits ( currentAccount ) ;
616646 if (
617- ! isRateLimitedForFamily ( currentAccount , family , model ) &&
618- ! this . isAccountCoolingDown ( currentAccount )
647+ this . isAccountSelectableForFamily (
648+ currentAccount ,
649+ family ,
650+ model ,
651+ requireFresh ,
652+ )
619653 ) {
620654 currentAccount . lastUsed = nowMs ( ) ;
621655 return currentAccount ;
@@ -631,13 +665,14 @@ export class AccountManager {
631665 const accountsWithMetrics : AccountWithMetrics [ ] = this . accounts
632666 . map ( ( account ) : AccountWithMetrics | null => {
633667 if ( ! account ) return null ;
634- if ( account . enabled === false ) return null ;
635- clearExpiredRateLimits ( account ) ;
636- const isAvailable =
637- ! isRateLimitedForFamily ( account , family , model ) && ! this . isAccountCoolingDown ( account ) ;
638668 return {
639669 index : account . index ,
640- isAvailable,
670+ isAvailable : this . isAccountSelectableForFamily (
671+ account ,
672+ family ,
673+ model ,
674+ requireFresh ,
675+ ) ,
641676 lastUsed : account . lastUsed ,
642677 } ;
643678 } )
0 commit comments