Spaces:
Running on Zero
Running on Zero
File size: 10,215 Bytes
5f43c7d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | import React from "react";
import { Zap, Box, ArrowRight, CornerDownRight, AlertTriangle, Terminal } from "lucide-react";
import { C, FD, FM, fmt, toolIcon } from "../theme.js";
import { Bar, PanelTitle, GeneratedTag, BinaryRow } from "./Primitives.jsx";
import { turnProse } from "../useAnalysis.js";
// RIGHT panel. Mirrors the Elastic "powershell.exe detail" idea: full execution
// detail of the selected node. Three states below.
export function SessionDetail({ session }) {
const { tokens } = session;
const ctx = session.context;
return (
<div style={{ overflowY: "auto", padding: 16 }}>
<PanelTitle icon={Zap} text="SESSION TOKENS (CUMULATIVE)" />
<Bar label="cache re-reads" v={tokens.cacheRead} max={tokens.cacheRead} c={C.orange} note="summed across every round-trip — the cost driver, not window size" />
<Bar label="cache write" v={tokens.cacheCreate} max={tokens.cacheRead} c={C.amber} />
<Bar label="generated" v={tokens.out} max={tokens.cacheRead} c={C.cyan} />
<Bar label="fresh input" v={tokens.in} max={tokens.cacheRead} c={C.blue} />
<div style={{ fontSize: 11.5, color: C.text2, marginTop: 10, lineHeight: 1.55 }}>
Cache re-reads are <b style={{ color: C.orange }}>~{Math.round(tokens.cacheRead / Math.max(1, tokens.out))}×</b> generated — cumulative, so they vastly exceed the window. Spend tracks tool-call iterations, not answer length.
</div>
{ctx && (
<div style={{ fontSize: 11.5, color: C.text2, marginTop: 10, lineHeight: 1.55, background: C.black, border: `1px solid ${C.border}`, borderRadius: 7, padding: "8px 10px" }}>
Peak context window: <b style={{ color: (ctx.peakPct || 0) >= 0.8 ? C.amber : C.cyan }}>{fmt(ctx.peak)} / {fmt(ctx.limit)}</b> ({Math.round((ctx.peakPct || 0) * 100)}%) — the fuel gauge, bounded by the window. {ctx.compactions?.length ? `${ctx.compactions.length} compaction(s).` : "No compactions."}
</div>
)}
<PanelTitle icon={ArrowRight} text="WHO DROVE THE WORK" mt />
<CausalitySplit direct={session.direct} indirect={session.indirect} />
<div style={{ fontSize: 11, color: C.muted, marginTop: 8, lineHeight: 1.5 }}>
{Math.round((100 * session.indirect) / Math.max(1, session.direct + session.indirect))}% of tool calls were triggered by the agent's own prior output (proven value-flow).
</div>
</div>
);
}
export function TurnDetail({ turn, narrated, binaries }) {
const { tokens } = turn;
const prose = turnProse(narrated, turn.i);
// binaries (real tools behind Bash/npx) that fired in THIS turn — filtered from
// the session-level list by the turns each appeared in.
const turnBins = (binaries || []).filter((b) => (b.turns || []).includes(turn.i));
const a = turn.indirect > turn.direct * 1.5;
const deterministic = [
`This query set off ${turn.reqs} model round-trip${turn.reqs !== 1 ? "s" : ""} and ${turn.tools.length} tool call${turn.tools.length !== 1 ? "s" : ""}.`,
turn.tools.length
? a
? `${turn.indirect} (${Math.round((100 * turn.indirect) / turn.tools.length)}%) were driven by earlier tool output, not your message.`
: `${turn.direct} came from your instruction; ${turn.indirect} followed from earlier output.`
: "",
`Cost is dominated by cache re-reads — ${fmt(tokens.cacheRead)} cached tokens reloaded (cumulative across round-trips), vs ${fmt(tokens.out)} generated.`,
turn.ctxPeak ? `The live context window peaked at ${fmt(turn.ctxPeak)} during this turn (point-in-time, not cumulative).` : "",
].filter(Boolean).join(" ");
return (
<div style={{ overflowY: "auto", padding: 16 }}>
<PanelTitle icon={Zap} text="WHY THESE TOKENS" />
{prose ? (
<div style={{ marginTop: 10 }}>
<div style={{ marginBottom: 6 }}><GeneratedTag cites={`turn ${turn.i}`} /></div>
<div style={{ fontSize: 13, color: C.text2, lineHeight: 1.6 }}>{prose}</div>
</div>
) : (
<div style={{ fontSize: 13, color: C.text2, lineHeight: 1.6, marginTop: 10 }}>{deterministic}</div>
)}
<PanelTitle icon={Box} text="TOKEN BREAKDOWN (CUMULATIVE)" mt />
<Bar label="cache re-reads" v={tokens.cacheRead} max={tokens.cacheRead} c={C.orange} note="volume = long tool loops · summed across round-trips" />
<Bar label="cache write" v={tokens.cacheCreate} max={tokens.cacheRead} c={C.amber} />
<Bar label="generated" v={tokens.out} max={tokens.cacheRead} c={C.cyan} />
<Bar label="fresh input" v={tokens.in} max={tokens.cacheRead} c={C.blue} />
<PanelTitle icon={ArrowRight} text="CAUSALITY SPLIT" mt />
<CausalitySplit direct={turn.direct} indirect={turn.indirect} />
<div style={{ fontSize: 11, color: C.muted, marginTop: 8, lineHeight: 1.5 }}>
Indirect = the tool's input appeared verbatim in an earlier result (proven). Tap a tool to see its trigger.
</div>
{turnBins.length > 0 && (
<>
<PanelTitle icon={Terminal} text="BINARIES RUN HERE" mt />
<div style={{ fontSize: 10.5, color: C.muted, marginTop: 4, lineHeight: 1.5 }}>
The real tools behind this turn's Bash calls — extracted from the command, not just "npx".
</div>
<div style={{ marginTop: 6 }}>
{turnBins.map((b) => <BinaryRow key={b.binary} b={b} />)}
</div>
</>
)}
</div>
);
}
export function ToolDetail({ tool, onBack }) {
const Icon = toolIcon(tool.name);
const ind = tool.provenance === "indirect";
const provenFlow = ind && tool.flowValue;
const inputStr =
tool.input && typeof tool.input === "object"
? JSON.stringify(tool.input, null, 2)
: String(tool.input ?? tool.summary ?? "");
return (
<div style={{ overflowY: "auto", padding: 16 }}>
<PanelTitle icon={Icon} text="TOOL DETAIL" />
<div style={{ fontFamily: FD, fontSize: 15, fontWeight: 600, marginTop: 8, display: "flex", alignItems: "center", gap: 8 }}>
{tool.mcp ? `${tool.mcp.server}:${tool.mcp.tool}` : tool.name}
{tool.errored && (
<span style={{ fontFamily: FM, fontSize: 9, color: C.red, border: `1px solid ${C.red}`, borderRadius: 4, padding: "1px 6px", display: "inline-flex", alignItems: "center", gap: 4 }}>
<AlertTriangle size={10} /> ERRORED
</span>
)}
</div>
{tool.mcp && (
<div style={{ fontFamily: FM, fontSize: 9.5, color: C.cyan, marginTop: 6 }}>MCP · {tool.mcp.server}</div>
)}
{/* full input */}
<div style={{ fontFamily: FM, fontSize: 9.5, color: C.muted, marginTop: 12, marginBottom: 4 }}>FULL INPUT</div>
<pre style={{ fontFamily: FM, fontSize: 11, color: C.text2, margin: 0, background: C.black, padding: 10, borderRadius: 7, border: `1px solid ${C.borderSoft}`, whiteSpace: "pre-wrap", wordBreak: "break-word", maxHeight: 220, overflow: "auto", lineHeight: 1.5 }}>
{inputStr}
</pre>
{/* provenance verdict — proven vs hypothesis separated */}
<div style={{ marginTop: 14 }}>
{provenFlow ? (
<div style={{ background: C.orangeMut, border: `1px solid ${C.orangeBd}`, borderRadius: 8, padding: 12 }}>
<div style={{ color: C.orange, fontWeight: 600, fontSize: 13, display: "flex", alignItems: "center", gap: 7 }}>
<CornerDownRight size={15} /> Indirect — proven value-flow
</div>
<div style={{ fontSize: 12.5, color: C.text2, marginTop: 8, lineHeight: 1.55 }}>
Fired because a value from an earlier <b style={{ color: C.orange }}>{tool.sourceTool}</b> result reappeared <b>verbatim</b> in this input. This is asserted, not inferred.
</div>
<div style={{ marginTop: 10 }}>
<div style={{ fontFamily: FM, fontSize: 9.5, color: C.muted, marginBottom: 4 }}>VALUE THAT FLOWED</div>
<div style={{ fontFamily: FM, fontSize: 11, color: C.orange, background: C.black, padding: "6px 9px", borderRadius: 5, border: `1px solid ${C.orangeBd}`, wordBreak: "break-all" }}>
{tool.flowValue}
</div>
</div>
</div>
) : ind ? (
<div style={{ background: C.card, border: `1px dashed ${C.border}`, borderRadius: 8, padding: 12 }}>
<div style={{ color: C.amber, fontWeight: 600, fontSize: 13 }}>Indirect — proximity (hypothesis)</div>
<div style={{ fontSize: 12.5, color: C.text2, marginTop: 8, lineHeight: 1.55 }}>
Likely driven by an earlier <b>{tool.sourceTool || "tool"}</b> result, but no verbatim value was pinned. A hypothesis for you to judge — not asserted.
</div>
</div>
) : (
<div style={{ background: C.card, border: `1px solid ${C.border}`, borderRadius: 8, padding: 12 }}>
<div style={{ color: C.text, fontWeight: 600, fontSize: 13 }}>Direct — from your instruction</div>
<div style={{ fontSize: 12.5, color: C.text2, marginTop: 8, lineHeight: 1.55 }}>
No earlier tool result fed this input. It traces to your query.
</div>
</div>
)}
</div>
<div onClick={onBack} style={{ marginTop: 14, fontFamily: FM, fontSize: 11, color: C.muted, cursor: "pointer" }}>← back</div>
</div>
);
}
function CausalitySplit({ direct, indirect }) {
const tot = Math.max(1, direct + indirect);
return (
<div style={{ display: "flex", height: 26, borderRadius: 7, overflow: "hidden", border: `1px solid ${C.borderSoft}`, marginTop: 8 }}>
<div style={{ width: `${(100 * direct) / tot}%`, background: C.border, display: "flex", alignItems: "center", justifyContent: "center" }}>
{direct > 0 && <span style={{ fontFamily: FM, fontSize: 10, color: C.text }}>{direct} direct</span>}
</div>
<div style={{ width: `${(100 * indirect) / tot}%`, background: `linear-gradient(90deg,${C.orange},${C.orangeHi})`, display: "flex", alignItems: "center", justifyContent: "center" }}>
{indirect > 0 && <span style={{ fontFamily: FM, fontSize: 10, color: "#fff" }}>{indirect} indirect</span>}
</div>
</div>
);
}
|