@phren/cli
Version:
Knowledge layer for AI agents - CLI, MCP server, and data layer
166 lines (165 loc) • 5.88 kB
TypeScript
import { type TmuxHealth } from "./terminal-tmux.js";
/** One tool's installed version, or why there is none. */
export interface ToolVersion {
tool: string;
status: "ok" | "missing" | "error";
version?: string;
detail?: string;
}
export interface StoreSync {
name: string;
role: string;
available: boolean;
branch?: string;
upstream?: string;
ahead?: number;
behind?: number;
lastPushStatus?: string;
lastPushAt?: string;
lastSuccessfulPushAt?: string;
consecutiveFailures?: number;
lastSuccessfulPullAt?: string;
/** The newest successful pull or push. */
lastSyncedAt?: string;
/** Both the store and its remote have commits the other lacks. */
diverged?: boolean;
/** No successful sync for over STORE_STALE_MS while the store has a remote. */
stale?: boolean;
/** The last sync failure in plain words, only while the store is failing. */
error?: string;
/** One line a computer list shows as is when the store needs attention. */
warning?: string;
degraded: boolean;
}
export interface LastScheduledRun {
name?: string;
paused?: boolean;
project: string;
status: string;
reason?: string;
startedAt: string;
finishedAt?: string;
}
export interface PeerHealth {
name: string;
reachable: boolean;
ms: number;
error?: string;
version?: string;
/** Why an unreachable peer failed, as a stable offline code (docs/phren-hook.md#offline-reasons). */
code?: string;
/** Whether the peer's own hooks.yaml lists this computer; null when its Hook is too old to say. */
listsBack: boolean | null;
}
export interface CanaryStep {
name: string;
status: "ok" | "failed" | "skipped";
durationMs: number;
reason?: string;
detail?: string;
}
export interface CanaryResult {
version: 1;
trigger: "manual" | "daily";
computer: string;
startedAt: string;
finishedAt: string;
durationMs: number;
ok: boolean;
steps: CanaryStep[];
}
export interface HealthDetails {
product: "phren-hook";
computer: {
name: string;
id?: string;
};
checkedAt: string;
versions: ToolVersion[];
stores: StoreSync[];
schedules: {
running: boolean | null;
lastTickAt?: string;
lastRun: LastScheduledRun | null;
};
peers: {
configured: boolean;
error?: string;
computers: PeerHealth[];
};
push: {
configured: boolean;
devices?: number;
};
canary: CanaryResult | null;
terminal: TerminalHealth;
}
/** Which terminal multiplexer the Hook drives, per running server, and tmux's state. */
export interface TerminalHealth {
/** "herdr" while a Herdr server answers, else "tmux" when tmux can host agents, else "none". */
provider: "herdr" | "tmux" | "none";
servers: {
name: string;
provider: "herdr" | "tmux";
}[];
tmux: TmuxHealth;
}
/** The running servers the Hook lists (Herdr's, else tmux's) and tmux's own state. */
export declare function terminalHealth(): Promise<TerminalHealth>;
/** One line on the terminal: the provider, its servers and tmux's state. */
export declare function describeTerminal(terminal: TerminalHealth): string;
export interface HealthOptions {
/** The running Hook's own version; undefined when asked from outside a Hook. */
hookVersion?: string;
computerId?: string;
store: string;
/** The Hook knows whether its scheduler runs; a CLI caller does not. */
scheduler?: {
running: boolean;
lastTickAt?: Date;
};
/** The Hook's loaded APNs sender; a CLI caller checks for apns.json instead. */
push?: {
configured: boolean;
devices: number;
};
}
/** `<tool> --version`, bounded to 8 seconds and remembered for 5 minutes. `args` come
* before `--version` for a tool behind a subcommand (`phren agent --version`). */
export declare function toolVersion(tool: string, executable?: string, args?: string[]): Promise<ToolVersion>;
/** Only for tests: forget cached versions. */
export declare function clearVersionCache(): void;
/** Branch and ahead/behind against the upstream as last fetched; nothing is fetched here. */
export declare function storeSync(store: string): Promise<StoreSync[]>;
/**
* The degraded stores' warnings for the overview: the last answer at once,
* refreshed in the background once a minute old, so the overview never
* waits on Git.
*/
export declare function cachedStoreWarnings(store: string, now?: number): string[];
/** The newest run in schedule-runs.jsonl, with its schedule's name when the project still has it. */
export declare function lastScheduledRun(store: string, runsFile?: string): Promise<LastScheduledRun | null>;
/** This computer's public SSH host key, the pin a peer's hooks.yaml holds for it. */
export declare function ownHostKey(): Promise<string | undefined>;
/** Whether this computer's hooks.yaml lists the caller, by pinned host key or by name. */
export declare function listsCaller(caller: {
name?: string;
hostKey?: string;
}): Promise<{
computers: string[];
knowsCaller: boolean;
}>;
export declare function canaryFile(root?: string): string;
export declare function readCanary(root?: string): Promise<CanaryResult | null>;
/** Everything a person needs to tell whether phren is healthy on this computer.
* Bounded: versions are cached, each peer probe stops at 5 seconds, and nothing
* here returns a secret, a file's contents or a store path. */
export declare function healthDetails(options: HealthOptions): Promise<HealthDetails>;
/** Plain lines for `phren status`. */
export declare function formatHealth(health: HealthDetails, color: {
dim: string;
reset: string;
red: string;
yellow: string;
green: string;
}): string[];