@@ -174,6 +174,30 @@ func TestGetModelPricing_OpenAIGPT54Fallback(t *testing.T) {
174174 require .InDelta (t , 1.5 , pricing .LongContextOutputMultiplier , 1e-12 )
175175}
176176
177+ func TestGetModelPricing_OpenAIGPT54MiniFallback (t * testing.T ) {
178+ svc := newTestBillingService ()
179+
180+ pricing , err := svc .GetModelPricing ("gpt-5.4-mini" )
181+ require .NoError (t , err )
182+ require .NotNil (t , pricing )
183+ require .InDelta (t , 7.5e-7 , pricing .InputPricePerToken , 1e-12 )
184+ require .InDelta (t , 4.5e-6 , pricing .OutputPricePerToken , 1e-12 )
185+ require .InDelta (t , 7.5e-8 , pricing .CacheReadPricePerToken , 1e-12 )
186+ require .Zero (t , pricing .LongContextInputThreshold )
187+ }
188+
189+ func TestGetModelPricing_OpenAIGPT54NanoFallback (t * testing.T ) {
190+ svc := newTestBillingService ()
191+
192+ pricing , err := svc .GetModelPricing ("gpt-5.4-nano" )
193+ require .NoError (t , err )
194+ require .NotNil (t , pricing )
195+ require .InDelta (t , 2e-7 , pricing .InputPricePerToken , 1e-12 )
196+ require .InDelta (t , 1.25e-6 , pricing .OutputPricePerToken , 1e-12 )
197+ require .InDelta (t , 2e-8 , pricing .CacheReadPricePerToken , 1e-12 )
198+ require .Zero (t , pricing .LongContextInputThreshold )
199+ }
200+
177201func TestCalculateCost_OpenAIGPT54LongContextAppliesWholeSessionMultipliers (t * testing.T ) {
178202 svc := newTestBillingService ()
179203
@@ -210,6 +234,8 @@ func TestGetFallbackPricing_FamilyMatching(t *testing.T) {
210234 {name : "gemini unknown no fallback" , model : "gemini-2.0-pro" , expectNilPricing : true },
211235 {name : "openai gpt5.1" , model : "gpt-5.1" , expectedInput : 1.25e-6 },
212236 {name : "openai gpt5.4" , model : "gpt-5.4" , expectedInput : 2.5e-6 },
237+ {name : "openai gpt5.4 mini" , model : "gpt-5.4-mini" , expectedInput : 7.5e-7 },
238+ {name : "openai gpt5.4 nano" , model : "gpt-5.4-nano" , expectedInput : 2e-7 },
213239 {name : "openai gpt5.3 codex" , model : "gpt-5.3-codex" , expectedInput : 1.5e-6 },
214240 {name : "openai gpt5.1 codex max alias" , model : "gpt-5.1-codex-max" , expectedInput : 1.5e-6 },
215241 {name : "openai codex mini latest alias" , model : "codex-mini-latest" , expectedInput : 1.5e-6 },
@@ -564,6 +590,40 @@ func TestCalculateCostWithServiceTier_FlexAppliesHalfMultiplier(t *testing.T) {
564590 require .InDelta (t , baseCost .TotalCost * 0.5 , flexCost .TotalCost , 1e-10 )
565591}
566592
593+ func TestCalculateCostWithServiceTier_Gpt54MiniPriorityFallsBackToTierMultiplier (t * testing.T ) {
594+ svc := newTestBillingService ()
595+ tokens := UsageTokens {InputTokens : 120 , OutputTokens : 30 , CacheCreationTokens : 12 , CacheReadTokens : 8 }
596+
597+ baseCost , err := svc .CalculateCost ("gpt-5.4-mini" , tokens , 1.0 )
598+ require .NoError (t , err )
599+
600+ priorityCost , err := svc .CalculateCostWithServiceTier ("gpt-5.4-mini" , tokens , 1.0 , "priority" )
601+ require .NoError (t , err )
602+
603+ require .InDelta (t , baseCost .InputCost * 2 , priorityCost .InputCost , 1e-10 )
604+ require .InDelta (t , baseCost .OutputCost * 2 , priorityCost .OutputCost , 1e-10 )
605+ require .InDelta (t , baseCost .CacheCreationCost * 2 , priorityCost .CacheCreationCost , 1e-10 )
606+ require .InDelta (t , baseCost .CacheReadCost * 2 , priorityCost .CacheReadCost , 1e-10 )
607+ require .InDelta (t , baseCost .TotalCost * 2 , priorityCost .TotalCost , 1e-10 )
608+ }
609+
610+ func TestCalculateCostWithServiceTier_Gpt54NanoFlexAppliesHalfMultiplier (t * testing.T ) {
611+ svc := newTestBillingService ()
612+ tokens := UsageTokens {InputTokens : 100 , OutputTokens : 50 , CacheCreationTokens : 40 , CacheReadTokens : 20 }
613+
614+ baseCost , err := svc .CalculateCost ("gpt-5.4-nano" , tokens , 1.0 )
615+ require .NoError (t , err )
616+
617+ flexCost , err := svc .CalculateCostWithServiceTier ("gpt-5.4-nano" , tokens , 1.0 , "flex" )
618+ require .NoError (t , err )
619+
620+ require .InDelta (t , baseCost .InputCost * 0.5 , flexCost .InputCost , 1e-10 )
621+ require .InDelta (t , baseCost .OutputCost * 0.5 , flexCost .OutputCost , 1e-10 )
622+ require .InDelta (t , baseCost .CacheCreationCost * 0.5 , flexCost .CacheCreationCost , 1e-10 )
623+ require .InDelta (t , baseCost .CacheReadCost * 0.5 , flexCost .CacheReadCost , 1e-10 )
624+ require .InDelta (t , baseCost .TotalCost * 0.5 , flexCost .TotalCost , 1e-10 )
625+ }
626+
567627func TestCalculateCostWithServiceTier_PriorityFallsBackToTierMultiplierWithoutExplicitPriorityPrice (t * testing.T ) {
568628 svc := newTestBillingService ()
569629 tokens := UsageTokens {InputTokens : 120 , OutputTokens : 30 , CacheCreationTokens : 12 , CacheReadTokens : 8 }
0 commit comments