UNPKG

mcp-memory-ts

Version:

Cloud-based vector MCP memory service for Claude.ai - TypeScript implementation

154 lines 6.27 kB
/** * Import command - Import vCard files to create entities */ import * as fs from 'fs/promises'; import { DatabaseConnection } from '../../database/connection.js'; import { DatabaseOperations } from '../../database/operations.js'; import { parseVCard } from '../../vcard/parser.js'; import { vcardToEntity, validateVCard } from '../../vcard/mapper.js'; import { createEntity } from '../../models/index.js'; import { EntityType, ImportanceLevel } from '../../types/enums.js'; export async function importVCard(options) { const { userId, inputPath, entityType = EntityType.PERSON, personType, importance = ImportanceLevel.MEDIUM, tags = [], dryRun = false, merge = false, } = options; console.log(`Importing vCard from: ${inputPath}`); console.log(`User: ${userId}`); console.log(`Entity type: ${entityType}`); if (personType) console.log(`Person type: ${personType}`); console.log(`Importance: ${importance}`); if (tags.length > 0) console.log(`Tags: ${tags.join(', ')}`); console.log(`Dry run: ${dryRun ? 'YES' : 'NO'}`); console.log(`Merge: ${merge ? 'YES' : 'NO'}`); // Read vCard file const vcardText = await fs.readFile(inputPath, 'utf-8'); // Parse vCards console.log('\nParsing vCard file...'); const vcards = parseVCard(vcardText); console.log(`Found ${vcards.length} vCard entries`); const result = { success: true, imported: 0, updated: 0, failed: 0, errors: [], entities: [], }; if (vcards.length === 0) { console.log('No valid vCards found in file'); return result; } // Connect to database const dbUrl = process.env.TURSO_URL; const authToken = process.env.TURSO_AUTH_TOKEN; if (!dbUrl || !authToken) { throw new Error('TURSO_URL and TURSO_AUTH_TOKEN environment variables are required'); } const db = new DatabaseConnection({ url: dbUrl, authToken, }); await db.connect(); const dbOps = new DatabaseOperations(db); try { // Get user by email or ID let user = await dbOps.getUserByEmail(userId); if (!user) { user = await dbOps.getUserById(userId); } if (!user) { throw new Error(`User not found: ${userId}`); } console.log(`Found user: ${user.email} (${user.id})`); // Get existing entities for merge comparison let existingEntities = []; if (merge) { existingEntities = await dbOps.getEntitiesByUserId(user.id, 10000); console.log(`Found ${existingEntities.length} existing entities for merge comparison`); } // Process each vCard for (let i = 0; i < vcards.length; i++) { const vcard = vcards[i]; try { // Validate vCard const validation = validateVCard(vcard); if (!validation.valid) { result.failed++; result.errors.push({ line: i + 1, card: vcard.fn || 'Unknown', error: validation.errors.join(', '), }); continue; } // Convert to entity const entityData = vcardToEntity(vcard, user.id, { entityType, personType, importance, tags, }); // Check for merge let existingEntity = null; if (merge) { // Try to find by email first, then by name existingEntity = existingEntities.find(e => (e.email && entityData.email && e.email.toLowerCase() === entityData.email.toLowerCase()) || (e.name.toLowerCase() === entityData.name.toLowerCase())) || null; } if (dryRun) { console.log(`[DRY RUN] Would ${existingEntity ? 'skip (already exists)' : 'create'}: ${entityData.name}`); if (existingEntity && merge) { result.updated++; } else if (!existingEntity) { result.imported++; } result.entities.push(entityData); } else { if (existingEntity && merge) { // Skip existing entity in merge mode console.log(`⊘ Skipped (already exists): ${entityData.name}`); result.updated++; result.entities.push(existingEntity); } else if (!existingEntity || !merge) { // Create new entity const entity = createEntity(entityData); const savedEntity = await dbOps.createEntity(entity); console.log(`✓ Imported: ${entityData.name}`); result.imported++; result.entities.push(savedEntity); } } } catch (error) { result.failed++; result.errors.push({ line: i + 1, card: vcard.fn || 'Unknown', error: String(error), }); console.error(`✗ Failed: ${vcard.fn || 'Unknown'} - ${error}`); } } // Summary console.log('\n=== Import Summary ==='); console.log(`Total processed: ${vcards.length}`); console.log(`Successfully imported: ${result.imported}`); console.log(`Successfully updated: ${result.updated}`); console.log(`Failed: ${result.failed}`); if (result.errors.length > 0) { console.log('\n=== Errors ==='); for (const error of result.errors) { console.log(`Line ${error.line} (${error.card}): ${error.error}`); } } result.success = result.failed === 0; } finally { await db.disconnect(); } return result; } //# sourceMappingURL=import.js.map