import { type NotLinkedComputer } from "./hand-off.js";
import { type HookPeer } from "./peers.js";
import { type Json } from "./protocol.js";
import { NEAR_LIMIT_LEFT, type AccountUsage, type Subscription, type UsageCredits, type UsageWindow } from "./usage.js";
export { NEAR_LIMIT_LEFT };
/**
 * Every computer's agent usage merged by account, for a conductor choosing
 * where to send work: `account_usage` and `phren dispatch usage`. Read like
 * `live_sessions`: this Hook, then each linked Hook over its pinned pipe, with
 * unreachable and unlinked computers listed apart.
 *
 * The merge follows the phone's cards: one account is one allowance whichever
 * computers report it, so each window comes from the newest report that has
 * it (`mergedWindows`). Claude and Codex
 * rows merge by their account key; a Claude login with no identity
 * (`claude:home:<id>`) stays per computer, since two unknown logins are not
 * one account. A window whose reset time has passed says `reset` and has no
 * percent, and a report older than STALE_AFTER_MS is flagged stale.
 *
 * `nearLimit` is information: the owner often wants quota used before it
 * resets. Only `exhausted` (a window at 100% or refusing requests) rules an
 * account out.
 */
/** A report older than this is flagged: the Hook reads each account at most once a minute. */
export declare const STALE_AFTER_MS: number;
export interface AccountWindow {
    id: string;
    name: string;
    usedPercent?: number;
    leftPercent?: number;
    resetsAt?: string;
    resetsIn?: string;
    /** Reset since its report: the allowance is back, but no new percent is known. */
    reset?: true;
    /** The service is refusing requests on this window now. */
    limited?: true;
    /** At 100% or refused: no quota on this window until it resets. */
    exhausted?: true;
    usedUSD?: number;
    limitUSD?: number;
}
export interface AccountUsageRow {
    /** `source` or `source|key`, as the phone keys its cards. */
    id: string;
    harness: string;
    name: string;
    /** The login's email, else the account's label, when the Hook names one. */
    account?: string;
    windows: AccountWindow[];
    /** Least room on any window with a percent; `limited` counts as 0. */
    leftPercent?: number;
    /** Under 20% left on some window. Information, not a reason to avoid the account. */
    nearLimit: boolean;
    /** A window is at 100% or refusing requests: never dispatch to it until `availableIn`. */
    exhausted: boolean;
    /** When the last exhausted window resets, as "3h 10m". */
    availableIn?: string;
    spend?: {
        amountUSD: number;
        period: string;
    };
    subscription?: Subscription;
    /** Codex's credit balance from the newest report that has one. */
    credits?: UsageCredits;
    updatedAt?: string;
    /** How old the standing report is, as "4m" or "2d 3h". */
    age?: string;
    stale: boolean;
    /** The computer whose report stands. */
    from?: string;
    /** Where it is signed in, with the Claude account id dispatch takes there. */
    computers: Array<{
        name: string;
        account?: string;
    }>;
    message?: string;
}
export interface AccountUsageView {
    accounts: AccountUsageRow[];
    /** Harnesses no computer reported numbers for, with what each Hook said. */
    noData: Array<{
        harness: string;
        name: string;
        computers: string[];
        message?: string;
    }>;
    /** The computers that answered, this one first. */
    computers: string[];
    unreachable: Array<{
        computer: string;
        error: string;
        code?: string;
    }>;
    /** Registered in the store but not linked in hooks.yaml: their usage is unknown, not zero. */
    notLinked: NotLinkedComputer[];
    enrolled: number;
    peerError?: string;
}
export interface ComputerUsage {
    computer: string;
    accounts: AccountUsage[];
}
export declare function ageText(ms: number): string;
/** The phone's card key, except that a Claude login with no identity stays on its own computer. */
export declare function accountIdentity(usage: AccountUsage, computer: string): string;
/** Percent used and left, with a passed reset reported as reset rather than as its old percent. */
export declare function settleWindow(window: UsageWindow, now: number): AccountWindow;
/** Least room across an account's windows, undefined when none has a percent. */
export declare function roomLeft(windows: readonly AccountWindow[]): number | undefined;
/** One row per account across every computer's report. */
export declare function mergeAccountUsage(reports: readonly ComputerUsage[], now?: number): Pick<AccountUsageView, "accounts" | "noData">;
export interface ReadAccountUsageOptions {
    /** This computer's Hook; tests pass the fixture's socket. */
    hook?: (route: string) => Promise<Json>;
    peers?: () => Promise<{
        peers: HookPeer[];
        peerError?: string;
    }>;
    peer?: (peer: HookPeer, route: string) => Promise<Json>;
    store?: string | null;
    now?: number;
}
/** This Hook's usage and every linked Hook's, merged by account. */
export declare function readAccountUsage(options?: ReadAccountUsageOptions): Promise<AccountUsageView>;
/** The one-line answer a conductor reads first: how many, and which accounts are tight or stale. */
export declare function usageSummary(view: AccountUsageView): string;
/** "5-hour 82% left (resets in 2h 10m), weekly 64% left (resets in 3d 4h)": what launch and failover rank Claude accounts by. */
export declare function claudeRoom(row: Pick<AccountUsageRow, "windows">): string;
/** `phren dispatch usage` without --json. */
export declare function formatAccountUsage(view: AccountUsageView): string;
