fix: more accurate cost tracking hopefully

This commit is contained in:
2026-02-06 10:13:19 -08:00
parent c471c7ad3d
commit e8e9f5c79c
+57 -45
View File
@@ -717,60 +717,72 @@ fn process_json_line(
// Only update stats if we have usage information // Only update stats if we have usage information
if let Some(usage) = &message.usage { if let Some(usage) = &message.usage {
if let Some(model) = &message.model { // Get model from message, or fall back to last known model from stats
// Calculate cost for historical tracking (including cache tokens) let model = message.model.clone().or_else(|| {
let cost_usd = calculate_cost( let stats_guard = stats.read();
stats_guard.model.clone()
}).unwrap_or_else(|| {
println!("[WARNING] No model info available for cost calculation, using default");
"claude-sonnet-4-5-20250929".to_string()
});
// Calculate cost for historical tracking (including cache tokens)
let cost_usd = calculate_cost(
usage.input_tokens,
usage.output_tokens,
&model,
usage.cache_creation_input_tokens,
usage.cache_read_input_tokens,
);
println!("Assistant message tokens - input: {}, output: {}, cache_creation: {:?}, cache_read: {:?}, cost: ${:.4}",
usage.input_tokens,
usage.output_tokens,
usage.cache_creation_input_tokens,
usage.cache_read_input_tokens,
cost_usd
);
// Store cost for later use in output events
message_cost = Some(MessageCost {
input_tokens: usage.input_tokens,
output_tokens: usage.output_tokens,
cost_usd,
});
// Batch all stats updates in a single write lock
{
let mut stats_guard = stats.write();
stats_guard.increment_messages();
stats_guard.add_usage(
usage.input_tokens, usage.input_tokens,
usage.output_tokens, usage.output_tokens,
model, &model,
usage.cache_creation_input_tokens, usage.cache_creation_input_tokens,
usage.cache_read_input_tokens, usage.cache_read_input_tokens,
); );
stats_guard.get_session_duration();
// Store cost for later use in output events // Attribute tokens to tools if any tools were used in this message
message_cost = Some(MessageCost { if !tools_in_message.is_empty() {
input_tokens: usage.input_tokens, let per_tool_input = usage.input_tokens / tools_in_message.len() as u64;
output_tokens: usage.output_tokens, let per_tool_output = usage.output_tokens / tools_in_message.len() as u64;
cost_usd, for tool in &tools_in_message {
}); stats_guard.add_tool_tokens(tool, per_tool_input, per_tool_output);
// Batch all stats updates in a single write lock
{
let mut stats_guard = stats.write();
stats_guard.increment_messages();
stats_guard.add_usage(
usage.input_tokens,
usage.output_tokens,
model,
usage.cache_creation_input_tokens,
usage.cache_read_input_tokens,
);
stats_guard.get_session_duration();
// Attribute tokens to tools if any tools were used in this message
if !tools_in_message.is_empty() {
let per_tool_input = usage.input_tokens / tools_in_message.len() as u64;
let per_tool_output = usage.output_tokens / tools_in_message.len() as u64;
for tool in &tools_in_message {
stats_guard.add_tool_tokens(tool, per_tool_input, per_tool_output);
}
} }
} }
// Record to historical cost tracking
let app_clone = app.clone();
let input = usage.input_tokens;
let output = usage.output_tokens;
tauri::async_runtime::spawn(async move {
record_cost(&app_clone, input, output, cost_usd).await;
});
// Don't emit here - we'll emit on Result message instead
// This reduces the frequency of updates
} else {
// Just increment message count if no usage info
stats.write().increment_messages();
} }
// Record to historical cost tracking
let app_clone = app.clone();
let input = usage.input_tokens;
let output = usage.output_tokens;
tauri::async_runtime::spawn(async move {
record_cost(&app_clone, input, output, cost_usd).await;
});
// Don't emit here - we'll emit on Result message instead
// This reduces the frequency of updates
} else { } else {
// Just increment message count if no usage info // Just increment message count if no usage info
stats.write().increment_messages(); stats.write().increment_messages();