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.

393 lines 55.8 kB
/** * AgentActivationStrategy - Strategy for agent element activation * * Handles activation, deactivation, and status tracking for agent elements. * Uses "execution" strategy with state file management. * * SECURITY & CONSISTENCY IMPROVEMENTS: * - Security logging for activation errors (Issue #24 - Medium Priority) * - Activation rollback on critical failures (Issue #24 - Medium Priority) * - Optimistic locking for state updates (Issue #24 - Medium Priority) */ import { BaseActivationStrategy } from './BaseActivationStrategy.js'; import { SecurityMonitor } from '../../security/securityMonitor.js'; import { logger } from '../../utils/logger.js'; export class AgentActivationStrategy extends BaseActivationStrategy { agentManager; constructor(agentManager) { super(); this.agentManager = agentManager; } /** * Activate an agent with execution strategy * Executes agent logic, updates state file, and tracks activation * * IMPROVEMENT: Enhanced error handling with security logging and rollback (Issue #24) */ async activate(name, context) { // Use the manager's activation method which tracks active agents const result = await this.agentManager.activateAgent(name); if (!result.success || !result.agent) { return this.createNotFoundResponse(name, 'Agent'); } const agent = result.agent; // Extract optional goal from context const goal = context?.goal || context?.goals?.[0]; // Execute agent logic (goals/decisions) // For now, this is a side-effect activation that updates state const state = agent.getState(); const executionSummary = []; // Track if we need to rollback activation on critical failure let criticalFailure = false; if (goal) { // If goal provided, add it to the agent's goals try { agent.addGoal({ description: goal.description || goal, priority: goal.priority || 'medium', importance: goal.importance || 5, urgency: goal.urgency || 5 }); executionSummary.push(`Goal added: ${goal.description || goal}`); } catch (error) { // FIX: Enhanced error logging with security monitoring (Issue #24) const errorMessage = error instanceof Error ? error.message : 'Could not add goal'; // Log to security monitor for audit trail SecurityMonitor.logSecurityEvent({ type: 'AGENT_ACTIVATION_FAILED', severity: 'MEDIUM', source: 'AgentActivationStrategy.activate', details: `Failed to add goal during agent activation: ${errorMessage}`, additionalData: { agentName: name, goalDescription: goal.description || goal, error: errorMessage } }); // Log to standard logger for debugging logger.warn(`Goal addition failed during agent activation`, { agentName: name, error: errorMessage }); executionSummary.push(`Note: ${errorMessage}`); // Determine if this is a critical failure requiring rollback // Critical failures: validation errors that indicate bad input or security issues if (error instanceof Error && (errorMessage.includes('harmful content') || errorMessage.includes('security') || errorMessage.includes('Maximum number of goals'))) { criticalFailure = true; } } } // FIX: Rollback activation on critical failures (Issue #24) if (criticalFailure) { logger.error(`Critical failure during agent activation, rolling back`, { agentName: name }); // Deactivate the agent to rollback await this.agentManager.deactivateAgent(name); // Log security event for rollback SecurityMonitor.logSecurityEvent({ type: 'AGENT_ACTIVATION_ROLLBACK', severity: 'HIGH', source: 'AgentActivationStrategy.activate', details: `Agent activation rolled back due to critical failure`, additionalData: { agentName: name, reason: 'Critical goal addition failure' } }); // Return error response return { content: [{ type: "text", text: `❌ Agent activation failed and was rolled back\n\nCritical error occurred during goal addition. Please review the goal parameters and try again.` }] }; } // FIX: Optimistic locking for state updates (Issue #24) // Use public persistState API which implements Option C pattern (Issue #123) const filename = agent.metadata.name; try { // Save state with atomic write and proper version handling await this.agentManager.persistState(filename); const currentState = agent.getState(); logger.debug(`Agent state persisted successfully`, { agentName: name, sessionCount: currentState.sessionCount, goalCount: currentState.goals.length }); } catch (error) { // State save failure - log and continue (agent is still activated) const errorMessage = error instanceof Error ? error.message : 'Unknown error'; SecurityMonitor.logSecurityEvent({ type: 'MEMORY_SAVE_FAILED', // Using existing event type for state save failures severity: 'MEDIUM', source: 'AgentActivationStrategy.activate', details: `Failed to save agent state after activation: ${errorMessage}`, additionalData: { agentName: name, error: errorMessage } }); logger.warn(`Agent state save failed, but agent remains activated`, { agentName: name, error: errorMessage }); executionSummary.push(`Warning: State persistence failed - ${errorMessage}`); } // Build execution response const parts = [ goal ? `✅ Agent activated and executed goal: ${goal.description || goal}` : `✅ Agent activated successfully`, '' ]; // Add outcome description for test expectations if (goal) { parts.push('Agent activates with initial goals loaded'); } else { parts.push('Agent becomes active, increments session count'); } parts.push(''); parts.push(`**Session**: #${state.sessionCount + 1}`); parts.push(...this.formatV1Fields(agent.metadata, agent.extensions)); if (executionSummary.length > 0) { parts.push(''); parts.push('**Execution Summary**:'); executionSummary.forEach(line => parts.push(`- ${line}`)); } const activeGoals = agent.getState().goals.filter((g) => g.status === 'in_progress'); if (activeGoals.length > 0) { parts.push(''); parts.push(`**Active Goals**: ${activeGoals.length}`); } parts.push(''); parts.push('Agent execution completed'); // Issue #642: Fail-safe warning for CLI restrictions const restrictionWarning = this.formatRestrictionWarning(agent.metadata); if (restrictionWarning) { parts.push(restrictionWarning); } const gatekeeperWarning = this.formatGatekeeperValidityWarning(agent.metadata); if (gatekeeperWarning) { parts.push(gatekeeperWarning); } return { content: [{ type: "text", text: parts.join('\n') }] }; } /** * Deactivate an agent * * @throws {ElementNotFoundError} When agent does not exist * @see Issue #275 - Handlers return success=true for missing elements */ async deactivate(name) { const result = await this.agentManager.deactivateAgent(name); if (!result.success) { this.throwNotFoundError(name, 'Agent'); } return this.createSuccessResponse(result.message); } /** * Get all active agents */ async getActiveElements() { // Use the manager's method to get active agents directly const activeAgents = await this.agentManager.getActiveAgents(); if (activeAgents.length === 0) { return { content: [{ type: "text", text: "🤖 No active agents" }] }; } const agentList = activeAgents.map(a => { const state = a.getState(); const goals = state.goals?.length || 0; return `🤖 ${a.metadata.name} (${goals} active goals)`; }).join('\n'); return { content: [{ type: "text", text: `Active agents:\n${agentList}` }] }; } /** * Format v1 agent fields (specializations, decisionFramework, riskTolerance) * for display. Only includes fields that are explicitly set — avoids showing * phantom defaults on v2 agents. (Issue #749) */ formatV1Fields(metadata, extensions) { // Issue #749: V2 agents should not show V1 defaults. // `goal` (singular, AgentGoalConfig) is the definitive V2 marker — it's // required on AgentMetadataV2 and never present on V1 agents (which use // `goals` plural). The Agent constructor always defaults decisionFramework // and riskTolerance, so checking truthiness alone shows phantom values. if (metadata.goal) { return []; } const lines = []; const specs = metadata.specializations; const framework = extensions?.decisionFramework ?? metadata.decisionFramework; const risk = extensions?.riskTolerance ?? metadata.riskTolerance; if (specs?.length > 0) { lines.push(`**Specializations**: ${specs.join(', ')}`); } if (framework) { lines.push(`**Decision Framework**: ${framework}`); } if (risk) { lines.push(`**Risk Tolerance**: ${risk}`); } return lines; } /** * Get detailed information about an agent * Extracted from ElementCRUDHandler.ts lines 730-770 */ async getElementDetails(name) { // Use flexible finding to support both display name and filename const allAgents = await this.agentManager.list(); const agent = await this.findElementFlexibly(name, allAgents); if (!agent) { this.throwNotFoundError(name, 'Agent'); } const metadata = agent.metadata; const details = [ `🤖 **${agent.metadata.name}**`, `${agent.metadata.description}`, ``, `**Status**: ${agent.getStatus()}` ]; details.push(...this.formatV1Fields(metadata)); // V2 fields if (metadata.goal) { details.push(''); details.push('**Goal Configuration**:'); details.push(`- Template: ${metadata.goal.template}`); if (metadata.goal.parameters && metadata.goal.parameters.length > 0) { details.push(`- Parameters: ${metadata.goal.parameters.length} defined`); metadata.goal.parameters.forEach((param) => { const required = param.required ? 'required' : 'optional'; details.push(` - ${param.name} (${param.type}, ${required})`); }); } else { details.push('- Parameters: none'); } if (metadata.goal.successCriteria && metadata.goal.successCriteria.length > 0) { details.push(`- Success Criteria: ${metadata.goal.successCriteria.length} defined`); } } if (metadata.activates) { details.push(''); details.push('**Activates**:'); const elementTypes = Object.keys(metadata.activates); elementTypes.forEach(type => { const elements = metadata.activates[type]; if (elements && elements.length > 0) { details.push(`- ${type}: ${elements.join(', ')}`); } }); } if (metadata.tools) { details.push(''); details.push('**Tools**:'); if (metadata.tools.allowed && metadata.tools.allowed.length > 0) { details.push(`- Allowed: ${metadata.tools.allowed.length} tools`); } if (metadata.tools.denied && metadata.tools.denied.length > 0) { details.push(`- Denied: ${metadata.tools.denied.length} tools`); } } if (metadata.systemPrompt) { details.push(''); details.push('**System Prompt**:'); const truncated = metadata.systemPrompt.length > 100 ? `${metadata.systemPrompt.substring(0, 100)}...` : metadata.systemPrompt; details.push(truncated); } if (metadata.autonomy) { details.push(''); details.push('**Autonomy Configuration**:'); if (metadata.autonomy.riskTolerance) { details.push(`- Risk Tolerance: ${metadata.autonomy.riskTolerance}`); } if (metadata.autonomy.maxAutonomousSteps !== undefined) { const stepsLabel = metadata.autonomy.maxAutonomousSteps === 0 ? 'unlimited' : metadata.autonomy.maxAutonomousSteps; details.push(`- Max Autonomous Steps: ${stepsLabel}`); } if (metadata.autonomy.requiresApproval && metadata.autonomy.requiresApproval.length > 0) { details.push(`- Requires Approval: ${metadata.autonomy.requiresApproval.length} patterns`); } if (metadata.autonomy.autoApprove && metadata.autonomy.autoApprove.length > 0) { details.push(`- Auto Approve: ${metadata.autonomy.autoApprove.length} patterns`); } } // Issue #722: Display resilience policy if (metadata.resilience) { details.push(''); details.push('**Resilience Policy**:'); if (metadata.resilience.onStepLimitReached) { details.push(`- On Step Limit Reached: ${metadata.resilience.onStepLimitReached}`); } if (metadata.resilience.onExecutionFailure) { details.push(`- On Execution Failure: ${metadata.resilience.onExecutionFailure}`); } if (metadata.resilience.maxRetries !== undefined) { details.push(`- Max Retries: ${metadata.resilience.maxRetries}`); } if (metadata.resilience.maxContinuations !== undefined) { details.push(`- Max Continuations: ${metadata.resilience.maxContinuations}`); } // Issue #749: Display retryBackoff and preserveState (were missing) if (metadata.resilience.retryBackoff) { details.push(`- Retry Backoff: ${metadata.resilience.retryBackoff}`); } if (metadata.resilience.preserveState !== undefined) { details.push(`- Preserve State: ${metadata.resilience.preserveState}`); } } // Issue #722: Display tags and triggers if (metadata.tags && metadata.tags.length > 0) { details.push(''); details.push(`**Tags**: ${metadata.tags.join(', ')}`); } if (metadata.triggers && metadata.triggers.length > 0) { details.push(`**Triggers**: ${metadata.triggers.join(', ')}`); } details.push(''); details.push('**Instructions**:'); details.push(agent.instructions || agent.extensions?.instructions || 'No instructions available'); if (agent.content?.trim()) { details.push(''); details.push('**Reference:**'); details.push(agent.content); } const agentState = agent.state; if (agentState?.goals && agentState.goals.length > 0) { details.push('', '**Current Goals**:'); agentState.goals.forEach((g) => { details.push(`- ${g.description} (${g.status})`); }); } return { content: [{ type: "text", text: details.join('\n') }] }; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQWdlbnRBY3RpdmF0aW9uU3RyYXRlZ3kuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaGFuZGxlcnMvc3RyYXRlZ2llcy9BZ2VudEFjdGl2YXRpb25TdHJhdGVneS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7OztHQVVHO0FBR0gsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFFckUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQ3BFLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUUvQyxNQUFNLE9BQU8sdUJBQXdCLFNBQVEsc0JBQXNCO0lBQ3BDO0lBQTdCLFlBQTZCLFlBQTBCO1FBQ3JELEtBQUssRUFBRSxDQUFDO1FBRG1CLGlCQUFZLEdBQVosWUFBWSxDQUFjO0lBRXZELENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBWSxFQUFFLE9BQTZCO1FBQ3hELGlFQUFpRTtRQUNqRSxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRTNELElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3JDLE9BQU8sSUFBSSxDQUFDLHNCQUFzQixDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNwRCxDQUFDO1FBRUQsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQztRQUUzQixxQ0FBcUM7UUFDckMsTUFBTSxJQUFJLEdBQUcsT0FBTyxFQUFFLElBQUksSUFBSSxPQUFPLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFbEQsd0NBQXdDO1FBQ3hDLCtEQUErRDtRQUMvRCxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsUUFBUSxF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QUUsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7aUJBQ3pCLENBQUM7U0FDSCxDQUFDO0lBQ0osQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBBZ2VudEFjdGl2YXRpb25TdHJhdGVneSAtIFN0cmF0ZWd5IGZvciBhZ2VudCBlbGVtZW50IGFjdGl2YXRpb25cbiAqXG4gKiBIYW5kbGVzIGFjdGl2YXRpb24sIGRlYWN0aXZhdGlvbiwgYW5kIHN0YXR1cyB0cmFja2luZyBmb3IgYWdlbnQgZWxlbWVudHMuXG4gKiBVc2VzIFwiZXhlY3V0aW9uXCIgc3RyYXRlZ3kgd2l0aCBzdGF0ZSBmaWxlIG1hbmFnZW1lbnQuXG4gKlxuICogU0VDVVJJVFkgJiBDT05TSVNURU5DWSBJTVBST1ZFTUVOVFM6XG4gKiAtIFNlY3VyaXR5IGxvZ2dpbmcgZm9yIGFjdGl2YXRpb24gZXJyb3JzIChJc3N1ZSAjMjQgLSBNZWRpdW0gUHJpb3JpdHkpXG4gKiAtIEFjdGl2YXRpb24gcm9sbGJhY2sgb24gY3JpdGljYWwgZmFpbHVyZXMgKElzc3VlICMyNCAtIE1lZGl1bSBQcmlvcml0eSlcbiAqIC0gT3B0aW1pc3RpYyBsb2NraW5nIGZvciBzdGF0ZSB1cGRhdGVzIChJc3N1ZSAjMjQgLSBNZWRpdW0gUHJpb3JpdHkpXG4gKi9cblxuaW1wb3J0IHsgQWdlbnRNYW5hZ2VyIH0gZnJvbSAnLi4vLi4vZWxlbWVudHMvYWdlbnRzL0FnZW50TWFuYWdlci5qcyc7XG5pbXBvcnQgeyBCYXNlQWN0aXZhdGlvblN0cmF0ZWd5IH0gZnJvbSAnLi9CYXNlQWN0aXZhdGlvblN0cmF0ZWd5LmpzJztcbmltcG9ydCB7IEVsZW1lbnRBY3RpdmF0aW9uU3RyYXRlZ3ksIE1DUFJlc3BvbnNlIH0gZnJvbSAnLi9FbGVtZW50QWN0aXZhdGlvblN0cmF0ZWd5LmpzJztcbmltcG9ydCB7IFNlY3VyaXR5TW9uaXRvciB9IGZyb20gJy4uLy4uL3NlY3VyaXR5L3NlY3VyaXR5TW9uaXRvci5qcyc7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi8uLi91dGlscy9sb2dnZXIuanMnO1xuXG5leHBvcnQgY2xhc3MgQWdlbnRBY3RpdmF0aW9uU3RyYXRlZ3kgZXh0ZW5kcyBCYXNlQWN0aXZhdGlvblN0cmF0ZWd5IGltcGxlbWVudHMgRWxlbWVudEFjdGl2YXRpb25TdHJhdGVneSB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgYWdlbnRNYW5hZ2VyOiBBZ2VudE1hbmFnZXIpIHtcbiAgICBzdXBlcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFjdGl2YXRlIGFuIGFnZW50IHdpdGggZXhlY3V0aW9uIHN0cmF0ZWd5XG4gICAqIEV4ZWN1dGVzIGFnZW50IGxvZ2ljLCB1cGRhdGVzIHN0YXRlIGZpbGUsIGFuZCB0cmFja3MgYWN0aXZhdGlvblxuICAgKlxuICAgKiBJTVBST1ZFTUVOVDogRW5oYW5jZWQgZXJyb3IgaGFuZGxpbmcgd2l0aCBzZWN1cml0eSBsb2dnaW5nIGFuZCByb2xsYmFjayAoSXNzdWUgIzI0KVxuICAgKi9cbiAgYXN5bmMgYWN0aXZhdGUobmFtZTogc3RyaW5nLCBjb250ZXh0PzogUmVjb3JkPHN0cmluZywgYW55Pik6IFByb21pc2U8TUNQUmVzcG9uc2U+IHtcbiAgICAvLyBVc2UgdGhlIG1hbmFnZXIncyBhY3RpdmF0aW9uIG1ldGhvZCB3aGljaCB0cmFja3MgYWN0aXZlIGFnZW50c1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuYWdlbnRNYW5hZ2VyLmFjdGl2YXRlQWdlbnQobmFtZSk7XG5cbiAgICBpZiAoIXJlc3VsdC5zdWNjZXNzIHx8ICFyZXN1bHQuYWdlbnQpIHtcbiAgICAgIHJldHVybiB0aGlzLmNyZWF0ZU5vdEZvdW5kUmVzcG9uc2UobmFtZSwgJ0FnZW50Jyk7XG4gICAgfVxuXG4gICAgY29uc3QgYWdlbnQgPSByZXN1bHQuYWdlbnQ7XG5cbiAgICAvLyBFeHRyYWN0IG9wdGlvbmFsIGdvYWwgZnJvbSBjb250ZXh0XG4gICAgY29uc3QgZ29hbCA9IGNvbnRleHQ/LmdvYWwgfHwgY29udGV4dD8uZ29hbHM/LlswXTtcblxuICAgIC8vIEV4ZWN1dGUgYWdlbnQgbG9naWMgKGdvYWxzL2RlY2lzaW9ucylcbiAgICAvLyBGb3Igbm93LCB0aGlzIGlzIGEgc2lkZS1lZmZlY3QgYWN0aXZhdGlvbiB0aGF0IHVwZGF0ZXMgc3RhdGVcbiAgICBjb25zdCBzdGF0ZSA9IGFnZW50LmdldFN0YXRlKCk7XG4gICAgY29uc3QgZXhlY3V0aW9uU3VtbWFyeTogc3RyaW5nW10gPSBbXTtcblxuICAgIC8vIFRyYWNrIGlmIHdlIG5lZWQgdG8gcm9sbGJhY2sgYWN0aXZhdGlvbiBvbiBjcml0aWNhbCBmYWlsdXJlXG4gICAgbGV0IGNyaXRpY2FsRmFpbHVyZSA9IGZhbHNlO1xuXG4gICAgaWYgKGdvYWwpIHtcbiAgICAgIC8vIElmIGdvYWwgcHJvdmlkZWQsIGFkZCBpdCB0byB0aGUgYWdlbnQncyBnb2Fsc1xuICAgICAgdHJ5IHtcbiAgICAgICAgYWdlbnQuYWRkR29hbCh7XG4gICAgICAgICAgZGVzY3JpcHRpb246IGdvYWwuZGVzY3JpcHRpb24gfHwgZ29hbCxcbiAgICAgICAgICBwcmlvcml0eTogZ29hbC5wcmlvcml0eSB8fCAnbWVkaXVtJyxcbiAgICAgICAgICBpbXBvcnRhbmNlOiBnb2FsLmltcG9ydGFuY2UgfHwgNSxcbiAgICAgICAgICB1cmdlbmN5OiBnb2FsLnVyZ2VuY3kgfHwgNVxuICAgICAgICB9KTtcbiAgICAgICAgZXhlY3V0aW9uU3VtbWFyeS5wdXNoKGBHb2FsIGFkZGVkOiAke2dvYWwuZGVzY3JpcHRpb24gfHwgZ29hbH1gKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIC8vIEZJWDogRW5oYW5jZWQgZXJyb3IgbG9nZ2luZyB3aXRoIHNlY3VyaXR5IG1vbml0b3JpbmcgKElzc3VlICMyNClcbiAgICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiAnQ291bGQgbm90IGFkZCBnb2FsJztcblxuICAgICAgICAvLyBMb2cgdG8gc2VjdXJpdHkgbW9uaXRvciBmb3IgYXVkaXQgdHJhaWxcbiAgICAgICAgU2VjdXJpdHlNb25pdG9yLmxvZ1NlY3VyaXR5RXZlbnQoe1xuICAgICAgICAgIHR5cGU6ICdBR0VOVF9BQ1RJVkFUSU9OX0ZBSUxFRCcsXG4gICAgICAgICAgc2V2ZXJpdHk6ICdNRURJVU0nLFxuICAgICAgICAgIHNvdXJjZTogJ0FnZW50QWN0aXZhdGlvblN0cmF0ZWd5LmFjdGl2YXRlJyxcbiAgICAgICAgICBkZXRhaWxzOiBgRmFpbGVkIHRvIGFkZCBnb2FsIGR1cmluZyBhZ2VudCBhY3RpdmF0aW9uOiAke2Vycm9yTWVzc2FnZX1gLFxuICAgICAgICAgIGFkZGl0aW9uYWxEYXRhOiB7XG4gICAgICAgICAgICBhZ2VudE5hbWU6IG5hbWUsXG4gICAgICAgICAgICBnb2FsRGVzY3JpcHRpb246IGdvYWwuZGVzY3JpcHRpb24gfHwgZ29hbCxcbiAgICAgICAgICAgIGVycm9yOiBlcnJvck1lc3NhZ2VcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIExvZyB0byBzdGFuZGFyZCBsb2dnZXIgZm9yIGRlYnVnZ2luZ1xuICAgICAgICBsb2dnZXIud2FybihgR29hbCBhZGRpdGlvbiBmYWlsZWQgZHVyaW5nIGFnZW50IGFjdGl2YXRpb25gLCB7XG4gICAgICAgICAgYWdlbnROYW1lOiBuYW1lLFxuICAgICAgICAgIGVycm9yOiBlcnJvck1lc3NhZ2VcbiAgICAgICAgfSk7XG5cbiAgICAgICAgZXhlY3V0aW9uU3VtbWFyeS5wdXNoKGBOb3RlOiAke2Vycm9yTWVzc2FnZX1gKTtcblxuICAgICAgICAvLyBEZXRlcm1pbmUgaWYgdGhpcyBpcyBhIGNyaXRpY2FsIGZhaWx1cmUgcmVxdWlyaW5nIHJvbGxiYWNrXG4gICAgICAgIC8vIENyaXRpY2FsIGZhaWx1cmVzOiB2YWxpZGF0aW9uIGVycm9ycyB0aGF0IGluZGljYXRlIGJhZCBpbnB1dCBvciBzZWN1cml0eSBpc3N1ZXNcbiAgICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IgJiYgKFxuICAgICAgICAgIGVycm9yTWVzc2FnZS5pbmNsdWRlcygnaGFybWZ1bCBjb250ZW50JykgfHxcbiAgICAgICAgICBlcnJvck1lc3NhZ2UuaW5jbHVkZXMoJ3NlY3VyaXR5JykgfHxcbiAgICAgICAgICBlcnJvck1lc3NhZ2UuaW5jbHVkZXMoJ01heGltdW0gbnVtYmVyIG9mIGdvYWxzJylcbiAgICAgICAgKSkge1xuICAgICAgICAgIGNyaXRpY2FsRmFpbHVyZSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBGSVg6IFJvbGxiYWNrIGFjdGl2YXRpb24gb24gY3JpdGljYWwgZmFpbHVyZXMgKElzc3VlICMyNClcbiAgICBpZiAoY3JpdGljYWxGYWlsdXJlKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoYENyaXRpY2FsIGZhaWx1cmUgZHVyaW5nIGFnZW50IGFjdGl2YXRpb24sIHJvbGxpbmcgYmFja2AsIHtcbiAgICAgICAgYWdlbnROYW1lOiBuYW1lXG4gICAgICB9KTtcblxuICAgICAgLy8gRGVhY3RpdmF0ZSB0aGUgYWdlbnQgdG8gcm9sbGJhY2tcbiAgICAgIGF3YWl0IHRoaXMuYWdlbnRNYW5hZ2VyLmRlYWN0aXZhdGVBZ2VudChuYW1lKTtcblxuICAgICAgLy8gTG9nIHNlY3VyaXR5IGV2ZW50IGZvciByb2xsYmFja1xuICAgICAgU2VjdXJpdHlNb25pdG9yLmxvZ1NlY3VyaXR5RXZlbnQoe1xuICAgICAgICB0eXBlOiAnQUdFTlRfQUNUSVZBVElPTl9ST0xMQkFDSycsXG4gICAgICAgIHNldmVyaXR5OiAnSElHSCcsXG4gICAgICAgIHNvdXJjZTogJ0FnZW50QWN0aXZhdGlvblN0cmF0ZWd5LmFjdGl2YXRlJyxcbiAgICAgICAgZGV0YWlsczogYEFnZW50IGFjdGl2YXRpb24gcm9sbGVkIGJhY2sgZHVlIHRvIGNyaXRpY2FsIGZhaWx1cmVgLFxuICAgICAgICBhZGRpdGlvbmFsRGF0YToge1xuICAgICAgICAgIGFnZW50TmFtZTogbmFtZSxcbiAgICAgICAgICByZWFzb246ICdDcml0aWNhbCBnb2FsIGFkZGl0aW9uIGZhaWx1cmUnXG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICAvLyBSZXR1cm4gZXJyb3IgcmVzcG9uc2VcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbnRlbnQ6IFt7XG4gICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgdGV4dDogYOKdjCBBZ2VudCBhY3RpdmF0aW9uIGZhaWxlZCBhbmQgd2FzIHJvbGxlZCBiYWNrXFxuXFxuQ3JpdGljYWwgZXJyb3Igb2NjdXJyZWQgZHVyaW5nIGdvYWwgYWRkaXRpb24uIFBsZWFzZSByZXZpZXcgdGhlIGdvYWwgcGFyYW1ldGVycyBhbmQgdHJ5IGFnYWluLmBcbiAgICAgICAgfV1cbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gRklYOiBPcHRpbWlzdGljIGxvY2tpbmcgZm9yIHN0YXRlIHVwZGF0ZXMgKElzc3VlICMyNClcbiAgICAvLyBVc2UgcHVibGljIHBlcnNpc3RTdGF0ZSBBUEkgd2hpY2ggaW1wbGVtZW50cyBPcHRpb24gQyBwYXR0ZXJuIChJc3N1ZSAjMTIzKVxuICAgIGNvbnN0IGZpbGVuYW1lID0gYWdlbnQubWV0YWRhdGEubmFtZTtcblxuICAgIHRyeSB7XG4gICAgICAvLyBTYXZlIHN0YXRlIHdpdGggYXRvbWljIHdyaXRlIGFuZCBwcm9wZXIgdmVyc2lvbiBoYW5kbGluZ1xuICAgICAgYXdhaXQgdGhpcy5hZ2VudE1hbmFnZXIucGVyc2lzdFN0YXRlKGZpbGVuYW1lKTtcblxuICAgICAgY29uc3QgY3VycmVudFN0YXRlID0gYWdlbnQuZ2V0U3RhdGUoKTtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhgQWdlbnQgc3RhdGUgcGVyc2lzdGVkIHN1Y2Nlc3NmdWxseWAsIHtcbiAgICAgICAgYWdlbnROYW1lOiBuYW1lLFxuICAgICAgICBzZXNzaW9uQ291bnQ6IGN1cnJlbnRTdGF0ZS5zZXNzaW9uQ291bnQsXG4gICAgICAgIGdvYWxDb3VudDogY3VycmVudFN0YXRlLmdvYWxzLmxlbmd0aFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIC8vIFN0YXRlIHNhdmUgZmFpbHVyZSAtIGxvZyBhbmQgY29udGludWUgKGFnZW50IGlzIHN0aWxsIGFjdGl2YXRlZClcbiAgICAgIGNvbnN0IGVycm9yTWVzc2FnZSA9IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogJ1Vua25vd24gZXJyb3InO1xuXG4gICAgICBTZWN1cml0eU1vbml0b3IubG9nU2VjdXJpdHlFdmVudCh7XG4gICAgICAgIHR5cGU6ICdNRU1PUllfU0FWRV9GQUlMRUQnLCAvLyBVc2luZyBleGlzdGluZyBldmVudCB0eXBlIGZvciBzdGF0ZSBzYXZlIGZhaWx1cmVzXG4gICAgICAgIHNldmVyaXR5OiAnTUVESVVNJyxcbiAgICAgICAgc291cmNlOiAnQWdlbnRBY3RpdmF0aW9uU3RyYXRlZ3kuYWN0aXZhdGUnLFxuICAgICAgICBkZXRhaWxzOiBgRmFpbGVkIHRvIHNhdmUgYWdlbnQgc3RhdGUgYWZ0ZXIgYWN0aXZhdGlvbjogJHtlcnJvck1lc3NhZ2V9YCxcbiAgICAgICAgYWRkaXRpb25hbERhdGE6IHtcbiAgICAgICAgICBhZ2VudE5hbWU6IG5hbWUsXG4gICAgICAgICAgZXJyb3I6IGVycm9yTWVzc2FnZVxuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgbG9nZ2VyLndhcm4oYEFnZW50IHN0YXRlIHNhdmUgZmFpbGVkLCBidXQgYWdlbnQgcmVtYWlucyBhY3RpdmF0ZWRgLCB7XG4gICAgICAgIGFnZW50TmFtZTogbmFtZSxcbiAgICAgICAgZXJyb3I6IGVycm9yTWVzc2FnZVxuICAgICAgfSk7XG5cbiAgICAgIGV4ZWN1dGlvblN1bW1hcnkucHVzaChgV2FybmluZzogU3RhdGUgcGVyc2lzdGVuY2UgZmFpbGVkIC0gJHtlcnJvck1lc3NhZ2V9YCk7XG4gICAgfVxuXG4gICAgLy8gQnVpbGQgZXhlY3V0aW9uIHJlc3BvbnNlXG4gICAgY29uc3QgcGFydHMgPSBbXG4gICAgICBnb2FsXG4gICAgICAgID8gYOKchSBBZ2VudCBhY3RpdmF0ZWQgYW5kIGV4ZWN1dGVkIGdvYWw6ICR7Z29hbC5kZXNjcmlwdGlvbiB8fCBnb2FsfWBcbiAgICAgICAgOiBg4pyFIEFnZW50IGFjdGl2YXRlZCBzdWNjZXNzZnVsbHlgLFxuICAgICAgJydcbiAgICBdO1xuXG4gICAgLy8gQWRkIG91dGNvbWUgZGVzY3JpcHRpb24gZm9yIHRlc3QgZXhwZWN0YXRpb25zXG4gICAgaWYgKGdvYWwpIHtcbiAgICAgIHBhcnRzLnB1c2goJ0FnZW50IGFjdGl2YXRlcyB3aXRoIGluaXRpYWwgZ29hbHMgbG9hZGVkJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHBhcnRzLnB1c2goJ0FnZW50IGJlY29tZXMgYWN0aXZlLCBpbmNyZW1lbnRzIHNlc3Npb24gY291bnQnKTtcbiAgICB9XG4gICAgcGFydHMucHVzaCgnJyk7XG5cbiAgICBwYXJ0cy5wdXNoKGAqKlNlc3Npb24qKjogIyR7c3RhdGUuc2Vzc2lvbkNvdW50ICsgMX1gKTtcbiAgICBwYXJ0cy5wdXNoKC4uLnRoaXMuZm9ybWF0VjFGaWVsZHMoYWdlbnQubWV0YWRhdGEgYXMgYW55LCBhZ2VudC5leHRlbnNpb25zIGFzIGFueSkpO1xuXG4gICAgaWYgKGV4ZWN1dGlvblN1bW1hcnkubGVuZ3RoID4gMCkge1xuICAgICAgcGFydHMucHVzaCgnJyk7XG4gICAgICBwYXJ0cy5wdXNoKCcqKkV4ZWN1dGlvbiBTdW1tYXJ5Kio6Jyk7XG4gICAgICBleGVjdXRpb25TdW1tYXJ5LmZvckVhY2gobGluZSA9PiBwYXJ0cy5wdXNoKGAtICR7bGluZX1gKSk7XG4gICAgfVxuXG4gICAgY29uc3QgYWN0aXZlR29hbHMgPSBhZ2VudC5nZXRTdGF0ZSgpLmdvYWxzLmZpbHRlcigoZzogeyBzdGF0dXM6IHN0cmluZyB9KSA9PiBnLnN0YXR1cyA9PT0gJ2luX3Byb2dyZXNzJyk7XG4gICAgaWYgKGFjdGl2ZUdvYWxzLmxlbmd0aCA+IDApIHtcbiAgICAgIHBhcnRzLnB1c2goJycpO1xuICAgICAgcGFydHMucHVzaChgKipBY3RpdmUgR29hbHMqKjogJHthY3RpdmVHb2Fscy5sZW5ndGh9YCk7XG4gICAgfVxuXG4gICAgcGFydHMucHVzaCgnJyk7XG4gICAgcGFydHMucHVzaCgnQWdlbnQgZXhlY3V0aW9uIGNvbXBsZXRlZCcpO1xuXG4gICAgLy8gSXNzdWUgIzY0MjogRmFpbC1zYWZlIHdhcm5pbmcgZm9yIENMSSByZXN0cmljdGlvbnNcbiAgICBjb25zdCByZXN0cmljdGlvbldhcm5pbmcgPSB0aGlzLmZvcm1hdFJlc3RyaWN0aW9uV2FybmluZyhhZ2VudC5tZXRhZGF0YSBhcyB1bmtub3duIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KTtcbiAgICBpZiAocmVzdHJpY3Rpb25XYXJuaW5nKSB7XG4gICAgICBwYXJ0cy5wdXNoKHJlc3RyaWN0aW9uV2FybmluZyk7XG4gICAgfVxuXG4gICAgY29uc3QgZ2F0ZWtlZXBlcldhcm5pbmcgPSB0aGlzLmZvcm1hdEdhdGVrZWVwZXJWYWxpZGl0eVdhcm5pbmcoYWdlbnQubWV0YWRhdGEgYXMgdW5rbm93biBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik7XG4gICAgaWYgKGdhdGVrZWVwZXJXYXJuaW5nKSB7XG4gICAgICBwYXJ0cy5wdXNoKGdhdGVrZWVwZXJXYXJuaW5nKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgY29udGVudDogW3tcbiAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgIHRleHQ6IHBhcnRzLmpvaW4oJ1xcbicpXG4gICAgICB9XVxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogRGVhY3RpdmF0ZSBhbiBhZ2VudFxuICAgKlxuICAgKiBAdGhyb3dzIHtFbGVtZW50Tm90Rm91bmRFcnJvcn0gV2hlbiBhZ2VudCBkb2VzIG5vdCBleGlzdFxuICAgKiBAc2VlIElzc3VlICMyNzUgLSBIYW5kbGVycyByZXR1cm4gc3VjY2Vzcz10cnVlIGZvciBtaXNzaW5nIGVsZW1lbnRzXG4gICAqL1xuICBhc3luYyBkZWFjdGl2YXRlKG5hbWU6IHN0cmluZyk6IFByb21pc2U8TUNQUmVzcG9uc2U+IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmFnZW50TWFuYWdlci5kZWFjdGl2YXRlQWdlbnQobmFtZSk7XG5cbiAgICBpZiAoIXJlc3VsdC5zdWNjZXNzKSB7XG4gICAgICB0aGlzLnRocm93Tm90Rm91bmRFcnJvcihuYW1lLCAnQWdlbnQnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5jcmVhdGVTdWNjZXNzUmVzcG9uc2UocmVzdWx0Lm1lc3NhZ2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhbGwgYWN0aXZlIGFnZW50c1xuICAgKi9cbiAgYXN5bmMgZ2V0QWN0aXZlRWxlbWVudHMoKTogUHJvbWlzZTxNQ1BSZXNwb25zZT4ge1xuICAgIC8vIFVzZSB0aGUgbWFuYWdlcidzIG1ldGhvZCB0byBnZXQgYWN0aXZlIGFnZW50cyBkaXJlY3RseVxuICAgIGNvbnN0IGFjdGl2ZUFnZW50cyA9IGF3YWl0IHRoaXMuYWdlbnRNYW5hZ2VyLmdldEFjdGl2ZUFnZW50cygpO1xuXG4gICAgaWYgKGFjdGl2ZUFnZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbnRlbnQ6IFt7XG4gICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgdGV4dDogXCLwn6SWIE5vIGFjdGl2ZSBhZ2VudHNcIlxuICAgICAgICB9XVxuICAgICAgfTtcbiAgICB9XG5cbiAgICBjb25zdCBhZ2VudExpc3QgPSBhY3RpdmVBZ2VudHMubWFwKGEgPT4ge1xuICAgICAgY29uc3Qgc3RhdGUgPSBhLmdldFN0YXRlKCk7XG4gICAgICBjb25zdCBnb2FscyA9IHN0YXRlLmdvYWxzPy5sZW5ndGggfHwgMDtcbiAgICAgIHJldHVybiBg8J+kliAke2EubWV0YWRhdGEubmFtZX0gKCR7Z29hbHN9IGFjdGl2ZSBnb2FscylgO1xuICAgIH0pLmpvaW4oJ1xcbicpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbnRlbnQ6IFt7XG4gICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICB0ZXh0OiBgQWN0aXZlIGFnZW50czpcXG4ke2FnZW50TGlzdH1gXG4gICAgICB9XVxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogRm9ybWF0IHYxIGFnZW50IGZpZWxkcyAoc3BlY2lhbGl6YXRpb25zLCBkZWNpc2lvbkZyYW1ld29yaywgcmlza1RvbGVyYW5jZSlcbiAgICogZm9yIGRpc3BsYXkuIE9ubHkgaW5jbHVkZXMgZmllbGRzIHRoYXQgYXJlIGV4cGxpY2l0bHkgc2V0IOKAlCBhdm9pZHMgc2hvd2luZ1xuICAgKiBwaGFudG9tIGRlZmF1bHRzIG9uIHYyIGFnZW50cy4gKElzc3VlICM3NDkpXG4gICAqL1xuICBwcml2YXRlIGZvcm1hdFYxRmllbGRzKFxuICAgIG1ldGFkYXRhOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIGV4dGVuc2lvbnM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+XG4gICk6IHN0cmluZ1tdIHtcbiAgICAvLyBJc3N1ZSAjNzQ5OiBWMiBhZ2VudHMgc2hvdWxkIG5vdCBzaG93IFYxIGRlZmF1bHRzLlxuICAgIC8vIGBnb2FsYCAoc2luZ3VsYXIsIEFnZW50R29hbENvbmZpZykgaXMgdGhlIGRlZmluaXRpdmUgVjIgbWFya2VyIOKAlCBpdCdzXG4gICAgLy8gcmVxdWlyZWQgb24gQWdlbnRNZXRhZGF0YVYyIGFuZCBuZXZlciBwcmVzZW50IG9uIFYxIGFnZW50cyAod2hpY2ggdXNlXG4gICAgLy8gYGdvYWxzYCBwbHVyYWwpLiBUaGUgQWdlbnQgY29uc3RydWN0b3IgYWx3YXlzIGRlZmF1bHRzIGRlY2lzaW9uRnJhbWV3b3JrXG4gICAgLy8gYW5kIHJpc2tUb2xlcmFuY2UsIHNvIGNoZWNraW5nIHRydXRoaW5lc3MgYWxvbmUgc2hvd3MgcGhhbnRvbSB2YWx1ZXMuXG4gICAgaWYgKG1ldGFkYXRhLmdvYWwpIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG5cbiAgICBjb25zdCBsaW5lczogc3RyaW5nW10gPSBbXTtcbiAgICBjb25zdCBzcGVjcyA9IG1ldGFkYXRhLnNwZWNpYWxpemF0aW9ucztcbiAgICBjb25zdCBmcmFtZXdvcmsgPSBleHRlbnNpb25zPy5kZWNpc2lvbkZyYW1ld29yayA/PyBtZXRhZGF0YS5kZWNpc2lvbkZyYW1ld29yaztcbiAgICBjb25zdCByaXNrID0gZXh0ZW5zaW9ucz8ucmlza1RvbGVyYW5jZSA/PyBtZXRhZGF0YS5yaXNrVG9sZXJhbmNlO1xuXG4gICAgaWYgKHNwZWNzPy5sZW5ndGggPiAwKSB7XG4gICAgICBsaW5lcy5wdXNoKGAqKlNwZWNpYWxpemF0aW9ucyoqOiAke3NwZWNzLmpvaW4oJywgJyl9YCk7XG4gICAgfVxuICAgIGlmIChmcmFtZXdvcmspIHtcbiAgICAgIGxpbmVzLnB1c2goYCoqRGVjaXNpb24gRnJhbWV3b3JrKio6ICR7ZnJhbWV3b3JrfWApO1xuICAgIH1cbiAgICBpZiAocmlzaykge1xuICAgICAgbGluZXMucHVzaChgKipSaXNrIFRvbGVyYW5jZSoqOiAke3Jpc2t9YCk7XG4gICAgfVxuICAgIHJldHVybiBsaW5lcztcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgZGV0YWlsZWQgaW5mb3JtYXRpb24gYWJvdXQgYW4gYWdlbnRcbiAgICogRXh0cmFjdGVkIGZyb20gRWxlbWVudENSVURIYW5kbGVyLnRzIGxpbmVzIDczMC03NzBcbiAgICovXG4gIGFzeW5jIGdldEVsZW1lbnREZXRhaWxzKG5hbWU6IHN0cmluZyk6IFByb21pc2U8TUNQUmVzcG9uc2U+IHtcbiAgICAvLyBVc2UgZmxleGlibGUgZmluZGluZyB0byBzdXBwb3J0IGJvdGggZGlzcGxheSBuYW1lIGFuZCBmaWxlbmFtZVxuICAgIGNvbnN0IGFsbEFnZW50cyA9IGF3YWl0IHRoaXMuYWdlbnRNYW5hZ2VyLmxpc3QoKTtcbiAgICBjb25zdCBhZ2VudCA9IGF3YWl0IHRoaXMuZmluZEVsZW1lbnRGbGV4aWJseShuYW1lLCBhbGxBZ2VudHMpO1xuICAgIGlmICghYWdlbnQpIHtcbiAgICAgIHRoaXMudGhyb3dOb3RGb3VuZEVycm9yKG5hbWUsICdBZ2VudCcpO1xuICAgIH1cblxuICAgIGNvbnN0IG1ldGFkYXRhID0gYWdlbnQubWV0YWRhdGEgYXMgYW55O1xuXG4gICAgY29uc3QgZGV0YWlscyA9IFtcbiAgICAgIGDwn6SWICoqJHthZ2VudC5tZXRhZGF0YS5uYW1lfSoqYCxcbiAgICAgIGAke2FnZW50Lm1ldGFkYXRhLmRlc2NyaXB0aW9ufWAsXG4gICAgICBgYCxcbiAgICAgIGAqKlN0YXR1cyoqOiAke2FnZW50LmdldFN0YXR1cygpfWBcbiAgICBdO1xuXG4gICAgZGV0YWlscy5wdXNoKC4uLnRoaXMuZm9ybWF0VjFGaWVsZHMobWV0YWRhdGEpKTtcblxuICAgIC8vIFYyIGZpZWxkc1xuICAgIGlmIChtZXRhZGF0YS5nb2FsKSB7XG4gICAgICBkZXRhaWxzLnB1c2goJycpO1xuICAgICAgZGV0YWlscy5wdXNoKCcqKkdvYWwgQ29uZmlndXJhdGlvbioqOicpO1xuICAgICAgZGV0YWlscy5wdXNoKGAtIFRlbXBsYXRlOiAke21ldGFkYXRhLmdvYWwudGVtcGxhdGV9YCk7XG4gICAgICBpZiAobWV0YWRhdGEuZ29hbC5wYXJhbWV0ZXJzICYmIG1ldGFkYXRhLmdvYWwucGFyYW1ldGVycy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGRldGFpbHMucHVzaChgLSBQYXJhbWV0ZXJzOiAke21ldGFkYXRhLmdvYWwucGFyYW1ldGVycy5sZW5ndGh9IGRlZmluZWRgKTtcbiAgICAgICAgbWV0YWRhdGEuZ29hbC5wYXJhbWV0ZXJzLmZvckVhY2goKHBhcmFtOiBhbnkpID0+IHtcbiAgICAgICAgICBjb25zdCByZXF1aXJlZCA9IHBhcmFtLnJlcXVpcmVkID8gJ3JlcXVpcmVkJyA6ICdvcHRpb25hbCc7XG4gICAgICAgICAgZGV0YWlscy5wdXNoKGAgIC0gJHtwYXJhbS5uYW1lfSAoJHtwYXJhbS50eXBlfSwgJHtyZXF1aXJlZH0pYCk7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZGV0YWlscy5wdXNoKCctIFBhcmFtZXRlcnM6IG5vbmUnKTtcbiAgICAgIH1cbiAgICAgIGlmIChtZXRhZGF0YS5nb2FsLnN1Y2Nlc3NDcml0ZXJpYSAmJiBtZXRhZGF0YS5nb2FsLnN1Y2Nlc3NDcml0ZXJpYS5sZW5ndGggPiAwKSB7XG4gICAgICAgIGRldGFpbHMucH