"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HELPER_AGENT_PRESETS = void 0;
exports.selectModelForTask = selectModelForTask;
exports.getHelperAgentPreset = getHelperAgentPreset;
exports.createHelperAgentConfig = createHelperAgentConfig;
exports.createModelRoutingPolicyFromRegistry = createModelRoutingPolicyFromRegistry;
exports.summarizeRoutingMetrics = summarizeRoutingMetrics;
exports.calibrateModelRoutingPolicy = calibrateModelRoutingPolicy;
const DEFAULT_PROMPT_LENGTH_ESCALATION_THRESHOLD = 6000;
const DEFAULT_FAILURE_ESCALATION_THRESHOLD = 2;
const DEFAULT_CONFIDENCE_ESCALATION_THRESHOLD = 0.45;
exports.HELPER_AGENT_PRESETS = {
    explore: {
        type: 'explore',
        name: 'explore',
        systemPrompt: 'You are a read-only exploration helper. Inspect the available context and return a concise summary with file paths, relevant symbols, and open questions.',
        maxTurns: 6,
        defaultRisk: 'low',
        allowWrites: false,
    },
    summarize: {
        type: 'summarize',
        name: 'summarize',
        systemPrompt: 'You compress noisy context into a short, faithful summary. Preserve decisions, errors, file paths, and next actions. Do not add new facts.',
        maxTurns: 4,
        defaultRisk: 'low',
        allowWrites: false,
    },
    'test-triage': {
        type: 'test-triage',
        name: 'explore',
        systemPrompt: 'You analyze failing test output. Return likely root causes, implicated files, and the smallest next validation command.',
        maxTurns: 5,
        defaultRisk: 'medium',
        allowWrites: false,
    },
    'memory-extract': {
        type: 'memory-extract',
        name: 'explore',
        systemPrompt: 'You extract durable lessons from a session. Return only concise candidate memories with evidence and confidence.',
        maxTurns: 4,
        defaultRisk: 'low',
        allowWrites: false,
    },
    edit: {
        type: 'edit',
        name: 'general',
        systemPrompt: 'You make a narrow code edit that directly satisfies the task. Keep changes minimal and report files changed plus validation status.',
        maxTurns: 8,
        defaultRisk: 'medium',
        allowWrites: true,
    },
    plan: {
        type: 'plan',
        name: 'plan',
        systemPrompt: 'You create a short implementation plan grounded in the provided repository context. Return phases, dependencies, risks, and validation commands.',
        maxTurns: 5,
        defaultRisk: 'medium',
        allowWrites: true,
    },
    review: {
        type: 'review',
        name: 'explore',
        systemPrompt: 'You review completed work for bugs, missing tests, and request fulfillment. Lead with findings ordered by severity.',
        maxTurns: 6,
        defaultRisk: 'high',
        allowWrites: false,
    },
    general: {
        type: 'general',
        name: 'general',
        systemPrompt: 'You are a bounded helper agent. Complete the requested task and return a concise summary of findings and actions.',
        maxTurns: 8,
        defaultRisk: 'medium',
        allowWrites: true,
    },
};
function selectModelForTask(input, policy = {}) {
    const preset = exports.HELPER_AGENT_PRESETS[input.taskType];
    const reasons = [];
    const risk = input.requestedRisk ?? preset.defaultRisk;
    const promptLength = input.prompt?.length ?? 0;
    const previousFailures = input.previousFailures ?? 0;
    const confidence = input.confidence ?? 1;
    const requiresWrite = input.requiresWrite ?? preset.allowWrites;
    const promptThreshold = policy.promptLengthEscalationThreshold ?? DEFAULT_PROMPT_LENGTH_ESCALATION_THRESHOLD;
    const failureThreshold = policy.failureEscalationThreshold ?? DEFAULT_FAILURE_ESCALATION_THRESHOLD;
    const confidenceThreshold = policy.confidenceEscalationThreshold ?? DEFAULT_CONFIDENCE_ESCALATION_THRESHOLD;
    if (risk === 'high')
        reasons.push('high-risk task');
    if (requiresWrite && risk !== 'low')
        reasons.push('state-modifying task');
    if (promptLength > promptThreshold)
        reasons.push('large prompt context');
    if (previousFailures >= failureThreshold)
        reasons.push('previous helper failures');
    if (confidence < confidenceThreshold)
        reasons.push('low helper confidence');
    if (reasons.length > 0) {
        return {
            tier: policy.strongModel ? 'strong' : 'default',
            model: policy.strongModel ?? policy.defaultModel,
            escalated: true,
            reasons,
        };
    }
    if (!requiresWrite && risk === 'low') {
        return {
            tier: policy.smallModel ? 'small' : 'default',
            model: policy.smallModel ?? policy.defaultModel,
            escalated: false,
            reasons: ['bounded low-risk helper task'],
        };
    }
    return {
        tier: 'default',
        model: policy.defaultModel ?? policy.fallbackModel,
        escalated: false,
        reasons: ['default model for medium-risk helper task'],
    };
}
function getHelperAgentPreset(type) {
    return exports.HELPER_AGENT_PRESETS[type];
}
function createHelperAgentConfig(input, policy = {}) {
    const preset = getHelperAgentPreset(input.taskType);
    const routing = selectModelForTask(input, policy);
    return {
        name: preset.name,
        systemPrompt: preset.systemPrompt,
        model: routing.model,
        maxTurns: preset.maxTurns,
        routing,
    };
}
function createModelRoutingPolicyFromRegistry(models) {
    const enabled = models.filter((model) => model.enabled);
    return {
        smallModel: firstModelName(enabled, ['local.general', 'local.summariser']),
        defaultModel: firstModelName(enabled, ['local.coder', 'local.general']),
        strongModel: firstModelName(enabled, ['cloud.reasoner', 'cloud.reviewer']),
        fallbackModel: firstModelName(enabled, ['local.general', 'local.coder', 'local.summariser']),
    };
}
function summarizeRoutingMetrics(metrics) {
    const summary = {
        total: metrics.length,
        success: metrics.filter((metric) => metric.success).length,
        failure: metrics.filter((metric) => !metric.success).length,
        successRate: rate(metrics.filter((metric) => metric.success).length, metrics.length),
        escalationRate: rate(metrics.filter((metric) => metric.escalated).length, metrics.length),
        byTier: {},
        byModel: {},
        topReasons: [],
    };
    const reasonCounts = new Map();
    for (const metric of metrics) {
        addBucket(summary.byTier, metric.tier ?? 'unknown', metric.success);
        addBucket(summary.byModel, metric.model ?? 'unknown', metric.success);
        for (const reason of metric.reasons ?? []) {
            reasonCounts.set(reason, (reasonCounts.get(reason) ?? 0) + 1);
        }
    }
    summary.topReasons = Array.from(reasonCounts.entries())
        .map(([reason, count]) => ({ reason, count }))
        .sort((a, b) => b.count - a.count || a.reason.localeCompare(b.reason))
        .slice(0, 5);
    return summary;
}
function calibrateModelRoutingPolicy(metrics, currentPolicy = {}) {
    const summary = summarizeRoutingMetrics(metrics);
    const suggestedPolicy = {};
    const recommendations = [];
    const small = summary.byTier.small;
    const nonEscalatedFailures = metrics.filter((metric) => !metric.escalated && !metric.success).length;
    if (small && small.count >= 3 && small.successRate < 0.7) {
        suggestedPolicy.confidenceEscalationThreshold = Math.max(currentPolicy.confidenceEscalationThreshold ?? DEFAULT_CONFIDENCE_ESCALATION_THRESHOLD, 0.6);
        recommendations.push('Small helper success is below 70%; raise the confidence escalation threshold before using the small tier.');
    }
    if (nonEscalatedFailures >= 2) {
        suggestedPolicy.failureEscalationThreshold = 1;
        recommendations.push('Repeated non-escalated failures were observed; escalate after the first helper failure.');
    }
    if (summary.escalationRate > 0.8 && summary.successRate > 0.8) {
        suggestedPolicy.promptLengthEscalationThreshold = Math.max(currentPolicy.promptLengthEscalationThreshold ?? DEFAULT_PROMPT_LENGTH_ESCALATION_THRESHOLD, 9000);
        recommendations.push('Most helper work escalates successfully; raise the prompt-length threshold to give smaller helpers more bounded opportunities.');
    }
    if (recommendations.length === 0) {
        recommendations.push('No threshold changes suggested from the available routing metrics.');
    }
    return { summary, suggestedPolicy, recommendations };
}
function addBucket(target, key, success) {
    const bucket = target[key] ?? { count: 0, success: 0, failure: 0, successRate: 0 };
    bucket.count++;
    if (success)
        bucket.success++;
    else
        bucket.failure++;
    bucket.successRate = rate(bucket.success, bucket.count);
    target[key] = bucket;
}
function rate(value, total) {
    return total > 0 ? Number((value / total).toFixed(3)) : 0;
}
function firstModelName(models, roles) {
    for (const role of roles) {
        const model = models.find((candidate) => candidate.role === role);
        if (model)
            return model.model_name;
    }
    return undefined;
}
//# sourceMappingURL=modelRouting.js.map