feat(usage): include cache tokens in total token calculation and add tests

- Updated `TotalTokens` calculation to account for `CacheReadTokens` and `CacheCreationTokens`.
- Added tests to validate accurate token aggregation and fallback behavior for `CachedTokens`.
This commit is contained in:
Luis Pater
2026-05-28 21:34:54 +08:00
parent 2bcc76220c
commit 65e760aa1a
2 changed files with 35 additions and 1 deletions

View File

@@ -527,7 +527,7 @@ func parseClaudeUsageNode(usageNode gjson.Result) usage.Detail {
if detail.CachedTokens == 0 {
detail.CachedTokens = detail.CacheCreationTokens
}
detail.TotalTokens = detail.InputTokens + detail.OutputTokens
detail.TotalTokens = detail.InputTokens + detail.OutputTokens + detail.CacheReadTokens + detail.CacheCreationTokens
return detail
}

View File

@@ -89,6 +89,40 @@ func TestParseOpenAIStreamUsageResponsesFields(t *testing.T) {
}
}
func TestParseClaudeUsageIncludesCacheTokensInTotal(t *testing.T) {
data := []byte(`{"usage":{"input_tokens":3085,"output_tokens":253,"cache_read_input_tokens":7,"cache_creation_input_tokens":19514}}`)
detail := ParseClaudeUsage(data)
if detail.InputTokens != 3085 {
t.Fatalf("input tokens = %d, want %d", detail.InputTokens, 3085)
}
if detail.OutputTokens != 253 {
t.Fatalf("output tokens = %d, want %d", detail.OutputTokens, 253)
}
if detail.CacheReadTokens != 7 {
t.Fatalf("cache read tokens = %d, want %d", detail.CacheReadTokens, 7)
}
if detail.CacheCreationTokens != 19514 {
t.Fatalf("cache creation tokens = %d, want %d", detail.CacheCreationTokens, 19514)
}
if detail.CachedTokens != 7 {
t.Fatalf("cached tokens = %d, want %d", detail.CachedTokens, 7)
}
if detail.TotalTokens != 22859 {
t.Fatalf("total tokens = %d, want %d", detail.TotalTokens, 22859)
}
}
func TestParseClaudeUsageFallsBackCachedTokensToCacheCreation(t *testing.T) {
data := []byte(`{"usage":{"input_tokens":3085,"output_tokens":253,"cache_creation_input_tokens":19514}}`)
detail := ParseClaudeUsage(data)
if detail.CachedTokens != 19514 {
t.Fatalf("cached tokens = %d, want %d", detail.CachedTokens, 19514)
}
if detail.TotalTokens != 22852 {
t.Fatalf("total tokens = %d, want %d", detail.TotalTokens, 22852)
}
}
func TestParseGeminiCLIUsage_TopLevelUsageMetadata(t *testing.T) {
data := []byte(`{"usageMetadata":{"promptTokenCount":11,"candidatesTokenCount":7,"thoughtsTokenCount":3,"totalTokenCount":21,"cachedContentTokenCount":5}}`)
detail := ParseGeminiCLIUsage(data)