/**
 * src/models/universal.ts
 *
 * Universal OpenAI-compatible provider. One adapter covers every provider
 * that speaks the OpenAI Chat Completions API:
 *
 *   • Groq          — https://api.groq.com/openai/v1            (GROQ_API_KEY)
 *   • Together AI   — https://api.together.xyz/v1               (TOGETHER_API_KEY)
 *   • Perplexity    — https://api.perplexity.ai                 (PERPLEXITY_API_KEY)
 *   • xAI Grok      — https://api.x.ai/v1                       (XAI_API_KEY)
 *   • Mistral       — https://api.mistral.ai/v1                 (MISTRAL_API_KEY)
 *   • OpenRouter    — https://openrouter.ai/api/v1              (OPENROUTER_API_KEY)
 *   • Cloudflare AI — https://api.cloudflare.com/.../ai/v1      (CF_AI_API_KEY + CF_ACCOUNT_ID)
 *   • Vercel AI GW  — https://gateway.ai.vercel.app/v1          (VERCEL_AI_GATEWAY_KEY)
 *   • ByteDance Ark — https://ark.cn-beijing.volces.com/api/v3  (BYTEPLUS_API_KEY)
 *   • HuggingFace   — https://api-inference.huggingface.co/v1   (HF_API_KEY)
 *   • SGLang        — http://localhost:30000/v1                 (SGLANG_BASE_URL)
 *   • vLLM          — http://localhost:8000/v1                  (VLLM_BASE_URL)
 *
 * Each provider is registered with a default model that the failover chain
 * will pick up when its env key is set. The owner can override per-tier
 * defaults from the Settings tab.
 *
 * This single file gives Muassis parity with OpenClaw on 10+ model
 * providers without adding 10 separate adapter files.
 */
