her / ui /src /components /SessionReport.jsx
geekwrestler's picture
Squash history (purge pre-scrub demo session blobs)
5f43c7d
import React from "react";
import {
CheckCircle2, AlertTriangle, ShieldAlert, Bot, ScrollText, Flame, Coins,
Wrench, RefreshCw, Info, Clock, Cpu, GitBranch, Layers, MessageSquare,
Network, Map, Code2, Sparkles, ArrowRight, Link2, ChevronRight, Lightbulb, ShieldCheck,
Rocket, Database, Boxes, Server, Gauge, Scissors,
} from "lucide-react";
import { C, FD, FB, FM, fmt, fmtWhen } from "../theme.js";
import { BinaryLogo, GeneratedTag } from "./Primitives.jsx";
// SESSION REPORT — the executive cover page for a session (the simplified default
// view). It unifies every deterministic signal Her produces — cost, outcome, the
// real binaries run, the high-impact actions + risk, timestamps, and the cited
// recommendations — and is the jumping-off point to the Journey Graph (Mode A) and
// the turn-by-turn detail (Mode B). Numbers are the engine; the only GENERATED
// prose is the "What happened" overview (labelled). Suggest, never assert.
const COST_W = { in: 1.0, cacheCreate: 1.25, cacheRead: 0.1, out: 5.0 };
const RISK = {
High: { c: C.red, note: "high-impact actions detected" },
Medium: { c: C.amber, note: "review the flagged actions" },
Low: { c: C.cyan, note: "minor actions only" },
None: { c: C.muted, note: "nothing high-impact" },
};
const TAG = {
LIVE: { c: C.red, icon: Rocket },
PRODUCTION: { c: C.red, icon: Rocket }, // legacy alias
SECURITY: { c: C.orange, icon: ShieldAlert },
DATA: { c: "#f472b6", icon: Database },
NETWORK: { c: C.cyan, icon: Network },
CONFIG: { c: C.amber, icon: Code2 },
DEV: { c: C.blue, icon: Server },
};
function durationStr(a, b) {
if (!a || !b) return "—";
const ms = new Date(b).getTime() - new Date(a).getTime();
if (isNaN(ms) || ms < 0) return "—";
const s = Math.round(ms / 1000);
const h = Math.floor(s / 3600), m = Math.floor((s % 3600) / 60), ss = s % 60;
return h ? `${h}h ${m}m` : m ? `${m}m ${ss}s` : `${ss}s`;
}
// A friendly type tag for a binary in "Tools Discovered".
function binKind(b) {
const blob = `${b.product || ""} ${b.blurb || ""} ${b.security || ""}`.toLowerCase();
if (/\b(database|postgres|sql|mongo|redis|sqlite|db client)\b/.test(blob)) return "DB CLI";
if (b.via && b.via !== "direct") return "pkg";
if (/\bcli\b/.test(blob) || b.identified) return "CLI";
return "binary";
}
export default function SessionReport({
session, turns, binaries, entities, impact, recommendations, advice,
overview, narrated, onOpenTurn, onOpenJourney, onOpenRaw, onAskHer, chatOpen,
}) {
const S = session;
const tk = S.tokens || {};
// point-in-time window occupancy ("fuel gauge") — distinct from the cumulative tk.*
const ctx = S.context || { peak: 0, limit: 1e6, peakPct: 0, trajectory: [], compactions: [], overLimit: [] };
const reqs = turns.reduce((s, t) => s + (t.reqs || 0), 0);
const im = impact || { riskLevel: "None", actions: [], outcome: null };
const outcome = im.outcome || { label: "—", detail: "" };
const risk = RISK[im.riskLevel] || RISK.None;
const agentPct = Math.round(100 * (S.indirectRatio || 0));
// cost breakdown (by COST contribution — this is "why this COST so much")
const parts = [
{ label: "Cache re-reads", raw: tk.cacheRead || 0, cost: (tk.cacheRead || 0) * COST_W.cacheRead, c: C.orange },
{ label: "Generated (agent output)", raw: tk.out || 0, cost: (tk.out || 0) * COST_W.out, c: C.cyan },
{ label: "Cache write", raw: tk.cacheCreate || 0, cost: (tk.cacheCreate || 0) * COST_W.cacheCreate, c: C.amber },
{ label: "Fresh input", raw: tk.in || 0, cost: (tk.in || 0) * COST_W.in, c: C.blue },
];
const totalCost = parts.reduce((s, p) => s + p.cost, 0) || 1;
const driver = parts.reduce((a, b) => (b.cost > a.cost ? b : a), parts[0]);
// most important turns — by cost
const ranked = [...turns]
.filter((t) => (t.tokens?.cost ?? 0) > 0)
.sort((a, b) => (b.tokens.cost ?? 0) - (a.tokens.cost ?? 0))
.slice(0, 4);
// tools discovered = binaries (real CLIs/pkgs) + skills/plugins + sub-agents + MCP
const bins = (binaries || []).map((b) => ({ ...b, glyph: "binary", kind: binKind(b) }));
const skills = (entities?.skills || []).map((s) => ({ name: s.name, turns: s.turns, glyph: "skill", kind: "skill" }));
const agents = (entities?.subAgents || []).map((a) => ({ name: a.name, turns: a.turns, glyph: "agent", kind: a.via === "workflow" ? "workflow" : "agent" }));
const mcp = (entities?.mcpServers || []).map((m) => ({ name: m.name, turns: m.turns, glyph: "mcp", kind: "MCP" }));
const tools = [...bins, ...skills, ...agents, ...mcp];
const recs = (advice?.recommendations?.length ? advice.recommendations : recommendations) || [];
function copySummary() {
const lines = [
`Her · session report — ${S.sessionId ? S.sessionId.slice(0, 8) : ""}`,
`${S.cwd || ""}`,
`Outcome: ${outcome.label} (${outcome.detail})`,
`Token cost: ${fmt(S.cost || 0)} cost-weighted tokens (not $) · cache re-reads ${fmt(tk.cacheRead || 0)} cumulative across ${reqs} round-trips · agent-driven ${agentPct}%`,
`Peak context: ${fmt(ctx.peak || 0)} / ${fmt(ctx.limit || 0)} (${Math.round((ctx.peakPct || 0) * 100)}% of the window)${ctx.compactions?.length ? ` · ${ctx.compactions.length} compaction(s)` : ""}`,
`Risk: ${im.riskLevel} (${im.riskReason || ""})`,
`Tools: ${tools.map((t) => t.product || t.name).join(", ")}`,
im.actions?.length ? `Actions: ${im.actions.map((a) => `${a.title} [${a.tag}]`).join("; ")}` : "",
`Started ${fmtWhen(S.startedAt)} · ${durationStr(S.startedAt, S.endedAt)} · ${S.model || ""}`,
].filter(Boolean);
try { navigator.clipboard.writeText(lines.join("\n")); } catch { /* ignore */ }
}
return (
<div style={{ flex: 1, minWidth: 0, overflowY: "auto", padding: "22px 26px 40px" }}>
{/* title + actions */}
<div style={{ display: "flex", alignItems: "flex-start", gap: 16, flexWrap: "wrap" }}>
<div style={{ flex: 1, minWidth: 280 }}>
<div style={{ fontFamily: FD, fontWeight: 700, fontSize: 26, letterSpacing: 0.2 }}>Session Report</div>
<div style={{ fontSize: 13, color: C.text2, marginTop: 4, lineHeight: 1.5, maxWidth: 640 }}>
Executive summary for this coding-agent session — what happened, why it cost, and what to review.
</div>
</div>
<div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
<ReportBtn icon={Map} text="Open Journey Graph" onClick={onOpenJourney} />
<ReportBtn icon={Code2} text="Open Raw Trace" onClick={onOpenRaw} />
<ReportBtn icon={Sparkles} text="Ask Her" onClick={onAskHer} primary active={chatOpen} />
</div>
</div>
{/* stat band */}
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(190px,1fr))", gap: 12, marginTop: 18 }}>
<StatCard label="OUTCOME" icon={outcome.label === "Succeeded" ? CheckCircle2 : AlertTriangle}
iconColor={outcome.label === "Succeeded" ? C.cyan : C.amber}
value={outcome.label} valueColor={outcome.label === "Succeeded" ? C.cyan : C.amber}
sub={outcome.detail} big />
<StatCard label="TOKEN COST" value={fmt(S.cost || 0)} valueColor={C.orange} grad sub="cost-weighted tokens · not $ (cacheRead ×0.1 · out ×5)" />
<PeakContextCard ctx={ctx} />
<StatCard label="CACHE RE-READS" value={fmt(tk.cacheRead || 0)}
sub={`cumulative across ${reqs} round-trips · ~${Math.round(S.cacheReadOverOut || 0)}× generated · not window size`} />
<StatCard label="RISK LEVEL" icon={ShieldAlert} iconColor={risk.c} value={im.riskLevel} valueColor={risk.c}
sub={im.riskReason || risk.note} />
<StatCard label="AGENT-DRIVEN" icon={Bot} iconColor={C.orange} value={`${agentPct}%`}
sub={`${S.indirect || 0} of ${S.tools || 0} tool calls`} />
</div>
{/* main grid */}
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(260px,1fr))", gap: 12, marginTop: 12 }}>
{/* WHAT HAPPENED */}
<Card icon={ScrollText} title="WHAT HAPPENED">
{overview?.text ? (
<>
<div style={{ marginBottom: 8 }}><GeneratedTag cites={overview.label} /></div>
<ul style={{ margin: 0, paddingLeft: 0, listStyle: "none", display: "flex", flexDirection: "column", gap: 8 }}>
{sentences(overview.text).map((s, i) => (
<li key={i} style={{ display: "flex", gap: 8, fontSize: 12.5, color: C.text2, lineHeight: 1.5 }}>
<CheckCircle2 size={13} color={C.cyan} style={{ flexShrink: 0, marginTop: 2 }} /> <span>{s}</span>
</li>
))}
</ul>
</>
) : (
<div style={{ fontSize: 12.5, color: C.muted, lineHeight: 1.5 }}>
{S.turns} queries · {S.tools} tool calls · {S.humanTurns} human / {S.systemTurns} system turns. (Plain-English summary appears when the local model is running.)
</div>
)}
</Card>
{/* ACTIONS WORTH REVIEWING */}
<Card icon={AlertTriangle} title="ACTIONS WORTH REVIEWING" accent={C.amber}>
{im.actions?.length ? im.actions.map((a, i) => {
const tg = TAG[a.tag] || { c: C.muted, icon: Info };
const Ic = tg.icon;
return (
<div key={i} className="row lift" onClick={() => a.turns?.length && onOpenTurn(a.turns[0])}
style={{ display: "flex", gap: 10, alignItems: "center", cursor: a.turns?.length ? "pointer" : "default", background: C.card, border: `1px solid ${C.borderSoft}`, borderRadius: 8, padding: "9px 11px", marginTop: i ? 7 : 0 }}>
<div style={{ width: 26, height: 26, borderRadius: 7, background: C.elevated, border: `1px solid ${tg.c}`, display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }}>
<Ic size={13} color={tg.c} />
</div>
<div style={{ minWidth: 0, flex: 1 }}>
<div style={{ fontSize: 12.5, fontWeight: 600, color: C.text }}>{a.title}</div>
<div style={{ fontSize: 11, color: C.muted, lineHeight: 1.4, marginTop: 1 }}>{a.detail}</div>
</div>
<span style={{ fontFamily: FM, fontSize: 8.5, letterSpacing: 0.5, color: tg.c, border: `1px solid ${tg.c}`, borderRadius: 4, padding: "1px 6px", flexShrink: 0 }}>{a.tag}</span>
</div>
);
}) : (
<div className="row" style={{ display: "flex", gap: 9, alignItems: "center", fontSize: 12.5, color: C.text2, lineHeight: 1.5 }}>
<ShieldCheck size={16} color={C.cyan} style={{ flexShrink: 0 }} />
<span>No high-impact actions detected — no deploys, config/secret changes, tunnels, or privilege changes.</span>
</div>
)}
</Card>
{/* TOOLS DISCOVERED */}
<Card icon={Wrench} title="TOOLS DISCOVERED">
{tools.length ? (
<>
<div style={{ display: "flex", flexWrap: "wrap", gap: 7 }}>
{tools.map((t) => {
const clickable = t.turns && t.turns.length;
return (
<span key={t.glyph + ":" + t.name}
onClick={() => clickable && onOpenTurn(t.turns[0])}
className={clickable ? "lift" : ""}
title={`${t.product || t.name}${t.blurb ? " — " + t.blurb : ""}${t.security ? " ⚠ " + t.security : ""}${t.turns?.length ? " · turn(s) " + t.turns.join(", ") : ""}`}
style={{ display: "inline-flex", alignItems: "center", gap: 6, fontFamily: FM, fontSize: 10.5, color: C.text2, border: `1px solid ${C.borderSoft}`, borderRadius: 7, padding: "4px 8px 4px 6px", cursor: clickable ? "pointer" : "default" }}>
{toolGlyph(t)}
<span style={{ color: C.text }}>{t.product || t.name}</span>
<span style={{ color: C.muted, fontSize: 9 }}>({t.kind})</span>
{t.security && <ShieldAlert size={10} color={C.amber} />}
</span>
);
})}
</div>
<div onClick={onOpenJourney} className="lift" style={{ cursor: "pointer", fontFamily: FM, fontSize: 10.5, color: C.orange, marginTop: 12, display: "inline-flex", alignItems: "center", gap: 5 }}>
See all {S.tools} tool calls <ArrowRight size={12} />
</div>
</>
) : <Empty text="No external binaries or MCP servers detected." />}
</Card>
</div>
{/* COST & CONTEXT — one widget, two halves of the same token story: cumulative
spend (left, no ceiling) vs the point-in-time window gauge (right, ≤1M). Side
by side so the two quantities can't be mistaken for each other. */}
<CostContextCard S={S} parts={parts} totalCost={totalCost} driver={driver}
ctx={ctx} reqs={reqs} onOpenTurn={onOpenTurn} />
{/* bottom grid */}
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(300px,1fr))", gap: 12, marginTop: 12 }}>
{/* MOST IMPORTANT TURNS */}
<Card icon={Flame} title="MOST IMPORTANT TURNS">
<div style={{ display: "flex", flexDirection: "column", gap: 7 }}>
{ranked.map((t) => {
const errs = (t.tools || []).filter((tc) => tc.errored).length;
const title = t.guide?.head || (t.heavy ? "Heaviest turn" : firstClause(t.prompt));
const detail = t.guide?.body ? clip(t.guide.body, 90) : `${(t.tools || []).length} tools${errs ? `, ${errs} errored` : ""}`;
const pct = Math.round((100 * (t.tokens.cost ?? 0)) / Math.max(1, S.cost || 1));
return (
<div key={t.i} className="row lift" onClick={() => onOpenTurn(t.i)}
style={{ display: "flex", gap: 10, alignItems: "flex-start", cursor: "pointer", background: C.card, border: `1px solid ${C.borderSoft}`, borderRadius: 8, padding: "9px 11px" }}>
<span style={{ fontFamily: FM, fontSize: 10, color: C.muted, background: C.black, borderRadius: 5, padding: "2px 6px", flexShrink: 0 }}>#{String(t.i).padStart(2, "0")}</span>
<div style={{ minWidth: 0, flex: 1 }}>
<div style={{ fontSize: 12.5, fontWeight: 600, color: C.text, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{title}</div>
<div style={{ fontSize: 11, color: C.muted, lineHeight: 1.4, marginTop: 2 }}>{detail}</div>
</div>
<div style={{ textAlign: "right", flexShrink: 0 }}>
<div style={{ fontFamily: FM, fontSize: 12, color: t.heavy ? C.orange : C.text2, fontWeight: 600 }}>{fmt(t.tokens.cost ?? 0)}</div>
<div style={{ fontFamily: FM, fontSize: 9, color: C.muted }}>{pct}% of cost</div>
</div>
<ChevronRight size={14} color={C.muted} style={{ flexShrink: 0, marginTop: 2 }} />
</div>
);
})}
{ranked.length === 0 && <Empty text="No costed turns." />}
</div>
</Card>
{/* RECOMMENDED NEXT RUN */}
<Card icon={RefreshCw} title="RECOMMENDED NEXT RUN">
{recs.length ? recs.slice(0, 4).map((r, i) => (
<div key={i} className="row lift" onClick={() => r.turns?.length && onOpenTurn(r.turns[0])}
style={{ display: "flex", gap: 10, alignItems: "flex-start", cursor: r.turns?.length ? "pointer" : "default", background: C.card, border: `1px solid ${C.borderSoft}`, borderRadius: 8, padding: "9px 11px", marginTop: i ? 7 : 0 }}>
<Lightbulb size={14} color={C.amber} style={{ flexShrink: 0, marginTop: 2 }} />
<div style={{ minWidth: 0, flex: 1 }}>
<div style={{ fontSize: 12.5, fontWeight: 600, color: C.text, display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap" }}>
{r.headline}
<AttrBadge attribution={r.attribution} scoped={!!r.scoped} />
</div>
<div style={{ fontSize: 11.5, color: C.muted, lineHeight: 1.45, marginTop: 2 }}>{clip(r.scoped || r.advice || "", 120)}</div>
</div>
<ChevronRight size={14} color={C.muted} style={{ flexShrink: 0, marginTop: 2 }} />
</div>
)) : (
<div className="row" style={{ display: "flex", gap: 9, alignItems: "center", fontSize: 12.5, color: C.text2, lineHeight: 1.5 }}>
<CheckCircle2 size={16} color={C.cyan} style={{ flexShrink: 0 }} />
<span>Nothing stands out to change — expensive but clean. No loops, avoidable re-reads, or CLI flailing.</span>
</div>
)}
</Card>
{/* SESSION AT A GLANCE */}
<Card icon={Info} title="SESSION AT A GLANCE">
<Glance icon={Clock} label="Started" value={fmtWhen(S.startedAt) || "—"} />
<Glance icon={Clock} label="Duration" value={durationStr(S.startedAt, S.endedAt)} />
<Glance icon={Cpu} label="Model" value={modelLabel(S.model)} />
<Glance icon={Layers} label="Mode" value={`${S.humanTurns || 0} human + ${S.systemTurns || 0} system`} />
<Glance icon={GitBranch} label="Branch" value={S.gitBranch || "—"} />
<Glance icon={MessageSquare} label="Queries" value={String(S.turns ?? "—")} />
<Glance icon={Wrench} label="Tools called" value={String(S.tools ?? "—")} />
<div onClick={copySummary} className="lift" style={{ cursor: "pointer", marginTop: 12, display: "flex", alignItems: "center", justifyContent: "center", gap: 7, background: C.black, border: `1px solid ${C.borderSoft}`, borderRadius: 8, padding: "8px 10px", fontFamily: FM, fontSize: 11, color: C.text2 }}>
<Link2 size={13} color={C.orange} /> Copy summary
</div>
</Card>
</div>
</div>
);
}
// ---------- small presentational atoms (Tactical Grey) ----------------------
function ReportBtn({ icon: Icon, text, onClick, primary, active }) {
// `active` (panel open) gives a pressed look so it reads as a toggle — click again to close.
const bg = primary ? (active ? C.orangeHi : C.orange) : (active ? C.orangeMut : "transparent");
const fg = primary ? "#fff" : (active ? C.orange : C.text2);
return (
<div onClick={onClick} className="row lift" title={active ? "click to close the panel" : undefined}
style={{ display: "flex", alignItems: "center", gap: 7, cursor: "pointer", fontFamily: FM, fontSize: 11.5, color: fg, background: bg, border: `1px solid ${primary || active ? (active && !primary ? C.orangeBd : C.orange) : C.border}`, borderRadius: 8, padding: "8px 13px", boxShadow: active ? "inset 0 1px 4px rgba(0,0,0,.35)" : "none" }}>
<Icon size={14} color={primary ? "#fff" : C.orange} /> {text}
</div>
);
}
function StatCard({ label, icon: Icon, iconColor, value, valueColor, sub, grad, big }) {
return (
<div style={{ background: `linear-gradient(135deg,${C.card},${C.panel})`, border: `1px solid ${C.borderSoft}`, borderRadius: 10, padding: "13px 15px" }}>
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
<span style={{ fontFamily: FM, fontSize: 9, letterSpacing: 0.6, color: C.muted }}>{label}</span>
{Icon && <Icon size={14} color={iconColor || C.muted} />}
</div>
<div className={grad ? "hb" : ""} style={{ fontFamily: FD, fontWeight: 700, fontSize: big ? 22 : 26, color: grad ? undefined : (valueColor || C.text), marginTop: 6, lineHeight: 1.1, display: "flex", alignItems: "center", gap: 8 }}>
{big && Icon && <Icon size={20} color={iconColor} />}{value}
</div>
{sub && <div style={{ fontSize: 10.5, color: C.muted, marginTop: 5, lineHeight: 1.4 }}>{sub}</div>}
</div>
);
}
// PEAK CONTEXT — the "fuel gauge" headline: the fullest the live window ever got,
// over the model's limit. Point-in-time, bounded by the window (≤1M) — the opposite
// kind of number from the cumulative cost/cache stats beside it.
function PeakContextCard({ ctx }) {
const pct = Math.round((ctx.peakPct || 0) * 100);
const over = (ctx.overLimit || []).length > 0;
const near = pct >= 80;
const c = over ? C.red : near ? C.amber : C.cyan;
return (
<div style={{ background: `linear-gradient(135deg,${C.card},${C.panel})`, border: `1px solid ${C.borderSoft}`, borderRadius: 10, padding: "13px 15px" }}>
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
<span style={{ fontFamily: FM, fontSize: 9, letterSpacing: 0.6, color: C.muted }}>PEAK CONTEXT</span>
<Gauge size={14} color={c} />
</div>
<div style={{ fontFamily: FD, fontWeight: 700, fontSize: 22, color: c, marginTop: 6, lineHeight: 1.1 }}>
{fmt(ctx.peak || 0)}<span style={{ fontSize: 13, color: C.muted, fontWeight: 500 }}> / {fmt(ctx.limit || 0)}</span>
</div>
<div style={{ height: 6, background: C.black, borderRadius: 3, marginTop: 7, overflow: "hidden" }}>
<div style={{ width: `${Math.min(100, Math.max(2, pct))}%`, height: "100%", background: `linear-gradient(90deg,${c},${c}aa)` }} />
</div>
<div style={{ fontSize: 10.5, color: C.muted, marginTop: 5, lineHeight: 1.4 }}>
{over ? "⚠ a request exceeded the window — data suspect" : `${pct}% of the window · point-in-time, not cumulative`}
</div>
</div>
);
}
// COST & CONTEXT — the unified token story in one card. LEFT: cumulative cost
// breakdown (no ceiling). RIGHT: the point-in-time window gauge + trajectory (≤1M).
// The side-by-side contrast IS the point — cumulative ≠ window occupancy.
function CostContextCard({ S, parts, totalCost, driver, ctx, reqs, onOpenTurn }) {
return (
<div style={{ marginTop: 12 }}>
<Card icon={Coins} title="COST & CONTEXT — THE TOKEN STORY">
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(290px,1fr))", gap: 22 }}>
{/* LEFT — cumulative spend */}
<div>
<SubHead text="WHY IT COST · cumulative tokens" />
{/* Whole phrase is the hover target — the native `title` lives on this
<span> (a `title` on an inline <svg> icon does NOT show a tooltip in
Chrome). Dotted underline signals it's hoverable. */}
<div style={{ fontSize: 12.5, color: C.text2, margin: "8px 0 10px" }}>
Total: <b style={{ color: C.orange }}>{fmt(S.cost || 0)}</b>{" "}
<span
title={
`HOW IT'S COMPUTED\n` +
`cost-weighted tokens = fresh-input ×1 + cache-write ×1.25 + cache-read ×0.1 + generated ×5\n` +
`(Anthropic's uniform price ratios), summed across all ${reqs} round-trips.\n` +
`A relative spend proxy in input-token-equivalents — multiply by your input $/token for dollars.\n\n` +
`WHY IT'S NOT THE CONTEXT WINDOW\n` +
`This is CUMULATIVE and has no ceiling, so it routinely dwarfs the window. ` +
`The context window here is ${fmt(ctx.limit || 0)} (point-in-time, bounded — see the gauge on the right). ` +
`${fmt(S.cost || 0)} cost-weighted tokens is the running sum over every round-trip, NOT how full the ${fmt(ctx.limit || 0)} window got — different quantities.`
}
style={{ color: C.muted, cursor: "help", borderBottom: `1px dotted ${C.muted}` }}>
cost-weighted tokens (not $) <Info size={11} color={C.muted} style={{ verticalAlign: "-1px" }} />
</span>
</div>
{parts.map((p) => {
const pct = Math.round((100 * p.cost) / totalCost);
return (
<div key={p.label} style={{ marginTop: 8 }}>
<div style={{ display: "flex", justifyContent: "space-between", fontSize: 11.5 }}>
<span style={{ color: C.text2 }}>{p.label}</span>
<span style={{ fontFamily: FM, color: C.muted }}>{fmt(p.raw)} <span style={{ color: p.c }}>({pct}%)</span></span>
</div>
<div style={{ height: 6, background: C.black, borderRadius: 3, marginTop: 4, overflow: "hidden" }}>
<div style={{ width: `${Math.max(1, pct)}%`, height: "100%", background: `linear-gradient(90deg,${p.c},${p.c}aa)` }} />
</div>
</div>
);
})}
<div style={{ display: "flex", gap: 7, marginTop: 12, fontSize: 11.5, color: C.text2, lineHeight: 1.5, background: C.black, border: `1px solid ${C.borderSoft}`, borderRadius: 7, padding: "9px 10px" }}>
<Lightbulb size={13} color={C.amber} style={{ flexShrink: 0, marginTop: 1 }} />
<span><b style={{ color: driver.c }}>{driver.label}</b> dominates cost ({Math.round((100 * driver.cost) / totalCost)}%){driver.label === "Cache re-reads" ? ` — the conversation re-read from cache on every round-trip, summed across all ${reqs}. Cumulative spend, not window size.` : "."}</span>
</div>
</div>
{/* RIGHT — point-in-time window */}
<div style={{ borderLeft: `1px solid ${C.borderSoft}`, paddingLeft: 22 }}>
<SubHead text="CONTEXT WINDOW · point-in-time fill" />
<div style={{ marginTop: 8 }}>
<ContextTrajectory ctx={ctx} reqs={reqs} onOpenTurn={onOpenTurn} />
</div>
</div>
</div>
</Card>
</div>
);
}
function SubHead({ text }) {
return <div style={{ fontFamily: FM, fontSize: 9.5, letterSpacing: 0.6, color: C.muted, textTransform: "uppercase" }}>{text}</div>;
}
// CONTEXT WINDOW trajectory — an area chart of how full the live window got per turn
// (the gauge over time), with compaction markers (sharp drops) and the 1M ceiling.
function ContextTrajectory({ ctx, reqs, onOpenTurn }) {
const traj = ctx.trajectory || [];
const limit = ctx.limit || 1e6;
const compactTurns = new Set((ctx.compactions || []).map((c) => c.atTurn));
const W = 300, H = 84, n = traj.length;
if (!n) return <Empty text="No per-request token usage in this session." />;
const x = (i) => (n === 1 ? W / 2 : (i / (n - 1)) * W);
const y = (v) => H - Math.min(1, v / limit) * H;
const pts = traj.map((e, i) => `${x(i).toFixed(1)},${y(e.end).toFixed(1)}`);
const area = `M0,${H} L${pts.join(" L")} L${W},${H} Z`;
const line = `M${pts.join(" L")}`;
const over = (ctx.overLimit || []).length > 0;
const peakPct = Math.round((ctx.peakPct || 0) * 100);
return (
<div>
<div style={{ fontSize: 11.5, color: C.text2, marginBottom: 8, lineHeight: 1.5 }}>
Peak fill <b style={{ color: peakPct >= 80 ? C.amber : C.cyan }}>{fmt(ctx.peak || 0)}</b> of {fmt(limit)} (<b>{peakPct}%</b>). The live window — bounded by {fmt(limit)} — across {reqs} round-trips. Not the cumulative totals.
</div>
<svg viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="none" style={{ width: "100%", height: 84, display: "block" }}>
{/* 1M ceiling */}
<line x1="0" y1="1" x2={W} y2="1" stroke={C.red} strokeWidth="1" strokeDasharray="3 3" opacity="0.5" />
{/* 80% line */}
<line x1="0" y1={H * 0.2} x2={W} y2={H * 0.2} stroke={C.amber} strokeWidth="0.75" strokeDasharray="2 4" opacity="0.4" />
<path d={area} fill={`${C.cyan}22`} />
<path d={line} fill="none" stroke={over ? C.red : C.cyan} strokeWidth="1.5" />
{/* compaction markers */}
{traj.map((e, i) => compactTurns.has(e.i) ? (
<line key={e.i} x1={x(i)} y1="0" x2={x(i)} y2={H} stroke={C.orange} strokeWidth="1.25" strokeDasharray="2 2" />
) : null)}
</svg>
<div style={{ display: "flex", justifyContent: "space-between", fontFamily: FM, fontSize: 9, color: C.muted, marginTop: 3 }}>
<span>turn 00</span>
<span>{fmt(limit)} ceiling</span>
<span>turn {String(traj[n - 1].i).padStart(2, "0")}</span>
</div>
<div style={{ display: "flex", gap: 7, marginTop: 10, fontSize: 11.5, color: C.text2, lineHeight: 1.5, background: C.black, border: `1px solid ${C.borderSoft}`, borderRadius: 7, padding: "9px 10px" }}>
<Scissors size={13} color={C.orange} style={{ flexShrink: 0, marginTop: 1 }} />
{ctx.compactions?.length ? (
<span><b style={{ color: C.orange }}>{ctx.compactions.length} compaction{ctx.compactions.length === 1 ? "" : "s"}</b> detected — the window was trimmed where it dips.{" "}
{ctx.compactions.map((c) => (
<span key={c.atTurn} onClick={() => onOpenTurn(c.atTurn)} className="lift" style={{ cursor: "pointer", color: C.orange, fontFamily: FM }}>
#{String(c.atTurn).padStart(2, "0")} ({fmt(c.before)}→{fmt(c.after)}){" "}
</span>
))}
</span>
) : (
<span>No compactions — the window climbed to {peakPct}% and never had to be trimmed.</span>
)}
</div>
</div>
);
}
function Card({ icon: Icon, title, accent, children }) {
return (
<div style={{ background: C.panel, border: `1px solid ${C.borderSoft}`, borderRadius: 10, padding: "14px 15px" }}>
<div style={{ display: "flex", alignItems: "center", gap: 7, marginBottom: 11 }}>
<Icon size={14} color={accent || C.cyan} />
<span style={{ fontFamily: FM, fontSize: 10.5, letterSpacing: 0.7, color: accent || C.cyan, fontWeight: 600 }}>{title}</span>
</div>
{children}
</div>
);
}
function Glance({ icon: Icon, label, value }) {
return (
<div style={{ display: "flex", alignItems: "center", gap: 9, padding: "5px 0", borderBottom: `1px solid ${C.borderSoft}` }}>
<Icon size={13} color={C.muted} />
<span style={{ fontSize: 12, color: C.muted, flex: 1 }}>{label}</span>
<span style={{ fontFamily: FM, fontSize: 11.5, color: C.text2, textAlign: "right", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", maxWidth: 200 }}>{value}</span>
</div>
);
}
function AttrBadge({ attribution, scoped }) {
const generally = attribution && attribution !== "Anthropic";
return (
<span title={generally ? "A widely-recommended practice (not Anthropic-specific)" : "From Anthropic's Claude Code best practices"}
style={{ fontFamily: FM, fontSize: 8, letterSpacing: 0.3, color: generally ? C.amber : C.cyan, border: `1px solid ${generally ? C.amber : C.cyan}`, borderRadius: 4, padding: "1px 5px" }}>
{generally ? "GENERALLY RECOMMENDED" : "ANTHROPIC"}
</span>
);
}
function Empty({ text }) {
return <div style={{ fontSize: 12, color: C.muted, padding: "4px 0" }}>{text}</div>;
}
// ---------- helpers ---------------------------------------------------------
function sentences(text) {
return String(text || "")
.split(/(?<=[.!?])\s+/)
.map((s) => s.trim())
.filter((s) => s.length > 2)
.slice(0, 6);
}
function firstClause(p) {
const s = String(p || "").replace(/\s+/g, " ").trim();
return s.length > 48 ? s.slice(0, 48) + "…" : s || "(turn)";
}
function clip(s, n) {
s = String(s || "");
return s.length > n ? s.slice(0, n).trimEnd() + "…" : s;
}
function modelLabel(m) {
if (!m) return "—";
return String(m).replace(/^claude-/, "Claude ").replace(/-(\d{8})$/, "").replace(/-/g, " ");
}
// Leading glyph for a Tools-Discovered chip: binaries get their logo (monogram
// fallback); skills/plugins, sub-agents, and MCP servers get a typed icon.
function toolGlyph(t) {
if (t.glyph === "binary") return <BinaryLogo b={t} size={14} />;
if (t.glyph === "mcp") return <Network size={13} color={C.cyan} />;
if (t.glyph === "skill") return <Boxes size={13} color={C.amber} />;
return <Bot size={13} color={C.blue} />; // agent / workflow
}