/** * Provider Registry — single source of truth for backend provider metadata. * Centralizes env var mappings, default models, and OpenClaw provider configs. * * NOTE: When adding a new provider type, also update src/lib/providers.ts */ export const BUILTIN_PROVIDER_TYPES = [ 'anthropic', 'openai', 'google', 'openrouter', 'moonshot', 'siliconflow', 'minimax-portal', 'minimax-portal-cn', 'qwen-portal', 'ollama', ] as const; export type BuiltinProviderType = (typeof BUILTIN_PROVIDER_TYPES)[number]; export type ProviderType = BuiltinProviderType | 'custom'; interface ProviderModelEntry extends Record { id: string; name: string; } interface ProviderBackendMeta { envVar?: string; defaultModel?: string; /** OpenClaw models.providers config (omit for built-in providers like anthropic) */ providerConfig?: { baseUrl: string; api: string; apiKeyEnv: string; models?: ProviderModelEntry[]; headers?: Record; }; } const REGISTRY: Record = { anthropic: { envVar: 'ANTHROPIC_API_KEY', defaultModel: 'anthropic/claude-opus-4-6', // anthropic is built-in to OpenClaw's model registry, no provider config needed }, openai: { envVar: 'OPENAI_API_KEY', defaultModel: 'openai/gpt-5.2', providerConfig: { baseUrl: 'https://api.openai.com/v1', api: 'openai-responses', apiKeyEnv: 'OPENAI_API_KEY', }, }, google: { envVar: 'GEMINI_API_KEY', defaultModel: 'google/gemini-3.1-pro-preview', // google is built-in to OpenClaw's pi-ai catalog, no providerConfig needed. // Adding models.providers.google overrides the built-in and can break Gemini. }, openrouter: { envVar: 'OPENROUTER_API_KEY', defaultModel: 'openrouter/anthropic/claude-opus-4.6', providerConfig: { baseUrl: 'https://openrouter.ai/api/v1', api: 'openai-completions', apiKeyEnv: 'OPENROUTER_API_KEY', headers: { 'HTTP-Referer': 'https://claw-x.com', 'X-Title': 'ClawX', }, }, }, moonshot: { envVar: 'MOONSHOT_API_KEY', defaultModel: 'moonshot/kimi-k2.5', providerConfig: { baseUrl: 'https://api.moonshot.cn/v1', api: 'openai-completions', apiKeyEnv: 'MOONSHOT_API_KEY', models: [ { id: 'kimi-k2.5', name: 'Kimi K2.5', reasoning: false, input: ['text'], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 256000, maxTokens: 8192, }, ], }, }, siliconflow: { envVar: 'SILICONFLOW_API_KEY', defaultModel: 'siliconflow/deepseek-ai/DeepSeek-V3', providerConfig: { baseUrl: 'https://api.siliconflow.cn/v1', api: 'openai-completions', apiKeyEnv: 'SILICONFLOW_API_KEY', }, }, 'minimax-portal': { envVar: 'MINIMAX_API_KEY', defaultModel: 'minimax-portal/MiniMax-M2.5', providerConfig: { baseUrl: 'https://api.minimax.io/anthropic', api: 'anthropic-messages', apiKeyEnv: 'MINIMAX_API_KEY', }, }, 'minimax-portal-cn': { envVar: 'MINIMAX_CN_API_KEY', defaultModel: 'minimax-portal/MiniMax-M2.5', providerConfig: { baseUrl: 'https://api.minimaxi.com/anthropic', api: 'anthropic-messages', apiKeyEnv: 'MINIMAX_CN_API_KEY', }, }, 'qwen-portal': { envVar: 'QWEN_API_KEY', defaultModel: 'qwen-portal/coder-model', providerConfig: { baseUrl: 'https://portal.qwen.ai/v1', api: 'openai-completions', apiKeyEnv: 'QWEN_API_KEY', }, }, custom: { envVar: 'CUSTOM_API_KEY', }, // Additional providers with env var mappings but no default model groq: { envVar: 'GROQ_API_KEY' }, deepgram: { envVar: 'DEEPGRAM_API_KEY' }, cerebras: { envVar: 'CEREBRAS_API_KEY' }, xai: { envVar: 'XAI_API_KEY' }, mistral: { envVar: 'MISTRAL_API_KEY' }, }; /** Get the environment variable name for a provider type */ export function getProviderEnvVar(type: string): string | undefined { return REGISTRY[type]?.envVar; } /** Get the default model string for a provider type */ export function getProviderDefaultModel(type: string): string | undefined { return REGISTRY[type]?.defaultModel; } /** Get the OpenClaw provider config (baseUrl, api, apiKeyEnv, models, headers) */ export function getProviderConfig( type: string ): { baseUrl: string; api: string; apiKeyEnv: string; models?: ProviderModelEntry[]; headers?: Record } | undefined { return REGISTRY[type]?.providerConfig; } /** * All provider types that have env var mappings. * Used by GatewayManager to inject API keys as env vars. */ export function getKeyableProviderTypes(): string[] { return Object.entries(REGISTRY) .filter(([, meta]) => meta.envVar) .map(([type]) => type); }