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.

138 lines 16.5 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'; 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); console.error(`Loaded persona: ${persona.metadata.name} (${persona.unique_id})`); } } catch (error) { console.error(`Error loading persona ${file}: ${error}`); } } } catch (error) { console.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) { console.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); console.error(`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) { console.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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGVyc29uYUxvYWRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9wZXJzb25hL1BlcnNvbmFMb2FkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxPQUFPLEtBQUssRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNsQyxPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUc3QixPQUFPLEVBQUUsZUFBZSxFQUFFLGdCQUFnQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDM0UsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDbkUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRTNELE1BQU0sT0FBTyxhQUFhO0lBQ2hCLFdBQVcsQ0FBUztJQUU1QixZQUFZLFdBQW1CO1FBQzdCLElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO0lBQ2pDLENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxPQUFPLENBQUMsY0FBbUM7UUFDL0MsMEJBQTBCO1FBQzFCLE1BQU0sZUFBZSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUV4QyxNQUFNLFFBQVEsR0FBRyxJQUFJLEdBQUcsRUFBbUIsQ0FBQztRQUU1QyxJQUFJLENBQUM7WUFDSCxNQUFNLEtBQUssR0FBRyxNQUFNLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ2pELE1BQU0sYUFBYSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFFakUsS0FBSyxNQUFNLElBQUksSUFBSSxhQUFhLEVBQUUsQ0FBQztnQkFDakMsSUFBSSxDQUFDO29CQUNILE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUs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QUMsVUFBVTtZQUFFLFFBQVEsQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDO1FBQ3RELElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYTtZQUFFLFFBQVEsQ0FBQyxhQUFhLEdBQUcsRUFBRSxDQUFDO1FBQ3pELElBQUksUUFBUSxDQUFDLFlBQVksS0FBSyxTQUFTO1lBQUUsUUFBUSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUM7UUFDdkUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxpQkFBaUI7WUFBRSxRQUFRLENBQUMsaUJBQWlCLEdBQUcsT0FBTyxDQUFDO1FBQ3RFLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSztZQUFFLFFBQVEsQ0FBQyxLQUFLLEdBQUcsTUFBTSxDQUFDO1FBQzdDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTztZQUFFLFFBQVEsQ0FBQyxPQUFPLEdBQUcsY0FBYyxDQUFDO0lBQzNELENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogUGVyc29uYSBsb2FkaW5nIGFuZCBmaWxlIG1hbmFnZW1lbnRcbiAqL1xuXG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcy9wcm9taXNlcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IG1hdHRlciBmcm9tICdncmF5LW1hdHRlcic7XG5pbXBvcnQgeyBQZXJzb25hLCBQZXJzb25hTWV0YWRhdGEgfSBmcm9tICcuLi90eXBlcy9wZXJzb25hLmpzJztcbmltcG9ydCB7IGVuc3VyZURpcmVjdG9yeSwgZ2VuZXJhdGVVbmlxdWVJZCB9IGZyb20gJy4uL3V0aWxzL2ZpbGVzeXN0ZW0uanMnO1xuaW1wb3J0IHsgU2VjdXJlWWFtbFBhcnNlciB9IGZyb20gJy4uL3NlY3VyaXR5L3NlY3VyZVlhbWxQYXJzZXIuanMnO1xuaW1wb3J0IHsgU2VjdXJpdHlFcnJvciB9IGZyb20gJy4uL2Vycm9ycy9TZWN1cml0eUVycm9yLmpzJztcblxuZXhwb3J0IGNsYXNzIFBlcnNvbmFMb2FkZXIge1xuICBwcml2YXRlIHBlcnNvbmFzRGlyOiBzdHJpbmc7XG4gIFxuICBjb25zdHJ1Y3RvcihwZXJzb25hc0Rpcjogc3RyaW5nKSB7XG4gICAgdGhpcy5wZXJzb25hc0RpciA9IHBlcnNvbmFzRGlyO1xuICB9XG4gIFxuICAvKipcbiAgICogTG9hZCBhbGwgcGVyc29uYXMgZnJvbSB0aGUgcGVyc29uYXMgZGlyZWN0b3J5XG4gICAqL1xuICBhc3luYyBsb2FkQWxsKGdldEN1cnJlbnRVc2VyOiAoKSA9PiBzdHJpbmcgfCBudWxsKTogUHJvbWlzZTxNYXA8c3RyaW5nLCBQZXJzb25hPj4ge1xuICAgIC8vIEVuc3VyZSBkaXJlY3RvcnkgZXhpc3RzXG4gICAgYXdhaXQgZW5zdXJlRGlyZWN0b3J5KHRoaXMucGVyc29uYXNEaXIpO1xuICAgIFxuICAgIGNvbnN0IHBlcnNvbmFzID0gbmV3IE1hcDxzdHJpbmcsIFBlcnNvbmE+KCk7XG4gICAgXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGZpbGVzID0gYXdhaXQgZnMucmVhZGRpcih0aGlzLnBlcnNvbmFzRGlyKTtcbiAgICAgIGNvbnN0IG1hcmtkb3duRmlsZXMgPSBmaWxlcy5maWx0ZXIoZmlsZSA9PiBmaWxlLmVuZHNXaXRoKCcubWQnKSk7XG4gICAgICBcbiAgICAgIGZvciAoY29uc3QgZmlsZSBvZiBtYXJrZG93bkZpbGVzKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcGVyc29uYSA9IGF3YWl0IHRoaXMubG9hZFBlcnNvbmEoZmlsZSwgZ2V0Q3VycmVudFVzZXIpO1xuICAgICAgICAgIGlmIChwZXJzb25hKSB7XG4gICAgICAgICAgICBwZXJzb25hcy5zZXQoZmlsZSwgcGVyc29uYSk7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGBMb2FkZWQgcGVyc29uYTogJHtwZXJzb25hLm1ldGFkYXRhLm5hbWV9ICgke3BlcnNvbmEudW5pcXVlX2lkfSlgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihgRXJyb3IgbG9hZGluZyBwZXJzb25hICR7ZmlsZX06ICR7ZXJyb3J9YCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc29sZS5lcnJvcihgRXJyb3IgcmVhZGluZyBwZXJzb25hcyBkaXJlY3Rvcnk6ICR7ZXJyb3J9YCk7XG4gICAgfVxuICAgIFxuICAgIHJldHVybiBwZXJzb25hcztcbiAgfVxuICBcbiAgLyoqXG4gICAqIExvYWQgYSBzaW5nbGUgcGVyc29uYSBmcm9tIGZpbGVcbiAgICovXG4gIGFzeW5jIGxvYWRQZXJzb25hKGZpbGVuYW1lOiBzdHJpbmcsIGdldEN1cnJlbnRVc2VyOiAoKSA9PiBzdHJpbmcgfCBudWxsKTogUHJvbWlzZTxQZXJzb25hIHwgbnVsbD4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBmaWxlUGF0aCA9IHBhdGguam9pbih0aGlzLnBlcnNvbmFzRGlyLCBmaWxlbmFtZSk7XG4gICAgICBjb25zdCBmaWxlQ29udGVudCA9IGF3YWl0IGZzLnJlYWRGaWxlKGZpbGVQYXRoLCAndXRmLTgnKTtcbiAgICAgIFxuICAgICAgLy8gVXNlIHNlY3VyZSBZQU1MIHBhcnNlciBpbnN0ZWFkIG9mIGRpcmVjdCBncmF5LW1hdHRlclxuICAgICAgbGV0IHBhcnNlZDtcbiAgICAgIHRyeSB7XG4gICAgICAgIHBhcnNlZCA9IFNlY3VyZVlhbWxQYXJzZXIuc2FmZU1hdHRlcihmaWxlQ29udGVudCk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBTZWN1cml0eUVycm9yKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihgU2VjdXJpdHkgdGhyZWF0IGRldGVjdGVkIGluIHBlcnNvbmEgJHtmaWxlbmFtZX06ICR7ZXJyb3IubWVzc2FnZX1gKTtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgY29uc3QgbWV0YWRhdGEgPSBwYXJzZWQuZGF0YSBhcyBQZXJzb25hTWV0YWRhdGE7XG4gICAgICBjb25zdCBjb250ZW50ID0gcGFyc2VkLmNvbnRlbnQ7XG4gICAgICBcbiAgICAgIGlmICghbWV0YWRhdGEubmFtZSkge1xuICAgICAgICBtZXRhZGF0YS5uYW1lID0gcGF0aC5iYXNlbmFtZShmaWxlbmFtZSwgJy5tZCcpO1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBHZW5lcmF0ZSB1bmlxdWUgSUQgaWYgbm90IHByZXNlbnRcbiAgICAgIGxldCB1bmlxdWVJZCA9IG1ldGFkYXRhLnVuaXF1ZV9pZDtcbiAgICAgIGlmICghdW5pcXVlSWQpIHtcbiAgICAgICAgY29uc3QgYXV0aG9yRm9ySWQgPSBtZXRhZGF0YS5hdXRob3IgfHwgZ2V0Q3VycmVudFVzZXIoKSB8fCB1bmRlZmluZWQ7XG4gICAgICAgIHVuaXF1ZUlkID0gZ2VuZXJhdGVVbmlxdWVJZChtZXRhZGF0YS5uYW1lLCBhdXRob3JGb3JJZCk7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYEdlbmVyYXRlZCB1bmlxdWUgSUQgZm9yICR7bWV0YWRhdGEubmFtZX06ICR7dW5pcXVlSWR9YCk7XG4gICAgICB9XG4gICAgICBcbiAgICAgIC8vIFNldCBkZWZhdWx0IHZhbHVlcyBmb3IgbWV0YWRhdGEgZmllbGRzXG4gICAgICB0aGlzLnNldERlZmF1bHRNZXRhZGF0YShtZXRhZGF0YSk7XG4gICAgICBcbiAgICAgIGNvbnN0IHBlcnNvbmE6IFBlcnNvbmEgPSB7XG4gICAgICAgIG1ldGFkYXRhLFxuICAgICAgICBjb250ZW50LFxuICAgICAgICBmaWxlbmFtZSxcbiAgICAgICAgdW5pcXVlX2lkOiB1bmlxdWVJZCxcbiAgICAgIH07XG4gICAgICBcbiAgICAgIHJldHVybiBwZXJzb25hO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLmVycm9yKGBFcnJvciBsb2FkaW5nIHBlcnNvbmEgJHtmaWxlbmFtZX06ICR7ZXJyb3J9YCk7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBTYXZlIGEgcGVyc29uYSB0byBmaWxlXG4gICAqL1xuICBhc3luYyBzYXZlUGVyc29uYShwZXJzb25hOiBQZXJzb25hKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgZmlsZVBhdGggPSBwYXRoLmpvaW4odGhpcy5wZXJzb25hc0RpciwgcGVyc29uYS5maWxlbmFtZSk7XG4gICAgXG4gICAgLy8gVXNlIHNlY3VyZSBZQU1MIHN0cmluZ2lmaWNhdGlvblxuICAgIGNvbnN0IHNlY3VyZVBhcnNlciA9IFNlY3VyZVlhbWxQYXJzZXIuY3JlYXRlU2VjdXJlTWF0dGVyUGFyc2VyKCk7XG4gICAgY29uc3QgZmlsZUNvbnRlbnQgPSBzZWN1cmVQYXJzZXIuc3RyaW5naWZ5KHBlcnNvbmEuY29udGVudCwgcGVyc29uYS5tZXRhZGF0YSk7XG4gICAgXG4gICAgYXdhaXQgZnMud3JpdGVGaWxlKGZpbGVQYXRoLCBmaWxlQ29udGVudCwgJ3V0Zi04Jyk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBEZWxldGUgYSBwZXJzb25hIGZpbGVcbiAgICovXG4gIGFzeW5jIGRlbGV0ZVBlcnNvbmEoZmlsZW5hbWU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGZpbGVQYXRoID0gcGF0aC5qb2luKHRoaXMucGVyc29uYXNEaXIsIGZpbGVuYW1lKTtcbiAgICBhd2FpdCBmcy51bmxpbmsoZmlsZVBhdGgpO1xuICB9XG4gIFxuICAvKipcbiAgICogQ2hlY2sgaWYgYSBwZXJzb25hIGZpbGUgZXhpc3RzXG4gICAqL1xuICBhc3luYyBwZXJzb25hRXhpc3RzKGZpbGVuYW1lOiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgZmlsZVBhdGggPSBwYXRoLmpvaW4odGhpcy5wZXJzb25hc0RpciwgZmlsZW5hbWUpO1xuICAgICAgYXdhaXQgZnMuYWNjZXNzKGZpbGVQYXRoKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuICBcbiAgLyoqXG4gICAqIFNldCBkZWZhdWx0IG1ldGFkYXRhIHZhbHVlc1xuICAgKi9cbiAgcHJpdmF0ZSBzZXREZWZhdWx0TWV0YWRhdGEobWV0YWRhdGE6IFBlcnNvbmFNZXRhZGF0YSk6IHZvaWQge1xuICAgIGlmICghbWV0YWRhdGEuY2F0ZWdvcnkpIG1ldGFkYXRhLmNhdGVnb3J5ID0gJ2dlbmVyYWwnO1xuICAgIGlmICghbWV0YWRhdGEuYWdlX3JhdGluZykgbWV0YWRhdGEuYWdlX3JhdGluZyA9ICdhbGwnO1xuICAgIGlmICghbWV0YWRhdGEuY29udGVudF9mbGFncykgbWV0YWRhdGEuY29udGVudF9mbGFncyA9IFtdO1xuICAgIGlmIChtZXRhZGF0YS5haV9nZW5lcmF0ZWQgPT09IHVuZGVmaW5lZCkgbWV0YWRhdGEuYWlfZ2VuZXJhdGVkID0gZmFsc2U7XG4gICAgaWYgKCFtZXRhZGF0YS5nZW5lcmF0aW9uX21ldGhvZCkgbWV0YWRhdGEuZ2VuZXJhdGlvbl9tZXRob2QgPSAnaHVtYW4nO1xuICAgIGlmICghbWV0YWRhdGEucHJpY2UpIG1ldGFkYXRhLnByaWNlID0gJ2ZyZWUnO1xuICAgIGlmICghbWV0YWRhdGEubGljZW5zZSkgbWV0YWRhdGEubGljZW5zZSA9ICdDQy1CWS1TQS00LjAnO1xuICB9XG59Il19