import type { AgentConfig, AgentId } from '../types.js';
/** Represents the installation state of an agent's CLI binary. */
export interface CliState {
    installed: boolean;
    version: string | null;
    path: string | null;
}
/**
 * Minimum Codex CLI version that supports hooks.
 * Mirrored on `AGENTS.codex.capabilities.hooks.since` -- kept exported for
 * legacy import sites that haven't migrated to `supports()` yet.
 */
export declare const CODEX_HOOKS_MIN_VERSION = "0.116.0";
/** Minimum Gemini CLI version that supports the hooks system (v0.26.0, Jan 2026). */
export declare const GEMINI_HOOKS_MIN_VERSION = "0.26.0";
/**
 * Synchronous PATH search -- no subprocess. Returns first matching binary path.
 *
 * Skips our own shims dir (`~/.agents/.cache/shims/`) — those shims are
 * dispatch helpers, not real installs. Counting them as installed produced a
 * false positive where agents with NO real binary on the host (e.g. a
 * never-installed Cursor whose only PATH entry was our `cursor-agent` shim
 * dispatcher) showed up under `agents view`'s "Not Managed by Agents CLI"
 * section, even though the user had nothing to import.
 */
interface NativeBinaryResolutionOptions {
    shimsDir?: string;
    historyDir?: string;
}
/**
 * Resolve a PATH candidate to the immutable native executable agents-cli may
 * safely register. An adopted launcher can live outside the shims directory
 * while resolving back into it; in that case its durable adoption record is
 * the source of truth for the original executable.
 */
export declare function resolveNativeBinaryPath(command: string, candidate: string, options?: NativeBinaryResolutionOptions): string | null;
export declare function findInPath(command: string, options?: NativeBinaryResolutionOptions): string | null;
/**
 * Per-harness dispatch data that used to live in `if (agentId === …)` /
 * `switch (agentId)` arms inside this file. These are stable properties of a
 * harness, not per-call-site quirks — a new AgentId must declare every field
 * (the completeness test in agents.test.ts pins that).
 *
 * Left as call-site specials (not registry data): `getAccountInfo` and
 * `readAuthAccountIdentity` — those are parsers, not flags.
 */
export type VersionStdoutMatch = 'semver' | 'openclaw';
export type UnmanagedBinaryResolver = 'path' | 'grok-downloads';
export type McpRegisterPath = 'cli' | 'config';
export type McpAddHttpStyle = 'transport' | 'url';
export type McpAddStdioStyle = 'scope' | 'simple';
export type McpConfigWriteStyle = 'json-mcpServers' | 'yaml-mcp_servers';
export interface AgentRegistryConfig extends AgentConfig {
    /**
     * Session-transcript directory as path segments under a HOME root, or null
     * when this harness has no local session tree `agents` can walk.
     */
    sessionDir: string[] | null;
    /** File extension of session transcripts, or null when unknown. */
    sessionFileExt: '.jsonl' | '.json' | null;
    /** How to parse `cli --version` stdout. */
    versionStdoutMatch: VersionStdoutMatch;
    /** How to find an unmanaged (non-version-home) binary. */
    unmanagedBinary: UnmanagedBinaryResolver;
    /**
     * How `registerMcp` / `unregisterMcp` talk to the harness. `config` writes
     * the file directly (no `mcp add` CLI); `cli` shells out.
     */
    mcpRegister: McpRegisterPath;
    /** Argv shape for `mcp add` over HTTP. */
    mcpAddHttp: McpAddHttpStyle;
    /** Argv shape for `mcp add` over stdio. */
    mcpAddStdio: McpAddStdioStyle;
    /** On-disk map key + serialization when writing MCP config directly. */
    mcpConfigWrite: McpConfigWriteStyle;
}
/**
 * Master registry of all supported agents keyed by AgentId.
 *
 * Each entry defines the agent's CLI command, npm package, config directory layout,
 * instructions file name, slash-command format, and capability flags. This is the
 * single source of truth for agent metadata consumed throughout the codebase.
 */
