/** * @verevoir/llm — shared OpenAI-compatible adapter factory. * * Many providers (DeepSeek, SambaNova, Mistral, …) expose an OpenAI-compatible * Chat Completions API: same `openai` SDK, just a different `baseURL`, API key, * and model catalogue. Rather than copy the adapter per provider, this factory * builds one from a small config — a provider id, base URL, key env var, and a * **model catalogue** (provider/family entries, the de-brittle model identity * from STDIO-332). `models` / `rates` / labels all derive from the catalogue, * so a version bump is a one-line `currentId` change and decisions key on * `provider/family`, never on the exact version. * * Importing a subpath built on this factory requires `openai` as a peer * dependency on the consumer (the same one `/openai` + `/deepseek` already use). * * Ships `chat()` only — single-shot text generation — matching the staged * rollout of the other OpenAI-compatible adapters. Tool calling follows later. */ import { type ChatOptions, type ChatReply, type ChatWithToolLoopOptions, type ChatWithToolLoopResult, type ChatWithToolsOptions, type ChatWithToolsResult, type ModelCatalogEntry, type ModelClass, type RatesTable } from './index.js'; /** Config for one OpenAI-compatible provider. */ export interface OpenAICompatConfig { /** Provider id reported on every {@link TokenUsage}, e.g. `mistral`. */ provider: string; /** The provider's OpenAI-compatible base URL. */ baseURL: string; /** Env var that overrides `baseURL` at runtime (a gateway/proxy/regional/ * self-hosted endpoint), e.g. `SAMBA_NOVA_BASE_URL`. Optional. */ baseUrlEnv?: string; /** Whether a base-URL override without a key makes this usable — true only * for a generic OpenAI-compatible client pointed at a keyless local server. * Hosted providers (SambaNova, Mistral, …) leave it false: they need a key. */ keylessCapable?: boolean; /** Env var holding the default API key when no per-call key is passed. */ apiKeyEnv: string; /** The model catalogue — provider/family entries; `models`/`rates`/labels * derive from it. Each entry's `modelClass` (when set) places it in the * class→model map. */ catalog: ModelCatalogEntry[]; } /** A built OpenAI-compatible adapter. */ export interface OpenAICompatAdapter { PROVIDER: string; BASE_URL: string; models: Readonly>; rates: RatesTable; chat: (options: ChatOptions) => Promise; chatWithTools: (options: ChatWithToolsOptions) => Promise; chatWithToolLoop: (options: ChatWithToolLoopOptions) => Promise; } /** Build an OpenAI-compatible adapter for one provider. Registers the model * catalogue (decisions key on provider/family; labels + family pricing become * available) as an import side-effect, the same way the bespoke adapters * register their labels. */ export declare function createOpenAICompatAdapter(config: OpenAICompatConfig): OpenAICompatAdapter; //# sourceMappingURL=openai-compat.d.ts.map