|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import React from 'react'; |
|
|
import { Box, Text } from 'ink'; |
|
|
import { Colors } from '../colors.js'; |
|
|
|
|
|
|
|
|
|
|
|
export interface FormattedStats { |
|
|
inputTokens: number; |
|
|
outputTokens: number; |
|
|
toolUseTokens: number; |
|
|
thoughtsTokens: number; |
|
|
cachedTokens: number; |
|
|
totalTokens: number; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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> |
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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()} |
|
|
/> |
|
|
{stats.toolUseTokens > 0 && ( |
|
|
<StatRow |
|
|
label="Tool Use Tokens" |
|
|
value={stats.toolUseTokens.toLocaleString()} |
|
|
/> |
|
|
)} |
|
|
<StatRow |
|
|
label="Thoughts Tokens" |
|
|
value={stats.thoughtsTokens.toLocaleString()} |
|
|
/> |
|
|
{stats.cachedTokens > 0 && ( |
|
|
<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> |
|
|
); |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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> |
|
|
); |
|
|
|