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.

274 lines 38.9 kB
/** * Persona element class implementing IElement interface. * Represents a behavioral profile that defines AI personality and interaction style. */ import { BaseElement } from '../elements/BaseElement.js'; import { ElementType } from '../portfolio/types.js'; import { logger } from '../utils/logger.js'; import { SecureYamlParser } from '../security/secureYamlParser.js'; import { sanitizeGatekeeperPolicy } from '../handlers/mcp-aql/policies/ElementPolicies.js'; export class PersonaElement extends BaseElement { // instructions and content inherited from BaseElement (v2.0 dual-field architecture) filename; /** * Backward compatibility: provide unique_id as an alias for id */ get unique_id() { return this.id; } set unique_id(value) { this.id = value; } constructor(metadata, instructions = '', filename = '', metadataService, content = '') { super(ElementType.PERSONA, metadata, metadataService); this.instructions = instructions; this.content = content; this.filename = filename; // Ensure persona-specific metadata this.metadata = { ...this.metadata, triggers: metadata.triggers && metadata.triggers.length > 0 ? metadata.triggers : undefined, category: metadata.category || 'personal', age_rating: metadata.age_rating || 'all', content_flags: metadata.content_flags || [], ai_generated: metadata.ai_generated || false, generation_method: metadata.generation_method || 'human', price: metadata.price || 'free', revenue_split: metadata.revenue_split, // Preserve revenue_split if provided license: metadata.license || 'CC-BY-SA-4.0', created_date: metadata.created_date || new Date().toISOString().split('T')[0] }; } /** * Create PersonaElement from legacy Persona interface */ static fromLegacy(legacyPersona, metadataService) { const metadata = { name: legacyPersona.metadata.name, description: legacyPersona.metadata.description, author: legacyPersona.metadata.author, version: legacyPersona.metadata.version, triggers: legacyPersona.metadata.triggers, category: legacyPersona.metadata.category, age_rating: legacyPersona.metadata.age_rating, content_flags: legacyPersona.metadata.content_flags, ai_generated: legacyPersona.metadata.ai_generated, generation_method: legacyPersona.metadata.generation_method, price: legacyPersona.metadata.price, revenue_split: legacyPersona.metadata.revenue_split, license: legacyPersona.metadata.license, created_date: legacyPersona.metadata.created_date }; // Legacy personas: body content maps to instructions (it IS behavioral directives) const persona = new PersonaElement(metadata, legacyPersona.content, legacyPersona.filename, metadataService); // Preserve the legacy unique_id as the element id persona.id = legacyPersona.unique_id; return persona; } /** * Convert to legacy Persona interface for backward compatibility */ toLegacy() { const legacyMetadata = { name: this.metadata.name, description: this.metadata.description, unique_id: this.id, author: this.metadata.author, triggers: this.metadata.triggers, version: this.metadata.version, category: this.metadata.category, age_rating: this.metadata.age_rating, content_flags: this.metadata.content_flags, ai_generated: this.metadata.ai_generated, generation_method: this.metadata.generation_method, price: this.metadata.price, revenue_split: this.metadata.revenue_split, license: this.metadata.license, created_date: this.metadata.created_date }; return { metadata: legacyMetadata, content: this.instructions || this.content, filename: this.filename, unique_id: this.id }; } /** * Persona-specific validation */ validate() { const result = super.validate(); // Initialize arrays if not present if (!result.errors) result.errors = []; if (!result.warnings) result.warnings = []; // Add persona-specific validation rules // Instructions should not be empty (primary field for personas) const effectiveInstructions = this.instructions || this.content; if (!effectiveInstructions || effectiveInstructions.trim().length === 0) { result.errors.push({ field: 'instructions', message: 'Persona instructions cannot be empty', code: 'EMPTY_INSTRUCTIONS' }); } // Instructions should be reasonable length if (effectiveInstructions && effectiveInstructions.length > 10000) { result.warnings.push({ field: 'instructions', message: 'Persona instructions are very long, consider breaking them down', severity: 'medium' }); } // Triggers should be reasonable if (this.metadata.triggers && this.metadata.triggers.length > 10) { result.warnings.push({ field: 'triggers', message: 'Many triggers may cause activation conflicts', severity: 'medium' }); } // Check for adult content flags if (this.metadata.age_rating === '18+' && !this.metadata.content_flags?.includes('adult')) { result.warnings.push({ field: 'content_flags', message: '18+ content should include "adult" in content_flags', severity: 'low' }); } // Update the valid flag based on final errors result.valid = (result.errors?.length || 0) === 0; return result; } /** * Get content for serialization. * Returns instructions as the primary body text (v1 compat). * v2 format writes instructions to YAML frontmatter and content as body. */ getContent() { return this.instructions || this.content; } /** * Serialize persona to markdown format * Refactored to use base class pattern with getContent() */ serialize() { // Store original metadata const originalMetadata = this.metadata; // Add persona-specific fields to metadata temporarily // Cast to PersonaElementMetadata to include unique_id this.metadata = { ...originalMetadata, unique_id: this.id, // Include ID as unique_id for legacy compatibility triggers: originalMetadata.triggers, category: originalMetadata.category, age_rating: originalMetadata.age_rating, content_flags: originalMetadata.content_flags, ai_generated: originalMetadata.ai_generated, generation_method: originalMetadata.generation_method, price: originalMetadata.price, revenue_split: originalMetadata.revenue_split, license: originalMetadata.license, created_date: originalMetadata.created_date }; // Use base class serialize which now uses js-yaml const result = super.serialize(); // Restore original metadata this.metadata = originalMetadata; return result; } /** * Serialize to JSON format for internal use and testing */ serializeToJSON() { // Include persona-specific fields const data = { ...JSON.parse(super.serializeToJSON()), instructions: this.instructions, content: this.content }; return JSON.stringify(data, null, 2); } /** * Deserialize persona from markdown format */ deserialize(data) { try { const parsed = SecureYamlParser.safeMatter(data); const metadata = parsed.data; // Update metadata this.metadata = { ...this.metadata, name: metadata.name, description: metadata.description, author: metadata.author, version: metadata.version, triggers: metadata.triggers, category: metadata.category, age_rating: metadata.age_rating, content_flags: metadata.content_flags, ai_generated: metadata.ai_generated, generation_method: metadata.generation_method, price: metadata.price, revenue_split: metadata.revenue_split, license: metadata.license, created_date: metadata.created_date, gatekeeper: sanitizeGatekeeperPolicy(metadata.gatekeeper, metadata.name || 'unknown', 'persona', metadata), }; // Dual-field loading: detect v2 format (instructions in YAML frontmatter) const bodyText = parsed.content.trim(); if (metadata.instructions) { // v2 format: instructions from YAML, body text is content (reference material) this.instructions = metadata.instructions; this.content = bodyText; } else { // v1 format: body text maps to instructions (it IS behavioral directives) this.instructions = bodyText; this.content = ''; } // Update ID if provided if (metadata.unique_id) { this.id = metadata.unique_id; } this._isDirty = true; logger.debug(`Deserialized persona: ${this.metadata.name}`); } catch (error) { // Preserve original error context for better debugging const errorMessage = error instanceof Error ? error.message : String(error); const errorStack = error instanceof Error ? error.stack : undefined; logger.error('Failed to deserialize persona', { error: errorMessage, stack: errorStack, data: data.substring(0, 200) // Log first 200 chars for context }); // Re-throw with original error as cause const deserializeError = new Error(`PersonaElement deserialization failed: ${errorMessage}`); if (error instanceof Error) { deserializeError.cause = error; } throw deserializeError; } } /** * Persona activation lifecycle */ async activate() { logger.info(`Activating persona: ${this.metadata.name} (${this.id})`); // Personas don't need special activation logic currently // But this provides a hook for future enhancements await super.activate?.(); } /** * Persona deactivation lifecycle */ async deactivate() { logger.info(`Deactivating persona: ${this.metadata.name} (${this.id})`); // Personas don't need special deactivation logic currently // But this provides a hook for future enhancements await super.deactivate?.(); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGVyc29uYUVsZW1lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcGVyc29uYS9QZXJzb25hRWxlbWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFFSCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFekQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRXBELE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUVuRSxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSxpREFBaUQsQ0FBQztBQWtCM0YsTUFBTSxPQUFPLGNBQWUsU0FBUSxXQUFXO0lBQzdDLHFGQUFxRjtJQUM5RSxRQUFRLENBQVM7SUFHeEI7O09BRUc7SUFDSCxJQUFJLFNBQVM7UUFDWCxPQUFPLElBQUksQ0FBQyxFQUFFLENBQUM7SUFDakIsQ0FBQztJQUVELElBQUksU0FBUyxDQUFDLEtBQWE7UUFDekIsSUFBSSxDQUFDLEVBQUUsR0FBRyxLQUFLLENBQUM7SUFDbEIsQ0FBQztJQUVELFlBQVksUUFBeUMsRUFBRSxlQUF1QixFQUFFLEVBQUUsV0FBbUIsRUFBRSxFQUFFLGVBQWdDLEVBQUUsVUFBa0IsRUFBRTtRQUM3SixLQUFLLENBQUMsV0FBVyxDQUFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsZUFBZSxDQUFDLENBQUM7UUFDdEQsSUFBSSxDQUFDLFlBQVksR0FBRyxZQUFZLENBQUM7UUFDakMsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDdkIsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7UUFFekIsbUNBQW1DO1FBQ25DLElBQUksQ0FBQyxRQUFRLEdBQUc7WUFDZCxHQUFHLElBQUksQ0FBQyxRQUFRO1lBQ2hCLFFBQVEsRUFBRSxRQUFRLENBQUMsUUFBUSxJ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QUMsQ0FBQyxrQ0FBa0M7YUFDaEUsQ0FBQyxDQUFDO1lBRUgsd0NBQXdDO1lBQ3hDLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxLQUFLLENBQUMsMENBQTBDLFlBQVksRUFBRSxDQUFDLENBQUM7WUFDN0YsSUFBSSxLQUFLLFlBQVksS0FBSyxFQUFFLENBQUM7Z0JBQzNCLGdCQUFnQixDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7WUFDakMsQ0FBQztZQUNELE1BQU0sZ0JBQWdCLENBQUM7UUFDekIsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNhLEtBQUssQ0FBQyxRQUFRO1FBQzVCLE1BQU0sQ0FBQyxJQUFJLENBQUMsdUJBQXVCLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxLQUFLLElBQUksQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBRXRFLHlEQUF5RDtRQUN6RCxtREFBbUQ7UUFFbkQsTUFBTSxLQUFLLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQ7O09BRUc7SUFDYSxLQUFLLENBQUMsVUFBVTtRQUM5QixNQUFNLENBQUMsSUFBSSxDQUFDLHlCQUF5QixJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksS0FBSyxJQUFJLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUV4RSwyREFBMkQ7UUFDM0QsbURBQW1EO1FBRW5ELE1BQU0sS0FBSyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUM7SUFDN0IsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBQZXJzb25hIGVsZW1lbnQgY2xhc3MgaW1wbGVtZW50aW5nIElFbGVtZW50IGludGVyZmFjZS5cbiAqIFJlcHJlc2VudHMgYSBiZWhhdmlvcmFsIHByb2ZpbGUgdGhhdCBkZWZpbmVzIEFJIHBlcnNvbmFsaXR5IGFuZCBpbnRlcmFjdGlvbiBzdHlsZS5cbiAqL1xuXG5pbXBvcnQgeyBCYXNlRWxlbWVudCB9IGZyb20gJy4uL2VsZW1lbnRzL0Jhc2VFbGVtZW50LmpzJztcbmltcG9ydCB7IElFbGVtZW50LCBJRWxlbWVudE1ldGFkYXRhLCBFbGVtZW50VmFsaWRhdGlvblJlc3VsdCB9IGZyb20gJy4uL3R5cGVzL2VsZW1lbnRzL2luZGV4LmpzJztcbmltcG9ydCB7IEVsZW1lbnRUeXBlIH0gZnJvbSAnLi4vcG9ydGZvbGlvL3R5cGVzLmpzJztcbmltcG9ydCB7IFBlcnNvbmFNZXRhZGF0YSB9IGZyb20gJy4uL3R5cGVzL3BlcnNvbmEuanMnO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi4vdXRpbHMvbG9nZ2VyLmpzJztcbmltcG9ydCB7IFNlY3VyZVlhbWxQYXJzZXIgfSBmcm9tICcuLi9zZWN1cml0eS9zZWN1cmVZYW1sUGFyc2VyLmpzJztcbmltcG9ydCB7IE1ldGFkYXRhU2VydmljZSB9IGZyb20gJy4uL3NlcnZpY2VzL01ldGFkYXRhU2VydmljZS5qcyc7XG5pbXBvcnQgeyBzYW5pdGl6ZUdhdGVrZWVwZXJQb2xpY3kgfSBmcm9tICcuLi9oYW5kbGVycy9tY3AtYXFsL3BvbGljaWVzL0VsZW1lbnRQb2xpY2llcy5qcyc7XG5cbi8vIEV4dGVuZCBJRWxlbWVudE1ldGFkYXRhIHdpdGggcGVyc29uYS1zcGVjaWZpYyBmaWVsZHNcbmV4cG9ydCBpbnRlcmZhY2UgUGVyc29uYUVsZW1lbnRNZXRhZGF0YSBleHRlbmRzIElFbGVtZW50TWV0YWRhdGEge1xuICB0eXBlPzogRWxlbWVudFR5cGUuUEVSU09OQTsgICAgICAgICAgICAgICAvLyBQZXJzb25hIHR5cGUgY29uc3RyYWludCBmb3IgdHlwZSBzYWZldHlcbiAgdW5pcXVlX2lkPzogc3RyaW5nOyAgLy8gTGVnYWN5IElEIGZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5XG4gIHRyaWdnZXJzPzogc3RyaW5nW107XG4gIGNhdGVnb3J5Pzogc3RyaW5nO1xuICBhZ2VfcmF0aW5nPzogJ2FsbCcgfCAnMTMrJyB8ICcxOCsnO1xuICBjb250ZW50X2ZsYWdzPzogc3RyaW5nW107XG4gIGFpX2dlbmVyYXRlZD86IGJvb2xlYW47XG4gIGdlbmVyYXRpb25fbWV0aG9kPzogJ2h1bWFuJyB8ICdDaGF0R1BUJyB8ICdDbGF1ZGUnIHwgJ2h5YnJpZCc7XG4gIHByaWNlPzogc3RyaW5nO1xuICByZXZlbnVlX3NwbGl0Pzogc3RyaW5nO1xuICBsaWNlbnNlPzogc3RyaW5nO1xuICBjcmVhdGVkX2RhdGU/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjbGFzcyBQZXJzb25hRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IGltcGxlbWVudHMgSUVsZW1lbnQge1xuICAvLyBpbnN0cnVjdGlvbnMgYW5kIGNvbnRlbnQgaW5oZXJpdGVkIGZyb20gQmFzZUVsZW1lbnQgKHYyLjAgZHVhbC1maWVsZCBhcmNoaXRlY3R1cmUpXG4gIHB1YmxpYyBmaWxlbmFtZTogc3RyaW5nO1xuICBwdWJsaWMgZGVjbGFyZSBtZXRhZGF0YTogUGVyc29uYUVsZW1lbnRNZXRhZGF0YTtcblxuICAvKipcbiAgICogQmFja3dhcmQgY29tcGF0aWJpbGl0eTogcHJvdmlkZSB1bmlxdWVfaWQgYXMgYW4gYWxpYXMgZm9yIGlkXG4gICAqL1xuICBnZXQgdW5pcXVlX2lkKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuaWQ7XG4gIH1cblxuICBzZXQgdW5pcXVlX2lkKHZhbHVlOiBzdHJpbmcpIHtcbiAgICB0aGlzLmlkID0gdmFsdWU7XG4gIH1cblxuICBjb25zdHJ1Y3RvcihtZXRhZGF0YTogUGFydGlhbDxQZXJzb25hRWxlbWVudE1ldGFkYXRhPiwgaW5zdHJ1Y3Rpb25zOiBzdHJpbmcgPSAnJywgZmlsZW5hbWU6IHN0cmluZyA9ICcnLCBtZXRhZGF0YVNlcnZpY2U6IE1ldGFkYXRhU2VydmljZSwgY29udGVudDogc3RyaW5nID0gJycpIHtcbiAgICBzdXBlcihFbGVtZW50VHlwZS5QRVJTT05BLCBtZXRhZGF0YSwgbWV0YWRhdGFTZXJ2aWNlKTtcbiAgICB0aGlzLmluc3RydWN0aW9ucyA9IGluc3RydWN0aW9ucztcbiAgICB0aGlzLmNvbnRlbnQgPSBjb250ZW50O1xuICAgIHRoaXMuZmlsZW5hbWUgPSBmaWxlbmFtZTtcbiAgICBcbiAgICAvLyBFbnN1cmUgcGVyc29uYS1zcGVjaWZpYyBtZXRhZGF0YVxuICAgIHRoaXMubWV0YWRhdGEgPSB7XG4gICAgICAuLi50aGlzLm1ldGFkYXRhLFxuICAgICAgdHJpZ2dlcnM6IG1ldGFkYXRhLnRyaWdnZXJzICYmIG1ldGFkYXRhLnRyaWdnZXJzLmxlbmd0aCA+IDAgPyBtZXRhZGF0YS50cmlnZ2VycyA6IHVuZGVmaW5lZCxcbiAgICAgIGNhdGVnb3J5OiBtZXRhZGF0YS5jYXRlZ29yeSB8fCAncGVyc29uYWwnLFxuICAgICAgYWdlX3JhdGluZzogbWV0YWRhdGEuYWdlX3JhdGluZyB8fCAnYWxsJyxcbiAgICAgIGNvbnRlbnRfZmxhZ3M6IG1ldGFkYXRhLmNvbnRlbnRfZmxhZ3MgfHwgW10sXG4gICAgICBhaV9nZW5lcmF0ZWQ6IG1ldGFkYXRhLmFpX2dlbmVyYXRlZCB8fCBmYWxzZSxcbiAgICAgIGdlbmVyYXRpb25fbWV0aG9kOiBtZXRhZGF0YS5nZW5lcmF0aW9uX21ldGhvZCB8fCAnaHVtYW4nLFxuICAgICAgcHJpY2U6IG1ldGFkYXRhLnByaWNlIHx8ICdmcmVlJyxcbiAgICAgIHJldmVudWVfc3BsaXQ6IG1ldGFkYXRhLnJldmVudWVfc3BsaXQsICAvLyBQcmVzZXJ2ZSByZXZlbnVlX3NwbGl0IGlmIHByb3ZpZGVkXG4gICAgICBsaWNlbnNlOiBtZXRhZGF0YS5saWNlbnNlIHx8ICdDQy1CWS1TQS00LjAnLFxuICAgICAgY3JlYXRlZF9kYXRlOiBtZXRhZGF0YS5jcmVhdGVkX2RhdGUgfHwgbmV3IERhdGUoKS50b0lTT1N0cmluZygpLnNwbGl0KCdUJylbMF1cbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBQZXJzb25hRWxlbWVudCBmcm9tIGxlZ2FjeSBQZXJzb25hIGludGVyZmFjZVxuICAgKi9cbiAgc3RhdGljIGZyb21MZWdhY3kobGVnYWN5UGVyc29uYTogeyBtZXRhZGF0YTogUGVyc29uYU1ldGFkYXRhOyBjb250ZW50OiBzdHJpbmc7IGZpbGVuYW1lOiBzdHJpbmc7IHVuaXF1ZV9pZDogc3RyaW5nIH0sIG1ldGFkYXRhU2VydmljZTogTWV0YWRhdGFTZXJ2aWNlKTogUGVyc29uYUVsZW1lbnQge1xuICAgIGNvbnN0IG1ldGFkYXRhOiBQYXJ0aWFsPFBlcnNvbmFFbGVtZW50TWV0YWRhdGE+ID0ge1xuICAgICAgbmFtZTogbGVnYWN5UGVyc29uYS5tZXRhZGF0YS5uYW1lLFxuICAgICAgZGVzY3JpcHRpb246IGxlZ2FjeVBlcnNvbmEubWV0YWRhdGEuZGVzY3JpcHRpb24sXG4gICAgICBhdXRob3I6IGxlZ2FjeVBlcnNvbmEubWV0YWRhdGEuYXV0aG9yLFxuICAgICAgdmVyc2lvbjogbGVnYWN5UGVyc29uYS5tZXRhZGF0YS52ZXJzaW9uLFxuICAgICAgdHJpZ2dlcnM6IGxlZ2FjeVBlcnNvbmEubWV0YWRhdGEudHJpZ2dlcnMsXG4gICAgICBjYXRlZ29yeTogbGVnYWN5UGVyc29uYS5tZXRhZGF0YS5jYXRlZ29yeSxcbiAgICAgIGFnZV9yYXRpbmc6IGxlZ2FjeVBlcnNvbmEubWV0YWRhdGEuYWdlX3JhdGluZyBhcyBcImFsbFwiIHwgXCIxMytcIiB8IFwiMTgrXCIgfCB1bmRlZmluZWQsXG4gICAgICBjb250ZW50X2ZsYWdzOiBsZWdhY3lQZXJzb25hLm1ldGFkYXRhLmNvbnRlbnRfZmxhZ3MsXG4gICAgICBhaV9nZW5lcmF0ZWQ6IGxlZ2FjeVBlcnNvbmEubWV0YWRhdGEuYWlfZ2VuZXJhdGVkLFxuICAgICAgZ2VuZXJhdGlvbl9tZXRob2Q6IGxlZ2FjeVBlcnNvbmEubWV0YWRhdGEuZ2VuZXJhdGlvbl9tZXRob2QgYXMgXCJodW1hblwiIHwgXCJDaGF0R1BUXCIgfCBcIkNsYXVkZVwiIHwgXCJoeWJyaWRcIiB8IHVuZGVmaW5lZCxcbiAgICAgIHByaWNlOiBsZWdhY3lQZXJzb25hLm1ldGFkYXRhLnByaWNlLFxuICAgICAgcmV2ZW51ZV9zcGxpdDogbGVnYWN5UGVyc29uYS5tZXRhZGF0YS5yZXZlbnVlX3NwbGl0LFxuICAgICAgbGljZW5zZTogbGVnYWN5UGVyc29uYS5tZXRhZGF0YS5saWNlbnNlLFxuICAgICAgY3JlYXRlZF9kYXRlOiBsZWdhY3lQZXJzb25hLm1ldGFkYXRhLmNyZWF0ZWRfZGF0ZVxuICAgIH07XG5cbiAgICAvLyBMZWdhY3kgcGVyc29uYXM6IGJvZHkgY29udGVudCBtYXBzIHRvIGluc3RydWN0aW9ucyAoaXQgSVMgYmVoYXZpb3JhbCBkaXJlY3RpdmVzKVxuICAgIGNvbnN0IHBlcnNvbmEgPSBuZXcgUGVyc29uYUVsZW1lbnQobWV0YWRhdGEsIGxlZ2FjeVBlcnNvbmEuY29udGVudCwgbGVnYWN5UGVyc29uYS5maWxlbmFtZSwgbWV0YWRhdGFTZXJ2aWNlKTtcblxuICAgIC8vIFByZXNlcnZlIHRoZSBsZWdhY3kgdW5pcXVlX2lkIGFzIHRoZSBlbGVtZW50IGlkXG4gICAgcGVyc29uYS5pZCA9IGxlZ2FjeVBlcnNvbmEudW5pcXVlX2lkO1xuXG4gICAgcmV0dXJuIHBlcnNvbmE7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydCB0byBsZWdhY3kgUGVyc29uYSBpbnRlcmZhY2UgZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHlcbiAgICovXG4gIHRvTGVnYWN5KCk6IHsgbWV0YWRhdGE6IFBlcnNvbmFNZXRhZGF0YTsgY29udGVudDogc3RyaW5nOyBmaWxlbmFtZTogc3RyaW5nOyB1bmlxdWVfaWQ6IHN0cmluZyB9IHtcbiAgICBjb25zdCBsZWdhY3lNZXRhZGF0YTogUGVyc29uYU1ldGFkYXRhID0ge1xuICAgICAgbmFtZTogdGhpcy5tZXRhZGF0YS5uYW1lLFxuICAgICAgZGVzY3JpcHRpb246IHRoaXMubWV0YWRhdGEuZGVzY3JpcHRpb24sXG4gICAgICB1bmlxdWVfaWQ6IHRoaXMuaWQsXG4gICAgICBhdXRob3I6IHRoaXMubWV0YWRhdGEuYXV0aG9yLFxuICAgICAgdHJpZ2dlcnM6IHRoaXMubWV0YWRhdGEudHJpZ2dlcnMsXG4gICAgICB2ZXJzaW9uOiB0aGlzLm1ldGFkYXRhLnZlcnNpb24sXG4gICAgICBjYXRlZ29yeTogdGhpcy5tZXRhZGF0YS5jYXRlZ29yeSxcbiAgICAgIGFnZV9yYXRpbmc6IHRoaXMubWV0YWRhdGEuYWdlX3JhdGluZyxcbiAgICAgIGNvbnRlbnRfZmxhZ3M6IHRoaXMubWV0YWRhdGEuY29udGVudF9mbGFncyxcbiAgICAgIGFpX2dlbmVyYXRlZDogdGhpcy5tZXRhZGF0YS5haV9nZW5lcmF0ZWQsXG4gICAgICBnZW5lcmF0aW9uX21ldGhvZDogdGhpcy5tZXRhZGF0YS5nZW5lcmF0aW9uX21ldGhvZCxcbiAgICAgIHByaWNlOiB0aGlzLm1ldGFkYXRhLnByaWNlLFxuICAgICAgcmV2ZW51ZV9zcGxpdDogdGhpcy5tZXRhZGF0YS5yZXZlbnVlX3NwbGl0LFxuICAgICAgbGljZW5zZTogdGhpcy5tZXRhZGF0YS5saWNlbnNlLFxuICAgICAgY3JlYXRlZF9kYXRlOiB0aGlzLm1ldGFkYXRhLmNyZWF0ZWRfZGF0ZVxuICAgIH07XG5cbiAgICByZXR1cm4ge1xuICAgICAgbWV0YWRhdGE6IGxlZ2FjeU1ldGFkYXRhLFxuICAgICAgY29udGVudDogdGhpcy5pbnN0cnVjdGlvbnMgfHwgdGhpcy5jb250ZW50LFxuICAgICAgZmlsZW5hbWU6IHRoaXMuZmlsZW5hbWUsXG4gICAgICB1bmlxdWVfaWQ6IHRoaXMuaWRcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFBlcnNvbmEtc3BlY2lmaWMgdmFsaWRhdGlvblxuICAgKi9cbiAgcHVibGljIG92ZXJyaWRlIHZhbGlkYXRlKCk6IEVsZW1lbnRWYWxpZGF0aW9uUmVzdWx0IHtcbiAgICBjb25zdCByZXN1bHQgPSBzdXBlci52YWxpZGF0ZSgpO1xuICAgIFxuICAgIC8vIEluaXRpYWxpemUgYXJyYXlzIGlmIG5vdCBwcmVzZW50XG4gICAgaWYgKCFyZXN1bHQuZXJyb3JzKSByZXN1bHQuZXJyb3JzID0gW107XG4gICAgaWYgKCFyZXN1bHQud2FybmluZ3MpIHJlc3VsdC53YXJuaW5ncyA9IFtdO1xuICAgIFxuICAgIC8vIEFkZCBwZXJzb25hLXNwZWNpZmljIHZhbGlkYXRpb24gcnVsZXNcblxuICAgIC8vIEluc3RydWN0aW9ucyBzaG91bGQgbm90IGJlIGVtcHR5IChwcmltYXJ5IGZpZWxkIGZvciBwZXJzb25hcylcbiAgICBjb25zdCBlZmZlY3RpdmVJbnN0cnVjdGlvbnMgPSB0aGlzLmluc3RydWN0aW9ucyB8fCB0aGlzLmNvbnRlbnQ7XG4gICAgaWYgKCFlZmZlY3RpdmVJbnN0cnVjdGlvbnMgfHwgZWZmZWN0aXZlSW5zdHJ1Y3Rpb25zLnRyaW0oKS5sZW5ndGggPT09IDApIHtcbiAgICAgIHJlc3VsdC5lcnJvcnMucHVzaCh7XG4gICAgICAgIGZpZWxkOiAnaW5zdHJ1Y3Rpb25zJyxcbiAgICAgICAgbWVzc2FnZTogJ1BlcnNvbmEgaW5zdHJ1Y3Rpb25zIGNhbm5vdCBiZSBlbXB0eScsXG4gICAgICAgIGNvZGU6ICdFTVBUWV9JTlNUUlVDVElPTlMnXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBJbnN0cnVjdGlvbnMgc2hvdWxkIGJlIHJlYXNvbmFibGUgbGVuZ3RoXG4gICAgaWYgKGVmZmVjdGl2ZUluc3RydWN0aW9ucyAmJiBlZmZlY3RpdmVJbnN0cnVjdGlvbnMubGVuZ3RoID4gMTAwMDApIHtcbiAgICAgIHJlc3VsdC53YXJuaW5ncy5wdXNoKHtcbiAgICAgICAgZmllbGQ6ICdpbnN0cnVjdGlvbnMnLFxuICAgICAgICBtZXNzYWdlOiAnUGVyc29uYSBpbnN0cnVjdGlvbnMgYXJlIHZlcnkgbG9uZywgY29uc2lkZXIgYnJlYWtpbmcgdGhlbSBkb3duJyxcbiAgICAgICAgc2V2ZXJpdHk6ICdtZWRpdW0nXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBUcmlnZ2VycyBzaG91bGQgYmUgcmVhc29uYWJsZVxuICAgIGlmICh0aGlzLm1ldGFkYXRhLnRyaWdnZXJzICYmIHRoaXMubWV0YWRhdGEudHJpZ2dlcnMubGVuZ3RoID4gMTApIHtcbiAgICAgIHJlc3VsdC53YXJuaW5ncy5wdXNoKHtcbiAgICAgICAgZmllbGQ6ICd0cmlnZ2VycycsXG4gICAgICAgIG1lc3NhZ2U6ICdNYW55IHRyaWdnZXJzIG1heSBjYXVzZSBhY3RpdmF0aW9uIGNvbmZsaWN0cycsXG4gICAgICAgIHNldmVyaXR5OiAnbWVkaXVtJ1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIGFkdWx0IGNvbnRlbnQgZmxhZ3NcbiAgICBpZiAodGhpcy5tZXRhZGF0YS5hZ2VfcmF0aW5nID09PSAnMTgrJyAmJiAhdGhpcy5tZXRhZGF0YS5jb250ZW50X2ZsYWdzPy5pbmNsdWRlcygnYWR1bHQnKSkge1xuICAgICAgcmVzdWx0Lndhcm5pbmdzLnB1c2goe1xuICAgICAgICBmaWVsZDogJ2NvbnRlbnRfZmxhZ3MnLFxuICAgICAgICBtZXNzYWdlOiAnMTgrIGNvbnRlbnQgc2hvdWxkIGluY2x1ZGUgXCJhZHVsdFwiIGluIGNvbnRlbnRfZmxhZ3MnLFxuICAgICAgICBzZXZlcml0eTogJ2xvdydcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIFVwZGF0ZSB0aGUgdmFsaWQgZmxhZyBiYXNlZCBvbiBmaW5hbCBlcnJvcnNcbiAgICByZXN1bHQudmFsaWQgPSAocmVzdWx0LmVycm9ycz8ubGVuZ3RoIHx8IDApID09PSAwO1xuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgY29udGVudCBmb3Igc2VyaWFsaXphdGlvbi5cbiAgICogUmV0dXJucyBpbnN0cnVjdGlvbnMgYXMgdGhlIHByaW1hcnkgYm9keSB0ZXh0ICh2MSBjb21wYXQpLlxuICAgKiB2MiBmb3JtYXQgd3JpdGVzIGluc3RydWN0aW9ucyB0byBZQU1MIGZyb250bWF0dGVyIGFuZCBjb250ZW50IGFzIGJvZHkuXG4gICAqL1xuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgZ2V0Q29udGVudCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmluc3RydWN0aW9ucyB8fCB0aGlzLmNvbnRlbnQ7XG4gIH1cblxuICAvKipcbiAgICogU2VyaWFsaXplIHBlcnNvbmEgdG8gbWFya2Rvd24gZm9ybWF0XG4gICAqIFJlZmFjdG9yZWQgdG8gdXNlIGJhc2UgY2xhc3MgcGF0dGVybiB3aXRoIGdldENvbnRlbnQoKVxuICAgKi9cbiAgcHVibGljIG92ZXJyaWRlIHNlcmlhbGl6ZSgpOiBzdHJpbmcge1xuICAgIC8vIFN0b3JlIG9yaWdpbmFsIG1ldGFkYXRhXG4gICAgY29uc3Qgb3JpZ2luYWxNZXRhZGF0YSA9IHRoaXMubWV0YWRhdGE7XG4gICAgXG4gICAgLy8gQWRkIHBlcnNvbmEtc3BlY2lmaWMgZmllbGRzIHRvIG1ldGFkYXRhIHRlbXBvcmFyaWx5XG4gICAgLy8gQ2FzdCB0byBQZXJzb25hRWxlbWVudE1ldGFkYXRhIHRvIGluY2x1ZGUgdW5pcXVlX2lkXG4gICAgdGhpcy5tZXRhZGF0YSA9IHtcbiAgICAgIC4uLm9yaWdpbmFsTWV0YWRhdGEsXG4gICAgICB1bmlxdWVfaWQ6IHRoaXMuaWQsICAvLyBJbmNsdWRlIElEIGFzIHVuaXF1ZV9pZCBmb3IgbGVnYWN5IGNvbXBhdGliaWxpdHlcbiAgICAgIHRyaWdnZXJzOiAob3JpZ2luYWxNZXRhZGF0YSBhcyBQZXJzb25hRWxlbWVudE1ldGFkYXRhKS50cmlnZ2VycyxcbiAgICAgIGNhdGVnb3J5OiAob3JpZ2luYWxNZXRhZGF0YSBhcyBQZXJzb25hRWxlbWVudE1ldGFkYXRhKS5jYXRlZ29yeSxcbiAgICAgIGFnZV9yYXRpbmc6IChvcmlnaW5hbE1ldGFkYXRhIGFzIFBlcnNvbmFFbGVtZW50TWV0YWRhdGEpLmFnZV9yYXRpbmcsXG4gICAgICBjb250ZW50X2ZsYWdzOiAob3JpZ2luYWxNZXRhZGF0YSBhcyBQZXJzb25hRWxlbWVudE1ldGFkYXRhKS5jb250ZW50X2ZsYWdzLFxuICAgICAgYWlfZ2VuZXJhdGVkOiAob3JpZ2luYWxNZXRhZGF0YSBhcyBQZXJzb25hRWxlbWVudE1ldGFkYXRhKS5haV9nZW5lcmF0ZWQsXG4gICAgICBnZW5lcmF0aW9uX21ldGhvZDogKG9yaWdpbmFsTWV0YWRhdGEgYXMgUGVyc29uYUVsZW1lbnRNZXRhZGF0YSkuZ2VuZXJhdGlvbl9tZXRob2QsXG4gICAgICBwcmljZTogKG9yaWdpbmFsTWV0YWRhdGEgYXMgUGVyc29uYUVsZW1lbnRNZXRhZGF0YSkucHJpY2UsXG4gICAgICByZXZlbnVlX3NwbGl0OiAob3JpZ2luYWxNZXRhZGF0YSBhcyBQZXJzb25hRWxlbWVudE1ldGFkYXRhKS5yZXZlbnVlX3NwbGl0LFxuICAgICAgbGljZW5zZTogKG9yaWdpbmFsTWV0YWRhdGEgYXMgUGVyc29uYUVsZW1lbnRNZXRhZGF0YSkubGljZW5zZSxcbiAgICAgIGNyZWF0ZWRfZGF0ZTogKG9yaWdpbmFsTWV0YWRhdGEgYXMgUGVyc29uYUVsZW1lbnRNZXRhZGF0YSkuY3JlYXRlZF9kYXRlXG4gICAgfTtcbiAgICBcbiAgICAvLyBVc2UgYmFzZSBjbGFzcyBzZXJpYWxpemUgd2hpY2ggbm93IHVzZXMganMteWFtbFxuICAgIGNvbnN0IHJlc3VsdCA9IHN1cGVyLnNlcmlhbGl6ZSgpO1xuICAgIFxuICAgIC8vIFJlc3RvcmUgb3JpZ2luYWwgbWV0YWRhdGFcbiAgICB0aGlzLm1ldGFkYXRhID0gb3JpZ2luYWxNZXRhZGF0YTtcbiAgICBcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG4gIFxuICAvKipcbiAgICogU2VyaWFsaXplIHRvIEpTT04gZm9ybWF0IGZvciBpbnRlcm5hbCB1c2UgYW5kIHRlc3RpbmdcbiAgICovXG4gIHB1YmxpYyBvdmVycmlkZSBzZXJpYWxpemVUb0pTT04oKTogc3RyaW5nIHtcbiAgICAvLyBJbmNsdWRlIHBlcnNvbmEtc3BlY2lmaWMgZmllbGRzXG4gICAgY29uc3QgZGF0YSA9IHtcbiAgICAgIC4uLkpTT04ucGFyc2Uoc3VwZXIuc2VyaWFsaXplVG9KU09OKCkpLFxuICAgICAgaW5zdHJ1Y3Rpb25zOiB0aGlzLmluc3RydWN0aW9ucyxcbiAgICAgIGNvbnRlbnQ6IHRoaXMuY29udGVudFxuICAgIH07XG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGRhdGEsIG51bGwsIDIpO1xuICB9XG5cbiAgLyoqXG4gICAqIERlc2VyaWFsaXplIHBlcnNvbmEgZnJvbSBtYXJrZG93biBmb3JtYXRcbiAgICovXG4gIHB1YmxpYyBvdmVycmlkZSBkZXNlcmlhbGl6ZShkYXRhOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcGFyc2VkID0gU2VjdXJlWWFtbFBhcnNlci5zYWZlTWF0dGVyKGRhdGEpO1xuICAgICAgY29uc3QgbWV0YWRhdGEgPSBwYXJzZWQuZGF0YSBhcyBQZXJzb25hTWV0YWRhdGE7XG4gICAgICBcbiAgICAgIC8vIFVwZGF0ZSBtZXRhZGF0YVxuICAgICAgdGhpcy5tZXRhZGF0YSA9IHtcbiAgICAgICAgLi4udGhpcy5tZXRhZGF0YSxcbiAgICAgICAgbmFtZTogbWV0YWRhdGEubmFtZSxcbiAgICAgICAgZGVzY3JpcHRpb246IG1ldGFkYXRhLmRlc2NyaXB0aW9uLFxuICAgICAgICBhdXRob3I6IG1ldGFkYXRhLmF1dGhvcixcbiAgICAgICAgdmVyc2lvbjogbWV0YWRhdGEudmVyc2lvbixcbiAgICAgICAgdHJpZ2dlcnM6IG1ldGFkYXRhLnRyaWdnZXJzLFxuICAgICAgICBjYXRlZ29yeTogbWV0YWRhdGEuY2F0ZWdvcnksXG4gICAgICAgIGFnZV9yYXRpbmc6IG1ldGFkYXRhLmFnZV9yYXRpbmcgYXMgXCJhbGxcIiB8IFwiMTMrXCIgfCBcIjE4K1wiIHwgdW5kZWZpbmVkLFxuICAgICAgICBjb250ZW50X2ZsYWdzOiBtZXRhZGF0YS5jb250ZW50X2ZsYWdzLFxuICAgICAgICBhaV9nZW5lcmF0ZWQ6IG1ldGFkYXRhLmFpX2dlbmVyYXRlZCxcbiAgICAgICAgZ2VuZXJhdGlvbl9tZXRob2Q6IG1ldGFkYXRhLmdlbmVyYXRpb25fbWV0aG9kIGFzIFwiaHVtYW5cIiB8IFwiQ2hhdEdQVFwiIHwgXCJDbGF1ZGVcIiB8IFwiaHlicmlkXCIgfCB1bmRlZmluZWQsXG4gICAgICAgIHByaWNlOiBtZXRhZGF0YS5wcmljZSxcbiAgICAgICAgcmV2ZW51ZV9zcGxpdDogbWV0YWRhdGEucmV2ZW51ZV9zcGxpdCxcbiAgICAgICAgbGljZW5zZTogbWV0YWRhdGEubGljZW5zZSxcbiAgICAgICAgY3JlYXRlZF9kYXRlOiBtZXRhZGF0YS5jcmVhdGVkX2RhdGUsXG4gICAgICAgIGdhdGVrZWVwZXI6IHNhbml0aXplR2F0ZWtlZXBlclBvbGljeSgobWV0YWRhdGEgYXMgYW55KS5nYXRla2VlcGVyLCBtZXRhZGF0YS5uYW1lIHx8ICd1bmtub3duJywgJ3BlcnNvbmEnLCBtZXRhZGF0YSBhcyB1bmtub3duIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KSxcbiAgICAgIH07XG5cbiAgICAgIC8vIER1YWwtZmllbGQgbG9hZGluZzogZGV0ZWN0IHYyIGZvcm1hdCAoaW5zdHJ1Y3Rpb25zIGluIFlBTUwgZnJvbnRtYXR0ZXIpXG4gICAgICBjb25zdCBib2R5VGV4dCA9IHBhcnNlZC5jb250ZW50LnRyaW0oKTtcbiAgICAgIGlmIChtZXRhZGF0YS5pbnN0cnVjdGlvbnMpIHtcbiAgICAgICAgLy8gdjIgZm9ybWF0OiBpbnN0cnVjdGlvbnMgZnJvbSBZQU1MLCBib2R5IHRleHQgaXMgY29udGVudCAocmVmZXJlbmNlIG1hdGVyaWFsKVxuICAgICAgICB0aGlzLmluc3RydWN0aW9ucyA9IG1ldGFkYXRhLmluc3RydWN0aW9ucztcbiAgICAgICAgdGhpcy5jb250ZW50ID0gYm9keVRleHQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyB2MSBmb3JtYXQ6IGJvZHkgdGV4dCBtYXBzIHRvIGluc3RydWN0aW9ucyAoaXQgSVMgYmVoYXZpb3JhbCBkaXJlY3RpdmVzKVxuICAgICAgICB0aGlzLmluc3RydWN0aW9ucyA9IGJvZHlUZXh0O1xuICAgICAgICB0aGlzLmNvbnRlbnQgPSAnJztcbiAgICAgIH1cblxuICAgICAgLy8gVXBkYXRlIElEIGlmIHByb3ZpZGVkXG4gICAgICBpZiAobWV0YWRhdGEudW5pcXVlX2lkKSB7XG4gICAgICAgIHRoaXMuaWQgPSBtZXRhZGF0YS51bmlxdWVfaWQ7XG4gICAgICB9XG4gICAgICBcbiAgICAgIHRoaXMuX2lzRGlydHkgPSB0cnVlO1xuICAgICAgbG9nZ2VyLmRlYnVnKGBEZXNlcmlhbGl6ZWQgcGVyc29uYTogJHt0aGlzLm1ldGFkYXRhLm5hbWV9YCk7XG4gICAgICBcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgLy8gUHJlc2VydmUgb3JpZ2luYWwgZXJyb3IgY29udGV4dCBmb3IgYmV0dGVyIGRlYnVnZ2luZ1xuICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpO1xuICAgICAgY29uc3QgZXJyb3JTdGFjayA9IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5zdGFjayA6IHVuZGVmaW5lZDtcbiAgICAgIFxuICAgICAgbG9nZ2VyLmVycm9yKCdGYWlsZWQgdG8gZGVzZXJpYWxpemUgcGVyc29uYScsIHsgXG4gICAgICAgIGVycm9yOiBlcnJvck1lc3NhZ2UsXG4gICAgICAgIHN0YWNrOiBlcnJvclN0YWNrLFxuICAgICAgICBkYXRhOiBkYXRhLnN1YnN0cmluZygwLCAyMDApIC8vIExvZyBmaXJzdCAyMDAgY2hhcnMgZm9yIGNvbnRleHRcbiAgICAgIH0pO1xuICAgICAgXG4gICAgICAvLyBSZS10aHJvdyB3aXRoIG9yaWdpbmFsIGVycm9yIGFzIGNhdXNlXG4gICAgICBjb25zdCBkZXNlcmlhbGl6ZUVycm9yID0gbmV3IEVycm9yKGBQZXJzb25hRWxlbWVudCBkZXNlcmlhbGl6YXRpb24gZmFpbGVkOiAke2Vycm9yTWVzc2FnZX1gKTtcbiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIGRlc2VyaWFsaXplRXJyb3IuY2F1c2UgPSBlcnJvcjtcbiAgICAgIH1cbiAgICAgIHRocm93IGRlc2VyaWFsaXplRXJyb3I7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBlcnNvbmEgYWN0aXZhdGlvbiBsaWZlY3ljbGVcbiAgICovXG4gIHB1YmxpYyBvdmVycmlkZSBhc3luYyBhY3RpdmF0ZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsb2dnZXIuaW5mbyhgQWN0aXZhdGluZyBwZXJzb25hOiAke3RoaXMubWV0YWRhdGEubmFtZX0gKCR7dGhpcy5pZH0pYCk7XG4gICAgXG4gICAgLy8gUGVyc29uYXMgZG9uJ3QgbmVlZCBzcGVjaWFsIGFjdGl2YXRpb24gbG9naWMgY3VycmVudGx5XG4gICAgLy8gQnV0IHRoaXMgcHJvdmlkZXMgYSBob29rIGZvciBmdXR1cmUgZW5oYW5jZW1lbnRzXG4gICAgXG4gICAgYXdhaXQgc3VwZXIuYWN0aXZhdGU/LigpO1xuICB9XG5cbiAgLyoqXG4gICAqIFBlcnNvbmEgZGVhY3RpdmF0aW9uIGxpZmVjeWNsZVxuICAgKi9cbiAgcHVibGljIG92ZXJyaWRlIGFzeW5jIGRlYWN0aXZhdGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbG9nZ2VyLmluZm8oYERlYWN0aXZhdGluZyBwZXJzb25hOiAke3RoaXMubWV0YWRhdGEubmFtZX0gKCR7dGhpcy5pZH0pYCk7XG4gICAgXG4gICAgLy8gUGVyc29uYXMgZG9uJ3QgbmVlZCBzcGVjaWFsIGRlYWN0aXZhdGlvbiBsb2dpYyBjdXJyZW50bHlcbiAgICAvLyBCdXQgdGhpcyBwcm92aWRlcyBhIGhvb2sgZm9yIGZ1dHVyZSBlbmhhbmNlbWVudHNcbiAgICBcbiAgICBhd2FpdCBzdXBlci5kZWFjdGl2YXRlPy4oKTtcbiAgfVxufVxuIl19