From 770f862832dfef477705bee69bd2a84397d105a8 Mon Sep 17 00:00:00 2001
From: Abhi <43648792+abhipatel12@users.noreply.github.com>
Date: Sun, 29 Jun 2025 20:44:33 -0400
Subject: feat: Change /stats to include more detailed breakdowns (#2615)
---
.../cli/src/ui/components/ToolStatsDisplay.tsx | 208 +++++++++++++++++++++
1 file changed, 208 insertions(+)
create mode 100644 packages/cli/src/ui/components/ToolStatsDisplay.tsx
(limited to 'packages/cli/src/ui/components/ToolStatsDisplay.tsx')
diff --git a/packages/cli/src/ui/components/ToolStatsDisplay.tsx b/packages/cli/src/ui/components/ToolStatsDisplay.tsx
new file mode 100644
index 00000000..f2335d9e
--- /dev/null
+++ b/packages/cli/src/ui/components/ToolStatsDisplay.tsx
@@ -0,0 +1,208 @@
+/**
+ * @license
+ * Copyright 2025 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import React from 'react';
+import { Box, Text } from 'ink';
+import { Colors } from '../colors.js';
+import { formatDuration } from '../utils/formatters.js';
+import {
+ getStatusColor,
+ TOOL_SUCCESS_RATE_HIGH,
+ TOOL_SUCCESS_RATE_MEDIUM,
+ USER_AGREEMENT_RATE_HIGH,
+ USER_AGREEMENT_RATE_MEDIUM,
+} from '../utils/displayUtils.js';
+import { useSessionStats } from '../contexts/SessionContext.js';
+import { ToolCallStats } from '@google/gemini-cli-core';
+
+const TOOL_NAME_COL_WIDTH = 25;
+const CALLS_COL_WIDTH = 8;
+const SUCCESS_RATE_COL_WIDTH = 15;
+const AVG_DURATION_COL_WIDTH = 15;
+
+const StatRow: React.FC<{
+ name: string;
+ stats: ToolCallStats;
+}> = ({ name, stats }) => {
+ const successRate = stats.count > 0 ? (stats.success / stats.count) * 100 : 0;
+ const avgDuration = stats.count > 0 ? stats.durationMs / stats.count : 0;
+ const successColor = getStatusColor(successRate, {
+ green: TOOL_SUCCESS_RATE_HIGH,
+ yellow: TOOL_SUCCESS_RATE_MEDIUM,
+ });
+
+ return (
+
+
+ {name}
+
+
+ {stats.count}
+
+
+ {successRate.toFixed(1)}%
+
+
+ {formatDuration(avgDuration)}
+
+
+ );
+};
+
+export const ToolStatsDisplay: React.FC = () => {
+ const { stats } = useSessionStats();
+ const { tools } = stats.metrics;
+ const activeTools = Object.entries(tools.byName).filter(
+ ([, metrics]) => metrics.count > 0,
+ );
+
+ if (activeTools.length === 0) {
+ return (
+
+ No tool calls have been made in this session.
+
+ );
+ }
+
+ const totalDecisions = Object.values(tools.byName).reduce(
+ (acc, tool) => {
+ acc.accept += tool.decisions.accept;
+ acc.reject += tool.decisions.reject;
+ acc.modify += tool.decisions.modify;
+ return acc;
+ },
+ { accept: 0, reject: 0, modify: 0 },
+ );
+
+ const totalReviewed =
+ totalDecisions.accept + totalDecisions.reject + totalDecisions.modify;
+ const agreementRate =
+ totalReviewed > 0 ? (totalDecisions.accept / totalReviewed) * 100 : 0;
+ const agreementColor = getStatusColor(agreementRate, {
+ green: USER_AGREEMENT_RATE_HIGH,
+ yellow: USER_AGREEMENT_RATE_MEDIUM,
+ });
+
+ return (
+
+
+ Tool Stats For Nerds
+
+
+
+ {/* Header */}
+
+
+ Tool Name
+
+
+ Calls
+
+
+ Success Rate
+
+
+ Avg Duration
+
+
+
+ {/* Divider */}
+
+
+ {/* Tool Rows */}
+ {activeTools.map(([name, stats]) => (
+
+ ))}
+
+
+
+ {/* User Decision Summary */}
+ User Decision Summary
+
+
+ Total Reviewed Suggestions:
+
+
+ {totalReviewed}
+
+
+
+
+ » Accepted:
+
+
+ {totalDecisions.accept}
+
+
+
+
+ » Rejected:
+
+
+ {totalDecisions.reject}
+
+
+
+
+ » Modified:
+
+
+ {totalDecisions.modify}
+
+
+
+ {/* Divider */}
+
+
+
+
+ Overall Agreement Rate:
+
+
+ 0 ? agreementColor : undefined}>
+ {totalReviewed > 0 ? `${agreementRate.toFixed(1)}%` : '--'}
+
+
+
+
+ );
+};
--
cgit v1.2.3