/**
 * Profile management -- named bundles of (host CLI, endpoint, model, auth).
 *
 * Profiles let users run agents against alternative providers (OpenRouter,
 * custom endpoints) without reconfiguring the agent CLI itself. Stored as
 * YAML files under ~/.agents/profiles/.
 */
import type { AgentId } from './types.js';
import { type Preset } from './profiles-presets.js';
import { type ModelTier } from './model-tiers.js';
/** A named profile binding an agent host, env vars, and optional keychain auth. */
export interface Profile {
    name: string;
    host: {
        agent: AgentId;
        version?: string;
    };
    env: Record<string, string>;
    /** Default durable credential account. A per-run --account overrides it. */
    account?: string;
    auth?: {
        envVar: string;
        keychainItem: string;
    };
    /**
     * When true, the host manages its own login and the keychain token named by
     * `auth` is optional: if it is not stored, no auth env var is injected and the
     * run proceeds on the host's own credentials (e.g. `opencode auth`). Without
     * this flag a missing keychain item is a hard error at exec time.
     */
    authOptional?: boolean;
    description?: string;
    preset?: string;
    provider?: string;
    /**
     * Stored for backward-compatible YAML parsing only — no longer read for
     * display. `profileLabel()` always derives the display name from `name` via
     * the vendor/brand table. Old YAML files that carry this key still parse
     * correctly; it is simply ignored.
     */
    label?: string;
    /**
     * Name of the harness this one was forked from — either a native agent id
     * (`claude`, `opencode`) or another custom harness. Display-only lineage:
     * the fork is a full copy, so deleting the source never affects it.
     */
    forkedFrom?: string;
    /**
     * Optional secondary model retried on the same host when the primary model
     * env value hits a rate limit. Reuses the `--fallback` cascade in
     * `runWithFallback` (src/lib/exec.ts) — the swap is expressed as an
     * envOverride on a same-agent FallbackEntry, so only the model env var
     * changes; auth, base URL, and every other profile env value are preserved.
     */
    fallback_model?: string;
    /**
     * Per-tier model ids for this harness's OWN catalog, keyed by the same cost
     * tiers `agents run --model cheap|default|best|ultra` uses for a native
     * agent. Lets a custom harness (which runs through a host agent's binary,
     * e.g. `deepseek-flash` hosted on `claude`) resolve a tier against its own
     * models instead of colliding with the host agent's native catalog
     * (`resolveTier` in model-tiers.ts, which only knows native agents).
     * An unset tier clamps to the next CHEAPER tier that IS set (see
     * `resolveProfileTierModel`). Omitted entirely -> tiers are not supported
     * for this profile and a requested tier falls back to the harness's single
     * pinned model, unchanged from before this field existed.
     */
    models?: Partial<Record<ModelTier, string>>;
}
/**
 * Stable, machine-readable summary used by `agents view` and `--json`.
 * `agent` is the underlying harness (claude/codex/...) so consumers can
 * group profiles under installed agents without reparsing host strings.
 */
export interface ProfileSummary {
    name: string;
    /** Human-facing header label — always derived from `name` via the vendor/brand table. */
    label: string;
    agent: AgentId;
    host: string;
    /** Host version pin, or null when the harness follows the host's default. */
    hostVersion: string | null;
    provider: string;
    model: string;
    auth: string;
    path: string;
    description: string | null;
    /** Native agent id or custom harness this one was forked from, if recorded. */
    forkedFrom: string | null;
}
/** Get the directory where profile YAML files are stored. */
export declare function getProfilesDir(): string;
/** Return the on-disk YAML path for a profile name. */
export declare function getProfilePath(name: string): string;
/** Validate a profile name against the allowed pattern. Throws on invalid input. */
export declare function validateProfileName(name: string): void;
/** Check whether a profile YAML file exists on disk. */
export declare function profileExists(name: string): boolean;
/**
 * True when `name` is a custom harness (a profile that is not shadowing a
 * native agent id) — the predicate routines/monitors use to accept an
 * `agent:` value that `agents run` will resolve as a profile. A native id
 * always reads as native, matching exec's resolution order.
 */
