@@ -74,6 +74,7 @@ import {
7474} from "./accounts/rate-limits.js" ;
7575
7676const log = createLogger ( "accounts" ) ;
77+ const ACCOUNT_SELECTION_FRESH_WINDOW_MS = 5 * 60_000 ;
7778
7879function initFamilyState ( defaultValue : number ) : Record < ModelFamily , number > {
7980 return Object . fromEntries (
@@ -381,12 +382,45 @@ export class AccountManager {
381382 return account ?? null ;
382383 }
383384
385+ private hasFreshAccessToken ( account : ManagedAccount ) : boolean {
386+ if ( ! account . access ) return false ;
387+ if ( typeof account . expires !== "number" || ! Number . isFinite ( account . expires ) ) {
388+ return false ;
389+ }
390+ return account . expires > nowMs ( ) + ACCOUNT_SELECTION_FRESH_WINDOW_MS ;
391+ }
392+
393+ private isAccountSelectableForFamily (
394+ account : ManagedAccount ,
395+ family : ModelFamily ,
396+ model ?: string | null ,
397+ requireFresh = false ,
398+ ) : boolean {
399+ if ( account . enabled === false ) return false ;
400+ clearExpiredRateLimits ( account ) ;
401+ if ( isRateLimitedForFamily ( account , family , model ) || this . isAccountCoolingDown ( account ) ) {
402+ return false ;
403+ }
404+ return ! requireFresh || this . hasFreshAccessToken ( account ) ;
405+ }
406+
407+ private hasFreshAvailableAccountForFamily (
408+ family : ModelFamily ,
409+ model ?: string | null ,
410+ ) : boolean {
411+ return this . accounts . some (
412+ ( account ) =>
413+ Boolean ( account ) &&
414+ this . isAccountSelectableForFamily ( account , family , model ) &&
415+ this . hasFreshAccessToken ( account ) ,
416+ ) ;
417+ }
418+
384419 isAccountAvailableForFamily ( index : number , family : ModelFamily , model ?: string | null ) : boolean {
385420 const account = this . getAccountByIndex ( index ) ;
386421 if ( ! account ) return false ;
387- if ( account . enabled === false ) return false ;
388- clearExpiredRateLimits ( account ) ;
389- return ! isRateLimitedForFamily ( account , family , model ) && ! this . isAccountCoolingDown ( account ) ;
422+ const requireFresh = this . hasFreshAvailableAccountForFamily ( family , model ) ;
423+ return this . isAccountSelectableForFamily ( account , family , model , requireFresh ) ;
390424 }
391425
392426 setActiveIndex ( index : number ) : ManagedAccount | null {
@@ -446,15 +480,13 @@ export class AccountManager {
446480 if ( count === 0 ) return null ;
447481
448482 const cursor = this . cursorByFamily [ family ] ;
483+ const requireFresh = this . hasFreshAvailableAccountForFamily ( family , model ) ;
449484
450485 for ( let i = 0 ; i < count ; i ++ ) {
451486 const idx = ( cursor + i ) % count ;
452487 const account = this . accounts [ idx ] ;
453488 if ( ! account ) continue ;
454- if ( account . enabled === false ) continue ;
455-
456- clearExpiredRateLimits ( account ) ;
457- if ( isRateLimitedForFamily ( account , family , model ) || this . isAccountCoolingDown ( account ) ) {
489+ if ( ! this . isAccountSelectableForFamily ( account , family , model , requireFresh ) ) {
458490 continue ;
459491 }
460492
@@ -472,15 +504,13 @@ export class AccountManager {
472504 if ( count === 0 ) return null ;
473505
474506 const cursor = this . cursorByFamily [ family ] ;
507+ const requireFresh = this . hasFreshAvailableAccountForFamily ( family , model ) ;
475508
476509 for ( let i = 0 ; i < count ; i ++ ) {
477510 const idx = ( cursor + i ) % count ;
478511 const account = this . accounts [ idx ] ;
479512 if ( ! account ) continue ;
480- if ( account . enabled === false ) continue ;
481-
482- clearExpiredRateLimits ( account ) ;
483- if ( isRateLimitedForFamily ( account , family , model ) || this . isAccountCoolingDown ( account ) ) {
513+ if ( ! this . isAccountSelectableForFamily ( account , family , model , requireFresh ) ) {
484514 continue ;
485515 }
486516
@@ -495,6 +525,7 @@ export class AccountManager {
495525 getCurrentOrNextForFamilyHybrid ( family : ModelFamily , model ?: string | null , options ?: HybridSelectionOptions ) : ManagedAccount | null {
496526 const count = this . accounts . length ;
497527 if ( count === 0 ) return null ;
528+ const requireFresh = this . hasFreshAvailableAccountForFamily ( family , model ) ;
498529
499530 const currentIndex = this . currentAccountIndexByFamily [ family ] ;
500531 if ( currentIndex >= 0 && currentIndex < count ) {
@@ -503,10 +534,13 @@ export class AccountManager {
503534 if ( currentAccount . enabled === false ) {
504535 // Fall through to hybrid selection.
505536 } else {
506- clearExpiredRateLimits ( currentAccount ) ;
507537 if (
508- ! isRateLimitedForFamily ( currentAccount , family , model ) &&
509- ! this . isAccountCoolingDown ( currentAccount )
538+ this . isAccountSelectableForFamily (
539+ currentAccount ,
540+ family ,
541+ model ,
542+ requireFresh ,
543+ )
510544 ) {
511545 currentAccount . lastUsed = nowMs ( ) ;
512546 return currentAccount ;
@@ -522,13 +556,14 @@ export class AccountManager {
522556 const accountsWithMetrics : AccountWithMetrics [ ] = this . accounts
523557 . map ( ( account ) : AccountWithMetrics | null => {
524558 if ( ! account ) return null ;
525- if ( account . enabled === false ) return null ;
526- clearExpiredRateLimits ( account ) ;
527- const isAvailable =
528- ! isRateLimitedForFamily ( account , family , model ) && ! this . isAccountCoolingDown ( account ) ;
529559 return {
530560 index : account . index ,
531- isAvailable,
561+ isAvailable : this . isAccountSelectableForFamily (
562+ account ,
563+ family ,
564+ model ,
565+ requireFresh ,
566+ ) ,
532567 lastUsed : account . lastUsed ,
533568 } ;
534569 } )
0 commit comments