diff --git a/ui/src/lib/cost-reporting.test.ts b/ui/src/lib/cost-reporting.test.ts index f4f46c0817e..58f78c1c9e6 100644 --- a/ui/src/lib/cost-reporting.test.ts +++ b/ui/src/lib/cost-reporting.test.ts @@ -19,6 +19,14 @@ describe("cost presentation", () => { expect(visibleRunCostUsd({ billingType: "subscription_included", costUsd: 50 })).toBe(0); }); + it("includes separate legacy Claude cache reads without changing legacy Codex totals", () => { + const tokens = { inputTokens: 100, cachedInputTokens: 80, outputTokens: 10 }; + expect(visibleRunTokenTotal({ ...tokens, provider: "anthropic" })).toBe(190); + expect(visibleRunTokenTotal({ ...tokens, provider: "openai" })).toBe(110); + expect(visibleRunTokenTotal({ ...tokens, provider: "anthropic", accountingReceiptId: "saved-receipt" })).toBe(190); + expect(visibleRunTokenTotal({ provider: "anthropic", input_tokens: 100, cache_read_input_tokens: 80, output_tokens: 10 })).toBe(190); + }); + it("formats finance amounts in their recorded currency", () => { expect(formatCents(123, "USD")).toBe("$1.23"); expect(formatCents(123, "EUR")).toBe("€1.23"); diff --git a/ui/src/lib/utils.ts b/ui/src/lib/utils.ts index 02c1ab32bf8..37dc38eaf4d 100644 --- a/ui/src/lib/utils.ts +++ b/ui/src/lib/utils.ts @@ -179,8 +179,9 @@ function readRunCostUsd(payload: Record | null): number | null return null; } -/** Receipt-backed runs store uncached input separately. Older run snapshots - * retain their original input total (Codex included cached input in it). */ +/** Receipt-backed runs and legacy Claude snapshots store uncached input + * separately. Older Codex input already includes its cached tokens. Unknown + * legacy formats retain their original input-plus-output interpretation. */ export function visibleRunTokenTotal(usage: Record | null | undefined): number { const count = (...keys: string[]) => { for (const key of keys) { @@ -192,7 +193,9 @@ export function visibleRunTokenTotal(usage: Record | null | und const input = count("inputTokens", "input_tokens"); const output = count("outputTokens", "output_tokens"); const cached = count("cachedInputTokens", "cached_input_tokens", "cache_read_input_tokens"); - return input + output + (typeof usage?.accountingReceiptId === "string" && usage.accountingReceiptId.length > 0 ? cached : 0); + const inputExcludesCached = usage?.provider === "anthropic" + || (typeof usage?.accountingReceiptId === "string" && usage.accountingReceiptId.length > 0); + return input + output + (inputExcludesCached ? cached : 0); } export function visibleRunCostUsd(