/** * @license * Copyright 2025 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import React, { createContext, useCallback, useContext, useState, useMemo, useEffect, } from 'react'; import { uiTelemetryService, SessionMetrics, ModelMetrics, } from '@google/gemini-cli-core'; // --- Interface Definitions --- export type { SessionMetrics, ModelMetrics }; export interface SessionStatsState { sessionStartTime: Date; metrics: SessionMetrics; lastPromptTokenCount: number; promptCount: number; } export interface ComputedSessionStats { totalApiTime: number; totalToolTime: number; agentActiveTime: number; apiTimePercent: number; toolTimePercent: number; cacheEfficiency: number; totalDecisions: number; successRate: number; agreementRate: number; totalCachedTokens: number; totalPromptTokens: number; } // Defines the final "value" of our context, including the state // and the functions to update it. interface SessionStatsContextValue { stats: SessionStatsState; startNewPrompt: () => void; getPromptCount: () => number; } // --- Context Definition --- const SessionStatsContext = createContext( undefined, ); // --- Provider Component --- export const SessionStatsProvider: React.FC<{ children: React.ReactNode }> = ({ children, }) => { const [stats, setStats] = useState({ sessionStartTime: new Date(), metrics: uiTelemetryService.getMetrics(), lastPromptTokenCount: 0, promptCount: 0, }); useEffect(() => { const handleUpdate = ({ metrics, lastPromptTokenCount, }: { metrics: SessionMetrics; lastPromptTokenCount: number; }) => { setStats((prevState) => ({ ...prevState, metrics, lastPromptTokenCount, })); }; uiTelemetryService.on('update', handleUpdate); // Set initial state handleUpdate({ metrics: uiTelemetryService.getMetrics(), lastPromptTokenCount: uiTelemetryService.getLastPromptTokenCount(), }); return () => { uiTelemetryService.off('update', handleUpdate); }; }, []); const startNewPrompt = useCallback(() => { setStats((prevState) => ({ ...prevState, promptCount: prevState.promptCount + 1, })); }, []); const getPromptCount = useCallback( () => stats.promptCount, [stats.promptCount], ); const value = useMemo( () => ({ stats, startNewPrompt, getPromptCount, }), [stats, startNewPrompt, getPromptCount], ); return ( {children} ); }; // --- Consumer Hook --- export const useSessionStats = () => { const context = useContext(SessionStatsContext); if (context === undefined) { throw new Error( 'useSessionStats must be used within a SessionStatsProvider', ); } return context; };