@@ -221,5 +221,86 @@ describe("Cost Utility", () => {
221221 expect ( result . totalInputTokens ) . toBe ( 6000 ) // Total already includes cache
222222 expect ( result . totalOutputTokens ) . toBe ( 500 )
223223 } )
224+
225+ it ( "should not apply long-context pricing at the threshold" , ( ) => {
226+ const modelWithLongContextPricing : ModelInfo = {
227+ ...mockModelInfo ,
228+ longContextPricing : {
229+ thresholdTokens : 272_000 ,
230+ inputPriceMultiplier : 2 ,
231+ outputPriceMultiplier : 1.5 ,
232+ cacheWritesPriceMultiplier : 2 ,
233+ cacheReadsPriceMultiplier : 2 ,
234+ } ,
235+ }
236+
237+ const result = calculateApiCostOpenAI ( modelWithLongContextPricing , 272_000 , 1_000 , undefined , 100_000 )
238+
239+ // Input cost: (3.0 / 1_000_000) * (272000 - 100000) = 0.516
240+ // Output cost: (15.0 / 1_000_000) * 1000 = 0.015
241+ // Cache reads: (0.3 / 1_000_000) * 100000 = 0.03
242+ // Total: 0.516 + 0.015 + 0.03 = 0.561
243+ expect ( result . totalCost ) . toBeCloseTo ( 0.561 , 6 )
244+ } )
245+
246+ it ( "should apply long-context pricing above the threshold" , ( ) => {
247+ const modelWithLongContextPricing : ModelInfo = {
248+ maxTokens : 128_000 ,
249+ contextWindow : 1_050_000 ,
250+ supportsPromptCache : true ,
251+ inputPrice : 2.5 ,
252+ outputPrice : 15.0 ,
253+ cacheWritesPrice : 5.0 ,
254+ cacheReadsPrice : 0.25 ,
255+ longContextPricing : {
256+ thresholdTokens : 272_000 ,
257+ inputPriceMultiplier : 2 ,
258+ outputPriceMultiplier : 1.5 ,
259+ cacheWritesPriceMultiplier : 2 ,
260+ cacheReadsPriceMultiplier : 2 ,
261+ } ,
262+ }
263+
264+ const result = calculateApiCostOpenAI ( modelWithLongContextPricing , 300_000 , 1_000 , 20_000 , 100_000 )
265+
266+ // Input cost: (5.0 / 1_000_000) * (300000 - 20000 - 100000) = 0.9
267+ // Output cost: (22.5 / 1_000_000) * 1000 = 0.0225
268+ // Cache writes: (10.0 / 1_000_000) * 20000 = 0.2
269+ // Cache reads: (0.5 / 1_000_000) * 100000 = 0.05
270+ // Total: 0.9 + 0.0225 + 0.2 + 0.05 = 1.1725
271+ expect ( result . totalCost ) . toBeCloseTo ( 1.1725 , 6 )
272+ } )
273+
274+ it ( "should skip long-context pricing for service tiers outside the allowed list" , ( ) => {
275+ const modelWithLongContextPricing : ModelInfo = {
276+ maxTokens : 128_000 ,
277+ contextWindow : 1_050_000 ,
278+ supportsPromptCache : true ,
279+ inputPrice : 5.0 ,
280+ outputPrice : 30.0 ,
281+ cacheReadsPrice : 0.5 ,
282+ longContextPricing : {
283+ thresholdTokens : 272_000 ,
284+ inputPriceMultiplier : 2 ,
285+ outputPriceMultiplier : 1.5 ,
286+ appliesToServiceTiers : [ "default" , "flex" ] ,
287+ } ,
288+ }
289+
290+ const result = calculateApiCostOpenAI (
291+ modelWithLongContextPricing ,
292+ 300_000 ,
293+ 1_000 ,
294+ undefined ,
295+ 100_000 ,
296+ "priority" ,
297+ )
298+
299+ // Input cost: (5.0 / 1_000_000) * (300000 - 100000) = 1.0
300+ // Output cost: (30.0 / 1_000_000) * 1000 = 0.03
301+ // Cache reads: (0.5 / 1_000_000) * 100000 = 0.05
302+ // Total: 1.0 + 0.03 + 0.05 = 1.08
303+ expect ( result . totalCost ) . toBeCloseTo ( 1.08 , 6 )
304+ } )
224305 } )
225306} )
0 commit comments