import type { AggregateRow } from '../db/repositories/usage-repository.js'; /** * One window against another. * * Every report described a single window in absolutes, so "am I trending up?" * meant re-running with a second hand-computed date pair and diffing mentally. * * The one rule this module exists to keep: reported and estimated cost are * deltaed SEPARATELY and never summed, exactly as they are reported. A single * "spend is up $40" across two bases would be the same lie in motion. */ export interface Delta { /** current minus previous. Negative means the current window is lower. */ absolute: number; /** * Change as a fraction of the previous value, or `undefined` when the previous * value is 0. * * There is no percentage change from zero. Reporting one as 100%, or as * Infinity, would be inventing a figure -- going from $0 to $5 is a new thing * happening, not a 100% rise. */ ratio?: number; } export interface ComparisonTotals { records: Delta; sessions: Delta; inputTokens: Delta; outputTokens: Delta; cacheReadTokens: Delta; cacheWriteTokens: Delta; reasoningTokens: Delta; totalTokens: Delta; /** Kept apart, like every other cost figure in this codebase. */ reportedCost: Delta; estimatedCost: Delta; } export interface Comparison { /** The window being compared against. */ previous: { since: string; until: string; label: string; }; previousTotals: AggregateRow; delta: ComparisonTotals; /** Things that would make the comparison misleading if unsaid. Never empty. */ caveats: string[]; } export declare function delta(current: number, previous: number): Delta; export declare function compareTotals(current: AggregateRow, previous: AggregateRow): ComparisonTotals; /** * The window of equal length immediately before an explicit range. * * `resolvePeriod` is the normal source of a previous window, because it can * align to the same local midnights the period itself uses. This is the raw * arithmetic, for a caller that has only two instants. */ export declare function previousWindow(since: string, until: string): { since: string; until: string; label: string; }; /** * Caveats that travel with the numbers. * * The partial-window one matters most: comparing a part-finished today against a * whole previous day shows a fall that is an artefact of the clock, not of * behaviour, and it is the single easiest way to misread this feature. */ export declare function comparisonCaveats(current: { since: string; until?: string; }, previousTotals: AggregateRow): string[];