mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-10-01 02:04:24 +00:00
The run detail tab, route, query hook, and query key say usage. Every read of input_tokens, output_tokens, total_tokens, reasoning_tokens, cache_read_tokens, cache_write_tokens, and total_usd_micros moves to usage.tokens and usage.cost, with lib/usage.ts replacing lib/billing.ts: totalTokens sums the five buckets, and costSourceTag names a cost that the provider reported or that was summed from differently sourced parts. The Usage tab and the stage popover show that tag next to such a cost. Test fixtures build a Usage through makeUsage; the failing set of the web tests is unchanged from main (the same 13 environment failures). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
53 lines
1.8 KiB
TypeScript
53 lines
1.8 KiB
TypeScript
import type { Cost, TokenCounts, Usage } from "@qltysh/fabro-api-client";
|
|
|
|
export interface UsageTokenBucket {
|
|
label: string;
|
|
value: number;
|
|
}
|
|
|
|
/** The sum of the five disjoint token buckets. */
|
|
export function totalTokens(usage: Usage): number {
|
|
const { input, output, reasoning, cache_read, cache_write } = usage.tokens;
|
|
return input + output + reasoning + cache_read + cache_write;
|
|
}
|
|
|
|
/** Output tokens as they are priced: completion plus reasoning. */
|
|
export function billableOutputTokens(tokens: TokenCounts): number {
|
|
return tokens.output + tokens.reasoning;
|
|
}
|
|
|
|
/** The disjoint token buckets shown in every usage breakdown. */
|
|
export function usageTokenBuckets(usage: Usage): UsageTokenBucket[] {
|
|
return [
|
|
{ label: "Cache read", value: usage.tokens.cache_read },
|
|
{ label: "Cache creation", value: usage.tokens.cache_write },
|
|
{ label: "Uncached", value: usage.tokens.input },
|
|
{ label: "Output", value: billableOutputTokens(usage.tokens) },
|
|
];
|
|
}
|
|
|
|
/** Whether the usage carries any tokens or a cost. */
|
|
export function hasUsage(usage: Usage): boolean {
|
|
return totalTokens(usage) !== 0 || (usage.cost?.usd_micros ?? 0) !== 0;
|
|
}
|
|
|
|
/** The cost in USD micros, when the usage carries one. */
|
|
export function costUsdMicros(usage: Usage | null | undefined): number | undefined {
|
|
return usage?.cost?.usd_micros;
|
|
}
|
|
|
|
/**
|
|
* A short tag for a cost that did not come from the catalog: `reported`
|
|
* when the provider gave the figure, `summed` when it was assembled from
|
|
* differently sourced parts. Catalog estimates carry no tag.
|
|
*/
|
|
export function costSourceTag(cost: Cost | null | undefined): string | null {
|
|
switch (cost?.source) {
|
|
case "provider":
|
|
return "reported";
|
|
case "application":
|
|
return "summed";
|
|
default:
|
|
return null;
|
|
}
|
|
}
|