/** * Low-level LLM provider abstraction — used by `AIRouter` to fan a single * call out across multiple providers with circuit-breaker + budget control. * * Distinct from the higher-level `AIClient.chat()` (conversational turn * with thread state): an `LLMProvider.run(...)` is a single shot. Router * apps compose providers; conversational apps compose `AIClient`s. * * Ships two concrete implementations: * - `OpenAICompatProvider` — base class for any OpenAI Chat Completions-shaped * API (Groq, Cerebras, OpenRouter, DeepInfra, Maritaca, Azure OpenAI). * Apps subclass with their endpoint URL + API key env var. * - `WorkersAIProvider` — uses Cloudflare's `env.AI` binding directly * (no fetch). In-process backstop when external providers are circuit-broken. */ export type ProviderErrorKind = '429' | '5xx' | 'network' | 'timeout' | 'parse' | 'config'; export interface ProviderRunArgs { system: string; user: string; maxTokens?: number; temperature?: number; timeoutMs?: number; /** * Optional image attachments (v0.15). When present, the user message is * rewritten as a multi-part `content` array (`[{type:'text'},{type:'image_url'}]`) * so vision-capable models can see them. Providers that don't support * multimodal input should drop this field silently. * * Provide either `url` (public URL Meta / your CDN can serve) or `b64` * (base64-encoded bytes) with the image's `mimeType` (defaults to * `image/jpeg`). */ images?: Array<{ url?: string; b64?: string; mimeType?: string; }>; } export interface ProviderSuccess { ok: true; response: string; model: string; httpStatus: number | null; tokensIn: number | null; tokensOut: number | null; } export interface ProviderFailure { ok: false; errorKind: ProviderErrorKind; errorMessage: string; model: string; httpStatus?: number | null; } export type ProviderResult = ProviderSuccess | ProviderFailure; export interface LLMProvider { readonly name: string; readonly model: string; run(args: ProviderRunArgs): Promise; } export interface OpenAICompatProviderOptions { /** Logical name used in chain config + ledger rows. Required. */ name: string; /** Full chat-completions URL (e.g. `https://api.groq.com/openai/v1/chat/completions`). */ url: string; /** Bearer token. */ apiKey: string; /** Model slug passed as the `model` field. */ model: string; /** Extra request headers (e.g. OpenRouter's `HTTP-Referer`). */ extraHeaders?: Record; /** Extra body fields merged into the JSON payload. */ extraBody?: Record; /** * Name of the "max tokens" field in the request body (v0.15). Default * `'max_tokens'` (classic Chat Completions). Azure OpenAI reasoning-family * deployments (`gpt-5-*`, `o1-*`) require `'max_completion_tokens'`. Set * this once per provider instance so the router doesn't have to know. */ maxTokensField?: 'max_tokens' | 'max_completion_tokens'; /** * When `true` (v0.15), the `temperature` field is omitted from the request * body. Reasoning-family models on Azure (`gpt-5.4-*`, `o1-*`) reject any * non-default value and error. Default `false`. */ omitTemperature?: boolean; } /** * OpenAI Chat-Completions-compatible provider. Subclass or instantiate * directly per upstream API. * * class GroqProvider extends OpenAICompatProvider { * constructor(env) { * super({ * name: 'groq_8b', * url: 'https://api.groq.com/openai/v1/chat/completions', * apiKey: env.GROQ_API_KEY, * model: 'llama-3.1-8b-instant', * }); * } * } */ export declare class OpenAICompatProvider implements LLMProvider { readonly name: string; readonly url: string; readonly apiKey: string; readonly model: string; readonly extraHeaders: Record; readonly extraBody: Record; readonly maxTokensField: 'max_tokens' | 'max_completion_tokens'; readonly omitTemperature: boolean; constructor(opts: OpenAICompatProviderOptions); run({ system, user, maxTokens, temperature, timeoutMs, images }: ProviderRunArgs): Promise; } /** Cloudflare Workers AI binding shape used by `WorkersAIProvider`. */ export interface WorkersAIBinding { run(model: string, input: unknown, opts?: { signal?: AbortSignal; }): Promise; } export interface WorkersAIProviderOptions { name: string; /** The `env.AI` binding from a Worker with `[ai]` in wrangler.toml. */ ai: WorkersAIBinding | undefined; model: string; } /** * Cloudflare Workers AI provider — uses the `env.AI` binding in-process. * Useful as the last link in a fallback chain because it doesn't depend on * a remote endpoint being reachable. */ export declare class WorkersAIProvider implements LLMProvider { readonly name: string; readonly ai: WorkersAIBinding | undefined; readonly model: string; constructor(opts: WorkersAIProviderOptions); run({ system, user, maxTokens, temperature, timeoutMs }: ProviderRunArgs): Promise; } //# sourceMappingURL=llm_provider.d.ts.map