/**
 * Tool Converter Utilities
 *
 * Converts between NeuroLink tool format and MCP tool format.
 * Enables seamless interoperability between NeuroLink's internal
 * tool representation and the MCP protocol specification.
 *
 * @module mcp/toolConverter
 * @since 8.39.0
 */
import { inferAnnotations } from "./toolAnnotations.js";
import { withTimeout } from "../utils/async/withTimeout.js";
/**
 * Convert NeuroLink tool to MCP server tool format
 */
export function neuroLinkToolToMCP(tool, options = {}) {
    const { inferAnnotations: shouldInfer = true, defaultAnnotations = {}, preserveMetadata = true, namespacePrefix, } = options;
    // Apply namespace prefix if provided
    const toolName = namespacePrefix
        ? `${namespacePrefix}_${tool.name}`
        : tool.name;
    // Infer annotations from tool definition
    const inferredAnnotations = shouldInfer
        ? inferAnnotations({ name: tool.name, description: tool.description })
        : {};
    // Build annotations
    const annotations = {
        ...defaultAnnotations,
        ...inferredAnnotations,
    };
    // Add tags if present
    if (tool.tags?.length) {
        annotations.tags = [
            ...new Set([...(annotations.tags ?? []), ...tool.tags]),
        ];
    }
    // Build input schema
    const inputSchema = tool.parameters ?? {
        type: "object",
        properties: {},
    };
    // Build metadata
    const metadata = preserveMetadata
        ? { ...tool.metadata }
        : {};
    if (tool.category) {
        metadata.category = tool.category;
    }
    if (tool.isAsync !== undefined) {
        metadata.isAsync = tool.isAsync;
    }
    return {
        name: toolName,
        description: tool.description,
        inputSchema,
        annotations,
        execute: tool.execute,
        metadata,
    };
}
/**
 * Convert MCP server tool to NeuroLink tool format
 */
export function mcpToolToNeuroLink(tool, options = {}) {
    const { removeNamespacePrefix } = options;
    // Remove namespace prefix if provided
    let toolName = tool.name;
    if (removeNamespacePrefix &&
        tool.name.startsWith(`${removeNamespacePrefix}_`)) {
        toolName = tool.name.slice(removeNamespacePrefix.length + 1);
    }
    return {
        name: toolName,
        description: tool.description,
        parameters: tool.inputSchema,
        execute: tool.execute,
        category: tool.metadata?.category,
        tags: tool.annotations?.tags,
        metadata: tool.metadata,
    };
}
/**
 * Convert MCP protocol tool to MCPServerTool
 * (For tools received from external MCP servers)
 */
export function mcpProtocolToolToServerTool(protocolTool, executor, options = {}) {
    const { inferAnnotations: shouldInfer = true, defaultAnnotations = {} } = options;
    // Convert protocol annotations to our format
    const protocolAnnotations = protocolTool.annotations ?? {};
    // Infer additional annotations
    const inferredAnnotations = shouldInfer
        ? inferAnnotations({
            name: protocolTool.name,
            description: protocolTool.description ?? "",
        })
        : {};
    // Merge annotations with precedence: protocol > inferred > defaults
    const annotations = {
        ...defaultAnnotations,
        ...inferredAnnotations,
        title: protocolAnnotations.title ??
            inferredAnnotations.title ??
            defaultAnnotations.title,
        readOnlyHint: protocolAnnotations.readOnlyHint ??
            inferredAnnotations.readOnlyHint ??
            defaultAnnotations.readOnlyHint,
        destructiveHint: protocolAnnotations.destructiveHint ??
            inferredAnnotations.destructiveHint ??
            defaultAnnotations.destructiveHint,
        idempotentHint: protocolAnnotations.idempotentHint ??
            inferredAnnotations.idempotentHint ??
            defaultAnnotations.idempotentHint,
        openWorldHint: protocolAnnotations.openWorldHint ??
            inferredAnnotations.openWorldHint ??
            defaultAnnotations.openWorldHint,
    };
    return {
        name: protocolTool.name,
        description: protocolTool.description ?? "No description provided",
        inputSchema: protocolTool.inputSchema,
        annotations,
        execute: executor,
    };
}
/**
 * Convert MCPServerTool to MCP protocol tool format
 * (For exposing tools to external MCP clients)
 */
