/**
 * Canonical chat-model resolution — identical across every agent app.
 *
 * The ONLY per-app inputs are DATA, never logic: the default model, the
 * allowlist, the env value the deployment set, and the catalog-fetch loader.
 * The logic is one precedence ladder + one fail-closed validator that every
 * product uses the same way — there is no per-product variant, no env-var name
 * baked in, and no backend dimension (router-vs-sandbox is the harness/dispatch
 * concern, not model resolution; a sandbox's provider default lives in the
 * sandbox subpath).
 *
 * - resolveChatModel: request > workspace > env > default. The product reads its
 *   own deploy env var and passes the VALUE as `envModel`; the shell knows no
 *   env-var names. Source is canonical: 'request' | 'workspace' | 'env' | 'default'.
 * - validateChatModelId: fail-closed. Admit an id that is in the allowlist, or
 *   equals the operator-set env model, or is served by the live router catalog
 *   (exact, or a bare id resolved to its canonical id when the suffix is unique).
 */
/** The router /v1/models entry shape this module reads. Minimal on purpose. */
interface ModelInfo {
    id: string;
    name?: string;
    _provider?: string;
    provider?: string;
}
type ChatModelSource = 'request' | 'workspace' | 'env' | 'default';
interface ResolvedChatModel {
    model: string;
    source: ChatModelSource;
}
interface ChatModelValidationSuccess {
    succeeded: true;
    value: string;
}
interface ChatModelValidationFailure {
    succeeded: false;
    error: string;
}
type ChatModelValidationResult = ChatModelValidationSuccess | ChatModelValidationFailure;
/** The catalog-fetch boundary: maps a router base URL to the raw model list. */
type LoadModels = (routerBaseUrl: string) => Promise<ModelInfo[]>;
interface ResolveChatModelInput {
    /** Per-request override (highest precedence). */
    requestModel?: string;
    /** Persisted workspace-pinned model. */
    workspaceModel?: string;
    /** The value the deployment's model env var holds (the product reads its own
     *  var name and passes the value — the shell stays env-var-name agnostic). */
    envModel?: string;
    /** Final fallback (the product's default, typically profile.model.default). */
    defaultModel: string;
}
/** Resolve the chat-turn model by the one canonical precedence. Blank values are
 *  treated as absent. */
declare function resolveChatModel(input: ResolveChatModelInput): ResolvedChatModel;
interface ValidateChatModelIdInput {
    /** Ids accepted without a catalog round-trip (defaults + operator-trusted). */
    allowlist?: Iterable<string>;
    /** The operator-set env model value — always admitted (operator-trusted). */
    envModel?: string;
    /** Catalog loader; required to reach the catalog path. */
    loadModels?: LoadModels;
    /** Catalog endpoint base; required to reach the catalog path. */
    routerBaseUrl?: string;
}
/**
 * Fail-closed model-id validation. Accepts an id only when it is well-formed AND
 * (in the allowlist, or equals the operator-set env model, or served by the live
 * catalog). A bare id (no provider prefix) resolves to its canonical id only when
 * the suffix is unique across the catalog — an ambiguous suffix is rejected
 * rather than silently assigned a provider.
 */
declare function validateChatModelId(modelId: unknown, input: ValidateChatModelIdInput): Promise<ChatModelValidationResult>;
declare function cleanModelId(value: unknown): string | undefined;
declare function isWellFormedModelId(modelId: string): boolean;
declare function catalogIdsForModel(model: ModelInfo): string[];

export { type ChatModelSource, type ChatModelValidationFailure, type ChatModelValidationResult, type ChatModelValidationSuccess, type LoadModels, type ModelInfo, type ResolveChatModelInput, type ResolvedChatModel, type ValidateChatModelIdInput, catalogIdsForModel, cleanModelId, isWellFormedModelId, resolveChatModel, validateChatModelId };
