/**
 * src/models/registry.ts
 *
 * Single source of truth for "what models are available in Muassis." Used
 * by the dashboard Settings tab and the /api/models endpoint to render a
 * model picker grouped by provider, with cost + capability metadata.
 *
 * Provider availability is derived from process.env at runtime so the
 * dashboard always reflects "what's actually wired right now."
 */
import { config } from '../config.js';
import { OPENAI_MODELS } from './openai.js';
import { KIMI_MODELS } from './kimi.js';
import { ANTHROPIC_MODELS } from './anthropic.js';
export function listAllProviders() {
    // Re-read process.env every call so flipping a key live shows up
    const has = (envKey) => Boolean(process.env[envKey] && process.env[envKey] !== 'mock_google_key' && process.env[envKey] !== 'mock_together_key');
    // Demo: this provider entry now routes through Ollama Cloud (NVIDIA_NIM_BASE_URL=https://ollama.com/v1).
    // Models listed below are Ollama Cloud names (bare, no provider prefix). To
    // restore NIM-native catalog, revert .env and put back the qwen/, deepseek-ai/,
    // meta/ prefixed entries.
    const nim = {
        name: 'nvidia-nim',
        display_name: 'NVIDIA NIM (bundled, free)',
        available: true, // always — bundled key
        api_key_env: 'NVIDIA_NIM_API_KEY',
        setup_url: 'https://build.nvidia.com/',
        bundled: true,
        models: [
            {
                provider: 'nvidia-nim', model: 'kimi-k2.5',
                display_name: 'Kimi K2.5 (default — 1T MoE, fast)',
                context_window: 131072, cost_per_1m_input: 0, cost_per_1m_output: 0,
                supports_tools: true, supports_vision: false,
                available: true, is_bundled: true,
                notes: 'Jan 2026 Kimi. 1T MoE, strong Arabic + tool-calling. ~25s for contract drafts (3× faster than K2.6).',
            },
            {
                provider: 'nvidia-nim', model: 'kimi-k2.6',
                display_name: 'Kimi K2.6 (newest — thinking)',
                context_window: 131072, cost_per_1m_input: 0, cost_per_1m_output: 0,
                supports_tools: true, supports_vision: false,
                available: true, is_bundled: true,
                notes: 'Thinking-mode K2. Best on hard reasoning but adds 60-90s latency on long-form turns.',
            },
            {
                provider: 'nvidia-nim', model: 'kimi-k2-thinking',
                display_name: 'Kimi K2 Thinking (reasoning)',
                context_window: 131072, cost_per_1m_input: 0, cost_per_1m_output: 0,
                supports_tools: true, supports_vision: false,
                available: true, is_bundled: true,
                notes: 'Purpose-built reasoning variant of Kimi K2. Use for complex multi-step plans.',
            },
            {
                provider: 'nvidia-nim', model: 'kimi-k2:1t',
                display_name: 'Kimi K2 1T (original, no thinking)',
                context_window: 131072, cost_per_1m_input: 0, cost_per_1m_output: 0,
                supports_tools: true, supports_vision: false,
                available: true, is_bundled: true,
                notes: 'Older non-thinking K2. Snappier responses, less deliberation.',
            },
            {
                provider: 'nvidia-nim', model: 'qwen3-next:80b',
                display_name: 'Qwen3-Next 80B (legacy fallback)',
                context_window: 131072, cost_per_1m_input: 0, cost_per_1m_output: 0,
                supports_tools: true, supports_vision: false,
                available: true, is_bundled: true,
                notes: 'Previous default. Keep as escape hatch if Kimi misbehaves.',
            },
        ],
    };
    const anthropicAvailable = has('ANTHROPIC_API_KEY');
    const anthropicProvider = {
        name: 'anthropic',
        display_name: 'Anthropic Claude',
        available: anthropicAvailable,
        api_key_env: 'ANTHROPIC_API_KEY',
        setup_url: 'https://console.anthropic.com/settings/keys',
        bundled: false,
        models: Object.entries(ANTHROPIC_MODELS).map(([model, m]) => ({
            provider: 'anthropic', model, display_name: model,
            context_window: m.ctx, cost_per_1m_input: m.in, cost_per_1m_output: m.out,
            supports_tools: m.supports_tools, supports_vision: m.supports_vision,
            available: anthropicAvailable, is_bundled: false,
        })),
    };
    const openaiAvailable = has('OPENAI_API_KEY');
    const openaiProvider = {
        name: 'openai',
        display_name: 'OpenAI ChatGPT',
        available: openaiAvailable,
        api_key_env: 'OPENAI_API_KEY',
        setup_url: 'https://platform.openai.com/api-keys',
        bundled: false,
        models: Object.entries(OPENAI_MODELS).map(([model, m]) => ({
            provider: 'openai', model, display_name: model,
            context_window: m.ctx, cost_per_1m_input: m.in, cost_per_1m_output: m.out,
            supports_tools: m.supports_tools, supports_vision: m.supports_vision,
            available: openaiAvailable, is_bundled: false,
        })),
    };
    const kimiAvailable = has('MOONSHOT_API_KEY');
    const kimiProvider = {
        name: 'kimi',
        display_name: 'Moonshot Kimi',
        available: kimiAvailable,
        api_key_env: 'MOONSHOT_API_KEY',
        setup_url: 'https://platform.moonshot.ai/console/api-keys',
        bundled: false,
        models: Object.entries(KIMI_MODELS).map(([model, m]) => ({
            provider: 'kimi', model, display_name: model,
            context_window: m.ctx, cost_per_1m_input: m.in, cost_per_1m_output: m.out,
            supports_tools: m.supports_tools, supports_vision: m.supports_vision,
            available: kimiAvailable, is_bundled: false,
        })),
    };
    const deepseekAvailable = has('DEEPSEEK_API_KEY');
    const deepseekProvider = {
        name: 'deepseek',
        display_name: 'DeepSeek (direct)',
        available: deepseekAvailable,
        api_key_env: 'DEEPSEEK_API_KEY',
        setup_url: 'https://platform.deepseek.com/api_keys',
        bundled: false,
        models: [
            {
                provider: 'deepseek', model: 'deepseek-reasoner',
                display_name: 'DeepSeek-R1 reasoner',
                context_window: 128_000, cost_per_1m_input: 0.55, cost_per_1m_output: 2.19,
                supports_tools: false, supports_vision: false,
                available: deepseekAvailable, is_bundled: false,
            },
            {
                provider: 'deepseek', model: 'deepseek-chat',
                display_name: 'DeepSeek-V3.2',
                context_window: 128_000, cost_per_1m_input: 0.27, cost_per_1m_output: 1.10,
                supports_tools: true, supports_vision: false,
                available: deepseekAvailable, is_bundled: false,
            },
        ],
    };
    const geminiAvailable = has('GOOGLE_AI_API_KEY');
    const geminiProvider = {
        name: 'gemini',
        display_name: 'Google Gemini',
        available: geminiAvailable,
        api_key_env: 'GOOGLE_AI_API_KEY',
        setup_url: 'https://aistudio.google.com/apikey',
        bundled: false,
        models: [
            {
                provider: 'gemini', model: 'gemini-2.0-flash',
                display_name: 'Gemini 2.0 Flash',
                context_window: 1_000_000, cost_per_1m_input: 0.10, cost_per_1m_output: 0.40,
                supports_tools: true, supports_vision: true,
                available: geminiAvailable, is_bundled: false,
            },
        ],
    };
    return [nim, anthropicProvider, openaiProvider, kimiProvider, deepseekProvider, geminiProvider];
}
/**
 * Resolve the active model for a tier by reading (in order):
 *   1. Per-tenant identity_fact `preference.model.<tier>` (e.g. "anthropic:claude-sonnet-4-6")
 *   2. Env var `MUASSIS_<TIER>_MODEL`
 *   3. Default from MODELS table
 */
export async function resolveActiveModel(tenantId, tier) {
    if (tenantId) {
        try {
            const { getFact } = await import('../autonomy/identity.js');
            const fact = await getFact(tenantId, `preference.model.${tier}`);
            if (fact?.fact_value) {
                const [provider, ...modelParts] = fact.fact_value.split(':');
                if (provider && modelParts.length > 0) {
                    return { provider, model: modelParts.join(':'), source: 'tenant' };
                }
            }
        }
        catch { /* fall through */ }
    }
    const envKey = tier === 'brain' ? 'MUASSIS_BRAIN_MODEL' : tier === 'flash' ? 'MUASSIS_FLASH_MODEL' : 'MUASSIS_REASONING_MODEL';
    const envVal = config[envKey];
    if (envVal) {
        const [provider, ...modelParts] = envVal.split(':');
        if (provider && modelParts.length > 0) {
            return { provider, model: modelParts.join(':'), source: 'env' };
        }
    }
    return null; // signals "use default chain"
}
//# sourceMappingURL=registry.js.map