Files
gemini-cli/packages/cli/src/ui/contexts/SessionContext.tsx
Arya Gummadi 8f8082fe3d feat: add file change tracking to session metrics (#6094)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Jacob Richman <jacob314@gmail.com>
2025-08-19 05:57:53 +00:00

144 lines
3.0 KiB
TypeScript

/**
* @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,
sessionId,
} from '@google/gemini-cli-core';
// --- Interface Definitions ---
export type { SessionMetrics, ModelMetrics };
export interface SessionStatsState {
sessionId: string;
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;
totalLinesAdded: number;
totalLinesRemoved: 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<SessionStatsContextValue | undefined>(
undefined,
);
// --- Provider Component ---
export const SessionStatsProvider: React.FC<{ children: React.ReactNode }> = ({
children,
}) => {
const [stats, setStats] = useState<SessionStatsState>({
sessionId,
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 (
<SessionStatsContext.Provider value={value}>
{children}
</SessionStatsContext.Provider>
);
};
// --- Consumer Hook ---
export const useSessionStats = () => {
const context = useContext(SessionStatsContext);
if (context === undefined) {
throw new Error(
'useSessionStats must be used within a SessionStatsProvider',
);
}
return context;
};