UNPKG

@mickdarling/dollhousemcp

Version:

DollhouseMCP - A Model Context Protocol (MCP) server that enables dynamic AI persona management from markdown files, allowing Claude and other compatible AI assistants to activate and switch between different behavioral personas.

139 lines 16.7 kB
/** * Persona loading and file management */ import * as fs from 'fs/promises'; import * as path from 'path'; import { ensureDirectory, generateUniqueId } from '../utils/filesystem.js'; import { SecureYamlParser } from '../security/secureYamlParser.js'; import { SecurityError } from '../errors/SecurityError.js'; import { logger } from '../utils/logger.js'; export class PersonaLoader { personasDir; constructor(personasDir) { this.personasDir = personasDir; } /** * Load all personas from the personas directory */ async loadAll(getCurrentUser) { // Ensure directory exists await ensureDirectory(this.personasDir); const personas = new Map(); try { const files = await fs.readdir(this.personasDir); const markdownFiles = files.filter(file => file.endsWith('.md')); for (const file of markdownFiles) { try { const persona = await this.loadPersona(file, getCurrentUser); if (persona) { personas.set(file, persona); logger.debug(`Loaded persona: ${persona.metadata.name} (${persona.unique_id})`); } } catch (error) { logger.error(`Error loading persona ${file}: ${error}`); } } } catch (error) { logger.error(`Error reading personas directory: ${error}`); } return personas; } /** * Load a single persona from file */ async loadPersona(filename, getCurrentUser) { try { const filePath = path.join(this.personasDir, filename); const fileContent = await fs.readFile(filePath, 'utf-8'); // Use secure YAML parser instead of direct gray-matter let parsed; try { parsed = SecureYamlParser.safeMatter(fileContent); } catch (error) { if (error instanceof SecurityError) { logger.error(`Security threat detected in persona ${filename}: ${error.message}`); return null; } throw error; } const metadata = parsed.data; const content = parsed.content; if (!metadata.name) { metadata.name = path.basename(filename, '.md'); } // Generate unique ID if not present let uniqueId = metadata.unique_id; if (!uniqueId) { const authorForId = metadata.author || getCurrentUser() || undefined; uniqueId = generateUniqueId(metadata.name, authorForId); logger.debug(`Generated unique ID for ${metadata.name}: ${uniqueId}`); } // Set default values for metadata fields this.setDefaultMetadata(metadata); const persona = { metadata, content, filename, unique_id: uniqueId, }; return persona; } catch (error) { logger.error(`Error loading persona ${filename}: ${error}`); return null; } } /** * Save a persona to file */ async savePersona(persona) { const filePath = path.join(this.personasDir, persona.filename); // Use secure YAML stringification const secureParser = SecureYamlParser.createSecureMatterParser(); const fileContent = secureParser.stringify(persona.content, persona.metadata); await fs.writeFile(filePath, fileContent, 'utf-8'); } /** * Delete a persona file */ async deletePersona(filename) { const filePath = path.join(this.personasDir, filename); await fs.unlink(filePath); } /** * Check if a persona file exists */ async personaExists(filename) { try { const filePath = path.join(this.personasDir, filename); await fs.access(filePath); return true; } catch { return false; } } /** * Set default metadata values */ setDefaultMetadata(metadata) { if (!metadata.category) metadata.category = 'general'; if (!metadata.age_rating) metadata.age_rating = 'all'; if (!metadata.content_flags) metadata.content_flags = []; if (metadata.ai_generated === undefined) metadata.ai_generated = false; if (!metadata.generation_method) metadata.generation_method = 'human'; if (!metadata.price) metadata.price = 'free'; if (!metadata.license) metadata.license = 'CC-BY-SA-4.0'; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGVyc29uYUxvYWRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wZXJzb25hL1BlcnNvbmFMb2FkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxPQUFPLEtBQUssRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNsQyxPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUc3QixPQUFPLEVBQUUsZUFBZSxFQUFFLGdCQUFnQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDM0UsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDbkUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzNELE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUU1QyxNQUFNLE9BQU8sYUFBYTtJQUNoQixXQUFXLENBQVM7SUFFNUIsWUFBWSxXQUFtQjtRQUM3QixJQUFJLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztJQUNqQyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsT0FBTyxDQUFDLGNBQW1DO1FBQy9DLDBCQUEwQjtRQUMxQixNQUFNLGVBQWUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7UUFFeEMsTUFBTSxRQUFRLEdBQUcsSUFBSSxHQUFHLEVBQW1CLENBQUM7UUFFNUMsSUFBSSxDQUFDO1lBQ0gsTUFBTSxLQUFLLEdBQUcsTUFBTSxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUNqRCxNQUFNLGFBQWEsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1lBRWpFLEtBQUssTUFBTSxJQUFJLElBQUksYUFBYSxFQUFFLENBQUM7Z0JBQ2pDLElBQUksQ0FBQztvQkFDSCxNQUFNLE9BQU8s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USxHQUFHLFNBQVMsQ0FBQztRQUN0RCxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVU7WUFBRSxRQUFRLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztRQUN0RCxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWE7WUFBRSxRQUFRLENBQUMsYUFBYSxHQUFHLEVBQUUsQ0FBQztRQUN6RCxJQUFJLFFBQVEsQ0FBQyxZQUFZLEtBQUssU0FBUztZQUFFLFFBQVEsQ0FBQyxZQUFZLEdBQUcsS0FBSyxDQUFDO1FBQ3ZFLElBQUksQ0FBQyxRQUFRLENBQUMsaUJBQWlCO1lBQUUsUUFBUSxDQUFDLGlCQUFpQixHQUFHLE9BQU8sQ0FBQztRQUN0RSxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUs7WUFBRSxRQUFRLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQztRQUM3QyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU87WUFBRSxRQUFRLENBQUMsT0FBTyxHQUFHLGNBQWMsQ0FBQztJQUMzRCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFBlcnNvbmEgbG9hZGluZyBhbmQgZmlsZSBtYW5hZ2VtZW50XG4gKi9cblxuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMvcHJvbWlzZXMnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCBtYXR0ZXIgZnJvbSAnZ3JheS1tYXR0ZXInO1xuaW1wb3J0IHsgUGVyc29uYSwgUGVyc29uYU1ldGFkYXRhIH0gZnJvbSAnLi4vdHlwZXMvcGVyc29uYS5qcyc7XG5pbXBvcnQgeyBlbnN1cmVEaXJlY3RvcnksIGdlbmVyYXRlVW5pcXVlSWQgfSBmcm9tICcuLi91dGlscy9maWxlc3lzdGVtLmpzJztcbmltcG9ydCB7IFNlY3VyZVlhbWxQYXJzZXIgfSBmcm9tICcuLi9zZWN1cml0eS9zZWN1cmVZYW1sUGFyc2VyLmpzJztcbmltcG9ydCB7IFNlY3VyaXR5RXJyb3IgfSBmcm9tICcuLi9lcnJvcnMvU2VjdXJpdHlFcnJvci5qcyc7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi91dGlscy9sb2dnZXIuanMnO1xuXG5leHBvcnQgY2xhc3MgUGVyc29uYUxvYWRlciB7XG4gIHByaXZhdGUgcGVyc29uYXNEaXI6IHN0cmluZztcbiAgXG4gIGNvbnN0cnVjdG9yKHBlcnNvbmFzRGlyOiBzdHJpbmcpIHtcbiAgICB0aGlzLnBlcnNvbmFzRGlyID0gcGVyc29uYXNEaXI7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBMb2FkIGFsbCBwZXJzb25hcyBmcm9tIHRoZSBwZXJzb25hcyBkaXJlY3RvcnlcbiAgICovXG4gIGFzeW5jIGxvYWRBbGwoZ2V0Q3VycmVudFVzZXI6ICgpID0+IHN0cmluZyB8IG51bGwpOiBQcm9taXNlPE1hcDxzdHJpbmcsIFBlcnNvbmE+PiB7XG4gICAgLy8gRW5zdXJlIGRpcmVjdG9yeSBleGlzdHNcbiAgICBhd2FpdCBlbnN1cmVEaXJlY3RvcnkodGhpcy5wZXJzb25hc0Rpcik7XG4gICAgXG4gICAgY29uc3QgcGVyc29uYXMgPSBuZXcgTWFwPHN0cmluZywgUGVyc29uYT4oKTtcbiAgICBcbiAgICB0cnkge1xuICAgICAgY29uc3QgZmlsZXMgPSBhd2FpdCBmcy5yZWFkZGlyKHRoaXMucGVyc29uYXNEaXIpO1xuICAgICAgY29uc3QgbWFya2Rvd25GaWxlcyA9IGZpbGVzLmZpbHRlcihmaWxlID0+IGZpbGUuZW5kc1dpdGgoJy5tZCcpKTtcbiAgICAgIFxuICAgICAgZm9yIChjb25zdCBmaWxlIG9mIG1hcmtkb3duRmlsZXMpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBwZXJzb25hID0gYXdhaXQgdGhpcy5sb2FkUGVyc29uYShmaWxlLCBnZXRDdXJyZW50VXNlcik7XG4gICAgICAgICAgaWYgKHBlcnNvbmEpIHtcbiAgICAgICAgICAgIHBlcnNvbmFzLnNldChmaWxlLCBwZXJzb25hKTtcbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZyhgTG9hZGVkIHBlcnNvbmE6ICR7cGVyc29uYS5tZXRhZGF0YS5uYW1lfSAoJHtwZXJzb25hLnVuaXF1ZV9pZH0pYCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIGxvZ2dlci5lcnJvcihgRXJyb3IgbG9hZGluZyBwZXJzb25hICR7ZmlsZX06ICR7ZXJyb3J9YCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgbG9nZ2VyLmVycm9yKGBFcnJvciByZWFkaW5nIHBlcnNvbmFzIGRpcmVjdG9yeTogJHtlcnJvcn1gKTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIHBlcnNvbmFzO1xuICB9XG4gIFxuICAvKipcbiAgICogTG9hZCBhIHNpbmdsZSBwZXJzb25hIGZyb20gZmlsZVxuICAgKi9cbiAgYXN5bmMgbG9hZFBlcnNvbmEoZmlsZW5hbWU6IHN0cmluZywgZ2V0Q3VycmVudFVzZXI6ICgpID0+IHN0cmluZyB8IG51bGwpOiBQcm9taXNlPFBlcnNvbmEgfCBudWxsPiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGZpbGVQYXRoID0gcGF0aC5qb2luKHRoaXMucGVyc29uYXNEaXIsIGZpbGVuYW1lKTtcbiAgICAgIGNvbnN0IGZpbGVDb250ZW50ID0gYXdhaXQgZnMucmVhZEZpbGUoZmlsZVBhdGgsICd1dGYtOCcpO1xuICAgICAgXG4gICAgICAvLyBVc2Ugc2VjdXJlIFlBTUwgcGFyc2VyIGluc3RlYWQgb2YgZGlyZWN0IGdyYXktbWF0dGVyXG4gICAgICBsZXQgcGFyc2VkO1xuICAgICAgdHJ5IHtcbiAgICAgICAgcGFyc2VkID0gU2VjdXJlWWFtbFBhcnNlci5zYWZlTWF0dGVyKGZpbGVDb250ZW50KTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIFNlY3VyaXR5RXJyb3IpIHtcbiAgICAgICAgICBsb2dnZXIuZXJyb3IoYFNlY3VyaXR5IHRocmVhdCBkZXRlY3RlZCBpbiBwZXJzb25hICR7ZmlsZW5hbWV9OiAke2Vycm9yLm1lc3NhZ2V9YCk7XG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9XG4gICAgICBcbiAgICAgIGNvbnN0IG1ldGFkYXRhID0gcGFyc2VkLmRhdGEgYXMgUGVyc29uYU1ldGFkYXRhO1xuICAgICAgY29uc3QgY29udGVudCA9IHBhcnNlZC5jb250ZW50O1xuICAgICAgXG4gICAgICBpZiAoIW1ldGFkYXRhLm5hbWUpIHtcbiAgICAgICAgbWV0YWRhdGEubmFtZSA9IHBhdGguYmFzZW5hbWUoZmlsZW5hbWUsICcubWQnKTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgLy8gR2VuZXJhdGUgdW5pcXVlIElEIGlmIG5vdCBwcmVzZW50XG4gICAgICBsZXQgdW5pcXVlSWQgPSBtZXRhZGF0YS51bmlxdWVfaWQ7XG4gICAgICBpZiAoIXVuaXF1ZUlkKSB7XG4gICAgICAgIGNvbnN0IGF1dGhvckZvcklkID0gbWV0YWRhdGEuYXV0aG9yIHx8IGdldEN1cnJlbnRVc2VyKCkgfHwgdW5kZWZpbmVkO1xuICAgICAgICB1bmlxdWVJZCA9IGdlbmVyYXRlVW5pcXVlSWQobWV0YWRhdGEubmFtZSwgYXV0aG9yRm9ySWQpO1xuICAgICAgICBsb2dnZXIuZGVidWcoYEdlbmVyYXRlZCB1bmlxdWUgSUQgZm9yICR7bWV0YWRhdGEubmFtZX06ICR7dW5pcXVlSWR9YCk7XG4gICAgICB9XG4gICAgICBcbiAgICAgIC8vIFNldCBkZWZhdWx0IHZhbHVlcyBmb3IgbWV0YWRhdGEgZmllbGRzXG4gICAgICB0aGlzLnNldERlZmF1bHRNZXRhZGF0YShtZXRhZGF0YSk7XG4gICAgICBcbiAgICAgIGNvbnN0IHBlcnNvbmE6IFBlcnNvbmEgPSB7XG4gICAgICAgIG1ldGFkYXRhLFxuICAgICAgICBjb250ZW50LFxuICAgICAgICBmaWxlbmFtZSxcbiAgICAgICAgdW5pcXVlX2lkOiB1bmlxdWVJZCxcbiAgICAgIH07XG4gICAgICBcbiAgICAgIHJldHVybiBwZXJzb25hO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoYEVycm9yIGxvYWRpbmcgcGVyc29uYSAke2ZpbGVuYW1lfTogJHtlcnJvcn1gKTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuICBcbiAgLyoqXG4gICAqIFNhdmUgYSBwZXJzb25hIHRvIGZpbGVcbiAgICovXG4gIGFzeW5jIHNhdmVQZXJzb25hKHBlcnNvbmE6IFBlcnNvbmEpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBmaWxlUGF0aCA9IHBhdGguam9pbih0aGlzLnBlcnNvbmFzRGlyLCBwZXJzb25hLmZpbGVuYW1lKTtcbiAgICBcbiAgICAvLyBVc2Ugc2VjdXJlIFlBTUwgc3RyaW5naWZpY2F0aW9uXG4gICAgY29uc3Qgc2VjdXJlUGFyc2VyID0gU2VjdXJlWWFtbFBhcnNlci5jcmVhdGVTZWN1cmVNYXR0ZXJQYXJzZXIoKTtcbiAgICBjb25zdCBmaWxlQ29udGVudCA9IHNlY3VyZVBhcnNlci5zdHJpbmdpZnkocGVyc29uYS5jb250ZW50LCBwZXJzb25hLm1ldGFkYXRhKTtcbiAgICBcbiAgICBhd2FpdCBmcy53cml0ZUZpbGUoZmlsZVBhdGgsIGZpbGVDb250ZW50LCAndXRmLTgnKTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIERlbGV0ZSBhIHBlcnNvbmEgZmlsZVxuICAgKi9cbiAgYXN5bmMgZGVsZXRlUGVyc29uYShmaWxlbmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgZmlsZVBhdGggPSBwYXRoLmpvaW4odGhpcy5wZXJzb25hc0RpciwgZmlsZW5hbWUpO1xuICAgIGF3YWl0IGZzLnVubGluayhmaWxlUGF0aCk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBDaGVjayBpZiBhIHBlcnNvbmEgZmlsZSBleGlzdHNcbiAgICovXG4gIGFzeW5jIHBlcnNvbmFFeGlzdHMoZmlsZW5hbWU6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBmaWxlUGF0aCA9IHBhdGguam9pbih0aGlzLnBlcnNvbmFzRGlyLCBmaWxlbmFtZSk7XG4gICAgICBhd2FpdCBmcy5hY2Nlc3MoZmlsZVBhdGgpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG4gIFxuICAvKipcbiAgICogU2V0IGRlZmF1bHQgbWV0YWRhdGEgdmFsdWVzXG4gICAqL1xuICBwcml2YXRlIHNldERlZmF1bHRNZXRhZGF0YShtZXRhZGF0YTogUGVyc29uYU1ldGFkYXRhKTogdm9pZCB7XG4gICAgaWYgKCFtZXRhZGF0YS5jYXRlZ29yeSkgbWV0YWRhdGEuY2F0ZWdvcnkgPSAnZ2VuZXJhbCc7XG4gICAgaWYgKCFtZXRhZGF0YS5hZ2VfcmF0aW5nKSBtZXRhZGF0YS5hZ2VfcmF0aW5nID0gJ2FsbCc7XG4gICAgaWYgKCFtZXRhZGF0YS5jb250ZW50X2ZsYWdzKSBtZXRhZGF0YS5jb250ZW50X2ZsYWdzID0gW107XG4gICAgaWYgKG1ldGFkYXRhLmFpX2dlbmVyYXRlZCA9PT0gdW5kZWZpbmVkKSBtZXRhZGF0YS5haV9nZW5lcmF0ZWQgPSBmYWxzZTtcbiAgICBpZiAoIW1ldGFkYXRhLmdlbmVyYXRpb25fbWV0aG9kKSBtZXRhZGF0YS5nZW5lcmF0aW9uX21ldGhvZCA9ICdodW1hbic7XG4gICAgaWYgKCFtZXRhZGF0YS5wcmljZSkgbWV0YWRhdGEucHJpY2UgPSAnZnJlZSc7XG4gICAgaWYgKCFtZXRhZGF0YS5saWNlbnNlKSBtZXRhZGF0YS5saWNlbnNlID0gJ0NDLUJZLVNBLTQuMCc7XG4gIH1cbn0iXX0=