diff --git a/packages/__tests__/cost/modelCostFromRegistry.test.ts b/packages/__tests__/cost/modelCostFromRegistry.test.ts index 73aa4f6602..04e742fe5f 100644 --- a/packages/__tests__/cost/modelCostFromRegistry.test.ts +++ b/packages/__tests__/cost/modelCostFromRegistry.test.ts @@ -318,7 +318,11 @@ describe("modelCostBreakdownFromRegistry", () => { expect(breakdown.inputCost).toBe(250000 * 0.000006); expect(breakdown.outputCost).toBe(50000 * 0.0000225); expect(breakdown.cachedInputCost).toBe(10000 * 0.000003 * 0.1); - expect(breakdown.cacheWrite5mCost).toBe(5000 * 0.000003 * 1.25); + // Regression for #5766: cache writes tier on the same threshold + // as the input cost (here, the long-context tier), not the base + // tier — the original 0.000003 base-tier rate undercharged + // >200k-token Anthropic requests at the long-context rate. + expect(breakdown.cacheWrite5mCost).toBe(5000 * 0.000006 * 1.25); } }); diff --git a/packages/cost/models/calculate-cost.ts b/packages/cost/models/calculate-cost.ts index 860396a924..5ccfacc5c6 100644 --- a/packages/cost/models/calculate-cost.ts +++ b/packages/cost/models/calculate-cost.ts @@ -215,16 +215,23 @@ export function calculateModelCostBreakdown(params: { modelUsage.cacheDetails.cachedInput * cachedInputPricing.input * cachedMultiplier; } + // Cache writes tier on the same threshold as inputCost — the + // long-context threshold is "total prompt tokens above N", and + // cache writes count toward that. Using the base tier (preprocessed + // pricing tier 0) undercharges >200k-token requests at the + // long-context rate. Regression for #5766. if (modelUsage.cacheDetails.write5m) { - const write5mMultiplier = basePricing.cacheMultipliers?.write5m ?? 1.0; + const write5mPricing = getPricingTier(preprocessedPricing, getThresholdValue(modelUsage, "inputCost")); + const write5mMultiplier = write5mPricing.cacheMultipliers?.write5m ?? 1.0; breakdown.cacheWrite5mCost = - modelUsage.cacheDetails.write5m * basePricing.input * write5mMultiplier; + modelUsage.cacheDetails.write5m * write5mPricing.input * write5mMultiplier; } if (modelUsage.cacheDetails.write1h) { - const write1hMultiplier = basePricing.cacheMultipliers?.write1h ?? 1.0; + const write1hPricing = getPricingTier(preprocessedPricing, getThresholdValue(modelUsage, "inputCost")); + const write1hMultiplier = write1hPricing.cacheMultipliers?.write1h ?? 1.0; breakdown.cacheWrite1hCost = - modelUsage.cacheDetails.write1h * basePricing.input * write1hMultiplier; + modelUsage.cacheDetails.write1h * write1hPricing.input * write1hMultiplier; } }