import type { ClaudeInvoker } from '../invoker.js'; import { type SelectableAccount, type AccountOrder } from '../selector/selector.js'; import { type RotationStrategy } from '../usage/rotation-plan.js'; import type { Ledger } from '../ledger/ledger.schema.js'; import type { CapDecision } from '../usage/confirm-cap.js'; import { type HeadlessRunner } from './launcher.js'; /** An account the rotator can run: selectable plus its config dir. */ export interface RotatableAccount extends SelectableAccount { dir: string; } export interface AutoRotateDeps { claude: ClaudeInvoker; accounts: T[]; loggedIn: Set; pinned?: string; now: () => number; defaultBackoffMinutes: number; /** * Confirm a cap against the account's OWN usage before recording it. * * Required rather than optional: an unverified cap takes an account out for * hours, so a call site must not be able to skip this by forgetting it. */ confirmCap: (account: T, renderedText: string) => Promise; /** * Model fallback order, the operator's `modelPreference` (default Fable then * Opus). Empty disables model fallback and rotates on accounts alone. */ modelPreference?: string[]; /** * Which runs out first, the model or the account. Same setting the * interactive path follows, so `ccx models` means one thing everywhere: a * strategy that governed only one of the two ways to run is a setting that * lies about what it does. */ modelStrategy?: RotationStrategy; /** * How accounts are ordered (default `priority`). The headless path must honour * the same `ccx order` setting as the interactive one, or `most-room` would * apply to a live session but not to a `-p` run. */ order?: AccountOrder; /** Remaining headroom per account (higher = less used), for the `most-room` order. */ roomOf?: (name: string) => number; /** Starting ledger; threaded through and returned updated for the caller to persist. */ ledger: Ledger; run?: HeadlessRunner; out: (message: string) => void; /** Emit the winning run's captured output (real CLI writes to std streams). */ writeOutput?: (stdout: string, stderr: string) => void; } export interface AutoRotateResult { exitCode: number; account?: string; rotations: number; /** Updated ledger to persist. */ ledger: Ledger; } /** * Run a headless request, hopping to the next healthy account each time the * current one reports a usage cap, until one succeeds or every account is * capped. The ledger is threaded through (never mutated in place) so the caller * persists exactly once. */ export declare function autoRotateHeadless(args: string[], deps: AutoRotateDeps): Promise;