export declare const AGENTS: Record<AgentId, AgentRegistryConfig>;
/** All current and legacy agent IDs derived from the AGENTS registry. */
export declare const ALL_AGENT_IDS: AgentId[];
/**
 * Agents the routine daemon can fire locally. Lives here (not runner.ts) so
 * routines.ts can import it for schedule-time validation without a circular
 * import (runner.ts already imports from routines.ts).
 *
 * This is a curated subset of AGENT_COMMANDS, not "every harness that can run
 * headlessly". Expanding it is a product change (gemini is hard-deprecated and
 * is deliberately absent). Argv itself is baked from AGENT_COMMANDS in
 * daemon/runner.ts bakeRoutineArgv — do not reintroduce a second token table.
 */
export declare const ROUTINE_AGENT_IDS: readonly string[];
/** Agents retained only for legacy reads, not install/import/sync targets. */
export declare const HARD_DEPRECATED_AGENT_IDS: AgentId[];
/** Agents that can receive managed installs, imports, and resource sync writes. */
export declare const MANAGED_AGENT_IDS: AgentId[];
/**
 * A self-updating agent is a single global binary installed by an official
 * `curl … | sh` / `brew install` script that carries NO version token — the
 * installer can only ever fetch the *current* release, and the binary then keeps
 * itself up to date in place (droid, grok, antigravity, cursor, hermes,
 * goose). There is no semver to pin, so agents-cli must not model these as
 * having multiple installable version-homes the way it does for npm-packaged
 * agents (claude, codex, kimi, …).
 *
 * The predicate is `!npmPackage && installScript && !installScript.includes('VERSION')`:
 *   - `npmPackage` empty       → not installed from npm, so `agents add x@1.2.3`
 *                                can't resolve a registry version.
 *   - `installScript` present  → it IS installed by a script (not unmanaged).
 *   - no `VERSION` placeholder → the script has no slot for a pinned version
 *                                (contrast: an installer templated with `VERSION`
 *                                could pin, and is NOT self-updating).
 *
 * Route every "is this a pinnable, multi-version agent?" decision through here —
 * never a scattered `agent === 'droid'`.
 */
export declare function isSelfUpdatingAgent(agent: AgentId): boolean;
export declare function isAgentHardDeprecated(agent: AgentId): boolean;
/** Get the chalk color function for an agent. Works for any AgentId or SessionAgentId. */
export declare function colorAgent(agentId: string): (s: string) => string;
/** Return the agent's display name, colored. */
export declare function agentLabel(agentId: string): string;
/** Check whether the given agent's CLI binary is present on PATH. */
export declare function isCliInstalled(agentId: AgentId): Promise<boolean>;
/** Return the installed CLI version for the given agent, or null if not found. */
export declare function getCliVersion(agentId: AgentId): Promise<string | null>;
/** Return the absolute path to the agent's CLI binary on PATH, or null. */
export declare function getCliPath(agentId: AgentId): Promise<string | null>;
/**
 * Resolve the full CLI state for an agent: whether it is installed, its version,
 * and the path to the binary. Checks version-managed installs first, then falls
 * back to a plain PATH lookup.
 */
export declare function getCliState(agentId: AgentId): Promise<CliState>;
/**
 * Resolve the agent's OWN install — the one agents-cli does not manage — by plain
 * PATH lookup, ignoring the version dirs entirely.
 *
 * Callers that specifically mean "the user's own globally-installed CLI" must use
 * this rather than `getCliState`, whose managed fast path reports an installed
 * version (any version dir, in readdir order) and would therefore hand back an
 * isolated copy — a copy that is deliberately unreachable from PATH — labelled as
 * the global install.
 */
export declare function getUnmanagedCliState(agentId: AgentId): Promise<CliState>;
/** Resolve CLI state for all registered agents in parallel. */
export declare function getAllCliStates(): Promise<Partial<Record<AgentId, CliState>>>;
/** Info about an existing unmanaged agent installation. */
export interface UnmanagedInstall {
    agentId: AgentId;
    configDir: string;
    version: string | null;
}
/**
 * Agents that `agents setup` probes for pre-existing native installations
 * (i.e., a config dir present before agents-cli took over). Derived from
 * `sessionDir` so a new harness cannot be walkable yet missing from setup.
 */
export declare const UNMANAGED_DETECTION_CANDIDATES: AgentId[];
/**
 * Detect existing agent installations that are NOT yet managed by agents-cli.
 * Returns agents whose config dir exists as a real directory (not a symlink).
 */
