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.

236 lines 30.9 kB
/** * Portfolio sync handler for the sync_portfolio MCP tool * Manages bi-directional synchronization between local portfolio and GitHub * * Uses dependency injection for all services: * - PortfolioSyncManager for sync operations * - ConfigManager for configuration * - PersonaIndicatorService for persona indicator formatting */ import { SecureErrorHandler } from '../security/errorHandler.js'; export class SyncHandler { syncManager; configManager; indicatorService; constructor(syncManager, configManager, indicatorService) { this.syncManager = syncManager; this.configManager = configManager; this.indicatorService = indicatorService; } /** * Handle portfolio sync operations */ async handleSyncOperation(options) { const indicator = this.indicatorService.getPersonaIndicator(); try { await this.configManager.initialize(); // Check if sync is enabled (allow list-remote and compare even when disabled) const syncEnabled = this.configManager.getSetting('sync.enabled'); const readOnlyOperations = ['list-remote', 'compare']; if (!syncEnabled && !readOnlyOperations.includes(options.operation)) { return { content: [{ type: "text", text: `${indicator}⚠️ **Sync is Disabled**\n\n` + `Portfolio sync is currently disabled for privacy.\n\n` + `To enable sync:\n` + `\`dollhouse_config action: "set", setting: "sync.enabled", value: true\`\n\n` + `You can still use \`list-remote\` and \`compare\` to view differences.` }] }; } // Map our operation to PortfolioSyncManager's SyncOperation format const syncOp = { operation: this.mapOperation(options.operation), element_name: options.element_name, element_type: options.element_type || options.filter?.type, // Use filter.type if element_type not provided bulk: options.operation.includes('bulk'), show_diff: options.operation === 'compare', force: options.options?.force, confirm: options.options?.force || options.options?.dry_run === false // force implies confirm, dry_run=false means confirm }; // Call the unified handleSyncOperation method const result = await this.syncManager.handleSyncOperation(syncOp); // Format the result based on the operation type return this.formatResult(result, options, indicator); } catch (error) { const sanitizedError = SecureErrorHandler.sanitizeError(error); return { content: [{ type: "text", text: `${indicator}❌ Sync operation failed: ${sanitizedError.message}` }] }; } } mapOperation(operation) { switch (operation) { case 'list-remote': return 'list-remote'; case 'download': case 'bulk-download': return 'download'; case 'upload': case 'bulk-upload': return 'upload'; case 'compare': return 'compare'; default: return 'list-remote'; } } formatResult(result, options, indicator) { if (!result.success) { return { content: [{ type: "text", text: `${indicator}${result.message}` }] }; } switch (options.operation) { case 'list-remote': return this.formatListResult(result, indicator); case 'download': case 'bulk-download': return this.formatDownloadResult(result, options, indicator); case 'upload': case 'bulk-upload': return this.formatUploadResult(result, options, indicator); case 'compare': return this.formatCompareResult(result, options, indicator); default: return { content: [{ type: "text", text: `${indicator}${result.message}` }] }; } } formatListResult(result, indicator) { if (!result.elements || result.elements.length === 0) { return { content: [{ type: "text", text: `${indicator}📋 **GitHub Portfolio is Empty**\n\n` + `No elements found in your GitHub portfolio.\n\n` + `Upload elements using:\n` + `\`sync_portfolio operation: "upload", element_name: "name", element_type: "type"\`` }] }; } let text = `${indicator}📋 **GitHub Portfolio Contents**\n\n`; text += `Found ${result.elements.length} elements:\n\n`; // Group by type const byType = {}; for (const element of result.elements) { if (!byType[element.type]) { byType[element.type] = []; } byType[element.type].push(element); } for (const [type, elements] of Object.entries(byType)) { text += `**${type}** (${elements.length}):\n`; for (const element of elements) { text += ` • ${element.name}`; if (element.remoteVersion) { text += ` v${element.remoteVersion}`; } if (element.status) { text += ` (${element.status})`; } text += '\n'; } text += '\n'; } return { content: [{ type: "text", text }] }; } formatDownloadResult(result, options, indicator) { if (options.operation === 'bulk-download') { const elements = result.elements || []; const downloaded = elements.filter(e => e.action === 'download').length; const skipped = elements.filter(e => e.action === 'skip').length; return { content: [{ type: "text", text: `${indicator}✅ **Bulk Download Complete**\n\n` + `Downloaded: ${downloaded} elements\n` + `Skipped: ${skipped} elements\n\n` + result.message }] }; } return { content: [{ type: "text", text: `${indicator}✅ **Element Downloaded**\n\n` + `Element: ${options.element_name} (${options.element_type})\n\n` + result.message }] }; } formatUploadResult(result, options, indicator) { if (options.operation === 'bulk-upload') { const elements = result.elements || []; const uploaded = elements.filter(e => e.action === 'upload').length; const skipped = elements.filter(e => e.action === 'skip').length; return { content: [{ type: "text", text: `${indicator}✅ **Bulk Upload Complete**\n\n` + `Uploaded: ${uploaded} elements\n` + `Skipped: ${skipped} elements\n\n` + result.message }] }; } return { content: [{ type: "text", text: `${indicator}✅ **Element Uploaded**\n\n` + `Element: ${options.element_name} (${options.element_type})\n\n` + result.message }] }; } formatCompareResult(result, options, indicator) { let text = `${indicator}🔍 **Version Comparison**\n\n`; text += `Element: ${options.element_name} (${options.element_type})\n\n`; if (result.data) { // If we have detailed comparison data const data = result.data; if (data.local) { text += `**Local Version**: ${data.local.version}\n`; text += ` Modified: ${new Date(data.local.timestamp).toLocaleString()}\n`; } else { text += `**Local Version**: Not found\n`; } if (data.remote) { text += `\n**Remote Version**: ${data.remote.version}\n`; text += ` Modified: ${new Date(data.remote.timestamp).toLocaleString()}\n`; } else { text += `\n**Remote Version**: Not found\n`; } if (data.diff) { text += `\n**Differences**:\n${data.diff}`; } } text += `\n\n${result.message}`; return { content: [{ type: "text", text }] }; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU3luY0hhbmRsZXJWMi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9oYW5kbGVycy9TeW5jSGFuZGxlclYyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7OztHQVFHO0FBSUgsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFvQmpFLE1BQU0sT0FBTyxXQUFXO0lBRUg7SUFDQTtJQUNBO0lBSG5CLFlBQ21CLFdBQWlDLEVBQ2pDLGFBQTRCLEVBQzVCLGdCQUF5QztRQUZ6QyxnQkFBVyxHQUFYLFdBQVcsQ0FBc0I7UUFDakMsa0JBQWEsR0FBYixhQUFhLENBQWU7UUFDNUIscUJBQWdCLEdBQWhCLGdCQUFnQixDQUF5QjtJQUN6RCxDQUFDO0lBRUo7O09BRUc7SUFDSCxLQUFLLENBQUMsbUJBQW1CLENBQUMsT0FBNkI7UUFDckQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFFOUQsSUFBSSxDQUFDO1lBQ0gsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBRXRDLDhFQUE4RTtZQUM5RSxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUNsRSxNQUFNLGtCQUFrQixHQUFHLENBQUMsYUFBYSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQ3RELElBQUksQ0FBQyxXQUFXLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7Z0JBQ3BFLE9BQU87b0JBQ0wsT0FBTyxFQUFFLENBQUM7NEJBQ1IsSUFBSSxFQUFFLE1BQU07NEJBQ1osSUFBSSxFQUFFLEdBQUcsU0FBUyw2QkFBNkI7Z0NBQ3pDLHVEQUF1RDtnQ0FDdkQsbUJBQW1CO2dDQUNuQiw4RUFBOEU7Z0NBQzlFLHdFQUF3RTt5QkFDL0UsQ0FB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SUFBSSxFQUFFLENBQUM7Z0JBQ2QsSUFBSSxJQUFJLHVCQUF1QixJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDN0MsQ0FBQztRQUNILENBQUM7UUFFRCxJQUFJLElBQUksT0FBTyxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7UUFFaEMsT0FBTztZQUNMLE9BQU8sRUFBRSxDQUFDO29CQUNSLElBQUksRUFBRSxNQUFNO29CQUNaLElBQUk7aUJBQ0wsQ0FBQztTQUNILENBQUM7SUFDSixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFBvcnRmb2xpbyBzeW5jIGhhbmRsZXIgZm9yIHRoZSBzeW5jX3BvcnRmb2xpbyBNQ1AgdG9vbFxuICogTWFuYWdlcyBiaS1kaXJlY3Rpb25hbCBzeW5jaHJvbml6YXRpb24gYmV0d2VlbiBsb2NhbCBwb3J0Zm9saW8gYW5kIEdpdEh1YlxuICpcbiAqIFVzZXMgZGVwZW5kZW5jeSBpbmplY3Rpb24gZm9yIGFsbCBzZXJ2aWNlczpcbiAqIC0gUG9ydGZvbGlvU3luY01hbmFnZXIgZm9yIHN5bmMgb3BlcmF0aW9uc1xuICogLSBDb25maWdNYW5hZ2VyIGZvciBjb25maWd1cmF0aW9uXG4gKiAtIFBlcnNvbmFJbmRpY2F0b3JTZXJ2aWNlIGZvciBwZXJzb25hIGluZGljYXRvciBmb3JtYXR0aW5nXG4gKi9cblxuaW1wb3J0IHsgUG9ydGZvbGlvU3luY01hbmFnZXIsIFN5bmNPcGVyYXRpb24sIFN5bmNSZXN1bHQgfSBmcm9tICcuLi9wb3J0Zm9saW8vUG9ydGZvbGlvU3luY01hbmFnZXIuanMnO1xuaW1wb3J0IHsgQ29uZmlnTWFuYWdlciB9IGZyb20gJy4uL2NvbmZpZy9Db25maWdNYW5hZ2VyLmpzJztcbmltcG9ydCB7IFNlY3VyZUVycm9ySGFuZGxlciB9IGZyb20gJy4uL3NlY3VyaXR5L2Vycm9ySGFuZGxlci5qcyc7XG5pbXBvcnQgeyBFbGVtZW50VHlwZSB9IGZyb20gJy4uL3BvcnRmb2xpby9Qb3J0Zm9saW9NYW5hZ2VyLmpzJztcbmltcG9ydCB7IFBlcnNvbmFJbmRpY2F0b3JTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvUGVyc29uYUluZGljYXRvclNlcnZpY2UuanMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFN5bmNPcGVyYXRpb25PcHRpb25zIHtcbiAgb3BlcmF0aW9uOiAnbGlzdC1yZW1vdGUnIHwgJ2Rvd25sb2FkJyB8ICd1cGxvYWQnIHwgJ2NvbXBhcmUnIHwgJ2J1bGstZG93bmxvYWQnIHwgJ2J1bGstdXBsb2FkJztcbiAgZWxlbWVudF9uYW1lPzogc3RyaW5nO1xuICBlbGVtZW50X3R5cGU/OiBFbGVtZW50VHlwZTtcbiAgZmlsdGVyPzoge1xuICAgIHR5cGU/OiBFbGVtZW50VHlwZTtcbiAgICBhdXRob3I/OiBzdHJpbmc7XG4gICAgdXBkYXRlZF9hZnRlcj86IHN0cmluZztcbiAgfTtcbiAgb3B0aW9ucz86IHtcbiAgICBmb3JjZT86IGJvb2xlYW47XG4gICAgZHJ5X3J1bj86IGJvb2xlYW47XG4gICAgaW5jbHVkZV9wcml2YXRlPzogYm9vbGVhbjtcbiAgfTtcbn1cblxuZXhwb3J0IGNsYXNzIFN5bmNIYW5kbGVyIHtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBzeW5jTWFuYWdlcjogUG9ydGZvbGlvU3luY01hbmFnZXIsXG4gICAgcHJpdmF0ZSByZWFkb25seSBjb25maWdNYW5hZ2VyOiBDb25maWdNYW5hZ2VyLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgaW5kaWNhdG9yU2VydmljZTogUGVyc29uYUluZGljYXRvclNlcnZpY2VcbiAgKSB7fVxuICBcbiAgLyoqXG4gICAqIEhhbmRsZSBwb3J0Zm9saW8gc3luYyBvcGVyYXRpb25zXG4gICAqL1xuICBhc3luYyBoYW5kbGVTeW5jT3BlcmF0aW9uKG9wdGlvbnM6IFN5bmNPcGVyYXRpb25PcHRpb25zKSB7XG4gICAgY29uc3QgaW5kaWNhdG9yID0gdGhpcy5pbmRpY2F0b3JTZXJ2aWNlLmdldFBlcnNvbmFJbmRpY2F0b3IoKTtcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmNvbmZpZ01hbmFnZXIuaW5pdGlhbGl6ZSgpO1xuXG4gICAgICAvLyBDaGVjayBpZiBzeW5jIGlzIGVuYWJsZWQgKGFsbG93IGxpc3QtcmVtb3RlIGFuZCBjb21wYXJlIGV2ZW4gd2hlbiBkaXNhYmxlZClcbiAgICAgIGNvbnN0IHN5bmNFbmFibGVkID0gdGhpcy5jb25maWdNYW5hZ2VyLmdldFNldHRpbmcoJ3N5bmMuZW5hYmxlZCcpO1xuICAgICAgY29uc3QgcmVhZE9ubHlPcGVyYXRpb25zID0gWydsaXN0LXJlbW90ZScsICdjb21wYXJlJ107XG4gICAgICBpZiAoIXN5bmNFbmFibGVkICYmICFyZWFkT25seU9wZXJhdGlvbnMuaW5jbHVkZXMob3B0aW9ucy5vcGVyYXRpb24pKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgY29udGVudDogW3tcbiAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgdGV4dDogYCR7aW5kaWNhdG9yfeKaoO+4jyAqKlN5bmMgaXMgRGlzYWJsZWQqKlxcblxcbmAgK1xuICAgICAgICAgICAgICAgICAgYFBvcnRmb2xpbyBzeW5jIGlzIGN1cnJlbnRseSBkaXNhYmxlZCBmb3IgcHJpdmFjeS5cXG5cXG5gICtcbiAgICAgICAgICAgICAgICAgIGBUbyBlbmFibGUgc3luYzpcXG5gICtcbiAgICAgICAgICAgICAgICAgIGBcXGBkb2xsaG91c2VfY29uZmlnIGFjdGlvbjogXCJzZXRcIiwgc2V0dGluZzogXCJzeW5jLmVuYWJsZWRcIiwgdmFsdWU6IHRydWVcXGBcXG5cXG5gICtcbiAgICAgICAgICAgICAgICAgIGBZb3UgY2FuIHN0aWxsIHVzZSBcXGBsaXN0LXJlbW90ZVxcYCBhbmQgXFxgY29tcGFyZVxcYCB0byB2aWV3IGRpZmZlcmVuY2VzLmBcbiAgICAgICAgICB9XVxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBNYXAgb3VyIG9wZXJhdGlvbiB0byBQb3J0Zm9saW9TeW5jTWFuYWdlcidzIFN5bmNPcGVyYXRpb24gZm9ybWF0XG4gICAgICBjb25zdCBzeW5jT3A6IFN5bmNPcGVyYXRpb24gPSB7XG4gICAgICAgIG9wZXJhdGlvbjogdGhpcy5tYXBPcGVyYXRpb24ob3B0aW9ucy5vcGVyYXRpb24pLFxuICAgICAgICBlbGVtZW50X25hbWU6IG9wdGlvbnMuZWxlbWVudF9uYW1lLFxuICAgICAgICBlbGVtZW50X3R5cGU6IG9wdGlvbnMuZWxlbWVudF90eXBlIHx8IG9wdGlvbnMuZmlsdGVyPy50eXBlLCAvLyBVc2UgZmlsdGVyLnR5cGUgaWYgZWxlbWVudF90eXBlIG5vdCBwcm92aWRlZFxuICAgICAgICBidWxrOiBvcHRpb25zLm9wZXJhdGlvbi5pbmNsdWRlcygnYnVsaycpLFxuICAgICAgICBzaG93X2RpZmY6IG9wdGlvbnMub3BlcmF0aW9uID09PSAnY29tcGFyZScsXG4gICAgICAgIGZvcmNlOiBvcHRpb25zLm9wdGlvbnM/LmZvcmNlLFxuICAgICAgICBjb25maXJtOiBvcHRpb25zLm9wdGlvbnM/LmZvcmNlIHx8IG9wdGlvbnMub3B0aW9ucz8uZHJ5X3J1biA9PT0gZmFsc2UgLy8gZm9yY2UgaW1wbGllcyBjb25maXJtLCBkcnlfcnVuPWZhbHNlIG1lYW5zIGNvbmZpcm1cbiAgICAgIH07XG4gICAgICBcbiAgICAgIC8vIENhbGwgdGhlIHVuaWZpZWQgaGFuZGxlU3luY09wZXJhdGlvbiBtZXRob2RcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuc3luY01hbmFnZXIuaGFuZGxlU3luY09wZXJhdGlvbihzeW5jT3ApO1xuICAgICAgXG4gICAgICAvLyBGb3JtYXQgdGhlIHJlc3VsdCBiYXNlZCBvbiB0aGUgb3BlcmF0aW9uIHR5cGVcbiAgICAgIHJldHVybiB0aGlzLmZvcm1hdFJlc3VsdChyZXN1bHQsIG9wdGlvbnMsIGluZGljYXRvcik7XG4gICAgICBcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc3Qgc2FuaXRpemVkRXJyb3IgPSBTZWN1cmVFcnJvckhhbmRsZXIuc2FuaXRpemVFcnJvcihlcnJvcik7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbe1xuICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgIHRleHQ6IGAke2luZGljYXRvcn3inYwgU3luYyBvcGVyYXRpb24gZmFpbGVkOiAke3Nhbml0aXplZEVycm9yLm1lc3NhZ2V9YFxuICAgICAgICB9XVxuICAgICAgfTtcbiAgICB9XG4gIH1cbiAgXG4gIHByaXZhdGUgbWFwT3BlcmF0aW9uKG9wZXJhdGlvbjogc3RyaW5nKTogJ2Rvd25sb2FkJyB8ICd1cGxvYWQnIHwgJ2NvbXBhcmUnIHwgJ2xpc3QtcmVtb3RlJyB7XG4gICAgc3dpdGNoIChvcGVyYXRpb24pIHtcbiAgICAgIGNhc2UgJ2xpc3QtcmVtb3RlJzpcbiAgICAgICAgcmV0dXJuICdsaXN0LXJlbW90ZSc7XG4gICAgICBjYXNlICdkb3dubG9hZCc6XG4gICAgICBjYXNlICdidWxrLWRvd25sb2FkJzpcbiAgICAgICAgcmV0dXJuICdkb3dubG9hZCc7XG4gICAgICBjYXNlICd1cGxvYWQnOlxuICAgICAgY2FzZSAnYnVsay11cGxvYWQnOlxuICAgICAgICByZXR1cm4gJ3VwbG9hZCc7XG4gICAgICBjYXNlICdjb21wYXJlJzpcbiAgICAgICAgcmV0dXJuICdjb21wYXJlJztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiAnbGlzdC1yZW1vdGUnO1xuICAgIH1cbiAgfVxuICBcbiAgcHJpdmF0ZSBmb3JtYXRSZXN1bHQocmVzdWx0OiBTeW5jUmVzdWx0LCBvcHRpb25zOiBTeW5jT3BlcmF0aW9uT3B0aW9ucywgaW5kaWNhdG9yOiBzdHJpbmcpIHtcbiAgICBpZiAoIXJlc3VsdC5zdWNjZXNzKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbe1xuICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgIHRleHQ6IGAke2luZGljYXRvcn3inYwgJHtyZXN1bHQubWVzc2FnZX1gXG4gICAgICAgIH1dXG4gICAgICB9O1xuICAgIH1cbiAgICBcbiAgICBzd2l0Y2ggKG9wdGlvbnMub3BlcmF0aW9uKSB7XG4gICAgICBjYXNlICdsaXN0LXJlbW90ZSc6XG4gICAgICAgIHJldHVybiB0aGlzLmZvcm1hdExpc3RSZXN1bHQocmVzdWx0LCBpbmRpY2F0b3IpO1xuICAgICAgXG4gICAgICBjYXNlICdkb3dubG9hZCc6XG4gICAgICBjYXNlICdidWxrLWRvd25sb2FkJzpcbiAgICAgICAgcmV0dXJuIHRoaXMuZm9ybWF0RG93bmxvYWRSZXN1bHQocmVzdWx0LCBvcHRpb25zLCBpbmRpY2F0b3IpO1xuICAgICAgXG4gICAgICBjYXNlICd1cGxvYWQnOlxuICAgICAgY2FzZSAnYnVsay11cGxvYWQnOlxuICAgICAgICByZXR1cm4gdGhpcy5mb3JtYXRVcGxvYWRSZXN1bHQocmVzdWx0LCBvcHRpb25zLCBpbmRpY2F0b3IpO1xuICAgICAgXG4gICAgICBjYXNlICdjb21wYXJlJzpcbiAgICAgICAgcmV0dXJuIHRoaXMuZm9ybWF0Q29tcGFyZVJlc3VsdChyZXN1bHQsIG9wdGlvbnMsIGluZGljYXRvcik7XG4gICAgICBcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgY29udGVudDogW3tcbiAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgdGV4dDogYCR7aW5kaWNhdG9yfeKchSAke3Jlc3VsdC5tZXNzYWdlfWBcbiAgICAgICAgICB9XVxuICAgICAgICB9O1xuICAgIH1cbiAgfVxuICBcbiAgcHJpdmF0ZSBmb3JtYXRMaXN0UmVzdWx0KHJlc3VsdDogU3luY1Jlc3VsdCwgaW5kaWNhdG9yOiBzdHJpbmcpIHtcbiAgICBpZiAoIXJlc3VsdC5lbGVtZW50cyB8fCByZXN1bHQuZWxlbWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbe1xuICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgIHRleHQ6IGAke2luZGljYXRvcn3wn5OLICoqR2l0SHViIFBvcnRmb2xpbyBpcyBFbXB0eSoqXFxuXFxuYCArXG4gICAgICAgICAgICAgICAgYE5vIGVsZW1lbnRzIGZvdW5kIGluIHlvdXIgR2l0SHViIHBvcnRmb2xpby5cXG5cXG5gICtcbiAgICAgICAgICAgICAgICBgVXBsb2FkIGVsZW1lbnRzIHVzaW5nOlxcbmAgK1xuICAgICAgICAgICAgICAgIGBcXGBzeW5jX3BvcnRmb2xpbyBvcGVyYXRpb246IFwidXBsb2FkXCIsIGVsZW1lbnRfbmFtZTogXCJuYW1lXCIsIGVsZW1lbnRfdHlwZTogXCJ0eXBlXCJcXGBgXG4gICAgICAgIH1dXG4gICAgICB9O1xuICAgIH1cbiAgICBcbiAgICBsZXQgdGV4dCA9IGAke2luZGljYXRvcn3wn5OLICoqR2l0SHViIFBvcnRmb2xpbyBDb250ZW50cyoqXFxuXFxuYDtcbiAgICB0ZXh0ICs9IGBGb3VuZCAke3Jlc3VsdC5lbGVtZW50cy5sZW5ndGh9IGVsZW1lbnRzOlxcblxcbmA7XG4gICAgXG4gICAgLy8gR3JvdXAgYnkgdHlwZVxuICAgIGNvbnN0IGJ5VHlwZTogUmVjb3JkPHN0cmluZywgYW55W10+ID0ge307XG4gICAgZm9yIChjb25zdCBlbGVtZW50IG9mIHJlc3VsdC5lbGVtZW50cykge1xuICAgICAgaWYgKCFieVR5cGVbZWxlbWVudC50eXBlXSkge1xuICAgICAgICBieVR5cGVbZWxlbWVudC50eXBlXSA9IFtdO1xuICAgICAgfVxuICAgICAgYnlUeXBlW2VsZW1lbnQudHlwZV0ucHVzaChlbGVtZW50KTtcbiAgICB9XG4gICAgXG4gICAgZm9yIChjb25zdCBbdHlwZSwgZWxlbWVudHNdIG9mIE9iamVjdC5lbnRyaWVzKGJ5VHlwZSkpIHtcbiAgICAgIHRleHQgKz0gYCoqJHt0eXBlfSoqICgke2VsZW1lbnRzLmxlbmd0aH0pOlxcbmA7XG4gICAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZWxlbWVudHMpIHtcbiAgICAgICAgdGV4dCArPSBgICDigKIgJHtlbGVtZW50Lm5hbWV9YDtcbiAgICAgICAgaWYgKGVsZW1lbnQucmVtb3RlVmVyc2lvbikge1xuICAgICAgICAgIHRleHQgKz0gYCB2JHtlbGVtZW50LnJlbW90ZVZlcnNpb259YDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZWxlbWVudC5zdGF0dXMpIHtcbiAgICAgICAgICB0ZXh0ICs9IGAgKCR7ZWxlbWVudC5zdGF0dXN9KWA7XG4gICAgICAgIH1cbiAgICAgICAgdGV4dCArPSAnXFxuJztcbiAgICAgIH1cbiAgICAgIHRleHQgKz0gJ1xcbic7XG4gICAgfVxuICAgIFxuICAgIHJldHVybiB7XG4gICAgICBjb250ZW50OiBbe1xuICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgdGV4dFxuICAgICAgfV1cbiAgICB9O1xuICB9XG4gIFxuICBwcml2YXRlIGZvcm1hdERvd25sb2FkUmVzdWx0KHJlc3VsdDogU3luY1Jlc3VsdCwgb3B0aW9uczogU3luY09wZXJhdGlvbk9wdGlvbnMsIGluZGljYXRvcjogc3RyaW5nKSB7XG4gICAgaWYgKG9wdGlvbnMub3BlcmF0aW9uID09PSAnYnVsay1kb3dubG9hZCcpIHtcbiAgICAgIGNvbnN0IGVsZW1lbnRzID0gcmVzdWx0LmVsZW1lbnRzIHx8IFtdO1xuICAgICAgY29uc3QgZG93bmxvYWRlZCA9IGVsZW1lbnRzLmZpbHRlcihlID0+IGUuYWN0aW9uID09PSAnZG93bmxvYWQnKS5sZW5ndGg7XG4gICAgICBjb25zdCBza2lwcGVkID0gZWxlbWVudHMuZmlsdGVyKGUgPT4gZS5hY3Rpb24gPT09ICdza2lwJykubGVuZ3RoO1xuICAgICAgXG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbe1xuICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgIHRleHQ6IGAke2luZGljYXRvcn3inIUgKipCdWxrIERvd25sb2FkIENvbXBsZXRlKipcXG5cXG5gICtcbiAgICAgICAgICAgICAgICBgRG93bmxvYWRlZDogJHtkb3dubG9hZGVkfSBlbGVtZW50c1xcbmAgK1xuICAgICAgICAgICAgICAgIGBTa2lwcGVkOiAke3NraXBwZWR9IGVsZW1lbnRzXFxuXFxuYCArXG4gICAgICAgICAgICAgICAgcmVzdWx0Lm1lc3NhZ2VcbiAgICAgICAgfV1cbiAgICAgIH07XG4gICAgfVxuICAgIFxuICAgIHJldHVybiB7XG4gICAgICBjb250ZW50OiBbe1xuICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgdGV4dDogYCR7aW5kaWNhdG9yfeKchSAqKkVsZW1lbnQgRG93bmxvYWRlZCoqXFxuXFxuYCArXG4gICAgICAgICAgICAgIGBFbGVtZW50OiAke29wdGlvbnMuZWxlbWVudF9uYW1lfSAoJHtvcHRpb25zLmVsZW1lbnRfdHlwZX0pXFxuXFxuYCArXG4gICAgICAgICAgICAgIHJlc3VsdC5tZXNzYWdlXG4gICAgICB9XVxuICAgIH07XG4gIH1cbiAgXG4gIHByaXZhdGUgZm9ybWF0VXBsb2FkUmVzdWx0KHJlc3VsdDogU3luY1Jlc3VsdCwgb3B0aW9uczogU3luY09wZXJhdGlvbk9wdGlvbnMsIGluZGljYXRvcjogc3RyaW5nKSB7XG4gICAgaWYgKG9wdGlvbnMub3BlcmF0aW9uID09PSAnYnVsay11cGxvYWQnKSB7XG4gICAgICBjb25zdCBlbGVtZW50cyA9IHJlc3VsdC5lbGVtZW50cyB8fCBbXTtcbiAgICAgIGNvbnN0IHVwbG9hZGVkID0gZWxlbWVudHMuZmlsdGVyKGUgPT4gZS5hY3Rpb24gPT09ICd1cGxvYWQnKS5sZW5ndGg7XG4gICAgICBjb25zdCBza2lwcGVkID0gZWxlbWVudHMuZmlsdGVyKGUgPT4gZS5hY3Rpb24gPT09ICdza2lwJykubGVuZ3RoO1xuICAgICAgXG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbe1xuICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgIHRleHQ6IGAke2luZGljYXRvcn3inIUgKipCdWxrIFVwbG9hZCBDb21wbGV0ZSoqXFxuXFxuYCArXG4gICAgICAgICAgICAgICAgYFVwbG9hZGVkOiAke3VwbG9hZGVkfSBlbGVtZW50c1xcbmAgK1xuICAgICAgICAgICAgICAgIGBTa2lwcGVkOiAke3NraXBwZWR9IGVsZW1lbnRzXFxuXFxuYCArXG4gICAgICAgICAgICAgICAgcmVzdWx0Lm1lc3NhZ2VcbiAgICAgICAgfV1cbiAgICAgIH07XG4gICAgfVxuICAgIFxuICAgIHJldHVybiB7XG4gICAgICBjb250ZW50OiBbe1xuICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgdGV4dDogYCR7aW5kaWNhdG9yfeKchSAqKkVsZW1lbnQgVXBsb2FkZWQqKlxcblxcbmAgK1xuICAgICAgICAgICAgICBgRWxlbWVudDogJHtvcHRpb25zLmVsZW1lbnRfbmFtZX0gKCR7b3B0aW9ucy5lbGVtZW50X3R5cGV9KVxcblxcbmAgK1xuICAgICAgICAgICAgICByZXN1bHQubWVzc2FnZVxuICAgICAgfV1cbiAgICB9O1xuICB9XG4gIFxuICBwcml2YXRlIGZvcm1hdENvbXBhcmVSZXN1bHQocmVzdWx0OiBTeW5jUmVzdWx0LCBvcHRpb25zOiBTeW5jT3BlcmF0aW9uT3B0aW9ucywgaW5kaWNhdG9yOiBzdHJpbmcpIHtcbiAgICBsZXQgdGV4dCA9IGAke2luZGljYXRvcn3wn5SNICoqVmVyc2lvbiBDb21wYXJpc29uKipcXG5cXG5gO1xuICAgIHRleHQgKz0gYEVsZW1lbnQ6ICR7b3B0aW9ucy5lbGVtZW50X25hbWV9ICgke29wdGlvbnMuZWxlbWVudF90eXBlfSlcXG5cXG5gO1xuICAgIFxuICAgIGlmIChyZXN1bHQuZGF0YSkge1xuICAgICAgLy8gSWYgd2UgaGF2ZSBkZXRhaWxlZCBjb21wYXJpc29uIGRhdGFcbiAgICAgIGNvbnN0IGRhdGEgPSByZXN1bHQuZGF0YTtcbiAgICAgIGlmIChkYXRhLmxvY2FsKSB7XG4gICAgICAgIHRleHQgKz0gYCoqTG9jYWwgVmVyc2lvbioqOiAke2RhdGEubG9jYWwudmVyc2lvbn1cXG5gO1xuICAgICAgICB0ZXh0ICs9IGAgIE1vZGlmaWVkOiAke25ldyBEYXRlKGRhdGEubG9jYWwudGltZXN0YW1wKS50b0xvY2FsZVN0cmluZygpfVxcbmA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0ZXh0ICs9IGAqKkxvY2FsIFZlcnNpb24qKjogTm90IGZvdW5kXFxuYDtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgaWYgKGRhdGEucmVtb3RlKSB7XG4gICAgICAgIHRleHQgKz0gYFxcbioqUmVtb3RlIFZlcnNpb24qKjogJHtkYXRhLnJlbW90ZS52ZXJzaW9ufVxcbmA7XG4gICAgICAgIHRleHQgKz0gYCAgTW9kaWZpZWQ6ICR7bmV3IERhdGUoZGF0YS5yZW1vdGUudGltZXN0YW1wKS50b0xvY2FsZVN0cmluZygpfVxcbmA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0ZXh0ICs9IGBcXG4qKlJlbW90ZSBWZXJzaW9uKio6IE5vdCBmb3VuZFxcbmA7XG4gICAgICB9XG4gICAgICBcbiAgICAgIGlmIChkYXRhLmRpZmYpIHtcbiAgICAgICAgdGV4dCArPSBgXFxuKipEaWZmZXJlbmNlcyoqOlxcbiR7ZGF0YS5kaWZmfWA7XG4gICAgICB9XG4gICAgfVxuICAgIFxuICAgIHRleHQgKz0gYFxcblxcbiR7cmVzdWx0Lm1lc3NhZ2V9YDtcbiAgICBcbiAgICByZXR1cm4ge1xuICAgICAgY29udGVudDogW3tcbiAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgIHRleHRcbiAgICAgIH1dXG4gICAgfTtcbiAgfVxufVxuIl19