adds a new /usage page that lets board operators see how much each ai provider is consuming across any date window, with per-model breakdowns, rolling 5h/24h/7d burn windows, weekly budget bars, and a deficit notch when projected spend is on track to exceed the monthly budget. - new GET /companies/:id/costs/by-provider endpoint aggregates cost events by provider + model with pro-rated billing type splits from heartbeat runs - new GET /companies/:id/costs/window-spend endpoint returns rolling window spend (5h, 24h, 7d) per provider with no schema changes - QuotaBar: reusable boxed-border progress bar with green/yellow/red threshold fill colors and optional deficit notch - ProviderQuotaCard: per-provider card showing budget allocation bars, rolling windows, subscription usage, and model breakdown with token/cost share overlays - Usage page: date preset toggles (mtd, 7d, 30d, ytd, all, custom), provider tabs, 30s polling plus ws invalidation on cost_event - custom date range blocks queries until both dates are selected and treats boundaries as local-time (not utc midnight) so full days are included regardless of timezone - query key to timestamp is floored to the nearest minute to prevent cache churn on every 30s refetch tick
31 lines
1.3 KiB
TypeScript
31 lines
1.3 KiB
TypeScript
import type { CostSummary, CostByAgent, CostByProviderModel, CostWindowSpendRow } from "@paperclipai/shared";
|
|
import { api } from "./client";
|
|
|
|
export interface CostByProject {
|
|
projectId: string | null;
|
|
projectName: string | null;
|
|
costCents: number;
|
|
inputTokens: number;
|
|
outputTokens: number;
|
|
}
|
|
|
|
function dateParams(from?: string, to?: string): string {
|
|
const params = new URLSearchParams();
|
|
if (from) params.set("from", from);
|
|
if (to) params.set("to", to);
|
|
const qs = params.toString();
|
|
return qs ? `?${qs}` : "";
|
|
}
|
|
|
|
export const costsApi = {
|
|
summary: (companyId: string, from?: string, to?: string) =>
|
|
api.get<CostSummary>(`/companies/${companyId}/costs/summary${dateParams(from, to)}`),
|
|
byAgent: (companyId: string, from?: string, to?: string) =>
|
|
api.get<CostByAgent[]>(`/companies/${companyId}/costs/by-agent${dateParams(from, to)}`),
|
|
byProject: (companyId: string, from?: string, to?: string) =>
|
|
api.get<CostByProject[]>(`/companies/${companyId}/costs/by-project${dateParams(from, to)}`),
|
|
byProvider: (companyId: string, from?: string, to?: string) =>
|
|
api.get<CostByProviderModel[]>(`/companies/${companyId}/costs/by-provider${dateParams(from, to)}`),
|
|
windowSpend: (companyId: string) =>
|
|
api.get<CostWindowSpendRow[]>(`/companies/${companyId}/costs/window-spend`),
|
|
};
|