From a41788d7dcb8dcf65e093c2951ce4b7ed6f4b0fc Mon Sep 17 00:00:00 2001 From: Igor Velho Date: Mon, 24 Aug 2026 14:53:42 +0100 Subject: [PATCH] feat: show subagent-inclusive cost total in WorkStatusPrimaryGroup --- .../chat/work-status/WorkStatusPrimaryGroup.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/ui/src/components/chat/work-status/WorkStatusPrimaryGroup.tsx b/packages/ui/src/components/chat/work-status/WorkStatusPrimaryGroup.tsx index 4db88c6c..6b68b0c1 100644 --- a/packages/ui/src/components/chat/work-status/WorkStatusPrimaryGroup.tsx +++ b/packages/ui/src/components/chat/work-status/WorkStatusPrimaryGroup.tsx @@ -4,7 +4,7 @@ import { useGitStore } from '@/stores/useGitStore'; import { useRuntimeAPIs } from '@/hooks/useRuntimeAPIs'; import { runBackgroundNetworkTask } from '@/lib/background-network'; import { useFreshestPrVisualSummaryForBranch } from '@/stores/useGitHubPrStatusStore'; -import { useSession, useSessionMessages } from '@/sync/sync-context'; +import { useSessionMessages } from '@/sync/sync-context'; import { useConfigStore } from '@/stores/useConfigStore'; import { useUIStore } from '@/stores/useUIStore'; import { useProjectsStore } from '@/stores/useProjectsStore'; @@ -14,6 +14,8 @@ import { resolveUsageTone } from '@/lib/quota'; import { sessionEvents } from '@/lib/sessionEvents'; import { normalizePath } from '@/lib/pathNormalization'; import { computeContextUsage } from './contextUsage'; +import { formatCost } from './subagentCost'; +import { useSubagentCostRollup } from './useSubagentCostRollup'; import { WorkStatusCallout, WorkStatusMeter, @@ -33,11 +35,6 @@ type Props = { showRepository: boolean; }; -// Spend is read against a budget, so it keeps its real precision instead of -// collapsing to two decimals. Trailing zeros are dropped so exact values stay -// short. -const trimZeros = (value: string): string => (value.includes('.') ? value.replace(/0+$/, '').replace(/\.$/, '') : value); -const formatCost = (cost: number): string => `$${trimZeros(cost.toFixed(4))}`; // Matches the header readout exactly: one decimal, capped the same way, so the // two places that report context fill never disagree by a rounding step. const formatPercent = (percent: number): string => `${Math.min(percent, 999).toFixed(1)}%`; @@ -49,7 +46,6 @@ const formatPercent = (percent: number): string => `${Math.min(percent, 999).toF */ export const WorkStatusPrimaryGroup: React.FC = ({ sessionId, directory, goalRow, showSession, showRepository }) => { const { t } = useI18n(); - const session = useSession(sessionId ?? '', directory ?? undefined); const { git } = useRuntimeAPIs(); const ensureStatus = useGitStore((state) => state.ensureStatus); const fetchStatus = useGitStore((state) => state.fetchStatus); @@ -195,7 +191,11 @@ export const WorkStatusPrimaryGroup: React.FC = ({ sessionId, directory, : usageTone === 'warn' ? 'var(--status-warning)' : 'var(--status-success)'; - const cost = typeof session?.cost === 'number' && session.cost > 0 ? session.cost : null; + // Rollup total: own cost plus every descendant subagent's cost, recursively + // (see useSubagentCostRollup). Shown here instead of session.cost alone, so + // spend that ran in a spawned subagent doesn't hide from the reader. + const { totalCost } = useSubagentCostRollup(sessionId); + const cost = totalCost !== null && totalCost > 0 ? totalCost : null; const hasSession = showSession && (usagePercent !== null || cost !== null || Boolean(goalRow)); const hasRepository = showRepository && Boolean(branch || changed || prSummary || attentionLabel);