/** * kosha-discovery — Spec-driven OpenAI-compatible discoverer. * * Most providers that speak the OpenAI wire format differ only in four ways: * the base URL, the model-list path, how origin is read off a model ID, and * which IDs are worth keeping. Writing a class per provider for that is * ceremony — {@link GenericOpenAICompatibleDiscoverer} takes those four * differences as data so a new provider is one entry in * {@link GENERIC_OPENAI_PROVIDERS} plus one entry in `PROVIDER_CATALOG`. * * Providers whose classification is genuinely non-trivial (OpenRouter's * per-route pricing, Groq's flat IDs plus context windows, Vercel's origin * remapping) keep their own hand-written discoverers. This module is for the * long tail, which is where most new providers land. * @module */ import type { CredentialResult, ModelCard, ModelMode } from "../types.js"; import { type ModelClassification, OpenAICompatibleDiscoverer, type OpenAICompatibleModel } from "./openai-compatible.js"; import type { StaticModelSeed } from "./static-direct.js"; /** * Everything that distinguishes one OpenAI-compatible provider from another. */ export interface OpenAICompatibleProviderSpec { /** Canonical provider ID; must match a `PROVIDER_CATALOG` entry. */ providerId: string; /** Display name used in errors and provider listings. */ providerName: string; /** * Base URL up to (but excluding) the model-list path. May already carry a * version segment — the endpoint chain tries `/models` before `/v1/models`, * so both `https://api.x.ai/v1` and `https://api.example.com` work. */ baseUrl: string; /** * Explicit, ordered model-list URLs. Set this when the list endpoint does * not sit directly under {@link baseUrl} (Upstage serves `/v1/models` while * inference lives at `/v1/solar`). */ modelListUrls?: readonly string[]; /** * True when the provider publishes no model-list endpoint. Discovery then * reports the public catalog seed instead of failing — the models are real, * the provider just doesn't enumerate them over HTTP. */ seedOnly?: boolean; /** True when IDs are `vendor/model` namespaced (`deepseek-ai/DeepSeek-V3`). */ namespacedIds?: boolean; /** Lowercased ID prefix → canonical kosha origin provider. */ originAliases?: Readonly>; /** Keyword → origin rules for flat IDs. Most specific first. */ originRules?: ReadonlyArray; /** Keyword → mode overrides applied before the built-in heuristics. */ modeRules?: ReadonlyArray; /** Substrings that disqualify a model ID entirely. */ excludePatterns?: readonly string[]; /** Capability tags added to every chat model this provider serves. */ chatCapabilities?: readonly string[]; /** * Last-resort curated models, used only when there is no credential *and* * both public catalogs are unreachable. Worth setting for providers whose * IDs the built-in aliases point at. */ staticSeeds?: readonly StaticModelSeed[]; } /** * A provider discoverer built from an {@link OpenAICompatibleProviderSpec}. */ export declare class GenericOpenAICompatibleDiscoverer extends OpenAICompatibleDiscoverer { readonly providerId: string; readonly providerName: string; readonly baseUrl: string; private readonly spec; constructor(spec: OpenAICompatibleProviderSpec, baseUrlOverride?: string); /** * Seed-only providers never hit the network for a list, and a keyless run * falls back through the public catalogs to the curated seeds. Everything * else defers to the shared OpenAI-compatible pipeline, whose errors stay * visible in `discoveryErrors()` rather than being masked by a fallback. */ discover(credential: CredentialResult, options?: { timeout?: number; }): Promise; /** Public catalog seed, falling back to the curated list. */ private keylessModels; /** * Try `/models` under the configured base first, then `/v1/models`, so a * base URL that already ends in a version segment resolves in one hop and * one that does not still resolves on the second. */ protected modelListEndpoints(): string[]; protected isRelevantModel(model: OpenAICompatibleModel): boolean; protected classifyModel(model: OpenAICompatibleModel): ModelClassification; /** Namespaced IDs carry their origin as a prefix; flat IDs need keywords. */ private resolveOrigin; /** Spec rules win over the shared heuristics; chat is the fallback. */ private resolveMode; private resolveCapabilities; } /** * Every provider kosha discovers through the generic OpenAI-compatible path. * * Adding a provider here plus a `PROVIDER_CATALOG` descriptor is the whole * change — credentials resolve from the descriptor's `credentialEnvVars` and * keyless discovery resolves from the public catalog seeds. */ export declare const GENERIC_OPENAI_PROVIDERS: readonly OpenAICompatibleProviderSpec[]; /** Look up a generic provider spec by canonical provider ID. */ export declare function getGenericProviderSpec(providerId: string): OpenAICompatibleProviderSpec | undefined; //# sourceMappingURL=generic-openai.d.ts.map