export declare function isCustomHarnessName(name: string): boolean;
/** Read and parse a profile from disk. Throws if not found or malformed. */
export declare function readProfile(name: string): Profile;
/** Write a profile to disk atomically (write-to-tmp then rename). */
export declare function writeProfile(profile: Profile): void;
/** Delete a profile from disk. Returns false if it did not exist. */
export declare function deleteProfile(name: string): boolean;
/** List all valid profiles, sorted by name. Malformed files are silently skipped. */
export declare function listProfiles(): Profile[];
/** Format the host harness and optional pinned version for display. */
export declare function profileHostLabel(profile: Profile): string;
/** Return the configured provider name, deriving it from the shared keychain item when needed. */
export declare function profileProviderLabel(profile: Profile): string;
/** Return the configured model env value for display. */
export declare function profileModelLabel(profile: Profile): string;
/**
 * Return the env var key that carries this profile's model (e.g.
 * `ANTHROPIC_MODEL`), or null when the profile has no recognizable model env.
 * `fallback_model` swaps THIS key so provider selection, auth, and base URL
 * are all preserved on retry.
 */
export declare function profileModelEnvKey(profile: Profile): string | null;
/**
 * Build a non-secret auth identity/status label for list surfaces.
 *
 * - Inline JWT in env: decode locally and show email / preferred_username / sub.
 * - Inline opaque token in env: masked prefix/suffix (user explicitly stored it
 *   in the YAML, so they accept the leak in their own output).
 * - Keychain-backed auth: provider + "stored" or "missing" (non-prompting).
 * - No auth at all: provider only.
 */
export declare function profileAuthLabel(profile: Profile): string;
/**
 * Header label for the harness — derived from `profile.name` by splitting on
 * `[-_]` and mapping each token through the vendor/brand table. Never reads
 * the stored `label` field; old YAML files with a `label:` key are unaffected.
 *
 * Examples: `deepseek-flash` → `'DeepSeek Flash'`, `spark` → `'Spark'`,
 * `deepseek_chat_v3` → `'DeepSeek Chat V3'`.
 */
export declare function profileLabel(profile: Profile): string;
/** Build a stable, machine-readable summary for list and view surfaces. */
export declare function profileSummary(profile: Profile): ProfileSummary;
/**
 * Build a profile from a preset. The keychain item is shared across all
 * profiles that point at the same provider, so adding kimi + deepseek prompts
 * for the OpenRouter key exactly once.
 */
export declare function profileFromPreset(profileName: string, preset: Preset, version?: string): Profile;
/** Return the model-override env var for a host (known hosts mapped; else `<HOST>_MODEL`). */
export declare function modelEnvKeyForHost(host: AgentId): string;
/** Return the base-URL env var for a host, or null when the host has no known override var. */
export declare function baseUrlEnvKeyForHost(host: AgentId): string | null;
/** Return the auth-token env var for a host, or null when unknown. */
export declare function authEnvKeyForHost(host: AgentId): string | null;
/** Options for {@link profileFromHostModel}. */
export interface HostModelOptions {
    version?: string;
    /** Base URL for OpenAI/Anthropic-compatible hosts (claude, codex). Ignored for hosts without a known var. */
    baseUrl?: string;
    /** Provider label + keychain namespace; only needed when the host requires a token. */
    provider?: string;
    /** Env var the host reads its auth token from; pair with `provider` to attach keychain auth. */
    authEnvVar?: string;
    description?: string;
}
/**
 * Build a custom-harness profile from a host CLI + model in one shot, without a
 * preset. The model lands on the host's model env var ({@link modelEnvKeyForHost});
 * auth is attached only when both `provider` and `authEnvVar` are supplied
 * (hosts that manage their own login — e.g. opencode — need neither).
 */
export declare function profileFromHostModel(name: string, host: AgentId, model: string, opts?: HostModelOptions): Profile;
/** Overrides applied on top of the source when forking a harness. */
export interface ForkProfileOptions {
    /** Translate the fork onto a different native harness host. */
    host?: AgentId;
    /** Swap the pinned model. Written onto the source's model env key when it has
     *  one, else onto the host's canonical model var. */
    model?: string;
    /** Swap the endpoint. Only applied for hosts with a known base-URL var. */
    baseUrl?: string;
    /** Repoint auth at a different provider's keychain item. */
    provider?: string;
    /** Env var the host reads its token from; pair with `provider`. */
    authEnvVar?: string;
    /** Re-pin (or unpin, with an empty string) the host CLI version. */
    version?: string;
    description?: string;
}
/**
 * Copy an existing harness under a new name, applying overrides. The fork is a
 * full copy — env, auth binding, and fallback model all carry over — so the two
 * diverge from here and deleting the source never affects the fork.
 */