export declare function getUnmanagedAgentInstalls(): Promise<UnmanagedInstall[]>;
/** Create the agent's slash-commands directory if it does not exist. */
export declare function ensureCommandsDir(agentId: AgentId): void;
/** Create the agent's skills directory if it does not exist. */
export declare function ensureSkillsDir(agentId: AgentId): void;
/**
 * The agent's config-dir name relative to $HOME — e.g. '.claude',
 * '.gemini/antigravity-cli', '.config/amp', '.kimi-code'.
 *
 * Path segment to join onto a (version) home root when locating an agent's
 * commands/skills/plugins. Do NOT hardcode `.${agentId}`: it is wrong for
 * every agent whose config dir is nested or under ~/.config — antigravity
 * (~/.gemini/antigravity-cli), amp (~/.config/amp), goose (~/.config/goose),
 * kimi (~/.kimi-code). Mirrors the shim configDirName derivation in shims.ts.
 *
 * Relativized against the module-level HOME constant (the same value used to
 * build every `configDir`), NOT a fresh `os.homedir()` — so the result stays a
 * clean relative name even when HOME is overridden after module load (tests,
 * sandboxes). Using `os.homedir()` here would yield `../../real/home/.claude`.
 */
export declare function agentConfigDirName(agentId: AgentId): string;
/** Account identity and billing information extracted from an agent's auth config. */
export interface AccountInfo {
    accountKey: string | null;
    usageKey: string | null;
    accountId: string | null;
    organizationId: string | null;
    userId: string | null;
    email: string | null;
    plan: string | null;
    usageStatus: 'available' | 'rate_limited' | 'out_of_credits' | null;
    overageCredits: {
        amount: number;
        currency: string;
    } | null;
    lastActive: Date | null;
    signedIn: boolean;
    organizationType?: string | null;
    organizationName?: string | null;
}
/**
 * Human-readable label for a Claude account's organizationType as read from
 * .claude.json's oauthAccount ("claude_team" -> "Team"). Unrecognized values
 * (future tiers) are rendered by stripping the "claude_" prefix and
 * title-casing the rest — an unfamiliar-but-visible label beats silence.
 * Returns null for missing input.
 */
export declare function formatClaudeOrgLabel(orgType: string | null | undefined): string | null;
/**
 * Short badge identifying which ORG an account belongs to — "Turing Labs" for a
 * multi-seat Team/Enterprise org, whose name is real identity that disambiguates
 * a Team seat from a same-email personal plan. Returns null for personal plans
 * (Max/Pro/Free): the tier label now lives in the aligned plan column, so a badge
 * would only duplicate it, and a personal org's name is auto-generated boilerplate
 * ("<email>'s Organization"), not identity. Also null when the account carries no
 * organizationType (signed out, non-Claude agents, configs predating the field).
 */
export declare function accountOrgBadge(info?: Pick<AccountInfo, 'organizationType' | 'organizationName'> | null): string | null;
/** Agents whose local credential formats expose enough state for account selection. */
export declare const ACCOUNT_INSPECTION_AGENT_IDS: readonly ["claude", "codex", "gemini", "cursor", "grok", "antigravity", "kimi", "droid", "opencode", "muse"];
/** Whether agents-cli can determine this agent's per-version sign-in state. */
export declare function supportsAccountInspection(agentId: AgentId): boolean;
/**
 * Human-readable account identity shared by every account-aware surface.
 * Prefer email, append a multi-seat Claude organization name when present,
 * then fall back to a non-secret account id or a generic signed-in label.
 */
export declare function accountDisplayLabel(info?: Pick<AccountInfo, 'email' | 'accountId' | 'signedIn' | 'organizationType' | 'organizationName'> | null): string;
/** Return the email address associated with the agent's auth config, or null. */
export declare function getAccountEmail(agentId: AgentId, home?: string): Promise<string | null>;
/** Where an agent's credential file lives, split into the per-version copy and
 *  the active/global copy under the real HOME. */
