import { defineTool } from "@sheason/pi-coding-agent";
import { Type } from "typebox";
import { remoteMcpResourceToken } from "../mcp/remote-mcp-tools.js";
export const DISCOVER_PEER_RESOURCES_TOOL_NAME = "discover_peer_resources";
export function createDiscoverPeerResourcesToolDefinition(getHost) {
    return defineTool({
        name: DISCOVER_PEER_RESOURCES_TOOL_NAME,
        label: "Discover Peer Resources",
        description: "Discover available peer-provided skills, context files, MCP capabilities, and system prompts. Call this when hub-local skills and MCP tools do not cover the task.",
        promptSnippet: "Discover peer skills, context, and MCP tools before using peer_mcp.",
        promptGuidelines: [
            "Use discover_peer_resources when you need capabilities beyond hub-local tools and skills.",
            "After discovering peer MCP tools, use peer_mcp with the exact tool-name to call them.",
        ],
        parameters: Type.Object({
            "peer-id": Type.Optional(Type.String({ description: "Filter results to a specific peer id. Omit to list all peers." })),
            "resource-type": Type.Optional(Type.Union([
                Type.Literal("skills"),
                Type.Literal("mcp"),
                Type.Literal("context"),
                Type.Literal("extensions"),
                Type.Literal("prompts"),
                Type.Literal("themes"),
                Type.Literal("all"),
            ], {
                description: "Type of resources to list. Default: all.",
            })),
        }),
        async execute(_toolCallId, params) {
            const host = getHost();
            const input = params;
            const agentId = host.getAgentId();
            const registry = host.getConfigLayers();
            const peerMcpSnapshots = host.getPeerMcpSnapshots();
            const resourceType = input["resource-type"] ?? "all";
            const filterPeerId = input["peer-id"];
            const lines = ["# D-Pi Peer Resources", ""];
            // Collect peer config layers
            const peerSnapshots = registry.listPeerSnapshots(agentId);
            const peerLayers = [];
            for (const { peerId, snapshot } of peerSnapshots) {
                if (filterPeerId && peerId !== filterPeerId)
                    continue;
                if (snapshot.global) {
                    peerLayers.push({ peerId, scope: "global", layer: snapshot.global });
                }
                if (snapshot.cwdLayer) {
                    peerLayers.push({ peerId, scope: "cwd", layer: snapshot.cwdLayer });
                }
            }
            // Skills section
            if (resourceType === "all" || resourceType === "skills") {
                lines.push("## Peer Skills", "");
                let hasSkills = false;
                for (const { peerId, scope, layer } of peerLayers) {
                    const skills = (layer.skills ?? []).slice().sort((a, b) => a.name.localeCompare(b.name));
                    if (skills.length === 0)
                        continue;
                    hasSkills = true;
                    lines.push(`### Peer ${peerId} (${scope})`, "");
                    for (const skill of skills) {
                        lines.push(`- **${skill.name}**: ${skill.description}`);
                        if (skill.disableModelInvocation) {
                            lines.push("  (explicit-invocation only)");
                        }
                    }
                    lines.push("");
                }
                if (!hasSkills) {
                    lines.push("No peer-provided skills available.", "");
                }
            }
            // Context section (contextFiles + appendSystemPrompt)
            if (resourceType === "all" || resourceType === "context") {
                lines.push("## Peer Context", "");
                let hasContext = false;
                for (const { peerId, scope, layer } of peerLayers) {
                    if ((layer.contextFiles?.length ?? 0) > 0) {
                        hasContext = true;
                        lines.push(`### Peer ${peerId} (${scope}) — Context Files`, "");
                        for (const cf of layer.contextFiles) {
                            lines.push(`#### ${cf.path}`, "", cf.content, "");
                        }
                    }
                    if ((layer.appendSystemPrompt?.length ?? 0) > 0) {
                        hasContext = true;
                        lines.push(`### Peer ${peerId} (${scope}) — System Instructions`, "");
                        for (const prompt of layer.appendSystemPrompt) {
                            lines.push(prompt, "");
                        }
                    }
                }
                if (!hasContext) {
                    lines.push("No peer-provided context available.", "");
                }
            }
            // MCP section
            if (resourceType === "all" || resourceType === "mcp") {
                lines.push("## Peer MCP Capabilities", "");
                lines.push("Call `peer_mcp` with `peer-id`, exact `tool-name`, and `args` when a listed peer MCP tool is needed.", "");
                let hasMcp = false;
                const filteredMcp = filterPeerId
                    ? peerMcpSnapshots.filter((p) => p.peerId === filterPeerId)
                    : peerMcpSnapshots;
                for (const peer of [...filteredMcp].sort((a, b) => a.peerId.localeCompare(b.peerId))) {
                    const runningServers = peer.servers.filter((server) => server.status === "running");
                    if (runningServers.length === 0)
                        continue;
                    hasMcp = true;
                    lines.push(`### Peer MCP: ${peer.peerId}`, "");
                    for (const server of [...runningServers].sort((a, b) => a.name.localeCompare(b.name))) {
                        const resourceId = server.resourceId ?? server.name;
                        lines.push(`- **Server**: ${server.name} (Resource ID: ${resourceId})`);
                        for (const tool of [...server.capabilities.tools].sort((a, b) => a.name.localeCompare(b.name))) {
                            const remoteToolName = `mcp__${remoteMcpResourceToken(peer.peerId, resourceId)}__${tool.name}`;
                            lines.push(`  - \`${remoteToolName}\`${tool.description ? `: ${tool.description}` : ""}`);
                        }
                    }
                    lines.push("");
                }
                if (!hasMcp) {
                    lines.push("No peer-provided MCP tools available.", "");
                }
            }
            // Extensions section
            if (resourceType === "all" || resourceType === "extensions") {
                lines.push("## Peer Extensions", "");
                let hasExtensions = false;
                for (const { peerId, scope, layer } of peerLayers) {
                    const extensions = (layer.extensions ?? []).slice().sort((a, b) => a.name.localeCompare(b.name));
                    if (extensions.length === 0)
                        continue;
                    hasExtensions = true;
                    lines.push(`### Peer ${peerId} (${scope})`, "");
                    for (const ext of extensions) {
                        lines.push(`- **${ext.name}**${ext.filePath ? ` (${ext.filePath})` : ""}`);
                    }
                    lines.push("");
                }
                if (!hasExtensions) {
                    lines.push("No peer-provided extensions available.", "");
                }
                lines.push("Note: Peer extensions can modify agent behavior at runtime. If an extension is needed long-term, move it to the hub.", "");
            }
            // Prompts section
            if (resourceType === "all" || resourceType === "prompts") {
                lines.push("## Peer Prompts", "");
                let hasPrompts = false;
                for (const { peerId, scope, layer } of peerLayers) {
                    const prompts = (layer.prompts ?? []).slice().sort((a, b) => a.name.localeCompare(b.name));
                    if (prompts.length === 0)
                        continue;
                    hasPrompts = true;
                    lines.push(`### Peer ${peerId} (${scope})`, "");
                    for (const prompt of prompts) {
                        lines.push(`- **${prompt.name}**${prompt.filePath ? ` (${prompt.filePath})` : ""}`);
                    }
                    lines.push("");
                }
                if (!hasPrompts) {
                    lines.push("No peer-provided prompts available.", "");
                }
            }
            // Themes section
            if (resourceType === "all" || resourceType === "themes") {
                lines.push("## Peer Themes", "");
                let hasThemes = false;
                for (const { peerId, scope, layer } of peerLayers) {
                    const themes = (layer.themes ?? []).slice().sort((a, b) => a.name.localeCompare(b.name));
                    if (themes.length === 0)
                        continue;
                    hasThemes = true;
                    lines.push(`### Peer ${peerId} (${scope})`, "");
                    for (const theme of themes) {
                        lines.push(`- **${theme.name}**${theme.filePath ? ` (${theme.filePath})` : ""}`);
                    }
                    lines.push("");
                }
                if (!hasThemes) {
                    lines.push("No peer-provided themes available.", "");
                }
            }
            return { content: [{ type: "text", text: lines.join("\n").trimEnd() }], details: null };
        },
    });
}
//# sourceMappingURL=discover-peer-resources.js.map