"use strict";
/**
 * Category and tag derivation for compiled workflows.
 *
 * Categories are derived dynamically from registered MCP server metadata —
 * not hardcoded. As new servers are registered, their categories and tags
 * automatically participate in workflow classification.
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.deriveCategory = deriveCategory;
exports.deriveTagsFromSteps = deriveTagsFromSteps;
const mcpDbService = __importStar(require("../../../mcp/db"));
const defaults_1 = require("../../../../modules/defaults");
/**
 * Load category signals from registered MCP servers.
 * Each server's metadata.category becomes a category, with the server's
 * name, tags, and tool names as matching keywords.
 */
async function loadCategorySignals() {
    try {
        const { servers } = await mcpDbService.listMcpServers({ limit: 100 });
        return servers.map(s => ({
            category: s.metadata?.category || 'general',
            keywords: [
                s.name.toLowerCase(),
                ...(s.tags || []).map(t => t.toLowerCase()),
                ...(s.tool_manifest || []).map((t) => t.name?.toLowerCase()).filter(Boolean),
            ],
        }));
    }
    catch {
        return [];
    }
}
/**
 * Derive a category for a compiled workflow based on which MCP servers
 * and tools were used in the execution trace. Queries the DB for
 * current server metadata so new servers are automatically recognized.
 */
async function deriveCategory(steps) {
    const signals = await loadCategorySignals();
    const counts = new Map();
    const tokens = [];
    for (const step of steps) {
        if (step.kind === 'tool') {
            tokens.push(step.toolName.toLowerCase());
            if (step.mcpServerId)
                tokens.push(step.mcpServerId.toLowerCase());
            for (const key of Object.keys(step.arguments)) {
                tokens.push(key.toLowerCase());
            }
        }
    }
    const signalText = tokens.join(' ');
    for (const { category, keywords } of signals) {
        const hits = keywords.filter(kw => signalText.includes(kw)).length;
        if (hits > 0)
            counts.set(category, (counts.get(category) || 0) + hits);
    }
    const hasLlm = steps.some(s => s.kind === 'llm');
    if (hasLlm && (counts.get('database') || counts.get('data-extraction') || 0) > 0) {
        counts.set('reporting', (counts.get('reporting') || 0) + 5);
    }
    let best = 'general';
    let bestCount = 0;
    for (const [cat, count] of counts) {
        if (count > bestCount) {
            best = cat;
            bestCount = count;
        }
    }
    return best;
}
function deriveTagsFromSteps(steps, name, description) {
    const tags = new Set();
    for (const step of steps) {
        if (step.kind === 'tool') {
            tags.add(step.toolName);
            if (step.mcpServerId)
                tags.add(step.mcpServerId);
            tags.add(step.source);
        }
    }
    const text = `${name} ${description || ''}`.toLowerCase();
    const keywords = text
        .replace(/[^a-z0-9\s-]/g, ' ')
        .split(/\s+/)
        .filter((w) => w.length > 2 && !defaults_1.STOP_WORDS.has(w));
    for (const kw of keywords) {
        tags.add(kw);
    }
    return Array.from(tags);
}
