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.
This commit is contained in:
parent
b7f77d8f60
commit
90efeea507
2 changed files with 25 additions and 0 deletions
|
|
@ -7,6 +7,7 @@
|
||||||
createAgentSession,
|
createAgentSession,
|
||||||
removeAgentSession,
|
removeAgentSession,
|
||||||
getChildSessions,
|
getChildSessions,
|
||||||
|
getTotalCost,
|
||||||
type AgentSession,
|
type AgentSession,
|
||||||
} from '../../stores/agents.svelte';
|
} from '../../stores/agents.svelte';
|
||||||
import { focusPane } from '../../stores/layout.svelte';
|
import { focusPane } from '../../stores/layout.svelte';
|
||||||
|
|
@ -41,6 +42,7 @@
|
||||||
let hasToolCalls = $derived(session?.messages.some(m => m.type === 'tool_call') ?? false);
|
let hasToolCalls = $derived(session?.messages.some(m => m.type === 'tool_call') ?? false);
|
||||||
let parentSession = $derived(session?.parentSessionId ? getAgentSession(session.parentSessionId) : undefined);
|
let parentSession = $derived(session?.parentSessionId ? getAgentSession(session.parentSessionId) : undefined);
|
||||||
let childSessions = $derived(session ? getChildSessions(session.id) : []);
|
let childSessions = $derived(session ? getChildSessions(session.id) : []);
|
||||||
|
let totalCost = $derived(session && childSessions.length > 0 ? getTotalCost(session.id) : null);
|
||||||
|
|
||||||
const mdRenderer = new Renderer();
|
const mdRenderer = new Renderer();
|
||||||
mdRenderer.code = function({ text, lang }: { text: string; lang?: string }) {
|
mdRenderer.code = function({ text, lang }: { text: string; lang?: string }) {
|
||||||
|
|
@ -280,6 +282,9 @@
|
||||||
{:else if session.status === 'done'}
|
{:else if session.status === 'done'}
|
||||||
<div class="done-bar">
|
<div class="done-bar">
|
||||||
<span class="cost">${session.costUsd.toFixed(4)}</span>
|
<span class="cost">${session.costUsd.toFixed(4)}</span>
|
||||||
|
{#if totalCost && totalCost.costUsd > session.costUsd}
|
||||||
|
<span class="total-cost">(total: ${totalCost.costUsd.toFixed(4)})</span>
|
||||||
|
{/if}
|
||||||
<span class="tokens">{session.inputTokens + session.outputTokens} tokens</span>
|
<span class="tokens">{session.inputTokens + session.outputTokens} tokens</span>
|
||||||
<span class="duration">{(session.durationMs / 1000).toFixed(1)}s</span>
|
<span class="duration">{(session.durationMs / 1000).toFixed(1)}s</span>
|
||||||
{#if !autoScroll}
|
{#if !autoScroll}
|
||||||
|
|
@ -774,6 +779,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.done-bar { color: var(--ctp-green); }
|
.done-bar { color: var(--ctp-green); }
|
||||||
|
.total-cost { color: var(--ctp-yellow); font-size: 10px; }
|
||||||
.error-bar { color: var(--ctp-red); }
|
.error-bar { color: var(--ctp-red); }
|
||||||
|
|
||||||
.follow-up {
|
.follow-up {
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,25 @@ export function getChildSessions(parentId: string): AgentSession[] {
|
||||||
return sessions.filter(s => s.parentSessionId === parentId);
|
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 {
|
export function removeAgentSession(id: string): void {
|
||||||
// Also remove from parent's childSessionIds
|
// Also remove from parent's childSessionIds
|
||||||
const session = sessions.find(s => s.id === id);
|
const session = sessions.find(s => s.id === id);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue