llm-provider-compat

August 20, 2026 · View on GitHub

English | 中文

Website Sponsor

Author website · X · Bilibili · YouTube · Sponsor

npm version license

npm install llm-provider-compat

Universal LLM provider compatibility layer — normalizes provider-specific payload differences (thinking formats, output budgets, tool pairing, media transport) into a single first-match-wins dispatch pipeline.

Plus dynamic version detection (auto-discovers latest models from provider APIs) and OAuth login (device-code flow for xAI Grok, extensible to others).

License: MIT


Supported Providers (51 total)

Tier 1 — Dedicated Compat Sub-Modules (14)

These have non-standard wire protocols requiring explicit payload normalization.

ProviderAPIThinking FormatKey Quirks
Anthropicanthropic-messagesthinking: { type, budget_tokens }Prompt caching, adaptive effort (Fable/Mythos 5), required output cap, empty content filter, tool block reorder
DeepSeekopenai-completions / anthropic-messagesthinking: { type } + reasoning_effortEffort collapse, reasoning_content replay, token budget uplift, V4 Anthropic profile, "Thinking..." injection
Kimi / Moonshotopenai-completionsthinking: { type, keep? } + reasoning_effortreasoning_content replay, MFJS schema normalization, utility temp
DashScope / Qwenopenai-completionsenable_thinking: booleanCovers dashscope-coding, SiliconFlow, ModelScope, Infini; video → video_url
Zhipu / BigModelopenai-completionsthinking: { type, clear_thinking }reasoning_content replay, strict removal, store/stream_options strip, OpenCode Go
MiMo / Xiaomiopenai-completionschat_template_kwargs: { enable_thinking, preserve_thinking }reasoning_content replay, input_audio, video_url, token plan
Mistral / Devstralopenai-completionsstandard OpenAI9-char tool call IDs, synthetic assistant injection between tool→user
OpenRouteropenai-completionsreasoning: { effort } + verbosityClaude Fable/Mythos 5 adaptive, usage: { include: true }
Volcengine Arkopenai-completionsthinking: { type } + reasoning_effortEffort ceiling (max→high), utility/off disable
LongCatopenai-completionsthinking: { type: "disabled" }Utility-only: disables thinking, strips reasoning_content
Agnes AIopenai-completionsstrippedNo reasoning protocol — strips all thinking fields
OpenAI Codexopenai-codex-responsesstrippedStrips output budget + temperature from Responses
OpenAI Audioopenai-completionsN/Adata:audio image_url → input_audio
DashScope/Kimi/MiMo Videoopenai-completionsN/Adata:video image_url → video_url

Tier 2 — Standard OpenAI-Compatible (37)

These pass through the default pathway without a dedicated sub-module.

API-key providers: OpenAI, xAI (Grok), Google Gemini, Groq, Cohere, Perplexity, Together AI, Fireworks, DeepInfra, Cerebras, SiliconFlow, ModelScope, Infini, StepFun, Baichuan, Baidu Cloud, Hunyuan, MiniMax, Ollama, Amazon Bedrock, Amazon Bedrock Mantle, Azure OpenAI, Google Vertex AI, Google Vertex AI (Anthropic), Cloudflare AI Gateway, Vercel AI, Venice AI, OpenRouter (non-adaptive models), LongCat (non-utility)

OAuth providers: xAI Grok (OAuth), OpenAI Codex (OAuth), GitLab Duo (OAuth), GitHub Copilot (OAuth)

Special-purpose: Volcengine Speech (BigASR), System Speech Recognition


OAuth Login

xAI (Grok) Device-Code OAuth

Full OAuth 2.0 device authorization grant for xAI Grok CLI access.

import { createXaiOAuthProvider } from "llm-provider-compat";

const xai = createXaiOAuthProvider();

const creds = await xai.login({
  onDeviceCode: ({ userCode, verificationUri }) => {
    console.log(`Open ${verificationUri} and enter code: ${userCode}`);
  },
});
// → { access, refresh, expires, tokenEndpoint }

// Refresh when expired:
const fresh = await xai.refreshToken(creds);

Exported API:

