/** * TokenUsage — Token 统计面板 * * 始终展示完整结构,无会话时显示零值。 * 固定在详情面板中部,高度由内容自然决定。 */ import { Box, Typography, Stack, Table, TableBody, TableRow, TableCell } from '@mui/material'; import { Zap } from 'lucide-react'; import { useAgentStore } from '@renderer/stores/agent-store'; import { formatTokens } from '@renderer/lib/formatters'; // v0.7.4 P3-1: 文案出层(字典含注册副作用,须在 t() 使用前 import) import { t } from '@renderer/lib/i18n'; import '@renderer/lib/i18n-strings'; export function TokenUsage(): React.JSX.Element { const tokenUsage = useAgentStore((s) => s.tokenUsage); const maxIterations = useAgentStore((s) => s.maxIterations); const currentIteration = useAgentStore((s) => s.currentIteration); const contextWindow = useAgentStore((s) => s.contextWindow); const maxTokens = contextWindow; // v0.3.18 修复: 上下文占用百分比改用 lastInputTokens(单次占用),而非累计 totalTokens // 之前 totalTokens 是所有轮次累加值,除以单次窗口得出无意义的百分比 const contextPercent = maxTokens > 0 && tokenUsage.lastInputTokens > 0 ? Math.min((tokenUsage.lastInputTokens / maxTokens) * 100, 100) : 0; // 累计消耗的输入/输出占比(用于进度条展示累计消耗的构成) const inputPercent = tokenUsage.totalTokens > 0 ? (tokenUsage.inputTokens / tokenUsage.totalTokens) * 100 : 0; return ( {/* 标题 */} {t('trace.token.usage')} {/* 进度条 */} {/* 数值卡片 */} {/* 底部汇总 */} {t('trace.token.total')} {tokenUsage.totalTokens > 0 ? formatTokens(tokenUsage.totalTokens) : '-'} {t('trace.token.context')} 80 ? 'error.main' : contextPercent > 60 ? 'warning.main' : 'text.secondary', }} > {tokenUsage.lastInputTokens > 0 ? `${formatTokens(tokenUsage.lastInputTokens)} (${contextPercent.toFixed(1)}%)` : '-'} {tokenUsage.lastCompressedSaved > 0 && ( {t('trace.token.compressedSaved')} {formatTokens(tokenUsage.lastCompressedSaved)} )} 迭代 {currentIteration} / {maxIterations}
); } function StatCard({ label, value, color }: { label: string; value: string; color: string }) { return ( {label} {value} ); }