import { config } from '../config.js';
import { callOpenAICompatible, ModelError, } from './provider.js';
export const UNIVERSAL_PROVIDERS = [
    {
        name: 'groq',
        label: 'Groq (LPU)',
        baseUrl: 'https://api.groq.com/openai/v1',
        apiKeyEnv: 'GROQ_API_KEY',
        defaultModel: 'llama-3.3-70b-versatile',
        models: ['llama-3.3-70b-versatile', 'llama-3.1-8b-instant', 'mixtral-8x7b-32768', 'qwen-qwq-32b'],
    },
    {
        name: 'together',
        label: 'Together AI',
        baseUrl: 'https://api.together.xyz/v1',
        apiKeyEnv: 'TOGETHER_API_KEY',
        defaultModel: 'meta-llama/Llama-3.3-70B-Instruct-Turbo',
        models: ['meta-llama/Llama-3.3-70B-Instruct-Turbo', 'Qwen/Qwen2.5-Coder-32B-Instruct', 'deepseek-ai/DeepSeek-V3'],
    },
    {
        name: 'perplexity',
        label: 'Perplexity (Sonar)',
        baseUrl: 'https://api.perplexity.ai',
        apiKeyEnv: 'PERPLEXITY_API_KEY',
        defaultModel: 'sonar-pro',
        models: ['sonar', 'sonar-pro', 'sonar-reasoning', 'sonar-reasoning-pro'],
    },
    {
        name: 'xai',
        label: 'xAI Grok',
        baseUrl: 'https://api.x.ai/v1',
        apiKeyEnv: 'XAI_API_KEY',
        defaultModel: 'grok-2-latest',
        models: ['grok-2-latest', 'grok-2-vision-latest', 'grok-beta'],
    },
    {
        name: 'mistral',
        label: 'Mistral',
        baseUrl: 'https://api.mistral.ai/v1',
        apiKeyEnv: 'MISTRAL_API_KEY',
        defaultModel: 'mistral-large-latest',
        models: ['mistral-large-latest', 'mistral-small-latest', 'open-mistral-nemo', 'codestral-latest'],
    },
    {
        name: 'openrouter',
        label: 'OpenRouter',
        baseUrl: 'https://openrouter.ai/api/v1',
        apiKeyEnv: 'OPENROUTER_API_KEY',
        defaultModel: 'anthropic/claude-3.5-sonnet',
        // OpenRouter is a router-of-routers — the model field can be any
        // upstream model name. Surface a useful starter list.
        models: ['anthropic/claude-3.5-sonnet', 'openai/gpt-4o', 'google/gemini-2.0-flash', 'meta-llama/llama-3.3-70b-instruct'],
    },
    {
        name: 'vercel-ai',
        label: 'Vercel AI Gateway',
        baseUrl: 'https://gateway.ai.vercel.app/v1',
        apiKeyEnv: 'VERCEL_AI_GATEWAY_KEY',
        defaultModel: 'anthropic/claude-3.5-sonnet',
        models: ['anthropic/claude-3.5-sonnet', 'openai/gpt-4o'],
    },
    {
        name: 'byteplus',
        label: 'ByteDance Ark',
        baseUrl: 'https://ark.cn-beijing.volces.com/api/v3',
        apiKeyEnv: 'BYTEPLUS_API_KEY',
        defaultModel: 'doubao-pro-32k',
        models: ['doubao-pro-32k', 'doubao-lite-32k'],
    },
    {
        name: 'huggingface',
        label: 'HuggingFace Router',
        baseUrl: 'https://api-inference.huggingface.co/v1',
        apiKeyEnv: 'HF_API_KEY',
        defaultModel: 'meta-llama/Llama-3.3-70B-Instruct',
        models: ['meta-llama/Llama-3.3-70B-Instruct', 'Qwen/Qwen2.5-72B-Instruct'],
    },
    {
        name: 'sglang',
        label: 'SGLang (local)',
        baseUrl: process.env.SGLANG_BASE_URL || 'http://localhost:30000/v1',
        apiKeyEnv: 'SGLANG_API_KEY', // optional for local; empty string is OK
        defaultModel: 'local',
        models: ['local'],
    },
    {
        name: 'vllm',
        label: 'vLLM (local)',
        baseUrl: process.env.VLLM_BASE_URL || 'http://localhost:8000/v1',
        apiKeyEnv: 'VLLM_API_KEY',
        defaultModel: 'local',
        models: ['local'],
    },
];
export class UniversalProvider {
    name;
    model;
    cfg;
    constructor(cfg) {
        this.cfg = cfg;
        this.name = cfg.name;
        this.model = cfg.defaultModel;
    }
    async chat(messages, options = {}) {
        const apiKey = (process.env[this.cfg.apiKeyEnv] || '').trim();
        // Local providers (SGLang/vLLM) can run keyless; reject only when the
        // env var is explicitly required and missing AND the URL isn't local.
        const isLocal = /^https?:\/\/(localhost|127\.|0\.0\.0\.0|\[::1\])/i.test(this.cfg.baseUrl);
        if (!apiKey && !isLocal) {
            throw new ModelError(`${this.cfg.label} API key not configured (set ${this.cfg.apiKeyEnv})`, 503, this.model);
        }
        return callOpenAICompatible(this.cfg.baseUrl, apiKey || 'no-key', this.model, messages, options);
    }
}
/**
 * Return the subset of universal providers that have keys set right now
 * (or are local URLs). Failover registry uses this on boot + on env reload.
 */
export function activeUniversalProviders() {
    const out = [];
    for (const cfg of UNIVERSAL_PROVIDERS) {
        const isLocal = /^https?:\/\/(localhost|127\.|0\.0\.0\.0|\[::1\])/i.test(cfg.baseUrl);
        const key = (process.env[cfg.apiKeyEnv] || '').trim();
        if (key || isLocal)
            out.push(new UniversalProvider(cfg));
    }
    return out;
}
// Re-export config for type satisfaction in failover where we already pull config
void config;
//# sourceMappingURL=universal.js.map