(function (factory) {
    if (typeof module === "object" && typeof module.exports === "object") {
        var v = factory(require, exports);
        if (v !== undefined) module.exports = v;
    }
    else if (typeof define === "function" && define.amd) {
        define(["require", "exports", "n8n-workflow"], factory);
    }
})(function (require, exports) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.formatNodeResult = formatNodeResult;
    exports.searchCodeBuilderNodes = searchCodeBuilderNodes;
    const n8n_workflow_1 = require("n8n-workflow");
    function formatBuilderHint(nodeTypeParser, nodeId, version) {
        const nodeType = nodeTypeParser.getLeanNodeType(nodeId, version);
        const hint = nodeType?.builderHint?.searchHint;
        if (!hint)
            return '';
        return `  @builderHint ${hint}`;
    }
    function getDirectRelatedNodeIds(nodeTypeParser, nodeId, version) {
        const nodeType = nodeTypeParser.getLeanNodeType(nodeId, version);
        const relatedNodes = nodeType?.builderHint?.relatedNodes;
        if (!relatedNodes)
            return [];
        return relatedNodes.map((r) => r.nodeType);
    }
    function getRelatedNodesWithHints(nodeTypeParser, nodeId, version, nodeFilter) {
        const nodeType = nodeTypeParser.getLeanNodeType(nodeId, version);
        return nodeType?.builderHint?.relatedNodes?.filter((r) => nodeFilter?.(r.nodeType) ?? true);
    }
    function formatRelatedNodesWithHints(relatedNodes) {
        if (relatedNodes.length === 0)
            return '';
        const lines = ['  @relatedNodes'];
        for (const related of relatedNodes) {
            lines.push(`    - ${related.nodeType}: "${related.relationHint}"`);
        }
        return lines.join('\n');
    }
    function collectAllRelatedNodeIds(nodeTypeParser, initialNodeIds, excludeNodeIds) {
        const allRelated = new Set();
        const visited = new Set();
        for (const node of initialNodeIds) {
            visited.add(node.id);
        }
        for (const id of excludeNodeIds) {
            visited.add(id);
        }
        const queue = [...initialNodeIds];
        while (queue.length > 0) {
            const current = queue.shift();
            const relatedIds = getDirectRelatedNodeIds(nodeTypeParser, current.id, current.version);
            for (const relatedId of relatedIds) {
                if (visited.has(relatedId)) {
                    continue;
                }
                visited.add(relatedId);
                allRelated.add(relatedId);
                const relatedNodeType = nodeTypeParser.getLeanNodeType(relatedId);
                if (relatedNodeType) {
                    const relatedVersion = Array.isArray(relatedNodeType.version)
                        ? relatedNodeType.version[relatedNodeType.version.length - 1]
                        : relatedNodeType.version;
                    queue.push({ id: relatedId, version: relatedVersion });
                }
            }
        }
        return allRelated;
    }
    const CONNECTION_TYPE_TO_SDK = {
        ai_tool: { fn: 'tool()', subnodeField: 'subnodes.tools' },
        ai_vectorStore: { fn: 'vectorStore()', subnodeField: 'subnodes.vectorStore' },
        ai_retriever: { fn: 'retriever()', subnodeField: 'subnodes.retriever' },
        ai_languageModel: { fn: 'languageModel()', subnodeField: 'subnodes.model' },
        ai_memory: { fn: 'memory()', subnodeField: 'subnodes.memory' },
        ai_outputParser: { fn: 'outputParser()', subnodeField: 'subnodes.outputParser' },
        ai_embedding: { fn: 'embeddings()', subnodeField: 'subnodes.embeddings' },
        ai_document: { fn: 'documentLoader()', subnodeField: 'subnodes.documentLoader' },
        ai_textSplitter: { fn: 'textSplitter()', subnodeField: 'subnodes.textSplitter' },
    };
    const MODE_DISPLAY_NAME_OVERRIDES = {
        retrieve: {
            'Retrieve Documents (As Vector Store for Chain/Tool)': 'Retrieve Documents (As Vector Store for Chain)',
        },
    };
    function formatModeForDisplay(mode, showSdkMapping) {
        const lines = [];
        const displayName = MODE_DISPLAY_NAME_OVERRIDES[mode.value]?.[mode.displayName] ?? mode.displayName;
        let firstLine = `      - ${mode.value}: "${displayName}"`;
        if (showSdkMapping) {
            const sdkMapping = mode.outputConnectionType
                ? CONNECTION_TYPE_TO_SDK[mode.outputConnectionType]
                : undefined;
            if (sdkMapping) {
                const fnWithMode = sdkMapping.fn.replace('()', `({ mode: '${mode.value}' })`);
                firstLine += ` → use ${fnWithMode} for ${sdkMapping.subnodeField}`;
            }
            else {
                firstLine += ' → use node()';
            }
        }
        lines.push(firstLine);
        if (mode.description) {
            lines.push(`        ${mode.description}`);
        }
        if (mode.builderHint) {
            lines.push(`        @builderHint ${mode.builderHint.propertyHint}`);
        }
        return lines.join('\n');
    }
    function getDiscriminatorInfo(nodeTypeParser, nodeId, version) {
        const precomputed = nodeTypeParser.getVersionDiscriminators(nodeId, version);
        if (!precomputed) {
            return { type: 'none' };
        }
        const { resourceOperations, operationDiscriminator, modeDiscriminator } = precomputed;
        if (resourceOperations && resourceOperations.resources.length > 0) {
            const resources = resourceOperations.resources
                .filter((r) => r.value !== '__CUSTOM_API_CALL__')
                .map((r) => ({
                value: r.value,
                description: r.description,
                builderHint: r.builderHint,
                operations: r.operations
                    .filter((op) => op.value !== '__CUSTOM_API_CALL__')
                    .map((op) => ({
                    value: op.value,
                    description: op.description,
                    builderHint: op.builderHint,
                })),
            }));
            if (resources.length > 0) {
                return { type: 'resource_operation', resources };
            }
        }
        if (operationDiscriminator && operationDiscriminator.operations.length > 0) {
            const operations = operationDiscriminator.operations
                .filter((op) => op.value !== '__CUSTOM_API_CALL__')
                .map((op) => ({
                value: op.value,
                description: op.description,
                builderHint: op.builderHint,
            }));
            if (operations.length > 0) {
                return { type: 'operation', operations };
            }
        }
        if (modeDiscriminator && modeDiscriminator.modes.length > 0) {
            return { type: 'mode', modes: modeDiscriminator.modes };
        }
        return { type: 'none' };
    }
    function formatResourceOperationLines(resources, nodeId) {
        const lines = ['    resource:'];
        for (const resource of resources) {
            lines.push(`      - ${resource.value}:`);
            if (resource.description) {
                lines.push(`          ${resource.description}`);
            }
            if (resource.builderHint) {
                lines.push(`          @builderHint ${resource.builderHint.propertyHint}`);
            }
            lines.push('          operations:');
            for (const op of resource.operations) {
                lines.push(`            - ${op.value}`);
                if (op.description) {
                    lines.push(`              ${op.description}`);
                }
                if (op.builderHint) {
                    lines.push(`              @builderHint ${op.builderHint.propertyHint}`);
                }
            }
        }
        const firstResource = resources[0];
        const firstOp = firstResource?.operations[0]?.value || 'get';
        lines.push('');
        lines.push('  Use get_node_types with discriminators:');
        lines.push(`    get_node_types({ nodeIds: [{ nodeId: "${nodeId}", resource: "${firstResource?.value}", operation: "${firstOp}" }] })`);
        return lines;
    }
    function formatOperationLines(operations, nodeId) {
        const lines = ['    operation:'];
        for (const op of operations) {
            lines.push(`      - ${op.value}`);
            if (op.description) {
                lines.push(`        ${op.description}`);
            }
            if (op.builderHint) {
                lines.push(`        @builderHint ${op.builderHint.propertyHint}`);
            }
        }
        const firstOp = operations[0]?.value ?? 'default';
        lines.push('');
        lines.push('  Use get_node_types with discriminators:');
        lines.push(`    get_node_types({ nodeIds: [{ nodeId: "${nodeId}", operation: "${firstOp}" }] })`);
        return lines;
    }
    function formatModeLines(modes, nodeId) {
        const lines = ['    mode:'];
        const hasSubnodeModes = modes.some((m) => m.outputConnectionType);
        for (const mode of modes) {
            lines.push(formatModeForDisplay(mode, hasSubnodeModes));
        }
        const firstMode = modes[0];
        lines.push('');
        lines.push('  Use get_node_types with discriminators:');
        lines.push(`    get_node_types({ nodeIds: [{ nodeId: "${nodeId}", mode: "${firstMode.value}" }] })`);
        return lines;
    }
    function formatDiscriminatorInfo(info, nodeId) {
        if (info.type === 'none') {
            return '  Discriminators: none (use node directly without resource/operation/mode)';
        }
        const lines = ['  Discriminators:'];
        if (info.type === 'resource_operation' && info.resources) {
            lines.push(...formatResourceOperationLines(info.resources, nodeId));
        }
        else if (info.type === 'operation' && info.operations) {
            lines.push(...formatOperationLines(info.operations, nodeId));
        }
        else if (info.type === 'mode' && info.modes) {
            lines.push(...formatModeLines(info.modes, nodeId));
        }
        return lines.join('\n');
    }
    function formatNodeResult(nodeTypeParser, nodeId, version) {
        const nodeType = nodeTypeParser.getLeanNodeType(nodeId, version);
        if (!nodeType)
            return undefined;
        const resolvedVersion = version ?? (Array.isArray(nodeType.version) ? Math.max(...nodeType.version) : nodeType.version);
        const triggerTag = (0, n8n_workflow_1.isTriggerNodeType)(nodeId) ? ' [TRIGGER]' : '';
        const basicInfo = `- ${nodeId}${triggerTag}\n  Display Name: ${nodeType.displayName}\n  Version: ${resolvedVersion}\n  Description: ${nodeType.description}`;
        const builderHint = formatBuilderHint(nodeTypeParser, nodeId, resolvedVersion);
        const relatedNodesWithHints = getRelatedNodesWithHints(nodeTypeParser, nodeId, resolvedVersion);
        const discInfo = getDiscriminatorInfo(nodeTypeParser, nodeId, resolvedVersion);
        const discStr = formatDiscriminatorInfo(discInfo, nodeId);
        const parts = [basicInfo];
        if (builderHint)
            parts.push(builderHint);
        if (relatedNodesWithHints && relatedNodesWithHints.length > 0) {
            const relatedNodesStr = formatRelatedNodesWithHints(relatedNodesWithHints);
            if (relatedNodesStr)
                parts.push(relatedNodesStr);
        }
        if (discStr)
            parts.push(discStr);
        return parts.join('\n');
    }
    function searchForQuery(nodeTypeParser, query, nodeFilter) {
        const results = nodeTypeParser.searchNodeTypes(query, 5, nodeFilter);
        if (results.length === 0) {
            return {
                result: `## "${query}"\nNo nodes found. Try a different search term.`,
                hasResults: false,
            };
        }
        const shownNodeIds = new Set(results.map((node) => node.id));
        const allNodeLines = [];
        let totalRelatedCount = 0;
        for (const node of results) {
            const triggerTag = node.isTrigger ? ' [TRIGGER]' : '';
            const basicInfo = `- ${node.id}${triggerTag}\n  Display Name: ${node.displayName}\n  Version: ${node.version}\n  Description: ${node.description}`;
            const builderHint = formatBuilderHint(nodeTypeParser, node.id, node.version);
            const relatedNodesWithHints = getRelatedNodesWithHints(nodeTypeParser, node.id, node.version, nodeFilter);
            const discInfo = getDiscriminatorInfo(nodeTypeParser, node.id, node.version);
            const discStr = formatDiscriminatorInfo(discInfo, node.id);
            const parts = [basicInfo];
            if (builderHint)
                parts.push(builderHint);
            if (relatedNodesWithHints && relatedNodesWithHints.length > 0) {
                const relatedNodesStr = formatRelatedNodesWithHints(relatedNodesWithHints);
                if (relatedNodesStr)
                    parts.push(relatedNodesStr);
            }
            else {
                const relatedNodeIds = collectAllRelatedNodeIds(nodeTypeParser, [{ id: node.id, version: node.version }], shownNodeIds);
                if (discStr)
                    parts.push(discStr);
                allNodeLines.push(parts.join('\n'));
                for (const relatedId of relatedNodeIds) {
                    if (nodeFilter && !nodeFilter(relatedId))
                        continue;
                    const nodeType = nodeTypeParser.getLeanNodeType(relatedId);
                    if (nodeType) {
                        const version = Array.isArray(nodeType.version)
                            ? nodeType.version[nodeType.version.length - 1]
                            : nodeType.version;
                        const relatedTriggerTag = (0, n8n_workflow_1.isTriggerNodeType)(relatedId) ? ' [TRIGGER]' : '';
                        const relatedBasicInfo = `- ${relatedId}${relatedTriggerTag} [RELATED]\n  Display Name: ${nodeType.displayName}\n  Version: ${version}\n  Description: ${nodeType.description}`;
                        const relatedBuilderHint = formatBuilderHint(nodeTypeParser, relatedId, version);
                        const relatedDiscInfo = getDiscriminatorInfo(nodeTypeParser, relatedId, version);
                        const relatedDiscStr = formatDiscriminatorInfo(relatedDiscInfo, relatedId);
                        const relatedParts = [relatedBasicInfo];
                        if (relatedBuilderHint)
                            relatedParts.push(relatedBuilderHint);
                        if (relatedDiscStr)
                            relatedParts.push(relatedDiscStr);
                        allNodeLines.push(relatedParts.join('\n'));
                        shownNodeIds.add(relatedId);
                        totalRelatedCount++;
                    }
                }
                continue;
            }
            if (discStr)
                parts.push(discStr);
            allNodeLines.push(parts.join('\n'));
        }
        const countSuffix = totalRelatedCount > 0 ? ` (+ ${totalRelatedCount} related)` : '';
        return {
            result: `## "${query}"\nFound ${results.length} nodes${countSuffix}:\n\n${allNodeLines.join('\n\n')}`,
            hasResults: true,
        };
    }
    function searchCodeBuilderNodes(nodeTypeParser, queries, options) {
        const { nodeFilter } = options ?? {};
        const searchResults = queries.map((query) => ({
            query,
            ...searchForQuery(nodeTypeParser, query, nodeFilter),
        }));
        return {
            results: searchResults.map(({ result }) => result).join('\n\n---\n\n'),
            queriesWithNoResults: searchResults
                .filter(({ hasResults }) => !hasResults)
                .map(({ query }) => query),
        };
    }
});
//# sourceMappingURL=search.js.map