/** * Cross-capability runtime helpers shared by image / audio / video * generation. Pure functions (no IO) so they can be unit-tested without * touching providers. * * - candidate model resolution * - geometry/value nearest-neighbour matching * - terminal failure aggregation (FailoverError) * - "no model configured" message builder */ import type { Config, AgentModelConfig } from '../../config/schema.js'; import { type FallbackAttempt, type FailoverReason } from '../failover-error.js'; import { type ParsedCapabilityModelRef } from './model-ref.js'; export interface CapabilityProviderCandidate { id: string; aliases?: readonly string[]; defaultModel?: string | null; models?: readonly string[]; isConfigured?: (ctx: { cfg?: Config; agentId?: string; agentDir?: string; }) => boolean; } export interface ResolveCapabilityModelCandidatesParams { cfg?: Config; /** Active capability model config from a manifest/runtime policy. */ modelConfig: { primary?: string; fallbacks?: string[]; } | AgentModelConfig | undefined; /** Caller-supplied per-call override (highest priority). */ modelOverride?: string; /** Optional ref parser; defaults to {@link parseCapabilityModelRef}. */ parseModelRef?: (raw: string | undefined) => ParsedCapabilityModelRef | null; agentId?: string; agentDir?: string; /** Snapshot of registered providers used to enumerate fallbacks. */ listProviders: (cfg?: Config) => CapabilityProviderCandidate[]; /** * When true and the explicit candidates fail, append every configured * provider's default model. */ autoProviderFallback?: boolean; } export interface ResolvedCapabilityModelCandidate { provider: string; model: string; } /** * Build the ordered candidate list from: * 1. modelOverride * 2. modelConfig.primary * 3. modelConfig.fallbacks[] * 4. (optional) every isConfigured() provider's defaultModel * * Duplicates are dropped (case-insensitive on provider, exact on model). */ export declare function resolveCapabilityModelCandidates(params: ResolveCapabilityModelCandidatesParams): ResolvedCapabilityModelCandidate[]; export declare function resolveClosestSize(params: { requestedSize?: string; requestedAspectRatio?: string; supportedSizes?: ReadonlyArray; }): string | undefined; export declare function resolveClosestAspectRatio(params: { requestedAspectRatio?: string; requestedSize?: string; supportedAspectRatios?: ReadonlyArray; }): string | undefined; export declare function resolveClosestResolution(params: { requestedResolution?: T; supportedResolutions?: ReadonlyArray; }): T | undefined; export interface RecordCapabilityCandidateFailureParams { attempts: FallbackAttempt[]; provider: string; model: string; error: unknown; durationMs?: number; } /** Push a structured {@link FallbackAttempt} entry derived from `error`. */ export declare function recordCapabilityCandidateFailure(params: RecordCapabilityCandidateFailureParams): FallbackAttempt; export interface ThrowCapabilityGenerationFailureParams { capabilityLabel: string; attempts: FallbackAttempt[]; lastError: unknown; } /** Throw a unified {@link FailoverError} after all candidates have been exhausted. */ export declare function throwCapabilityGenerationFailure(params: ThrowCapabilityGenerationFailureParams): never; export interface BuildNoCapabilityModelConfiguredMessageParams { /** Display label, e.g. "image-generation". */ capabilityLabel: string; /** Config key path, e.g. "imageGenerationModel". */ modelConfigKey: string; providers: ReadonlyArray; /** Optional env-var lookup, e.g. (id) => PROVIDER_ENV_MAP[id]. */ getProviderEnvVars?: (id: string) => readonly string[] | undefined; } export declare function buildNoCapabilityModelConfiguredMessage(params: BuildNoCapabilityModelConfiguredMessageParams): string; /** * Build a `metadata.normalization` snapshot from a completed normalization * pass. Providers / runtime can spread it into their result metadata. */ export declare function buildMediaGenerationNormalizationMetadata(params: { normalization?: Record; }): Record; export type { FailoverReason };