"use strict";
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.AgentRegistry = void 0;
const fs = __importStar(require("fs-extra"));
const path = __importStar(require("path"));
/**
 * Agent Registry
 *
 * Central marketplace for agent discovery and capability matching.
 * Answers: "Which agent can handle this task?"
 */
class AgentRegistry {
    constructor(baseDir) {
        this.capabilities = new Map();
        this.taskMap = new Map();
        this.registryPath = path.join(baseDir || process.cwd(), ".mycontext", "agent-registry.json");
    }
    /**
     * Initialize: Load persisted registry
     */
    async init() {
        if (await fs.pathExists(this.registryPath)) {
            try {
                const data = await fs.readJson(this.registryPath);
                this.capabilities = new Map(Object.entries(data.capabilities || {}));
                this.taskMap = new Map(Object.entries(data.taskMap || {}));
            }
            catch (error) {
                console.warn("Failed to load agent registry, starting fresh:", error);
            }
        }
        else {
            // Bootstrap with default agents
            await this.bootstrapDefaults();
        }
        await this.persist();
    }
    /**
     * Register an agent capability
     */
    register(capability) {
        this.capabilities.set(capability.agentType, capability);
        // Update task map
        for (const task of capability.handles) {
            const existing = this.taskMap.get(task) || [];
            if (!existing.includes(capability.agentType)) {
                existing.push(capability.agentType);
                this.taskMap.set(task, existing);
            }
        }
    }
    /**
     * Unregister an agent
     */
    unregister(agentType) {
        const capability = this.capabilities.get(agentType);
        if (!capability)
            return false;
        // Remove from capabilities
        this.capabilities.delete(agentType);
        // Remove from task map
        for (const task of capability.handles) {
            const agents = this.taskMap.get(task) || [];
            const filtered = agents.filter((a) => a !== agentType);
            if (filtered.length > 0) {
                this.taskMap.set(task, filtered);
            }
            else {
                this.taskMap.delete(task);
            }
        }
        return true;
    }
    /**
     * Find agents that can handle a specific task
     */
    findAgentsFor(taskType, options) {
        const minScore = options?.minScore ?? 50;
        const maxResults = options?.maxResults ?? 10;
        const matches = [];
        // Direct matches from task map
        const directMatches = this.taskMap.get(taskType) || [];
        for (const agentType of directMatches) {
            const capability = this.capabilities.get(agentType);
            if (!capability)
                continue;
            if (options?.requireParallelizable && !capability.parallelizable) {
                continue;
            }
            matches.push({
                agentType,
                capability,
                score: 100, // Perfect match
                reason: `Handles ${taskType} directly`,
            });
        }
        // Fuzzy matches (similar task types)
        for (const [agentType, capability] of this.capabilities.entries()) {
            if (directMatches.includes(agentType))
                continue; // Already added
            if (options?.requireParallelizable && !capability.parallelizable) {
                continue;
            }
            const score = this.calculateMatchScore(taskType, capability);
            if (score >= minScore) {
                matches.push({
                    agentType,
                    capability,
                    score,
                    reason: `Similar to ${capability.handles.join(", ")}`,
                });
            }
        }
        // Sort by score (descending) and return top N
        return matches
            .sort((a, b) => b.score - a.score)
            .slice(0, maxResults);
    }
    /**
     * Get best agent for a task
     */
    getBestAgentFor(taskType) {
        const matches = this.findAgentsFor(taskType, { maxResults: 1 });
        return matches[0] || null;
    }
    /**
     * Get capability for agent type
     */
    getCapability(agentType) {
        return this.capabilities.get(agentType);
    }
    /**
     * List all registered agents
     */
    listAll() {
        return Array.from(this.capabilities.values());
    }
    /**
     * List agents by tag
     */
    listByTag(tag) {
        return this.listAll().filter((cap) => cap.tags.includes(tag));
    }
    /**
     * List agents that can run in parallel
     */
    listParallelizable() {
        return this.listAll().filter((cap) => cap.parallelizable);
    }
    /**
     * Search agents
     */
    search(query) {
        const lowerQuery = query.toLowerCase();
        return this.listAll().filter((cap) => {
            return (cap.agentType.toLowerCase().includes(lowerQuery) ||
                cap.description.toLowerCase().includes(lowerQuery) ||
                cap.handles.some((h) => h.toLowerCase().includes(lowerQuery)) ||
                cap.tags.some((t) => t.toLowerCase().includes(lowerQuery)));
        });
    }
    /**
     * Get statistics
     */
    getStats() {
        const agents = this.listAll();
        const parallelizable = agents.filter((a) => a.parallelizable).length;
        const avgBudget = agents.reduce((sum, a) => sum + a.contextBudgetKB, 0) / agents.length;
        const byPriority = agents.reduce((acc, a) => {
            acc[a.priority] = (acc[a.priority] || 0) + 1;
            return acc;
        }, {});
        return {
            totalAgents: agents.length,
            parallelizableAgents: parallelizable,
            totalTaskTypes: this.taskMap.size,
            averageContextBudgetKB: Math.round(avgBudget),
            agentsByPriority: byPriority,
        };
    }
    /**
     * Validate registry consistency
     */
    validate() {
        const errors = [];
        // Check for orphaned task map entries
        for (const [task, agents] of this.taskMap.entries()) {
            for (const agentType of agents) {
                if (!this.capabilities.has(agentType)) {
                    errors.push(`Task "${task}" references non-existent agent "${agentType}"`);
                }
            }
        }
        // Check for duplicate handles
        const allHandles = new Map();
        for (const [agentType, capability] of this.capabilities.entries()) {
            for (const handle of capability.handles) {
                const handlers = allHandles.get(handle) || [];
                handlers.push(agentType);
                allHandles.set(handle, handlers);
            }
        }
        // Warn about conflicts (same task handled by non-parallelizable agents)
        for (const [handle, handlers] of allHandles.entries()) {
            if (handlers.length > 1) {
                const nonParallelizable = handlers.filter((h) => {
                    const cap = this.capabilities.get(h);
                    return cap && !cap.parallelizable;
                });
                if (nonParallelizable.length > 1) {
                    errors.push(`Task "${handle}" has multiple non-parallelizable handlers: ${nonParallelizable.join(", ")}`);
                }
            }
        }
        return {
            valid: errors.length === 0,
            errors,
        };
    }
    /**
     * Calculate match score
     */
    calculateMatchScore(taskType, capability) {
        // Exact match
        if (capability.handles.includes(taskType)) {
            return 100;
        }
        // Fuzzy matching based on string similarity
        let maxSimilarity = 0;
        for (const handle of capability.handles) {
            const similarity = this.stringSimilarity(taskType, handle);
            maxSimilarity = Math.max(maxSimilarity, similarity);
        }
        return Math.round(maxSimilarity * 100);
    }
    /**
     * String similarity (simple Levenshtein-based)
     */
    stringSimilarity(a, b) {
        const longer = a.length > b.length ? a : b;
        const shorter = a.length > b.length ? b : a;
        if (longer.length === 0)
            return 1.0;
        const editDistance = this.levenshteinDistance(longer, shorter);
        return (longer.length - editDistance) / longer.length;
    }
    /**
     * Levenshtein distance
     */
    levenshteinDistance(a, b) {
        const matrix = [];
        for (let i = 0; i <= b.length; i++) {
            matrix[i] = [i];
        }
        for (let j = 0; j <= a.length; j++) {
            matrix[0][j] = j;
        }
        for (let i = 1; i <= b.length; i++) {
            for (let j = 1; j <= a.length; j++) {
                if (b.charAt(i - 1) === a.charAt(j - 1)) {
                    matrix[i][j] = matrix[i - 1][j - 1];
                }
                else {
                    matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j] + 1);
                }
            }
        }
        return matrix[b.length][a.length];
    }
    /**
     * Bootstrap default agent capabilities
     */
    async bootstrapDefaults() {
        // Register existing MyContext agents with their capabilities
        const defaults = [
            {
                agentType: "PromptToIntentAgent",
                version: "1.0.0",
                handles: ["intent-extraction", "requirement-analysis"],
                requiredContext: ["user-prompt"],
                contextBudgetKB: 20,
                parallelizable: true,
                estimatedDurationMs: 3000,
                maxDurationMs: 10000,
                dependencies: [],
                conflicts: [],
                cpuIntensive: false,
                requiresNetwork: true,
                description: "Converts natural language prompts to structured intents",
                tags: ["nlp", "intent", "analysis"],
                priority: "high",
            },
            {
                agentType: "FeaturePlannerAgent",
                version: "1.0.0",
                handles: ["feature-decomposition", "dependency-analysis", "feature-planning"],
                requiredContext: ["brain.features", "brain.questions"],
                contextBudgetKB: 100,
                parallelizable: true,
                estimatedDurationMs: 5000,
                maxDurationMs: 20000,
                dependencies: [],
                conflicts: [],
                cpuIntensive: false,
                requiresNetwork: true,
                description: "Plans and decomposes features into tasks",
                tags: ["planning", "features", "architecture"],
                priority: "critical",
            },
            {
                agentType: "CodeGenAgent",
                version: "1.0.0",
                handles: ["code-generation", "component-creation", "file-creation"],
                requiredContext: ["brain.features", "brain.components"],
                contextBudgetKB: 200,
                parallelizable: true,
                estimatedDurationMs: 8000,
                maxDurationMs: 30000,
                dependencies: ["FeaturePlannerAgent"],
                conflicts: [],
                cpuIntensive: true,
                requiresNetwork: true,
                description: "Generates code for components and features",
                tags: ["codegen", "implementation"],
                priority: "high",
            },
            {
                agentType: "ValidationAgent",
                version: "1.0.0",
                handles: ["validation", "syntax-check", "pre-flight-check"],
                requiredContext: ["operations"],
                contextBudgetKB: 50,
                parallelizable: true,
                estimatedDurationMs: 2000,
                maxDurationMs: 10000,
                dependencies: [],
                conflicts: [],
                cpuIntensive: false,
                requiresNetwork: false,
                description: "Validates operations and code syntax",
                tags: ["validation", "quality"],
                priority: "critical",
            },
            {
                agentType: "TestGeneratorAgent",
                version: "1.0.0",
                handles: ["test-generation", "test-planning"],
                requiredContext: ["brain.features", "brain.components"],
                contextBudgetKB: 150,
                parallelizable: true,
                estimatedDurationMs: 6000,
                maxDurationMs: 25000,
                dependencies: ["CodeGenAgent"],
                conflicts: [],
                cpuIntensive: false,
                requiresNetwork: true,
                description: "Generates test suites for components",
                tags: ["testing", "quality"],
                priority: "medium",
            },
        ];
        for (const capability of defaults) {
            this.register(capability);
        }
    }
    /**
     * Persist registry to disk
     */
    async persist() {
        await fs.ensureDir(path.dirname(this.registryPath));
        const data = {
            version: "1.0.0",
            capabilities: Object.fromEntries(this.capabilities),
            taskMap: Object.fromEntries(this.taskMap),
            updatedAt: new Date().toISOString(),
        };
        await fs.writeJson(this.registryPath, data, { spaces: 2 });
    }
}
exports.AgentRegistry = AgentRegistry;
//# sourceMappingURL=AgentRegistry.js.map