export interface CredentialPresence {
    /** The credential file exists inside the passed version home. */
    perVersion: boolean;
    /** The credential file exists under the active/global HOME (the one the login
     *  symlink actually targets), independent of the version home. */
    active: boolean;
    /** Whether agents-cli knows WHERE this agent's credential lives at all — i.e.
     *  the agent has an entry in {@link CREDENTIAL_FILE_SEGMENTS}. When false both
     *  probes are trivially false because there is nothing to look for, so absence
     *  is NOT evidence of a logout and no caller may treat it as provable.
     *
     *  This is deliberately separate from `supportsAccountInspection`: the two
     *  registries move independently, and an agent has already been added to the
     *  inspection set without a credential path (cursor), which without this flag
     *  produced a false "logged out" critical for every installed version. */
    knownLocation: boolean;
}
/**
 * File-presence probe for an agent's credential, split by location: whether it
 * exists in a SPECIFIC version home (`perVersion`) and whether it exists under
 * the active/global HOME (`active`). A logged-out claim is only *provable* when
 * BOTH are absent — a version that merely lacks its own copy but shares the
 * global login is signed in, not logged out. Pure file existence; no decrypt,
 * no network, no keychain prompt. Agents with no inspectable identity return
 * `{ perVersion: false, active: false }` and must NEVER yield a provable-logout
 * claim (the caller gates on {@link supportsAccountInspection}).
 */
export declare function credentialPresence(agentId: AgentId, versionHome: string): CredentialPresence;
/** Decrypted contents of Droid's auth.v2.file (subset we consume). */
export interface DroidAuthPayload {
    access_token?: string;
    active_organization_id?: string | null;
}
/**
 * Factory Droid stores its OAuth credential encrypted at ~/.factory/auth.v2.file
 * (AES-256-GCM, format `ivB64:tagB64:ctB64`) with the 32-byte key base64-stored
 * in ~/.factory/auth.v2.key. On the keyfile-v2 source there is no OS-keychain /
 * device binding — the key is on disk — so we can decrypt locally with no
 * network call. Every failure (missing key file — e.g. a keyring-v2/legacy
 * login with no on-disk key, a bad GCM tag, or malformed JSON) returns null.
 * Never throws. Shared by account identity below and the Droid usage fetcher
 * in usage.ts.
 */
export declare function decryptDroidAuthPayload(base: string): DroidAuthPayload | null;
/**
 * Decrypt a Droid `auth.v2.file` (AES-256-GCM `ivB64:tagB64:ctB64`) using the
 * raw 32-byte key stored base64 in `auth.v2.key`, given the EXACT paths to both.
 * Same crypto as decryptDroidAuthPayload but without the account-global HOME
 * fallback, so the identity of a SPECIFIC version home resolves against only
 * that home's files (carryForwardAuthFiles needs per-dir identity). Returns null
 * on any failure (missing file/key, wrong key length, bad GCM tag, malformed
 * JSON). Never throws.
 */
export declare function decryptDroidAuthFile(filePath: string, keyPath: string): DroidAuthPayload | null;
/**
 * Stable account identity for a *file-auth* agent's credential directory
 * (droid / kimi / antigravity), or null when the directory holds no decodable
 * account claim. Unlike a naive top-level JSON key-scan (which matched NO real
 * credential file), this decrypts / decodes each agent's REAL on-disk format so
 * the identity resolves against production credentials:
 *   - droid: AES-256-GCM auth.v2.file (+ auth.v2.key) -> WorkOS access-token JWT
 *     -> email / org_id / sub.
 *   - kimi: credentials/kimi-code.json -> access-token JWT -> user_id / sub.
 *   - antigravity: antigravity-oauth-token -> token.refresh_token -> JWT sub
 *     when the token is a JWT, else a SHA-256 hash of the raw refresh-token
 *     value (opaque Google consumer tokens are stable per login — hashed so
 *     the identity key, which is persisted as a usage-cache key, never carries
 *     a live credential).
 * Two directories for the SAME account compare equal; two DIFFERENT accounts
 * compare distinct. Used by carryForwardAuthFiles to refuse overwriting one
 * account's login with a credential that belongs to a DIFFERENT account
 * (RUSH-1764). Never throws.
 */
