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.

354 lines 53.4 kB
/** * Browse collection content from GitHub */ import { CollectionSeeder } from './CollectionSeeder.js'; import { logger } from '../utils/logger.js'; import { ElementType } from '../portfolio/types.js'; // Content types supported by MCP server // Now includes memories (IP concerns resolved) // ⚠️ CRITICAL: When adding new element types, you MUST update this array! // Also update validTypes array in src/index.ts // See docs/developer-guide/ADDING_NEW_ELEMENT_TYPES_CHECKLIST.md for complete guide const MCP_SUPPORTED_TYPES = [ ElementType.PERSONA, // personas - supported by PersonaTools and ElementTools ElementType.SKILL, // skills - supported by ElementTools ElementType.AGENT, // agents - supported by ElementTools ElementType.TEMPLATE, // templates - supported by ElementTools ElementType.MEMORY // memories - supported by ElementTools (restored) ]; /** * Type guard to safely check if a string is a valid ElementType */ function isElementType(value) { return Object.values(ElementType).includes(value); } /** * Type guard to safely check if an ElementType is supported by MCP */ function isMCPSupportedType(elementType) { return MCP_SUPPORTED_TYPES.includes(elementType); } export class CollectionBrowser { githubClient; collectionCache; indexManager; baseUrl = 'https://api.github.com/repos/DollhouseMCP/collection/contents'; constructor(githubClient, collectionCache, indexManager) { this.githubClient = githubClient; this.collectionCache = collectionCache; this.indexManager = indexManager; } /** * Browse collection content by section and type * Uses CollectionIndexManager for fast browsing with background refresh * 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 using collection index first for faster browsing const indexResult = await this.browseFromIndex(section, type); if (indexResult) { logger.debug('Used collection index for browsing'); return indexResult; } // Fallback to GitHub API 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) { // Filter to only show MCP-supported content types const contentTypes = data.filter((item) => { if (item.type !== 'dir') return false; const elementType = isElementType(item.name) ? item.name : null; return elementType && isMCPSupportedType(elementType); }); 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 using the fast collection index * Returns null if index is not available or browsing fails */ async browseFromIndex(section, type) { try { const index = await this.indexManager.getIndex(); // If no section provided, show top-level sections if (!section) { const sections = [ { name: 'library', type: 'dir' }, { name: 'showcase', type: 'dir' }, { name: 'catalog', type: 'dir' } ]; return { items: [], categories: [], sections }; } // In the library section, we have content type directories if (section === 'library' && !type) { // Get unique content types from index const contentTypes = this.getContentTypesFromIndex(index); return { items: [], categories: contentTypes }; } // Get items for specific type or all items in section const items = this.getItemsFromIndex(index, section, type); const formattedItems = this.convertIndexItemsToGitHubFormat(items); return { items: formattedItems, categories: [] }; } catch (error) { logger.debug('Failed to browse from collection index', { error: error instanceof Error ? error.message : String(error) }); return null; } } /** * Get unique content types from collection index */ getContentTypesFromIndex(index) { const types = new Set(); // Extract types from index keys and filter for MCP-supported types Object.keys(index.index).forEach(typeName => { const elementType = isElementType(typeName) ? typeName : null; if (elementType && isMCPSupportedType(elementType)) { types.add(typeName); } }); return Array.from(types).map(type => ({ name: type, type: 'dir' })); } /** * Get items from collection index by section and type */ getItemsFromIndex(index, section, type) { // For library section with type, get items from that type if (section === 'library' && type) { return index.index[type] || []; } // For library section without type, return empty (should show categories) if (section === 'library' && !type) { return []; } // For other sections (showcase, catalog), return all items that match // Note: The current index structure is primarily for library content // Future enhancement: extend index to include showcase/catalog sections return []; } /** * Convert index entries to GitHub API format for compatibility */ convertIndexItemsToGitHubFormat(items) { return items.map(item => ({ name: item.name.endsWith('.md') ? item.name : `${item.name}.md`, 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}` })); } /** * 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') { // Only include MCP-supported types in cache browsing const typeName = pathParts[1]; const elementType = isElementType(typeName) ? typeName : null; if (elementType && isMCPSupportedType(elementType)) { types.add(typeName); } } }); 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 (coming soon)', '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': '🤖', 'templates': '📄', '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': '🤖', 'templates': '📄', '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) => { // Use item.path for correct GitHub file path, item.name for display // This fixes the mismatch where browse returned "Code Review.md" but file is "code-review.md" const fullPath = item.path || (section + (type ? `/${type}` : '') + `/${item.name}`); const displayName = item.name.replace('.md', ''); textParts.push(` ▫️ **${displayName}**\n`, ` 📥 Install: \`install_collection_content "${fullPath}"\`\n`, ` 👁️ Details: \`get_collection_content "${fullPath}"\`\n\n`); }); } return textParts.join(''); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29sbGVjdGlvbkJyb3dzZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29sbGVjdGlvbi9Db2xsZWN0aW9uQnJvd3Nlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUlILE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBR3pELE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFcEQsd0NBQXdDO0FBQ3hDLCtDQUErQztBQUMvQywwRUFBMEU7QUFDMUUsK0NBQStDO0FBQy9DLG9GQUFvRjtBQUNwRixNQUFNLG1CQUFtQixHQUFHO0lBQzFCLFdBQVcsQ0FBQyxPQUFPLEVBQUssd0RBQXdEO0lBQ2hGLFdBQVcsQ0FBQyxLQUFLLEVBQU8scUNBQXFDO0lBQzdELFdBQVcsQ0FBQyxLQUFLLEVBQU8scUNBQXFDO0lBQzdELFdBQVcsQ0FBQyxRQUFRLEVBQUksd0NBQXdDO0lBQ2hFLFdBQVcsQ0FBQyxNQUFNLENBQU0sa0RBQWtEO0NBQzNFLENBQUM7QUFFRjs7R0FFRztBQUNILFNBQVMsYUFBYSxDQUFDLEtBQWE7SUFDbEMsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFvQixDQUFDLENBQUM7QUFDbkUsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUyxrQkFBa0IsQ0FBQyxXQUF3QjtJQUNsRCxPQUFPLG1CQUFtQixDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsQ0FBQztBQUNuRCxDQUFDO0FBRUQsTUFBTSxPQUFPLGlCQUFpQjtJQUNwQixZQUFZLENBQWU7SUFDM0IsZUFBZSxDQUFrQjtJQUNqQyxZQUFZLENBQXlCO0lBQ3JDLE9BQU8sR0FBRywrREFBK0QsQ0FBQztJQUVsRixZQUFZLFlBQTBCLEVBQUUsZUFBZ0MsRUFBRSxZQUFvQztR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LFNBQVMsQ0FBQyxJQUFJLENBQ1osV0FBVyxXQUFXLE1BQU0sRUFDNUIsbURBQW1ELFFBQVEsT0FBTyxFQUNsRSxnREFBZ0QsUUFBUSxTQUFTLENBQ2xFLENBQUM7WUFDSixDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCxPQUFPLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDNUIsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBCcm93c2UgY29sbGVjdGlvbiBjb250ZW50IGZyb20gR2l0SHViXG4gKi9cblxuaW1wb3J0IHsgR2l0SHViQ2xpZW50IH0gZnJvbSAnLi9HaXRIdWJDbGllbnQuanMnO1xuaW1wb3J0IHsgQ29sbGVjdGlvbkNhY2hlLCBDb2xsZWN0aW9uSXRlbSB9IGZyb20gJy4uL2NhY2hlL0NvbGxlY3Rpb25DYWNoZS5qcyc7XG5pbXBvcnQgeyBDb2xsZWN0aW9uU2VlZGVyIH0gZnJvbSAnLi9Db2xsZWN0aW9uU2VlZGVyLmpzJztcbmltcG9ydCB7IENvbGxlY3Rpb25JbmRleE1hbmFnZXIgfSBmcm9tICcuL0NvbGxlY3Rpb25JbmRleE1hbmFnZXIuanMnO1xuaW1wb3J0IHsgQ29sbGVjdGlvbkluZGV4LCBJbmRleEVudHJ5IH0gZnJvbSAnLi4vdHlwZXMvY29sbGVjdGlvbi5qcyc7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi91dGlscy9sb2dnZXIuanMnO1xuaW1wb3J0IHsgRWxlbWVudFR5cGUgfSBmcm9tICcuLi9wb3J0Zm9saW8vdHlwZXMuanMnO1xuXG4vLyBDb250ZW50IHR5cGVzIHN1cHBvcnRlZCBieSBNQ1Agc2VydmVyXG4vLyBOb3cgaW5jbHVkZXMgbWVtb3JpZXMgKElQIGNvbmNlcm5zIHJlc29sdmVkKVxuLy8g4pqg77iPIENSSVRJQ0FMOiBXaGVuIGFkZGluZyBuZXcgZWxlbWVudCB0eXBlcywgeW91IE1VU1QgdXBkYXRlIHRoaXMgYXJyYXkhXG4vLyBBbHNvIHVwZGF0ZSB2YWxpZFR5cGVzIGFycmF5IGluIHNyYy9pbmRleC50c1xuLy8gU2VlIGRvY3MvZGV2ZWxvcGVyLWd1aWRlL0FERElOR19ORVdfRUxFTUVOVF9UWVBFU19DSEVDS0xJU1QubWQgZm9yIGNvbXBsZXRlIGd1aWRlXG5jb25zdCBNQ1BfU1VQUE9SVEVEX1RZUEVTID0gW1xuICBFbGVtZW50VHlwZS5QRVJTT05BLCAgICAvLyBwZXJzb25hcyAtIHN1cHBvcnRlZCBieSBQZXJzb25hVG9vbHMgYW5kIEVsZW1lbnRUb29sc1xuICBFbGVtZW50VHlwZS5TS0lMTCwgICAgICAvLyBza2lsbHMgLSBzdXBwb3J0ZWQgYnkgRWxlbWVudFRvb2xzXG4gIEVsZW1lbnRUeXBlLkFHRU5ULCAgICAgIC8vIGFnZW50cyAtIHN1cHBvcnRlZCBieSBFbGVtZW50VG9vbHNcbiAgRWxlbWVudFR5cGUuVEVNUExBVEUsICAgLy8gdGVtcGxhdGVzIC0gc3VwcG9ydGVkIGJ5IEVsZW1lbnRUb29sc1xuICBFbGVtZW50VHlwZS5NRU1PUlkgICAgICAvLyBtZW1vcmllcyAtIHN1cHBvcnRlZCBieSBFbGVtZW50VG9vbHMgKHJlc3RvcmVkKVxuXTtcblxuLyoqXG4gKiBUeXBlIGd1YXJkIHRvIHNhZmVseSBjaGVjayBpZiBhIHN0cmluZyBpcyBhIHZhbGlkIEVsZW1lbnRUeXBlXG4gKi9cbmZ1bmN0aW9uIGlzRWxlbWVudFR5cGUodmFsdWU6IHN0cmluZyk6IHZhbHVlIGlzIEVsZW1lbnRUeXBlIHtcbiAgcmV0dXJuIE9iamVjdC52YWx1ZXMoRWxlbWVudFR5cGUpLmluY2x1ZGVzKHZhbHVlIGFzIEVsZW1lbnRUeXBlKTtcbn1cblxuLyoqXG4gKiBUeXBlIGd1YXJkIHRvIHNhZmVseSBjaGVjayBpZiBhbiBFbGVtZW50VHlwZSBpcyBzdXBwb3J0ZWQgYnkgTUNQXG4gKi9cbmZ1bmN0aW9uIGlzTUNQU3VwcG9ydGVkVHlwZShlbGVtZW50VHlwZTogRWxlbWVudFR5cGUpOiBib29sZWFuIHtcbiAgcmV0dXJuIE1DUF9TVVBQT1JURURfVFlQRVMuaW5jbHVkZXMoZWxlbWVudFR5cGUpO1xufVxuXG5leHBvcnQgY2xhc3MgQ29sbGVjdGlvbkJyb3dzZXIge1xuICBwcml2YXRlIGdpdGh1YkNsaWVudDogR2l0SHViQ2xpZW50O1xuICBwcml2YXRlIGNvbGxlY3Rpb25DYWNoZTogQ29sbGVjdGlvbkNhY2hlO1xuICBwcml2YXRlIGluZGV4TWFuYWdlcjogQ29sbGVjdGlvbkluZGV4TWFuYWdlcjtcbiAgcHJpdmF0ZSBiYXNlVXJsID0gJ2h0dHBzOi8vYXBpLmdpdGh1Yi5jb20vcmVwb3MvRG9sbGhvdXNlTUNQL2NvbGxlY3Rpb24vY29udGVudHMnO1xuICBcbiAgY29uc3RydWN0b3IoZ2l0aHViQ2xpZW50OiBHaXRIdWJDbGllbnQsIGNvbGxlY3Rpb25DYWNoZTogQ29sbGVjdGlvbkNhY2hlLCBpbmRleE1hbmFnZXI6IENvbGxlY3Rpb25JbmRleE1hbmFnZXIpIHtcbiAgICB0aGlzLmdpdGh1YkNsaWVudCA9IGdpdGh1YkNsaWVudDtcbiAgICB0aGlzLmNvbGxlY3Rpb25DYWNoZSA9IGNvbGxlY3Rpb25DYWNoZTtcbiAgICB0aGlzLmluZGV4TWFuYWdlciA9IGluZGV4TWFuYWdlcjtcbiAgfVxuICBcbiAgLyoqXG4gICAqIEJyb3dzZSBjb2xsZWN0aW9uIGNvbnRlbnQgYnkgc2VjdGlvbiBhbmQgdHlwZVxuICAgKiBVc2VzIENvbGxlY3Rpb25JbmRleE1hbmFnZXIgZm9yIGZhc3QgYnJvd3Npbmcgd2l0aCBiYWNrZ3JvdW5kIHJlZnJlc2hcbiAgICogRmFsbHMgYmFjayB0byBjYWNoZWQgZGF0YSB3aGVuIEdpdEh1YiBBUEkgaXMgbm90IGF2YWlsYWJsZSBvciBub3QgYXV0aGVudGljYXRlZFxuICAgKiBAcGFyYW0gc2VjdGlvbiAtIFRvcCBsZXZlbCBzZWN0aW9uOiBsaWJyYXJ5LCBzaG93Y2FzZSwgb3IgY2F0YWxvZ1xuICAgKiBAcGFyYW0gdHlwZSAtIE9wdGlvbmFsIGNvbnRlbnQgdHlwZSB3aXRoaW4gdGhlIGxpYnJhcnkgc2VjdGlvbiAocGVyc29uYXMsIHNraWxscywgZXRjLilcbiAgICovXG4gIGFzeW5jIGJyb3dzZUNvbGxlY3Rpb24oc2VjdGlvbj86IHN0cmluZywgdHlwZT86IHN0cmluZyk6IFByb21pc2U8eyBpdGVtczogYW55W10sIGNhdGVnb3JpZXM6IGFueVtdLCBzZWN0aW9ucz86IGFueVtdIH0+IHtcbiAgICB0cnkge1xuICAgICAgLy8gVHJ5IHVzaW5nIGNvbGxlY3Rpb24gaW5kZXggZmlyc3QgZm9yIGZhc3RlciBicm93c2luZ1xuICAgICAgY29uc3QgaW5kZXhSZXN1bHQgPSBhd2FpdCB0aGlzLmJyb3dzZUZyb21JbmRleChzZWN0aW9uLCB0eXBlKTtcbiAgICAgIGlmIChpbmRleFJlc3VsdCkge1xuICAgICAgICBsb2dnZXIuZGVidWcoJ1VzZWQgY29sbGVjdGlvbiBpbmRleCBmb3IgYnJvd3NpbmcnKTtcbiAgICAgICAgcmV0dXJuIGluZGV4UmVzdWx0O1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBGYWxsYmFjayB0byBHaXRIdWIgQVBJXG4gICAgICBsZXQgdXJsID0gdGhpcy5iYXNlVXJsO1xuICAgICAgXG4gICAgICAvLyBJZiBubyBzZWN0aW9uIHByb3ZpZGVkLCBzaG93IHRvcC1sZXZlbCBzZWN0aW9uc1xuICAgICAgaWYgKCFzZWN0aW9uKSB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCB0aGlzLmdpdGh1YkNsaWVudC5mZXRjaEZyb21HaXRIdWIodXJsLCBmYWxzZSk7XG4gICAgICAgIGlmICghQXJyYXkuaXNBcnJheShkYXRhKSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBjb2xsZWN0aW9uIHJlc3BvbnNlLiBFeHBlY3RlZCBkaXJlY3RvcnkgbGlzdGluZy4nKTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgLy8gRmlsdGVyIHRvIG9ubHkgc2hvdyBjb250ZW50IGRpcmVjdG9yaWVzXG4gICAgICAgIGNvbnN0IHNlY3Rpb25zID0gZGF0YS5maWx0ZXIoKGl0ZW06IGFueSkgPT4gXG4gICAgICAgICAgaXRlbS50eXBlID09PSAnZGlyJyAmJiBbJ2xpYnJhcnknLCAnc2hvd2Nhc2UnLCAnY2F0YWxvZyddLmluY2x1ZGVzKGl0ZW0ubmFtZSlcbiAgICAgICAgKTtcbiAgICAgICAgXG4gICAgICAgIHJldHVybiB7IGl0ZW1zOiBbXSwgY2F0ZWdvcmllczogW10sIHNlY3Rpb25zIH07XG4gICAgICB9XG4gICAgICBcbiAgICAgIC8vIEJyb3dzZSB3aXRoaW4gYSBzZWN0aW9uXG4gICAgICB1cmwgPSB0eXBlIFxuICAgICAgICA/IGAke3RoaXMuYmFzZVVybH0vJHtzZWN0aW9ufS8ke3R5cGV9YCBcbiAgICAgICAgOiBgJHt0aGlzLmJhc2VVcmx9LyR7c2VjdGlvbn1gO1xuICAgICAgXG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgdGhpcy5naXRodWJDbGllbnQuZmV0Y2hGcm9tR2l0SHViKHVybCwgZmFsc2UpO1xuICAgICAgXG4gICAgICBpZiAoIUFycmF5LmlzQXJyYXkoZGF0YSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGNvbGxlY3Rpb24gcmVzcG9uc2UuIEV4cGVjdGVkIGRpcmVjdG9yeSBsaXN0aW5nLicpO1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBJbiB0aGUgbGlicmFyeSBzZWN0aW9uLCB3ZSBoYXZlIGNvbnRlbnQgdHlwZSBkaXJlY3Rvcmllc1xuICAgICAgaWYgKHNlY3Rpb24gPT09ICdsaWJyYXJ5JyAmJiAhdHlwZSkge1xuICAgICAgICAvLyBGaWx0ZXIgdG8gb25seSBzaG93IE1DUC1zdXBwb3J0ZWQgY29udGVudCB0eXBlc1xuICAgICAgICBjb25zdCBjb250ZW50VHlwZXMgPSBkYXRhLmZpbHRlcigoaXRlbTogYW55KSA9PiB7XG4gICAgICAgICAgaWYgKGl0ZW0udHlwZSAhPT0gJ2RpcicpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICBjb25zdCBlbGVtZW50VHlwZSA9IGlzRWxlbWVudFR5cGUoaXRlbS5uYW1lKSA/IGl0ZW0ubmFtZSBhcyBFbGVtZW50VHlwZSA6IG51bGw7XG4gICAgICAgICAgcmV0dXJuIGVsZW1lbnRUeXBlICYmIGlzTUNQU3VwcG9ydGVkVHlwZShlbGVtZW50VHlwZSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4geyBpdGVtczogW10sIGNhdGVnb3JpZXM6IGNvbnRlbnRUeXBlcyB9O1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBGb3IgbGlicmFyeSBjb250ZW50IHR5cGVzLCBzaG93IGZpbGVzIGRpcmVjdGx5IChmbGF0IHN0cnVjdHVyZSlcbiAgICAgIGNvbnN0IGl0ZW1zID0gZGF0YS5maWx0ZXIoKGl0ZW06IGFueSkgPT4gaXRlbS50eXBlID09PSAnZmlsZScgJiYgaXRlbS5uYW1lLmVuZHNXaXRoKCcubWQnKSk7XG4gICAgICAvLyBGb3Igbm9uLWxpYnJhcnkgc2VjdGlvbnMsIHRoZXkgbWlnaHQgc3RpbGwgaGF2ZSBzdWJkaXJlY3Rvcmllc1xuICAgICAgY29uc3QgY2F0ZWdvcmllcyA9IHNlY3Rpb24gPT09ICdsaWJyYXJ5JyA/IFtdIDogZGF0YS5maWx0ZXIoKGl0ZW06IGFueSkgPT4gaXRlbS50eXBlID09PSAnZGlyJyk7XG4gICAgICBcbiAgICAgIHJldHVybiB7IGl0ZW1zLCBjYXRlZ29yaWVzIH07XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhgR2l0SHViIEFQSSBicm93c2UgZmFpbGVkLCBmYWxsaW5nIGJhY2sgdG8gY2FjaGU6ICR7ZXJyb3J9YCk7XG4gICAgICBcbiAgICAgIC8vIEZhbGxiYWNrIHRvIGNhY2hlZCBkYXRhXG4gICAgICByZXR1cm4gdGhpcy5icm93c2VGcm9tQ2FjaGUoc2VjdGlvbiwgdHlwZSk7XG4gICAgfVxuICB9XG4gIFxuICAvKipcbiAgICogQnJvd3NlIGNvbGxlY3Rpb24gdXNpbmcgdGhlIGZhc3QgY29sbGVjdGlvbiBpbmRleFxuICAgKiBSZXR1cm5zIG51bGwgaWYgaW5kZXggaXMgbm90IGF2YWlsYWJsZSBvciBicm93c2luZyBmYWlsc1xuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBicm93c2VGcm9tSW5kZXgoc2VjdGlvbj86IHN0cmluZywgdHlwZT86IHN0cmluZyk6IFByb21pc2U8eyBpdGVtczogYW55W10sIGNhdGVnb3JpZXM6IGFueVtdLCBzZWN0aW9ucz86IGFueVtdIH0gfCBudWxsPiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGluZGV4ID0gYXdhaXQgdGhpcy5pbmRleE1hbmFnZXIuZ2V0SW5kZXgoKTtcbiAgICAgIFxuICAgICAgLy8gSWYgbm8gc2VjdGlvbiBwcm92aWRlZCwgc2hvdyB0b3AtbGV2ZWwgc2VjdGlvbnNcbiAgICAgIGlmICghc2VjdGlvbikge1xuICAgICAgICBjb25zdCBzZWN0aW9ucyA9IFtcbiAgICAgICAgICB7IG5hbWU6ICdsaWJyYXJ5JywgdHlwZTogJ2RpcicgfSxcbiAgICAgICAgICB7IG5hbWU6ICdzaG93Y2FzZScsIHR5cGU6ICdkaXInIH0sXG4gICAgICAgICAgeyBuYW1lOiAnY2F0YWxvZycsIHR5cGU6ICdkaXInIH1cbiAgICAgICAgXTtcbiAgICAgICAgcmV0dXJuIHsgaXRlbXM6IFtdLCBjYXRlZ29yaWVzOiBbXSwgc2VjdGlvbnMgfTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgLy8gSW4gdGhlIGxpYnJhcnkgc2VjdGlvbiwgd2UgaGF2ZSBjb250ZW50IHR5cGUgZGlyZWN0b3JpZXNcbiAgICAgIGlmIChzZWN0aW9uID09PSAnbGlicmFyeScgJiYgIXR5cGUpIHtcbiAgICAgICAgLy8gR2V0IHVuaXF1ZSBjb250ZW50IHR5cGVzIGZyb20gaW5kZXhcbiAgICAgICAgY29uc3QgY29udGVudFR5cGVzID0gdGhpcy5nZXRDb250ZW50VHlwZXNGcm9tSW5kZXgoaW5kZXgpO1xuICAgICAgICByZXR1cm4geyBpdGVtczogW10sIGNhdGVnb3JpZXM6IGNvbnRlbnRUeXBlcyB9O1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBHZXQgaXRlbXMgZm9yIHNwZWNpZmljIHR5cGUgb3IgYWxsIGl0ZW1zIGluIHNlY3Rpb25cbiAgICAgIGNvbnN0IGl0ZW1zID0gdGhpcy5nZXRJdGVtc0Zyb21JbmRleChpbmRleCwgc2VjdGlvbiwgdHlwZSk7XG4gICAgICBjb25zdCBmb3JtYXR0ZWRJdGVtcyA9IHRoaXMuY29udmVydEluZGV4SXRlbXNUb0dpdEh1YkZvcm1hdChpdGVtcyk7XG4gICAgICBcbiAgICAgIHJldHVybiB7IGl0ZW1zOiBmb3JtYXR0ZWRJdGVtcywgY2F0ZWdvcmllczogW10gfTtcbiAgICAgIFxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIuZGVidWcoJ0ZhaWxlZCB0byBicm93c2UgZnJvbSBjb2xsZWN0aW9uIGluZGV4JywgeyBlcnJvcjogZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpIH0pO1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG4gIFxuICAvKipcbiAgICogR2V0IHVuaXF1ZSBjb250ZW50IHR5cGVzIGZyb20gY29sbGVjdGlvbiBpbmRleFxuICAgKi9cbiAgcHJpdmF0ZSBnZXRDb250ZW50VHlwZXNGcm9tSW5kZXgoaW5kZXg6IENvbGxlY3Rpb25JbmRleCk6IGFueVtdIHtcbiAgICBjb25zdCB0eXBlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgIFxuICAgIC8vIEV4dHJhY3QgdHlwZXMgZnJvbSBpbmRleCBrZXlzIGFuZCBmaWx0ZXIgZm9yIE1DUC1zdXBwb3J0ZWQgdHlwZXNcbiAgICBPYmplY3Qua2V5cyhpbmRleC5pbmRleCkuZm9yRWFjaCh0eXBlTmFtZSA9PiB7XG4gICAgICBjb25zdCBlbGVtZW50VHlwZSA9IGlzRWxlbWVudFR5cGUodHlwZU5hbWUpID8gdHlwZU5hbWUgYXMgRWxlbWVudFR5cGUgOiBudWxsO1xuICAgICAgaWYgKGVsZW1lbnRUeXBlICYmIGlzTUNQU3VwcG9ydGVkVHlwZShlbGVtZW50VHlwZSkpIHtcbiAgICAgICAgdHlwZXMuYWRkKHR5cGVOYW1lKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBcbiAgICByZXR1cm4gQXJyYXkuZnJvbSh0eXBlcykubWFwKHR5cGUgPT4gKHtcbiAgICAgIG5hbWU6IHR5cGUsXG4gICAgICB0eXBlOiAnZGlyJ1xuICAgIH0pKTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIEdldCBpdGVtcyBmcm9tIGNvbGxlY3Rpb24gaW5kZXggYnkgc2VjdGlvbiBhbmQgdHlwZVxuICAgKi9cbiAgcHJpdmF0ZSBnZXRJdGVtc0Zyb21JbmRleChpbmRleDogQ29sbGVjdGlvbkluZGV4LCBzZWN0aW9uOiBzdHJpbmcsIHR5cGU/OiBzdHJpbmcpOiBJbmRleEVudHJ5W10ge1xuICAgIC8vIEZvciBsaWJyYXJ5IHNlY3Rpb24gd2l0aCB0eXBlLCBnZXQgaXRlbXMgZnJvbSB0aGF0IHR5cGVcbiAgICBpZiAoc2VjdGlvbiA9PT0gJ2xpYnJhcnknICYmIHR5cGUpIHtcbiAgICAgIHJldHVybiBpbmRleC5pbmRleFt0eXBlXSB8fCBbXTtcbiAgICB9XG4gICAgXG4gICAgLy8gRm9yIGxpYnJhcnkgc2VjdGlvbiB3aXRob3V0IHR5cGUsIHJldHVybiBlbXB0eSAoc2hvdWxkIHNob3cgY2F0ZWdvcmllcylcbiAgICBpZiAoc2VjdGlvbiA9PT0gJ2xpYnJhcnknICYmICF0eXBlKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIFxuICAgIC8vIEZvciBvdGhlciBzZWN0aW9ucyAoc2hvd2Nhc2UsIGNhdGFsb2cpLCByZXR1cm4gYWxsIGl0ZW1zIHRoYXQgbWF0Y2hcbiAgICAvLyBOb3RlOiBUaGUgY3VycmVudCBpbmRleCBzdHJ1Y3R1cmUgaXMgcHJpbWFyaWx5IGZvciBsaWJyYXJ5IGNvbnRlbnRcbiAgICAvLyBGdXR1cmUgZW5oYW5jZW1lbnQ6IGV4dGVuZCBpbmRleCB0byBpbmNsdWRlIHNob3djYXNlL2NhdGFsb2cgc2VjdGlvbnNcbiAgICByZXR1cm4gW107XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBDb252ZXJ0IGluZGV4IGVudHJpZXMgdG8gR2l0SHViIEFQSSBmb3JtYXQgZm9yIGNvbXBhdGliaWxpdHlcbiAgICovXG4gIHByaXZhdGUgY29udmVydEluZGV4SXRlbXNUb0dpdEh1YkZvcm1hdChpdGVtczogSW5kZXhFbnRyeVtdKTogYW55W10ge1xuICAgIHJldHVybiBpdGVtcy5tYXAoaXRlbSA9PiAoe1xuICAgICAgbmFtZTogaXRlbS5uYW1lLmVuZHNXaXRoKCcubWQnKSA/IGl0ZW0ubmFtZSA6IGAke2l0ZW0ubmFtZX0ubWRgLFxuICAgICAgcGF0aDogaXRlbS5wYXRoLFxuICAgICAgc2hhOiBpdGVtLnNoYSxcbiAgICAgIHR5cGU6ICdmaWxlJyxcbiAgICAgIHVybDogYGh0dHBzOi8vYXBpLmdpdGh1Yi5jb20vcmVwb3MvRG9sbGhvdXNlTUNQL2NvbGxlY3Rpb24vY29udGVudHMvJHtpdGVtLnBhdGh9YCxcbiAgICAgIGh0bWxfdXJsOiBgaHR0cHM6Ly9naXRodWIuY29tL0RvbGxob3VzZU1DUC9jb2xsZWN0aW9uL2Jsb2IvbWFpbi8ke2l0ZW0ucGF0aH1gXG4gICAgfSkpO1xuICB9XG4gIFxuICAvKipcbiAgICogQnJvd3NlIGNvbGxlY3Rpb24gZnJvbSBjYWNoZWQgZGF0YVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBicm93c2VGcm9tQ2FjaGUoc2VjdGlvbj86IHN0cmluZywgdHlwZT86IHN0cmluZyk6IFByb21pc2U8eyBpdGVtczogYW55W10sIGNhdGVnb3JpZXM6IGFueVtdLCBzZWN0aW9ucz86IGFueVtdIH0+IHtcbiAgICB0cnkge1xuICAgICAgLy8gSWYgbm8gc2VjdGlvbiBwcm92aWRlZCwgc2hvdyBhdmFpbGFibGUgc2VjdGlvbnMgZnJvbSBzZWVkIGRhdGFcbiAgICAgIGlmICghc2VjdGlvbikge1xuICAgICAgICBjb25zdCBzZWN0aW9ucyA9IFtcbiAgICAgICAgICB7IG5hbWU6ICdsaWJyYXJ5JywgdHlwZTogJ2RpcicgfVxuICAgICAgICBdO1xuICAgICAgICByZXR1cm4geyBpdGVtczogW10sIGNhdGVnb3JpZXM6IFtdLCBzZWN0aW9ucyB9O1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBHZXQgY2FjaGVkIG9yIHNlZWQgZGF0YVxuICAgICAgbGV0IGNhY2hlZEl0ZW1zID0gYXdhaXQgdGhpcy5jb2xsZWN0aW9uQ2FjaGUubG9hZENhY2hlKCk7XG4gICAgICBcbiAgICAgIGlmICghY2FjaGVkSXRlbXMgfHwgY2FjaGVkSXRlbXMuaXRlbXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIC8vIFVzZSBzZWVkIGRhdGEgaWYgY2FjaGUgaXMgZW1wdHlcbiAgICAgICAgY29uc3Qgc2VlZERhdGEgPSBDb2xsZWN0aW9uU2VlZGVyLmdldFNlZWREYXRhKCk7XG4gICAgICAgIGF3YWl0IHRoaXMuY29sbGVjdGlvbkNhY2hlLnNhdmVDYWNoZShzZWVkRGF0YSk7XG4gICAgICAgIGNhY2hlZEl0ZW1zID0geyBpdGVtczogc2VlZERhdGEsIHRpbWVzdGFtcDogRGF0ZS5ub3coKSB9O1xuICAgICAgICBsb2dnZXIuZGVidWcoJ1VzaW5nIHNlZWQgZGF0YSBmb3IgY29sbGVjdGlvbiBicm93c2luZycpO1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBJbiB0aGUgbGlicmFyeSBzZWN0aW9uLCB3ZSBoYXZlIGNvbnRlbnQgdHlwZSBkaXJlY3Rvcmllc1xuICAgICAgaWYgKHNlY3Rpb24gPT09ICdsaWJyYXJ5JyAmJiAhdHlwZSkge1xuICAgICAgICBjb25zdCBjb250ZW50VHlwZXMgPSB0aGlzLmdldENvbnRlbnRUeXBlc0Zyb21JdGVtcyhjYWNoZWRJdGVtcy5pdGVtcyk7XG4gICAgICAgIHJldHVybiB7IGl0ZW1zOiBbXSwgY2F0ZWdvcmllczogY29udGVudFR5cGVzIH07XG4gICAgICB9XG4gICAgICBcbiAgICAgIC8vIEdldCBpdGVtcyBmb3Igc3BlY2lmaWMgdHlwZSBvciBhbGwgaXRlbXMgaW4gc2VjdGlvblxuICAgICAgY29uc3QgaXRlbXMgPSB0aGlzLmZpbHRlckl0ZW1zQnlTZWN0aW9uKGNhY2hlZEl0ZW1zLml0ZW1zLCBzZWN0aW9uLCB0eXBlKTtcbiAgICAgIGNvbnN0IGZvcm1hdHRlZEl0ZW1zID0gdGhpcy5jb252ZXJ0Q2FjaGVJdGVtc1RvR2l0SHViRm9ybWF0KGl0ZW1zKTtcbiAgICAgIFxuICAgICAgcmV0dXJuIHsgaXRlbXM6IGZvcm1hdHRlZEl0ZW1zLCBjYXRlZ29yaWVzOiBbXSB9O1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoYENhY2hlIGJyb3dzZSBmYWlsZWQ6ICR7ZXJyb3J9YCk7XG4gICAgICBcbiAgICAgIC8vIExhc3QgcmVzb3J0OiB1c2Ugc2VlZCBkYXRhIGRpcmVjdGx5XG4gICAgICByZXR1cm4gdGhpcy5icm93c2VGcm9tU2VlZERhdGEoc2VjdGlvbiwgdHlwZSk7XG4gICAgfVxuICB9XG4gIFxuICAvKipcbiAgICogQnJvd3NlIGNvbGxlY3Rpb24gZnJvbSBzZWVkIGRhdGEgYXMgbGFzdCByZXNvcnRcbiAgICovXG4gIHByaXZhdGUgYnJvd3NlRnJvbVNlZWREYXRhKHNlY3Rpb24/OiBzdHJpbmcsIHR5cGU/OiBzdHJpbmcpOiB7IGl0ZW1zOiBhbnlbXSwgY2F0ZWdvcmllczogYW55W10sIHNlY3Rpb25zPzogYW55W10gfSB7XG4gICAgaWYgKCFzZWN0aW9uKSB7XG4gICAgICBjb25zdCBzZWN0aW9ucyA9IFt7IG5hbWU6ICdsaWJyYXJ5JywgdHlwZTogJ2RpcicgfV07XG4gICAgICByZXR1cm4geyBpdGVtczogW10sIGNhdGVnb3JpZXM6IFtdLCBzZWN0aW9ucyB9O1xuICAgIH1cbiAgICBcbiAgICBjb25zdCBzZWVkRGF0YSA9IENvbGxlY3Rpb25TZWVkZXIuZ2V0U2VlZERhdGEoKTtcbiAgICBcbiAgICBpZiAoc2VjdGlvbiA9PT0gJ2xpYnJhcnknICYmICF0eXBlKSB7XG4gICAgICBjb25zdCBjb250ZW50VHlwZXMgPSB0aGlzLmdldENvbnRlbnRUeXBlc0Zyb21JdGVtcyhzZWVkRGF0YSk7XG4gICAgICByZXR1cm4geyBpdGVtczogW10sIGNhdGVnb3JpZXM6IGNvbnRlbnRUeXBlcyB9O1xuICAgIH1cbiAgICBcbiAgICBjb25zdCBpdGVtcyA9IHRoaXMuZmlsdGVySXRlbXNCeVNlY3Rpb24oc2VlZERhdGEsIHNlY3Rpb24sIHR5cGUpO1xuICAgIGNvbnN0IGZvcm1hdHRlZEl0ZW1zID0gdGhpcy5jb252ZXJ0Q2FjaGVJdGVtc1RvR2l0SHViRm9ybWF0KGl0ZW1zKTtcbiAgICBcbiAgICByZXR1cm4geyBpdGVtczogZm9ybWF0dGVkSXRlbXMsIGNhdGVnb3JpZXM6IFtdIH07XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBHZXQgdW5pcXVlIGNvbnRlbnQgdHlwZXMgZnJvbSBpdGVtc1xuICAgKi9cbiAgcHJpdmF0ZSBnZXRDb250ZW50VHlwZXNGcm9tSXRlbXMoaXRlbXM6IENvbGxlY3Rpb25JdGVtW10pOiBhbnlbXSB7XG4gICAgY29uc3QgdHlwZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBcbiAgICBpdGVtcy5mb3JFYWNoKGl0ZW0gPT4ge1xuICAgICAgY29uc3QgcGF0aFBhcnRzID0gaXRlbS5wYXRoLnNwbGl0KCcvJyk7XG4gICAgICBpZiAocGF0aFBhcnRzLmxlbmd0aCA+PSAyICYmIHBhdGhQYXJ0c1swXSA9PT0gJ2xpYnJhcnknKSB7XG4gICAgICAgIC8vIE9ubHkgaW5jbHVkZSBNQ1Atc3VwcG9ydGVkIHR5cGVzIGluIGNhY2hlIGJyb3dzaW5nXG4gICAgICAgIGNvbnN0IHR5cGVOYW1lID0gcGF0aFBhcnRzWzFdO1xuICAgICAgICBjb25zdCBlbGVtZW50VHlwZSA9IGlzRWxlbWVudFR5cGUodHlwZU5hbWUpID8gdHlwZU5hbWUgYXMgRWxlbWVudFR5cGUgOiBudWxsO1xuICAgICAgICBpZiAoZWxlbWVudFR5cGUgJiYgaXNNQ1BTdXBwb3J0ZWRUeXBlKGVsZW1lbnRUeXBlKSkge1xuICAgICAgICAgIHR5cGVzLmFkZCh0eXBlTmFtZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgICBcbiAgICByZXR1cm4gQXJyYXkuZnJvbSh0eXBlcykubWFwKHR5cGUgPT4gKHtcbiAgICAgIG5hbWU6IHR5cGUsXG4gICAgICB0eXBlOiAnZGlyJ1xuICAgIH0pKTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIEZpbHRlciBpdGVtcyBieSBzZWN0aW9uIGFuZCB0eXBlXG4gICAqL1xuICBwcml2YXRlIGZpbHRlckl0ZW1zQnlTZWN0aW9uKGl0ZW1zOiBDb2xsZWN0aW9uSXRlbVtdLCBzZWN0aW9uOiBzdHJpbmcsIHR5cGU/OiBzdHJpbmcpOiBDb2xsZWN0aW9uSXRlbVtdIHtcbiAgICByZXR1cm4gaXRlbXMuZmlsdGVyKGl0ZW0gPT4ge1xuICAgICAgY29uc3QgcGF0aFBhcnRzID0gaXRlbS5wYXRoLnNwbGl0KCcvJyk7XG4gICAgICBcbiAgICAgIGlmIChwYXRoUGFydHNbMF0gIT09IHNlY3Rpb24pIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgXG4gICAgICBpZiAodHlwZSAmJiBwYXRoUGFydHNbMV0gIT09IHR5cGUpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgXG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9KTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIENvbnZlcnQgY2FjaGUgaXRlbXMgdG8gR2l0SHViIEFQSSBmb3JtYXRcbiAgICovXG4gIHByaXZhdGUgY29udmVydENhY2hlSXRlbXNUb0dpdEh1YkZvcm1hdChpdGVtczogQ29sbGVjdGlvbkl0ZW1bXSk6IGFueVtdIHtcbiAgICByZXR1cm4gaXRlbXMubWFwKGl0ZW0gPT4gKHtcbiAgICAgIG5hbWU6IGl0ZW0ubmFtZSxcbiAgICAgIHBhdGg6IGl0ZW0ucGF0aCxcbiAgICAgIHNoYTogaXRlbS5zaGEsXG4gICAgICB0eXBlOiAnZmlsZScsXG4gICAgICB1cmw6IGBodHRwczovL2FwaS5naXRodWIuY29tL3JlcG9zL0RvbGxob3VzZU1DUC9jb2xsZWN0aW9uL2NvbnRlbnRzLyR7aXRlbS5wYXRofWAsXG4gICAgICBodG1sX3VybDogYGh0dHBzOi8vZ2l0aHViLmNvbS9Eb2xsaG91c2VNQ1AvY29sbGVjdGlvbi9ibG9iL21haW4vJHtpdGVtLnBhdGh9YFxuICAgIH0pKTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIEZvcm1hdCBjb2xsZWN0aW9uIGJyb3dzZSByZXN1bHRzXG4gICAqL1xuICBmb3JtYXRCcm93c2VSZXN1bHRzKGl0ZW1zOiBhbnlbXSwgY2F0ZWdvcmllczogYW55W10sIHNlY3Rpb24/OiBzdHJpbmcsIHR5cGU/OiBzdHJpbmcsIHBlcnNvbmFJbmRpY2F0b3I6IHN0cmluZyA9ICcnKTogc3RyaW5nIHtcbiAgICBjb25zdCB0ZXh0UGFydHMgPSBbYCR7cGVyc29uYUluZGljYXRvcn3wn4+qICoqRG9sbGhvdXNlTUNQIENvbGxlY3Rpb24qKlxcblxcbmBdO1xuICAgIFxuICAgIC8vIFNob3cgdG9wLWxldmVsIHNlY3Rpb25zIGlmIG5vIHNlY3Rpb24gc3BlY2lmaWVkXG4gICAgaWYgKCFzZWN0aW9uICYmIGNhdGVnb3JpZXMubGVuZ3RoID4gMCkge1xuICAgICAgdGV4dFBhcnRzLnB1c2goYCoq8J+TmiBDb2xsZWN0aW9uIFNlY3Rpb25zICgke2NhdGVnb3JpZXMubGVuZ3RofSk6KipcXG5gKTtcbiAgICAgIGNhdGVnb3JpZXMuZm9yRWFjaCgoc2VjOiBhbnkpID0+IHtcbiAgICAgICAgY29uc3Qgc2VjdGlvbkljb25zOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge1xuICAgICAgICAgICdsaWJyYXJ5JzogJ/Cfk5YnLFxuICAgICAgICAgICdzaG93Y2FzZSc6ICfirZAnLFxuICAgICAgICAgICdjYXRhbG9nJzogJ/Cfko4nXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGljb24gPSBzZWN0aW9uSWNvbnNbc2VjLm5hbWVdIHx8ICfwn5OBJztcbiAgICAgICAgY29uc3QgZGVzY3JpcHRpb25zOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge1xuICAgICAgICAgICdsaWJyYXJ5JzogJ0ZyZWUgY29tbXVuaXR5IGNvbnRlbnQnLFxuICAgICAgICAgICdzaG93Y2FzZSc6ICdGZWF0dXJlZCBoaWdoLXF1YWxpdHkgY29udGVudCAoY29taW5nIHNvb24pJyxcbiAgICAgICAgICAnY2F0YWxvZyc6ICdQcmVtaXVtIGNvbnRlbnQgKGNvbWluZyBzb29uKSdcbiAgICAgICAgfTtcbiAgICAgICAgdGV4dFBhcnRzLnB1c2goXG4gICAgICAgICAgYCAgICR7aWNvbn0gKioke3NlYy5uYW1lfSoqIC0gJHtkZXNjcmlwdGlvbnNbc2VjLm5hbWVdIHx8ICdDb250ZW50IGNvbGxlY3Rpb24nfVxcbmAsXG4gICAgICAgICAgYCAgICAgIEJyb3dzZTogXFxgYnJvd3NlX2NvbGxlY3Rpb24gXCIke3NlYy5uYW1lfVwiXFxgXFxuXFxuYFxuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gdGV4dFBhcnRzLmpvaW4oJycpO1xuICAgIH1cbiAgICBcbiAgICAvLyBTaG9