/**
 * Agent Network Tool
 *
 * Unified view of the entire agent network: local master, local workers,
 * remote peers, and each peer's workers — all in one command.
 */
import { log } from '../utils/logger.js';
import { AgentRegistryManager } from '../core/agent-registry.js';
import { checkAgentHealth } from '../utils/agent-utils.js';
import { agentMaster } from '../core/agent-master.js';
export const agentNetworkTool = {
    name: 'agent_network',
    label: 'Network Overview',
    description: 'Show unified view of the entire agent network: master, local workers, remote peers and their workers',
    parameters: {
        type: 'object',
        properties: {
            include_offline: {
                type: 'boolean',
                description: 'Include offline agents in listing',
                default: false,
            },
            skip_peer_workers: {
                type: 'boolean',
                description: 'Skip querying remote peers for their worker lists (faster)',
                default: false,
            },
        },
        required: [],
    },
    async execute(_toolCallId, params) {
        const includeOffline = params.include_offline === true;
        const skipPeerWorkers = params.skip_peer_workers === true;
        try {
            const registry = new AgentRegistryManager();
            registry.markOfflineAgents();
            registry.cleanupOldTasks();
            registry.save();
            const agents = registry.getAgents();
            const isServing = agentMaster.isServing();
            const masterConfig = agentMaster.getConfig();
            const selfAgents = agents.filter(a => a.type === 'self');
            const localWorkers = agents.filter(a => a.type === 'local' && (includeOffline || a.status !== 'offline'));
            const remotePeers = agents.filter(a => a.type === 'remote');
            // Health check all local agents in parallel
            const healthResults = new Map();
            const healthChecks = [...localWorkers, ...remotePeers]
                .filter(a => a.endpoint)
                .map(async (a) => {
                const healthy = await checkAgentHealth(a.endpoint, 3000);
                healthResults.set(a.id, healthy);
                // Update registry status based on live health check
                if (healthy && a.status === 'offline') {
                    a.status = 'idle';
                    a.lastHeartbeat = Date.now();
                    registry.upsertAgent(a);
                }
                else if (!healthy && a.status !== 'offline') {
                    a.status = 'offline';
                    registry.upsertAgent(a);
                }
            });
            await Promise.all(healthChecks);
            registry.save();
            // Tasks summary
            const tasks = registry.getTasks();
            const pendingTasks = tasks.filter(t => t.status === 'pending' || t.status === 'running');
            const completedTasks = tasks.filter(t => t.status === 'completed');
            const failedTasks = tasks.filter(t => t.status === 'failed' || t.status === 'cancelled');
            let output = '# Agent Network Overview\n\n';
            // Master status
            output += '## Master\n';
            if (isServing && masterConfig) {
                output += `  ${masterConfig.name} | http://localhost:${masterConfig.port} | serving\n`;
            }
            else {
                output += '  Not serving. Use `agent_serve` to start.\n';
            }
            // Local workers
            output += `\n## Local Workers (${localWorkers.length})\n`;
            if (localWorkers.length === 0) {
                output += '  None. Use `agent_spawn_local --name worker1` to create one.\n';
            }
            else {
                for (const w of localWorkers) {
                    const health = healthResults.get(w.id);
                    const icon = health ? '+' : '-';
                    const persona = w.persona?.loaded ? ` | ${w.persona.name}` : '';
                    output += `  [${icon}] ${w.name} | ${w.status} | ${w.endpoint || 'no endpoint'}${persona}\n`;
                }
            }
            // Remote peers and their workers
            output += `\n## Remote Peers (${remotePeers.length})\n`;
            if (remotePeers.length === 0) {
                output += '  None. Use `agent_peer_add --name peer --endpoint http://host:port` to add.\n';
            }
            else {
                for (const peer of remotePeers) {
                    const health = healthResults.get(peer.id);
                    const icon = health ? '+' : '-';
                    output += `  [${icon}] ${peer.name} | ${peer.status} | ${peer.endpoint || 'no endpoint'}\n`;
                    // Query peer's workers
                    if (!skipPeerWorkers && health && peer.endpoint) {
                        try {
                            const controller = new AbortController();
                            const timeoutId = setTimeout(() => controller.abort(), 5000);
                            const res = await fetch(`${peer.endpoint}/agents`, { signal: controller.signal });
                            clearTimeout(timeoutId);
                            if (res.ok) {
                                const peerAgents = await res.json();
                                const peerWorkers = peerAgents.filter((a) => a.type === 'local' && (includeOffline || a.status !== 'offline'));
                                if (peerWorkers.length > 0) {
                                    for (const pw of peerWorkers) {
                                        const pIcon = pw.status !== 'offline' ? '+' : '-';
                                        const pPersona = pw.persona?.loaded ? ` | ${pw.persona.name}` : '';
                                        output += `    [${pIcon}] ${pw.name} | ${pw.status}${pPersona}\n`;
                                    }
                                }
                                else {
                                    output += '    (no workers)\n';
                                }
                            }
                        }
                        catch {
                            output += '    (could not query workers)\n';
                        }
                    }
                }
            }
            // Tasks summary
            output += '\n## Tasks\n';
            output += `  Active: ${pendingTasks.length} | Completed: ${completedTasks.length} | Failed: ${failedTasks.length}\n`;
            // Show active tasks if any
            if (pendingTasks.length > 0) {
                output += '\n  Active tasks:\n';
                for (const t of pendingTasks.slice(0, 10)) {
                    const agent = registry.getAgent(t.agentId);
                    const agentName = agent?.name || t.agentId.substring(0, 8);
                    const age = Math.floor((Date.now() - t.created) / 1000);
                    output += `    ${t.id.substring(0, 8)} | ${agentName} | ${t.payload.tool} | ${t.status} | ${age}s ago\n`;
                }
                if (pendingTasks.length > 10) {
                    output += `    ... and ${pendingTasks.length - 10} more\n`;
                }
            }
            return {
                content: [{ type: 'text', text: output }],
                details: {
                    is_serving: isServing,
                    local_workers: localWorkers.length,
                    remote_peers: remotePeers.length,
                    active_tasks: pendingTasks.length,
                    completed_tasks: completedTasks.length,
                    failed_tasks: failedTasks.length,
                    agents: agents.map(a => ({
                        id: a.id,
                        name: a.name,
                        type: a.type,
                        status: a.status,
                        endpoint: a.endpoint,
                    })),
                },
            };
        }
        catch (error) {
            log.error('Failed to get network overview:', error);
            return {
                content: [{
                        type: 'text',
                        text: `Failed to get network overview: ${error instanceof Error ? error.message : String(error)}`,
                    }],
                details: { error: error instanceof Error ? error.message : String(error) },
                isError: true,
            };
        }
    },
};
//# sourceMappingURL=agentNetwork.js.map