/** Flush cadence — runtime is billed within ~this window of accruing, so a long/perpetual run can't * burn unbilled compute and the credit watcher sees the spend promptly. */ export declare const DEFAULT_RUNTIME_FLUSH_INTERVAL_MS = 60000; export interface RuntimeFlusherDeps { /** The run being metered (for the id base + correlation). */ runId: string; /** This worker session's id (fresh per claim) — separates a restarted run's sessions in the id. */ sessionId: string; /** Wall-clock at which this session's runtime starts accruing (the claim time). */ startedAtMs: number; /** vCPUs provisioned for the task. Runtime is billed per vCPU-SECOND, so each delta is wall-clock * seconds × this. Defaults to 1 (the 1-vCPU `small` size → vCPU-seconds == wall-clock). */ vcpus?: number; /** Monotonic-ish clock; injected for tests. */ now: () => number; /** Book a runtime vCPU-seconds delta under `identifier` (brokered: `RunnerControlClient.reportUsage`). */ report: (deltaSeconds: number, identifier: string) => Promise; intervalMs?: number; } export declare class RuntimeFlusher { private readonly deps; private timer; private firing; private stopped; /** Total vCPU-seconds already booked (across successful flushes). The next delta is `total - this`. */ private flushedSeconds; /** Per-flush sequence — advances only on a successful flush, so a retry reuses the same id. */ private seq; /** Wall-clock ms excluded from billing — frozen (suspended) time on the snapshot substrate. */ private excludedMs; constructor(deps: RuntimeFlusherDeps); /** Book everything unbilled right now (the pre-freeze flush: suspended time must never appear as * billed runtime, so the tail is booked BEFORE the snapshot — the suspension billing rule). */ flushNow(): Promise; /** Exclude `ms` of wall-clock from billing — the frozen window on a wake (computed from the wake's * authoritative wall clock, since the guest's own clock was stopped). Never lets elapsed go * negative. */ excludeIdle(ms: number): void; /** Begin periodic delta flushing. */ start(): void; /** * Suspend the periodic timer across a VM freeze — the pre-freeze hook pauses AFTER the tail flush * (as its last, non-throwing step), and the wake path resumes AFTER {@link excludeIdle}. Without * this, a tick landing in the sliver between the guest clock resync and the idle rebase would * compute its delta over the whole frozen window and bill suspended time. Reversible, unlike * {@link stop}; a freeze that aborts (snapshot failure → the seam holds in-process) must resume so * a long hold keeps metering. */ pause(): void; /** Restart periodic flushing after {@link pause} (wake, or a freeze abort). No-op once stopped. */ resume(): void; /** Stop the periodic timer and drain any in-flight flush. Does NOT book the final tail — call * {@link flushFinal} for that on a clean terminal. Idempotent. */ stop(): Promise; /** Book the remaining runtime since the last successful flush (the terminal tail). Runs even after * {@link stop}; it's the replacement for the old single terminal runtime charge. */ flushFinal(): Promise; /** Compute the unbilled delta and book it under a fixed per-flush id. `final` lets the terminal tail * flush after `stop()`; the timer path skips once stopped. */ private flush; }