/**
 * Supervisor Agent
 *
 * Coordinates multiple sub-agents in parallel, with multiple execution strategies.
 */
import { EventEmitter } from 'events';
// ============================================================================
// Supervisor Agent
// ============================================================================
export class SupervisorAgent extends EventEmitter {
    executor = null;
    /**
     * Set the sub-agent executor function
     */
    setExecutor(exec) {
        this.executor = exec;
    }
    /**
     * Orchestrate a plan
     */
    async orchestrate(plan) {
        const startTime = Date.now();
        this.emit('orchestrate:start', { goal: plan.mainGoal, strategy: plan.mergeStrategy });
        let results;
        switch (plan.mergeStrategy) {
            case 'sequential':
                results = await this.executeSequential(plan.subAgents);
                break;
            case 'parallel':
                results = await this.executeParallel(plan.subAgents);
                break;
            case 'race':
                results = await this.executeRace(plan.subAgents);
                break;
            case 'all':
                results = await this.executeAll(plan.subAgents);
                break;
            default:
                results = await this.executeSequential(plan.subAgents);
        }
        const mergedOutput = this.mergeResults(results, plan.mergeStrategy);
        const success = Array.from(results.values()).some(r => r.success);
        const result = {
            success,
            results,
            strategy: plan.mergeStrategy,
            totalDuration: Date.now() - startTime,
            mergedOutput,
        };
        this.emit('orchestrate:complete', result);
        return result;
    }
    /**
     * Execute tasks sequentially
     */
    async executeSequential(tasks) {
        const results = new Map();
        let context = '';
        for (const task of tasks) {
            const result = await this.executeTask(task, context);
            results.set(task.id, result);
            if (result.success) {
                context += `\n[${task.id}]: ${result.output}`;
            }
            else {
                break; // Stop on failure for sequential
            }
        }
        return results;
    }
    /**
     * Execute tasks in parallel (respecting dependencies)
     */
    async executeParallel(tasks) {
        const results = new Map();
        const completed = new Set();
        const remaining = [...tasks];
        while (remaining.length > 0) {
            const ready = remaining.filter(t => t.dependencies.every(d => completed.has(d)));
            if (ready.length === 0 && remaining.length > 0) {
                // Deadlock
                for (const t of remaining) {
                    results.set(t.id, { success: false, output: '', duration: 0, error: 'Deadlocked' });
                }
                break;
            }
            const batchResults = await Promise.allSettled(ready.map(async (task) => {
                const context = task.dependencies
                    .map(d => results.get(d))
                    .filter(r => r?.success)
                    .map(r => r.output)
                    .join('\n');
                const result = await this.executeTask(task, context);
                results.set(task.id, result);
                completed.add(task.id);
                return result;
            }));
            // Remove completed from remaining
            for (const task of ready) {
                const idx = remaining.indexOf(task);
                if (idx >= 0)
                    remaining.splice(idx, 1);
            }
        }
        return results;
    }
    /**
     * Race: first successful result wins
     */
    async executeRace(tasks) {
        const results = new Map();
        const winner = await Promise.any(tasks.map(async (task) => {
            const result = await this.executeTask(task, '');
            if (!result.success)
                throw new Error(result.error);
            results.set(task.id, result);
            return { task, result };
        })).catch(() => null);
        if (!winner) {
            // All failed
            for (const task of tasks) {
                if (!results.has(task.id)) {
                    results.set(task.id, { success: false, output: '', duration: 0, error: 'All agents failed' });
                }
            }
        }
        return results;
    }
    /**
     * All: execute all regardless of failures
     */
    async executeAll(tasks) {
        const results = new Map();
        await Promise.allSettled(tasks.map(async (task) => {
            const result = await this.executeTask(task, '');
            results.set(task.id, result);
        }));
        return results;
    }
    /**
     * Execute a single task
     */
    async executeTask(task, context) {
        const startTime = Date.now();
        this.emit('task:start', { id: task.id, agent: task.agent });
        try {
            if (!this.executor) {
                throw new Error('No executor set');
            }
            const result = await this.executor(task.agent, task.task, context);
            this.emit('task:complete', { id: task.id, success: result.success });
            return result;
        }
        catch (error) {
            const result = {
                success: false,
                output: '',
                duration: Date.now() - startTime,
                error: error instanceof Error ? error.message : String(error),
            };
            this.emit('task:error', { id: task.id, error: result.error });
            return result;
        }
    }
    /**
     * Merge results into a single output
     */
    mergeResults(results, strategy) {
        const outputs = Array.from(results.entries())
            .filter(([_, r]) => r.success)
            .map(([id, r]) => `[${id}]: ${r.output}`);
        if (strategy === 'race') {
            return outputs[0] || 'No successful results';
        }
        return outputs.join('\n\n---\n\n') || 'No successful results';
    }
}
//# sourceMappingURL=supervisor-agent.js.map