UNPKG

@notbnull/mcp-cursor-taskmaster

Version:

A project-scoped MCP server requiring explicit --project-dir configuration for task management, memory retrieval, and agentic workflows

131 lines 5.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.VectorStore = void 0; const vectra_1 = require("vectra"); const path_1 = __importDefault(require("path")); const promises_1 = __importDefault(require("fs/promises")); const os_1 = __importDefault(require("os")); class VectorStore { index; embedder; dataDir; indexPath; initialized = false; constructor(dataDir) { // Validate the data directory to prevent issues with invalid paths this.dataDir = this.validateDataDir(dataDir); this.indexPath = path_1.default.join(this.dataDir, "vectors.index"); } validateDataDir(dataDir) { // Extract the project directory from the data directory path const projectDir = path_1.default.dirname(dataDir); const taskmasterDirName = path_1.default.basename(dataDir); // If projectDir is empty, root, or invalid, use a safe fallback if (!projectDir || projectDir === "/" || projectDir === "\\" || taskmasterDirName !== ".taskmaster") { // Use home directory as fallback const fallbackDir = path_1.default.join(os_1.default.homedir(), ".cursor-taskmaster-projects", "default", ".taskmaster"); console.error(`Warning: Invalid data directory "${dataDir}", using fallback: ${fallbackDir}`); return fallbackDir; } // Resolve to absolute path to avoid relative path issues return path_1.default.resolve(dataDir); } async initialize() { try { // Ensure data directory exists console.error(`VectorStore: Creating directory ${this.dataDir}`); await promises_1.default.mkdir(this.dataDir, { recursive: true }); // Initialize the embedding model using dynamic import const { pipeline } = await import("@xenova/transformers"); this.embedder = await pipeline("feature-extraction", "Xenova/all-MiniLM-L6-v2"); // Check if index exists try { await promises_1.default.access(this.indexPath); // Load existing index this.index = new vectra_1.LocalIndex(this.indexPath); } catch { // Create new index this.index = new vectra_1.LocalIndex(this.indexPath); await this.index.createIndex(); } this.initialized = true; console.error(`VectorStore: Successfully initialized in ${this.dataDir}`); } catch (error) { console.error(`VectorStore: Failed to initialize in ${this.dataDir}:`, error); throw new Error(`Failed to initialize VectorStore: ${error instanceof Error ? error.message : "Unknown error"}`); } } async add(document) { if (!this.initialized) { throw new Error("VectorStore not initialized"); } // Generate embedding for the content const embedding = await this.generateEmbedding(document.content); // Add to index await this.index.insertItem({ vector: embedding, metadata: { id: document.id, ...document.metadata, }, }); } async search(query, limit = 5, threshold = 0.7) { if (!this.initialized) { throw new Error("VectorStore not initialized"); } // Generate embedding for the query const queryEmbedding = await this.generateEmbedding(query); // Search the index - updated API call const results = await this.index.queryItems(queryEmbedding, query, limit); // Filter by threshold and format results return results .filter((result) => result.score >= threshold) .map((result) => ({ id: result.item.metadata.id, score: result.score, metadata: result.item.metadata, })); } async delete(id) { if (!this.initialized) { throw new Error("VectorStore not initialized"); } // Find the item by id in metadata const allItems = await this.index.listItems(); const itemToDelete = allItems.find((item) => item.metadata?.id === id); if (itemToDelete) { await this.index.deleteItem(itemToDelete.id); return true; } return false; } async update(document) { // Delete existing and add new await this.delete(document.id); await this.add(document); } async generateEmbedding(text) { // Generate embeddings using the model const output = await this.embedder(text, { pooling: "mean", normalize: true, }); // Convert to array return Array.from(output.data); } async close() { // Vectra handles cleanup automatically this.initialized = false; } } exports.VectorStore = VectorStore; //# sourceMappingURL=vector-store.js.map