export function serverToolToMCPProtocol(tool) {
    // Build protocol annotations
    const annotations = {};
    if (tool.annotations?.title) {
        annotations.title = tool.annotations.title;
    }
    if (tool.annotations?.readOnlyHint !== undefined) {
        annotations.readOnlyHint = tool.annotations.readOnlyHint;
    }
    if (tool.annotations?.destructiveHint !== undefined) {
        annotations.destructiveHint = tool.annotations.destructiveHint;
    }
    if (tool.annotations?.idempotentHint !== undefined) {
        annotations.idempotentHint = tool.annotations.idempotentHint;
    }
    if (tool.annotations?.openWorldHint !== undefined) {
        annotations.openWorldHint = tool.annotations.openWorldHint;
    }
    // Build input schema
    const inputSchema = tool.inputSchema ?? {
        type: "object",
        properties: {},
    };
    return {
        name: tool.name,
        description: tool.description,
        inputSchema: {
            type: "object",
            properties: (inputSchema.properties ?? {}),
            required: ("required" in inputSchema
                ? inputSchema.required
                : undefined),
        },
        annotations: Object.keys(annotations).length > 0 ? annotations : undefined,
    };
}
/**
 * Batch convert NeuroLink tools to MCP format
 */
export function batchConvertToMCP(tools, options = {}) {
    return tools.map((tool) => neuroLinkToolToMCP(tool, options));
}
/**
 * Batch convert MCP tools to NeuroLink format
 */
export function batchConvertToNeuroLink(tools, options = {}) {
    return tools.map((tool) => mcpToolToNeuroLink(tool, options));
}
/**
 * Create a tool from a function with automatic schema inference
 */
export function createToolFromFunction(name, description, fn, options) {
    const inferredAnnotations = inferAnnotations({ name, description });
    return {
        name,
        description,
        inputSchema: options?.parameters ?? { type: "object", properties: {} },
        annotations: {
            ...inferredAnnotations,
            ...options?.annotations,
        },
        execute: async (params, context) => {
            const toolTimeoutMs = 30_000;
            const result = await withTimeout(fn(params, context), toolTimeoutMs, `Tool '${name}' execution timed out after ${toolTimeoutMs}ms`);
            return result;
        },
        metadata: options?.metadata,
    };
}
/**
 * Validate tool name according to MCP specification
 */
export function validateToolName(name) {
    const errors = [];
    if (!name || typeof name !== "string") {
        errors.push("Tool name is required and must be a string");
    }
    else {
        if (name.length > 64) {
            errors.push("Tool name must be 64 characters or less");
        }
        if (!/^[a-zA-Z_][a-zA-Z0-9_-]*$/.test(name)) {
            errors.push("Tool name must start with a letter or underscore and contain only alphanumeric characters, underscores, and hyphens");
        }
    }
    return { valid: errors.length === 0, errors };
}
/**
 * Sanitize tool name for MCP compatibility
 */
export function sanitizeToolName(name) {
    // Replace invalid characters with underscores
    let sanitized = name.replace(/[^a-zA-Z0-9_-]/g, "_");
    // Ensure starts with letter or underscore
    if (!/^[a-zA-Z_]/.test(sanitized)) {
        sanitized = `_${sanitized}`;
    }
    // Truncate to 64 characters
    if (sanitized.length > 64) {
        sanitized = sanitized.slice(0, 64);
    }
    return sanitized;
}
/**
 * Tool compatibility matrix
 */
export const TOOL_COMPATIBILITY = {
    /**
     * Features supported by MCP 2024-11-05 specification
     */
    MCP_2024_11_05: {
        annotations: true,
        inputSchema: true,
        outputSchema: false,
        streamingResults: false,
        batchExecution: false,
    },
    /**
     * Features supported by NeuroLink
     */
    NEUROLINK: {
        annotations: true,
        inputSchema: true,
        outputSchema: true,
        streamingResults: true,
        batchExecution: true,
        categories: true,
        tags: true,
    },
};
//# sourceMappingURL=toolConverter.js.map