From 1c7bbd3f15bebb76372835b28e1ed600465e8fe6 Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Tue, 10 Mar 2026 11:39:31 -0300 Subject: [PATCH] fix: round cost fields to 5 decimal places for cents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ensures consistent precision in pricing data across all provider scripts by rounding cost values to 5 decimal places. 💘 Generated with Crush Assisted-by: GLM-5 via Crush --- cmd/aihubmix/main.go | 7 ++++++- cmd/huggingface/main.go | 5 +++-- cmd/ionet/main.go | 10 ++++++---- cmd/openrouter/main.go | 21 +++++++++++++-------- cmd/synthetic/main.go | 13 +++++++++---- cmd/venice/main.go | 5 +++-- cmd/vercel/main.go | 10 ++++++---- 7 files changed, 46 insertions(+), 25 deletions(-) diff --git a/cmd/aihubmix/main.go b/cmd/aihubmix/main.go index 87535250bfa85ed62c88e671c3096ae3ff4dfb7a..14b73c504982d5ddb0bfd4802086b37924f55cf0 100644 --- a/cmd/aihubmix/main.go +++ b/cmd/aihubmix/main.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "log" + "math" "net/http" "os" "slices" @@ -95,11 +96,15 @@ func hasField(s, field string) bool { return false } +func roundCost(v float64) float64 { + return math.Round(v*1e5) / 1e5 +} + func parseFloat(p *float64) float64 { if p == nil { return 0 } - return *p + return roundCost(*p) } func calculateMaxTokens(contextLength, maxOutput, factor int64) int64 { diff --git a/cmd/huggingface/main.go b/cmd/huggingface/main.go index e1ea4186cb965254cd59698437c8e9d55f3ecca8..74032f96851c010d3cdb29e38eb1a9c5018ee5e6 100644 --- a/cmd/huggingface/main.go +++ b/cmd/huggingface/main.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "log" + "math" "net/http" "os" "slices" @@ -159,8 +160,8 @@ func main() { // Calculate pricing (convert from per-token to per-1M tokens) var costPer1MIn, costPer1MOut float64 if provider.Pricing != nil { - costPer1MIn = provider.Pricing.Input - costPer1MOut = provider.Pricing.Output + costPer1MIn = math.Round(provider.Pricing.Input*1e5) / 1e5 + costPer1MOut = math.Round(provider.Pricing.Output*1e5) / 1e5 } // Set default max tokens (conservative estimate) diff --git a/cmd/ionet/main.go b/cmd/ionet/main.go index 1f490c9da34ee21f5bf8093365014ff5a850c786..67c51bcf3e62fdd5f849dbd761fcb4549b01afbf 100644 --- a/cmd/ionet/main.go +++ b/cmd/ionet/main.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "log" + "math" "net/http" "os" "slices" @@ -79,10 +80,11 @@ func main() { } // Convert token prices (per token) to cost per 1M tokens - costPer1MIn := model.InputTokenPrice * 1_000_000 - costPer1MOut := model.OutputTokenPrice * 1_000_000 - costPer1MInCached := model.CacheReadTokenPrice * 1_000_000 - costPer1MOutCached := model.CacheWriteTokenPrice * 1_000_000 + roundCost := func(v float64) float64 { return math.Round(v*1e5) / 1e5 } + costPer1MIn := roundCost(model.InputTokenPrice * 1_000_000) + costPer1MOut := roundCost(model.OutputTokenPrice * 1_000_000) + costPer1MInCached := roundCost(model.CacheReadTokenPrice * 1_000_000) + costPer1MOutCached := roundCost(model.CacheWriteTokenPrice * 1_000_000) m := catwalk.Model{ ID: model.ID, diff --git a/cmd/openrouter/main.go b/cmd/openrouter/main.go index 792b23f51497bd5133dc47d4ba9155ab03521276..6c07567ceb96b3a93d5995af39b13dd4e78be7c3 100644 --- a/cmd/openrouter/main.go +++ b/cmd/openrouter/main.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "log" + "math" "net/http" "os" "slices" @@ -101,29 +102,33 @@ type ModelPricing struct { CostPer1MOutCached float64 `json:"cost_per_1m_out_cached"` } +func roundCost(v float64) float64 { + return math.Round(v*1e5) / 1e5 +} + func getPricing(model Model) ModelPricing { pricing := ModelPricing{} costPrompt, err := strconv.ParseFloat(model.Pricing.Prompt, 64) if err != nil { costPrompt = 0.0 } - pricing.CostPer1MIn = costPrompt * 1_000_000 + pricing.CostPer1MIn = roundCost(costPrompt * 1_000_000) costCompletion, err := strconv.ParseFloat(model.Pricing.Completion, 64) if err != nil { costCompletion = 0.0 } - pricing.CostPer1MOut = costCompletion * 1_000_000 + pricing.CostPer1MOut = roundCost(costCompletion * 1_000_000) costPromptCached, err := strconv.ParseFloat(model.Pricing.InputCacheWrite, 64) if err != nil { costPromptCached = 0.0 } - pricing.CostPer1MInCached = costPromptCached * 1_000_000 + pricing.CostPer1MInCached = roundCost(costPromptCached * 1_000_000) costCompletionCached, err := strconv.ParseFloat(model.Pricing.InputCacheRead, 64) if err != nil { costCompletionCached = 0.0 } - pricing.CostPer1MOutCached = costCompletionCached * 1_000_000 + pricing.CostPer1MOutCached = roundCost(costCompletionCached * 1_000_000) return pricing } @@ -334,23 +339,23 @@ func main() { if err != nil { costPrompt = 0.0 } - pricing.CostPer1MIn = costPrompt * 1_000_000 + pricing.CostPer1MIn = roundCost(costPrompt * 1_000_000) costCompletion, err := strconv.ParseFloat(bestEndpoint.Pricing.Completion, 64) if err != nil { costCompletion = 0.0 } - pricing.CostPer1MOut = costCompletion * 1_000_000 + pricing.CostPer1MOut = roundCost(costCompletion * 1_000_000) costPromptCached, err := strconv.ParseFloat(bestEndpoint.Pricing.InputCacheWrite, 64) if err != nil { costPromptCached = 0.0 } - pricing.CostPer1MInCached = costPromptCached * 1_000_000 + pricing.CostPer1MInCached = roundCost(costPromptCached * 1_000_000) costCompletionCached, err := strconv.ParseFloat(bestEndpoint.Pricing.InputCacheRead, 64) if err != nil { costCompletionCached = 0.0 } - pricing.CostPer1MOutCached = costCompletionCached * 1_000_000 + pricing.CostPer1MOutCached = roundCost(costCompletionCached * 1_000_000) canReason := slices.Contains(bestEndpoint.SupportedParams, "reasoning") supportsImages := slices.Contains(model.Architecture.InputModalities, "image") diff --git a/cmd/synthetic/main.go b/cmd/synthetic/main.go index 2c6256c6d45ce2036db18d338b874ff8ea8878b5..7b8f872475a1f5dfae469423ac60962695c2105e 100644 --- a/cmd/synthetic/main.go +++ b/cmd/synthetic/main.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "log" + "math" "net/http" "os" "slices" @@ -64,12 +65,16 @@ func parsePrice(s string) float64 { return v } +func roundCost(v float64) float64 { + return math.Round(v*1e5) / 1e5 +} + func getPricing(model Model) ModelPricing { return ModelPricing{ - CostPer1MIn: parsePrice(model.Pricing.Prompt) * 1_000_000, - CostPer1MOut: parsePrice(model.Pricing.Completion) * 1_000_000, - CostPer1MInCached: parsePrice(model.Pricing.InputCacheReads) * 1_000_000, - CostPer1MOutCached: parsePrice(model.Pricing.InputCacheReads) * 1_000_000, + CostPer1MIn: roundCost(parsePrice(model.Pricing.Prompt) * 1_000_000), + CostPer1MOut: roundCost(parsePrice(model.Pricing.Completion) * 1_000_000), + CostPer1MInCached: roundCost(parsePrice(model.Pricing.InputCacheReads) * 1_000_000), + CostPer1MOutCached: roundCost(parsePrice(model.Pricing.InputCacheReads) * 1_000_000), } } diff --git a/cmd/venice/main.go b/cmd/venice/main.go index d875bcd07452b64bbf4388544593f5397c467f8f..c37a0add90731a2937c5c87c38b5e8917e882847 100644 --- a/cmd/venice/main.go +++ b/cmd/venice/main.go @@ -225,11 +225,12 @@ func main() { } } + roundCost := func(v float64) float64 { return math.Round(v*1e5) / 1e5 } m := catwalk.Model{ ID: model.ID, Name: model.ModelSpec.Name, - CostPer1MIn: model.ModelSpec.Pricing.Input.USD, - CostPer1MOut: model.ModelSpec.Pricing.Output.USD, + CostPer1MIn: roundCost(model.ModelSpec.Pricing.Input.USD), + CostPer1MOut: roundCost(model.ModelSpec.Pricing.Output.USD), CostPer1MInCached: 0, CostPer1MOutCached: 0, ContextWindow: contextWindow, diff --git a/cmd/vercel/main.go b/cmd/vercel/main.go index 26b7268d8d98d03c6adb763af601fab3f00a04ab..86bc8a32cee02a1f597e10d3f0a362a8d82e00ff 100644 --- a/cmd/vercel/main.go +++ b/cmd/vercel/main.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "log" + "math" "net/http" "os" "slices" @@ -107,6 +108,7 @@ func main() { } // Parse pricing + roundCost := func(v float64) float64 { return math.Round(v*1e5) / 1e5 } costPer1MIn := 0.0 costPer1MOut := 0.0 costPer1MInCached := 0.0 @@ -115,28 +117,28 @@ func main() { if model.Pricing.Input != "" { costPrompt, err := strconv.ParseFloat(model.Pricing.Input, 64) if err == nil { - costPer1MIn = costPrompt * 1_000_000 + costPer1MIn = roundCost(costPrompt * 1_000_000) } } if model.Pricing.Output != "" { costCompletion, err := strconv.ParseFloat(model.Pricing.Output, 64) if err == nil { - costPer1MOut = costCompletion * 1_000_000 + costPer1MOut = roundCost(costCompletion * 1_000_000) } } if model.Pricing.InputCacheRead != "" { costCached, err := strconv.ParseFloat(model.Pricing.InputCacheRead, 64) if err == nil { - costPer1MInCached = costCached * 1_000_000 + costPer1MInCached = roundCost(costCached * 1_000_000) } } if model.Pricing.InputCacheWrite != "" { costCacheWrite, err := strconv.ParseFloat(model.Pricing.InputCacheWrite, 64) if err == nil { - costPer1MOutCached = costCacheWrite * 1_000_000 + costPer1MOutCached = roundCost(costCacheWrite * 1_000_000) } }