ExportDescription
createXaiOAuthProvider(opts?)Factory with custom fetch/sleep/now
xaiOAuthProviderPre-built instance (uses global fetch)
XAI_OAUTH_CLIENT_IDOfficial xAI Grok CLI client ID
XAI_OAUTH_DISCOVERY_URLOIDC discovery endpoint
XAI_OAUTH_SCOPESRequired OAuth scopes
XAI_OAUTH_RESOURCE_URLAPI resource URL (cli-chat-proxy.grok.com)

Auth Framework (extensible)

Generic auth types in src/auth/types.ts:

import type { AuthMethod, OAuthCredentials, ProviderAuthConfig } from "llm-provider-compat";

Supports oauth (device-code) and api (API key + metadata) methods with customizable login prompts (text/select).


Architecture

                     normalizeProviderPayload()

              ┌──────────────────────────────┐
              │  1. Provider-Agnostic Patches │
              │  stripEmptyTools /            │
              │  stripIncompatibleThinking /  │
              │  stripDisabledReasoningEffort /│
              │  stripOrphanToolMessages /    │
              │  normalizeImplicitOutputBudget│
              └──────────────┬───────────────┘


              ┌──────────────────────────────┐
              │  2. Provider Dispatch         │
              │  First-match-wins:            │
              │  deepseek → kimi → mimo →     │
              │  mistral → qwen → zhipu →     │
              │  volcengine → longcat →       │
              │  agnes → openaiAudio →        │
              │  openaiVideo → openrouter →   │
              │  anthropic → codexResponses   │
              │  → no match = default (no-op) │
              └──────────────┬───────────────┘


                     Final HTTP Payload

Dynamic Version Detection

import { fetchLatestModels } from "llm-provider-compat/dynamic-version";

const { latest } = await fetchLatestModels([
  { providerId: "gemini", baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai", apiKey: "..." },
  { providerId: "xai", baseUrl: "https://api.x.ai/v1", apiKey: "..." },
], { masterToggle: true });
// → { gemini: { "gemini-flash": "gemini-3.5-flash-preview" }, xai: { ... } }

Built-in strategies: openai, anthropic, gemini, deepseek, default (generic name-X.Y.Z regex).


API Reference

Main Entry

ExportSignature
normalizeProviderPayload(payload, model, options?) → payload
normalizeProviderContextMessages(messages, model, options?) → messages

Provider Catalog

ExportReturns
PROVIDER_CATALOGRecord<string, ProviderDefinition> — all 51 providers
getProvider(id)ProviderDefinition | undefined
listProviders()string[]
listProvidersByTier(tier)ProviderDefinition[]
getCompatModule(providerId)string | null
isSupportedProvider(providerId)boolean

Provider Detection

isDeepSeekModel, isAnthropicModel, getThinkingFormat, getReasoningProfile, modelSupportsImageInput, modelSupportsVideoInput, modelSupportsAudioInput, isDeepSeekFamilyModel, isDeepSeekReasoningModel, isOfficialMimoEndpoint

Dynamic Version Detection

fetchLatestModels, resolveLatestModels, createVersionCache, resolveTopModel, formatModelLabel

Output Budget

resolveOutputBudgetPolicy, resolveOutputCapCapability, normalizeImplicitOutputBudget

Tool Pairing

stripOrphanToolResults

Known Models

lookupKnown, lookupKnownProvider, lookupKnownWithSource, listKnownProviderModels, setDataDir


Adding a Provider

Tier 1: Create src/providers/<name>.ts → export matches(model) + apply(payload, model, options) → add to PROVIDER_MODULES[] in src/dispatcher.ts.

Tier 2: Just add to PROVIDER_CATALOG in src/catalog.ts.


No separate product site is required for this repository. The public face of the work is the author website, this GitHub repo, and the projects below.

Author websitehttps://guojiz.github.io/
Xhttps://x.com/guojizh
Bilibilihttps://space.bilibili.com/3493114115263006
YouTubehttps://youtube.com/@guojizh
Sponsorhttps://github.com/Guojiz/Sponsors

Other open-source projects