export declare function readAuthAccountIdentity(agent: AgentId, configDir: string): string | null;
/**
 * Antigravity (`agy`) stores its OAuth token via the Go keyring library
 * (zalando/go-keyring), which is platform-split:
 *
 *   - macOS: login keychain, service `gemini`, account `antigravity` — no file.
 *   - Linux with Secret Service (libsecret / gnome-keyring): attributes
 *     service=`gemini`, username=`antigravity` (go-keyring's Secret Service
 *     mapping of service+user). Prefer this over the file when a keyring
 *     daemon is running.
 *   - Linux without Secret Service: file fallback at
 *     `~/.gemini/antigravity-cli/antigravity-oauth-token`.
 *
 * Probe the OS keyring for existence after the file check. On macOS,
 * `security find-generic-password` without `-w` is metadata-only (never
 * prompts). On Linux, `secret-tool lookup` exit 0 means the item exists
 * (stdout is the secret — discarded, never logged). Cached per process —
 * the keyring is account-global, so one probe covers every installed version.
 * Returns false when the platform has no probe (Windows) or the tool is
 * missing. Guard with `AGENTS_NO_KEYCHAIN_PROBE=1` for hermetic tests.
 */
export declare function antigravityOsKeyringProbe(platform?: NodeJS.Platform): {
    cmd: string;
    args: string[];
} | null;
/** @internal test hook — clear the per-process keyring probe cache. */
export declare function __resetAntigravityKeychainCacheForTest(): void;
/**
 * OpenCode's account identity: the sorted, "+"-joined list of provider ids
 * that hold a valid credential in `auth.json` (e.g. `"anthropic+muse-spark"`).
 * `auth.json` carries no email/identity claim (see `isValidOpenCodeCredential`),
 * so this join is the closest thing to "which account is this" available — the
 * same value `agents view`/`agents doctor` show for OpenCode's signed-in state.
 *
 * This is the ONLY correct source for an OpenCode "account". OpenCode's SQLite
 * `opencode.db` also carries `account`/`account_state`/`control_account` tables,
 * but on a real, actively-used install (yosemite-s1, 1.16.0, 35 applied
 * migrations) all three are permanently empty — no migration ever populates
 * them, and no session has ever written a row. Reading from them instead of
 * `auth.json` always yields `undefined`, credential or not; `session/discover.ts`
 * uses this function rather than duplicating a sqlite lookup against those
 * dead tables.
 *
 * Sync (`fs.readFileSync`), no network. Returns undefined when `auth.json` is
 * missing, unreadable, or carries no valid credential.
 */
export declare function resolveOpenCodeAccountId(base: string): string | undefined;
/**
 * Whether a Claude version home's credential file is present but carries no
 * token — the "must have a real credential" floor (see
 * `isValidOpenCodeCredential`) applied to claude.
 *
 * A FAILED OAuth refresh leaves exactly this state behind: Claude Code rewrites
 * `.claude/.credentials.json` with `accessToken: ""`, `refreshToken: ""` and
 * `expiresAt: 0`, keeping only the descriptive fields (`subscriptionType`,
 * `rateLimitTier`, `refreshTokenExpiresAt`). Everything we derive from
 * `.claude.json` — email, plan — still looks healthy, so the install reported
 * `signedIn: true`, `agents view` drew usage bars for it, and balanced rotation
 * (whose `authValid` is just "email present") kept picking it — every pick dying
 * at spawn on "OAuth session expired and could not be refreshed".
 *
 * Only decidable off macOS: there the login Keychain is the canonical store and
 * this file is not authoritative, and probing the Keychain would raise an
 * authorization sheet per installed version on every `agents run` — the reason
 * rotation stopped calling `isClaudeAuthValid` at all. Off macOS the file IS the
 * only store, so a missing or token-less file is proof of signed-out — unless a
 * Linux setup-token (`.claude/.oauth_token`) is present, which the shim exports
 * as `CLAUDE_CODE_OAUTH_TOKEN` and can authenticate the run without
 * `.credentials.json`. `platform` is a parameter so both branches are testable
 * on any host.
 *
 * Sync, no Keychain, no network — safe on the `agents run` hot path.
 */
