UNPKG

n8n

Version:

n8n Workflow Automation Tool

162 lines 7.62 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AgentVectorStoresService = void 0; const agents_1 = require("@n8n/agents"); const di_1 = require("@n8n/di"); const credentials_service_1 = require("../../credentials/credentials.service"); const agents_credential_provider_1 = require("./adapters/agents-credential-provider"); const embedding_credential_1 = require("./json-config/embedding-credential"); const vector_store_factory_1 = require("./json-config/vector-store-factory"); const TEST_QUERY = 'n8n connection test'; const TEST_TIMEOUT_MS = 15_000; const MAX_MESSAGE_LENGTH = 500; function errorMessage(error) { const message = error instanceof Error ? error.message : String(error); return message.length > MAX_MESSAGE_LENGTH ? `${message.slice(0, MAX_MESSAGE_LENGTH)}…` : message; } async function withTimeout(work, timeoutMs) { let timer; const timeout = new Promise((_resolve, reject) => { timer = setTimeout(() => reject(new Error('Connection test timed out')), timeoutMs); }); try { return await Promise.race([work(), timeout]); } finally { clearTimeout(timer); } } async function checkPineconeIndex(config, apiKey, actualDimensions) { const none = { failure: null, warning: null }; if (typeof apiKey !== 'string' || !apiKey) return none; try { const { Pinecone } = await import('@pinecone-database/pinecone'); const pc = new Pinecone({ apiKey }); const index = await pc.describeIndex(config.indexName); const expected = index.dimension; if (typeof expected === 'number' && expected !== actualDimensions) { return { failure: `Index "${config.indexName}" expects ${expected} dimensions but model "${config.embedding.model}" produces ${actualDimensions}.`, warning: null, }; } if (config.namespace) { const stats = await pc.index(config.indexName).describeIndexStats(); if (!(config.namespace in (stats.namespaces ?? {}))) { return { failure: null, warning: `Namespace "${config.namespace}" has no data yet in index "${config.indexName}". It will appear once data is indexed — double-check the name if you expected existing data.`, }; } } } catch { } return none; } function readVectorSize(value) { if (!value || typeof value !== 'object') return undefined; if ('size' in value && typeof value.size === 'number') return value.size; return undefined; } function extractQdrantVectorSize(vectorsConfig) { if (!vectorsConfig || typeof vectorsConfig !== 'object') return undefined; const direct = readVectorSize(vectorsConfig); if (direct !== undefined) return direct; const [firstNamedVector] = Object.values(vectorsConfig); return readVectorSize(firstNamedVector); } async function checkQdrantDimension(config, url, apiKey, actualDimensions) { if (typeof url !== 'string' || !url) return null; try { const { QdrantClient } = await import('@qdrant/js-client-rest'); const client = new QdrantClient({ url, ...(typeof apiKey === 'string' && apiKey ? { apiKey } : {}), }); const collection = await client.getCollection(config.collectionName); const expected = extractQdrantVectorSize(collection.config?.params?.vectors); if (typeof expected === 'number' && expected !== actualDimensions) { return `Collection "${config.collectionName}" expects ${expected} dimensions but model "${config.embedding.model}" produces ${actualDimensions}.`; } } catch { } return null; } let AgentVectorStoresService = class AgentVectorStoresService { constructor(credentialsService) { this.credentialsService = credentialsService; } async testConnection(projectId, user, vectorStore) { const credentialProvider = new agents_credential_provider_1.AgentsCredentialProvider(this.credentialsService, projectId, user); let backend; let settled = false; const closeBackend = () => { if (backend) void Promise.resolve(backend.close?.()).catch(() => { }); }; try { return await withTimeout(async () => { const rawCredential = await credentialProvider.resolve(vectorStore.credential); backend = await (0, vector_store_factory_1.buildVectorStoreBackend)(vectorStore, credentialProvider, rawCredential); if (settled) { closeBackend(); throw new Error('Connection test timed out'); } const embeddingOptions = await (0, embedding_credential_1.resolveEmbeddingProviderOptionsFromCredential)(vectorStore.embedding.credential, vectorStore.embedding.model, credentialProvider); const embeddingModel = (0, agents_1.createEmbeddingModel)(vectorStore.embedding.model, embeddingOptions); const { embed } = await import('ai'); const { embedding } = await embed({ model: embeddingModel, value: TEST_QUERY }); const { failure, warning } = await this.checkProviderCompatibility(vectorStore, rawCredential, embedding.length); if (failure) { return { success: false, message: failure }; } await backend.query(embedding, { topK: 1 }); return { success: true, ...(warning ? { warning } : {}) }; }, TEST_TIMEOUT_MS); } catch (error) { return { success: false, message: errorMessage(error) }; } finally { settled = true; closeBackend(); } } async checkProviderCompatibility(vectorStore, rawCredential, actualDimensions) { switch (vectorStore.provider) { case 'pinecone': return await checkPineconeIndex(vectorStore, rawCredential.apiKey, actualDimensions); case 'qdrant': return { failure: await checkQdrantDimension(vectorStore, rawCredential.qdrantUrl, rawCredential.apiKey, actualDimensions), warning: null, }; case 'supabase': case 'postgres': return { failure: null, warning: null }; } } }; exports.AgentVectorStoresService = AgentVectorStoresService; exports.AgentVectorStoresService = AgentVectorStoresService = __decorate([ (0, di_1.Service)(), __metadata("design:paramtypes", [credentials_service_1.CredentialsService]) ], AgentVectorStoresService); //# sourceMappingURL=agent-vector-stores.service.js.map