/**
 * Quota Tracker — reads usage state from a JSON file and provides
 * load-shedding decisions to the job scheduler.
 *
 * The quota state file is written externally (by a collector script,
 * an OAuth integration, or the agent itself). This class reads it
 * and translates usage percentages into scheduling decisions.
 *
 * The architecture mirrors Dawn's proven pattern:
 * - Collector writes quota-state.json (polling interval, OAuth, etc.)
 * - QuotaTracker reads it and exposes canRunJob(priority)
 * - JobScheduler calls canRunJob before spawning sessions
 */
import type { QuotaState, JobPriority, JobSchedulerConfig } from '../core/types.js';
/**
 * Live pool-placeability signal for the POOL-AWARE quota throttle. Returned by an
 * injected provider (wired in server.ts) that asks the placement layer's OWN
 * `selectAccount` "is there a placeable account, and what is its headroom?". The
 * throttle uses placement's exact eligibility predicate by construction, so a
 * throttle "allow" always corresponds to a real account the pool can place on —
 * closing the band where the brake could allow work that placement couldn't land
 * (the respawn-loop gap). Spec: docs/specs/POOL-AWARE-QUOTA-THROTTLE-SPEC.md.
 */
export interface PoolQuota {
    /** True iff placement's selectAccount returned a placeable account. */
    placeable: boolean;
    /** Best placeable account's weekly utilization (0-100), or null if unknown. */
    weeklyPercent?: number | null;
    /** Best placeable account's 5-hour utilization (0-100), or null if unknown. */
    fiveHourPercent?: number | null;
    /**
     * True when the pool has a placeable account by STATUS but no trustworthy live
     * quota reading for it (e.g. a freshly-enrolled or just-after-an-outage pool
     * whose per-account snapshots are missing/stale). The throttle then applies the
     * SAME bounded degraded-mode cap as the file path (shed low, allow medium+)
     * rather than trusting a phantom "0% fresh" reading. Closes the round-2 finding
     * that the pool path had no staleness/provenance guard.
     */
    degraded?: boolean;
}
export interface QuotaTrackerConfig {
    /** Path to the quota state JSON file */
    quotaFile: string;
    /** Thresholds from scheduler config */
    thresholds: JobSchedulerConfig['quotaThresholds'];
    /** How stale (in ms) the quota data can be before we treat it as unknown */
    maxStalenessMs?: number;
}
export declare class QuotaTracker {
    private config;
    private cachedState;
    private lastRead;
    private readCooldownMs;
    private warnedNoFile;
    /**
     * Optional live pool-placeability provider (wired post-construction in
     * server.ts for multi-account agents). When set, the throttle reasons over the
     * pool's real placeability instead of a single account's usage. Unset on solo
     * agents → the legacy single-account path runs unchanged.
     */
    private poolQuotaProvider?;
    constructor(config: QuotaTrackerConfig);
    /**
     * Inject (or clear) the live pool-placeability provider. Wired in server.ts to
     * `() => selectAccount(subscriptionPool.list(), …)` so the throttle shares
     * placement's exact eligibility. Pass `undefined` to revert to single-account
     * gating.
     */
    setPoolQuotaProvider(fn: (() => PoolQuota | null) | undefined): void;
    /**
     * Read the current quota state from the file.
     * Returns null if file doesn't exist or is corrupted.
     */
    getState(): QuotaState | null;
    /**
     * Determine if a job at the given priority should run based on current quota.
     *
     * Checks BOTH weekly usage AND 5-hour rate limit:
     * - 5-hour >= 95%: block ALL spawns (sessions will immediately fail)
     * - 5-hour >= 80%: only critical priority
     * - Weekly >= shutdown (e.g. 95%): no jobs
     * - Weekly >= critical (e.g. 92%): critical only
     * - Weekly >= elevated (e.g. 85%): high+ only
     * - Weekly >= normal (e.g. 75%): medium+ only
     *
     * If quota data is unavailable or stale, defaults to allowing all jobs
     * (fail-open — better to run than to silently stop).
     */
    canRunJob(priority: JobPriority): boolean;
    /**
     * Check if a session should be spawned at the given priority.
     * Returns a structured result with reason — useful for logging and notifications.
     *
     * Checks both weekly AND 5-hour rate limits.
     */
    shouldSpawnSession(priority?: JobPriority): {
        allowed: boolean;
        reason: string;
    };
    /**
     * Bounded degraded-mode decision, shared by the file path (non-authoritative
     * estimate) and the pool path (placeable account with no trustworthy reading).
     * We don't KNOW the real usage, so: honor a genuine authoritative 5-hour wall,
     * then shed the lowest-priority work and allow medium+ — a conservative cap, not
     * an unbounded fail-open and not a whole-agent stall. Spec §4.
     */
    private boundedDegradedDecision;
    /**
     * Evaluate ONE account's (weekly, 5-hour) usage against the configured
     * thresholds for a given priority. Extracted so the pool-aware path can score
     * each account independently and pick the best-available one. The single-account
     * (legacy) path calls this directly with the one account's numbers, preserving
     * the exact prior behavior for agents that don't run a multi-account pool.
     */
    private evaluateAccountQuota;
    /**
     * Write a quota state to the file (for collector scripts or manual updates).
     */
    updateState(state: QuotaState): void;
    /**
     * Get the recommendation string for display purposes.
     */
    getRecommendation(): QuotaState['recommendation'];
    /**
     * Fetch quota status from a remote API (e.g., Dawn's /api/instar/quota).
     * If the remote says canProceed=false, updates local state accordingly.
     *
     * This allows Instar agents to check a central quota authority before
     * spawning sessions, preventing wasted attempts on exhausted machines.
     *
     * @param url - Full URL to the quota API (e.g., "https://dawn.bot-me.ai/api/instar/quota")
     * @param apiKey - Authorization token (sent as Bearer header)
     * @param timeoutMs - Request timeout (default 5000ms)
     * @returns Remote quota status, or null on failure (fail-open)
     */
    fetchRemoteQuota(url: string, apiKey: string, timeoutMs?: number): Promise<RemoteQuotaResult | null>;
}
/** Result from a remote quota API (e.g., /api/instar/quota) */
export interface RemoteQuotaResult {
    canProceed: boolean;
    blockReason?: string | null;
    activeAccount?: string | null;
    weeklyPercent: number;
    fiveHourPercent?: number | null;
    canRunPriority?: string;
    recommendation?: string | null;
    stale?: boolean;
}
//# sourceMappingURL=QuotaTracker.d.ts.map