export declare function isClaudeCredentialFileBlank(base: string, platform?: NodeJS.Platform): boolean;
/**
 * Identity of the Claude account a version home is (or was) logged into, read
 * straight from `.claude.json`'s `oauthAccount`.
 *
 * Deliberately independent of whether the credential still works. `getAccountInfo`
 * applies a credential floor so `agents view` and rotation route around an install
 * that would die at spawn; attribution of *history* must not. A transcript written
 * under an org is still that org's work after the token is revoked or the home is
 * trashed, and on Linux/Windows the floor would otherwise erase the identity of
 * every retired home (`isClaudeCredentialFileBlank` short-circuits only on darwin).
 */
export interface ClaudeHomeIdentity {
    email: string | null;
    accountId: string | null;
    organizationId: string | null;
    organizationName: string | null;
    organizationType: string | null;
    /**
     * Org-scoped identity — the rate-limit bucket, and the correct key to group by.
     * Two orgs under one email (a Team seat and a personal Max plan) are separate
     * buckets and MUST stay distinct; see `candidateIdentity` in lib/rotate.ts.
     */
    usageKey: string | null;
    /** Account+org identity, narrower than `usageKey`. */
    accountKey: string | null;
}
/** A version home's `.claude.json` plus the identity derived from it. */
export interface ClaudeHomeConfig {
    /** The config file actually read. */
    path: string;
    config: Record<string, any>;
    identity: ClaudeHomeIdentity;
}
/**
 * Read a Claude home's config and account identity. Returns null when the home has
 * no readable `.claude.json`, or has one with no `oauthAccount` (never signed in).
 *
 * Sync because the session scanner calls it once per home on a hot path, and the
 * file is a few KB of local JSON. No Keychain access — see `getAccountInfo`.
 */
export declare function readClaudeHomeConfig(base: string): ClaudeHomeConfig | null;
export declare function getAccountInfo(agentId: AgentId, home?: string): Promise<AccountInfo>;
/**
 * Determine when the agent was last used by checking session file mtimes,
 * falling back to config mtime.
 *
 * The session walk stats every transcript under the home's session dir —
 * thousands of files on long-lived installs — and `agents run` rotation calls
 * this once per installed version on every launch. The walk result is cached
 * on disk for a short window so back-to-back launches skip it entirely.
 * Cache read/write is best-effort: any failure falls back to walking.
 */
export declare function resolveLastActive(agentId: AgentId, base: string, configPath?: string, cachePath?: string, now?: Date): Date | null;
/**
 * Quick count of session files for an agent (without full DB scan).
 * Used during init to show approximate session count to user.
 */
export declare function countSessionFiles(agentId: AgentId): number;
/** Decode the payload section of a JWT token without verifying its signature. */
export declare function decodeJwtPayload(token: string): Record<string, any> | null;
/** Register an MCP server with an agent's CLI via `mcp add`. */
export declare function registerMcp(agentId: AgentId, name: string, command: string, scope?: 'user' | 'project', transport?: string, options?: {
    home?: string;
    binary?: string;
    headers?: Record<string, string>;
}): Promise<{
    success: boolean;
    error?: string;
}>;
/** Unregister (remove) a named MCP server from an agent's CLI config. */
export declare function unregisterMcp(agentId: AgentId, name: string, options?: {
    home?: string;
    binary?: string;
}): Promise<{
    success: boolean;
    error?: string;
}>;
/** Result of an MCP registration or removal operation targeting a specific agent and optional version. */
export interface McpTargetOperationResult {
    agentId: AgentId;
    version?: string;
    success: boolean;
    error?: string;
}
/**
 * Register an MCP server across multiple agent targets, including both direct
 * (non-version-managed) agents and specific version-managed installs.
 */
export declare function registerMcpToTargets(targets: {
    directAgents: AgentId[];
    versionSelections: Map<AgentId, string[]>;
}, name: string, command: string, scope?: 'user' | 'project', transport?: string, options?: {
    headers?: Record<string, string>;
}): Promise<McpTargetOperationResult[]>;
/**
 * Unregister an MCP server from multiple agent targets, including both direct
 * agents and specific version-managed installs.
 */
