import type { AgentId } from '../types.js';
import { type Installation } from './types.js';
/**
 * Persistence for {@link Installation} records.
 *
 * The record lives at `<versionDir>/installation.json` rather than in one
 * central index: the version dir is what `agents trash`/`agents prune` move,
 * copy and restore wholesale, so keeping identity inside it means identity
 * travels with the install instead of dangling in a registry that forgets to
 * follow. It is also why the file name is registered in versions.ts's
 * `PRESERVED_ON_CLEAN_REINSTALL` — a repair reinstall must not mint a new id.
 *
 * Path/enumeration plus frozen installation records. Depends on Node builtins,
 * installations-local modules, and base lib (`state`/`fs-atomic`/`primitives`/
 * `agents`/`shims`/`platform`) — never `plugins/`, `rules/`, `session/`, or
 * `devices/`, so those modules can import this file without an import cycle.
 */
/** Directory holding one installation. Same path as {@link getVersionDir}. */
export declare function installationDir(agent: AgentId, label: string): string;
export declare function installationRecordPath(agent: AgentId, label: string): string;
/** Mint an opaque installation id. Random, never derived from the release. */
export declare function mintInstallationId(): string;
/**
 * Read the record for one installation, or null when the version dir has none.
 * Never mints — use {@link ensureInstallation} for the migrating read.
 */
export declare function readInstallation(agent: AgentId, label: string): Installation | null;
export declare function writeInstallation(installation: Installation): void;
/**
 * Read the record for an existing version dir, minting and persisting one on
 * first sight. This is the migration path for every installation created before
 * frozen identity existed: their directory name IS their release, so the
 * migrated record seeds `label === releaseVersion` and dates the install from
 * the directory's own mtime rather than pretending it was created now.
 *
 * Throws when the version dir does not exist — an installation record must never
 * describe an install that isn't there.
 */
export declare function ensureInstallation(agent: AgentId, label: string): Installation;
/**
 * Create the record for a freshly-installed version dir. Idempotent: a repeat
 * `agents add` of the same label keeps the original id (identity is frozen) and
 * only records the release if it actually moved.
 */
export declare function createInstallation(agent: AgentId, label: string, releaseVersion: string): Installation;
/**
 * Move an installation's recorded release forward, preserving identity. Returns
 * the persisted record. Call only AFTER the new release is live on disk — the
 * record is the claim that it is.
 */
export declare function recordRelease(installation: Installation, releaseVersion: string): Installation;
/** Version-dir basenames present for an agent, oldest-first by directory name. */
export declare function listInstallationLabels(agent: AgentId): string[];
/**
 * Every installation of an agent, migrating records as needed. A version dir
 * that disappears mid-scan is skipped rather than failing the whole listing.
 */
export declare function listInstallations(agent: AgentId): Installation[];
/**
 * Get the directory where a specific version is installed.
 */
export declare function getVersionDir(agent: AgentId, version: string): string;
/**
 * Pick the real grok binary among `grok-*` entries in `downloadsDir` when NO
 * filename carries the pinned version string. Grok self-updates its binary in
 * place while running under the shim, so a version-home's downloads dir can
 * accumulate several `grok-*` files whose names have drifted away from that
 * version-home's pinned version (RUSH-2459: on yosemite-s0, version-home
 * `0.2.82` held `grok-1.0.0-linux-aarch64` after grok self-updated, plus a
 * stale, unrelated 99-byte `grok-0.2.118-linux-aarch64` wrapper script that
 * happened to sort alphabetically first).
 *
 * Never blindly take whatever `fs.readdirSync` returns first — that is exactly
 * the bug this replaces. Instead: exclude anything under
 * {@link MIN_GROK_BINARY_BYTES} (rejects wrapper/alias artifacts on size
 * alone, no content sniffing needed) and, among the survivors, prefer the most
 * recently modified — the file grok's self-updater actually wrote last.
 * Returns null (fail loud, never guess) when nothing survives the size filter.
 */
export declare function resolveGrokFallbackBinary(downloadsDir: string): string | null;
/**
 * Get the binary path for a specific agent version.
 */
export declare function getBinaryPath(agent: AgentId, version: string): string;
/**
 * Does this agent resolve to ONE global binary that is the same file regardless
 * of the `version` argument? (droid → always `~/.local/bin/droid`.) Computed
 * generically by probing `getBinaryPath` with two distinct versions rather than
 * hardcoding an agent id, so it stays correct if another global-binary agent is
 * added.
 *
 * This is the narrower cousin of `isSelfUpdatingAgent`: every global-binary
 * agent is self-updating, but grok is self-updating WITHOUT a global binary — it
 * stores a real per-version binary copy under each version-home
 * (`versions/grok/<v>/home/.grok/downloads/grok-<v>`), so its version-homes are
 * genuinely distinct and must NOT be collapsed. Gate the single-binary
 * collapse/live-version logic on THIS predicate; gate pin-refusal / "switch
 * profile" copy on `isSelfUpdatingAgent`.
 */
