@phren/cli
Version:
Knowledge layer for AI agents - CLI, MCP server, and data layer
83 lines (82 loc) • 4.01 kB
TypeScript
import { z } from "zod";
import { type HarnessInventory } from "./harnesses.js";
import type { AccountUsage } from "./usage.js";
/** One window's room: percent left, and when it resets. A window whose reset has passed is full again. */
export interface WindowRoom {
leftPercent?: number;
resetsAt?: string;
}
/** One signed-in account on one computer, as launch and failover weigh it. */
export interface AccountRoom {
account: string;
/** The login's key (`claude:<hash>`), the same on every computer. */
key?: string;
usable?: boolean;
fiveHour?: WindowRoom;
week?: WindowRoom;
/** A window is at 100% or refusing requests until `until`. */
exhausted?: boolean;
until?: string;
}
export interface AccountChoice {
account: string;
reason: string;
}
/** Claude's 5-hour session window and its 7-day window over all models. */
export declare const FIVE_HOUR = "five_hour", WEEK = "seven_day";
/** The 5-hour and weekly rooms of one usage row. */
export declare function accountWindows(usage: Pick<AccountUsage, "windows">, now: number): {
fiveHour?: WindowRoom;
week?: WindowRoom;
};
/**
* The account with the most headroom: the most left on the 5-hour window,
* then on the weekly one, then `default`, then by id. An account that is not
* usable (signed out), is out of quota, or that `blocked` names (it hit its
* limit and its window has not reset) is never chosen. Undefined when none is left.
*/
export declare function chooseAccount(rooms: readonly AccountRoom[], blocked?: (room: AccountRoom) => string | undefined): {
choice?: AccountChoice;
skipped: string[];
};
/** This computer's signed-in Claude accounts with their room, from the Hook's inventory and usage rows. */
export declare function claudeRooms(inventory: HarnessInventory | undefined, usage: readonly AccountUsage[], now: number): AccountRoom[];
/** How long an account that hit its limit is left alone when its reset time is unknown: one 5-hour window. */
export declare const UNKNOWN_RESET_MS: number;
declare const limitSchema: z.ZodObject<{
key: z.ZodString;
account: z.ZodString;
until: z.ZodString;
at: z.ZodString;
}, z.core.$strict>;
export type AccountLimit = z.infer<typeof limitSchema>;
/** How a login is told apart: its key, else its id on that computer (two unknown logins are not one). */
export declare const limitKey: (room: Pick<AccountRoom, "account" | "key">, computer: string) => string;
export declare function readAccountLimits(now?: number): Promise<AccountLimit[]>;
/** Records that a login hit its limit: no launch or failover chooses it again before `until`. */
export declare function noteAccountLimit(entry: {
key: string;
account: string;
until?: string;
}, now?: number): Promise<void>;
/** Why `room` on `computer` is held back by the ledger, or undefined. */
export declare function limitedBy(limits: readonly AccountLimit[], computer: string): (room: AccountRoom) => string | undefined;
type UsageReader = () => Promise<AccountUsage[]>;
/** The Hook's usage reader (`AccountUsageReader.limits`); tests pass fakes for both. */
export declare function setChoiceReaders(readers: {
usage?: UsageReader;
inventory?: () => Promise<HarnessInventory | undefined>;
}): void;
/**
* The account a Claude launch that names none runs under on this computer, or
* undefined to launch as before (`default`): only when more than one account is
* signed in here and their room can be read. Logged with the reason.
*/
export declare function pickClaudeAccount(what: string, computer?: string, now?: number): Promise<AccountChoice | undefined>;
/** Whether a dispatched Claude worker stopped at its usage limit continues on another signed-in account.
* Off unless the owner opts in with `phren config account-failover on` or PHREN_ACCOUNT_FAILOVER=on. */
export declare function resolveAccountFailover(env?: NodeJS.ProcessEnv, store?: string | null): {
on: boolean;
source: string;
};
export {};