@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.
167 lines ⢠23.7 kB
JavaScript
/**
* FIX: DMCP-SEC-006 - Security audit suppression
* This file delegates validation to element managers.
* Audit logging happens in the managers themselves.
* @security-audit-suppress DMCP-SEC-006
*/
import { ElementType } from '../../portfolio/PortfolioManager.js';
import { logger } from '../../utils/logger.js';
import { SecurityMonitor } from '../../security/securityMonitor.js';
import { normalizeElementTypeInput, formatValidElementTypesList, getElementTypeLabel, resolveElementByName } from './helpers.js';
import { ElementNotFoundError } from '../../utils/ErrorHandler.js';
export async function validateElement(context, args) {
await context.ensureInitialized();
try {
const { name, type, strict = false } = args;
const { type: normalizedType } = normalizeElementTypeInput(type);
logger.debug('[ElementCRUD] Normalized type', { inputType: type, normalizedType });
if (!normalizedType) {
return invalidType(type);
}
// FIX: Issue #281 - PERSONA now uses standard validation flow
const manager = getManager(context, normalizedType);
if (!manager) {
return unsupportedType(normalizedType);
}
const element = await resolveElementByName(manager, normalizedType, name);
if (!element) {
// Issue #275: Throw error instead of returning content for missing elements
throw new ElementNotFoundError(getElementTypeLabel(normalizedType), name);
}
// Use ElementValidator from ValidationRegistry for metadata validation
const validator = context.validationRegistry.getValidator(normalizedType);
const validatorResult = await validator.validateMetadata(element.metadata);
// Also call element's own validation for backwards compatibility
const elementValidation = element.validate();
// Combine results - validator gives string errors/warnings, element.validate() gives {field, message} objects
const validationResult = {
valid: validatorResult.isValid && elementValidation.valid,
errors: [
...validatorResult.errors.map((e) => ({ field: 'general', message: e })),
...(elementValidation.errors ?? [])
],
warnings: [
...validatorResult.warnings.map((w) => ({ field: 'general', message: w })),
...(elementValidation.warnings ?? [])
],
suggestions: [
...(validatorResult.suggestions ?? []),
...(elementValidation.suggestions ?? [])
]
};
const report = buildReport(normalizedType, name, validationResult, strict);
// FIX: DMCP-SEC-006 - Add security audit logging for validation
SecurityMonitor.logSecurityEvent({
type: 'ELEMENT_VALIDATED',
severity: 'LOW',
source: 'validateElement',
details: `Validated ${normalizedType}: ${name}`,
additionalData: { elementType: normalizedType, isValid: validationResult.valid }
});
return {
content: [{
type: "text",
text: report
}]
};
}
catch (error) {
// Re-throw ElementNotFoundError to propagate to MCP-AQL layer
// Issue #275: Handlers return success=true for missing elements
if (error instanceof ElementNotFoundError) {
throw error;
}
logger.error(`Failed to validate element:`, error);
return {
content: [{
type: "text",
text: `ā Failed to validate element: ${error instanceof Error ? error.message : 'Unknown error'}`
}]
};
}
}
function invalidType(type) {
return {
content: [{
type: "text",
text: `ā Invalid element type '${type}'. Valid types: ${formatValidElementTypesList()}`
}]
};
}
function unsupportedType(type) {
const labelPlural = getElementTypeLabel(type, { plural: true });
return {
content: [{
type: "text",
text: `ā Element type '${labelPlural}' is not yet supported for validation`
}]
};
}
function buildReport(type, name, validationResult, strict) {
const label = getElementTypeLabel(type);
let report = `š Validation Report for ${label} '${name}':\n`;
report += `${validationResult.valid ? 'ā
' : 'ā'} Status: ${validationResult.valid ? 'Valid' : 'Invalid'}\n\n`;
if (validationResult.errors && validationResult.errors.length > 0) {
report += `ā Errors (${validationResult.errors.length}):\n`;
validationResult.errors.forEach((error) => {
if (typeof error === 'string') {
report += ` ⢠General: ${error}\n`;
}
else {
report += ` ⢠${error.field || 'General'}: ${error.message}\n`;
if (error.fix) {
report += ` š” Fix: ${error.fix}\n`;
}
}
});
report += '\n';
}
if (validationResult.warnings && validationResult.warnings.length > 0) {
report += `ā ļø Warnings (${validationResult.warnings.length}):\n`;
validationResult.warnings.forEach((warning) => {
if (typeof warning === 'string') {
report += ` ⢠General: ${warning}\n`;
}
else {
report += ` ⢠${warning.field || 'General'}: ${warning.message}\n`;
if (warning.suggestion) {
report += ` š” Suggestion: ${warning.suggestion}\n`;
}
}
});
report += '\n';
}
if (validationResult.suggestions && validationResult.suggestions.length > 0) {
report += `š” Suggestions:\n`;
validationResult.suggestions.forEach((suggestion) => {
report += ` ⢠${suggestion}\n`;
});
}
if (strict) {
report += '\nš Strict Mode: Additional quality checks applied';
}
return report;
}
function getManager(context, type) {
switch (type) {
// FIX: Issue #281 - PERSONA now uses standard validation flow
case ElementType.PERSONA:
return context.personaManager;
case ElementType.SKILL:
return context.skillManager;
case ElementType.TEMPLATE:
return context.templateManager;
case ElementType.AGENT:
return context.agentManager;
case ElementType.MEMORY:
// FIX: Added memory validation support (fixes #1042)
// Previously: Memories returned "not yet supported for validation"
// Now: Full validation including metadata, retention, entry structure
return context.memoryManager;
case ElementType.ENSEMBLE:
return context.ensembleManager;
default:
return null;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGVFbGVtZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2hhbmRsZXJzL2VsZW1lbnQtY3J1ZC92YWxpZGF0ZUVsZW1lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7O0dBS0c7QUFFSCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFFbEUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQy9DLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUNwRSxPQUFPLEVBQ0wseUJBQXlCLEVBQ3pCLDJCQUEyQixFQUMzQixtQkFBbUIsRUFDbkIsb0JBQW9CLEVBRXJCLE1BQU0sY0FBYyxDQUFDO0FBQ3RCLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBU25FLE1BQU0sQ0FBQyxLQUFLLFVBQVUsZUFBZSxDQUNuQyxPQUEyQixFQUMzQixJQUF5QjtJQUV6QixNQUFNLE9BQU8sQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO0lBRWxDLElBQUksQ0FBQztRQUNILE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLE1BQU0sR0FBRyxLQUFLLEVBQUUsR0FBRyxJQUFJLENBQUM7UUFFNUMsTUFBTSxFQUFFLElBQUksRUFBRSxjQUFjLEVBQUUsR0FBRyx5QkFBeUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNqRSxNQUFNLENBQUMsS0FBSyxDQUFDLCtCQUErQixFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxjQUFjLEVBQUUsQ0FBQyxDQUFDO1FBRW5GLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUNwQixPQUFPLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUMzQixDQUFDO1FBRUQsOERBQThEO1FBQzlELE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxPQUFPLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDcEQs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UC1TRUMtMDA2IC0gU2VjdXJpdHkgYXVkaXQgc3VwcHJlc3Npb25cbiAqIFRoaXMgZmlsZSBkZWxlZ2F0ZXMgdmFsaWRhdGlvbiB0byBlbGVtZW50IG1hbmFnZXJzLlxuICogQXVkaXQgbG9nZ2luZyBoYXBwZW5zIGluIHRoZSBtYW5hZ2VycyB0aGVtc2VsdmVzLlxuICogQHNlY3VyaXR5LWF1ZGl0LXN1cHByZXNzIERNQ1AtU0VDLTAwNlxuICovXG5cbmltcG9ydCB7IEVsZW1lbnRUeXBlIH0gZnJvbSAnLi4vLi4vcG9ydGZvbGlvL1BvcnRmb2xpb01hbmFnZXIuanMnO1xuaW1wb3J0IHsgRWxlbWVudENydWRDb250ZXh0IH0gZnJvbSAnLi90eXBlcy5qcyc7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi8uLi91dGlscy9sb2dnZXIuanMnO1xuaW1wb3J0IHsgU2VjdXJpdHlNb25pdG9yIH0gZnJvbSAnLi4vLi4vc2VjdXJpdHkvc2VjdXJpdHlNb25pdG9yLmpzJztcbmltcG9ydCB7XG4gIG5vcm1hbGl6ZUVsZW1lbnRUeXBlSW5wdXQsXG4gIGZvcm1hdFZhbGlkRWxlbWVudFR5cGVzTGlzdCxcbiAgZ2V0RWxlbWVudFR5cGVMYWJlbCxcbiAgcmVzb2x2ZUVsZW1lbnRCeU5hbWUsXG4gIEVsZW1lbnRNYW5hZ2VyT3BlcmF0aW9uc1xufSBmcm9tICcuL2hlbHBlcnMuanMnO1xuaW1wb3J0IHsgRWxlbWVudE5vdEZvdW5kRXJyb3IgfSBmcm9tICcuLi8uLi91dGlscy9FcnJvckhhbmRsZXIuanMnO1xuaW1wb3J0IHR5cGUgeyBWYWxpZGF0aW9uUmVzdWx0IH0gZnJvbSAnLi4vLi4vc2VydmljZXMvdmFsaWRhdGlvbi9WYWxpZGF0aW9uUmVnaXN0cnkuanMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFZhbGlkYXRlRWxlbWVudEFyZ3Mge1xuICBuYW1lOiBzdHJpbmc7XG4gIHR5cGU6IHN0cmluZztcbiAgc3RyaWN0PzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHZhbGlkYXRlRWxlbWVudChcbiAgY29udGV4dDogRWxlbWVudENydWRDb250ZXh0LFxuICBhcmdzOiBWYWxpZGF0ZUVsZW1lbnRBcmdzXG4pIHtcbiAgYXdhaXQgY29udGV4dC5lbnN1cmVJbml0aWFsaXplZCgpO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgeyBuYW1lLCB0eXBlLCBzdHJpY3QgPSBmYWxzZSB9ID0gYXJncztcblxuICAgIGNvbnN0IHsgdHlwZTogbm9ybWFsaXplZFR5cGUgfSA9IG5vcm1hbGl6ZUVsZW1lbnRUeXBlSW5wdXQodHlwZSk7XG4gICAgbG9nZ2VyLmRlYnVnKCdbRWxlbWVudENSVURdIE5vcm1hbGl6ZWQgdHlwZScsIHsgaW5wdXRUeXBlOiB0eXBlLCBub3JtYWxpemVkVHlwZSB9KTtcblxuICAgIGlmICghbm9ybWFsaXplZFR5cGUpIHtcbiAgICAgIHJldHVybiBpbnZhbGlkVHlwZSh0eXBlKTtcbiAgICB9XG5cbiAgICAvLyBGSVg6IElzc3VlICMyODEgLSBQRVJTT05BIG5vdyB1c2VzIHN0YW5kYXJkIHZhbGlkYXRpb24gZmxvd1xuICAgIGNvbnN0IG1hbmFnZXIgPSBnZXRNYW5hZ2VyKGNvbnRleHQsIG5vcm1hbGl6ZWRUeXBlKTtcbiAgICBpZiAoIW1hbmFnZXIpIHtcbiAgICAgIHJldHVybiB1bnN1cHBvcnRlZFR5cGUobm9ybWFsaXplZFR5cGUpO1xuICAgIH1cblxuICAgIGNvbnN0IGVsZW1lbnQgPSBhd2FpdCByZXNvbHZlRWxlbWVudEJ5TmFtZShtYW5hZ2VyLCBub3JtYWxpemVkVHlwZSwgbmFtZSk7XG5cbiAgICBpZiAoIWVsZW1lbnQpIHtcbiAgICAgIC8vIElzc3VlICMyNzU6IFRocm93IGVycm9yIGluc3RlYWQgb2YgcmV0dXJuaW5nIGNvbnRlbnQgZm9yIG1pc3NpbmcgZWxlbWVudHNcbiAgICAgIHRocm93IG5ldyBFbGVtZW50Tm90Rm91bmRFcnJvcihnZXRFbGVtZW50VHlwZUxhYmVsKG5vcm1hbGl6ZWRUeXBlKSwgbmFtZSk7XG4gICAgfVxuXG4gICAgLy8gVXNlIEVsZW1lbnRWYWxpZGF0b3IgZnJvbSBWYWxpZGF0aW9uUmVnaXN0cnkgZm9yIG1ldGFkYXRhIHZhbGlkYXRpb25cbiAgICBjb25zdCB2YWxpZGF0b3IgPSBjb250ZXh0LnZhbGlkYXRpb25SZWdpc3RyeS5nZXRWYWxpZGF0b3Iobm9ybWFsaXplZFR5cGUpO1xuICAgIGNvbnN0IHZhbGlkYXRvclJlc3VsdDogVmFsaWRhdGlvblJlc3VsdCA9IGF3YWl0IHZhbGlkYXRvci52YWxpZGF0ZU1ldGFkYXRhKGVsZW1lbnQubWV0YWRhdGEpO1xuXG4gICAgLy8gQWxzbyBjYWxsIGVsZW1lbnQncyBvd24gdmFsaWRhdGlvbiBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHlcbiAgICBjb25zdCBlbGVtZW50VmFsaWRhdGlvbiA9IGVsZW1lbnQudmFsaWRhdGUoKTtcblxuICAgIC8vIENvbWJpbmUgcmVzdWx0cyAtIHZhbGlkYXRvciBnaXZlcyBzdHJpbmcgZXJyb3JzL3dhcm5pbmdzLCBlbGVtZW50LnZhbGlkYXRlKCkgZ2l2ZXMge2ZpZWxkLCBtZXNzYWdlfSBvYmplY3RzXG4gICAgY29uc3QgdmFsaWRhdGlvblJlc3VsdCA9IHtcbiAgICAgIHZhbGlkOiB2YWxpZGF0b3JSZXN1bHQuaXNWYWxpZCAmJiBlbGVtZW50VmFsaWRhdGlvbi52YWxpZCxcbiAgICAgIGVycm9yczogW1xuICAgICAgICAuLi52YWxpZGF0b3JSZXN1bHQuZXJyb3JzLm1hcCgoZTogc3RyaW5nKSA9PiAoeyBmaWVsZDogJ2dlbmVyYWwnLCBtZXNzYWdlOiBlIH0pKSxcbiAgICAgICAgLi4uKGVsZW1lbnRWYWxpZGF0aW9uLmVycm9ycyA/PyBbXSlcbiAgICAgIF0sXG4gICAgICB3YXJuaW5nczogW1xuICAgICAgICAuLi52YWxpZGF0b3JSZXN1bHQud2FybmluZ3MubWFwKCh3OiBzdHJpbmcpID0+ICh7IGZpZWxkOiAnZ2VuZXJhbCcsIG1lc3NhZ2U6IHcgfSkpLFxuICAgICAgICAuLi4oZWxlbWVudFZhbGlkYXRpb24ud2FybmluZ3MgPz8gW10pXG4gICAgICBdLFxuICAgICAgc3VnZ2VzdGlvbnM6IFtcbiAgICAgICAgLi4uKHZhbGlkYXRvclJlc3VsdC5zdWdnZXN0aW9ucyA/PyBbXSksXG4gICAgICAgIC4uLihlbGVtZW50VmFsaWRhdGlvbi5zdWdnZXN0aW9ucyA/PyBbXSlcbiAgICAgIF1cbiAgICB9O1xuXG4gICAgY29uc3QgcmVwb3J0ID0gYnVpbGRSZXBvcnQobm9ybWFsaXplZFR5cGUsIG5hbWUsIHZhbGlkYXRpb25SZXN1bHQsIHN0cmljdCk7XG5cbiAgICAvLyBGSVg6IERNQ1AtU0VDLTAwNiAtIEFkZCBzZWN1cml0eSBhdWRpdCBsb2dnaW5nIGZvciB2YWxpZGF0aW9uXG4gICAgU2VjdXJpdHlNb25pdG9yLmxvZ1NlY3VyaXR5RXZlbnQoe1xuICAgICAgdHlwZTogJ0VMRU1FTlRfVkFMSURBVEVEJyxcbiAgICAgIHNldmVyaXR5OiAnTE9XJyxcbiAgICAgIHNvdXJjZTogJ3ZhbGlkYXRlRWxlbWVudCcsXG4gICAgICBkZXRhaWxzOiBgVmFsaWRhdGVkICR7bm9ybWFsaXplZFR5cGV9OiAke25hbWV9YCxcbiAgICAgIGFkZGl0aW9uYWxEYXRhOiB7IGVsZW1lbnRUeXBlOiBub3JtYWxpemVkVHlwZSwgaXNWYWxpZDogdmFsaWRhdGlvblJlc3VsdC52YWxpZCB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgY29udGVudDogW3tcbiAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgIHRleHQ6IHJlcG9ydFxuICAgICAgfV1cbiAgICB9O1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIC8vIFJlLXRocm93IEVsZW1lbnROb3RGb3VuZEVycm9yIHRvIHByb3BhZ2F0ZSB0byBNQ1AtQVFMIGxheWVyXG4gICAgLy8gSXNzdWUgIzI3NTogSGFuZGxlcnMgcmV0dXJuIHN1Y2Nlc3M9dHJ1ZSBmb3IgbWlzc2luZyBlbGVtZW50c1xuICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEVsZW1lbnROb3RGb3VuZEVycm9yKSB7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG5cbiAgICBsb2dnZXIuZXJyb3IoYEZhaWxlZCB0byB2YWxpZGF0ZSBlbGVtZW50OmAsIGVycm9yKTtcbiAgICByZXR1cm4ge1xuICAgICAgY29udGVudDogW3tcbiAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgIHRleHQ6IGDinYwgRmFpbGVkIHRvIHZhbGlkYXRlIGVsZW1lbnQ6ICR7ZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiAnVW5rbm93biBlcnJvcid9YFxuICAgICAgfV1cbiAgICB9O1xuICB9XG59XG5cbmZ1bmN0aW9uIGludmFsaWRUeXBlKHR5cGU6IHN0cmluZykge1xuICByZXR1cm4ge1xuICAgIGNvbnRlbnQ6IFt7XG4gICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgIHRleHQ6IGDinYwgSW52YWxpZCBlbGVtZW50IHR5cGUgJyR7dHlwZX0nLiBWYWxpZCB0eXBlczogJHtmb3JtYXRWYWxpZEVsZW1lbnRUeXBlc0xpc3QoKX1gXG4gICAgfV1cbiAgfTtcbn1cblxuZnVuY3Rpb24gdW5zdXBwb3J0ZWRUeXBlKHR5cGU6IEVsZW1lbnRUeXBlKSB7XG4gIGNvbnN0IGxhYmVsUGx1cmFsID0gZ2V0RWxlbWVudFR5cGVMYWJlbCh0eXBlLCB7IHBsdXJhbDogdHJ1ZSB9KTtcbiAgcmV0dXJuIHtcbiAgICBjb250ZW50OiBbe1xuICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICB0ZXh0OiBg4p2MIEVsZW1lbnQgdHlwZSAnJHtsYWJlbFBsdXJhbH0nIGlzIG5vdCB5ZXQgc3VwcG9ydGVkIGZvciB2YWxpZGF0aW9uYFxuICAgIH1dXG4gIH07XG59XG5cbmZ1bmN0aW9uIGJ1aWxkUmVwb3J0KFxuICB0eXBlOiBFbGVtZW50VHlwZSxcbiAgbmFtZTogc3RyaW5nLFxuICB2YWxpZGF0aW9uUmVzdWx0OiBhbnksXG4gIHN0cmljdDogYm9vbGVhblxuKSB7XG4gIGNvbnN0IGxhYmVsID0gZ2V0RWxlbWVudFR5cGVMYWJlbCh0eXBlKTtcbiAgbGV0IHJlcG9ydCA9IGDwn5SNIFZhbGlkYXRpb24gUmVwb3J0IGZvciAke2xhYmVsfSAnJHtuYW1lfSc6XFxuYDtcbiAgcmVwb3J0ICs9IGAke3ZhbGlkYXRpb25SZXN1bHQudmFsaWQgPyAn4pyFJyA6ICfinYwnfSBTdGF0dXM6ICR7dmFsaWRhdGlvblJlc3VsdC52YWxpZCA/ICdWYWxpZCcgOiAnSW52YWxpZCd9XFxuXFxuYDtcblxuICBpZiAodmFsaWRhdGlvblJlc3VsdC5lcnJvcnMgJiYgdmFsaWRhdGlvblJlc3VsdC5lcnJvcnMubGVuZ3RoID4gMCkge1xuICAgIHJlcG9ydCArPSBg4p2MIEVycm9ycyAoJHt2YWxpZGF0aW9uUmVzdWx0LmVycm9ycy5sZW5ndGh9KTpcXG5gO1xuICAgIHZhbGlkYXRpb25SZXN1bHQuZXJyb3JzLmZvckVhY2goKGVycm9yOiBhbnkpID0+IHtcbiAgICAgIGlmICh0eXBlb2YgZXJyb3IgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJlcG9ydCArPSBgICAg4oCiIEdlbmVyYWw6ICR7ZXJyb3J9XFxuYDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlcG9ydCArPSBgICAg4oCiICR7ZXJyb3IuZmllbGQgfHwgJ0dlbmVyYWwnfTogJHtlcnJvci5tZXNzYWdlfVxcbmA7XG4gICAgICAgIGlmIChlcnJvci5maXgpIHtcbiAgICAgICAgICByZXBvcnQgKz0gYCAgICAg8J+SoSBGaXg6ICR7ZXJyb3IuZml4fVxcbmA7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXBvcnQgKz0gJ1xcbic7XG4gIH1cblxuICBpZiAodmFsaWRhdGlvblJlc3VsdC53YXJuaW5ncyAmJiB2YWxpZGF0aW9uUmVzdWx0Lndhcm5pbmdzLmxlbmd0aCA+IDApIHtcbiAgICByZXBvcnQgKz0gYOKaoO+4jyAgV2FybmluZ3MgKCR7dmFsaWRhdGlvblJlc3VsdC53YXJuaW5ncy5sZW5ndGh9KTpcXG5gO1xuICAgIHZhbGlkYXRpb25SZXN1bHQud2FybmluZ3MuZm9yRWFjaCgod2FybmluZzogYW55KSA9PiB7XG4gICAgICBpZiAodHlwZW9mIHdhcm5pbmcgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJlcG9ydCArPSBgICAg4oCiIEdlbmVyYWw6ICR7d2FybmluZ31cXG5gO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVwb3J0ICs9IGAgICDigKIgJHt3YXJuaW5nLmZpZWxkIHx8ICdHZW5lcmFsJ306ICR7d2FybmluZy5tZXNzYWdlfVxcbmA7XG4gICAgICAgIGlmICh3YXJuaW5nLnN1Z2dlc3Rpb24pIHtcbiAgICAgICAgICByZXBvcnQgKz0gYCAgICAg8J+SoSBTdWdnZXN0aW9uOiAke3dhcm5pbmcuc3VnZ2VzdGlvbn1cXG5gO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmVwb3J0ICs9ICdcXG4nO1xuICB9XG5cbiAgaWYgKHZhbGlkYXRpb25SZXN1bHQuc3VnZ2VzdGlvbnMgJiYgdmFsaWRhdGlvblJlc3VsdC5zdWdnZXN0aW9ucy5sZW5ndGggPiAwKSB7XG4gICAgcmVwb3J0ICs9IGDwn5KhIFN1Z2dlc3Rpb25zOlxcbmA7XG4gICAgdmFsaWRhdGlvblJlc3VsdC5zdWdnZXN0aW9ucy5mb3JFYWNoKChzdWdnZXN0aW9uOiBzdHJpbmcpID0+IHtcbiAgICAgIHJlcG9ydCArPSBgICAg4oCiICR7c3VnZ2VzdGlvbn1cXG5gO1xuICAgIH0pO1xuICB9XG5cbiAgaWYgKHN0cmljdCkge1xuICAgIHJlcG9ydCArPSAnXFxu8J+TiyBTdHJpY3QgTW9kZTogQWRkaXRpb25hbCBxdWFsaXR5IGNoZWNrcyBhcHBsaWVkJztcbiAgfVxuXG4gIHJldHVybiByZXBvcnQ7XG59XG5cbmZ1bmN0aW9uIGdldE1hbmFnZXIoY29udGV4dDogRWxlbWVudENydWRDb250ZXh0LCB0eXBlOiBFbGVtZW50VHlwZSk6IEVsZW1lbnRNYW5hZ2VyT3BlcmF0aW9uczxhbnk+IHwgbnVsbCB7XG4gIHN3aXRjaCAodHlwZSkge1xuICAgIC8vIEZJWDogSXNzdWUgIzI4MSAtIFBFUlNPTkEgbm93IHVzZXMgc3RhbmRhcmQgdmFsaWRhdGlvbiBmbG93XG4gICAgY2FzZSBFbGVtZW50VHlwZS5QRVJTT05BOlxuICAgICAgcmV0dXJuIGNvbnRleHQucGVyc29uYU1hbmFnZXI7XG4gICAgY2FzZSBFbGVtZW50VHlwZS5TS0lMTDpcbiAgICAgIHJldHVybiBjb250ZXh0LnNraWxsTWFuYWdlcjtcbiAgICBjYXNlIEVsZW1lbnRUeXBlLlRFTVBMQVRFOlxuICAgICAgcmV0dXJuIGNvbnRleHQudGVtcGxhdGVNYW5hZ2VyO1xuICAgIGNhc2UgRWxlbWVudFR5cGUuQUdFTlQ6XG4gICAgICByZXR1cm4gY29udGV4dC5hZ2VudE1hbmFnZXI7XG4gICAgY2FzZSBFbGVtZW50VHlwZS5NRU1PUlk6XG4gICAgICAvLyBGSVg6IEFkZGVkIG1lbW9yeSB2YWxpZGF0aW9uIHN1cHBvcnQgKGZpeGVzICMxMDQyKVxuICAgICAgLy8gUHJldmlvdXNseTogTWVtb3JpZXMgcmV0dXJuZWQgXCJub3QgeWV0IHN1cHBvcnRlZCBmb3IgdmFsaWRhdGlvblwiXG4gICAgICAvLyBOb3c6IEZ1bGwgdmFsaWRhdGlvbiBpbmNsdWRpbmcgbWV0YWRhdGEsIHJldGVudGlvbiwgZW50cnkgc3RydWN0dXJlXG4gICAgICByZXR1cm4gY29udGV4dC5tZW1vcnlNYW5hZ2VyO1xuICAgIGNhc2UgRWxlbWVudFR5cGUuRU5TRU1CTEU6XG4gICAgICByZXR1cm4gY29udGV4dC5lbnNlbWJsZU1hbmFnZXI7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBudWxsO1xuICB9XG59XG4iXX0=