export declare function unregisterMcpFromTargets(targets: {
    directAgents: AgentId[];
    versionSelections: Map<AgentId, string[]>;
}, name: string): Promise<McpTargetOperationResult[]>;
/** Scope at which an MCP server is registered: user-global or per-project. */
export type McpScope = 'user' | 'project';
/** Describes an MCP server discovered in an agent's config, with its scope and command. */
export interface InstalledMcp {
    name: string;
    scope: McpScope;
    command?: string;
    version?: string;
}
interface McpConfigEntry {
    command?: string;
    args?: string[];
    env?: Record<string, string>;
    type?: string;
    url?: string;
}
/**
 * Strip JSON comments for JSONC parsing.
 * Only removes comments outside of strings.
 *
 * Exported because the MCP writer needs the SAME parser the reader uses: a
 * naive `//`-to-end-of-line regex eats the `//` inside
 * `"$schema": "https://opencode.ai/config.json"`, which every opencode-generated
 * config carries.
 */
export declare function stripJsonComments(content: string): string;
/**
 * Get user-scoped MCP config path for an agent.
 *
 * All three MCP path resolvers read `MCP_TARGETS`, so the file the writer
 * targets, the file the parser reads, and the file the staleness detector
 * watches cannot drift apart. An agent with no MCP target (the hard-deprecated
 * `gemini`) keeps the historical settings.json default so old configs still
 * parse.
 */
export declare function getUserMcpConfigPath(agentId: AgentId): string;
/**
 * Get MCP config path for a specific HOME directory (used for version-managed agents).
 */
export declare function getMcpConfigPathForHome(agentId: AgentId, home: string): string;
/**
 * Get project-scoped MCP config path for an agent.
 */
export declare function getProjectMcpConfigPath(agentId: AgentId, cwd?: string): string;
/**
 * Parse MCP config based on agent type.
 */
export declare function parseMcpConfig(agentId: AgentId, configPath: string): Record<string, McpConfigEntry>;
/**
 * List installed MCP servers with scope information.
 * Pass options.home to read from a version-managed agent's home directory.
 */
export declare function listInstalledMcpsWithScope(agentId: AgentId, cwd?: string, options?: {
    home?: string;
}): InstalledMcp[];
/** Map of agent name aliases and shorthand identifiers to canonical AgentId values. */
export declare const AGENT_NAME_ALIASES: Record<string, AgentId>;
/**
 * Resolve a user-provided agent name (alias, shorthand, or canonical) to its AgentId.
 * Tolerates a single typo (insertion/deletion/substitution/transposition) against
 * canonical ids and aliases — `cladue` -> claude, `kim` -> kimi, `codx` -> codex —
 * but only when the correction is unambiguous (all distance-1 candidates agree on
 * one agent). Two-letter shorthands are excluded as fuzzy candidates.
 */
export declare function resolveAgentName(input: string): AgentId | null;
/** Check whether the input string matches any known agent name or alias. */
export declare function isAgentName(input: string): boolean;
/**
 * Split a CLI-provided `<agent>[@<version>][#<label>]` spec into its bare agent
 * id, optional exact version token, and optional account label, the same way
 * `agents run` does — NOT the
 * agent-spec qualifier engine (`@latest`/`@all`), which enumerates installed
 * versions for read/diagnostic commands, not a single launch target. Returns an
 * error message rather than throwing so callers decide exit-vs-continue.
 */
export declare function parseAgentVersionSpec(raw: string): {
    agent: AgentId;
    version?: string;
    label?: string;
} | {
    error: string;
};
/**
 * Build the deprecation notice lines for an agent, or null if it isn't
 * deprecated. Split from the printer so tests can assert the content without
 * capturing stdout. Lines are plain (uncolored) text.
 */
export declare function deprecationNotice(agent: AgentId): string[] | null;
export declare function hardDeprecationNotice(agent: AgentId): string[] | null;
export declare function hardDeprecationError(agent: AgentId): string;
/**
 * Print a deprecation warning (yellow) if the agent's registry entry carries a
 * `deprecated` marker; no-op otherwise. Call from any user entry point that
 * acts on a chosen agent — install (`agents add`) and `agents teams add`.
 */
export declare function warnAgentDeprecated(agent: AgentId): void;
/** Format an error message for an unrecognized agent name, listing valid options. */
export declare function formatAgentError(agentName: string, validAgents?: AgentId[]): string;
export {};
