diff --git a/src/app/components/event-tab/event-tab.component.html b/src/app/components/event-tab/event-tab.component.html index 9356b690..86fb92f5 100644 --- a/src/app/components/event-tab/event-tab.component.html +++ b/src/app/components/event-tab/event-tab.component.html @@ -229,6 +229,16 @@ } + @if (selectedEvent()?.cacheCreationTokenCount) { + + cacheCreationTokenCount + + + {{ selectedEvent()!.cacheCreationTokenCount | number }} + + + + } } @else { @@ -245,10 +255,28 @@ + @if (sessionUsageMetadata()['Cached Content Tokens'] > 0) { + + + + + } + @if (sessionUsageMetadata()['Cache Creation Tokens'] > 0) { + + + + + } + @if (sessionUsageMetadata()['Thoughts Tokens'] > 0) { + + + + + } diff --git a/src/app/components/event-tab/event-tab.component.ts b/src/app/components/event-tab/event-tab.component.ts index d3398c99..55386a95 100644 --- a/src/app/components/event-tab/event-tab.component.ts +++ b/src/app/components/event-tab/event-tab.component.ts @@ -190,6 +190,9 @@ export class EventTabComponent { const allEvents = Array.from(this.eventDataMap().values()); let totalPromptTokens = 0; let totalCandidatesTokens = 0; + let totalCachedContentTokens = 0; + let totalThoughtsTokens = 0; + let totalCacheCreationTokens = 0; let totalTokens = 0; allEvents.forEach(ev => { @@ -197,17 +200,30 @@ export class EventTabComponent { if (metadata) { const prompt = metadata.promptTokenCount ?? metadata.promptTokens ?? 0; const candidates = metadata.candidatesTokenCount ?? metadata.candidatesTokens ?? 0; + const cachedContent = metadata.cachedContentTokenCount ?? metadata.cachedContentTokens ?? 0; + const thoughts = metadata.thoughtsTokenCount ?? metadata.thoughtsTokens ?? 0; const total = metadata.totalTokenCount ?? metadata.totalTokens ?? 0; totalPromptTokens += Number(prompt); totalCandidatesTokens += Number(candidates); + totalCachedContentTokens += Number(cachedContent); + totalThoughtsTokens += Number(thoughts); totalTokens += Number(total); } + // Cache-write (creation) tokens live on the event itself, not in + // usageMetadata: google.genai's usage type forbids extra fields, so ADK + // surfaces them on the serializable event (alongside cacheMetadata) + // instead. Read/reasoning above are genuine usageMetadata fields. + const cacheCreation = ev.cacheCreationTokenCount ?? ev.cacheCreationTokens ?? 0; + totalCacheCreationTokens += Number(cacheCreation); }); return { 'Prompt Tokens': totalPromptTokens, 'Candidates Tokens': totalCandidatesTokens, + 'Cached Content Tokens': totalCachedContentTokens, + 'Cache Creation Tokens': totalCacheCreationTokens, + 'Thoughts Tokens': totalThoughtsTokens, 'Total Tokens': totalTokens }; }); diff --git a/src/app/core/models/types.ts b/src/app/core/models/types.ts index 95b89045..eb46698c 100644 --- a/src/app/core/models/types.ts +++ b/src/app/core/models/types.ts @@ -131,6 +131,10 @@ export declare interface Event extends LlmResponse { inputTranscription?: { text: string; }; outputTranscription?: { text: string; }; usageMetadata?: any; + // Prompt-cache write (creation) tokens. Serialized on the event itself + // rather than inside usageMetadata because google.genai's usage type + // forbids extra fields. + cacheCreationTokenCount?: number; interrupted?: boolean; turnComplete?: boolean; systemInstructionChanged?: boolean;
Total Prompt Tokens {{ sessionUsageMetadata()['Prompt Tokens'] | number }}
Total Cached Content Tokens{{ sessionUsageMetadata()['Cached Content Tokens'] | number }}
Total Cache Creation Tokens{{ sessionUsageMetadata()['Cache Creation Tokens'] | number }}
Total Candidates Tokens {{ sessionUsageMetadata()['Candidates Tokens'] | number }}
Total Thoughts Tokens{{ sessionUsageMetadata()['Thoughts Tokens'] | number }}
Total Tokens {{ sessionUsageMetadata()['Total Tokens'] | number }}