UNPKG

@dollhousemcp/mcp-server

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.

232 lines 36.1 kB
/** * Browse collection content from GitHub */ import { CollectionCache } from '../cache/CollectionCache.js'; import { CollectionSeeder } from './CollectionSeeder.js'; import { logger } from '../utils/logger.js'; export class CollectionBrowser { githubClient; collectionCache; baseUrl = 'https://api.github.com/repos/DollhouseMCP/collection/contents'; constructor(githubClient, collectionCache) { this.githubClient = githubClient; this.collectionCache = collectionCache || new CollectionCache(); } /** * Browse collection content by section and type * Falls back to cached data when GitHub API is not available or not authenticated * @param section - Top level section: library, showcase, or catalog * @param type - Optional content type within the library section (personas, skills, etc.) */ async browseCollection(section, type) { try { // Try GitHub API first let url = this.baseUrl; // If no section provided, show top-level sections if (!section) { const data = await this.githubClient.fetchFromGitHub(url, false); if (!Array.isArray(data)) { throw new Error('Invalid collection response. Expected directory listing.'); } // Filter to only show content directories const sections = data.filter((item) => item.type === 'dir' && ['library', 'showcase', 'catalog'].includes(item.name)); return { items: [], categories: [], sections }; } // Browse within a section url = type ? `${this.baseUrl}/${section}/${type}` : `${this.baseUrl}/${section}`; const data = await this.githubClient.fetchFromGitHub(url, false); if (!Array.isArray(data)) { throw new Error('Invalid collection response. Expected directory listing.'); } // In the library section, we have content type directories if (section === 'library' && !type) { const contentTypes = data.filter((item) => item.type === 'dir' && ['personas', 'skills', 'agents', 'prompts', 'templates', 'tools', 'ensembles', 'memories'].includes(item.name)); return { items: [], categories: contentTypes }; } // For library content types, show files directly (flat structure) const items = data.filter((item) => item.type === 'file' && item.name.endsWith('.md')); // For non-library sections, they might still have subdirectories const categories = section === 'library' ? [] : data.filter((item) => item.type === 'dir'); return { items, categories }; } catch (error) { logger.debug(`GitHub API browse failed, falling back to cache: ${error}`); // Fallback to cached data return this.browseFromCache(section, type); } } /** * Browse collection from cached data */ async browseFromCache(section, type) { try { // If no section provided, show available sections from seed data if (!section) { const sections = [ { name: 'library', type: 'dir' } ]; return { items: [], categories: [], sections }; } // Get cached or seed data let cachedItems = await this.collectionCache.loadCache(); if (!cachedItems || cachedItems.items.length === 0) { // Use seed data if cache is empty const seedData = CollectionSeeder.getSeedData(); await this.collectionCache.saveCache(seedData); cachedItems = { items: seedData, timestamp: Date.now() }; logger.debug('Using seed data for collection browsing'); } // In the library section, we have content type directories if (section === 'library' && !type) { const contentTypes = this.getContentTypesFromItems(cachedItems.items); return { items: [], categories: contentTypes }; } // Get items for specific type or all items in section const items = this.filterItemsBySection(cachedItems.items, section, type); const formattedItems = this.convertCacheItemsToGitHubFormat(items); return { items: formattedItems, categories: [] }; } catch (error) { logger.error(`Cache browse failed: ${error}`); // Last resort: use seed data directly return this.browseFromSeedData(section, type); } } /** * Browse collection from seed data as last resort */ browseFromSeedData(section, type) { if (!section) { const sections = [{ name: 'library', type: 'dir' }]; return { items: [], categories: [], sections }; } const seedData = CollectionSeeder.getSeedData(); if (section === 'library' && !type) { const contentTypes = this.getContentTypesFromItems(seedData); return { items: [], categories: contentTypes }; } const items = this.filterItemsBySection(seedData, section, type); const formattedItems = this.convertCacheItemsToGitHubFormat(items); return { items: formattedItems, categories: [] }; } /** * Get unique content types from items */ getContentTypesFromItems(items) { const types = new Set(); items.forEach(item => { const pathParts = item.path.split('/'); if (pathParts.length >= 2 && pathParts[0] === 'library') { types.add(pathParts[1]); } }); return Array.from(types).map(type => ({ name: type, type: 'dir' })); } /** * Filter items by section and type */ filterItemsBySection(items, section, type) { return items.filter(item => { const pathParts = item.path.split('/'); if (pathParts[0] !== section) { return false; } if (type && pathParts[1] !== type) { return false; } return true; }); } /** * Convert cache items to GitHub API format */ convertCacheItemsToGitHubFormat(items) { return items.map(item => ({ name: item.name, path: item.path, sha: item.sha, type: 'file', url: `https://api.github.com/repos/DollhouseMCP/collection/contents/${item.path}`, html_url: `https://github.com/DollhouseMCP/collection/blob/main/${item.path}` })); } /** * Format collection browse results */ formatBrowseResults(items, categories, section, type, personaIndicator = '') { const textParts = [`${personaIndicator}🏪 **DollhouseMCP Collection**\n\n`]; // Show top-level sections if no section specified if (!section && categories.length > 0) { textParts.push(`**📚 Collection Sections (${categories.length}):**\n`); categories.forEach((sec) => { const sectionIcons = { 'library': '📖', 'showcase': '⭐', 'catalog': '💎' }; const icon = sectionIcons[sec.name] || '📁'; const descriptions = { 'library': 'Free community content', 'showcase': 'Featured high-quality content', 'catalog': 'Premium content (coming soon)' }; textParts.push(` ${icon} **${sec.name}** - ${descriptions[sec.name] || 'Content collection'}\n`, ` Browse: \`browse_collection "${sec.name}"\`\n\n`); }); return textParts.join(''); } // Show content types within library section if (section === 'library' && !type && categories.length > 0) { textParts.push(`**📖 Library Content Types (${categories.length}):**\n`); categories.forEach((cat) => { const typeIcons = { 'personas': '🎭', 'skills': '🛠️', 'agents': '🤖', 'prompts': '💬', 'templates': '📄', 'tools': '🔧', 'ensembles': '🎼', 'memories': '🧠' }; const icon = typeIcons[cat.name] || '📁'; textParts.push(` ${icon} **${cat.name}** - Browse: \`browse_collection "library" "${cat.name}"\`\n`); }); textParts.push('\n'); } else if (categories.length > 0) { // Only show category navigation for non-library sections (showcase, catalog) textParts.push(`**📁 Subdirectories in ${section}${type ? `/${type}` : ''} (${categories.length}):**\n`); categories.forEach((cat) => { const browsePath = type ? `"${section}" "${type}/${cat.name}"` : `"${section}" "${cat.name}"`; textParts.push(` 📂 **${cat.name}** - Browse: \`browse_collection ${browsePath}\`\n`); }); textParts.push('\n'); } if (items.length > 0) { const contentType = type || 'content'; const contentIcons = { 'personas': '🎭', 'skills': '🛠️', 'agents': '🤖', 'prompts': '💬', 'templates': '📄', 'tools': '🔧', 'ensembles': '🎼', 'memories': '🧠' }; const icon = contentIcons[contentType] || '📄'; textParts.push(`**${icon} ${contentType.charAt(0).toUpperCase() + contentType.slice(1)} in ${section}${type ? `/${type}` : ''} (${items.length}):**\n`); items.forEach((item) => { const fullPath = section + (type ? `/${type}` : '') + `/${item.name}`; textParts.push(` ▫️ **${item.name.replace('.md', '')}**\n`, ` 📥 Install: \`install_content "${fullPath}"\`\n`, ` 👁️ Details: \`get_collection_content "${fullPath}"\`\n\n`); }); } return textParts.join(''); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29sbGVjdGlvbkJyb3dzZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29sbGVjdGlvbi9Db2xsZWN0aW9uQnJvd3Nlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUdILE9BQU8sRUFBRSxlQUFlLEVBQWtCLE1BQU0sNkJBQTZCLENBQUM7QUFDOUUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDekQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRTVDLE1BQU0sT0FBTyxpQkFBaUI7SUFDcEIsWUFBWSxDQUFlO0lBQzNCLGVBQWUsQ0FBa0I7SUFDakMsT0FBTyxHQUFHLCtEQUErRCxDQUFDO0lBRWxGLFlBQVksWUFBMEIsRUFBRSxlQUFpQztRQUN2RSxJQUFJLENBQUMsWUFBWSxHQUFHLFlBQVksQ0FBQztRQUNqQyxJQUFJLENBQUMsZUFBZSxHQUFHLGVBQWUsSUFBSSxJQUFJLGVBQWUsRUFBRSxDQUFDO0lBQ2xFLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFnQixFQUFFLElBQWE7UUFDcEQsSUFBSSxDQUFDO1lBQ0gsdUJBQXVCO1lBQ3ZCLElBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUM7WUFFdkIsa0RBQWtEO1lBQ2xELElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDYixNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsZUFBZSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztnQkFDakUsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztvQkFDekIsTUFBTSxJQUFJLEtBQUssQ0FBQywwREFBMEQsQ0FBQyxDQUFDO2dCQUM5RSxDQUFDO2dCQUVELDBDQUEwQztnQkFDMUMsTUFBTSxRQUFRLEdBQUcsSUFBSSxD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QUM7WUFDeEosS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQVMsRUFBRSxFQUFFO2dCQUMxQixNQUFNLFFBQVEsR0FBRyxPQUFPLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUN0RSxTQUFTLENBQUMsSUFBSSxDQUNaLFdBQVcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxNQUFNLEVBQzdDLHdDQUF3QyxRQUFRLE9BQU8sRUFDdkQsZ0RBQWdELFFBQVEsU0FBUyxDQUNsRSxDQUFDO1lBQ0osQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsT0FBTyxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzVCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQnJvd3NlIGNvbGxlY3Rpb24gY29udGVudCBmcm9tIEdpdEh1YlxuICovXG5cbmltcG9ydCB7IEdpdEh1YkNsaWVudCB9IGZyb20gJy4vR2l0SHViQ2xpZW50LmpzJztcbmltcG9ydCB7IENvbGxlY3Rpb25DYWNoZSwgQ29sbGVjdGlvbkl0ZW0gfSBmcm9tICcuLi9jYWNoZS9Db2xsZWN0aW9uQ2FjaGUuanMnO1xuaW1wb3J0IHsgQ29sbGVjdGlvblNlZWRlciB9IGZyb20gJy4vQ29sbGVjdGlvblNlZWRlci5qcyc7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi91dGlscy9sb2dnZXIuanMnO1xuXG5leHBvcnQgY2xhc3MgQ29sbGVjdGlvbkJyb3dzZXIge1xuICBwcml2YXRlIGdpdGh1YkNsaWVudDogR2l0SHViQ2xpZW50O1xuICBwcml2YXRlIGNvbGxlY3Rpb25DYWNoZTogQ29sbGVjdGlvbkNhY2hlO1xuICBwcml2YXRlIGJhc2VVcmwgPSAnaHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS9yZXBvcy9Eb2xsaG91c2VNQ1AvY29sbGVjdGlvbi9jb250ZW50cyc7XG4gIFxuICBjb25zdHJ1Y3RvcihnaXRodWJDbGllbnQ6IEdpdEh1YkNsaWVudCwgY29sbGVjdGlvbkNhY2hlPzogQ29sbGVjdGlvbkNhY2hlKSB7XG4gICAgdGhpcy5naXRodWJDbGllbnQgPSBnaXRodWJDbGllbnQ7XG4gICAgdGhpcy5jb2xsZWN0aW9uQ2FjaGUgPSBjb2xsZWN0aW9uQ2FjaGUgfHwgbmV3IENvbGxlY3Rpb25DYWNoZSgpO1xuICB9XG4gIFxuICAvKipcbiAgICogQnJvd3NlIGNvbGxlY3Rpb24gY29udGVudCBieSBzZWN0aW9uIGFuZCB0eXBlXG4gICAqIEZhbGxzIGJhY2sgdG8gY2FjaGVkIGRhdGEgd2hlbiBHaXRIdWIgQVBJIGlzIG5vdCBhdmFpbGFibGUgb3Igbm90IGF1dGhlbnRpY2F0ZWRcbiAgICogQHBhcmFtIHNlY3Rpb24gLSBUb3AgbGV2ZWwgc2VjdGlvbjogbGlicmFyeSwgc2hvd2Nhc2UsIG9yIGNhdGFsb2dcbiAgICogQHBhcmFtIHR5cGUgLSBPcHRpb25hbCBjb250ZW50IHR5cGUgd2l0aGluIHRoZSBsaWJyYXJ5IHNlY3Rpb24gKHBlcnNvbmFzLCBza2lsbHMsIGV0Yy4pXG4gICAqL1xuICBhc3luYyBicm93c2VDb2xsZWN0aW9uKHNlY3Rpb24/OiBzdHJpbmcsIHR5cGU/OiBzdHJpbmcpOiBQcm9taXNlPHsgaXRlbXM6IGFueVtdLCBjYXRlZ29yaWVzOiBhbnlbXSwgc2VjdGlvbnM/OiBhbnlbXSB9PiB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIFRyeSBHaXRIdWIgQVBJIGZpcnN0XG4gICAgICBsZXQgdXJsID0gdGhpcy5iYXNlVXJsO1xuICAgICAgXG4gICAgICAvLyBJZiBubyBzZWN0aW9uIHByb3ZpZGVkLCBzaG93IHRvcC1sZXZlbCBzZWN0aW9uc1xuICAgICAgaWYgKCFzZWN0aW9uKSB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCB0aGlzLmdpdGh1YkNsaWVudC5mZXRjaEZyb21HaXRIdWIodXJsLCBmYWxzZSk7XG4gICAgICAgIGlmICghQXJyYXkuaXNBcnJheShkYXRhKSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBjb2xsZWN0aW9uIHJlc3BvbnNlLiBFeHBlY3RlZCBkaXJlY3RvcnkgbGlzdGluZy4nKTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgLy8gRmlsdGVyIHRvIG9ubHkgc2hvdyBjb250ZW50IGRpcmVjdG9yaWVzXG4gICAgICAgIGNvbnN0IHNlY3Rpb25zID0gZGF0YS5maWx0ZXIoKGl0ZW06IGFueSkgPT4gXG4gICAgICAgICAgaXRlbS50eXBlID09PSAnZGlyJyAmJiBbJ2xpYnJhcnknLCAnc2hvd2Nhc2UnLCAnY2F0YWxvZyddLmluY2x1ZGVzKGl0ZW0ubmFtZSlcbiAgICAgICAgKTtcbiAgICAgICAgXG4gICAgICAgIHJldHVybiB7IGl0ZW1zOiBbXSwgY2F0ZWdvcmllczogW10sIHNlY3Rpb25zIH07XG4gICAgICB9XG4gICAgICBcbiAgICAgIC8vIEJyb3dzZSB3aXRoaW4gYSBzZWN0aW9uXG4gICAgICB1cmwgPSB0eXBlIFxuICAgICAgICA/IGAke3RoaXMuYmFzZVVybH0vJHtzZWN0aW9ufS8ke3R5cGV9YCBcbiAgICAgICAgOiBgJHt0aGlzLmJhc2VVcmx9LyR7c2VjdGlvbn1gO1xuICAgICAgXG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgdGhpcy5naXRodWJDbGllbnQuZmV0Y2hGcm9tR2l0SHViKHVybCwgZmFsc2UpO1xuICAgICAgXG4gICAgICBpZiAoIUFycmF5LmlzQXJyYXkoZGF0YSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGNvbGxlY3Rpb24gcmVzcG9uc2UuIEV4cGVjdGVkIGRpcmVjdG9yeSBsaXN0aW5nLicpO1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBJbiB0aGUgbGlicmFyeSBzZWN0aW9uLCB3ZSBoYXZlIGNvbnRlbnQgdHlwZSBkaXJlY3Rvcmllc1xuICAgICAgaWYgKHNlY3Rpb24gPT09ICdsaWJyYXJ5JyAmJiAhdHlwZSkge1xuICAgICAgICBjb25zdCBjb250ZW50VHlwZXMgPSBkYXRhLmZpbHRlcigoaXRlbTogYW55KSA9PiBcbiAgICAgICAgICBpdGVtLnR5cGUgPT09ICdkaXInICYmIFsncGVyc29uYXMnLCAnc2tpbGxzJywgJ2FnZW50cycsICdwcm9tcHRzJywgJ3RlbXBsYXRlcycsICd0b29scycsICdlbnNlbWJsZXMnLCAnbWVtb3JpZXMnXS5pbmNsdWRlcyhpdGVtLm5hbWUpXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiB7IGl0ZW1zOiBbXSwgY2F0ZWdvcmllczogY29udGVudFR5cGVzIH07XG4gICAgICB9XG4gICAgICBcbiAgICAgIC8vIEZvciBsaWJyYXJ5IGNvbnRlbnQgdHlwZXMsIHNob3cgZmlsZXMgZGlyZWN0bHkgKGZsYXQgc3RydWN0dXJlKVxuICAgICAgY29uc3QgaXRlbXMgPSBkYXRhLmZpbHRlcigoaXRlbTogYW55KSA9PiBpdGVtLnR5cGUgPT09ICdmaWxlJyAmJiBpdGVtLm5hbWUuZW5kc1dpdGgoJy5tZCcpKTtcbiAgICAgIC8vIEZvciBub24tbGlicmFyeSBzZWN0aW9ucywgdGhleSBtaWdodCBzdGlsbCBoYXZlIHN1YmRpcmVjdG9yaWVzXG4gICAgICBjb25zdCBjYXRlZ29yaWVzID0gc2VjdGlvbiA9PT0gJ2xpYnJhcnknID8gW10gOiBkYXRhLmZpbHRlcigoaXRlbTogYW55KSA9PiBpdGVtLnR5cGUgPT09ICdkaXInKTtcbiAgICAgIFxuICAgICAgcmV0dXJuIHsgaXRlbXMsIGNhdGVnb3JpZXMgfTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgbG9nZ2VyLmRlYnVnKGBHaXRIdWIgQVBJIGJyb3dzZSBmYWlsZWQsIGZhbGxpbmcgYmFjayB0byBjYWNoZTogJHtlcnJvcn1gKTtcbiAgICAgIFxuICAgICAgLy8gRmFsbGJhY2sgdG8gY2FjaGVkIGRhdGFcbiAgICAgIHJldHVybiB0aGlzLmJyb3dzZUZyb21DYWNoZShzZWN0aW9uLCB0eXBlKTtcbiAgICB9XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBCcm93c2UgY29sbGVjdGlvbiBmcm9tIGNhY2hlZCBkYXRhXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGJyb3dzZUZyb21DYWNoZShzZWN0aW9uPzogc3RyaW5nLCB0eXBlPzogc3RyaW5nKTogUHJvbWlzZTx7IGl0ZW1zOiBhbnlbXSwgY2F0ZWdvcmllczogYW55W10sIHNlY3Rpb25zPzogYW55W10gfT4ge1xuICAgIHRyeSB7XG4gICAgICAvLyBJZiBubyBzZWN0aW9uIHByb3ZpZGVkLCBzaG93IGF2YWlsYWJsZSBzZWN0aW9ucyBmcm9tIHNlZWQgZGF0YVxuICAgICAgaWYgKCFzZWN0aW9uKSB7XG4gICAgICAgIGNvbnN0IHNlY3Rpb25zID0gW1xuICAgICAgICAgIHsgbmFtZTogJ2xpYnJhcnknLCB0eXBlOiAnZGlyJyB9XG4gICAgICAgIF07XG4gICAgICAgIHJldHVybiB7IGl0ZW1zOiBbXSwgY2F0ZWdvcmllczogW10sIHNlY3Rpb25zIH07XG4gICAgICB9XG4gICAgICBcbiAgICAgIC8vIEdldCBjYWNoZWQgb3Igc2VlZCBkYXRhXG4gICAgICBsZXQgY2FjaGVkSXRlbXMgPSBhd2FpdCB0aGlzLmNvbGxlY3Rpb25DYWNoZS5sb2FkQ2FjaGUoKTtcbiAgICAgIFxuICAgICAgaWYgKCFjYWNoZWRJdGVtcyB8fCBjYWNoZWRJdGVtcy5pdGVtcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgLy8gVXNlIHNlZWQgZGF0YSBpZiBjYWNoZSBpcyBlbXB0eVxuICAgICAgICBjb25zdCBzZWVkRGF0YSA9IENvbGxlY3Rpb25TZWVkZXIuZ2V0U2VlZERhdGEoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5jb2xsZWN0aW9uQ2FjaGUuc2F2ZUNhY2hlKHNlZWREYXRhKTtcbiAgICAgICAgY2FjaGVkSXRlbXMgPSB7IGl0ZW1zOiBzZWVkRGF0YSwgdGltZXN0YW1wOiBEYXRlLm5vdygpIH07XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnVXNpbmcgc2VlZCBkYXRhIGZvciBjb2xsZWN0aW9uIGJyb3dzaW5nJyk7XG4gICAgICB9XG4gICAgICBcbiAgICAgIC8vIEluIHRoZSBsaWJyYXJ5IHNlY3Rpb24sIHdlIGhhdmUgY29udGVudCB0eXBlIGRpcmVjdG9yaWVzXG4gICAgICBpZiAoc2VjdGlvbiA9PT0gJ2xpYnJhcnknICYmICF0eXBlKSB7XG4gICAgICAgIGNvbnN0IGNvbnRlbnRUeXBlcyA9IHRoaXMuZ2V0Q29udGVudFR5cGVzRnJvbUl0ZW1zKGNhY2hlZEl0ZW1zLml0ZW1zKTtcbiAgICAgICAgcmV0dXJuIHsgaXRlbXM6IFtdLCBjYXRlZ29yaWVzOiBjb250ZW50VHlwZXMgfTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgLy8gR2V0IGl0ZW1zIGZvciBzcGVjaWZpYyB0eXBlIG9yIGFsbCBpdGVtcyBpbiBzZWN0aW9uXG4gICAgICBjb25zdCBpdGVtcyA9IHRoaXMuZmlsdGVySXRlbXNCeVNlY3Rpb24oY2FjaGVkSXRlbXMuaXRlbXMsIHNlY3Rpb24sIHR5cGUpO1xuICAgICAgY29uc3QgZm9ybWF0dGVkSXRlbXMgPSB0aGlzLmNvbnZlcnRDYWNoZUl0ZW1zVG9HaXRIdWJGb3JtYXQoaXRlbXMpO1xuICAgICAgXG4gICAgICByZXR1cm4geyBpdGVtczogZm9ybWF0dGVkSXRlbXMsIGNhdGVnb3JpZXM6IFtdIH07XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci5lcnJvcihgQ2FjaGUgYnJvd3NlIGZhaWxlZDogJHtlcnJvcn1gKTtcbiAgICAgIFxuICAgICAgLy8gTGFzdCByZXNvcnQ6IHVzZSBzZWVkIGRhdGEgZGlyZWN0bHlcbiAgICAgIHJldHVybiB0aGlzLmJyb3dzZUZyb21TZWVkRGF0YShzZWN0aW9uLCB0eXBlKTtcbiAgICB9XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBCcm93c2UgY29sbGVjdGlvbiBmcm9tIHNlZWQgZGF0YSBhcyBsYXN0IHJlc29ydFxuICAgKi9cbiAgcHJpdmF0ZSBicm93c2VGcm9tU2VlZERhdGEoc2VjdGlvbj86IHN0cmluZywgdHlwZT86IHN0cmluZyk6IHsgaXRlbXM6IGFueVtdLCBjYXRlZ29yaWVzOiBhbnlbXSwgc2VjdGlvbnM/OiBhbnlbXSB9IHtcbiAgICBpZiAoIXNlY3Rpb24pIHtcbiAgICAgIGNvbnN0IHNlY3Rpb25zID0gW3sgbmFtZTogJ2xpYnJhcnknLCB0eXBlOiAnZGlyJyB9XTtcbiAgICAgIHJldHVybiB7IGl0ZW1zOiBbXSwgY2F0ZWdvcmllczogW10sIHNlY3Rpb25zIH07XG4gICAgfVxuICAgIFxuICAgIGNvbnN0IHNlZWREYXRhID0gQ29sbGVjdGlvblNlZWRlci5nZXRTZWVkRGF0YSgpO1xuICAgIFxuICAgIGlmIChzZWN0aW9uID09PSAnbGlicmFyeScgJiYgIXR5cGUpIHtcbiAgICAgIGNvbnN0IGNvbnRlbnRUeXBlcyA9IHRoaXMuZ2V0Q29udGVudFR5cGVzRnJvbUl0ZW1zKHNlZWREYXRhKTtcbiAgICAgIHJldHVybiB7IGl0ZW1zOiBbXSwgY2F0ZWdvcmllczogY29udGVudFR5cGVzIH07XG4gICAgfVxuICAgIFxuICAgIGNvbnN0IGl0ZW1zID0gdGhpcy5maWx0ZXJJdGVtc0J5U2VjdGlvbihzZWVkRGF0YSwgc2VjdGlvbiwgdHlwZSk7XG4gICAgY29uc3QgZm9ybWF0dGVkSXRlbXMgPSB0aGlzLmNvbnZlcnRDYWNoZUl0ZW1zVG9HaXRIdWJGb3JtYXQoaXRlbXMpO1xuICAgIFxuICAgIHJldHVybiB7IGl0ZW1zOiBmb3JtYXR0ZWRJdGVtcywgY2F0ZWdvcmllczogW10gfTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIEdldCB1bmlxdWUgY29udGVudCB0eXBlcyBmcm9tIGl0ZW1zXG4gICAqL1xuICBwcml2YXRlIGdldENvbnRlbnRUeXBlc0Zyb21JdGVtcyhpdGVtczogQ29sbGVjdGlvbkl0ZW1bXSk6IGFueVtdIHtcbiAgICBjb25zdCB0eXBlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgIFxuICAgIGl0ZW1zLmZvckVhY2goaXRlbSA9PiB7XG4gICAgICBjb25zdCBwYXRoUGFydHMgPSBpdGVtLnBhdGguc3BsaXQoJy8nKTtcbiAgICAgIGlmIChwYXRoUGFydHMubGVuZ3RoID49IDIgJiYgcGF0aFBhcnRzWzBdID09PSAnbGlicmFyeScpIHtcbiAgICAgICAgdHlwZXMuYWRkKHBhdGhQYXJ0c1sxXSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgXG4gICAgcmV0dXJuIEFycmF5LmZyb20odHlwZXMpLm1hcCh0eXBlID0+ICh7XG4gICAgICBuYW1lOiB0eXBlLFxuICAgICAgdHlwZTogJ2RpcidcbiAgICB9KSk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBGaWx0ZXIgaXRlbXMgYnkgc2VjdGlvbiBhbmQgdHlwZVxuICAgKi9cbiAgcHJpdmF0ZSBmaWx0ZXJJdGVtc0J5U2VjdGlvbihpdGVtczogQ29sbGVjdGlvbkl0ZW1bXSwgc2VjdGlvbjogc3RyaW5nLCB0eXBlPzogc3RyaW5nKTogQ29sbGVjdGlvbkl0ZW1bXSB7XG4gICAgcmV0dXJuIGl0ZW1zLmZpbHRlcihpdGVtID0+IHtcbiAgICAgIGNvbnN0IHBhdGhQYXJ0cyA9IGl0ZW0ucGF0aC5zcGxpdCgnLycpO1xuICAgICAgXG4gICAgICBpZiAocGF0aFBhcnRzWzBdICE9PSBzZWN0aW9uKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgaWYgKHR5cGUgJiYgcGF0aFBhcnRzWzFdICE9PSB0eXBlKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBDb252ZXJ0IGNhY2hlIGl0ZW1zIHRvIEdpdEh1YiBBUEkgZm9ybWF0XG4gICAqL1xuICBwcml2YXRlIGNvbnZlcnRDYWNoZUl0ZW1zVG9HaXRIdWJGb3JtYXQoaXRlbXM6IENvbGxlY3Rpb25JdGVtW10pOiBhbnlbXSB7XG4gICAgcmV0dXJuIGl0ZW1zLm1hcChpdGVtID0+ICh7XG4gICAgICBuYW1lOiBpdGVtLm5hbWUsXG4gICAgICBwYXRoOiBpdGVtLnBhdGgsXG4gICAgICBzaGE6IGl0ZW0uc2hhLFxuICAgICAgdHlwZTogJ2ZpbGUnLFxuICAgICAgdXJsOiBgaHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS9yZXBvcy9Eb2xsaG91c2VNQ1AvY29sbGVjdGlvbi9jb250ZW50cy8ke2l0ZW0ucGF0aH1gLFxuICAgICAgaHRtbF91cmw6IGBodHRwczovL2dpdGh1Yi5jb20vRG9sbGhvdXNlTUNQL2NvbGxlY3Rpb24vYmxvYi9tYWluLyR7aXRlbS5wYXRofWBcbiAgICB9KSk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBGb3JtYXQgY29sbGVjdGlvbiBicm93c2UgcmVzdWx0c1xuICAgKi9cbiAgZm9ybWF0QnJvd3NlUmVzdWx0cyhpdGVtczogYW55W10sIGNhdGVnb3JpZXM6IGFueVtdLCBzZWN0aW9uPzogc3RyaW5nLCB0eXBlPzogc3RyaW5nLCBwZXJzb25hSW5kaWNhdG9yOiBzdHJpbmcgPSAnJyk6IHN0cmluZyB7XG4gICAgY29uc3QgdGV4dFBhcnRzID0gW2Ake3BlcnNvbmFJbmRpY2F0b3J98J+PqiAqKkRvbGxob3VzZU1DUCBDb2xsZWN0aW9uKipcXG5cXG5gXTtcbiAgICBcbiAgICAvLyBTaG93IHRvcC1sZXZlbCBzZWN0aW9ucyBpZiBubyBzZWN0aW9uIHNwZWNpZmllZFxuICAgIGlmICghc2VjdGlvbiAmJiBjYXRlZ29yaWVzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRleHRQYXJ0cy5wdXNoKGAqKvCfk5ogQ29sbGVjdGlvbiBTZWN0aW9ucyAoJHtjYXRlZ29yaWVzLmxlbmd0aH0pOioqXFxuYCk7XG4gICAgICBjYXRlZ29yaWVzLmZvckVhY2goKHNlYzogYW55KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlY3Rpb25JY29uczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHtcbiAgICAgICAgICAnbGlicmFyeSc6ICfwn5OWJyxcbiAgICAgICAgICAnc2hvd2Nhc2UnOiAn4q2QJyxcbiAgICAgICAgICAnY2F0YWxvZyc6ICfwn5KOJ1xuICAgICAgICB9O1xuICAgICAgICBjb25zdCBpY29uID0gc2VjdGlvbkljb25zW3NlYy5uYW1lXSB8fCAn8J+TgSc7XG4gICAgICAgIGNvbnN0IGRlc2NyaXB0aW9uczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHtcbiAgICAgICAgICAnbGlicmFyeSc6ICdGcmVlIGNvbW11bml0eSBjb250ZW50JyxcbiAgICAgICAgICAnc2hvd2Nhc2UnOiAnRmVhdHVyZWQgaGlnaC1xdWFsaXR5IGNvbnRlbnQnLFxuICAgICAgICAgICdjYXRhbG9nJzogJ1ByZW1pdW0gY29udGVudCAoY29taW5nIHNvb24pJ1xuICAgICAgICB9O1xuICAgICAgICB0ZXh0UGFydHMucHVzaChcbiAgICAgICAgICBgICAgJHtpY29ufSAqKiR7c2VjLm5hbWV9KiogLSAke2Rlc2NyaXB0aW9uc1tzZWMubmFtZV0gfHwgJ0NvbnRlbnQgY29sbGVjdGlvbid9XFxuYCxcbiAgICAgICAgICBgICAgICAgQnJvd3NlOiBcXGBicm93c2VfY29sbGVjdGlvbiBcIiR7c2VjLm5hbWV9XCJcXGBcXG5cXG5gXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiB0ZXh0UGFydHMuam9pbignJyk7XG4gICAgfVxuICAgIFxuICAgIC8vIFNob3cgY29udGVudCB0eXBlcyB3aXRoaW4gbGlicmFyeSBzZWN0aW9uXG4gICAgaWYgKHNlY3Rpb24gPT09ICdsaWJyYXJ5JyAmJiAhdHlwZSAmJiBjYXRlZ29yaWVzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRleHRQYXJ0cy5wdXNoKGAqKvCfk5YgTGlicmFyeSBDb250ZW50IFR5cGVzICgke2NhdGVnb3JpZXMubGVuZ3RofSk6KipcXG5gKTtcbiAgICAgIGNhdGVnb3JpZXMuZm9yRWFjaCgoY2F0OiBhbnkpID0+IHtcbiAgICAgICAgY29uc3QgdHlwZUljb25zOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge1xuICAgICAgICAgICdwZXJzb25hcyc6ICfwn46tJyxcbiAgICAgICAgICAnc2tpbGxzJzogJ/Cfm6DvuI8nLFxuICAgICAgICAgICdhZ2VudHMnOiAn8J+klicsXG4gICAgICAgICAgJ3Byb21wdHMnOiAn8J+SrCcsXG4gICAgICAgICAgJ3RlbXBsYXRlcyc6ICfwn5OEJyxcbiAgICAgICAgICAndG9vbHMnOiAn8J+UpycsXG4gICAgICAgICAgJ2Vuc2VtYmxlcyc6ICfwn468JyxcbiAgICAgICAgICAnbWVtb3JpZXMnOiAn8J+noCdcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgaWNvbiA9IHR5cGVJY29uc1tjYXQubmFtZV0gfHwgJ/Cfk4EnO1xuICAgICAgICB0ZXh0UGFydHMucHVzaChgICAgJHtpY29ufSAqKiR7Y2F0Lm5hbWV9KiogLSBCcm93c2U6IFxcYGJyb3dzZV9jb2xsZWN0aW9uIFwibGlicmFyeVwiIFwiJHtjYXQubmFtZX1cIlxcYFxcbmApO1xuICAgICAgfSk7XG4gICAgICB0ZXh0UGFydHMucHVzaCgnXFxuJyk7XG4gICAgfSBlbHNlIGlmIChjYXRlZ29yaWVzLmxlbmd0aCA+IDApIHtcbiAgICAgIC8vIE9ubHkgc2hvdyBjYXRlZ29yeSBuYXZpZ2F0aW9uIGZvciBub24tbGlicmFyeSBzZWN0aW9ucyAoc2hvd2Nhc2UsIGNhdGFsb2cpXG4gICAgICB0ZXh0UGFydHMucHVzaChgKirwn5OBIFN1YmRpcmVjdG9yaWVzIGluICR7c2VjdGlvbn0ke3R5cGUgPyBgLyR7dHlwZX1gIDogJyd9ICgke2NhdGVnb3JpZXMubGVuZ3RofSk6KipcXG5gKTtcbiAgICAgIGNhdGVnb3JpZXMuZm9yRWFjaCgoY2F0OiBhbnkpID0+IHtcbiAgICAgICAgY29uc3QgYnJvd3NlUGF0aCA9IHR5cGUgPyBgXCIke3NlY3Rpb259XCIgXCIke3R5cGV9LyR7Y2F0Lm5hbWV9XCJgIDogYFwiJHtzZWN0aW9ufVwiIFwiJHtjYXQubmFtZX1cImA7XG4gICAgICAgIHRleHRQYXJ0cy5wdXNoKGAgICDwn5OCICoqJHtjYXQubmFtZX0qKiAtIEJyb3dzZTogXFxgYnJvd3NlX2NvbGxlY3Rpb24gJHticm93c2VQYXRofVxcYFxcbmApO1xuICAgICAgfSk7XG4gICAgICB0ZXh0UGFydHMucHVzaCgnXFxuJyk7XG4gICAgfVxuICAgIFxuICAgIGlmIChpdGVtcy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCBjb250ZW50VHlwZSA9IHR5cGUgfHwgJ2NvbnRlbnQnO1xuICAgICAgY29uc3QgY29udGVudEljb25zOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge1xuICAgICAgICAncGVyc29uYXMnOiAn8J+OrScsXG4gICAgICAgICdza2lsbHMnOiAn8J+boO+4jycsXG4gICAgICAgICdhZ2VudHMnOiAn8J+klicsXG4gICAgICAgICdwcm9tcHRzJzogJ/CfkqwnLFxuICAgICAgICAndGVtcGxhdGVzJzogJ/Cfk4QnLFxuICAgICAgICAndG9vbHMnOiAn8J+UpycsXG4gICAgICAgICdlbnNlbWJsZXMnOiAn8J+OvCcsXG4gICAgICAgICdtZW1vcmllcyc6ICfwn6egJ1xuICAgICAgfTtcbiAgICAgIGNvbnN0IGljb24gPSBjb250ZW50SWNvbnNbY29udGVudFR5cGVdIHx8ICfwn5OEJztcbiAgICAgIFxuICAgICAgdGV4dFBhcnRzLnB1c2goYCoqJHtpY29ufSAke2NvbnRlbnRUeXBlLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgY29udGVudFR5cGUuc2xpY2UoMSl9IGluICR7c2VjdGlvbn0ke3R5cGUgPyBgLyR7dHlwZX1gIDogJyd9ICgke2l0ZW1zLmxlbmd0aH0pOioqXFxuYCk7XG4gICAgICBpdGVtcy5mb3JFYWNoKChpdGVtOiBhbnkpID0+IHtcbiAgICAgICAgY29uc3QgZnVsbFBhdGggPSBzZWN0aW9uICsgKHR5cGUgPyBgLyR7dHlwZX1gIDogJycpICsgYC8ke2l0ZW0ubmFtZX1gO1xuICAgICAgICB0ZXh0UGFydHMucHVzaChcbiAgICAgICAgICBgICAg4par77iPICoqJHtpdGVtLm5hbWUucmVwbGFjZSgnLm1kJywgJycpfSoqXFxuYCxcbiAgICAgICAgICBgICAgICAg8J+TpSBJbnN0YWxsOiBcXGBpbnN0YWxsX2NvbnRlbnQgXCIke2Z1bGxQYXRofVwiXFxgXFxuYCxcbiAgICAgICAgICBgICAgICAg8J+Rge+4jyBEZXRhaWxzOiBcXGBnZXRfY29sbGVjdGlvbl9jb250ZW50IFwiJHtmdWxsUGF0aH1cIlxcYFxcblxcbmBcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICBcbiAgICByZXR1cm4gdGV4dFBhcnRzLmpvaW4oJycpO1xuICB9XG59Il19