From 90efeea5076e4097f202f46f7f62c6ca95eee7e5 Mon Sep 17 00:00:00 2001 From: Hibryda Date: Fri, 6 Mar 2026 17:12:31 +0100 Subject: [PATCH] feat(v2): add recursive subagent cost aggregation in agent store and pane getTotalCost() recursively aggregates costUsd, inputTokens, outputTokens across parent and all child sessions. AgentPane done-bar displays total cost in yellow when children are present and total exceeds parent cost. --- v2/src/lib/components/Agent/AgentPane.svelte | 6 ++++++ v2/src/lib/stores/agents.svelte.ts | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/v2/src/lib/components/Agent/AgentPane.svelte b/v2/src/lib/components/Agent/AgentPane.svelte index e4a4670..2c6d733 100644 --- a/v2/src/lib/components/Agent/AgentPane.svelte +++ b/v2/src/lib/components/Agent/AgentPane.svelte @@ -7,6 +7,7 @@ createAgentSession, removeAgentSession, getChildSessions, + getTotalCost, type AgentSession, } from '../../stores/agents.svelte'; import { focusPane } from '../../stores/layout.svelte'; @@ -41,6 +42,7 @@ let hasToolCalls = $derived(session?.messages.some(m => m.type === 'tool_call') ?? false); let parentSession = $derived(session?.parentSessionId ? getAgentSession(session.parentSessionId) : undefined); let childSessions = $derived(session ? getChildSessions(session.id) : []); + let totalCost = $derived(session && childSessions.length > 0 ? getTotalCost(session.id) : null); const mdRenderer = new Renderer(); mdRenderer.code = function({ text, lang }: { text: string; lang?: string }) { @@ -280,6 +282,9 @@ {:else if session.status === 'done'}
${session.costUsd.toFixed(4)} + {#if totalCost && totalCost.costUsd > session.costUsd} + (total: ${totalCost.costUsd.toFixed(4)}) + {/if} {session.inputTokens + session.outputTokens} tokens {(session.durationMs / 1000).toFixed(1)}s {#if !autoScroll} @@ -774,6 +779,7 @@ } .done-bar { color: var(--ctp-green); } + .total-cost { color: var(--ctp-yellow); font-size: 10px; } .error-bar { color: var(--ctp-red); } .follow-up { diff --git a/v2/src/lib/stores/agents.svelte.ts b/v2/src/lib/stores/agents.svelte.ts index 323c1ac..628f5f2 100644 --- a/v2/src/lib/stores/agents.svelte.ts +++ b/v2/src/lib/stores/agents.svelte.ts @@ -111,6 +111,25 @@ export function getChildSessions(parentId: string): AgentSession[] { return sessions.filter(s => s.parentSessionId === parentId); } +/** Aggregate cost of a session plus all its children (recursive) */ +export function getTotalCost(id: string): { costUsd: number; inputTokens: number; outputTokens: number } { + const session = sessions.find(s => s.id === id); + if (!session) return { costUsd: 0, inputTokens: 0, outputTokens: 0 }; + + let costUsd = session.costUsd; + let inputTokens = session.inputTokens; + let outputTokens = session.outputTokens; + + for (const childId of session.childSessionIds) { + const childCost = getTotalCost(childId); + costUsd += childCost.costUsd; + inputTokens += childCost.inputTokens; + outputTokens += childCost.outputTokens; + } + + return { costUsd, inputTokens, outputTokens }; +} + export function removeAgentSession(id: string): void { // Also remove from parent's childSessionIds const session = sessions.find(s => s.id === id);