"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.VectorStoreWeaviate = void 0;
const documents_1 = require("@langchain/core/documents");
const weaviate_1 = require("@langchain/weaviate");
const n8n_workflow_1 = require("n8n-workflow");
const Weaviate_utils_1 = require("./Weaviate.utils");
const ai_utilities_1 = require("@n8n/ai-utilities");
const listSearch_1 = require("../shared/methods/listSearch");
const descriptions_1 = require("../shared/descriptions");
class ExtendedWeaviateVectorStore extends weaviate_1.WeaviateStore {
    static async fromExistingCollection(embeddings, args, defaultFilter) {
        const ctor = this;
        const baseCandidate = await ctor.fromExistingIndex(embeddings, args);
        if (!(baseCandidate instanceof ExtendedWeaviateVectorStore)) {
            throw new n8n_workflow_1.ApplicationError('Weaviate store factory did not return an ExtendedWeaviateVectorStore instance');
        }
        const base = baseCandidate;
        base.args = args;
        if (defaultFilter) {
            base.defaultFilter = defaultFilter;
        }
        return base;
    }
    async similaritySearchVectorWithScore(query, k, filter) {
        filter = filter ?? this.defaultFilter;
        const args = this.args;
        if (args.hybridQuery) {
            const options = {
                limit: k ?? undefined,
                autoLimit: args.autoCutLimit ?? undefined,
                alpha: args.alpha ?? undefined,
                vector: query,
                filter: filter ? (0, Weaviate_utils_1.parseCompositeFilter)(filter) : undefined,
                queryProperties: args.queryProperties
                    ? args.queryProperties.split(',').map((prop) => prop.trim())
                    : undefined,
                maxVectorDistance: args.maxVectorDistance ?? undefined,
                fusionType: args.fusionType,
                returnMetadata: args.hybridExplainScore ? ['explainScore'] : undefined,
            };
            const content = await super.hybridSearch(args.hybridQuery, options);
            return content.map((doc) => {
                const { score, ...metadata } = doc.metadata;
                if (typeof score !== 'number') {
                    throw new n8n_workflow_1.ApplicationError(`Unexpected score type: ${typeof score}`);
                }
                return [
                    new documents_1.Document({
                        pageContent: doc.pageContent,
                        metadata,
                    }),
                    score,
                ];
            });
        }
        return await super.similaritySearchVectorWithScore(query, k, filter ? (0, Weaviate_utils_1.parseCompositeFilter)(filter) : undefined);
    }
}
const sharedFields = [descriptions_1.weaviateCollectionRLC];
const shared_options = [
    {
        displayName: 'Tenant Name',
        name: 'tenant',
        type: 'string',
        default: '',
        validateType: 'string',
        description: 'Tenant Name. Collection must have been created with tenant support enabled.',
    },
    {
        displayName: 'Text Key',
        name: 'textKey',
        type: 'string',
        default: 'text',
        validateType: 'string',
        description: 'The key in the document that contains the embedded text',
    },
    {
        displayName: 'Skip Init Checks',
        name: 'skip_init_checks',
        type: 'boolean',
        default: false,
        validateType: 'boolean',
        description: 'Whether to skip init checks while instantiating the client',
    },
    {
        displayName: 'Init Timeout',
        name: 'timeout_init',
        type: 'number',
        default: 2,
        validateType: 'number',
        description: 'Number of timeout seconds for initial checks',
    },
    {
        displayName: 'Insert Timeout',
        name: 'timeout_insert',
        type: 'number',
        default: 90,
        validateType: 'number',
        description: 'Number of timeout seconds for inserts',
    },
    {
        displayName: 'Query Timeout',
        name: 'timeout_query',
        type: 'number',
        default: 30,
        validateType: 'number',
        description: 'Number of timeout seconds for queries',
    },
    {
        displayName: 'GRPC Proxy',
        name: 'proxy_grpc',
        type: 'string',
        default: '',
        validateType: 'string',
        description: 'Proxy to use for GRPC',
    },
];
const insertFields = [
    {
        displayName: 'Options',
        name: 'options',
        type: 'collection',
        placeholder: 'Add Option',
        default: {},
        options: [
            ...shared_options,
            {
                displayName: 'Clear Data',
                name: 'clearStore',
                type: 'boolean',
                default: false,
                description: 'Whether to clear the Collection/Tenant before inserting new data',
            },
        ],
    },
];
const retrieveFields = [
    {
        displayName: 'Options',
        name: 'options',
        type: 'collection',
        placeholder: 'Add Option',
        default: {},
        options: [
            {
                displayName: 'Search Filters',
                name: 'searchFilterJson',
                type: 'json',
                typeOptions: {
                    rows: 5,
                },
                default: '{\n  "OR": [\n    {\n        "path": ["pdf_info_Author"],\n        "operator": "Equal",\n        "valueString": "Elis"\n    },\n    {\n        "path": ["pdf_info_Author"],\n        "operator": "Equal",\n        "valueString": "Pinnacle"\n    }    \n  ]\n}',
                validateType: 'object',
                description: 'Filter pageContent or metadata using this <a href="https://weaviate.io/" target="_blank">filtering syntax</a>',
            },
            {
                displayName: 'Metadata Keys',
                name: 'metadataKeys',
                type: 'string',
                default: 'source,page',
                validateType: 'string',
                description: 'Select the metadata to retrieve along the content',
            },
            {
                displayName: 'Hybrid: Query Text',
                name: 'hybridQuery',
                type: 'string',
                default: '',
                validateType: 'string',
                description: 'Provide a query text to combine vector search with a keyword/text search',
            },
            {
                displayName: 'Hybrid: Explain Score',
                name: 'hybridExplainScore',
                type: 'boolean',
                default: false,
                validateType: 'boolean',
                description: 'Whether to show the score fused between hybrid and vector search explanation',
            },
            {
                displayName: 'Hybrid: Fusion Type',
                name: 'fusionType',
                type: 'options',
                options: [
                    {
                        name: 'Relative Score',
                        value: 'RelativeScore',
                    },
                    {
                        name: 'Ranked',
                        value: 'Ranked',
                    },
                ],
                default: 'RelativeScore',
                description: 'Select the fusion type for combining vector and keyword search results',
            },
            {
                displayName: 'Hybrid: Auto Cut Limit',
                name: 'autoCutLimit',
                type: 'number',
                default: undefined,
                validateType: 'number',
                description: 'Limit result groups by detecting sudden jumps in score',
            },
            {
                displayName: 'Hybrid: Alpha',
                name: 'alpha',
                type: 'number',
                default: 0.5,
                validateType: 'number',
                description: 'Change the relative weights of the keyword and vector components. 1.0 = pure vector, 0.0 = pure keyword.',
            },
            {
                displayName: 'Hybrid: Query Properties',
                name: 'queryProperties',
                type: 'string',
                default: '',
                validateType: 'string',
                description: 'Comma-separated list of properties to include in the query with optionally weighted values, e.g., "question^2,answer"',
            },
            {
                displayName: 'Hybrid: Max Vector Distance',
                name: 'maxVectorDistance',
                type: 'number',
                default: undefined,
                validateType: 'number',
                description: 'Set the maximum allowable distance for the vector search component',
            },
            ...shared_options,
        ],
    },
];
class VectorStoreWeaviate extends (0, ai_utilities_1.createVectorStoreNode)({
    meta: {
        displayName: 'Weaviate Vector Store',
        name: 'vectorStoreWeaviate',
        description: 'Work with your data in a Weaviate Cluster',
        icon: 'file:weaviate.svg',
        docsUrl: 'https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.vectorstoreweaviate/',
        credentials: [
            {
                name: 'weaviateApi',
                required: true,
            },
        ],
    },
    methods: {
        listSearch: { weaviateCollectionsSearch: listSearch_1.weaviateCollectionsSearch },
    },
    loadFields: retrieveFields,
    insertFields,
    sharedFields,
    retrieveFields,
    async getVectorStoreClient(context, filter, embeddings, itemIndex) {
        const collection = context.getNodeParameter('weaviateCollection', itemIndex, '', {
            extractValue: true,
        });
        const options = context.getNodeParameter('options', itemIndex, {});
        const credentials = await context.getCredentials('weaviateApi');
        const timeout = {
            query: options.timeout_query,
            init: options.timeout_init,
            insert: options.timeout_insert,
        };
        const proxies = {
            grpc: options.proxy_grpc,
        };
        const client = await (0, Weaviate_utils_1.createWeaviateClient)(credentials, timeout, proxies, options.skip_init_checks);
        const metadataKeys = options.metadataKeys ? options.metadataKeys.split(',') : [];
        const config = {
            client,
            indexName: collection,
            tenant: options.tenant ?? undefined,
            textKey: options.textKey ? options.textKey : 'text',
            metadataKeys: metadataKeys,
            hybridQuery: options.hybridQuery ?? undefined,
            autoCutLimit: options.autoCutLimit ?? undefined,
            alpha: options.alpha ?? undefined,
            queryProperties: options.queryProperties,
            maxVectorDistance: options.maxVectorDistance || undefined,
            fusionType: options.fusionType,
            hybridExplainScore: options.hybridExplainScore ?? false,
        };
        const validFilter = (filter && Object.keys(filter).length > 0 ? filter : undefined);
        return await ExtendedWeaviateVectorStore.fromExistingCollection(embeddings, config, validFilter);
    },
    async populateVectorStore(context, embeddings, documents, itemIndex) {
        const collectionName = context.getNodeParameter('weaviateCollection', itemIndex, '', {
            extractValue: true,
        });
        const options = context.getNodeParameter('options', itemIndex, {});
        const credentials = await context.getCredentials('weaviateApi');
        const metadataKeys = options.metadataKeys ? options.metadataKeys.split(',') : [];
        const client = await (0, Weaviate_utils_1.createWeaviateClient)(credentials);
        const config = {
            client,
            indexName: collectionName,
            tenant: options.tenant ?? undefined,
            textKey: options.textKey ? options.textKey : 'text',
            metadataKeys: metadataKeys,
        };
        if (options.clearStore) {
            if (!options.tenant) {
                await client.collections.delete(collectionName);
            }
            else {
                const collection = client.collections.get(collectionName);
                await collection.tenants.remove([{ name: options.tenant }]);
            }
        }
        await weaviate_1.WeaviateStore.fromDocuments(documents, embeddings, config);
    },
}) {
}
exports.VectorStoreWeaviate = VectorStoreWeaviate;
//# sourceMappingURL=VectorStoreWeaviate.node.js.map