summaryrefslogtreecommitdiff
path: root/packages/cli/src/ui/components/Stats.tsx
diff options
context:
space:
mode:
authorAbhi <[email protected]>2025-06-11 16:40:31 -0400
committerGitHub <[email protected]>2025-06-11 16:40:31 -0400
commit7a72d255d8effec1396170306cc6be57f598a6d8 (patch)
treeeab86a4d4d5f145a033eed06d16dedeba7b23a37 /packages/cli/src/ui/components/Stats.tsx
parent4160d904da8328eb7168b5b652d4c0f17682546c (diff)
feat: Add exit UI w/ stats (#924)
Diffstat (limited to 'packages/cli/src/ui/components/Stats.tsx')
-rw-r--r--packages/cli/src/ui/components/Stats.tsx114
1 files changed, 114 insertions, 0 deletions
diff --git a/packages/cli/src/ui/components/Stats.tsx b/packages/cli/src/ui/components/Stats.tsx
new file mode 100644
index 00000000..92fadd11
--- /dev/null
+++ b/packages/cli/src/ui/components/Stats.tsx
@@ -0,0 +1,114 @@
+/**
+ * @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';
+
+// --- Prop and Data Structures ---
+
+export interface FormattedStats {
+ inputTokens: number;
+ outputTokens: number;
+ toolUseTokens: number;
+ thoughtsTokens: number;
+ cachedTokens: number;
+ totalTokens: number;
+}
+
+// --- Helper Components ---
+
+/**
+ * Renders a single row with a colored label on the left and a value on the right.
+ */
+export const StatRow: React.FC<{
+ label: string;
+ value: string | number;
+ valueColor?: string;
+}> = ({ label, value, valueColor }) => (
+ <Box justifyContent="space-between" gap={2}>
+ <Text color={Colors.LightBlue}>{label}</Text>
+ <Text color={valueColor}>{value}</Text>
+ </Box>
+);
+
+/**
+ * Renders a full column for either "Last Turn" or "Cumulative" stats.
+ */
+export const StatsColumn: React.FC<{
+ title: string;
+ stats: FormattedStats;
+ isCumulative?: boolean;
+ width?: string | number;
+ children?: React.ReactNode;
+}> = ({ title, stats, isCumulative = false, width, children }) => {
+ const cachedDisplay =
+ isCumulative && stats.totalTokens > 0
+ ? `${stats.cachedTokens.toLocaleString()} (${((stats.cachedTokens / stats.totalTokens) * 100).toFixed(1)}%)`
+ : stats.cachedTokens.toLocaleString();
+
+ const cachedColor =
+ isCumulative && stats.cachedTokens > 0 ? Colors.AccentGreen : undefined;
+
+ return (
+ <Box flexDirection="column" width={width}>
+ <Text bold>{title}</Text>
+ <Box marginTop={1} flexDirection="column">
+ {/* All StatRows below will now inherit the gap */}
+ <StatRow
+ label="Input Tokens"
+ value={stats.inputTokens.toLocaleString()}
+ />
+ <StatRow
+ label="Output Tokens"
+ value={stats.outputTokens.toLocaleString()}
+ />
+ <StatRow
+ label="Tool Use Tokens"
+ value={stats.toolUseTokens.toLocaleString()}
+ />
+ <StatRow
+ label="Thoughts Tokens"
+ value={stats.thoughtsTokens.toLocaleString()}
+ />
+ <StatRow
+ label="Cached Tokens"
+ value={cachedDisplay}
+ valueColor={cachedColor}
+ />
+ {/* Divider Line */}
+ <Box
+ borderTop={true}
+ borderLeft={false}
+ borderRight={false}
+ borderBottom={false}
+ borderStyle="single"
+ />
+ <StatRow
+ label="Total Tokens"
+ value={stats.totalTokens.toLocaleString()}
+ />
+ {children}
+ </Box>
+ </Box>
+ );
+};
+
+/**
+ * Renders a column for displaying duration information.
+ */
+export const DurationColumn: React.FC<{
+ apiTime: string;
+ wallTime: string;
+}> = ({ apiTime, wallTime }) => (
+ <Box flexDirection="column" width={'48%'}>
+ <Text bold>Duration</Text>
+ <Box marginTop={1} flexDirection="column">
+ <StatRow label="API Time" value={apiTime} />
+ <StatRow label="Wall Time" value={wallTime} />
+ </Box>
+ </Box>
+);