use crate::model_resolver::ModelResolver;
use crate::provider::Usage as ProviderUsage;
use vtcode_config::models::ModelPricing;
pub fn provider_reports_exclusive_input(provider: &str) -> bool {
matches!(provider.trim().to_ascii_lowercase().as_str(), "anthropic" | "minimax")
}
pub fn normalized_turn_usage(provider: &str, usage: &ProviderUsage) -> vtcode_exec_events::Usage {
let cached = u64::from(usage.cache_read_tokens_or_fallback());
let creation = u64::from(usage.cache_creation_tokens_or_zero());
let mut input = u64::from(usage.prompt_tokens);
if provider_reports_exclusive_input(provider) {
input = input.saturating_add(cached).saturating_add(creation);
}
let output = u64::from(usage.completion_tokens);
vtcode_exec_events::Usage {
input_tokens: input,
cached_input_tokens: cached,
cache_creation_tokens: creation,
output_tokens: output,
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct SessionCostEstimate {
pub raw_usd: f64,
pub effective_usd: f64,
}
pub fn estimate_session_costs(
provider: &str,
model: &str,
usage: &vtcode_exec_events::Usage,
) -> Option<SessionCostEstimate> {
let resolved = ModelResolver::resolve(Some(provider), model, &[], None)?;
let pricing = resolved.pricing()?;
estimate_session_costs_with_pricing(pricing, usage)
}
pub fn estimate_session_costs_with_pricing(
pricing: ModelPricing,
usage: &vtcode_exec_events::Usage,
) -> Option<SessionCostEstimate> {
let input_rate = pricing.input?;
let output_rate = pricing.output?;
let input_tokens = usage.input_tokens as f64;
let output_tokens = usage.output_tokens as f64;
let cached_tokens = usage.cached_input_tokens as f64;
let creation_tokens = usage.cache_creation_tokens as f64;
let raw_usd = input_tokens * input_rate + output_tokens * output_rate;
let read_rate = pricing.cache_read.unwrap_or(input_rate * 0.10);
let write_rate = pricing.cache_write.unwrap_or(input_rate * 1.25);
let uncached_tokens = usage
.input_tokens
.saturating_sub(usage.cached_input_tokens)
.saturating_sub(usage.cache_creation_tokens) as f64;
let effective_usd = uncached_tokens * input_rate
+ cached_tokens * read_rate
+ creation_tokens * write_rate
+ output_tokens * output_rate;
Some(SessionCostEstimate { raw_usd, effective_usd })
}