@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.
282 lines • 53.3 kB
JavaScript
/**
* FIX: DMCP-SEC-006 - Security audit suppression
* This file delegates element creation to specialized managers.
* Audit logging happens in the managers themselves (PersonaManager, SkillManager, etc.).
* @security-audit-suppress DMCP-SEC-006
*/
import { ElementType } from '../../portfolio/PortfolioManager.js';
import { SECURITY_LIMITS } from '../../security/constants.js';
import { sanitizeInput, validateContentSize, validateCategory } from '../../security/InputValidator.js';
import { sanitizeMetadata, normalizeElementTypeInput, formatValidElementTypesList, detectUnknownMetadataProperties, formatUnknownPropertyWarnings, formatElementResolutionWarnings, collectGatekeeperAuthoringErrors, formatGatekeeperValidationMessage, } from './helpers.js';
import { resolveElementTypes } from '../../utils/elementTypeResolver.js';
import { logger } from '../../utils/logger.js';
// FIX: Issue #281 - SecurityMonitor import removed, persona logging now in PersonaManager.create()
import { formatSimpleErrorResponse, formatDuplicateError, formatExceptionError } from './responseFormatter.js';
/**
* Helper to add persona indicator prefix to response
*/
function addPersonaIndicator(response, indicator) {
return {
...response,
content: response.content.map(c => ({
...c,
text: `${indicator}${c.text}`
}))
};
}
export async function createElement(context, args) {
await context.ensureInitialized();
try {
const { name, type, description, content, instructions, metadata } = args;
const { type: normalizedType } = normalizeElementTypeInput(type);
if (!normalizedType) {
return {
content: [{
type: "text",
text: `❌ Invalid element type '${type}'. Valid types: ${formatValidElementTypesList()}`
}]
};
}
const validatedName = sanitizeInput(name, SECURITY_LIMITS.MAX_FILENAME_LENGTH);
if (description.length > SECURITY_LIMITS.MAX_DESCRIPTION_LENGTH) {
return {
content: [{
type: "text",
text: `❌ Description too large: Maximum allowed size is ${SECURITY_LIMITS.MAX_DESCRIPTION_LENGTH} characters.`
}]
};
}
const validatedDescription = sanitizeInput(description, SECURITY_LIMITS.MAX_DESCRIPTION_LENGTH);
if (content) {
try {
validateContentSize(content, SECURITY_LIMITS.MAX_CONTENT_LENGTH);
}
catch (error) {
return {
content: [{
type: "text",
text: `❌ Content too large: ${error.message}. Maximum allowed size is ${SECURITY_LIMITS.MAX_CONTENT_LENGTH} characters (${Math.floor(SECURITY_LIMITS.MAX_CONTENT_LENGTH / 1024)}KB).`
}]
};
}
}
// Issue #602 resolved: Both 'instructions' and 'content' are first-class fields.
// instructions = behavioral directives (command voice, "You ARE...", "ALWAYS...")
// content = reference material (informational, domain knowledge, examples)
if (instructions) {
try {
validateContentSize(instructions, SECURITY_LIMITS.MAX_CONTENT_LENGTH);
}
catch (error) {
return {
content: [{
type: "text",
text: `❌ Instructions too large: ${error.message}. Maximum allowed size is ${SECURITY_LIMITS.MAX_CONTENT_LENGTH} characters.`
}]
};
}
}
// Element-specific fields (ensemble elements, agent V2 fields) are merged into
// metadata by the dispatcher (MCPAQLHandler). createElement just sanitizes and delegates.
const sanitized = sanitizeMetadata(metadata);
const gatekeeperErrors = collectGatekeeperAuthoringErrors({ ...args }, sanitized);
if (gatekeeperErrors.length > 0) {
return formatSimpleErrorResponse(formatGatekeeperValidationMessage(gatekeeperErrors));
}
// Issue #621: Validate category format for element types that support it
// Persona also supports categories (validated internally by PersonaManager) — include here for consistent early error reporting
const CATEGORY_TYPES = new Set([ElementType.PERSONA, ElementType.SKILL, ElementType.TEMPLATE, ElementType.MEMORY]);
if (sanitized.category && CATEGORY_TYPES.has(normalizedType)) {
try {
validateCategory(sanitized.category);
}
catch (categoryError) {
return formatSimpleErrorResponse(`Invalid category '${sanitized.category}': ${categoryError.message}`);
}
}
// Detect unknown metadata properties and generate warnings for LLM feedback
const unknownPropertyWarnings = detectUnknownMetadataProperties(normalizedType, metadata);
const warningText = formatUnknownPropertyWarnings(unknownPropertyWarnings);
// Log warnings for debugging with structured data for better observability
if (unknownPropertyWarnings.length > 0) {
logger.warn(`[createElement] Unknown metadata properties detected`, {
elementType: normalizedType,
elementName: name,
warningCount: unknownPropertyWarnings.length,
unknownProperties: unknownPropertyWarnings.map(w => ({
property: w.property,
suggestion: w.suggestion
}))
});
}
switch (normalizedType) {
case ElementType.PERSONA: {
try {
// Issue #602: Both 'instructions' and 'content' are first-class fields.
const persona = await context.personaManager.create({
...sanitized,
name: validatedName,
description: validatedDescription,
instructions: instructions,
content: content,
});
const successMsg = `${warningText}✅ Created persona '${persona.metadata.name}' successfully`;
return { content: [{ type: "text", text: `${context.getPersonaIndicator()}${successMsg}` }] };
}
catch (personaError) {
const message = personaError instanceof Error ? personaError.message : String(personaError);
if (message.includes('instructions are required')) {
return formatSimpleErrorResponse(message);
}
const errorResponse = message.includes('already exists')
? formatDuplicateError(ElementType.PERSONA, validatedName)
: formatExceptionError(personaError, 'create', ElementType.PERSONA, validatedName);
return addPersonaIndicator(errorResponse, context.getPersonaIndicator());
}
}
case ElementType.SKILL: {
// FIX: Issue #20 - Catch duplicate errors from SkillManager
try {
const skill = await context.skillManager.create({
name: validatedName,
description: validatedDescription,
...sanitized,
instructions: instructions,
content: content || ''
});
const successMsg = `${warningText}✅ Created skill '${skill.metadata.name}' successfully`;
return { content: [{ type: "text", text: `${context.getPersonaIndicator()}${successMsg}` }] };
}
catch (skillError) {
// Check if it's a duplicate error
const message = skillError instanceof Error ? skillError.message : String(skillError);
const errorResponse = message.includes('already exists')
? formatDuplicateError(ElementType.SKILL, validatedName)
: formatExceptionError(skillError, 'create', ElementType.SKILL, validatedName);
return addPersonaIndicator(errorResponse, context.getPersonaIndicator());
}
}
case ElementType.TEMPLATE: {
// FIX: Issue #20 - Catch duplicate errors from TemplateManager
try {
const template = await context.templateManager.create({
name: validatedName,
description: validatedDescription,
instructions: instructions,
content: content || '',
metadata: sanitized,
});
const successMsg = `${warningText}✅ Created template '${template.metadata.name}' successfully`;
return { content: [{ type: "text", text: `${context.getPersonaIndicator()}${successMsg}` }] };
}
catch (templateError) {
// Check if it's a duplicate error
const message = templateError instanceof Error ? templateError.message : String(templateError);
const errorResponse = message.includes('already exists')
? formatDuplicateError(ElementType.TEMPLATE, validatedName)
: formatExceptionError(templateError, 'create', ElementType.TEMPLATE, validatedName);
return addPersonaIndicator(errorResponse, context.getPersonaIndicator());
}
}
case ElementType.AGENT: {
// V2 fields are merged into metadata by the dispatcher (MCPAQLHandler).
// Goal normalization (string→object) is handled by AgentManager.create().
try {
// Issue #722: v2 dual-field architecture — each field goes where it belongs.
// AgentManager.create() 3rd param = behavioral directives (agent.instructions).
// metadata.content = reference material (markdown body after frontmatter).
const agentInstructions = instructions || '';
const agentContent = content || '';
const agent = await context.agentManager.create(validatedName, validatedDescription, agentInstructions, { ...sanitized, content: agentContent });
if (agent.success) {
const baseMessage = agent.message && agent.message.toLowerCase().includes('created agent')
? agent.message
: `Created agent '${validatedName}' successfully`;
const successMsg = `${warningText}✅ ${baseMessage}`;
return { content: [{ type: "text", text: `${context.getPersonaIndicator()}${successMsg}` }] };
}
// FIX: Issue #20 - Include "failed to create" in error message for test compatibility
const failureReason = agent.message || 'Unknown error';
return formatSimpleErrorResponse(`Failed to create agent: ${failureReason}`);
}
catch (agentError) {
const message = agentError instanceof Error ? agentError.message : String(agentError);
const errorResponse = message.includes('already exists')
? formatDuplicateError(ElementType.AGENT, validatedName)
: formatExceptionError(agentError, 'create', ElementType.AGENT, validatedName);
return addPersonaIndicator(errorResponse, context.getPersonaIndicator());
}
}
case ElementType.MEMORY: {
try {
const memory = await context.memoryManager.create({
...sanitized,
name: validatedName,
description: validatedDescription,
content: content,
instructions: instructions,
});
const successMsg = `${warningText}✅ Created memory '${memory.metadata.name}' successfully`;
return { content: [{ type: "text", text: `${context.getPersonaIndicator()}${successMsg}` }] };
}
catch (memoryError) {
const message = memoryError instanceof Error ? memoryError.message : String(memoryError);
const errorResponse = message.includes('already exists')
? formatDuplicateError(ElementType.MEMORY, validatedName)
: formatExceptionError(memoryError, 'create', ElementType.MEMORY, validatedName);
return addPersonaIndicator(errorResponse, context.getPersonaIndicator());
}
}
case ElementType.ENSEMBLE: {
try {
// Issue #466: Resolve missing element_type via portfolio lookup before create
const resolutionResult = await resolveElementTypes(sanitized.elements || [], {
skillManager: context.skillManager,
templateManager: context.templateManager,
agentManager: context.agentManager,
memoryManager: context.memoryManager,
personaManager: context.personaManager,
ensembleManager: context.ensembleManager,
});
const resolutionWarningText = formatElementResolutionWarnings(resolutionResult);
const ensemble = await context.ensembleManager.create({
...sanitized,
name: validatedName,
description: validatedDescription,
elements: resolutionResult.resolved,
instructions: instructions,
content: content,
});
const successMsg = `${warningText}${resolutionWarningText}✅ Created ensemble '${ensemble.metadata.name}' successfully`;
return { content: [{ type: "text", text: `${context.getPersonaIndicator()}${successMsg}` }] };
}
catch (ensembleError) {
const message = ensembleError instanceof Error ? ensembleError.message : String(ensembleError);
const errorResponse = message.includes('already exists')
? formatDuplicateError(ElementType.ENSEMBLE, validatedName)
: formatExceptionError(ensembleError, 'create', ElementType.ENSEMBLE, validatedName);
return addPersonaIndicator(errorResponse, context.getPersonaIndicator());
}
}
default:
return {
content: [{
type: "text",
text: `❌ Element type '${type}' is not yet supported for creation`
}]
};
}
}
catch (error) {
logger.error('ElementCRUDHandler.createElement', error);
const message = error instanceof Error ? error.message : 'Unknown error';
const indicator = context.getPersonaIndicator();
return {
content: [{
type: "text",
text: `${indicator}❌ Failed to create element: ${message}`
}]
};
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlRWxlbWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9oYW5kbGVycy9lbGVtZW50LWNydWQvY3JlYXRlRWxlbWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7R0FLRztBQUVILE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUNsRSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDOUQsT0FBTyxFQUFFLGFBQWEsRUFBRSxtQkFBbUIsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ3hHLE9BQU8sRUFDTCxnQkFBZ0IsRUFDaEIseUJBQXlCLEVBQ3pCLDJCQUEyQixFQUMzQiwrQkFBK0IsRUFDL0IsNkJBQTZCLEVBQzdCLCtCQUErQixFQUMvQixnQ0FBZ0MsRUFDaEMsaUNBQWlDLEdBQ2xDLE1BQU0sY0FBYyxDQUFDO0FBQ3RCLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBRXpFLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUMvQyxtR0FBbUc7QUFDbkcsT0FBTyxFQUNMLHlCQUF5QixFQUN6QixvQkFBb0IsRUFDcEIsb0JBQW9CLEVBQ3JCLE1BQU0sd0JBQXdCLENBQUM7QUE4R2hDOztHQUVHO0FBQ0gsU0FBUyxtQkFBbUIsQ0FBQyxRQUF5QixFQUFFLFNBQWlCO0lBQ3ZFLE9BQU87UUFDTCxHQUFHLFFBQVE7UUFDWCxPQUFPLEVBQUUsUUFBUSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ2xDLEdBQUcsQ0FBQztZQUNKLElBQUksRUFBRSxHQUFHLFNBQVMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFO1NBQzlCLENBQUMsQ0FBQztLQUNKLENBQUM7QUFDSixDQUFDO0FBRUQsTUFBTSxDQUFDLEtBQUssVUFBVSxhQUFhLENBQUMsT0FBMkIsRUFBRSxJQUF1QjtJQUN0RixNQUFNLE9BQU8sQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO0lBRWxDLElBQUksQ0FBQztRQUNILE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxPQUFPLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxHQUFHLElBQUksQ0FBQztRQUUxRSxNQUFNLEVBQUUsSUFBSSxFQUFFLGNBQWMsRUFBRSxHQUFHLHlCQUF5QixDQUFDLElBQUksQ0FBQyxDQUFDO1FBRWpFLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUNwQixPQUFPO2dCQUNMLE9BQU8sRUFBRSxDQUFDO3dCQUNSLElBQUksRUFBRSxNQUFNO3dCQUNaLElBQUksRUFBRSwyQkFBMkIsSUFBSSxtQkFBbUIsMkJBQTJCLEVBQUUsRUFBRTtxQkFDeEYsQ0FBQzthQUNILENBQUM7UUFDSixDQUFDO1FBRUQsTUFBTSxhQUFhLEdBQUcsYUFBYSxDQUFDLElBQUksRUFBRSxlQUFlLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUUvRSxJQUFJLFdBQVcsQ0FBQyxNQUFNLEdBQUcsZUFBZSxDQUFDLHNCQUFzQixFQUFFLENBQUM7WUFDaEUsT0FBTztnQkFDTCxPQUFPLEVBQUUsQ0FBQzt3QkFDUixJQUFJLEVBQUUsTUFBTTt3QkFDWixJQUFJLEVBQUUsb0RBQW9ELGVBQWUsQ0FBQyxzQkFBc0IsY0FBYztxQkFDL0csQ0FBQzthQUNILENBQUM7UUFDSixDQUFDO1FBRUQsTUFBTSxvQkFBb0IsR0FBRyxhQUFhLENBQUMsV0FBVyxFQUFFLGVBQWUsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1FBRWhHLElBQUksT0FBTyxFQUFFLENBQUM7WUFDWixJQUFJLENBQUM7Z0JBQ0gsbUJBQW1CLENBQUMsT0FBTyxFQUFFLGVBQWUsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1lBQ25FLENBQUM7WUFBQyxPQUFPLEtBQVUsRUFBRSxDQUFDO2dCQUNwQixPQUFPO29CQUNMLE9BQU8sRUFBRSxDQUFDOzRCQUNSLElBQUksRUFBRSxNQUFNOzRCQUNaLElBQUksRUFBRSx3QkFBd0IsS0FBSyxDQUFDLE9BQU8sNkJBQTZCLGVBQWUsQ0FBQyxrQkFBa0IsZ0JBQWdCLElBQUksQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLGtCQUFrQixHQUFHLElBQUksQ0FBQyxNQUFNO3lCQUN0TCxDQUFDO2lCQUNILENBQUM7WUFDSixDQUFDO1FBQ0gsQ0FBQztRQUVELGlGQUFpRjtRQUNqRixrRkFBa0Y7UUFDbEYsMkVBQTJFO1FBQzNFLElBQUksWUFBWSxFQUFFLENBQUM7WUFDakIsSUFBSSxDQUFDO2dCQUNILG1CQUFtQixDQUFDLFlBQVksRUFBRSxlQUFlLENBQUMsa0JBQWtCLENBQUMsQ0FBQztZQUN4RSxDQUFDO1lBQUMsT0FBTyxLQUFVLEVBQUUsQ0FBQztnQkFDcEIsT0FBTztvQkFDTCxPQUFPLEVBQUUsQ0FBQzs0QkFDUixJQUFJLEVBQUUsTUFBTTs0QkFDWixJQUFJLEVBQUUsNkJBQTZCLEtBQUssQ0FBQyxPQUFPLDZCQUE2QixlQUFlLENBQUMsa0JBQWtCLGNBQWM7eUJBQzlILENBQUM7aUJBQ0gsQ0FBQztZQUNKLENBQUM7UUFDSCxDQUFDO1FBRUQsK0VBQStFO1FBQy9FLDBGQUEwRjtRQUMxRixNQUFNLFNBQVMsR0FBRyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUU3QyxNQUFNLGdCQUFnQixHQUFHLGdDQUFnQyxDQUFDLEVBQUUsR0FBRyxJQUFJLEVBQUUsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUNsRixJQUFJLGdCQUFnQixDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUNoQyxPQUFPLHlCQUF5QixDQUFDLGlDQUFpQyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQztRQUN4RixDQUFDO1FBRUQseUVBQXlFO1FBQ3pFLGdJQUFnSTtRQUNoSSxNQUFNLGNBQWMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUUsV0FBVyxDQUFDLEtBQUssRUFBRSxXQUFXLENBQUMsUUFBUSxFQUFFLFdBQVcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBQ25ILElBQUksU0FBUyxDQUFDLFFBQVEsSUFBSSxjQUFjLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxFQUFFLENBQUM7WUFDN0QsSUFBSSxDQUFDO2dCQUNILGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxRQUFrQixDQUFDLENBQUM7WUFDakQsQ0FBQztZQUFDLE9BQU8sYUFBa0IsRUFBRSxDQUFDO2dCQUM1QixPQUFPLHlCQUF5QixDQUM5QixxQkFBcUIsU0FBUyxDQUFDLFFBQVEsTUFBTSxhQUFhLENBQUMsT0FBTyxFQUFFLENBQ3JFLENBQUM7WUFDSixDQUFDO1FBQ0gsQ0FBQztRQUVELDRFQUE0RTtRQUM1RSxNQUFNLHVCQUF1QixHQUFHLCtCQUErQixDQUM3RCxjQUFjLEVBQ2QsUUFBbUMsQ0FDcEMsQ0FBQztRQUNGLE1BQU0sV0FBVyxHQUFHLDZCQUE2QixDQUFDLHVCQUF1QixDQUFDLENBQUM7UUFFM0UsMkVBQTJFO1FBQzNFLElBQUksdUJBQXVCLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3ZDLE1BQU0sQ0FBQyxJQUFJLENBQUMsc0RBQXNELEVBQUU7Z0JBQ2xFLFdBQVcsRUFBRSxjQUFjO2dCQUMzQixXQUFXLEVBQUUsSUFBSTtnQkFDakIsWUFBWSxFQUFFLHVCQUF1QixDQUFDLE1BQU07Z0JBQzVDLGlCQUFpQixFQUFFLHVCQUF1QixDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7b0JBQ25ELFFBQVEsRUFBRSxDQUFDLENBQUMsUUFBUTtvQkFDcEIsVUFBVSxFQUFFLENBQUMsQ0FBQyxVQUFVO2lCQUN6QixDQUFDLENBQUM7YUFDSixDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsUUFBUSxjQUFjLEVBQUUsQ0FBQztZQUN2QixLQUFLLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO2dCQUN6QixJQUFJLENBQUM7b0JBQ0gsd0VBQXdFO29CQUN4RSxNQUFNLE9BQU8sR0FBRyxNQUFNLE9BQU8sQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDO3dCQUNsRCxHQUFHLFNBQVM7d0JBQ1osSUFBSSxFQUFFLGFBQWE7d0JBQ25CLFdBQVcsRUFBRSxvQkFBb0I7d0JBQ2pDLFlBQVksRUFBRSxZQUFZO3dCQUMxQixPQUFPLEVBQUUsT0FBTztxQkFDakIsQ0FBQyxDQUFDO29CQUVILE1BQU0sVUFBVSxHQUFHLEdBQUcsV0FBVyxzQkFBc0IsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLGdCQUFnQixDQUFDO29CQUM3RixPQUFPLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLE9BQU8sQ0FBQyxtQkFBbUIsRUFBRSxHQUFHLFVBQVUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDO2dCQUNoRyxDQUFDO2dCQUFDLE9BQU8sWUFBWSxFQUFFLENBQUM7b0JBQ3RCLE1BQU0sT0FBTyxHQUFHLFlBQVksWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztvQkFDNUYsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLDJCQUEyQixDQUFDLEVBQUUsQ0FBQzt3QkFDbEQsT0FBTyx5QkFBeUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztvQkFDNUMsQ0FBQztvQkFDRCxNQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDO3dCQUN0RCxDQUFDLENBQUMsb0JBQW9CLENBQUMsV0FBVyxDQUFDLE9BQU8sRUFBRSxhQUFhLENBQUM7d0JBQzFELENBQUMsQ0FBQyxvQkFBb0IsQ0FBQyxZQUFZLEVBQUUsUUFBUSxFQUFFLFdBQVcsQ0FBQyxPQUFPLEVBQUUsYUFBYSxDQUFDLENBQUM7b0JBQ3JGLE9BQU8sbUJBQW1CLENBQUMsYUFBYSxFQUFFLE9BQU8sQ0FBQyxtQkFBbUIsRUFBRSxDQUFDLENBQUM7Z0JBQzNFLENBQUM7WUFDSCxDQUFDO1lBRUQsS0FBSyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztnQkFDdkIsNERBQTREO2dCQUM1RCxJQUFJLENBQUM7b0JBQ0gsTUFBTSxLQUFLLEdBQUcsTUFBTSxPQUFPLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQzt3QkFDOUMsSUFBSSxFQUFFLGFBQWE7d0JBQ25CLFdBQVcsRUFBRSxvQkFBb0I7d0JBQ2pDLEdBQUcsU0FBUzt3QkFDWixZQUFZLEVBQUUsWUFBWTt3QkFDMUIsT0FBTyxFQUFFLE9BQU8sSUFBSSxFQUFFO3FCQUN2QixDQUFDLENBQUM7b0JBQ0gsTUFBTSxVQUFVLEdBQUcsR0FBRyxXQUFXLG9CQUFvQixLQUFLLENBQUMsUUFBUSxDQUFDLElBQUksZ0JBQWdCLENBQUM7b0JBQ3pGLE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixFQUFFLEdBQUcsVUFBVSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQ2hHLENBQUM7Z0JBQUMsT0FBTyxVQUFVLEVBQUUsQ0FBQztvQkFDcEIsa0NBQWtDO29CQUNsQyxNQUFNLE9BQU8sR0FBRyxVQUFVLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7b0JBQ3RGLE1BQU0sYUFBYSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUM7d0JBQ3RELENBQUMsQ0FBQyxvQkFBb0IsQ0FBQyxXQUFXLENBQUMsS0FBSyxFQUFFLGFBQWEsQ0FBQzt3QkFDeEQsQ0FBQyxDQUFDLG9CQUFvQixDQUFDLFVBQVUsRUFBRSxRQUFRLEVBQUUsV0FBVyxDQUFDLEtBQUssRUFBRSxhQUFhLENBQUMsQ0FBQztvQkFDakYsT0FBTyxtQkFBbUIsQ0FBQyxhQUFhLEVBQUUsT0FBTyxDQUFDLG1CQUFtQixFQUFFLENBQUMsQ0FBQztnQkFDM0UsQ0FBQztZQUNILENBQUM7WUFFRCxLQUFLLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO2dCQUMxQiwrREFBK0Q7Z0JBQy9ELElBQUksQ0FBQztvQkFDSCxNQUFNLFFBQVEsR0FBRyxNQUFNLE9BQU8sQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDO3dCQUNwRCxJQUFJLEVBQUUsYUFBYTt3QkFDbkIsV0FBVyxFQUFFLG9CQUFvQjt3QkFDakMsWUFBWSxFQUFFLFlBQVk7d0JBQzFCLE9BQU8sRUFBRSxPQUFPLElBQUksRUFBRTt3QkFDdEIsUUFBUSxFQUFFLFNBQVM7cUJBQ3BCLENBQUMsQ0FBQztvQkFDSCxNQUFNLFVBQVUsR0FBRyxHQUFHLFdBQVcsdUJBQXVCLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxnQkFBZ0IsQ0FBQztvQkFDL0YsT0FBTyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsR0FBRyxPQUFPLENBQUMsbUJBQW1CLEVBQUUsR0FBRyxVQUFVLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQztnQkFDaEcsQ0FBQztnQkFBQyxPQUFPLGFBQWEsRUFBRSxDQUFDO29CQUN2QixrQ0FBa0M7b0JBQ2xDLE1BQU0sT0FBTyxHQUFHLGFBQWEsWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztvQkFDL0YsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQzt3QkFDdEQsQ0FBQyxDQUFDLG9CQUFvQixDQUFDLFdBQVcsQ0FBQyxRQUFRLEVBQUUsYUFBYSxDQUFDO3dCQUMzRCxDQUFDLENBQUMsb0JBQW9CLENBQUMsYUFBYSxFQUFFLFFBQVEsRUFBRSxXQUFXLENBQUMsUUFBUSxFQUFFLGFBQWEsQ0FBQyxDQUFDO29CQUN2RixPQUFPLG1CQUFtQixDQUFDLGFBQWEsRUFBRSxPQUFPLENBQUMsbUJBQW1CLEVBQUUsQ0FBQyxDQUFDO2dCQUMzRSxDQUFDO1lBQ0gsQ0FBQztZQUVELEtBQUssV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7Z0JBQ3ZCLHdFQUF3RTtnQkFDeEUsMEVBQTBFO2dCQUMxRSxJQUFJLENBQUM7b0JBQ0gsNkVBQTZFO29CQUM3RSxnRkFBZ0Y7b0JBQ2hGLDJFQUEyRTtvQkFDM0UsTUFBTSxpQkFBaUIsR0FBRyxZQUFZLElBQUksRUFBRSxDQUFDO29CQUM3QyxNQUFNLFlBQVksR0FBRyxPQUFPLElBQUksRUFBRSxDQUFDO29CQUNuQyxNQUFNLEtBQUssR0FBRyxNQUFNLE9BQU8sQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUM3QyxhQUFhLEVBQ2Isb0JBQW9CLEVBQ3BCLGlCQUFpQixFQUNqQixFQUFFLEdBQUcsU0FBUyxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsQ0FDeEMsQ0FBQztvQkFDRixJQUFJLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQzt3QkFDbEIsTUFBTSxXQUFXLEdBQUcsS0FBSyxDQUFDLE9BQU8sSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQUM7NEJBQ3hGLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTzs0QkFDZixDQUFDLENBQUMsa0JBQWtCLGFBQWEsZ0JBQWdCLENBQUM7d0JBQ3BELE1BQU0sVUFBVSxHQUFHLEdBQUcsV0FBVyxLQUFLLFdBQVcsRUFBRSxDQUFDO3dCQUNwRCxPQUFPLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLE9BQU8sQ0FBQyxtQkFBbUIsRUFBRSxHQUFHLFVBQVUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDO29CQUNoRyxDQUFDO29CQUNELHNGQUFzRjtvQkFDdEYsTUFBTSxhQUFhLEdBQUcsS0FBSyxDQUFDLE9BQU8sSUFBSSxlQUFlLENBQUM7b0JBQ3ZELE9BQU8seUJBQXlCLENBQUMsMkJBQTJCLGFBQWEsRUFBRSxDQUFDLENBQUM7Z0JBQy9FLENBQUM7Z0JBQUMsT0FBTyxVQUFVLEVBQUUsQ0FBQztvQkFDcEIsTUFBTSxPQUFPLEdBQUcsVUFBVSxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO29CQUN0RixNQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDO3dCQUN0RCxDQUFDLENBQUMsb0JBQW9CLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxhQUFhLENBQUM7d0JBQ3hELENBQUMsQ0FBQyxvQkFBb0IsQ0FBQyxVQUFVLEVBQUUsUUFBUSxFQUFFLFdBQVcsQ0FBQyxLQUFLLEVBQUUsYUFBYSxDQUFDLENBQUM7b0JBQ2pGLE9BQU8sbUJBQW1CLENBQUMsYUFBYSxFQUFFLE9BQU8sQ0FBQyxtQkFBbUIsRUFBRSxDQUFDLENBQUM7Z0JBQzNFLENBQUM7WUFDSCxDQUFDO1lBRUQsS0FBSyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztnQkFDeEIsSUFBSSxDQUFDO29CQUNILE1BQU0sTUFBTSxHQUFHLE1BQU0sT0FBTyxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUM7d0JBQ2hELEdBQUcsU0FBUzt3QkFDWixJQUFJLEVBQUUsYUFBYTt3QkFDbkIsV0FBVyxFQUFFLG9CQUFvQjt3QkFDakMsT0FBTyxFQUFFLE9BQU87d0JBQ2hCLFlBQVksRUFBRSxZQUFZO3FCQUMzQixDQUFDLENBQUM7b0JBQ0gsTUFBTSxVQUFVLEdBQUcsR0FBRyxXQUFXLHFCQUFxQixNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksZ0JBQWdCLENBQUM7b0JBQzNGLE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixFQUFFLEdBQUcsVUFBVSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQ2hHLENBQUM7Z0JBQUMsT0FBTyxXQUFXLEVBQUUsQ0FBQztvQkFDckIsTUFBTSxPQUFPLEdBQUcsV0FBVyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDO29CQUN6RixNQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDO3dCQUN0RCxDQUFDLENBQUMsb0JBQW9CLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxhQUFhLENBQUM7d0JBQ3pELENBQUMsQ0FBQyxvQkFBb0IsQ0FBQyxXQUFXLEVBQUUsUUFBUSxFQUFFLFdBQVcsQ0FBQyxNQUFNLEVBQUUsYUFBYSxDQUFDLENBQUM7b0JBQ25GLE9BQU8sbUJBQW1CLENBQUMsYUFBYSxFQUFFLE9BQU8sQ0FBQyxtQkFBbUIsRUFBRSxDQUFDLENBQUM7Z0JBQzNFLENBQUM7WUFDSCxDQUFDO1lBRUQsS0FBSyxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztnQkFDMUIsSUFBSSxDQUFDO29CQUNILDhFQUE4RTtvQkFDOUUsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLG1CQUFtQixDQUNoRCxTQUFTLENBQUMsUUFBUSxJQUFJLEVBQUUsRUFDeEI7d0JBQ0UsWUFBWSxFQUFFLE9BQU8sQ0FBQyxZQUFZO3dCQUNsQyxlQUFlLEVBQUUsT0FBTyxDQUFDLGVBQWU7d0JBQ3hDLFlBQVksRUFBRSxPQUFPLENBQUMsWUFBWTt3QkFDbEMsYUFBYSxFQUFFLE9BQU8sQ0FBQyxhQUFhO3dCQUNwQyxjQUFjLEVBQUUsT0FBTyxDQUFDLGNBQWM7d0JBQ3RDLGVBQWUsRUFBRSxPQUFPLENBQUMsZUFBZTtxQkFDekMsQ0FDRixDQUFDO29CQUNGLE1BQU0scUJBQXFCLEdBQUcsK0JBQStCLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztvQkFFaEYsTUFBTSxRQUFRLEdBQUcsTUFBTSxPQUFPLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQzt3QkFDcEQsR0FBRyxTQUFTO3dCQUNaLElBQUksRUFBRSxhQUFhO3dCQUNuQixXQUFXLEVBQUUsb0JBQW9CO3dCQUNqQyxRQUFRLEVBQUUsZ0JBQWdCLENBQUMsUUFBUTt3QkFDbkMsWUFBWSxFQUFFLFlBQVk7d0JBQzFCLE9BQU8sRUFBRSxPQUFPO3FCQUNqQixDQUFDLENBQUM7b0JBQ0gsTUFBTSxVQUFVLEdBQUcsR0FBRyxXQUFXLEdBQUcscUJBQXFCLHVCQUF1QixRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksZ0JBQWdCLENBQUM7b0JBQ3ZILE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixFQUFFLEdBQUcsVUFBVSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQ2hHLENBQUM7Z0JBQUMsT0FBTyxhQUFhLEVBQUUsQ0FBQztvQkFDdkIsTUFBTSxPQUFPLEdBQUcsYUFBYSxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO29CQUMvRixNQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDO3dCQUN0RCxDQUFDLENBQUMsb0JBQW9CLENBQUMsV0FBVyxDQUFDLFFBQVEsRUFBRSxhQUFhLENBQUM7d0JBQzNELENBQUMsQ0FBQyxvQkFBb0IsQ0FBQyxhQUFhLEVBQUUsUUFBUSxFQUFFLFdBQVcsQ0FBQyxRQUFRLEVBQUUsYUFBYSxDQUFDLENBQUM7b0JBQ3ZGLE9BQU8sbUJBQW1CLENBQUMsYUFBYSxFQUFFLE9BQU8sQ0FBQyxtQkFBbUIsRUFBRSxDQUFDLENBQUM7Z0JBQzNFLENBQUM7WUFDSCxDQUFDO1lBRUQ7Z0JBQ0UsT0FBTztvQkFDTCxPQUFPLEVBQUUsQ0FBQzs0QkFDUixJQUFJLEVBQUUsTUFBTTs0QkFDWixJQUFJLEVBQUUsbUJBQW1CLElBQUkscUNBQXFDO3lCQUNuRSxDQUFDO2lCQUNILENBQUM7UUFDTixDQUFDO0lBQ0gsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixNQUFNLENBQUMsS0FBSyxDQUFDLGtDQUFrQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3hELE1BQU0sT0FBTyxHQUFHLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQztRQUN6RSxNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztRQUNoRCxPQUFPO1lBQ0wsT0FBTyxFQUFFLENBQUM7b0JBQ1IsSUFBSSxFQUFFLE1BQU07b0JBQ1osSUFBSSxFQUFFLEdBQUcsU0FBUywrQkFBK0IsT0FBTyxFQUFFO2lCQUMzRCxDQUFDO1NBQ0gsQ0FBQztJQUNKLENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBGSVg6IERNQ1AtU0VDLTAwNiAtIFNlY3VyaXR5IGF1ZGl0IHN1cHByZXNzaW9uXG4gKiBUaGlzIGZpbGUgZGVsZWdhdGVzIGVsZW1lbnQgY3JlYXRpb24gdG8gc3BlY2lhbGl6ZWQgbWFuYWdlcnMuXG4gKiBBdWRpdCBsb2dnaW5nIGhhcHBlbnMgaW4gdGhlIG1hbmFnZXJzIHRoZW1zZWx2ZXMgKFBlcnNvbmFNYW5hZ2VyLCBTa2lsbE1hbmFnZXIsIGV0Yy4pLlxuICogQHNlY3VyaXR5LWF1ZGl0LXN1cHByZXNzIERNQ1AtU0VDLTAwNlxuICovXG5cbmltcG9ydCB7IEVsZW1lbnRUeXBlIH0gZnJvbSAnLi4vLi4vcG9ydGZvbGlvL1BvcnRmb2xpb01hbmFnZXIuanMnO1xuaW1wb3J0IHsgU0VDVVJJVFlfTElNSVRTIH0gZnJvbSAnLi4vLi4vc2VjdXJpdHkvY29uc3RhbnRzLmpzJztcbmltcG9ydCB7IHNhbml0aXplSW5wdXQsIHZhbGlkYXRlQ29udGVudFNpemUsIHZhbGlkYXRlQ2F0ZWdvcnkgfSBmcm9tICcuLi8uLi9zZWN1cml0eS9JbnB1dFZhbGlkYXRvci5qcyc7XG5pbXBvcnQge1xuICBzYW5pdGl6ZU1ldGFkYXRhLFxuICBub3JtYWxpemVFbGVtZW50VHlwZUlucHV0LFxuICBmb3JtYXRWYWxpZEVsZW1lbnRUeXBlc0xpc3QsXG4gIGRldGVjdFVua25vd25NZXRhZGF0YVByb3BlcnRpZXMsXG4gIGZvcm1hdFVua25vd25Qcm9wZXJ0eVdhcm5pbmdzLFxuICBmb3JtYXRFbGVtZW50UmVzb2x1dGlvbldhcm5pbmdzLFxuICBjb2xsZWN0R2F0ZWtlZXBlckF1dGhvcmluZ0Vycm9ycyxcbiAgZm9ybWF0R2F0ZWtlZXBlclZhbGlkYXRpb25NZXNzYWdlLFxufSBmcm9tICcuL2hlbHBlcnMuanMnO1xuaW1wb3J0IHsgcmVzb2x2ZUVsZW1lbnRUeXBlcyB9IGZyb20gJy4uLy4uL3V0aWxzL2VsZW1lbnRUeXBlUmVzb2x2ZXIuanMnO1xuaW1wb3J0IHsgRWxlbWVudENydWRDb250ZXh0IH0gZnJvbSAnLi90eXBlcy5qcyc7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi8uLi91dGlscy9sb2dnZXIuanMnO1xuLy8gRklYOiBJc3N1ZSAjMjgxIC0gU2VjdXJpdHlNb25pdG9yIGltcG9ydCByZW1vdmVkLCBwZXJzb25hIGxvZ2dpbmcgbm93IGluIFBlcnNvbmFNYW5hZ2VyLmNyZWF0ZSgpXG5pbXBvcnQge1xuICBmb3JtYXRTaW1wbGVFcnJvclJlc3BvbnNlLFxuICBmb3JtYXREdXBsaWNhdGVFcnJvcixcbiAgZm9ybWF0RXhjZXB0aW9uRXJyb3Jcbn0gZnJvbSAnLi9yZXNwb25zZUZvcm1hdHRlci5qcyc7XG5pbXBvcnQgdHlwZSB7IE1jcFRvb2xSZXNwb25zZSB9IGZyb20gJy4vcmVzcG9uc2VGb3JtYXR0ZXIuanMnO1xuaW1wb3J0IHR5cGUgeyBFbnNlbWJsZUVsZW1lbnQgfSBmcm9tICcuLi8uLi9lbGVtZW50cy9lbnNlbWJsZXMvdHlwZXMuanMnO1xuXG4vKipcbiAqIEFyZ3VtZW50cyBmb3IgY3JlYXRpbmcgYSBuZXcgZWxlbWVudC5cbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gQ3JlYXRlIGEgcGVyc29uYVxuICogeyBuYW1lOiAnaGVscGVyJywgdHlwZTogJ3BlcnNvbmEnLCBkZXNjcmlwdGlvbjogJ0EgaGVscGZ1bCBhc3Npc3RhbnQnLCBpbnN0cnVjdGlvbnM6ICdCZSBoZWxwZnVsJyB9XG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIENyZWF0ZSBhbiBlbnNlbWJsZSB3aXRoIGVsZW1lbnRzXG4gKiB7XG4gKiAgIG5hbWU6ICdteS1lbnNlbWJsZScsXG4gKiAgIHR5cGU6ICdlbnNlbWJsZScsXG4gKiAgIGRlc2NyaXB0aW9uOiAnQSBjb29yZGluYXRlZCBncm91cCcsXG4gKiAgIGVsZW1lbnRzOiBbeyBuYW1lOiAnc2tpbGwxJywgdHlwZTogJ3NraWxsJywgcm9sZTogJ3ByaW1hcnknLCBwcmlvcml0eTogMTAwLCBhY3RpdmF0aW9uOiAnYWx3YXlzJyB9XVxuICogfVxuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBDcmVhdGUgYSBWMiBhZ2VudCB3aXRoIGdvYWwgY29uZmlndXJhdGlvblxuICoge1xuICogICBuYW1lOiAndGFzay1ydW5uZXInLFxuICogICB0eXBlOiAnYWdlbnQnLFxuICogICBkZXNjcmlwdGlvbjogJ0V4ZWN1dGVzIHRhc2tzIGF1dG9ub21vdXNseScsXG4gKiAgIGdvYWw6IHtcbiAqICAgICB0ZW1wbGF0ZTogJ0NvbXBsZXRlIHRoZSBmb2xsb3dpbmcgdGFzazoge29iamVjdGl2ZX0nLFxuICogICAgIHBhcmFtZXRlcnM6IFt7IG5hbWU6ICdvYmplY3RpdmUnLCB0eXBlOiAnc3RyaW5nJywgcmVxdWlyZWQ6IHRydWUgfV0sXG4gKiAgICAgc3VjY2Vzc0NyaXRlcmlhOiBbJ1Rhc2sgY29tcGxldGVkIHN1Y2Nlc3NmdWxseScsICdSZXN1bHRzIGRvY3VtZW50ZWQnXVxuICogICB9LFxuICogICBhY3RpdmF0ZXM6IHsgc2tpbGxzOiBbJ2NvZGUtcmV2aWV3J10sIHBlcnNvbmFzOiBbJ2RldmVsb3BlciddIH1cbiAqIH1cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDcmVhdGVFbGVtZW50QXJncyB7XG4gIG5hbWU6IHN0cmluZztcbiAgdHlwZTogc3RyaW5nO1xuICBkZXNjcmlwdGlvbjogc3RyaW5nO1xuICAvKiogUmVmZXJlbmNlIG1hdGVyaWFsLCBrbm93bGVkZ2UsIGNvbnRleHQgKGluZm9ybWF0aW9uYWwpLiBGb3IgdGVtcGxhdGVzOiB0ZW1wbGF0ZSBib2R5LiAqL1xuICBjb250ZW50Pzogc3RyaW5nO1xuICAvKiogQmVoYXZpb3JhbCBkaXJlY3RpdmVzIChjb21tYW5kIHZvaWNlKS4gRm9yIHBlcnNvbmFzOiBiZWhhdmlvcmFsIHByb2ZpbGUuIEZvciBza2lsbHM6IGhvdyB0byBhcHBseS4gRm9yIGFnZW50czogYWdlbnQgYmVoYXZpb3JhbCBwcm90b2NvbC4gKi9cbiAgaW5zdHJ1Y3Rpb25zPzogc3RyaW5nO1xuICBtZXRhZGF0YT86IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAvKipcbiAgICogRm9yIGVuc2VtYmxlcyAtIGFycmF5IG9mIGVsZW1lbnQgcmVmZXJlbmNlcy5cbiAgICogSXNzdWUgIzI3ODogTExNcyBvZnRlbiBwYXNzIGVsZW1lbnRzIGF0IHRvcCBsZXZlbCwgbm90IGluc2lkZSBtZXRhZGF0YS5cbiAgICovXG4gIGVsZW1lbnRzPzogRW5zZW1ibGVFbGVtZW50W107XG5cbiAgLy8gVjIgQWdlbnQgZmllbGRzIChjYW4gYWxzbyBiZSBwYXNzZWQgaW4gbWV0YWRhdGEpXG4gIC8qKlxuICAgKiBGb3IgVjIgYWdlbnRzIC0gZ29hbCBjb25maWd1cmF0aW9uIHdpdGggdGVtcGxhdGUgYW5kIHBhcmFtZXRlcnMuXG4gICAqIENhbiBiZSBwYXNzZWQgYXMgYSBzaW1wbGUgc3RyaW5nICh3aWxsIGJlIGNvbnZlcnRlZCB0byBWMiBmb3JtYXQpXG4gICAqIG9yIGFzIGEgZnVsbCBWMiBjb25maWcgb2JqZWN0LlxuICAgKlxuICAgKiBAc2luY2UgdjIuMC4wIC0gQWdlbnQgVjIgSW5mcmFzdHJ1Y3R1cmVcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogLy8gU2ltcGxlIHN0cmluZyBnb2FsIChhdXRvLWNvbnZlcnRlZCB0byBWMiBmb3JtYXQpXG4gICAqIGdvYWw6ICdDb21wbGV0ZSB0aGUgYW5hbHlzaXMgdGFzaydcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogLy8gRnVsbCBWMiBjb25maWcgd2l0aCBwYXJhbWV0ZXJzXG4gICAqIGdvYWw6IHtcbiAgICogICB0ZW1wbGF0ZTogJ0FuYWx5emUge3RhcmdldH0gZm9yIHtwdXJwb3NlfScsXG4gICAqICAgcGFyYW1ldGVyczogW1xuICAgKiAgICAgeyBuYW1lOiAndGFyZ2V0JywgdHlwZTogJ3N0cmluZycsIHJlcXVpcmVkOiB0cnVlIH0sXG4gICAqICAgICB7IG5hbWU6ICdwdXJwb3NlJywgdHlwZTogJ3N0cmluZycsIHJlcXVpcmVkOiB0cnVlIH1cbiAgICogICBdLFxuICAgKiAgIHN1Y2Nlc3NDcml0ZXJpYTogWydBbmFseXNpcyBjb21wbGV0ZScsICdSZXBvcnQgZ2VuZXJhdGVkJ11cbiAgICogfVxuICAgKi9cbiAgZ29hbD86IHN0cmluZyB8IHtcbiAgICB0ZW1wbGF0ZTogc3RyaW5nO1xuICAgIHBhcmFtZXRlcnM/OiBBcnJheTx7XG4gICAgICBuYW1lOiBzdHJpbmc7XG4gICAgICB0eXBlOiAnc3RyaW5nJyB8ICdudW1iZXInIHwgJ2Jvb2xlYW4nO1xuICAgICAgcmVxdWlyZWQ6IGJvb2xlYW47XG4gICAgICBkZXNjcmlwdGlvbj86IHN0cmluZztcbiAgICAgIGRlZmF1bHQ/OiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuO1xuICAgIH0+O1xuICAgIHN1Y2Nlc3NDcml0ZXJpYT86IHN0cmluZ1tdO1xuICB9O1xuICAvKipcbiAgICogRm9yIFYyIGFnZW50cyAtIGVsZW1lbnRzIHRvIGFjdGl2YXRlIHdoZW4gYWdlbnQgZXhlY3V0ZXMuXG4gICAqIEBzaW5jZSB2Mi4wLjAgLSBBZ2VudCBWMiBJbmZyYXN0cnVjdHVyZVxuICAgKi9cbiAgYWN0aXZhdGVzPzoge1xuICAgIHBlcnNvbmFzPzogc3RyaW5nW107XG4gICAgc2tpbGxzPzogc3RyaW5nW107XG4gICAgbWVtb3JpZXM/OiBzdHJpbmdbXTtcbiAgICB0ZW1wbGF0ZXM/OiBzdHJpbmdbXTtcbiAgICBlbnNlbWJsZXM/OiBzdHJpbmdbXTtcbiAgICBba2V5OiBzdHJpbmddOiBzdHJpbmdbXSB8IHVuZGVmaW5lZDtcbiAgfTtcbiAgLyoqXG4gICAqIEZvciBWMiBhZ2VudHMgLSB0b29sIGNvbmZpZ3VyYXRpb24gKGluZm9ybWF0aW9uYWwpLlxuICAgKiBAc2luY2UgdjIuMC4wIC0gQWdlbnQgVjIgSW5mcmFzdHJ1Y3R1cmVcbiAgICovXG4gIHRvb2xzPzoge1xuICAgIGFsbG93ZWQ6IHN0cmluZ1tdO1xuICAgIGRlbmllZD86IHN0cmluZ1tdO1xuICB9O1xuICAvKipcbiAgICogRm9yIFYyIGFnZW50cyAtIGN1c3RvbSBzeXN0ZW0gcHJvbXB0IGZvciBMTE0gY29udGV4dC5cbiAgICogQHNpbmNlIHYyLjAuMCAtIEFnZW50IFYyIEluZnJhc3RydWN0dXJlXG4gICAqL1xuICBzeXN0ZW1Qcm9tcHQ/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogSGVscGVyIHRvIGFkZCBwZXJzb25hIGluZGljYXRvciBwcmVmaXggdG8gcmVzcG9uc2VcbiAqL1xuZnVuY3Rpb24gYWRkUGVyc29uYUluZGljYXRvcihyZXNwb25zZTogTWNwVG9vbFJlc3BvbnNlLCBpbmRpY2F0b3I6IHN0cmluZykge1xuICByZXR1cm4ge1xuICAgIC4uLnJlc3BvbnNlLFxuICAgIGNvbnRlbnQ6IHJlc3BvbnNlLmNvbnRlbnQubWFwKGMgPT4gKHtcbiAgICAgIC4uLmMsXG4gICAgICB0ZXh0OiBgJHtpbmRpY2F0b3J9JHtjLnRleHR9YFxuICAgIH0pKVxuICB9O1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlRWxlbWVudChjb250ZXh0OiBFbGVtZW50Q3J1ZENvbnRleHQsIGFyZ3M6IENyZWF0ZUVsZW1lbnRBcmdzKSB7XG4gIGF3YWl0IGNvbnRleHQuZW5zdXJlSW5pdGlhbGl6ZWQoKTtcblxuICB0cnkge1xuICAgIGNvbnN0IHsgbmFtZSwgdHlwZSwgZGVzY3JpcHRpb24sIGNvbnRlbnQsIGluc3RydWN0aW9ucywgbWV0YWRhdGEgfSA9IGFyZ3M7XG5cbiAgICBjb25zdCB7IHR5cGU6IG5vcm1hbGl6ZWRUeXBlIH0gPSBub3JtYWxpemVFbGVtZW50VHlwZUlucHV0KHR5cGUpO1xuXG4gICAgaWYgKCFub3JtYWxpemVkVHlwZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY29udGVudDogW3tcbiAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICB0ZXh0OiBg4p2MIEludmFsaWQgZWxlbWVudCB0eXBlICcke3R5cGV9Jy4gVmFsaWQgdHlwZXM6ICR7Zm9ybWF0VmFsaWRFbGVtZW50VHlwZXNMaXN0KCl9YFxuICAgICAgICB9XVxuICAgICAgfTtcbiAgICB9XG5cbiAgICBjb25zdCB2YWxpZGF0ZWROYW1lID0gc2FuaXRpemVJbnB1dChuYW1lLCBTRUNVUklUWV9MSU1JVFMuTUFYX0ZJTEVOQU1FX0xFTkdUSCk7XG5cbiAgICBpZiAoZGVzY3JpcHRpb24ubGVuZ3RoID4gU0VDVVJJVFlfTElNSVRTLk1BWF9ERVNDUklQVElPTl9MRU5HVEgpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbnRlbnQ6IFt7XG4gICAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgICAgdGV4dDogYOKdjCBEZXNjcmlwdGlvbiB0b28gbGFyZ2U6IE1heGltdW0gYWxsb3dlZCBzaXplIGlzICR7U0VDVVJJVFlfTElNSVRTLk1BWF9ERVNDUklQVElPTl9MRU5HVEh9IGNoYXJhY3RlcnMuYFxuICAgICAgICB9XVxuICAgICAgfTtcbiAgICB9XG5cbiAgICBjb25zdCB2YWxpZGF0ZWREZXNjcmlwdGlvbiA9IHNhbml0aXplSW5wdXQoZGVzY3JpcHRpb24sIFNFQ1VSSVRZX0xJTUlUUy5NQVhfREVTQ1JJUFRJT05fTEVOR1RIKTtcblxuICAgIGlmIChjb250ZW50KSB7XG4gICAgICB0cnkge1xuICAgICAgICB2YWxpZGF0ZUNvbnRlbnRTaXplKGNvbnRlbnQsIFNFQ1VSSVRZX0xJTUlUUy5NQVhfQ09OVEVOVF9MRU5HVEgpO1xuICAgICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGNvbnRlbnQ6IFt7XG4gICAgICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgICAgIHRleHQ6IGDinYwgQ29udGVudCB0b28gbGFyZ2U6ICR7ZXJyb3IubWVzc2FnZX0uIE1heGltdW0gYWxsb3dlZCBzaXplIGlzICR7U0VDVVJJVFlfTElNSVRTLk1BWF9DT05URU5UX0xFTkdUSH0gY2hhcmFjdGVycyAoJHtNYXRoLmZsb29yKFNFQ1VSSVRZX0xJTUlUUy5NQVhfQ09OVEVOVF9MRU5HVEggLyAxMDI0KX1LQikuYFxuICAgICAgICAgIH1dXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gSXNzdWUgIzYwMiByZXNvbHZlZDogQm90aCAnaW5zdHJ1Y3Rpb25zJyBhbmQgJ2NvbnRlbnQnIGFyZSBmaXJzdC1jbGFzcyBmaWVsZHMuXG4gICAgLy8gaW5zdHJ1Y3Rpb25zID0gYmVoYXZpb3JhbCBkaXJlY3RpdmVzIChjb21tYW5kIHZvaWNlLCBcIllvdSBBUkUuLi5cIiwgXCJBTFdBWVMuLi5cIilcbiAgICAvLyBjb250ZW50ID0gcmVmZXJlbmNlIG1hdGVyaWFsIChpbmZvcm1hdGlvbmFsLCBkb21haW4ga25vd2xlZGdlLCBleGFtcGxlcylcbiAgICBpZiAoaW5zdHJ1Y3Rpb25zKSB7XG4gICAgICB0cnkge1xuICAgICAgICB2YWxpZGF0ZUNvbnRlbnRTaXplKGluc3RydWN0aW9ucywgU0VDVVJJVFlfTElNSVRTLk1BWF9DT05URU5UX0xFTkdUSCk7XG4gICAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgY29udGVudDogW3tcbiAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgdGV4dDogYOKdjCBJbnN0cnVjdGlvbnMgdG9vIGxhcmdlOiAke2Vycm9yLm1lc3NhZ2V9LiBNYXhpbXVtIGFsbG93ZWQgc2l6ZSBpcyAke1NFQ1VSSVRZX0xJTUlUUy5NQVhfQ09OVEVOVF9MRU5HVEh9IGNoYXJhY3RlcnMuYFxuICAgICAgICAgIH1dXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRWxlbWVudC1zcGVjaWZpYyBmaWVsZHMgKGVuc2VtYmxlIGVsZW1lbnRzLCBhZ2VudCBWMiBmaWVsZHMpIGFyZSBtZXJnZWQgaW50b1xuICAgIC8vIG1ldGFkYXRhIGJ5IHRoZSBkaXNwYXRjaGVyIChNQ1BBUUxIYW5kbGVyKS4gY3JlYXRlRWxlbWVudCBqdXN0IHNhbml0aXplcyBhbmQgZGVsZWdhdGVzLlxuICAgIGNvbnN0IHNhbml0aXplZCA9IHNhbml0aXplTWV0YWRhdGEobWV0YWRhdGEpO1xuXG4gICAgY29uc3QgZ2F0ZWtlZXBlckVycm9ycyA9IGNvbGxlY3RHYXRla2VlcGVyQXV0aG9yaW5nRXJyb3JzKHsgLi4uYXJncyB9LCBzYW5pdGl6ZWQpO1xuICAgIGlmIChnYXRla2VlcGVyRXJyb3JzLmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVybiBmb3JtYXRTaW1wbGVFcnJvclJlc3BvbnNlKGZvcm1hdEdhdGVrZWVwZXJWYWxpZGF0aW9uTWVzc2FnZShnYXRla2VlcGVyRXJyb3JzKSk7XG4gICAgfVxuXG4gICAgLy8gSXNzdWUgIzYyMTogVmFsaWRhdGUgY2F0ZWdvcnkgZm9ybWF0IGZvciBlbGVtZW50IHR5cGVzIHRoYXQgc3VwcG9ydCBpdFxuICAgIC8vIFBlcnNvbmEgYWxzbyBzdXBwb3J0cyBjYXRlZ29yaWVzICh2YWxpZGF0ZWQgaW50ZXJuYWxseSBieSBQZXJzb25hTWFuYWdlcikg4oCUIGluY2x1ZGUgaGVyZSBmb3IgY29uc2lzdGVudCBlYXJseSBlcnJvciByZXBvcnRpbmdcbiAgICBjb25zdCBDQVRFR09SWV9UWVBFUyA9IG5ldyBTZXQoW0VsZW1lbnRUeXBlLlBFUlNPTkEsIEVsZW1lbnRUeXBlLlNLSUxMLCBFbGVtZW50VHlwZS5URU1QTEFURSwgRWxlbWVudFR5cGUuTUVNT1JZXSk7XG4gICAgaWYgKHNhbml0aXplZC5jYXRlZ29yeSAmJiBDQVRFR09SWV9UWVBFUy5oYXMobm9ybWFsaXplZFR5cGUpKSB7XG4gICAgICB0cnkge1xuICAgICAgICB2YWxpZGF0ZUNhdGVnb3J5KHNhbml0aXplZC5jYXRlZ29yeSBhcyBzdHJpbmcpO1xuICAgICAgfSBjYXRjaCAoY2F0ZWdvcnlFcnJvcjogYW55KSB7XG4gICAgICAgIHJldHVybiBmb3JtYXRTaW1wbGVFcnJvclJlc3BvbnNlKFxuICAgICAgICAgIGBJbnZhbGlkIGNhdGVnb3J5ICcke3Nhbml0aXplZC5jYXRlZ29yeX0nOiAke2NhdGVnb3J5RXJyb3IubWVzc2FnZX1gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRGV0ZWN0IHVua25vd24gbWV0YWRhdGEgcHJvcGVydGllcyBhbmQgZ2VuZXJhdGUgd2FybmluZ3MgZm9yIExMTSBmZWVkYmFja1xuICAgIGNvbnN0IHVua25vd25Qcm9wZXJ0eVdhcm5pbmdzID0gZGV0ZWN0VW5rbm93bk1ldGFkYXRhUHJvcGVydGllcyhcbiAgICAgIG5vcm1hbGl6ZWRUeXBlLFxuICAgICAgbWV0YWRhdGEgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj5cbiAgICApO1xuICAgIGNvbnN0IHdhcm5pbmdUZXh0ID0gZm9ybWF0VW5rbm93blByb3BlcnR5V2FybmluZ3ModW5rbm93blByb3BlcnR5V2FybmluZ3MpO1xuXG4gICAgLy8gTG9nIHdhcm5pbmdzIGZvciBkZWJ1Z2dpbmcgd2l0aCBzdHJ1Y3R1cmVkIGRhdGEgZm9yIGJldHRlciBvYnNlcnZhYmlsaXR5XG4gICAgaWYgKHVua25vd25Qcm9wZXJ0eVdhcm5pbmdzLmxlbmd0aCA+IDApIHtcbiAgICAgIGxvZ2dlci53YXJuKGBbY3JlYXRlRWxlbWVudF0gVW5rbm93biBtZXRhZGF0YSBwcm9wZXJ0aWVzIGRldGVjdGVkYCwge1xuICAgICAgICBlbGVtZW50VHlwZTogbm9ybWFsaXplZFR5cGUsXG4gICAgICAgIGVsZW1lbnROYW1lOiBuYW1lLFxuICAgICAgICB3YXJuaW5nQ291bnQ6IHVua25vd25Qcm9wZXJ0eVdhcm5pbmdzLmxlbmd0aCxcbiAgICAgICAgdW5rbm93blByb3BlcnRpZXM6IHVua25vd25Qcm9wZXJ0eVdhcm5pbmdzLm1hcCh3ID0+ICh7XG4gICAgICAgICAgcHJvcGVydHk6IHcucHJvcGVydHksXG4gICAgICAgICAgc3VnZ2VzdGlvbjogdy5zdWdnZXN0aW9uXG4gICAgICAgIH0pKVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgc3dpdGNoIChub3JtYWxpemVkVHlwZSkge1xuICAgICAgY2FzZSBFbGVtZW50VHlwZS5QRVJTT05BOiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgLy8gSXNzdWUgIzYwMjogQm90aCAnaW5zdHJ1Y3Rpb25zJyBhbmQgJ2NvbnRlbnQnIGFyZSBmaXJzdC1jbGFzcyBmaWVsZHMuXG4gICAgICAgICAgY29uc3QgcGVyc29uYSA9IGF3YWl0IGNvbnRleHQucGVyc29uYU1hbmFnZXIuY3JlYXRlKHtcbiAgICAgICAgICAgIC4uLnNhbml0aXplZCxcbiAgICAgICAgICAgIG5hbWU6IHZhbGlkYXRlZE5hbWUsXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjogdmFsaWRhdGVkRGVzY3JpcHRpb24sXG4gICAgICAgICAgICBpbnN0cnVjdGlvbnM6IGluc3RydWN0aW9ucyxcbiAgICAgICAgICAgIGNvbnRlbnQ6IGNvbnRlbnQsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBjb25zdCBzdWNjZXNzTXNnID0gYCR7d2FybmluZ1RleHR94pyFIENyZWF0ZWQgcGVyc29uYSAnJHtwZXJzb25hLm1ldGFkYXRhLm5hbWV9JyBzdWNjZXNzZnVsbHlgO1xuICAgICAgICAgIHJldHVybiB7IGNvbnRlbnQ6IFt7IHR5cGU6IFwidGV4dFwiLCB0ZXh0OiBgJHtjb250ZXh0LmdldFBlcnNvbmFJbmRpY2F0b3IoKX0ke3N1Y2Nlc3NNc2d9YCB9XSB9O1xuICAgICAgICB9IGNhdGNoIChwZXJzb25hRXJyb3IpIHtcbiAgICAgICAgICBjb25zdCBtZXNzYWdlID0gcGVyc29uYUVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBwZXJzb25hRXJyb3IubWVzc2FnZSA6IFN0cmluZyhwZXJzb25hRXJyb3IpO1xuICAgICAgICAgIGlmIChtZXNzYWdlLmluY2x1ZGVzKCdpbnN0cnVjdGlvbnMgYXJlIHJlcXVpcmVkJykpIHtcbiAgICAgICAgICAgIHJldHVybiBmb3JtYXRTaW1wbGVFcnJvclJlc3BvbnNlKG1lc3NhZ2UpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBlcnJvclJlc3BvbnNlID0gbWVzc2FnZS5pbmNsdWRlcygnYWxyZWFkeSBleGlzdHMnKVxuICAgICAgICAgICAgPyBmb3JtYXREdXBsaWNhdGVFcnJvcihFbGVtZW50VHlwZS5QRVJTT05BLCB2YWxpZGF0ZWROYW1lKVxuICAgICAgICAgICAgOiBmb3JtYXRFeGNlcHRpb25FcnJvcihwZXJzb25hRXJyb3IsICdjcmVhdGUnLCBFbGVtZW50VHlwZS5QRVJTT05BLCB2YWxpZGF0ZWROYW1lKTtcbiAgICAgICAgICByZXR1cm4gYWRkUGVyc29uYUluZGljYXRvcihlcnJvclJlc3BvbnNlLCBjb250ZXh0LmdldFBlcnNvbmFJbmRpY2F0b3IoKSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY2FzZSBFbGVtZW50VHlwZS5TS0lMTDoge1xuICAgICAgICAvLyBGSVg6IElzc3VlICMyMCAtIENhdGNoIGR1cGxpY2F0ZSBlcnJvcnMgZnJvbSBTa2lsbE1hbmFnZXJcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBza2lsbCA9IGF3YWl0IGNvbnRleHQuc2tpbGxNYW5hZ2VyLmNyZWF0ZSh7XG4gICAgICAgICAgICBuYW1lOiB2YWxpZGF0ZWROYW1lLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IHZhbGlkYXRlZERlc2NyaXB0aW9uLFxuICAgICAgICAgICAgLi4uc2FuaXRpemVkLFxuICAgICAgICAgICAgaW5zdHJ1Y3Rpb25zOiBpbnN0cnVjdGlvbnMsXG4gICAgICAgICAgICBjb250ZW50OiBjb250ZW50IHx8ICcnXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgY29uc3Qgc3VjY2Vzc01zZyA9IGAke3dhcm5pbmdUZXh0feKchSBDcmVhdGVkIHNraWxsICcke3NraWxsLm1ldGFkYXRhLm5hbWV9JyBzdWNjZXNzZnVsbHlgO1xuICAgICAgICAgIHJldHVybiB7IGNvbnRlbnQ6IFt7IHR5cGU6IFwidGV4dFwiLCB0ZXh0OiBgJHtjb250ZXh0LmdldFBlcnNvbmFJbmRpY2F0b3IoKX0ke3N1Y2Nlc3NNc2d9YCB9XSB9O1xuICAgICAgICB9IGNhdGNoIChza2lsbEVycm9yKSB7XG4gICAgICAgICAgLy8gQ2hlY2sgaWYgaXQncyBhIGR1cGxpY2F0ZSBlcnJvclxuICAgICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBza2lsbEVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBza2lsbEVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoc2tpbGxFcnJvcik7XG4gICAgICAgICAgY29uc3QgZXJyb3JSZXNwb25zZSA9IG1lc3NhZ2UuaW5jbHVkZXMoJ2FscmVhZHkgZXhpc3RzJylcbiAgICAgICAgICAgID8gZm9ybWF0RHVwbGljYXRlRXJyb3IoRWxlbWVudFR5cGUuU0tJTEwsIHZhbGlkYXRlZE5hbWUpXG4gICAgICAgICAgICA6IGZvcm1hdEV4Y2VwdGlvbkVycm9yKHNraWxsRXJyb3IsICdjcmVhdGUnLCBFbGVtZW50VHlwZS5TS0lMTCwgdmFsaWRhdGVkTmFtZSk7XG4gICAgICAgICAgcmV0dXJuIGFkZFBlcnNvbmFJbmRpY2F0b3IoZXJyb3JSZXNwb25zZSwgY29udGV4dC5nZXRQZXJzb25hSW5kaWNhdG9yKCkpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNhc2UgRWxlbWVudFR5cGUuVEVNUExBVEU6IHtcbiAgICAgICAgLy8gRklYOiBJc3N1ZSAjMjAgLSBDYXRjaCBkdXBsaWNhdGUgZXJyb3JzIGZyb20gVGVtcGxhdGVNYW5hZ2VyXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgdGVtcGxhdGUgPSBhd2FpdCBjb250ZXh0LnRlbXBsYXRlTWFuYWdlci5jcmVhdGUoe1xuICAgICAgICAgICAgbmFtZTogdmFsaWRhdGVkTmFtZSxcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiB2YWxpZGF0ZWREZXNjcmlwdGlvbixcbiAgICAgICAgICAgIGluc3RydWN0aW9uczogaW5zdHJ1Y3Rpb25zLFxuICAgICAgICAgICAgY29udGVudDogY29udGVudCB8fCAnJyxcbiAgICAgICAgICAgIG1ldGFkYXRhOiBzYW5pdGl6ZWQsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgY29uc3Qgc3VjY2Vzc01zZyA9IGAke3dhcm5pbmdUZXh0feKchSBDcmVhdGVkIHRlbXBsYXRlICcke3RlbXBsYXRlLm1ldGFkYXRhLm5hbWV9JyBzdWNjZXNzZnVsbHlgO1xuICAgICAgICAgIHJldHVybiB7IGNvbnRlbnQ6IFt7IHR5cGU6IFwidGV4dFwiLCB0ZXh0OiBgJHtjb250ZXh0LmdldFBlcnNvbmFJbmRpY2F0b3IoKX0ke3N1Y2Nlc3NNc2d9YCB9XSB9O1xuICAgICAgICB9IGNhdGNoICh0ZW1wbGF0ZUVycm9yKSB7XG4gICAgICAgICAgLy8gQ2hlY2sgaWYgaXQncyBhIGR1cGxpY2F0ZSBlcnJvclxuICAgICAgICAgIGNvbnN0IG1lc3NhZ2UgPSB0ZW1wbGF0ZUVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyB0ZW1wbGF0ZUVycm9yLm1lc3NhZ2UgOiBTdHJpbmcodGVtcGxhdGVFcnJvcik7XG4gICAgICAgICAgY29uc3QgZXJyb3JSZXNwb25zZSA9IG1lc3NhZ2UuaW5jbHVkZXMoJ2FscmVhZHkgZXhpc3RzJylcbiAgICAgICAgICAgID8gZm9ybWF0RHVwbGljYXRlRXJyb3IoRWxlbWVudFR5cGUuVEVNUExBVEUsIHZhbGlkYXRlZE5hbWUpXG4gICAgICAgICAgICA6IGZvcm1hdEV4Y2VwdGlvbkVycm9yKHRlbXBsYXRlRXJyb3IsICdjcmVhdGUnLCBFbGVtZW50VHlwZS5URU1QTEFURSwgdmFsaWRhdGVkTmFtZSk7XG4gICAgICAgICAgcmV0dXJuIGFkZFBlcnNvbmFJbmRpY2F0b3IoZXJyb3JSZXNwb25zZSwgY29udGV4dC5nZXRQZXJzb25hSW5kaWNhdG9yKCkpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNhc2UgRWxlbWVudFR5cGUuQUdFTlQ6IHtcbiAgICAgICAgLy8gVjIgZmllbGRzIGFyZSBtZXJnZWQgaW50byBtZXRhZGF0YSBieSB0aGUgZGlzcGF0Y2hlciAoTUNQQVFMSGFuZGxlcikuXG4gICAgICAgIC8vIEdvYWwgbm9ybWFsaXphdGlvbiAoc3RyaW5n4oaSb2JqZWN0KSBpcyBoYW5kbGVkIGJ5IEFnZW50TWFuYWdlci5jcmVhdGUoKS5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAvLyBJc3N1ZSAjNzIyOiB2MiBkdWFsLWZpZWxkIGFyY2hpdGVjdHVyZSDigJQgZWFjaCBmaWVsZCBnb2VzIHdoZXJlIGl0IGJlbG9uZ3MuXG4gICAgICAgICAgLy8gQWdlbnRNYW5hZ2VyLmNyZWF0ZSgpIDNyZCBwYXJhbSA9IGJlaGF2aW9yYWwgZGlyZWN0aXZlcyAoYWdlbnQuaW5zdHJ1Y3Rpb25zKS5cbiAgICAgICAgICAvLyBtZXRhZGF0YS5jb250ZW50ID0gcmVmZXJlbmNlIG1hdGVyaWFsIChtYXJrZG93biBib2R5IGFmdGVyIGZyb250bWF0dGVyKS5cbiAgICAgICAgICBjb25zdCBhZ2VudEluc3RydWN0aW9ucyA9IGluc3RydWN0aW9ucyB8fCAnJztcbiAgICAgICAgICBjb25zdCBhZ2VudENvbnRlbnQgPSBjb250ZW50IHx8ICcnO1xuICAgICAgICAgIGNvbnN0IGFnZW50ID0gYXdhaXQgY29udGV4dC5hZ2VudE1hbmFnZXIuY3JlYXRlKFxuICAgICAgICAgICAgdmFsaWRhdGVkTmFtZSxcbiAgICAgICAgICAgIHZhbGlkYXRlZERlc2NyaXB0aW9uLFxuICAgICAgICAgICAgYWdlbnRJbnN0cnVjdGlvbnMsXG4gICAgICAgICAgICB7IC4uLnNhbml0aXplZCwgY29udGVudDogYWdlbnRDb250ZW50IH1cbiAgICAgICAgICApO1xuICAgICAgICAgIGlmIChhZ2VudC5zdWNjZXNzKSB7XG4gICAgICAgICAgICBjb25zdCBiYXNlTWVzc2FnZSA9IGFnZW50Lm1lc3NhZ2UgJiYgYWdlbnQubWVzc2FnZS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKCdjcmVhdGVkIGFnZW50JylcbiAgICAgICAgICAgICAgPyBhZ2VudC5tZXNzYWdlXG4gICAgICAgICAgICAgIDogYENyZWF0ZWQgYWdlbnQgJyR7dmFsaWRhdGVkTmFtZX0nIHN1Y2Nlc3NmdWxseWA7XG4gICAgICAgICAgICBjb25zdCBzdWNjZXNzTXNnID0gYCR7d2FybmluZ1RleHR94pyFICR7YmFzZU1lc3NhZ2V9YDtcbiAgICAgICAgICAgIHJldHVybiB7IGNvbnRlbnQ6IFt7IHR5cGU6IFwidGV4dFwiLCB0ZXh0OiBgJHtjb250ZXh0LmdldFBlcnNvbmFJbmRpY2F0b3IoKX0ke3N1Y2Nlc3NNc2d9YCB9XSB9O1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBGSVg6IElzc3VlICMyMCAtIEluY2x1ZGUgXCJmYWlsZWQgdG8gY3JlYXRlXCIgaW4gZXJyb3IgbWVzc2FnZSBmb3IgdGVzdCBjb21wYXRpYmlsaXR5XG4gICAgICAgICAgY29uc3QgZmFpbHVyZVJlYXNvbiA9IGFnZW50Lm1lc3NhZ2UgfHwgJ1Vua25vd24gZXJyb3InO1xuICAgICAgICAgIHJldHVybiBmb3JtYXRTaW1wbGVFcnJvclJlc3BvbnNlKGBGYWlsZWQgdG8gY3JlYXRlIGFnZW50OiAke2ZhaWx1cmVSZWFzb259YCk7XG4gICAgICAgIH0gY2F0Y2ggKGFnZW50RXJyb3IpIHtcbiAgICAgICAgICBjb25zdCBtZXNzYWdlID0gYWdlbnRFcnJvciBpbnN0YW5jZW9mIEVycm9yID8gYWdlbnRFcnJvci5tZXNzYWdlIDogU3RyaW5nKGFnZW50RXJyb3IpO1xuICAgICAgICAgIGNvbnN0IGVycm9yUmVzcG9uc2UgPSBtZXNzYWdlLmluY2x1ZGVzKCdhbHJlYWR5IGV4aXN0cycpXG4gICAgICAgICAgICA/IGZvcm1hdER1cGxpY2F0ZUVycm9yKEVsZW1lbnRUeXBlLkFHRU5ULCB2YWxpZGF0ZWROYW1lKVxuICAgICAgICAgICAgOiBmb3JtYXRFeGNlcHRpb25FcnJvcihhZ2VudEVycm9yLCAnY3JlYXRlJywgRWxlbWVudFR5cGUuQUdFTlQsIHZhbGlkYXRlZE5hbWUpO1xuICAgICAgICAgIHJldHVybiBhZGRQZXJzb25hSW5kaWNhdG9yKGVycm9yUmVzcG9uc2UsIGNvbnRleHQuZ2V0UGVyc29uYUluZGljYXRvcigpKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjYXNlIEVsZW1lbnRUeXBlLk1FTU9SWToge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IG1lbW9yeSA9IGF3YWl0IGNvbnRleHQubWVtb3J5TWFuYWdlci5jcmVhdGUoe1xuICAgICAgICAgICAgLi4uc2FuaXRpemVkLFxuICAgICAgICAgICAgbmFtZTogdmFsaWRhdGVkTmFtZSxcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiB2YWxpZGF0ZWREZXNjcmlwdGlvbixcbiAgICAgICAgICAgIGNvbnRlbnQ6IGNvbnRlbnQsXG4gICAgICAgICAgICBpbnN0cnVjdGlvbnM6IGluc3RydWN0aW9ucyxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBjb25zdCBzdWNjZXNzTXNnID0gYCR7d2FybmluZ1RleHR94pyFIENyZWF0ZWQgbWVtb3J5ICcke21lbW9yeS5tZXRhZGF0YS5uYW1lfScgc3VjY2Vzc2Z1bGx5YDtcbiAgICAgICAgICByZXR1cm4geyBjb250ZW50OiBbeyB0eXBlOiBcInRleHRcIiwgdGV4dDogYCR7Y29udGV4dC5nZXRQZXJzb25hSW5kaWNhdG9yKCl9JHtzdWNjZXNzTXNnfWAgfV0gfTtcbiAgICAgICAgfSBjYXRjaCAobWVtb3J5RXJyb3IpIHtcbiAgICAgICAgICBjb25zdCBtZXNzYWdlID0gbWVtb3J5RXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IG1lbW9yeUVycm9yLm1lc3NhZ2UgOiBTdHJpbmcobWVtb3J5RXJyb3IpO1xuICAgICAgICAgIGNvbnN0IGVycm9yUmVzcG9uc2UgPSBtZXNzYWdlLmluY2x1ZGVzKCdhbHJlYWR5IGV4aXN0cycpXG4gICAgICAgICAgICA/IGZvcm1hdER1cGxpY2F0ZUVycm9yKEVsZW1lbnRUeXBlLk1FTU9SWSwgdmFsaWRhdGVkTmFtZSlcbiAgICAgICAgICAgIDogZm9ybWF0RXhjZXB0aW9uRXJyb3IobWVtb3J5RXJyb3IsICdjcmVhdGUnLCBFbGVtZW50VHlwZS5NRU1PUlksIH