@@ -252,7 +252,7 @@ impl DailyUsage {
252252
253253 fn keep_max ( & mut self , other : & DailyUsage ) -> bool {
254254 let before = self . clone ( ) ;
255- let incoming_covers_existing = other. covers ( self ) ;
255+ let incoming_covers_existing = other. covers ( self ) || other . covers_cost_reprice ( self ) ;
256256 self . tokens . input = self . tokens . input . max ( other. tokens . input ) ;
257257 self . tokens . output = self . tokens . output . max ( other. tokens . output ) ;
258258 self . tokens . cache_read = self . tokens . cache_read . max ( other. tokens . cache_read ) ;
@@ -283,6 +283,23 @@ impl DailyUsage {
283283 && self . tokens . cached_input >= other. tokens . cached_input
284284 && self . tokens . reasoning >= other. tokens . reasoning
285285 }
286+
287+ fn covers_cost_reprice ( & self , other : & DailyUsage ) -> bool {
288+ let incoming = self . tokens . total_billable_units ( ) ;
289+ let existing = other. tokens . total_billable_units ( ) ;
290+ existing >= 1_000_000 && incoming. saturating_mul ( 100 ) >= existing. saturating_mul ( 85 )
291+ }
292+ }
293+
294+ impl DailyTokens {
295+ fn total_billable_units ( & self ) -> u64 {
296+ self . input
297+ . saturating_add ( self . output )
298+ . saturating_add ( self . cache_read )
299+ . saturating_add ( self . cache_write )
300+ . saturating_add ( self . cached_input )
301+ . saturating_add ( self . reasoning )
302+ }
286303}
287304
288305fn read_daily_ledger ( path : & std:: path:: Path ) -> Option < DailyLedger > {
@@ -447,4 +464,71 @@ mod tests {
447464 assert_eq ! ( updated. requests, 10 ) ;
448465 assert_eq ! ( updated. api_equiv, 25.0 ) ;
449466 }
467+
468+ #[ test]
469+ fn daily_upsert_reprices_when_fresh_scan_has_broad_token_coverage ( ) {
470+ let original = DailyUsage {
471+ tokens : DailyTokens {
472+ input : 1_000 ,
473+ output : 10_000 ,
474+ cache_read : 1_000_000 ,
475+ cache_write : 100_000 ,
476+ cached_input : 0 ,
477+ reasoning : 0 ,
478+ } ,
479+ requests : 100 ,
480+ api_equiv : 300.0 ,
481+ } ;
482+ let repriced = DailyUsage {
483+ tokens : DailyTokens {
484+ input : 900 ,
485+ output : 9_500 ,
486+ cache_read : 900_000 ,
487+ cache_write : 95_000 ,
488+ cached_input : 0 ,
489+ reasoning : 0 ,
490+ } ,
491+ requests : 90 ,
492+ api_equiv : 100.0 ,
493+ } ;
494+ let mut slot = Some ( original) ;
495+
496+ assert ! ( upsert_vendor_day( & mut slot, & repriced) ) ;
497+ let updated = slot. unwrap ( ) ;
498+ assert_eq ! ( updated. tokens. cache_read, 1_000_000 ) ;
499+ assert_eq ! ( updated. requests, 100 ) ;
500+ assert_eq ! ( updated. api_equiv, 100.0 ) ;
501+ }
502+
503+ #[ test]
504+ fn daily_upsert_refuses_reprice_when_fresh_scan_is_too_partial ( ) {
505+ let original = DailyUsage {
506+ tokens : DailyTokens {
507+ input : 1_000 ,
508+ output : 10_000 ,
509+ cache_read : 1_000_000 ,
510+ cache_write : 100_000 ,
511+ cached_input : 0 ,
512+ reasoning : 0 ,
513+ } ,
514+ requests : 100 ,
515+ api_equiv : 300.0 ,
516+ } ;
517+ let partial = DailyUsage {
518+ tokens : DailyTokens {
519+ input : 100 ,
520+ output : 1_000 ,
521+ cache_read : 100_000 ,
522+ cache_write : 10_000 ,
523+ cached_input : 0 ,
524+ reasoning : 0 ,
525+ } ,
526+ requests : 10 ,
527+ api_equiv : 10.0 ,
528+ } ;
529+ let mut slot = Some ( original) ;
530+
531+ assert ! ( !upsert_vendor_day( & mut slot, & partial) ) ;
532+ assert_eq ! ( slot. unwrap( ) . api_equiv, 300.0 ) ;
533+ }
450534}
0 commit comments