"use client"; import { useState } from "react"; import { contextWindow, sessionCost, turnCost, type TurnUsage } from "@/src/core"; import { formatTokens, formatUsd, prettyModel } from "@/components/usage-format"; /** * The below-composer stats bar (wave 4 observability): the session's * money/context footprint as one quiet row beneath the composer — * LEFT-aligned: context window + session cost; RIGHT-aligned: model + * thinking level. Clicking the left side opens the per-turn detail popover. * * All folds come from core/prices.ts (sessionCost, contextWindow, turnCost) * — no cost math lives here. Absent data renders "—", never zero (the * doctrine): no turns yet → every figure is "—"; turns the price table * can't price count as unpriced, shown in the popover, never folded into a * fake $0. The RIGHT side is a PLACEHOLDER for the model + thinking-level * control (later work, with its contract changes): display-only for now, * model read from the last turn's usage. */ export function StatsBar({ turns }: { turns: TurnUsage[] }) { const [open, setOpen] = useState(false); const ctx = contextWindow({ turns }); const { cost, unpriced } = sessionCost({ turns }); // Honest cost: show dollars only when at least one turn priced; // otherwise "—" (never a fake $0.0000). const pricedCount = turns.length - unpriced; const costLabel = pricedCount > 0 ? formatUsd(cost) : "—"; const lastModel = turns.at(-1)?.model; return (
{/* Model + thinking level — a placeholder for the coming control (contract changes land with it); display-only today. */}
{lastModel ? prettyModel(lastModel) : "—"} · Thinking —
{open && (
Session stats
Context (last call) {ctx ? `${formatTokens(ctx.usedTokens)} / ${formatTokens(ctx.limit)}` : "—"}
Total cost {costLabel}
{unpriced > 0 && (
Unpriced turns {unpriced}
)}
{turns.length > 0 && ( <>
Turns
)}
)}
); }