@@ -342,17 +342,51 @@ const lastProbeAttempt = new Map<string, number>();
342342const MIN_PROBE_INTERVAL_MS = 30_000 ; // 30 seconds between probes per key
343343const PROBE_MARGIN_MS = 2 * 60 * 1000 ;
344344const PROBE_SCOPE_DELIMITER = "::" ;
345+ const PROBE_STATE_TTL_MS = 24 * 60 * 60 * 1000 ;
346+ const MAX_PROBE_KEYS = 256 ;
345347
346348function resolveProbeThrottleKey ( provider : string , agentDir ?: string ) : string {
347349 const scope = String ( agentDir ?? "" ) . trim ( ) ;
348350 return scope ? `${ scope } ${ PROBE_SCOPE_DELIMITER } ${ provider } ` : provider ;
349351}
350352
353+ function pruneProbeState ( now : number ) : void {
354+ for ( const [ key , ts ] of lastProbeAttempt ) {
355+ if ( ! Number . isFinite ( ts ) || ts <= 0 || now - ts > PROBE_STATE_TTL_MS ) {
356+ lastProbeAttempt . delete ( key ) ;
357+ }
358+ }
359+ }
360+
361+ function enforceProbeStateCap ( ) : void {
362+ while ( lastProbeAttempt . size > MAX_PROBE_KEYS ) {
363+ let oldestKey : string | null = null ;
364+ let oldestTs = Number . POSITIVE_INFINITY ;
365+ for ( const [ key , ts ] of lastProbeAttempt ) {
366+ if ( ts < oldestTs ) {
367+ oldestKey = key ;
368+ oldestTs = ts ;
369+ }
370+ }
371+ if ( ! oldestKey ) {
372+ break ;
373+ }
374+ lastProbeAttempt . delete ( oldestKey ) ;
375+ }
376+ }
377+
351378function isProbeThrottleOpen ( now : number , throttleKey : string ) : boolean {
379+ pruneProbeState ( now ) ;
352380 const lastProbe = lastProbeAttempt . get ( throttleKey ) ?? 0 ;
353381 return now - lastProbe >= MIN_PROBE_INTERVAL_MS ;
354382}
355383
384+ function markProbeAttempt ( now : number , throttleKey : string ) : void {
385+ pruneProbeState ( now ) ;
386+ lastProbeAttempt . set ( throttleKey , now ) ;
387+ enforceProbeStateCap ( ) ;
388+ }
389+
356390function shouldProbePrimaryDuringCooldown ( params : {
357391 isPrimary : boolean ;
358392 hasFallbackCandidates : boolean ;
@@ -383,7 +417,12 @@ export const _probeThrottleInternals = {
383417 lastProbeAttempt,
384418 MIN_PROBE_INTERVAL_MS ,
385419 PROBE_MARGIN_MS ,
420+ PROBE_STATE_TTL_MS ,
421+ MAX_PROBE_KEYS ,
386422 resolveProbeThrottleKey,
423+ isProbeThrottleOpen,
424+ pruneProbeState,
425+ markProbeAttempt,
387426} as const ;
388427
389428type CooldownDecision =
@@ -536,7 +575,7 @@ export async function runWithModelFallback<T>(params: {
536575 }
537576
538577 if ( decision . markProbe ) {
539- lastProbeAttempt . set ( probeThrottleKey , now ) ;
578+ markProbeAttempt ( now , probeThrottleKey ) ;
540579 }
541580 if (
542581 decision . reason === "rate_limit" ||
0 commit comments