diff --git a/frontend/src/api/admin/usage.ts b/frontend/src/api/admin/usage.ts
index d933ac6351f..b37996d61a4 100644
--- a/frontend/src/api/admin/usage.ts
+++ b/frontend/src/api/admin/usage.ts
@@ -14,6 +14,8 @@ export interface AdminUsageStatsResponse {
total_input_tokens: number
total_output_tokens: number
total_cache_tokens: number
+ total_cache_creation_tokens: number
+ total_cache_read_tokens: number
total_tokens: number
total_cost: number
total_actual_cost: number
diff --git a/frontend/src/components/admin/usage/UsageStatsCards.vue b/frontend/src/components/admin/usage/UsageStatsCards.vue
index 905ece61a54..415c7cc186a 100644
--- a/frontend/src/components/admin/usage/UsageStatsCards.vue
+++ b/frontend/src/components/admin/usage/UsageStatsCards.vue
@@ -15,9 +15,46 @@
{{ t('usage.totalTokens') }}
{{ formatTokens(stats?.total_tokens || 0) }}
-
- {{ t('usage.in') }}: {{ formatTokens(stats?.total_input_tokens || 0) }} /
- {{ t('usage.out') }}: {{ formatTokens(stats?.total_output_tokens || 0) }}
+
+ {{ t('usage.in') }}: {{ formatTokens(stats?.total_input_tokens || 0) }}
+ /
+ {{ t('usage.out') }}: {{ formatTokens(stats?.total_output_tokens || 0) }}
+ /
+
+ {{ cacheLabel() }}: {{ formatTokens(stats?.total_cache_tokens || 0) }}
+
+
+
+ {{ cacheDetailLabel() }}
+
+
+ {{ t('usage.cacheCreationTokensLabel') }}
+
+ {{ formatTokens(stats?.total_cache_creation_tokens || 0) }}
+
+
+
+ {{ t('usage.cacheReadTokensLabel') }}
+
+ {{ formatTokens(stats?.total_cache_read_tokens || 0) }}
+
+
+
+
@@ -64,4 +101,7 @@ const formatTokens = (value: number) => {
if (value >= 1e3) return (value / 1e3).toFixed(2) + 'K'
return value.toLocaleString()
}
+
+const cacheLabel = () => t('usage.cacheTotal')
+const cacheDetailLabel = () => t('usage.cacheBreakdown')
diff --git a/frontend/src/components/admin/usage/__tests__/UsageStatsCards.spec.ts b/frontend/src/components/admin/usage/__tests__/UsageStatsCards.spec.ts
new file mode 100644
index 00000000000..c73dec0b137
--- /dev/null
+++ b/frontend/src/components/admin/usage/__tests__/UsageStatsCards.spec.ts
@@ -0,0 +1,67 @@
+import { describe, expect, it, vi } from 'vitest'
+import { mount } from '@vue/test-utils'
+
+import UsageStatsCards from '../UsageStatsCards.vue'
+
+const messages: Record = {
+ 'usage.totalRequests': 'Total Requests',
+ 'usage.inSelectedRange': 'in selected range',
+ 'usage.totalTokens': 'Total Tokens',
+ 'usage.in': 'In',
+ 'usage.out': 'Out',
+ 'usage.cacheTotal': 'Cache',
+ 'usage.cacheBreakdown': 'Cache Token Breakdown',
+ 'usage.cacheCreationTokensLabel': 'Cache Creation',
+ 'usage.cacheReadTokensLabel': 'Cache Read',
+ 'usage.totalCost': 'Total Cost',
+ 'usage.accountCost': 'Cost',
+ 'usage.standardCost': 'Standard',
+ 'usage.avgDuration': 'Avg Duration',
+}
+
+vi.mock('vue-i18n', async () => {
+ const actual = await vi.importActual('vue-i18n')
+ return {
+ ...actual,
+ useI18n: () => ({
+ t: (key: string) => messages[key] ?? key,
+ }),
+ }
+})
+
+const stats = {
+ total_requests: 1,
+ total_input_tokens: 100,
+ total_output_tokens: 50,
+ total_cache_tokens: 34,
+ total_cache_creation_tokens: 12,
+ total_cache_read_tokens: 22,
+ total_tokens: 184,
+ total_cost: 0.001,
+ total_actual_cost: 0.001,
+ total_account_cost: 0.001,
+ average_duration_ms: 250,
+}
+
+describe('UsageStatsCards', () => {
+ it('shows cache token breakdown values', () => {
+ const wrapper = mount(UsageStatsCards, {
+ props: {
+ stats,
+ },
+ global: {
+ stubs: {
+ Icon: true,
+ },
+ },
+ })
+
+ const text = wrapper.text()
+ expect(text).toContain('Cache: 34')
+ expect(text).toContain('Cache Token Breakdown')
+ expect(text).toContain('Cache Creation')
+ expect(text).toContain('12')
+ expect(text).toContain('Cache Read')
+ expect(text).toContain('22')
+ })
+})
diff --git a/frontend/src/i18n/locales/en.ts b/frontend/src/i18n/locales/en.ts
index c26d4d063c8..0ac93a98113 100644
--- a/frontend/src/i18n/locales/en.ts
+++ b/frontend/src/i18n/locales/en.ts
@@ -878,6 +878,10 @@ export default {
cacheTtlOverridden1h: 'Billed as 1h',
totalRequests: 'Total Requests',
totalTokens: 'Total Tokens',
+ cacheTotal: 'Cache',
+ cacheBreakdown: 'Cache Token Breakdown',
+ cacheCreationTokensLabel: 'Cache Creation',
+ cacheReadTokensLabel: 'Cache Read',
totalCost: 'Total Cost',
standardCost: 'Standard',
actualCost: 'Actual',
diff --git a/frontend/src/i18n/locales/zh.ts b/frontend/src/i18n/locales/zh.ts
index 0ce766f9f7e..ec9c51a1717 100644
--- a/frontend/src/i18n/locales/zh.ts
+++ b/frontend/src/i18n/locales/zh.ts
@@ -882,6 +882,10 @@ export default {
cacheTtlOverridden1h: '按 1h 计费',
totalRequests: '总请求数',
totalTokens: '总 Token',
+ cacheTotal: '缓存',
+ cacheBreakdown: '缓存 Token 明细',
+ cacheCreationTokensLabel: '缓存创建',
+ cacheReadTokensLabel: '缓存读取',
totalCost: '总消费',
standardCost: '标准',
actualCost: '实际',