/**
 * Model router — cost-aware model selection.
 * Routes to cheaper models for simple tasks, expensive for complex ones.
 */
import chalk from 'chalk';
import { getModelCost } from './cost-tracker.js';
// Provider-specific model tiers
const MODEL_TIERS = {
    openrouter: [
        { id: 'anthropic/claude-haiku-4', tier: 'fast', description: 'Claude Haiku — fast, cheap' },
        { id: 'anthropic/claude-sonnet-4', tier: 'balanced', description: 'Claude Sonnet — balanced' },
        { id: 'anthropic/claude-opus-4', tier: 'powerful', description: 'Claude Opus — most capable' },
        { id: 'openai/gpt-4o-mini', tier: 'fast', description: 'GPT-4o Mini — fast, cheap' },
        { id: 'openai/gpt-4o', tier: 'balanced', description: 'GPT-4o — balanced' },
        { id: 'google/gemini-2.5-flash', tier: 'fast', description: 'Gemini Flash — fast, cheap' },
        { id: 'google/gemini-2.5-pro', tier: 'powerful', description: 'Gemini Pro — powerful' },
        { id: 'deepseek/deepseek-chat', tier: 'fast', description: 'DeepSeek V3 — very cheap' },
        { id: 'meta-llama/llama-4-maverick', tier: 'balanced', description: 'Llama 4 Maverick — open' },
    ],
    openai: [
        { id: 'gpt-4o-mini', tier: 'fast', description: 'GPT-4o Mini' },
        { id: 'gpt-4o', tier: 'balanced', description: 'GPT-4o' },
        { id: 'o3-mini', tier: 'powerful', description: 'o3-mini (reasoning)' },
    ],
    glm: [
        { id: 'glm-4-flash', tier: 'fast', description: 'GLM-4 Flash' },
        { id: 'glm-4-plus', tier: 'balanced', description: 'GLM-4 Plus' },
        { id: 'glm-4-long', tier: 'powerful', description: 'GLM-4 Long (128k context)' },
    ],
    deepseek: [
        { id: 'deepseek-chat', tier: 'fast', description: 'DeepSeek Chat — fast' },
        { id: 'deepseek-reasoner', tier: 'powerful', description: 'DeepSeek Reasoner — R1' },
    ],
    ollama: [
        { id: 'qwen2.5-coder:latest', tier: 'fast', description: 'Qwen 2.5 Coder (local)' },
        { id: 'deepseek-coder-v2:latest', tier: 'balanced', description: 'DeepSeek Coder v2 (local)' },
        { id: 'llama3.3:latest', tier: 'powerful', description: 'Llama 3.3 (local)' },
    ],
};
/**
 * Classify task complexity from the user's message.
 */
export function classifyComplexity(message) {
    const lower = message.toLowerCase();
    // Simple: short messages, single operations, questions
    const simpleSignals = [
        /^(what|how|why|where|when|who|which|list|show|print|explain)\b/,
        /^(read|cat|ls|find|search|grep|look)\b/,
        /\?([\s]*$)/,
        /^(yes|no|ok|sure|thanks|y|n)\b/i,
    ];
    if (message.length < 100 && simpleSignals.some((r) => r.test(lower))) {
        return 'simple';
    }
    // Complex: multi-step, architecture, large changes
    const complexSignals = [
        /\b(refactor|rewrite|architect|redesign|migrate|implement|build|create .+ system)\b/,
        /\b(entire|whole|all files|full|complete|comprehensive)\b/,
        /\b(performance|security audit|review all|test all)\b/,
        /and\b.*\band\b.*\band\b/, // multiple "and"s = multi-part request
    ];
    if (complexSignals.some((r) => r.test(lower))) {
        return 'complex';
    }
    return 'medium';
}
/**
 * Map provider display names to tier keys
 */
function getProviderKey(displayName) {
    const map = {
        'openrouter': 'openrouter',
        'glm (zhipuai)': 'glm',
        'glm': 'glm',
        'ollama (local)': 'ollama',
        'ollama': 'ollama',
        'lm studio': 'lmstudio',
        'lmstudio': 'lmstudio',
        'openai': 'openai',
        'deepseek': 'deepseek',
        'custom': 'custom',
    };
    const key = displayName.toLowerCase();
    return map[key] || key.replace(/[^a-z]/g, '');
}
/**
 * Suggest the best model for a given complexity and provider.
 */
export function routeModel(config, complexity) {
    const provider = getProviderKey(config.provider);
    const tiers = MODEL_TIERS[provider];
    if (!tiers) {
        return { model: config.model, reason: 'No routing available for this provider' };
    }
    const tierMap = {
        simple: 'fast',
        medium: 'balanced',
        complex: 'powerful',
    };
    const targetTier = tierMap[complexity];
    const match = tiers.find((m) => m.tier === targetTier);
    if (!match) {
        return { model: config.model, reason: 'No matching model tier' };
    }
    const cost = getModelCost(match.id);
    return {
        model: match.id,
        reason: `${complexity} task → ${match.description} ($${cost.input}/$${cost.output} per 1M tokens)`,
    };
}
export function printModelOptions(config) {
    const provider = getProviderKey(config.provider);
    const tiers = MODEL_TIERS[provider] || [];
    console.log(chalk.cyan(`\n  Models for ${config.provider}:`));
    const current = config.model;
    for (const m of tiers) {
        const marker = m.id === current ? chalk.green(' ◀ current') : '';
        const cost = getModelCost(m.id);
        console.log(chalk.white(`  ${m.tier.padEnd(10)}`) +
            chalk.dim(`${m.id.padEnd(35)} $${cost.input}/$${cost.output} per 1M`) +
            marker);
    }
    console.log();
}
/**
 * Switch to a model by name or tier.
 */
export function switchModel(config, nameOrTier) {
    const provider = getProviderKey(config.provider);
    const tiers = MODEL_TIERS[provider] || [];
    // Try exact match first
    const exact = tiers.find((m) => m.id === nameOrTier);
    if (exact)
        return exact.id;
    // Try tier match
    const tier = tiers.find((m) => m.tier === nameOrTier);
    if (tier)
        return tier.id;
    // Try partial match
    const partial = tiers.find((m) => m.id.includes(nameOrTier) || m.description.toLowerCase().includes(nameOrTier.toLowerCase()));
    if (partial)
        return partial.id;
    return null;
}
//# sourceMappingURL=model-router.js.map