import { EventEmitter } from 'events';
import { randomUUID } from 'crypto';
export class ACPRouter extends EventEmitter {
    agents = new Map();
    handlers = new Map();
    pendingRequests = new Map();
    messageLog = [];
    maxLogSize;
    constructor(maxLogSize = 100) {
        super();
        this.maxLogSize = maxLogSize;
    }
    register(agent) {
        this.agents.set(agent.id, agent);
        this.emit('agent:registered', agent);
    }
    unregister(agentId) {
        const agent = this.agents.get(agentId);
        if (agent) {
            this.agents.delete(agentId);
            this.emit('agent:unregistered', agent);
        }
    }
    onAction(action, handler) {
        this.handlers.set(action, handler);
    }
    async send(partial) {
        const msg = {
            ...partial,
            id: randomUUID(),
            timestamp: Date.now(),
        };
        this.messageLog.push(msg);
        if (this.messageLog.length > this.maxLogSize) {
            this.messageLog.splice(0, this.messageLog.length - this.maxLogSize);
        }
        return this.route(msg);
    }
    async request(to, action, payload, timeoutMs = 30000) {
        const correlationId = randomUUID();
        const promise = new Promise((resolve, reject) => {
            const timer = setTimeout(() => {
                this.pendingRequests.delete(correlationId);
                reject(new Error(`ACP request timed out after ${timeoutMs}ms: ${action} -> ${to}`));
            }, timeoutMs);
            this.pendingRequests.set(correlationId, { resolve, timer });
        });
        await this.send({
            type: 'request',
            from: 'router',
            to,
            action,
            payload,
            correlationId,
        });
        return promise;
    }
    async route(msg) {
        this.emit('message', msg);
        if (msg.type === 'response' && msg.correlationId) {
            this.resolveRequest(msg.correlationId, msg);
            return null;
        }
        if (msg.to === '*') {
            this.emit('broadcast', msg);
            const handler = this.handlers.get(msg.action);
            if (handler) {
                return handler(msg);
            }
            return null;
        }
        const handler = this.handlers.get(msg.action);
        if (handler) {
            const response = await handler(msg);
            if (response && msg.type === 'request') {
                return response;
            }
            return response;
        }
        return null;
    }
    resolveRequest(correlationId, response) {
        const pending = this.pendingRequests.get(correlationId);
        if (pending) {
            clearTimeout(pending.timer);
            this.pendingRequests.delete(correlationId);
            pending.resolve(response);
        }
    }
    getAgents() {
        return Array.from(this.agents.values());
    }
    getAgent(id) {
        return this.agents.get(id);
    }
    setAgentStatus(agentId, status) {
        const agent = this.agents.get(agentId);
        if (agent) {
            agent.status = status;
            this.emit('agent:status', { agentId, status });
        }
    }
    findByCapability(capability) {
        return Array.from(this.agents.values()).filter((agent) => agent.capabilities.includes(capability));
    }
    getLog() {
        return [...this.messageLog];
    }
    clearLog() {
        this.messageLog = [];
    }
    dispose() {
        this.pendingRequests.forEach((pending) => {
            clearTimeout(pending.timer);
        });
        this.pendingRequests.clear();
        this.removeAllListeners();
    }
}
//# sourceMappingURL=protocol.js.map