mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-29 06:25:16 -07:00
refactor(ui): Optimize rendering performance (#8239)
This commit is contained in:
@@ -14,10 +14,129 @@ import {
|
||||
useEffect,
|
||||
} from 'react';
|
||||
|
||||
import type { SessionMetrics, ModelMetrics } from '@google/gemini-cli-core';
|
||||
import type {
|
||||
SessionMetrics,
|
||||
ModelMetrics,
|
||||
ToolCallStats,
|
||||
} from '@google/gemini-cli-core';
|
||||
import { uiTelemetryService, sessionId } from '@google/gemini-cli-core';
|
||||
|
||||
// --- Interface Definitions ---
|
||||
export enum ToolCallDecision {
|
||||
ACCEPT = 'accept',
|
||||
REJECT = 'reject',
|
||||
MODIFY = 'modify',
|
||||
AUTO_ACCEPT = 'auto_accept',
|
||||
}
|
||||
|
||||
function areModelMetricsEqual(a: ModelMetrics, b: ModelMetrics): boolean {
|
||||
if (
|
||||
a.api.totalRequests !== b.api.totalRequests ||
|
||||
a.api.totalErrors !== b.api.totalErrors ||
|
||||
a.api.totalLatencyMs !== b.api.totalLatencyMs
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
a.tokens.prompt !== b.tokens.prompt ||
|
||||
a.tokens.candidates !== b.tokens.candidates ||
|
||||
a.tokens.total !== b.tokens.total ||
|
||||
a.tokens.cached !== b.tokens.cached ||
|
||||
a.tokens.thoughts !== b.tokens.thoughts ||
|
||||
a.tokens.tool !== b.tokens.tool
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function areToolCallStatsEqual(a: ToolCallStats, b: ToolCallStats): boolean {
|
||||
if (
|
||||
a.count !== b.count ||
|
||||
a.success !== b.success ||
|
||||
a.fail !== b.fail ||
|
||||
a.durationMs !== b.durationMs
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
a.decisions[ToolCallDecision.ACCEPT] !==
|
||||
b.decisions[ToolCallDecision.ACCEPT] ||
|
||||
a.decisions[ToolCallDecision.REJECT] !==
|
||||
b.decisions[ToolCallDecision.REJECT] ||
|
||||
a.decisions[ToolCallDecision.MODIFY] !==
|
||||
b.decisions[ToolCallDecision.MODIFY] ||
|
||||
a.decisions[ToolCallDecision.AUTO_ACCEPT] !==
|
||||
b.decisions[ToolCallDecision.AUTO_ACCEPT]
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function areMetricsEqual(a: SessionMetrics, b: SessionMetrics): boolean {
|
||||
if (a === b) return true;
|
||||
if (!a || !b) return false;
|
||||
|
||||
// Compare files
|
||||
if (
|
||||
a.files.totalLinesAdded !== b.files.totalLinesAdded ||
|
||||
a.files.totalLinesRemoved !== b.files.totalLinesRemoved
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare tools
|
||||
const toolsA = a.tools;
|
||||
const toolsB = b.tools;
|
||||
if (
|
||||
toolsA.totalCalls !== toolsB.totalCalls ||
|
||||
toolsA.totalSuccess !== toolsB.totalSuccess ||
|
||||
toolsA.totalFail !== toolsB.totalFail ||
|
||||
toolsA.totalDurationMs !== toolsB.totalDurationMs
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare tool decisions
|
||||
if (
|
||||
toolsA.totalDecisions[ToolCallDecision.ACCEPT] !==
|
||||
toolsB.totalDecisions[ToolCallDecision.ACCEPT] ||
|
||||
toolsA.totalDecisions[ToolCallDecision.REJECT] !==
|
||||
toolsB.totalDecisions[ToolCallDecision.REJECT] ||
|
||||
toolsA.totalDecisions[ToolCallDecision.MODIFY] !==
|
||||
toolsB.totalDecisions[ToolCallDecision.MODIFY] ||
|
||||
toolsA.totalDecisions[ToolCallDecision.AUTO_ACCEPT] !==
|
||||
toolsB.totalDecisions[ToolCallDecision.AUTO_ACCEPT]
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare tools.byName
|
||||
const toolsByNameAKeys = Object.keys(toolsA.byName);
|
||||
const toolsByNameBKeys = Object.keys(toolsB.byName);
|
||||
if (toolsByNameAKeys.length !== toolsByNameBKeys.length) return false;
|
||||
|
||||
for (const key of toolsByNameAKeys) {
|
||||
const toolA = toolsA.byName[key];
|
||||
const toolB = toolsB.byName[key];
|
||||
if (!toolB || !areToolCallStatsEqual(toolA, toolB)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Compare models
|
||||
const modelsAKeys = Object.keys(a.models);
|
||||
const modelsBKeys = Object.keys(b.models);
|
||||
if (modelsAKeys.length !== modelsBKeys.length) return false;
|
||||
|
||||
for (const key of modelsAKeys) {
|
||||
if (!b.models[key] || !areModelMetricsEqual(a.models[key], b.models[key])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export type { SessionMetrics, ModelMetrics };
|
||||
|
||||
@@ -80,11 +199,19 @@ export const SessionStatsProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
metrics: SessionMetrics;
|
||||
lastPromptTokenCount: number;
|
||||
}) => {
|
||||
setStats((prevState) => ({
|
||||
...prevState,
|
||||
metrics,
|
||||
lastPromptTokenCount,
|
||||
}));
|
||||
setStats((prevState) => {
|
||||
if (
|
||||
prevState.lastPromptTokenCount === lastPromptTokenCount &&
|
||||
areMetricsEqual(prevState.metrics, metrics)
|
||||
) {
|
||||
return prevState;
|
||||
}
|
||||
return {
|
||||
...prevState,
|
||||
metrics,
|
||||
lastPromptTokenCount,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
uiTelemetryService.on('update', handleUpdate);
|
||||
|
||||
Reference in New Issue
Block a user