fix(costs): align byAgent run filter to startedAt, tighten providerTabItems memo deps, stabilize byProject row keys

This commit is contained in:
Sai Shankar
2026-03-08 21:00:46 +05:30
committed by Dotta
parent 9d21380699
commit 7db3446a09
2 changed files with 11 additions and 8 deletions

View File

@@ -121,8 +121,8 @@ export function costService(db: Db) {
.orderBy(desc(sql`coalesce(sum(${costEvents.costCents}), 0)::int`));
const runConditions: ReturnType<typeof eq>[] = [eq(heartbeatRuns.companyId, companyId)];
if (range?.from) runConditions.push(gte(heartbeatRuns.finishedAt, range.from));
if (range?.to) runConditions.push(lte(heartbeatRuns.finishedAt, range.to));
if (range?.from) runConditions.push(gte(heartbeatRuns.startedAt, range.from));
if (range?.to) runConditions.push(lte(heartbeatRuns.startedAt, range.to));
const runRows = await db
.select({

View File

@@ -259,11 +259,14 @@ export function Costs() {
// totals are derived from byProvider (already memoized on providerData) so this memo
// only rebuilds when the underlying data actually changes, not on every query refetch. ----------
const providerTabItems = useMemo(() => {
const allTokens = providers.reduce(
// derive provider keys inline so this memo only rebuilds when byProvider changes,
// not on the extra tick caused by the derived `providers` memo also changing.
const providerKeys = Array.from(byProvider.keys());
const allTokens = providerKeys.reduce(
(s, p) => s + (byProvider.get(p)?.reduce((a, r) => a + r.inputTokens + r.outputTokens, 0) ?? 0),
0,
);
const allCents = providers.reduce(
const allCents = providerKeys.reduce(
(s, p) => s + (byProvider.get(p)?.reduce((a, r) => a + r.costCents, 0) ?? 0),
0,
);
@@ -273,7 +276,7 @@ export function Costs() {
label: (
<span className="flex items-center gap-1.5">
<span>All providers</span>
{providers.length > 0 && (
{providerKeys.length > 0 && (
<>
<span className="text-xs text-muted-foreground font-mono">
{formatTokens(allTokens)}
@@ -286,12 +289,12 @@ export function Costs() {
</span>
),
},
...providers.map((p) => ({
...providerKeys.map((p) => ({
value: p,
label: <ProviderTabLabel provider={p} rows={byProvider.get(p) ?? []} />,
})),
];
}, [providers, byProvider]);
}, [byProvider]);
// ---------- guard ----------
@@ -483,7 +486,7 @@ export function Costs() {
<div className="space-y-2">
{spendData.byProject.map((row, i) => (
<div
key={row.projectId ?? `na-${i}`}
key={row.projectId ?? "unattributed"}
className="flex items-center justify-between text-sm"
>
<span className="truncate">