@@ -21,9 +21,9 @@ func TestDecodeNewUsageQueueFields(t *testing.T) {
2121 "failed":true,
2222 "fail":{"status_code":429,"body":" rate limited "},
2323 "response_headers":{"Retry-After":["30"],"X-Upstream-Request-Id":["upstream-req-1"]},
24- "provider":"openai ",
25- "model":"gpt-5. 4",
26- "alias":"client-gpt ",
24+ "provider":"claude ",
25+ "model":"claude-sonnet- 4",
26+ "alias":"client-claude ",
2727 "endpoint":"POST /v1/chat/completions",
2828 "auth_type":"apikey",
2929 "api_key":"test-key",
@@ -39,7 +39,7 @@ func TestDecodeNewUsageQueueFields(t *testing.T) {
3939 if ev .EventKey != "ctx-request-id" || ev .RequestID != "ctx-request-id" {
4040 t .Fatalf ("request ids = event_key %q request_id %q" , ev .EventKey , ev .RequestID )
4141 }
42- if ev .Alias != "client-gpt " || ev .TTFTMs != 320 {
42+ if ev .Alias != "client-claude " || ev .TTFTMs != 320 {
4343 t .Fatalf ("alias/ttft = %q/%d" , ev .Alias , ev .TTFTMs )
4444 }
4545 if ev .CacheReadTokens != 4 || ev .CacheCreationTokens != 5 {
@@ -55,3 +55,63 @@ func TestDecodeNewUsageQueueFields(t *testing.T) {
5555 t .Fatalf ("reasoning/service tier = %q/%q" , ev .ReasoningEffort , ev .ServiceTier )
5656 }
5757}
58+
59+ func TestDecodeNormalizesTotalInputStyleCacheTokens (t * testing.T ) {
60+ raw := `{
61+ "timestamp":"2026-04-25T00:00:00Z",
62+ "provider":"openai",
63+ "model":"gpt-5",
64+ "request_id":"req-openai-cache",
65+ "tokens":{
66+ "input_tokens":1000,
67+ "output_tokens":50,
68+ "cached_tokens":900,
69+ "total_tokens":1050
70+ }
71+ }`
72+
73+ ev , err := Decode (raw )
74+ if err != nil {
75+ t .Fatalf ("Decode: %v" , err )
76+ }
77+ if ev .InputTokens != 100 {
78+ t .Fatalf ("input/new tokens = %d, want 100" , ev .InputTokens )
79+ }
80+ if ev .CachedTokens != 900 || ev .CacheReadTokens != 900 || ev .CacheCreationTokens != 0 {
81+ t .Fatalf ("cache split = cached %d read %d write %d, want 900/900/0" , ev .CachedTokens , ev .CacheReadTokens , ev .CacheCreationTokens )
82+ }
83+ if ev .TotalTokens != 1050 {
84+ t .Fatalf ("total tokens = %d, want preserved 1050" , ev .TotalTokens )
85+ }
86+ }
87+
88+ func TestDecodePreservesClaudeInputAndUsesExplicitCacheRead (t * testing.T ) {
89+ raw := `{
90+ "timestamp":"2026-04-25T00:00:00Z",
91+ "provider":"claude",
92+ "model":"claude-sonnet-4",
93+ "request_id":"req-claude-cache",
94+ "tokens":{
95+ "input_tokens":100,
96+ "output_tokens":50,
97+ "cached_tokens":900,
98+ "cache_read_tokens":0,
99+ "cache_creation_tokens":900,
100+ "total_tokens":1050
101+ }
102+ }`
103+
104+ ev , err := Decode (raw )
105+ if err != nil {
106+ t .Fatalf ("Decode: %v" , err )
107+ }
108+ if ev .InputTokens != 100 {
109+ t .Fatalf ("input/new tokens = %d, want 100" , ev .InputTokens )
110+ }
111+ if ev .CachedTokens != 0 || ev .CacheReadTokens != 0 || ev .CacheCreationTokens != 900 {
112+ t .Fatalf ("cache split = cached %d read %d write %d, want 0/0/900" , ev .CachedTokens , ev .CacheReadTokens , ev .CacheCreationTokens )
113+ }
114+ if ev .TotalTokens != 1050 {
115+ t .Fatalf ("total tokens = %d, want preserved 1050" , ev .TotalTokens )
116+ }
117+ }
0 commit comments