import type { ContextReading } from './context-service.js'; import { type PlanLimitWindow, type StatusLineInput } from '../collectors/claude-code/statusline.js'; import type { PlanLimitRepository, StoredPlanLimitReading } from '../db/repositories/plan-limit-repository.js'; import type { AggregateRow, UsageFilter, UsageRepository } from '../db/repositories/usage-repository.js'; /** * How much of a Pro or Max plan's 5-hour and weekly limits is used, as Claude * Code itself reported it. * * Until now this was the one figure the README said this tool could not see: * Claude Code writes it to no file. It does hand it to a configured status-line * command, so `ai-usage statusline` keeps each reading, and this service reports * the latest one per window -- the percentage verbatim, never re-derived from * tokens, because the limit is not published as a token count and any such * conversion would be a number made up. */ export declare const PLAN_WINDOW_LABEL: Record; export interface PlanPace { /** Average rise per hour, from the first reading in this window to the last. */ percentPerHour: number; /** Distinct readings the pace is measured over. */ readings: number; /** ISO: the first reading the pace is measured from. */ from: string; /** ISO: the last time the latest value was seen. */ to: string; /** * ISO: when the window reaches 100% at this pace. Absent when usage is not * rising, or is already at 100%. */ reachesFullAt?: string; /** True when that comes before the reset -- the one case worth a warning. */ fullBeforeReset: boolean; } export interface PlanWindowReport { window: PlanLimitWindow; label: string; /** * `current` -- the latest reading's window has not reset yet. * `reset` -- it has, and no reading has arrived since: usage in the new * window is unknown, NOT 0. * `none` -- no reading has ever been stored for this window. */ state: 'current' | 'reset' | 'none'; latest?: StoredPlanLimitReading; /** ISO: the reset time minus the window's length. Present for `current`. */ windowStart?: string; pace?: PlanPace; /** This machine's Claude Code turns since `windowStart`. Present for `current`. */ local?: AggregateRow; } export interface PlanUsageReport { windows: PlanWindowReport[]; /** True when nothing has ever been recorded, so the report is setup advice. */ noReadings: boolean; /** Things that would make the figures misleading if unsaid. Never empty. */ caveats: string[]; } /** One status-line render: everything it shows, and nothing it does not. */ export interface StatusLineReport { /** Windows with a current reading only. A window that has reset is left out. */ limits: Array<{ window: PlanLimitWindow; usedPercent: number; resetsAt: string; /** Present only when the pace reaches 100% before the reset. */ fullAt?: string; }>; /** Today's totals, local time, every client. */ today: AggregateRow; /** The cache in the session Claude Code is rendering for, when it has turns stored. */ session?: { hitRate?: number; breakCount: number; estimatedExtraCost?: number; }; /** The session's context size, when it is known. Absent otherwise -- never 0. */ context?: ContextReading; } export declare class PlanLimitService { private readonly limits; private readonly usage; constructor(limits: PlanLimitRepository, usage: UsageRepository); /** Stores what a status-line payload carried. Returns how many rows were new. */ record(input: StatusLineInput, now?: Date): number; report(baseFilter: UsageFilter, now?: Date): PlanUsageReport; window(window: PlanLimitWindow, baseFilter: UsageFilter, now?: Date): PlanWindowReport; private pace; private caveats; }