"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveProxyRequestRoute = void 0;
const helpers_1 = require("../utils/helpers");
const routing_config_1 = require("./routing-config");
const profile_router_1 = require("./profile-router");
const config_loader_facade_1 = require("../config/config-loader-facade");
function loadOpenAICompatProfiles(activeProfile) {
    const config = (0, config_loader_facade_1.loadConfigSafe)();
    const profiles = [activeProfile];
    for (const [profileName, settingsPath] of Object.entries(config.profiles)) {
        if (profileName === activeProfile.profileName) {
            continue;
        }
        try {
            const expandedPath = (0, helpers_1.expandPath)(settingsPath);
            const settings = (0, config_loader_facade_1.loadSettings)(expandedPath);
            const profile = (0, profile_router_1.resolveOpenAICompatProfileConfig)(profileName, expandedPath, settings.env || {});
            if (profile) {
                profiles.push(profile);
            }
        }
        catch {
            // Ignore invalid profiles while routing a live request.
        }
    }
    return profiles;
}
function resolveSelectorTarget(selector, activeProfile, profiles) {
    const trimmed = selector.trim();
    if (!trimmed) {
        return null;
    }
    const colonIndex = trimmed.indexOf(':');
    if (colonIndex > 0) {
        const profileName = trimmed.slice(0, colonIndex).trim();
        const profile = profiles.find((candidate) => candidate.profileName === profileName);
        if (profile) {
            const model = trimmed.slice(colonIndex + 1).trim() || profile.model;
            return { profile, model, explicitProfile: true };
        }
    }
    const namedProfile = profiles.find((candidate) => candidate.profileName === trimmed);
    if (namedProfile) {
        return { profile: namedProfile, model: namedProfile.model, explicitProfile: false };
    }
    return {
        profile: activeProfile,
        model: trimmed,
        explicitProfile: false,
    };
}
function profileSupportsModel(profile, model) {
    return [profile.model, profile.opusModel, profile.sonnetModel, profile.haikuModel].some((candidate) => typeof candidate === 'string' && candidate === model);
}
function estimateTokens(request) {
    let characters = 0;
    for (const message of request.messages) {
        if (typeof message.content === 'string') {
            characters += message.content.length;
            continue;
        }
        if (Array.isArray(message.content)) {
            for (const part of message.content) {
                characters += part.type === 'text' ? part.text.length : part.image_url.url.length;
            }
        }
        if (Array.isArray(message.tool_calls)) {
            for (const toolCall of message.tool_calls) {
                characters += toolCall.function.name.length + toolCall.function.arguments.length;
            }
        }
    }
    if (Array.isArray(request.tools)) {
        characters += JSON.stringify(request.tools).length;
    }
    return Math.max(1, Math.ceil(characters / 4));
}
function detectScenario(request, requestedModel, routing) {
    const estimatedTokens = estimateTokens(request);
    const hasWebSearchTool = request.tools?.some((tool) => tool.function.name === 'web_search') === true;
    const thinkingEnabled = request.reasoning?.enabled === true || typeof request.reasoning_effort === 'string';
    const modelId = requestedModel || '';
    const longContextThreshold = routing.longContextThreshold ?? 60000;
    if (hasWebSearchTool && routing.webSearch) {
        return { scenario: 'webSearch', selector: routing.webSearch, estimatedTokens };
    }
    if (thinkingEnabled && routing.think) {
        return { scenario: 'think', selector: routing.think, estimatedTokens };
    }
    if (estimatedTokens > longContextThreshold && routing.longContext) {
        return { scenario: 'longContext', selector: routing.longContext, estimatedTokens };
    }
    if (modelId.toLowerCase().includes('haiku') && routing.background) {
        return { scenario: 'background', selector: routing.background, estimatedTokens };
    }
    if (!requestedModel && routing.default) {
        return { scenario: 'default', selector: routing.default, estimatedTokens };
    }
    return { estimatedTokens };
}
function resolveProxyRequestRoute(activeProfile, request) {
    const profiles = loadOpenAICompatProfiles(activeProfile);
    const requestedModel = request.model?.trim() || undefined;
    const explicitTarget = requestedModel
        ? resolveSelectorTarget(requestedModel, activeProfile, profiles)
        : null;
    const routing = (0, routing_config_1.loadOpenAICompatProxyRoutingConfig)();
    if (explicitTarget?.explicitProfile) {
        return {
            profile: explicitTarget.profile,
            model: explicitTarget.model,
            estimatedTokens: estimateTokens(request),
            source: 'explicit-profile',
        };
    }
    const scenario = detectScenario(request, requestedModel, routing);
    if (scenario.selector) {
        const scenarioTarget = resolveSelectorTarget(scenario.selector, activeProfile, profiles);
        if (scenarioTarget) {
            return {
                profile: scenarioTarget.profile,
                model: scenarioTarget.model,
                scenario: scenario.scenario,
                estimatedTokens: scenario.estimatedTokens,
                source: 'scenario',
            };
        }
    }
    if (explicitTarget && explicitTarget.profile.profileName !== activeProfile.profileName) {
        return {
            profile: explicitTarget.profile,
            model: explicitTarget.model,
            estimatedTokens: scenario.estimatedTokens,
            source: 'profile-name',
        };
    }
    if (requestedModel) {
        const matchedProfile = profiles.find((profile) => profileSupportsModel(profile, requestedModel));
        if (matchedProfile) {
            return {
                profile: matchedProfile,
                model: requestedModel,
                estimatedTokens: scenario.estimatedTokens,
                source: 'profile-model-match',
            };
        }
        return {
            profile: activeProfile,
            model: requestedModel,
            estimatedTokens: scenario.estimatedTokens,
            source: 'request-model',
        };
    }
    return {
        profile: activeProfile,
        model: activeProfile.model,
        estimatedTokens: scenario.estimatedTokens,
        source: 'active-default',
    };
}
exports.resolveProxyRequestRoute = resolveProxyRequestRoute;
//# sourceMappingURL=request-router.js.map