export declare function isGlobalBinaryAgent(agent: AgentId): boolean;
/** Drop the live-version cache (call after an install/remove that changes the
 * running binary, e.g. `agents add droid@latest`). */
export declare function invalidateLiveVersionCache(agent?: AgentId): void;
/**
 * Resolve the version the ONE globally-installed binary actually reports via
 * `<cli> --version`, cached for {@link LIVE_VERSION_TTL_MS}. For a self-updating
 * global-binary agent (droid) this is the single source of truth for "which
 * version is installed" — the on-disk version-dir NAMES are just stale labels
 * left behind by successive `agents add`/self-update cycles. Returns null when
 * the binary isn't on PATH or the probe fails.
 */
export declare function getCliVersionFromPath(agent: AgentId): Promise<string | null>;
export declare function getLiveVersion(agent: AgentId): Promise<string | null>;
/**
 * Synchronous, non-blocking read of the live-version cache — returns the value
 * only if a recent {@link getLiveVersion} call already warmed it, else null.
 * `listInstalledVersions` is sync and must not shell out, so it prefers this
 * warm value (accurate) and otherwise falls back to the newest on-disk dir.
 */
export declare function getCachedLiveVersion(agent: AgentId): string | null;
/**
 * Get the isolated HOME directory for a specific agent version.
 * Each version has its own config isolation (like jobs sandbox).
 */
export declare function getVersionHomePath(agent: AgentId, version: string): string;
/**
 * Check if a specific version is installed.
 *
 * Probes the actual launch binary (the same executable the shims run), not just
 * the version dir or the node_modules/.bin/<cli> wrapper. For npm agents that
 * means statting the package's real `bin` target (getPackageBinaryPath), so a
 * present-but-gutted install (vendor auto-updater destroyed the binary) reports
 * as NOT installed and `agents add` re-runs its install step to repair it.
 */
export declare function isVersionInstalled(agent: AgentId, version: string): boolean;
/** Drop the installed-versions cache (call after install/remove mutations). */
export declare function invalidateInstalledVersionsCache(agent?: AgentId): void;
/**
 * Choose the single canonical version-dir to represent a self-updating
 * global-binary agent (droid). All its version dirs map to ONE binary, so
 * exactly one is real; the rest are stale labels. Prefer, in order: the dir the
 * live config symlink points at (what actually runs), the recorded global
 * default, the live `--version` (when the cache is warm), else the newest dir.
 * `versions` MUST be sorted ascending. Callers guarantee it is non-empty.
 */
export declare function pickCanonicalGlobalBinaryVersion(agent: AgentId, versions: string[]): string;
/**
 * List all installed versions for an agent (cached by versions-dir mtime).
 *
 * For a self-updating global-binary agent (droid) every version dir resolves to
 * the SAME binary, so this collapses them to a single canonical entry — one
 * install, one row in `agents view`, never the phantom set of semver dir names.
 */
export declare function listInstalledVersions(agent: AgentId): string[];
/**
 * Get the global default version for an agent.
 */
export declare function getGlobalDefault(agent: AgentId): string | null;
/**
 * Get the preferred ISOLATED version for an agent — the copy a bare
 * `agents run <agent>` falls back to when there is no global default.
 */
export declare function getIsolatedDefault(agent: AgentId): string | null;
/**
 * Mark an installed version as an isolated install (`agents add --isolated`).
 *
 * Isolated versions are fully self-contained: they never become the global
 * default and never own the user's real `~/.<agent>` config directory. This
 * flag is what keeps every "adopting" code path away from them.
 */
export declare function markVersionIsolated(agent: AgentId, version: string): void;
/**
 * Whether a version was installed as an isolated install (`agents add --isolated`).
 *
 * Used to exclude such versions from global-default promotion and from any
 * flow that would touch the user's real `~/.<agent>` directory, and to gate the
 * `--isolated` safety check on `agents remove`.
 */
export declare function isVersionIsolated(agent: AgentId, version: string): boolean;
/**
 * Get version specified in a project-root agents.yaml (not the user ~/.agents/.system/agents.yaml).
 */
export declare function getProjectVersion(agent: AgentId, startPath: string): string | null;
/**
 * Get the resolved version for an agent in the current context.
 * Checks project manifest first, then global default.
 */
export declare function resolveVersion(agent: AgentId, projectPath?: string): string | null;
/**
 * Get the effective HOME directory for an agent.
 * If version-managed with a resolved version, returns the version's home directory.
 * Otherwise returns the real HOME.
 */
export declare function getEffectiveHome(agentId: AgentId): string;
