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 (
Cache re-reads are ~{Math.round(tokens.cacheRead / Math.max(1, tokens.out))}× generated — cumulative, so they vastly exceed the window. Spend tracks tool-call iterations, not answer length.
{ctx && (
Peak context window: = 0.8 ? C.amber : C.cyan }}>{fmt(ctx.peak)} / {fmt(ctx.limit)} ({Math.round((ctx.peakPct || 0) * 100)}%) — the fuel gauge, bounded by the window. {ctx.compactions?.length ? `${ctx.compactions.length} compaction(s).` : "No compactions."}
)}
{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).
); } 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 (
{prose ? (
{prose}
) : (
{deterministic}
)}
Indirect = the tool's input appeared verbatim in an earlier result (proven). Tap a tool to see its trigger.
{turnBins.length > 0 && ( <>
The real tools behind this turn's Bash calls — extracted from the command, not just "npx".
{turnBins.map((b) => )}
)}
); } 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 (
{tool.mcp ? `${tool.mcp.server}:${tool.mcp.tool}` : tool.name} {tool.errored && ( ERRORED )}
{tool.mcp && (
MCP · {tool.mcp.server}
)} {/* full input */}
FULL INPUT
        {inputStr}
      
{/* provenance verdict — proven vs hypothesis separated */}
{provenFlow ? (
Indirect — proven value-flow
Fired because a value from an earlier {tool.sourceTool} result reappeared verbatim in this input. This is asserted, not inferred.
VALUE THAT FLOWED
{tool.flowValue}
) : ind ? (
Indirect — proximity (hypothesis)
Likely driven by an earlier {tool.sourceTool || "tool"} result, but no verbatim value was pinned. A hypothesis for you to judge — not asserted.
) : (
Direct — from your instruction
No earlier tool result fed this input. It traces to your query.
)}
← back
); } function CausalitySplit({ direct, indirect }) { const tot = Math.max(1, direct + indirect); return (
{direct > 0 && {direct} direct}
{indirect > 0 && {indirect} indirect}
); }