/**
 * Agent Insights Extension for Clawx TUI.
 *
 * Shows real-time execution metrics in the TUI:
 * - Turn counter in the status bar
 * - Per-tool execution timing
 * - Federation dispatch tags (local vs peer)
 * - End-of-run summary notification
 *
 * This is only possible because we own the agent loop and types.
 */
import { agentMaster } from "../core/agent-master.js";
import { AgentRegistryManager } from "../core/agent-registry.js";
const FEDERATION_DISPATCH = new Set(["agent_run", "agent_batch", "agent_send"]);
const FEDERATION_PEER = new Set([
    "agent_peer_add", "agent_peer_serve", "agent_peer_send",
    "agent_peer_list_workers", "agent_peer_chat",
]);
const FEDERATION_ALL = new Set([
    ...FEDERATION_DISPATCH, ...FEDERATION_PEER,
    "agent_serve", "agent_spawn_local", "agent_list", "agent_remove",
    "agent_network", "agent_status", "agent_result", "agent_cleanup",
    "agent_chat", "agent_chat_direct", "agent_rehydrate_workers",
    "agent_master_status",
]);
function formatDuration(ms) {
    if (ms < 1000)
        return `${ms}ms`;
    if (ms < 60000)
        return `${(ms / 1000).toFixed(1)}s`;
    const mins = Math.floor(ms / 60000);
    const secs = Math.round((ms % 60000) / 1000);
    return `${mins}m${secs}s`;
}
export function createAgentInsightsExtension() {
    return function agentInsightsExtension(pi) {
        let turnCount = 0;
        let toolCallCount = 0;
        let agentStartTime = 0;
        let toolStartTimes = new Map();
        const toolTimings = [];
        let federationCalls = 0;
        let dispatchCalls = 0;
        let peerCalls = 0;
        function reset() {
            turnCount = 0;
            toolCallCount = 0;
            agentStartTime = 0;
            toolStartTimes.clear();
            toolTimings.length = 0;
            federationCalls = 0;
            dispatchCalls = 0;
            peerCalls = 0;
        }
        // Show network status on session start
        pi.on("session_start", async (_event, ctx) => {
            if (agentMaster.isServing()) {
                try {
                    const reg = new AgentRegistryManager();
                    const agents = reg.getAgents();
                    const workers = agents.filter(a => a.type === "local" && a.status !== "offline").length;
                    const peers = agents.filter(a => a.type === "remote").length;
                    const port = agentMaster.getServer()?.port;
                    const parts = [];
                    if (workers > 0)
                        parts.push(`${workers} worker${workers !== 1 ? "s" : ""}`);
                    if (peers > 0)
                        parts.push(`${peers} peer${peers !== 1 ? "s" : ""}`);
                    const netInfo = parts.length > 0 ? parts.join(", ") : "no workers";
                    ctx.ui.setStatus("network", `network: :${port || "?"} ${netInfo}`);
                }
                catch {
                    ctx.ui.setStatus("network", "network: active");
                }
            }
        });
        // Track agent run lifecycle
        pi.on("agent_start", async (_event, ctx) => {
            reset();
            agentStartTime = Date.now();
            ctx.ui.setStatus("turns", "turn 1");
        });
        pi.on("turn_start", async (event, ctx) => {
            turnCount = event.turnIndex + 1;
            ctx.ui.setStatus("turns", `turn ${turnCount}`);
        });
        pi.on("tool_execution_start", async (event, ctx) => {
            toolCallCount++;
            toolStartTimes.set(event.toolCallId, Date.now());
            // Federation tagging
            if (FEDERATION_ALL.has(event.toolName)) {
                federationCalls++;
                if (FEDERATION_DISPATCH.has(event.toolName)) {
                    dispatchCalls++;
                    const target = event.args?.worker_id || event.args?.worker || event.args?.target || "auto";
                    ctx.ui.setWorkingMessage(`dispatching to ${target}...`);
                }
                if (FEDERATION_PEER.has(event.toolName)) {
                    peerCalls++;
                    const peer = event.args?.peer_name || event.args?.peer || "peer";
                    ctx.ui.setWorkingMessage(`contacting ${peer}...`);
                }
            }
            ctx.ui.setStatus("tools", `${toolCallCount} tool${toolCallCount !== 1 ? "s" : ""}`);
        });
        pi.on("tool_execution_end", async (event, ctx) => {
            const startTime = toolStartTimes.get(event.toolCallId);
            if (startTime) {
                const elapsed = Date.now() - startTime;
                toolTimings.push({ name: event.toolName, ms: elapsed });
                toolStartTimes.delete(event.toolCallId);
            }
            // Reset working message if it was a federation tool
            if (FEDERATION_ALL.has(event.toolName)) {
                ctx.ui.setWorkingMessage();
            }
        });
        pi.on("agent_end", async (_event, ctx) => {
            const totalElapsed = Date.now() - agentStartTime;
            if (toolCallCount > 0) {
                // Build summary
                const parts = [
                    `${turnCount} turn${turnCount !== 1 ? "s" : ""}`,
                    `${toolCallCount} tool${toolCallCount !== 1 ? "s" : ""}`,
                    formatDuration(totalElapsed),
                ];
                // Tool breakdown
                const grouped = new Map();
                for (const t of toolTimings) {
                    const entry = grouped.get(t.name) || { count: 0, totalMs: 0 };
                    entry.count++;
                    entry.totalMs += t.ms;
                    grouped.set(t.name, entry);
                }
                const breakdown = Array.from(grouped.entries())
                    .sort((a, b) => b[1].totalMs - a[1].totalMs)
                    .slice(0, 5) // top 5 slowest
                    .map(([name, stats]) => `${name} ${stats.count}x ${formatDuration(stats.totalMs)}`)
                    .join(", ");
                let summary = `${parts.join(" | ")}`;
                if (breakdown)
                    summary += ` — ${breakdown}`;
                if (federationCalls > 0) {
                    const fedParts = [];
                    if (dispatchCalls > 0)
                        fedParts.push(`${dispatchCalls} dispatched`);
                    if (peerCalls > 0)
                        fedParts.push(`${peerCalls} peer`);
                    summary += ` | federation: ${fedParts.join(", ")}`;
                }
                ctx.ui.notify(summary, "info");
            }
            // Update status bar
            ctx.ui.setStatus("turns", undefined);
            ctx.ui.setStatus("tools", undefined);
        });
        // Register /stats command to show last run stats on demand
        pi.registerCommand("stats", {
            description: "Show timing stats from the last agent run",
            handler: async (_args, ctx) => {
                if (toolTimings.length === 0) {
                    ctx.ui.notify("No stats yet — run a task first", "info");
                    return;
                }
                const totalElapsed = Date.now() - agentStartTime;
                const grouped = new Map();
                for (const t of toolTimings) {
                    const entry = grouped.get(t.name) || { count: 0, totalMs: 0 };
                    entry.count++;
                    entry.totalMs += t.ms;
                    grouped.set(t.name, entry);
                }
                const lines = [
                    `Turns: ${turnCount} | Tools: ${toolCallCount} | Total: ${formatDuration(totalElapsed)}`,
                    "",
                ];
                for (const [name, stats] of grouped) {
                    const avg = Math.round(stats.totalMs / stats.count);
                    lines.push(`  ${name}: ${stats.count}x, ${formatDuration(stats.totalMs)}` +
                        (stats.count > 1 ? ` (avg ${formatDuration(avg)})` : ""));
                }
                if (federationCalls > 0) {
                    lines.push("");
                    lines.push(`Federation: ${federationCalls} calls (${dispatchCalls} dispatched, ${peerCalls} peer)`);
                }
                ctx.ui.notify(lines.join("\n"), "info");
            },
        });
    };
}
//# sourceMappingURL=agent-insights.js.map