feat: show total session cost including subagents in Visible Context panel

Compute subagentCostUsd from sessionDetail.processes[].metrics and
display total cost (parent + subagents) with breakdown in the header.
When subagents exist, shows e.g. "$24.70 ($16.85 parent + $7.84 subagents)"
with a link to the Session Report for full details.

Replaces the "(parent only)" disclaimer since cost is now accurate.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Paul Holstein 2026-02-23 14:15:25 -05:00
parent 419913543c
commit 56dc860862
4 changed files with 38 additions and 17 deletions

View file

@ -102,6 +102,14 @@ export const ChatHistory = ({ tabId }: ChatHistoryProps): JSX.Element => {
sessionDetail,
} = tabData;
// Compute combined subagent cost from process metrics
const subagentCostUsd = useMemo(() => {
const processes = sessionDetail?.processes;
if (!processes || processes.length === 0) return undefined;
const total = processes.reduce((sum, p) => sum + (p.metrics.costUsd ?? 0), 0);
return total > 0 ? total : undefined;
}, [sessionDetail?.processes]);
// State for Context button hover (local state OK - doesn't need per-tab isolation)
const [isContextButtonHovered, setIsContextButtonHovered] = useState(false);
@ -874,6 +882,7 @@ export const ChatHistory = ({ tabId }: ChatHistoryProps): JSX.Element => {
onNavigateToUserGroup={handleNavigateToUserGroup}
totalSessionTokens={lastAiGroupTotalTokens}
sessionMetrics={sessionDetail?.metrics}
subagentCostUsd={subagentCostUsd}
onViewReport={effectiveTabId ? () => openSessionReport(effectiveTabId) : undefined}
phaseInfo={sessionPhaseInfo ?? undefined}
selectedPhase={selectedContextPhase}

View file

@ -28,6 +28,7 @@ interface SessionContextHeaderProps {
totalTokens: number;
totalSessionTokens?: number;
sessionMetrics?: SessionMetrics;
subagentCostUsd?: number;
onClose?: () => void;
onViewReport?: () => void;
phaseInfo?: ContextPhaseInfo;
@ -42,6 +43,7 @@ export const SessionContextHeader = ({
totalTokens,
totalSessionTokens,
sessionMetrics,
subagentCostUsd,
onClose,
onViewReport,
phaseInfo,
@ -132,24 +134,30 @@ export const SessionContextHeader = ({
<div className="col-span-2">
<span style={{ color: COLOR_TEXT_MUTED }}>Session Cost: </span>
<span className="font-medium tabular-nums" style={{ color: COLOR_TEXT_SECONDARY }}>
{formatCostUsd(sessionMetrics.costUsd)}
</span>
<span style={{ color: COLOR_TEXT_MUTED }}>
{' (parent only'}
{onViewReport && (
<>
{' · '}
<button
onClick={onViewReport}
className="underline"
style={{ color: COLOR_TEXT_SECONDARY }}
>
view full cost
</button>
</>
)}
{')'}
{formatCostUsd(sessionMetrics.costUsd + (subagentCostUsd ?? 0))}
</span>
{subagentCostUsd !== undefined && subagentCostUsd > 0 && (
<span style={{ color: COLOR_TEXT_MUTED }}>
{' ('}
{formatCostUsd(sessionMetrics.costUsd)}
{' parent + '}
{formatCostUsd(subagentCostUsd)}
{' subagents'}
{onViewReport && (
<>
{' · '}
<button
onClick={onViewReport}
className="underline"
style={{ color: COLOR_TEXT_SECONDARY }}
>
details
</button>
</>
)}
{')'}
</span>
)}
</div>
)}
</div>

View file

@ -49,6 +49,7 @@ export const SessionContextPanel = ({
onNavigateToUserGroup,
totalSessionTokens,
sessionMetrics,
subagentCostUsd,
onViewReport,
phaseInfo,
selectedPhase,
@ -193,6 +194,7 @@ export const SessionContextPanel = ({
totalTokens={totalTokens}
totalSessionTokens={totalSessionTokens}
sessionMetrics={sessionMetrics}
subagentCostUsd={subagentCostUsd}
onClose={onClose}
onViewReport={onViewReport}
phaseInfo={phaseInfo}

View file

@ -27,6 +27,8 @@ export interface SessionContextPanelProps {
totalSessionTokens?: number;
/** Full session metrics (input, output, cache tokens, cost) */
sessionMetrics?: SessionMetrics;
/** Combined cost of all subagent processes */
subagentCostUsd?: number;
/** Open the Session Report to see full cost breakdown */
onViewReport?: () => void;
/** Phase information for phase selector */