generated from nhcarrigan/template
fix: more accurate cost tracking hopefully
This commit is contained in:
+57
-45
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user