import { type SessionTokenUsage } from '../core/cost-calculator.js'; import type { DaemonSession } from '../core/types.js'; export type InputTokenSemantics = 'includes_cache' | 'uncached'; export interface UsageLedgerRecord { v: 2; /** `inputTokens` / `totalInputTokens` exclude both cache buckets. */ inputTokenSemantics: 'uncached'; /** 'ownership' marks a zero-delta marker written at session spawn so * consumers can exclude the session from native parsers BEFORE its first * positive delta lands; absent for normal usage records. */ kind?: 'ownership'; recordId: string; ts: string; /** Baseline reset epoch this delta was measured in — lets the ledger itself * re-seed a lost baseline (crash recovery) without ambiguity. */ epoch: number; larkAppId?: string; sessionId: string; cliId?: string; cliSessionId?: string; chatId?: string; title?: string; workingDir?: string; /** open_id of the user whose message triggered this turn — attribution * metadata only; usage is billed to the machine owner. */ callerOpenId?: string; model: string; /** Positive deltas since the previous record of this session. */ inputTokens: number; outputTokens: number; cacheReadTokens: number; cacheCreateTokens: number; /** Cumulative transcript totals at record time, for self-validation. */ totalInputTokens: number; totalOutputTokens: number; totalCacheReadTokens: number; totalCacheCreateTokens: number; } export interface RecordSessionUsageArgs { sessionId: string; usage: SessionTokenUsage; larkAppId?: string; cliId?: string; cliSessionId?: string; chatId?: string; title?: string; workingDir?: string; callerOpenId?: string; /** Injectable for tests; defaults to wall clock. */ now?: Date; /** Injectable for tests; defaults to ~/.botmux/usage (BOTMUX_USAGE_DIR overrides). */ ledgerDir?: string; } export declare function __resetUsageLedgerMemoryForTest(): void; export declare function defaultLedgerDir(): string; /** * Diff the cumulative usage snapshot against the session's stored baseline * and append a record when the delta is positive. Returns the record, or * null when there is nothing to write (no growth, or a shrink — transcript * rotation / clear — which just resets the baseline). */ export declare function recordSessionUsage(args: RecordSessionUsageArgs): UsageLedgerRecord | null; /** * Re-anchor a session's baseline to the current cumulative snapshot WITHOUT * writing a record. Called at worker spawn: anything already in the * transcript at that point (resumed history, direct-tmux use while the * daemon was down) stays out of the ledger — only growth that happens while * botmux drives the session is recorded. */ export declare function anchorSessionUsage(args: RecordSessionUsageArgs): void; interface DaemonSessionLedgerOpts { now?: Date; ledgerDir?: string; } /** Turn boundary (idle/limited edge, session close): append the delta. */ export declare function recordUsageForDaemonSession(ds: DaemonSession, opts?: DaemonSessionLedgerOpts): UsageLedgerRecord | null; export interface RecordSessionOwnershipArgs { sessionId: string; cliSessionId?: string; larkAppId?: string; cliId?: string; chatId?: string; title?: string; workingDir?: string; callerOpenId?: string; now?: Date; ledgerDir?: string; } /** * Append a zero-delta ownership marker tying a botmux session to its * CLI-native session id. Written at spawn / as soon as the CLI session id is * known — consumers (kaboo) exclude the session from their native parsers the * moment this line exists, closing the "native parser uploads the transcript * before the first positive delta lands" double-count window. Does NOT touch * baselines; the deterministic recordId makes cross-restart repeats collapse * at the consumer. */ export declare function recordSessionOwnership(args: RecordSessionOwnershipArgs): UsageLedgerRecord | null; /** Ownership marker from a live daemon session (no transcript read needed). */ export declare function recordOwnershipForDaemonSession(ds: DaemonSession, opts?: DaemonSessionLedgerOpts): UsageLedgerRecord | null; /** * Daemon-restart restore: a turn that was in flight when the daemon died may * have finished inside tmux while we were away — that work was submitted by * botmux and belongs in the ledger. If the session already has a baseline, * record the catch-up delta; only sessions the ledger has never seen are * anchored (their transcript history predates botmux bookkeeping). */ export declare function reconcileUsageForDaemonSession(ds: DaemonSession, opts?: DaemonSessionLedgerOpts): UsageLedgerRecord | null; /** Worker spawn: re-anchor so pre-existing transcript history is not billed. */ export declare function anchorUsageForDaemonSession(ds: DaemonSession, opts?: DaemonSessionLedgerOpts): void; export {}; //# sourceMappingURL=usage-ledger.d.ts.map