export declare function forkProfile(source: Profile, name: string, opts?: ForkProfileOptions): Profile;
/**
 * Edit an existing profile in-place, applying overrides without changing its
 * name or lineage. Reuses {@link forkProfile}'s validation and override logic
 * (model swap, base-URL validation, auth repoint), then restores the original
 * `forkedFrom` so an edit never self-references the profile.
 *
 * Note: this returns the updated `Profile` object but does NOT write it to
 * disk — callers should follow up with `writeProfile(result)` if persistence
 * is needed.
 */
export declare function editProfile(source: Profile, opts?: ForkProfileOptions): Profile;
/**
 * Rename a profile on disk, then rewrite `forkedFrom` in every other profile
 * that pointed at the old name so lineage display never goes stale.
 *
 * Throws if `oldName` does not exist or `newName` already exists. There is no
 * `--force` / overwrite path — a collision is a hard error directing the user
 * to remove the target first.
 */
export declare function renameProfile(oldName: string, newName: string): void;
/**
 * Resolve a profile into the env block that should be injected into the
 * spawned agent process. Reads the token from keychain at exec time so the
 * profile YAML never holds secrets.
 */
export declare function resolveProfileEnv(profile: Profile): Record<string, string>;
/** Resolved profile data ready for spawning an agent process. */
export interface ResolvedProfileRun {
    agent: AgentId;
    version?: string;
    env: Record<string, string>;
    profileName: string;
    /**
     * Same-host model swap for the `--fallback` cascade. Present only when the
     * profile declares `fallback_model` AND the profile has an identifiable
     * model env key to swap. `envKey` names the var (e.g. `ANTHROPIC_MODEL`),
     * `model` is the value to write on the retry attempt.
     */
    fallbackModel?: {
        envKey: string;
        model: string;
    };
    /**
     * Set when the caller requested a cost tier (`--model cheap|default|...`)
     * but this profile has no `models:` entry to resolve it against (not even a
     * cheaper tier to clamp to). `env` is returned unmodified — the harness's
     * single pinned model — and this note is informational only, matching the
     * "using harness default" convention exec.ts's native tier block already
     * uses; the caller prints it, it never throws.
     */
    tierNote?: string;
    /**
     * Concrete model id callers should forward as `ExecOptions.model`. Set when:
     * - `requestedModel` was a cost-tier token resolved against this profile's
     *   `models:` map, OR
     * - no `--model` was requested and this is an OpenCode host whose pin lives
     *   in `OPENCODE_MODEL` (OpenCode does not read that env var, so the pin
     *   has to become `--model` on the argv).
     * Undefined when the caller already passed a concrete `--model`, or when
     * tier resolution degraded (see `tierNote`).
     */
    resolvedModel?: string;
}
/**
 * Resolve a name into (agent, version, env). Throws if the name is not a
 * profile. Callers are expected to try agent-id resolution first and fall
 * back to this when that fails, so we don't need a "isProfile" probe.
 *
 * `requestedModel` is the caller's raw `--model` value. When it is a cost-tier
 * token (`cheap`/`default`/`best`/`ultra`), it is resolved against the
 * profile's OWN `models:` map (see `resolveProfileTierModel`) and substituted
 * into `env` as a concrete model id BEFORE returning — so exec.ts's native
 * tier-resolution block (which indexes the HOST agent's catalog, e.g. Claude's
 * own models) never sees a tier token for a profile-based run, and can't
 * collide the profile's harness identity with its host's catalog.
 */
export declare function resolveProfileForRun(name: string, requestedModel?: string): ResolvedProfileRun;
/**
 * Look up the preset a profile was created from, if any. Used by
 * `profiles view` to show upstream metadata like signup URLs.
 */
export declare function getPresetForProfile(profile: Profile): Preset | undefined;
