import http from 'node:http'; /** One assistant response's token usage, extracted from a session jsonl line. */ interface UsageRecord { /** Epoch milliseconds of the message. */ timestamp: number; /** Session id (from the session header line, fallback: file name). */ sessionId: string; /** Working directory of the session (from the session header line). */ cwd: string; provider: string; model: string; input: number; output: number; cacheRead: number; cacheWrite: number; reasoning: number; totalTokens: number; /** Total cost in USD, as reported by the session log. */ cost: number; } interface ScanResult { records: UsageRecord[]; fileCount: number; /** Files whose content was actually parsed in this scan. */ parsedFiles: number; /** Milliseconds the scan took. */ elapsedMs: number; } /** * Parse one session jsonl file into usage records. * Two sources contribute: * - assistant messages carrying a `usage` object (per-request billing data) * - subagent / trellis_subagent toolResult messages, whose `details` carry * the aggregated token usage of the spawned child agents */ declare function parseSessionFile(content: string, fallbackSessionId: string): UsageRecord[]; /** * Incremental scanner for the sessions directory. Caches parsed files by * (mtimeMs, size) so repeated scans only re-read changed files. */ declare class SessionStore { readonly dir: string; private cache; constructor(dir: string); scan(): Promise; } type RangeKey = "day" | "week" | "month"; interface BucketTotals { input: number; output: number; cacheRead: number; cacheWrite: number; reasoning: number; totalTokens: number; cost: number; requests: number; } interface TimeBucket extends BucketTotals { /** Bucket start, epoch ms (local-time aligned). */ start: number; label: string; } interface ModelUsage extends BucketTotals { provider: string; model: string; /** provider/model 组合名,便于展示。 */ name: string; sessions: number; } interface FolderUsage extends BucketTotals { /** Working directory path. */ cwd: string; /** Short display name (last segment or full path). */ name: string; sessions: number; } interface Overview { range: RangeKey; windowStart: number; generatedAt: number; summary: BucketTotals & { sessions: number; }; buckets: TimeBucket[]; models: ModelUsage[]; folders: FolderUsage[]; } declare const RANGES: Record; declare function isRangeKey(value: string): value is RangeKey; /** * Aggregate usage records into a fixed grid of time buckets plus a * per-model ranking, for the given range ending at `now`. */ declare function aggregate(records: UsageRecord[], range: RangeKey, now?: number): Overview; interface StatsServer { server: http.Server; /** Rescan the sessions directory and update in-memory records. */ refresh: () => Promise; } declare function createStatsServer(store: SessionStore): Promise; export { type BucketTotals, type FolderUsage, type ModelUsage, type Overview, RANGES, type RangeKey, type ScanResult, SessionStore, type StatsServer, type TimeBucket, type UsageRecord, aggregate, createStatsServer, isRangeKey, parseSessionFile };