@@ -23,10 +23,14 @@ import {
2323} from "./lib/output-test-runner.ts" ;
2424import { resultWriteTool , testComponentTool } from "./lib/tools/index.ts" ;
2525import {
26+ lookupModelPricing ,
27+ lookupModelPricingByKey ,
2628 getModelPricingDisplay ,
2729 calculateCost ,
2830 formatCost ,
2931 isPricingAvailable ,
32+ type ModelPricing ,
33+ type ModelPricingLookup ,
3034} from "./lib/pricing.ts" ;
3135import type { LanguageModel } from "ai" ;
3236
@@ -97,8 +101,8 @@ function extractResultWriteContent(steps: unknown[]): string | null {
97101 */
98102function calculateTotalCost (
99103 tests : SingleTestResult [ ] ,
100- modelString : string ,
101- ) : TotalCostInfo | null {
104+ pricing : ModelPricing ,
105+ ) : TotalCostInfo {
102106 let totalInputTokens = 0 ;
103107 let totalOutputTokens = 0 ;
104108 let totalCachedInputTokens = 0 ;
@@ -112,14 +116,12 @@ function calculateTotalCost(
112116 }
113117
114118 const costResult = calculateCost (
115- modelString ,
119+ pricing ,
116120 totalInputTokens ,
117121 totalOutputTokens ,
118122 totalCachedInputTokens ,
119123 ) ;
120124
121- if ( ! costResult ) return null ;
122-
123125 return {
124126 inputCost : costResult . inputCost ,
125127 outputCost : costResult . outputCost ,
@@ -131,6 +133,69 @@ function calculateTotalCost(
131133 } ;
132134}
133135
136+ /**
137+ * Resolve pricing lookup based on environment variables
138+ * Returns the pricing lookup result or null if disabled
139+ * Throws an error if pricing cannot be found and is not disabled
140+ */
141+ function resolvePricingLookup ( modelString : string ) : ModelPricingLookup | null {
142+ const costDisabled = process . env . MODEL_COST_DISABLED === "true" ;
143+ const explicitCostName = process . env . MODEL_COST_NAME ;
144+
145+ // If cost calculation is explicitly disabled, return null
146+ if ( costDisabled ) {
147+ return null ;
148+ }
149+
150+ // Check if pricing data file exists
151+ if ( ! isPricingAvailable ( ) ) {
152+ console . error (
153+ `\n✗ Model pricing file not found. Run 'bun run update-model-pricing' to download it.` ,
154+ ) ;
155+ console . error (
156+ ` Or set MODEL_COST_DISABLED=true to skip cost calculation.\n` ,
157+ ) ;
158+ process . exit ( 1 ) ;
159+ }
160+
161+ // If explicit cost name is provided, use that
162+ if ( explicitCostName ) {
163+ const lookup = lookupModelPricingByKey ( explicitCostName ) ;
164+ if ( ! lookup ) {
165+ console . error (
166+ `\n✗ Could not find pricing for MODEL_COST_NAME="${ explicitCostName } " in model-pricing.json` ,
167+ ) ;
168+ console . error (
169+ ` Check that the key exists in data/model-pricing.json.\n` ,
170+ ) ;
171+ process . exit ( 1 ) ;
172+ }
173+ return lookup ;
174+ }
175+
176+ // Try automatic lookup
177+ const lookup = lookupModelPricing ( modelString ) ;
178+ if ( ! lookup ) {
179+ console . error (
180+ `\n✗ Could not find pricing for model "${ modelString } " in model-pricing.json` ,
181+ ) ;
182+ console . error ( `\n Options:` ) ;
183+ console . error (
184+ ` 1. Set MODEL_COST_NAME=<key> to explicitly specify the pricing key` ,
185+ ) ;
186+ console . error ( ` Example: MODEL_COST_NAME=claude-sonnet-4-20250514` ) ;
187+ console . error (
188+ ` 2. Set MODEL_COST_DISABLED=true to skip cost calculation` ,
189+ ) ;
190+ console . error (
191+ `\n Browse data/model-pricing.json to find the correct key for your model.\n` ,
192+ ) ;
193+ process . exit ( 1 ) ;
194+ }
195+
196+ return lookup ;
197+ }
198+
134199/**
135200 * Run a single test with the AI agent
136201 */
@@ -281,10 +346,24 @@ async function main() {
281346 const isHttpTransport = mcpEnabled && isHttpUrl ( mcpServerUrl ) ;
282347 const mcpTransportType = isHttpTransport ? "HTTP" : "StdIO" ;
283348
349+ // Load environment configuration
350+ const envConfig = loadEnvConfig ( ) ;
351+
284352 console . log ( "╔════════════════════════════════════════════════════╗" ) ;
285353 console . log ( "║ SvelteBench 2.0 - Multi-Test ║" ) ;
286354 console . log ( "╚════════════════════════════════════════════════════╝" ) ;
287- console . log ( `Model: ${ process . env . MODEL } ` ) ;
355+ console . log ( `Model: ${ envConfig . modelString } ` ) ;
356+
357+ // Resolve pricing lookup
358+ const costDisabled = process . env . MODEL_COST_DISABLED === "true" ;
359+ const pricingLookup = resolvePricingLookup ( envConfig . modelString ) ;
360+
361+ if ( pricingLookup ) {
362+ console . log ( `Pricing model mapped: ${ pricingLookup . matchedKey } ` ) ;
363+ } else if ( costDisabled ) {
364+ console . log ( `Pricing: Disabled (MODEL_COST_DISABLED=true)` ) ;
365+ }
366+
288367 console . log ( `MCP Integration: ${ mcpEnabled ? "Enabled" : "Disabled" } ` ) ;
289368 if ( mcpEnabled ) {
290369 console . log ( `MCP Transport: ${ mcpTransportType } ` ) ;
@@ -298,10 +377,6 @@ async function main() {
298377 `TestComponent Tool: ${ testComponentEnabled ? "Enabled" : "Disabled" } ` ,
299378 ) ;
300379
301- // Check pricing availability
302- const hasPricing = isPricingAvailable ( ) ;
303- console . log ( `Pricing Data: ${ hasPricing ? "Available" : "Not available (run 'bun run update-model-pricing' to download)" } ` ) ;
304-
305380 // Discover all tests
306381 console . log ( "\n📁 Discovering tests..." ) ;
307382 const tests = discoverTests ( ) ;
@@ -340,8 +415,7 @@ async function main() {
340415 }
341416 }
342417
343- // Load environment configuration and get model provider
344- const envConfig = loadEnvConfig ( ) ;
418+ // Get model provider
345419 const model = getModelProvider ( envConfig ) ;
346420
347421 // Run all tests
@@ -397,17 +471,31 @@ async function main() {
397471 `Total: ${ passed } passed, ${ failed } failed, ${ skipped } skipped (${ ( totalDuration / 1000 ) . toFixed ( 1 ) } s)` ,
398472 ) ;
399473
400- // Calculate total cost
401- const totalCost = calculateTotalCost ( testResults , envConfig . modelString ) ;
402- const pricingDisplay = getModelPricingDisplay ( envConfig . modelString ) ;
474+ // Calculate total cost if pricing is available
475+ let totalCost : TotalCostInfo | null = null ;
476+ let pricingInfo : PricingInfo | null = null ;
477+
478+ if ( pricingLookup ) {
479+ totalCost = calculateTotalCost ( testResults , pricingLookup . pricing ) ;
480+ const pricingDisplay = getModelPricingDisplay ( pricingLookup . pricing ) ;
481+ pricingInfo = {
482+ inputCostPerMTok : pricingDisplay . inputCostPerMTok ,
483+ outputCostPerMTok : pricingDisplay . outputCostPerMTok ,
484+ cacheReadCostPerMTok : pricingDisplay . cacheReadCostPerMTok ,
485+ } ;
403486
404- if ( totalCost ) {
405487 console . log ( "\n💰 Cost Summary" ) ;
406488 console . log ( "─" . repeat ( 50 ) ) ;
407- console . log ( `Input tokens: ${ totalCost . inputTokens . toLocaleString ( ) } (${ formatCost ( totalCost . inputCost ) } )` ) ;
408- console . log ( `Output tokens: ${ totalCost . outputTokens . toLocaleString ( ) } (${ formatCost ( totalCost . outputCost ) } )` ) ;
489+ console . log (
490+ `Input tokens: ${ totalCost . inputTokens . toLocaleString ( ) } (${ formatCost ( totalCost . inputCost ) } )` ,
491+ ) ;
492+ console . log (
493+ `Output tokens: ${ totalCost . outputTokens . toLocaleString ( ) } (${ formatCost ( totalCost . outputCost ) } )` ,
494+ ) ;
409495 if ( totalCost . cachedInputTokens > 0 ) {
410- console . log ( `Cached tokens: ${ totalCost . cachedInputTokens . toLocaleString ( ) } (${ formatCost ( totalCost . cacheReadCost ) } )` ) ;
496+ console . log (
497+ `Cached tokens: ${ totalCost . cachedInputTokens . toLocaleString ( ) } (${ formatCost ( totalCost . cacheReadCost ) } )` ,
498+ ) ;
411499 }
412500 console . log ( `Total cost: ${ formatCost ( totalCost . totalCost ) } ` ) ;
413501 }
@@ -424,15 +512,6 @@ async function main() {
424512 const jsonPath = `${ resultsDir } /${ jsonFilename } ` ;
425513 const htmlPath = `${ resultsDir } /${ htmlFilename } ` ;
426514
427- // Build pricing info for metadata
428- const pricing : PricingInfo | null = pricingDisplay
429- ? {
430- inputCostPerMTok : pricingDisplay . inputCostPerMTok ,
431- outputCostPerMTok : pricingDisplay . outputCostPerMTok ,
432- cacheReadCostPerMTok : pricingDisplay . cacheReadCostPerMTok ,
433- }
434- : null ;
435-
436515 // Build the result data
437516 const resultData : MultiTestResultData = {
438517 tests : testResults ,
@@ -442,7 +521,8 @@ async function main() {
442521 mcpTransportType : mcpEnabled ? mcpTransportType : null ,
443522 timestamp : new Date ( ) . toISOString ( ) ,
444523 model : envConfig . modelString ,
445- pricing,
524+ pricingKey : pricingLookup ?. matchedKey ?? null ,
525+ pricing : pricingInfo ,
446526 totalCost,
447527 } ,
448528 } ;
0 commit comments