/** * Live model discovery, shared fetch/cache/diff/report machinery so a * provider's model list can never go stale silently. * * Each provider that has its own model-listing API (Anthropic, OpenAI, * Gemini today) calls `runLiveModelRefresh()` with a small fetch function. * The shared logic here handles: * - an on-disk TTL cache (same envelope shape as model-catalog-cache.ts, * via json-ttl-cache.ts's shared helpers) so a restart doesn't re-fetch * immediately and an offline boot still has the last known-good list; * - diffing against the previous list so a refresh can report what * actually changed ("3 new, 1 retired") instead of a silent no-op; * - an honest fallback chain: live fetch -> last on-disk cache (even if * stale) -> the packaged dated-static list -- never a bare empty array. */ import type { ModelDefinition } from './registry-types.js'; export type LiveModelDiscoverySource = 'live' | 'cache' | 'dated-static'; export interface LiveModelDiscoveryResult { /** The resolved model id list to use right now. Never empty when a dated-static baseline exists. */ readonly models: readonly string[]; /** Where `models` came from. */ readonly source: LiveModelDiscoverySource; /** Model ids present now that weren't in the previous known list. */ readonly added: readonly string[]; /** Model ids that were in the previous known list but are gone now. */ readonly removed: readonly string[]; /** Set when `source !== 'live'` because a live fetch was attempted and failed. Honest failure reason. */ readonly error?: string | undefined; /** Set when `source === 'dated-static'`: the date the packaged list was last verified. */ readonly asOf?: string | undefined; } /** Cache file path for a provider's live-discovered model list. */ export declare function getProviderModelsCachePath(persistenceRoot: string, providerId: string): string; /** Diff two model id lists. Order-independent. */ export declare function diffModelIds(previous: readonly string[], next: readonly string[]): { added: string[]; removed: string[]; }; /** Human-readable one-line summary of a refresh, for surfaces that just want a status line. */ export declare function formatModelDiscoveryReport(providerName: string, result: LiveModelDiscoveryResult): string; export interface LiveModelRefreshOptions { readonly providerName: string; /** * Absolute path to this provider's on-disk model-list cache file. When * omitted, refresh runs in-memory only (no on-disk persistence, no TTL * skip), used by tests and any caller that hasn't wired a persistence * root through yet. */ readonly cachePath?: string | undefined; /** Complete, hand-maintained fallback list used when live discovery is unavailable or fails. */ readonly datedStaticModels: readonly string[]; /** The date the dated-static list was last verified, e.g. '2026-07-12'. */ readonly datedStaticAsOf: string; /** Whether the provider has credentials configured. When false, live fetch is skipped entirely. */ readonly isConfigured: boolean; /** Performs the live fetch. Should reject on any failure (network, auth, parse). */ readonly fetchLive: () => Promise; /** * Bypass the TTL cache and always re-check live. Set this for an explicit * user-triggered refresh or a picker-open re-check; leave false for * routine background refreshes so they respect the on-disk TTL cache * instead of hitting the network on every boot. */ readonly force?: boolean | undefined; } /** * Run a single live-discovery refresh cycle for one provider: try the cache * for a diff baseline, attempt a live fetch when configured, fall back to * cache-then-dated-static on failure, and persist a successful fetch. */ export declare function runLiveModelRefresh(opts: LiveModelRefreshOptions): Promise; /** * Fetch a model id list from an OpenAI-style listing endpoint * (GET returning `{ "data": [{ "id": ... }] }`). Shared by every * OpenAI-compatible gateway provider; the same response shape is used by * Anthropic-style listings, so the Anthropic-compat fetcher delegates here * without the chat-capability filter. */ export declare function fetchModelIdsFromListing(providerName: string, url: string, headers: Record, options?: { readonly filterNonChat?: boolean | undefined; }): Promise; /** * Fetch Fireworks' live model list. Fireworks' OpenAI-compatible inference * surface has no /models listing; the documented listing lives on the * account-management API (GET /v1/accounts/fireworks/models, paginated). * Model resource names there ("accounts/fireworks/models/") are exactly * the ids the chat surface accepts. */ export declare function fetchFireworksModelIds(apiKey: string): Promise; /** * One model as Anthropic's GET /v1/models reports it. * * `/v1/models` carries the per-model token limits alongside the id, so the * authoritative output cap can be read from the provider rather than guessed * from a hand-maintained table that goes stale the day a model ships. */ export interface AnthropicLiveModel { readonly id: string; /** The model's max output tokens (`max_tokens`), when the API reported one. */ readonly maxOutputTokens?: number | undefined; /** The model's context window (`max_input_tokens`), when the API reported one. */ readonly maxInputTokens?: number | undefined; } /** * Fetch the live model list from Anthropic's GET /v1/models endpoint, with * each entry's reported token limits. * * A field the API omits comes back undefined rather than defaulted, so a * caller can tell "the provider did not say" from "the provider said zero" * and fall back to its offline table only in the first case. */ export declare function fetchAnthropicModels(apiKey: string): Promise; /** Fetch the live model list from Anthropic's GET /v1/models endpoint. */ export declare function fetchAnthropicModelIds(apiKey: string): Promise; /** Fetch the live model list from OpenAI's GET /v1/models endpoint, filtered to chat-capable ids. */ export declare function fetchOpenAIModelIds(apiKey: string): Promise; /** Fetch the live model list from Google's Gemini ListModels endpoint. */ export declare function fetchGeminiModelIds(apiKey: string): Promise; /** * Build a ModelDefinition for a live-discovered or dated-static model id that * isn't already represented in the shared model catalog (models.dev). Used * to fill the gap when the third-party catalog snapshot lags behind a * provider's own live listing (e.g. a model released today). */ export declare function buildProviderNativeModelDefinition(providerId: string, modelId: string): ModelDefinition; //# sourceMappingURL=live-model-discovery.d.ts.map