Show token stats for each image

This commit is contained in:
Nicolas Mowen 2026-05-14 09:36:26 -06:00
parent ee20bd9930
commit 8f07a81ac3

View File

@ -17,6 +17,7 @@ import {
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { ChatAttachmentChip } from "@/components/chat/ChatAttachmentChip"; import { ChatAttachmentChip } from "@/components/chat/ChatAttachmentChip";
import { parseAttachedEvent } from "@/utils/chatUtil"; import { parseAttachedEvent } from "@/utils/chatUtil";
import type { ChatStats, ShowStatsMode } from "@/types/chat";
type MessageBubbleProps = { type MessageBubbleProps = {
role: "user" | "assistant"; role: "user" | "assistant";
@ -24,14 +25,29 @@ type MessageBubbleProps = {
messageIndex?: number; messageIndex?: number;
onEditSubmit?: (messageIndex: number, newContent: string) => void; onEditSubmit?: (messageIndex: number, newContent: string) => void;
isComplete?: boolean; isComplete?: boolean;
stats?: ChatStats;
showStats?: ShowStatsMode;
}; };
function formatTokens(n: number | undefined): string | null {
if (n === undefined) return null;
if (n >= 1000) return `${(n / 1000).toFixed(1)}k`;
return String(n);
}
function formatRate(rate: number | undefined): string | null {
if (rate === undefined || rate <= 0) return null;
return rate >= 10 ? rate.toFixed(0) : rate.toFixed(1);
}
export function MessageBubble({ export function MessageBubble({
role, role,
content, content,
messageIndex = 0, messageIndex = 0,
onEditSubmit, onEditSubmit,
isComplete = true, isComplete = true,
stats,
showStats = "while_generating",
}: MessageBubbleProps) { }: MessageBubbleProps) {
const { t } = useTranslation(["views/chat", "common"]); const { t } = useTranslation(["views/chat", "common"]);
const isUser = role === "user"; const isUser = role === "user";
@ -214,7 +230,7 @@ export function MessageBubble({
</div> </div>
)} )}
</div> </div>
<div className="flex items-center gap-0.5"> <div className="flex items-center gap-1.5">
{isUser && onEditSubmit != null && ( {isUser && onEditSubmit != null && (
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
@ -256,6 +272,27 @@ export function MessageBubble({
</TooltipContent> </TooltipContent>
</Tooltip> </Tooltip>
)} )}
{!isUser &&
stats &&
(showStats === "always" || !isComplete) &&
(() => {
const ctx = formatTokens(stats.promptTokens);
const rate = formatRate(stats.tokensPerSecond);
if (ctx === null && rate === null) return null;
return (
<div className="flex items-center gap-1 text-xs text-muted-foreground">
{ctx !== null && (
<span>{t("stats.context", { tokens: ctx })}</span>
)}
{ctx !== null && rate !== null && (
<span aria-hidden="true">·</span>
)}
{rate !== null && (
<span>{t("stats.tokens_per_second", { rate })}</span>
)}
</div>
);
})()}
</div> </div>
</div> </div>
); );