@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.
385 lines • 49.3 kB
JavaScript
/**
* TypeScript type definitions for MCP-AQL (MCP Agent Query Language)
* These types match the GraphQL schema defined in schema.graphql
*/
import { ELEMENT_TYPE_MAP } from '../../utils/elementTypeNormalization.js';
/**
* Element types supported by DollhouseMCP.
* These correspond to the 6 core element types in the system.
*/
export var ElementType;
(function (ElementType) {
ElementType["Persona"] = "persona";
ElementType["Skill"] = "skill";
ElementType["Template"] = "template";
ElementType["Agent"] = "agent";
ElementType["Memory"] = "memory";
ElementType["Ensemble"] = "ensemble";
})(ElementType || (ElementType = {}));
/**
* Normalize any element type string (singular or plural) to an MCP-AQL ElementType value.
* Returns undefined for unrecognised input.
* Issue #433: Accept both "memory" and "memories" at the input parsing layer.
*/
const MCPAQL_TYPE_MAP = {
persona: ElementType.Persona, personas: ElementType.Persona,
skill: ElementType.Skill, skills: ElementType.Skill,
template: ElementType.Template, templates: ElementType.Template,
agent: ElementType.Agent, agents: ElementType.Agent,
memory: ElementType.Memory, memories: ElementType.Memory,
ensemble: ElementType.Ensemble, ensembles: ElementType.Ensemble,
};
// Runtime validation: every MCP-AQL ElementType must appear in MCPAQL_TYPE_MAP
for (const enumValue of Object.values(ElementType)) {
if (!Object.values(MCPAQL_TYPE_MAP).includes(enumValue)) {
throw new Error(`MCP-AQL types: ElementType '${enumValue}' is missing from MCPAQL_TYPE_MAP. ` +
`Update MCPAQL_TYPE_MAP to include both singular and plural entries for this type.`);
}
}
export function normalizeMCPAQLElementType(value) {
return MCPAQL_TYPE_MAP[value.trim().toLowerCase()];
}
/**
* Map of endpoint names to their safety annotations
*/
export const ENDPOINT_SAFETY = {
mcp_aql_create: {
readOnly: false,
destructive: false,
},
mcp_aql_read: {
readOnly: true,
destructive: false,
},
mcp_aql_update: {
readOnly: false,
destructive: true,
},
mcp_aql_delete: {
readOnly: false,
destructive: true,
},
};
/**
* Operation names grouped by endpoint
*/
export const ENDPOINT_OPERATIONS = {
create: ['create_element', 'import_element', 'addEntry', 'activate_element'],
read: [
'list_elements',
'get_element',
'search_elements',
'query_elements',
'get_active_elements',
'validate_element',
'render',
'export_element',
'deactivate_element',
'introspect',
],
update: ['edit_element'],
delete: ['delete_element', 'execute_agent', 'clear'],
};
/**
* Type guard to check if a string is a valid ElementType.
* Accepts both singular ("memory") and plural ("memories") forms.
* Issue #433: Users and LLMs naturally use either form.
*/
export function isElementType(value) {
if (typeof value !== 'string')
return false;
// Accept canonical MCP-AQL singular values
if (Object.values(ElementType).includes(value))
return true;
// Also accept plural portfolio-layer values (Issue #433)
return value.toLowerCase() in ELEMENT_TYPE_MAP;
}
/**
* Type guard to check if an object is a valid OperationInput
* Issue #290: Accepts both element_type (snake_case) and elementType (camelCase)
*/
export function isOperationInput(value) {
if (typeof value !== 'object' || value === null) {
return false;
}
const input = value;
// operation is required and must be a string
if (typeof input.operation !== 'string') {
return false;
}
// Issue #290: Accept both element_type and elementType
// elementType/element_type is optional but must be a valid ElementType if present
const elementTypeValue = input.element_type ?? input.elementType;
if (elementTypeValue !== undefined && !isElementType(elementTypeValue)) {
return false;
}
// params is optional but must be a plain object (not array, not null) if present
if (input.params !== undefined &&
(typeof input.params !== 'object' ||
input.params === null ||
Array.isArray(input.params))) {
return false;
}
return true;
}
/**
* Type guard to check if an object is a valid OperationResult
*/
export function isOperationResult(value) {
if (typeof value !== 'object' || value === null) {
return false;
}
const result = value;
// success is required and must be a boolean
if (typeof result.success !== 'boolean') {
return false;
}
// error must be a string if present
if (result.error !== undefined && typeof result.error !== 'string') {
return false;
}
// _meta is required (Issue #301: request correlation metadata)
if (typeof result._meta !== 'object' || result._meta === null) {
return false;
}
return true;
}
/**
* Type guard to check if an object is a valid BatchRequest
*/
export function isBatchRequest(value) {
if (typeof value !== 'object' || value === null) {
return false;
}
const input = value;
// operations is required and must be an array
if (!Array.isArray(input.operations)) {
return false;
}
// Each operation must be a valid OperationInput structure
return input.operations.every((op) => {
if (typeof op !== 'object' || op === null) {
return false;
}
const operation = op;
// operation field is required and must be a string
if (typeof operation.operation !== 'string') {
return false;
}
// elementType is optional but must be a valid ElementType if present
if (operation.elementType !== undefined && !isElementType(operation.elementType)) {
return false;
}
// params is optional but must be a plain object if present
if (operation.params !== undefined &&
(typeof operation.params !== 'object' ||
operation.params === null ||
Array.isArray(operation.params))) {
return false;
}
return true;
});
}
/**
* Type guard to check if input is in legacy tool format.
* Supports: { tool: 'operation_name', args: {...} }
* or: { tool: 'operation_name', params: {...} }
*
* INTERNAL USE ONLY - Not documented to users.
* Issue #205: Silent JSON fallback for edge cases.
*/
export function isLegacyToolFormat(value) {
if (typeof value !== 'object' || value === null) {
return false;
}
const input = value;
// Must have 'tool' as a string
if (typeof input.tool !== 'string') {
return false;
}
// args/params are optional but must be objects if present
if (input.args !== undefined) {
if (typeof input.args !== 'object' || input.args === null || Array.isArray(input.args)) {
return false;
}
}
if (input.params !== undefined) {
if (typeof input.params !== 'object' || input.params === null || Array.isArray(input.params)) {
return false;
}
}
return true;
}
/**
* Convert legacy tool format to proper OperationInput.
*
* PRECEDENCE RULES:
* 1. If `args` is present (even if empty {}), use `args`
* 2. Otherwise, if `params` is present, use `params`
* 3. If neither present, use empty object {}
*
* EDGE CASE: { tool: 'x', args: { a: 1 }, params: { b: 2 } }
* Result: { operation: 'x', params: { a: 1 } } (args wins, params ignored)
*
* INTERNAL USE ONLY - Not documented to users.
* Issue #205: Silent JSON fallback for edge cases.
*/
export function convertLegacyToMCPAQL(legacy) {
return {
operation: legacy.tool,
// Prefer 'args' over 'params' for legacy compatibility
params: legacy.args || legacy.params || {},
};
}
/**
* Internal metrics for input format tracking.
* Not exposed to users; for monitoring purposes only.
*
* High legacy_converted ratio might indicate:
* - Documentation issues
* - Model confusion
* - Need for better prompt engineering
*/
export class InputFormatMetrics {
static counts = {
proper: 0,
legacy_converted: 0,
permission_prompt_protocol: 0,
invalid: 0,
};
/**
* Record an input format event
*/
static record(format) {
this.counts[format]++;
}
/**
* Get current metrics snapshot
*/
static getMetrics() {
return { ...this.counts };
}
/**
* Reset metrics (mainly for testing)
*/
static reset() {
this.counts = {
proper: 0,
legacy_converted: 0,
permission_prompt_protocol: 0,
invalid: 0,
};
}
}
/**
* Parse and normalize operation input, handling multiple formats.
*
* Supports:
* 1. Proper MCP-AQL format: { operation: 'x', params: {...} }
* 2. Legacy tool format: { tool: 'x', args: {...} } (silent fallback)
*
* Issue #205: Silent JSON fallback for edge cases.
*
* @param input - Raw input to parse
* @returns Normalized OperationInput or null if invalid
*/
export function parseOperationInput(input) {
// Primary path: proper MCP-AQL format
if (isOperationInput(input)) {
InputFormatMetrics.record('proper');
// Issue #290: Normalize element_type to elementType for internal consistency
// Issue #433: Also normalize plural forms ("memories") to MCP-AQL singular ("memory")
const raw = input;
const rawTypeValue = (raw.element_type ?? raw.elementType);
if (rawTypeValue) {
const normalizedType = normalizeMCPAQLElementType(rawTypeValue);
return {
...input,
elementType: normalizedType,
element_type: normalizedType,
};
}
return input;
}
// Fallback: legacy tool format (silent conversion)
if (isLegacyToolFormat(input)) {
InputFormatMetrics.record('legacy_converted');
// Note: No user-visible logging here - this is a silent fallback
return convertLegacyToMCPAQL(input);
}
// Permission prompt protocol adaptation (Issue #647)
// Claude Code --permission-prompt-tool sends {tool_name, input, agent_identity?}
// without an operation field. Unambiguous: no other CRUDE operation uses
// tool_name as a top-level parameter.
if (input && typeof input === 'object' && !Array.isArray(input)
&& typeof input.tool_name === 'string'
&& !input.operation) {
const raw = input;
InputFormatMetrics.record('permission_prompt_protocol');
return {
operation: 'permission_prompt',
params: raw,
};
}
// Invalid format — input matched none of: {operation, ...}, {tool, ...}, {tool_name, ...}
// Callers handle null by returning an "invalid input" error to the client.
InputFormatMetrics.record('invalid');
return null;
}
/**
* Generate a diagnostic summary of invalid input for error messages.
* Helps agents and developers understand what was actually received when
* parsing fails — especially useful for debugging parallel-call issues (#1656).
*
* @param input - The raw input that failed to parse
* @returns Human-readable diagnostic string describing what was received
*
* @example
* describeInvalidInput(null)
* // => 'Received: null'
*
* describeInvalidInput({ params: { element_name: 'x' } })
* // => 'Received: { params } (missing "operation" field)'
*
* describeInvalidInput([{ operation: 'addEntry' }, { operation: 'addEntry' }])
* // => 'Received: array with 2 items (use { operations: [...] } for batch calls)'
*
* describeInvalidInput({ operation: 123, params: {} })
* // => 'Received: { operation, params } ("operation" is number, expected string)'
*/
export function describeInvalidInput(input) {
if (input === null)
return 'Received: null';
if (input === undefined)
return 'Received: undefined';
if (Array.isArray(input))
return `Received: array with ${input.length} items (use { operations: [...] } for batch calls)`;
if (typeof input !== 'object')
return `Received: ${typeof input}`;
const obj = input;
const keys = Object.keys(obj);
// Truncate key list for very large inputs
const keyPreview = keys.length > 8
? keys.slice(0, 8).join(', ') + `, ... (${keys.length} keys total)`
: keys.join(', ');
const hints = [];
if (!keys.includes('operation')) {
hints.push('missing "operation" field');
}
else if (typeof obj.operation !== 'string') {
hints.push(`"operation" is ${typeof obj.operation}, expected string`);
}
// Check for content that may have caused parsing issues.
// Threshold: content over this length is more likely to have JSON-encoding
// issues with markdown/special characters. Not a limit — just a diagnostic signal.
const CONTENT_DIAGNOSTIC_THRESHOLD = 80;
if (obj.params && typeof obj.params === 'object') {
const params = obj.params;
if (typeof params.content === 'string' && params.content.length > CONTENT_DIAGNOSTIC_THRESHOLD) {
hints.push(`content field is ${params.content.length} chars — if content contains markdown or special characters, ensure it is properly JSON-encoded`);
}
}
const hintStr = hints.length > 0 ? ` (${hints.join('; ')})` : '';
return `Received: { ${keyPreview} }${hintStr}`;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaGFuZGxlcnMvbWNwLWFxbC90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFFSCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSx5Q0FBeUMsQ0FBQztBQUUzRTs7O0dBR0c7QUFDSCxNQUFNLENBQU4sSUFBWSxXQU9YO0FBUEQsV0FBWSxXQUFXO0lBQ3JCLGtDQUFtQixDQUFBO0lBQ25CLDhCQUFlLENBQUE7SUFDZixvQ0FBcUIsQ0FBQTtJQUNyQiw4QkFBZSxDQUFBO0lBQ2YsZ0NBQWlCLENBQUE7SUFDakIsb0NBQXFCLENBQUE7QUFDdkIsQ0FBQyxFQVBXLFdBQVcsS0FBWCxXQUFXLFFBT3RCO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sZUFBZSxHQUFnQztJQUNuRCxPQUFPLEVBQUUsV0FBVyxDQUFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsV0FBVyxDQUFDLE9BQU87SUFDM0QsS0FBSyxFQUFFLFdBQVcsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLFdBQVcsQ0FBQyxLQUFLO0lBQ25ELFFBQVEsRUFBRSxXQUFXLENBQUMsUUFBUSxFQUFFLFNBQVMsRUFBRSxXQUFXLENBQUMsUUFBUTtJQUMvRCxLQUFLLEVBQUUsV0FBVyxDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsV0FBVyxDQUFDLEtBQUs7SUFDbkQsTUFBTSxFQUFFLFdBQVcsQ0FBQyxNQUFNLEVBQUUsUUFBUSxFQUFFLFdBQVcsQ0FBQyxNQUFNO0lBQ3hELFFBQVEsRUFBRSxXQUFXLENBQUMsUUFBUSxFQUFFLFNBQVMsRUFBRSxXQUFXLENBQUMsUUFBUTtDQUNoRSxDQUFDO0FBRUYsK0VBQStFO0FBQy9FLEtBQUssTUFBTSxTQUFTLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO0lBQ25ELElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLGVB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SyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDakUsT0FBTyxlQUFlLFVBQVUsS0FBSyxPQUFPLEVBQUUsQ0FBQztBQUNqRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUeXBlU2NyaXB0IHR5cGUgZGVmaW5pdGlvbnMgZm9yIE1DUC1BUUwgKE1DUCBBZ2VudCBRdWVyeSBMYW5ndWFnZSlcbiAqIFRoZXNlIHR5cGVzIG1hdGNoIHRoZSBHcmFwaFFMIHNjaGVtYSBkZWZpbmVkIGluIHNjaGVtYS5ncmFwaHFsXG4gKi9cblxuaW1wb3J0IHsgRUxFTUVOVF9UWVBFX01BUCB9IGZyb20gJy4uLy4uL3V0aWxzL2VsZW1lbnRUeXBlTm9ybWFsaXphdGlvbi5qcyc7XG5cbi8qKlxuICogRWxlbWVudCB0eXBlcyBzdXBwb3J0ZWQgYnkgRG9sbGhvdXNlTUNQLlxuICogVGhlc2UgY29ycmVzcG9uZCB0byB0aGUgNiBjb3JlIGVsZW1lbnQgdHlwZXMgaW4gdGhlIHN5c3RlbS5cbiAqL1xuZXhwb3J0IGVudW0gRWxlbWVudFR5cGUge1xuICBQZXJzb25hID0gJ3BlcnNvbmEnLFxuICBTa2lsbCA9ICdza2lsbCcsXG4gIFRlbXBsYXRlID0gJ3RlbXBsYXRlJyxcbiAgQWdlbnQgPSAnYWdlbnQnLFxuICBNZW1vcnkgPSAnbWVtb3J5JyxcbiAgRW5zZW1ibGUgPSAnZW5zZW1ibGUnLFxufVxuXG4vKipcbiAqIE5vcm1hbGl6ZSBhbnkgZWxlbWVudCB0eXBlIHN0cmluZyAoc2luZ3VsYXIgb3IgcGx1cmFsKSB0byBhbiBNQ1AtQVFMIEVsZW1lbnRUeXBlIHZhbHVlLlxuICogUmV0dXJucyB1bmRlZmluZWQgZm9yIHVucmVjb2duaXNlZCBpbnB1dC5cbiAqIElzc3VlICM0MzM6IEFjY2VwdCBib3RoIFwibWVtb3J5XCIgYW5kIFwibWVtb3JpZXNcIiBhdCB0aGUgaW5wdXQgcGFyc2luZyBsYXllci5cbiAqL1xuY29uc3QgTUNQQVFMX1RZUEVfTUFQOiBSZWNvcmQ8c3RyaW5nLCBFbGVtZW50VHlwZT4gPSB7XG4gIHBlcnNvbmE6IEVsZW1lbnRUeXBlLlBlcnNvbmEsIHBlcnNvbmFzOiBFbGVtZW50VHlwZS5QZXJzb25hLFxuICBza2lsbDogRWxlbWVudFR5cGUuU2tpbGwsIHNraWxsczogRWxlbWVudFR5cGUuU2tpbGwsXG4gIHRlbXBsYXRlOiBFbGVtZW50VHlwZS5UZW1wbGF0ZSwgdGVtcGxhdGVzOiBFbGVtZW50VHlwZS5UZW1wbGF0ZSxcbiAgYWdlbnQ6IEVsZW1lbnRUeXBlLkFnZW50LCBhZ2VudHM6IEVsZW1lbnRUeXBlLkFnZW50LFxuICBtZW1vcnk6IEVsZW1lbnRUeXBlLk1lbW9yeSwgbWVtb3JpZXM6IEVsZW1lbnRUeXBlLk1lbW9yeSxcbiAgZW5zZW1ibGU6IEVsZW1lbnRUeXBlLkVuc2VtYmxlLCBlbnNlbWJsZXM6IEVsZW1lbnRUeXBlLkVuc2VtYmxlLFxufTtcblxuLy8gUnVudGltZSB2YWxpZGF0aW9uOiBldmVyeSBNQ1AtQVFMIEVsZW1lbnRUeXBlIG11c3QgYXBwZWFyIGluIE1DUEFRTF9UWVBFX01BUFxuZm9yIChjb25zdCBlbnVtVmFsdWUgb2YgT2JqZWN0LnZhbHVlcyhFbGVtZW50VHlwZSkpIHtcbiAgaWYgKCFPYmplY3QudmFsdWVzKE1DUEFRTF9UWVBFX01BUCkuaW5jbHVkZXMoZW51bVZhbHVlKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBNQ1AtQVFMIHR5cGVzOiBFbGVtZW50VHlwZSAnJHtlbnVtVmFsdWV9JyBpcyBtaXNzaW5nIGZyb20gTUNQQVFMX1RZUEVfTUFQLiBgICtcbiAgICAgIGBVcGRhdGUgTUNQQVFMX1RZUEVfTUFQIHRvIGluY2x1ZGUgYm90aCBzaW5ndWxhciBhbmQgcGx1cmFsIGVudHJpZXMgZm9yIHRoaXMgdHlwZS5gXG4gICAgKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXplTUNQQVFMRWxlbWVudFR5cGUodmFsdWU6IHN0cmluZyk6IEVsZW1lbnRUeXBlIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIE1DUEFRTF9UWVBFX01BUFt2YWx1ZS50cmltKCkudG9Mb3dlckNhc2UoKV07XG59XG5cbi8qKlxuICogSW5wdXQgZm9yIGFsbCBNQ1AtQVFMIG9wZXJhdGlvbnMuXG4gKiBUaGUgb3BlcmF0aW9uIGZpZWxkIGRldGVybWluZXMgd2hpY2ggaGFuZGxlciBmdW5jdGlvbiBpcyBpbnZva2VkLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIE9wZXJhdGlvbklucHV0IHtcbiAgLyoqXG4gICAqIFRoZSBvcGVyYXRpb24gdG8gcGVyZm9ybSAoZS5nLiwgJ2NyZWF0ZV9lbGVtZW50JywgJ2xpc3RfZWxlbWVudHMnKVxuICAgKi9cbiAgb3BlcmF0aW9uOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEVsZW1lbnQgdHlwZSBmb3IgZWxlbWVudCBvcGVyYXRpb25zIChzbmFrZV9jYXNlLCBJc3N1ZSAjMjkwKVxuICAgKi9cbiAgZWxlbWVudF90eXBlPzogRWxlbWVudFR5cGU7XG5cbiAgLyoqXG4gICAqIEVsZW1lbnQgdHlwZSBmb3IgZWxlbWVudCBvcGVyYXRpb25zIChjYW1lbENhc2UsIGxlZ2FjeSlcbiAgICogQGRlcHJlY2F0ZWQgVXNlIGVsZW1lbnRfdHlwZSBpbnN0ZWFkXG4gICAqL1xuICBlbGVtZW50VHlwZT86IEVsZW1lbnRUeXBlO1xuXG4gIC8qKlxuICAgKiBPcGVyYXRpb24tc3BlY2lmaWMgcGFyYW1ldGVycyBhcyBhIEpTT04gb2JqZWN0XG4gICAqL1xuICBwYXJhbXM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbn1cblxuLyoqXG4gKiBCYXRjaCByZXF1ZXN0IGNvbnRhaW5pbmcgbXVsdGlwbGUgb3BlcmF0aW9ucyB0byBleGVjdXRlIGluIHNlcXVlbmNlLlxuICogT3BlcmF0aW9ucyBhcmUgZXhlY3V0ZWQgaW4gb3JkZXIsIGFuZCBmYWlsdXJlcyBkbyBub3Qgc3RvcCBleGVjdXRpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQmF0Y2hSZXF1ZXN0IHtcbiAgLyoqXG4gICAqIEFycmF5IG9mIG9wZXJhdGlvbnMgdG8gZXhlY3V0ZSBpbiBzZXF1ZW5jZVxuICAgKi9cbiAgb3BlcmF0aW9uczogQXJyYXk8e1xuICAgIG9wZXJhdGlvbjogc3RyaW5nO1xuICAgIGVsZW1lbnRfdHlwZT86IEVsZW1lbnRUeXBlO1xuICAgIGVsZW1lbnRUeXBlPzogRWxlbWVudFR5cGU7XG4gICAgcGFyYW1zPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIH0+O1xufVxuXG4vKipcbiAqIEluZGl2aWR1YWwgcmVzdWx0IGluIGEgYmF0Y2ggb3BlcmF0aW9uIHJlc3BvbnNlXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQmF0Y2hPcGVyYXRpb25SZXN1bHQge1xuICAvKipcbiAgICogSW5kZXggb2YgdGhlIG9wZXJhdGlvbiBpbiB0aGUgYmF0Y2ggKDAtYmFzZWQpXG4gICAqL1xuICBpbmRleDogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBPcGVyYXRpb24gdGhhdCB3YXMgZXhlY3V0ZWRcbiAgICovXG4gIG9wZXJhdGlvbjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBSZXN1bHQgb2YgdGhlIG9wZXJhdGlvblxuICAgKi9cbiAgcmVzdWx0OiBPcGVyYXRpb25SZXN1bHQ7XG59XG5cbi8qKlxuICogUmVzdWx0IG9mIGEgYmF0Y2ggb3BlcmF0aW9uIHJlcXVlc3QuXG4gKiBzdWNjZXNzPWZhbHNlIHdoZW4gdGhlIGJhdGNoIGl0c2VsZiBpcyByZWplY3RlZCAoZS5nLiBleGNlZWRzIHNpemUgbGltaXQpLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEJhdGNoUmVzdWx0IHtcbiAgc3VjY2VzczogYm9vbGVhbjtcblxuICAvKipcbiAgICogQXJyYXkgb2YgaW5kaXZpZHVhbCBvcGVyYXRpb24gcmVzdWx0c1xuICAgKi9cbiAgcmVzdWx0czogQmF0Y2hPcGVyYXRpb25SZXN1bHRbXTtcblxuICAvKipcbiAgICogU3VtbWFyeSBzdGF0aXN0aWNzXG4gICAqL1xuICBzdW1tYXJ5OiB7XG4gICAgdG90YWw6IG51bWJlcjtcbiAgICBzdWNjZWVkZWQ6IG51bWJlcjtcbiAgICBmYWlsZWQ6IG51bWJlcjtcbiAgfTtcblxuICAvKiogQmF0Y2gtbGV2ZWwgZXJyb3IgbWVzc2FnZSAocHJlc2VudCB3aGVuIHN1Y2Nlc3M9ZmFsc2UpICovXG4gIGVycm9yPzogc3RyaW5nO1xuXG4gIC8qKiBSZXF1ZXN0IGNvcnJlbGF0aW9uIGFuZCB0aW1pbmcgbWV0YWRhdGEgZm9yIHRoZSBvdmVyYWxsIGJhdGNoIChJc3N1ZSAjMzAxKSAqL1xuICBfbWV0YTogUmVzcG9uc2VNZXRhO1xufVxuXG4vKipcbiAqIFN1Y2Nlc3NmdWwgb3BlcmF0aW9uIHJlc3VsdC5cbiAqIERhdGEgY29udGFpbnMgdGhlIG9wZXJhdGlvbi1zcGVjaWZpYyByZXN1bHQgcGF5bG9hZC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBPcGVyYXRpb25TdWNjZXNzIHtcbiAgc3VjY2VzczogdHJ1ZTtcbiAgLyoqIE9wZXJhdGlvbi1zcGVjaWZpYyByZXN1bHQgcGF5bG9hZCAqL1xuICBkYXRhOiB1bmtub3duO1xuICAvKiogUmVxdWVzdCBjb3JyZWxhdGlvbiBhbmQgdGltaW5nIG1ldGFkYXRhIChJc3N1ZSAjMzAxKSAqL1xuICBfbWV0YTogUmVzcG9uc2VNZXRhO1xuICBlcnJvcj86IG5ldmVyO1xufVxuXG4vKipcbiAqIEZhaWxlZCBvcGVyYXRpb24gcmVzdWx0LlxuICogRXJyb3IgY29udGFpbnMgYSBodW1hbi1yZWFkYWJsZSBlcnJvciBtZXNzYWdlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIE9wZXJhdGlvbkZhaWx1cmUge1xuICBzdWNjZXNzOiBmYWxzZTtcbiAgLyoqIEh1bWFuLXJlYWRhYmxlIGVycm9yIG1lc3NhZ2UgKi9cbiAgZXJyb3I6IHN0cmluZztcbiAgLyoqIFJlcXVlc3QgY29ycmVsYXRpb24gYW5kIHRpbWluZyBtZXRhZGF0YSAoSXNzdWUgIzMwMSkgKi9cbiAgX21ldGE6IFJlc3BvbnNlTWV0YTtcbiAgZGF0YT86IG5ldmVyO1xufVxuXG4vKipcbiAqIFN0YW5kYXJkIHJlc3VsdCB0eXBlIGZvciBhbGwgTUNQLUFRTCBvcGVyYXRpb25zLlxuICogRGlzY3JpbWluYXRlZCB1bmlvbiBlbnN1cmVzIHR5cGUgc2FmZXR5OlxuICogLSBzdWNjZXNzOiB0cnVlIOKGkiBkYXRhIGlzIHByZXNlbnQsIGVycm9yIGlzIGFic2VudFxuICogLSBzdWNjZXNzOiBmYWxzZSDihpIgZXJyb3IgaXMgcHJlc2VudCwgZGF0YSBpcyBhYnNlbnRcbiAqL1xuZXhwb3J0IHR5cGUgT3BlcmF0aW9uUmVzdWx0ID0gT3BlcmF0aW9uU3VjY2VzcyB8IE9wZXJhdGlvbkZhaWx1cmU7XG5cbi8qKlxuICogUmVzcG9uc2UgbWV0YWRhdGEgZm9yIHJlcXVlc3QgY29ycmVsYXRpb24gYW5kIHRpbWluZy5cbiAqIEluY2x1ZGVkIGluIGV2ZXJ5IG9wZXJhdGlvbiByZXNwb25zZSB0byBlbmFibGUgbG9nIGNvcnJlbGF0aW9uIGFuZCBwZXJmb3JtYW5jZSBtb25pdG9yaW5nLlxuICogSXNzdWUgIzMwMTogUmVxdWVzdCBJRHMgYW5kIGRpc3RyaWJ1dGVkIHRyYWNpbmcgc3VwcG9ydC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZXNwb25zZU1ldGEge1xuICAvKiogQ29ycmVsYXRpb24gSUQgZnJvbSBDb250ZXh0VHJhY2tlciAobWF0Y2hlcyBjb3JyZWxhdGlvbklkIGluIGxvZyBlbnRyaWVzKSAqL1xuICByZXF1ZXN0SWQ6IHN0cmluZztcbiAgLyoqIFdhbGwtY2xvY2sgbWlsbGlzZWNvbmRzIGZvciB0aGUgb3BlcmF0aW9uICovXG4gIGR1cmF0aW9uTXM6IG51bWJlcjtcbiAgLyoqIElTTyA4NjAxIHJlc3BvbnNlIHRpbWVzdGFtcCAqL1xuICB0aW1lc3RhbXA6IHN0cmluZztcbn1cblxuLyoqXG4gKiBPcGVyYXRpb24gY2F0ZWdvcmllcyBtYXBwZWQgdG8gdGhlaXIgc2FmZXR5IGFubm90YXRpb25zXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT3BlcmF0aW9uU2FmZXR5IHtcbiAgcmVhZE9ubHk6IGJvb2xlYW47XG4gIGRlc3RydWN0aXZlOiBib29sZWFuO1xufVxuXG4vKipcbiAqIE1hcCBvZiBlbmRwb2ludCBuYW1lcyB0byB0aGVpciBzYWZldHkgYW5ub3RhdGlvbnNcbiAqL1xuZXhwb3J0IGNvbnN0IEVORFBPSU5UX1NBRkVUWTogUmVjb3JkPHN0cmluZywgT3BlcmF0aW9uU2FmZXR5PiA9IHtcbiAgbWNwX2FxbF9jcmVhdGU6IHtcbiAgICByZWFkT25seTogZmFsc2UsXG4gICAgZGVzdHJ1Y3RpdmU6IGZhbHNlLFxuICB9LFxuICBtY3BfYXFsX3JlYWQ6IHtcbiAgICByZWFkT25seTogdHJ1ZSxcbiAgICBkZXN0cnVjdGl2ZTogZmFsc2UsXG4gIH0sXG4gIG1jcF9hcWxfdXBkYXRlOiB7XG4gICAgcmVhZE9ubHk6IGZhbHNlLFxuICAgIGRlc3RydWN0aXZlOiB0cnVlLFxuICB9LFxuICBtY3BfYXFsX2RlbGV0ZToge1xuICAgIHJlYWRPbmx5OiBmYWxzZSxcbiAgICBkZXN0cnVjdGl2ZTogdHJ1ZSxcbiAgfSxcbn07XG5cbi8qKlxuICogT3BlcmF0aW9uIG5hbWVzIGdyb3VwZWQgYnkgZW5kcG9pbnRcbiAqL1xuZXhwb3J0IGNvbnN0IEVORFBPSU5UX09QRVJBVElPTlMgPSB7XG4gIGNyZWF0ZTogWydjcmVhdGVfZWxlbWVudCcsICdpbXBvcnRfZWxlbWVudCcsICdhZGRFbnRyeScsICdhY3RpdmF0ZV9lbGVtZW50J10sXG4gIHJlYWQ6IFtcbiAgICAnbGlzdF9lbGVtZW50cycsXG4gICAgJ2dldF9lbGVtZW50JyxcbiAgICAnc2VhcmNoX2VsZW1lbnRzJyxcbiAgICAncXVlcnlfZWxlbWVudHMnLFxuICAgICdnZXRfYWN0aXZlX2VsZW1lbnRzJyxcbiAgICAndmFsaWRhdGVfZWxlbWVudCcsXG4gICAgJ3JlbmRlcicsXG4gICAgJ2V4cG9ydF9lbGVtZW50JyxcbiAgICAnZGVhY3RpdmF0ZV9lbGVtZW50JyxcbiAgICAnaW50cm9zcGVjdCcsXG4gIF0sXG4gIHVwZGF0ZTogWydlZGl0X2VsZW1lbnQnXSxcbiAgZGVsZXRlOiBbJ2RlbGV0ZV9lbGVtZW50JywgJ2V4ZWN1dGVfYWdlbnQnLCAnY2xlYXInXSxcbn0gYXMgY29uc3Q7XG5cbi8qKlxuICogVHlwZSBndWFyZCB0byBjaGVjayBpZiBhIHN0cmluZyBpcyBhIHZhbGlkIEVsZW1lbnRUeXBlLlxuICogQWNjZXB0cyBib3RoIHNpbmd1bGFyIChcIm1lbW9yeVwiKSBhbmQgcGx1cmFsIChcIm1lbW9yaWVzXCIpIGZvcm1zLlxuICogSXNzdWUgIzQzMzogVXNlcnMgYW5kIExMTXMgbmF0dXJhbGx5IHVzZSBlaXRoZXIgZm9ybS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRWxlbWVudFR5cGUodmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBFbGVtZW50VHlwZSB7XG4gIGlmICh0eXBlb2YgdmFsdWUgIT09ICdzdHJpbmcnKSByZXR1cm4gZmFsc2U7XG4gIC8vIEFjY2VwdCBjYW5vbmljYWwgTUNQLUFRTCBzaW5ndWxhciB2YWx1ZXNcbiAgaWYgKE9iamVjdC52YWx1ZXMoRWxlbWVudFR5cGUpLmluY2x1ZGVzKHZhbHVlIGFzIEVsZW1lbnRUeXBlKSkgcmV0dXJuIHRydWU7XG4gIC8vIEFsc28gYWNjZXB0IHBsdXJhbCBwb3J0Zm9saW8tbGF5ZXIgdmFsdWVzIChJc3N1ZSAjNDMzKVxuICByZXR1cm4gdmFsdWUudG9Mb3dlckNhc2UoKSBpbiBFTEVNRU5UX1RZUEVfTUFQO1xufVxuXG4vKipcbiAqIFR5cGUgZ3VhcmQgdG8gY2hlY2sgaWYgYW4gb2JqZWN0IGlzIGEgdmFsaWQgT3BlcmF0aW9uSW5wdXRcbiAqIElzc3VlICMyOTA6IEFjY2VwdHMgYm90aCBlbGVtZW50X3R5cGUgKHNuYWtlX2Nhc2UpIGFuZCBlbGVtZW50VHlwZSAoY2FtZWxDYXNlKVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNPcGVyYXRpb25JbnB1dCh2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIE9wZXJhdGlvbklucHV0IHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ29iamVjdCcgfHwgdmFsdWUgPT09IG51bGwpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBjb25zdCBpbnB1dCA9IHZhbHVlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXG4gIC8vIG9wZXJhdGlvbiBpcyByZXF1aXJlZCBhbmQgbXVzdCBiZSBhIHN0cmluZ1xuICBpZiAodHlwZW9mIGlucHV0Lm9wZXJhdGlvbiAhPT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvLyBJc3N1ZSAjMjkwOiBBY2NlcHQgYm90aCBlbGVtZW50X3R5cGUgYW5kIGVsZW1lbnRUeXBlXG4gIC8vIGVsZW1lbnRUeXBlL2VsZW1lbnRfdHlwZSBpcyBvcHRpb25hbCBidXQgbXVzdCBiZSBhIHZhbGlkIEVsZW1lbnRUeXBlIGlmIHByZXNlbnRcbiAgY29uc3QgZWxlbWVudFR5cGVWYWx1ZSA9IGlucHV0LmVsZW1lbnRfdHlwZSA/PyBpbnB1dC5lbGVtZW50VHlwZTtcbiAgaWYgKGVsZW1lbnRUeXBlVmFsdWUgIT09IHVuZGVmaW5lZCAmJiAhaXNFbGVtZW50VHlwZShlbGVtZW50VHlwZVZhbHVlKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8vIHBhcmFtcyBpcyBvcHRpb25hbCBidXQgbXVzdCBiZSBhIHBsYWluIG9iamVjdCAobm90IGFycmF5LCBub3QgbnVsbCkgaWYgcHJlc2VudFxuICBpZiAoXG4gICAgaW5wdXQucGFyYW1zICE9PSB1bmRlZmluZWQgJiZcbiAgICAodHlwZW9mIGlucHV0LnBhcmFtcyAhPT0gJ29iamVjdCcgfHxcbiAgICAgIGlucHV0LnBhcmFtcyA9PT0gbnVsbCB8fFxuICAgICAgQXJyYXkuaXNBcnJheShpbnB1dC5wYXJhbXMpKVxuICApIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cblxuLyoqXG4gKiBUeXBlIGd1YXJkIHRvIGNoZWNrIGlmIGFuIG9iamVjdCBpcyBhIHZhbGlkIE9wZXJhdGlvblJlc3VsdFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNPcGVyYXRpb25SZXN1bHQodmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBPcGVyYXRpb25SZXN1bHQge1xuICBpZiAodHlwZW9mIHZhbHVlICE9PSAnb2JqZWN0JyB8fCB2YWx1ZSA9PT0gbnVsbCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGNvbnN0IHJlc3VsdCA9IHZhbHVlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXG4gIC8vIHN1Y2Nlc3MgaXMgcmVxdWlyZWQgYW5kIG11c3QgYmUgYSBib29sZWFuXG4gIGlmICh0eXBlb2YgcmVzdWx0LnN1Y2Nlc3MgIT09ICdib29sZWFuJykge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8vIGVycm9yIG11c3QgYmUgYSBzdHJpbmcgaWYgcHJlc2VudFxuICBpZiAocmVzdWx0LmVycm9yICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIHJlc3VsdC5lcnJvciAhPT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvLyBfbWV0YSBpcyByZXF1aXJlZCAoSXNzdWUgIzMwMTogcmVxdWVzdCBjb3JyZWxhdGlvbiBtZXRhZGF0YSlcbiAgaWYgKHR5cGVvZiByZXN1bHQuX21ldGEgIT09ICdvYmplY3QnIHx8IHJlc3VsdC5fbWV0YSA9PT0gbnVsbCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG4vKipcbiAqIFR5cGUgZ3VhcmQgdG8gY2hlY2sgaWYgYW4gb2JqZWN0IGlzIGEgdmFsaWQgQmF0Y2hSZXF1ZXN0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0JhdGNoUmVxdWVzdCh2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIEJhdGNoUmVxdWVzdCB7XG4gIGlmICh0eXBlb2YgdmFsdWUgIT09ICdvYmplY3QnIHx8IHZhbHVlID09PSBudWxsKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgY29uc3QgaW5wdXQgPSB2YWx1ZSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuICAvLyBvcGVyYXRpb25zIGlzIHJlcXVpcmVkIGFuZCBtdXN0IGJlIGFuIGFycmF5XG4gIGlmICghQXJyYXkuaXNBcnJheShpbnB1dC5vcGVyYXRpb25zKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8vIEVhY2ggb3BlcmF0aW9uIG11c3QgYmUgYSB2YWxpZCBPcGVyYXRpb25JbnB1dCBzdHJ1Y3R1cmVcbiAgcmV0dXJuIGlucHV0Lm9wZXJhdGlvbnMuZXZlcnkoKG9wKSA9PiB7XG4gICAgaWYgKHR5cGVvZiBvcCAhPT0gJ29iamVjdCcgfHwgb3AgPT09IG51bGwpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgY29uc3Qgb3BlcmF0aW9uID0gb3AgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG5cbiAgICAvLyBvcGVyYXRpb24gZmllbGQgaXMgcmVxdWlyZWQgYW5kIG11c3QgYmUgYSBzdHJpbmdcbiAgICBpZiAodHlwZW9mIG9wZXJhdGlvbi5vcGVyYXRpb24gIT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gZWxlbWVudFR5cGUgaXMgb3B0aW9uYWwgYnV0IG11c3QgYmUgYSB2YWxpZCBFbGVtZW50VHlwZSBpZiBwcmVzZW50XG4gICAgaWYgKG9wZXJhdGlvbi5lbGVtZW50VHlwZSAhPT0gdW5kZWZpbmVkICYmICFpc0VsZW1lbnRUeXBlKG9wZXJhdGlvbi5lbGVtZW50VHlwZSkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBwYXJhbXMgaXMgb3B0aW9uYWwgYnV0IG11c3QgYmUgYSBwbGFpbiBvYmplY3QgaWYgcHJlc2VudFxuICAgIGlmIChcbiAgICAgIG9wZXJhdGlvbi5wYXJhbXMgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgKHR5cGVvZiBvcGVyYXRpb24ucGFyYW1zICE9PSAnb2JqZWN0JyB8fFxuICAgICAgICBvcGVyYXRpb24ucGFyYW1zID09PSBudWxsIHx8XG4gICAgICAgIEFycmF5LmlzQXJyYXkob3BlcmF0aW9uLnBhcmFtcykpXG4gICAgKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0pO1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBTaWxlbnQgSlNPTiBGYWxsYmFjayBTdXBwb3J0IChJc3N1ZSAjMjA1KVxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIExlZ2FjeSB0b29sIGZvcm1hdCB0aGF0IHNvbWUgTExNcyBtaWdodCBnZW5lcmF0ZS5cbiAqIFRoaXMgaXMgTk9UIGRvY3VtZW50ZWQgYnV0IHNpbGVudGx5IHN1cHBvcnRlZCBmb3IgcmVzaWxpZW5jZS5cbiAqXG4gKiBOT1RFOiBPbmx5IG9uZSBvZiBhcmdzL3BhcmFtcyBzaG91bGQgYmUgdXNlZDsgaWYgYm90aCBhcmUgcHJlc2VudCxcbiAqIGFyZ3MgdGFrZXMgcHJlY2VkZW5jZS5cbiAqL1xuaW50ZXJmYWNlIExlZ2FjeVRvb2xGb3JtYXQge1xuICB0b29sOiBzdHJpbmc7XG4gIC8qKiBPcGVyYXRpb24gYXJndW1lbnRzICh0YWtlcyBwcmVjZWRlbmNlIG92ZXIgcGFyYW1zKSAqL1xuICBhcmdzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIC8qKiBPcGVyYXRpb24gcGFyYW1ldGVycyAodXNlZCBvbmx5IGlmIGFyZ3Mgbm90IHByZXNlbnQpICovXG4gIHBhcmFtcz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xufVxuXG4vKipcbiAqIFR5cGUgZ3VhcmQgdG8gY2hlY2sgaWYgaW5wdXQgaXMgaW4gbGVnYWN5IHRvb2wgZm9ybWF0LlxuICogU3VwcG9ydHM6IHsgdG9vbDogJ29wZXJhdGlvbl9uYW1lJywgYXJnczogey4uLn0gfVxuICogICAgICAgb3I6IHsgdG9vbDogJ29wZXJhdGlvbl9uYW1lJywgcGFyYW1zOiB7Li4ufSB9XG4gKlxuICogSU5URVJOQUwgVVNFIE9OTFkgLSBOb3QgZG9jdW1lbnRlZCB0byB1c2Vycy5cbiAqIElzc3VlICMyMDU6IFNpbGVudCBKU09OIGZhbGxiYWNrIGZvciBlZGdlIGNhc2VzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNMZWdhY3lUb29sRm9ybWF0KHZhbHVlOiB1bmtub3duKTogdmFsdWUgaXMgTGVnYWN5VG9vbEZvcm1hdCB7XG4gIGlmICh0eXBlb2YgdmFsdWUgIT09ICdvYmplY3QnIHx8IHZhbHVlID09PSBudWxsKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgY29uc3QgaW5wdXQgPSB2YWx1ZSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuICAvLyBNdXN0IGhhdmUgJ3Rvb2wnIGFzIGEgc3RyaW5nXG4gIGlmICh0eXBlb2YgaW5wdXQudG9vbCAhPT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvLyBhcmdzL3BhcmFtcyBhcmUgb3B0aW9uYWwgYnV0IG11c3QgYmUgb2JqZWN0cyBpZiBwcmVzZW50XG4gIGlmIChpbnB1dC5hcmdzICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAodHlwZW9mIGlucHV0LmFyZ3MgIT09ICdvYmplY3QnIHx8IGlucHV0LmFyZ3MgPT09IG51bGwgfHwgQXJyYXkuaXNBcnJheShpbnB1dC5hcmdzKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIGlmIChpbnB1dC5wYXJhbXMgIT09IHVuZGVmaW5lZCkge1xuICAgIGlmICh0eXBlb2YgaW5wdXQucGFyYW1zICE9PSAnb2JqZWN0JyB8fCBpbnB1dC5wYXJhbXMgPT09IG51bGwgfHwgQXJyYXkuaXNBcnJheShpbnB1dC5wYXJhbXMpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbi8qKlxuICogQ29udmVydCBsZWdhY3kgdG9vbCBmb3JtYXQgdG8gcHJvcGVyIE9wZXJhdGlvbklucHV0LlxuICpcbiAqIFBSRUNFREVOQ0UgUlVMRVM6XG4gKiAxLiBJZiBgYXJnc2AgaXMgcHJlc2VudCAoZXZlbiBpZiBlbXB0eSB7fSksIHVzZSBgYXJnc2BcbiAqIDIuIE90aGVyd2lzZSwgaWYgYHBhcmFtc2AgaXMgcHJlc2VudCwgdXNlIGBwYXJhbXNgXG4gKiAzLiBJZiBuZWl0aGVyIHByZXNlbnQsIHVzZSBlbXB0eSBvYmplY3Qge31cbiAqXG4gKiBFREdFIENBU0U6IHsgdG9vbDogJ3gnLCBhcmdzOiB7IGE6IDEgfSwgcGFyYW1zOiB7IGI6IDIgfSB9XG4gKiBSZXN1bHQ6IHsgb3BlcmF0aW9uOiAneCcsIHBhcmFtczogeyBhOiAxIH0gfSAoYXJncyB3aW5zLCBwYXJhbXMgaWdub3JlZClcbiAqXG4gKiBJTlRFUk5BTCBVU0UgT05MWSAtIE5vdCBkb2N1bWVudGVkIHRvIHVzZXJzLlxuICogSXNzdWUgIzIwNTogU2lsZW50IEpTT04gZmFsbGJhY2sgZm9yIGVkZ2UgY2FzZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb252ZXJ0TGVnYWN5VG9NQ1BBUUwobGVnYWN5OiBMZWdhY3lUb29sRm9ybWF0KTogT3BlcmF0aW9uSW5wdXQge1xuICByZXR1cm4ge1xuICAgIG9wZXJhdGlvbjogbGVnYWN5LnRvb2wsXG4gICAgLy8gUHJlZmVyICdhcmdzJyBvdmVyICdwYXJhbXMnIGZvciBsZWdhY3kgY29tcGF0aWJpbGl0eVxuICAgIHBhcmFtczogbGVnYWN5LmFyZ3MgfHwgbGVnYWN5LnBhcmFtcyB8fCB7fSxcbiAgfTtcbn1cblxuLyoqXG4gKiBJbnB1dCBmb3JtYXQgdHlwZXMgZm9yIGludGVybmFsIG1ldHJpY3MgdHJhY2tpbmcuXG4gKiBJc3N1ZSAjMjA1OiBTaWxlbnQgSlNPTiBmYWxsYmFjayBmb3IgZWRnZSBjYXNlcy5cbiAqL1xuZXhwb3J0IHR5cGUgSW5wdXRGb3JtYXQgPSAncHJvcGVyJyB8ICdsZWdhY3lfY29udmVydGVkJyB8ICdwZXJtaXNzaW9uX3Byb21wdF9wcm90b2NvbCcgfCAnaW52YWxpZCc7XG5cbi8qKlxuICogSW50ZXJuYWwgbWV0cmljcyBmb3IgaW5wdXQgZm9ybWF0IHRyYWNraW5nLlxuICogTm90IGV4cG9zZWQgdG8gdXNlcnM7IGZvciBtb25pdG9yaW5nIHB1cnBvc2VzIG9ubHkuXG4gKlxuICogSGlnaCBsZWdhY3lfY29udmVydGVkIHJhdGlvIG1pZ2h0IGluZGljYXRlOlxuICogLSBEb2N1bWVudGF0aW9uIGlzc3Vlc1xuICogLSBNb2RlbCBjb25mdXNpb25cbiAqIC0gTmVlZCBmb3IgYmV0dGVyIHByb21wdCBlbmdpbmVlcmluZ1xuICovXG5leHBvcnQgY2xhc3MgSW5wdXRGb3JtYXRNZXRyaWNzIHtcbiAgcHJpdmF0ZSBzdGF0aWMgY291bnRzOiBSZWNvcmQ8SW5wdXRGb3JtYXQsIG51bWJlcj4gPSB7XG4gICAgcHJvcGVyOiAwLFxuICAgIGxlZ2FjeV9jb252ZXJ0ZWQ6IDAsXG4gICAgcGVybWlzc2lvbl9wcm9tcHRfcHJvdG9jb2w6IDAsXG4gICAgaW52YWxpZDogMCxcbiAgfTtcblxuICAvKipcbiAgICogUmVjb3JkIGFuIGlucHV0IGZvcm1hdCBldmVudFxuICAgKi9cbiAgc3RhdGljIHJlY29yZChmb3JtYXQ6IElucHV0Rm9ybWF0KTogdm9pZCB7XG4gICAgdGhpcy5jb3VudHNbZm9ybWF0XSsrO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBjdXJyZW50IG1ldHJpY3Mgc25hcHNob3RcbiAgICovXG4gIHN0YXRpYyBnZXRNZXRyaWNzKCk6IFJlYWRvbmx5PFJlY29yZDxJbnB1dEZvcm1hdCwgbnVtYmVyPj4ge1xuICAgIHJldHVybiB7IC4uLnRoaXMuY291bnRzIH07XG4gIH1cblxuICAvKipcbiAgICogUmVzZXQgbWV0cmljcyAobWFpbmx5IGZvciB0ZXN0aW5nKVxuICAgKi9cbiAgc3RhdGljIHJlc2V0KCk6IHZvaWQge1xuICAgIHRoaXMuY291bnRzID0ge1xuICAgICAgcHJvcGVyOiAwLFxuICAgICAgbGVnYWN5X2NvbnZlcnRlZDogMCxcbiAgICAgIHBlcm1pc3Npb25fcHJvbXB0X3Byb3RvY29sOiAwLFxuICAgICAgaW52YWxpZDogMCxcbiAgICB9O1xuICB9XG59XG5cbi8qKlxuICogUGFyc2UgYW5kIG5vcm1hbGl6ZSBvcGVyYXRpb24gaW5wdXQsIGhhbmRsaW5nIG11bHRpcGxlIGZvcm1hdHMuXG4gKlxuICogU3VwcG9ydHM6XG4gKiAxLiBQcm9wZXIgTUNQLUFRTCBmb3JtYXQ6IHsgb3BlcmF0aW9uOiAneCcsIHBhcmFtczogey4uLn0gfVxuICogMi4gTGVnYWN5IHRvb2wgZm9ybWF0OiB7IHRvb2w6ICd4JywgYXJnczogey4uLn0gfSAoc2lsZW50IGZhbGxiYWNrKVxuICpcbiAqIElzc3VlICMyMDU6IFNpbGVudCBKU09OIGZhbGxiYWNrIGZvciBlZGdlIGNhc2VzLlxuICpcbiAqIEBwYXJhbSBpbnB1dCAtIFJhdyBpbnB1dCB0byBwYXJzZVxuICogQHJldHVybnMgTm9ybWFsaXplZCBPcGVyYXRpb25JbnB1dCBvciBudWxsIGlmIGludmFsaWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlT3BlcmF0aW9uSW5wdXQoaW5wdXQ6IHVua25vd24pOiBPcGVyYXRpb25JbnB1dCB8IG51bGwge1xuICAvLyBQcmltYXJ5IHBhdGg6IHByb3BlciBNQ1AtQVFMIGZvcm1hdFxuICBpZiAoaXNPcGVyYXRpb25JbnB1dChpbnB1dCkpIHtcbiAgICBJbnB1dEZvcm1hdE1ldHJpY3MucmVjb3JkKCdwcm9wZXInKTtcbiAgICAvLyBJc3N1ZSAjMjkwOiBOb3JtYWxpemUgZWxlbWVudF90eXBlIHRvIGVsZW1lbnRUeXBlIGZvciBpbnRlcm5hbCBjb25zaXN0ZW5jeVxuICAgIC8vIElzc3VlICM0MzM6IEFsc28gbm9ybWFsaXplIHBsdXJhbCBmb3JtcyAoXCJtZW1vcmllc1wiKSB0byBNQ1AtQVFMIHNpbmd1bGFyIChcIm1lbW9yeVwiKVxuICAgIGNvbnN0IHJhdyA9IGlucHV0IGFzIHVua25vd24gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgY29uc3QgcmF3VHlwZVZhbHVlID0gKHJhdy5lbGVtZW50X3R5cGUgPz8gcmF3LmVsZW1lbnRUeXBlKSBhcyBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgICBpZiAocmF3VHlwZVZhbHVlKSB7XG4gICAgICBjb25zdCBub3JtYWxpemVkVHlwZSA9IG5vcm1hbGl6ZU1DUEFRTEVsZW1lbnRUeXBlKHJhd1R5cGVWYWx1ZSk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5pbnB1dCxcbiAgICAgICAgZWxlbWVudFR5cGU6IG5vcm1hbGl6ZWRUeXBlLFxuICAgICAgICBlbGVtZW50X3R5cGU6IG5vcm1hbGl6ZWRUeXBlLFxuICAgICAgfSBhcyBPcGVyYXRpb25JbnB1dDtcbiAgICB9XG5cbiAgICByZXR1cm4gaW5wdXQ7XG4gIH1cblxuICAvLyBGYWxsYmFjazogbGVnYWN5IHRvb2wgZm9ybWF0IChzaWxlbnQgY29udmVyc2lvbilcbiAgaWYgKGlzTGVnYWN5VG9vbEZvcm1hdChpbnB1dCkpIHtcbiAgICBJbnB1dEZvcm1hdE1ldHJpY3MucmVjb3JkKCdsZWdhY3lfY29udmVydGVkJyk7XG4gICAgLy8gTm90ZTogTm8gdXNlci12aXNpYmxlIGxvZ2dpbmcgaGVyZSAtIHRoaXMgaXMgYSBzaWxlbnQgZmFsbGJhY2tcbiAgICByZXR1cm4gY29udmVydExlZ2FjeVRvTUNQQVFMKGlucHV0KTtcbiAgfVxuXG4gIC8vIFBlcm1pc3Npb24gcHJvbXB0IHByb3RvY29sIGFkYXB0YXRpb24gKElzc3VlICM2NDcpXG4gIC8vIENsYXVkZSBDb2RlIC0tcGVybWlzc2lvbi1wcm9tcHQtdG9vbCBzZW5kcyB7dG9vbF9uYW1lLCBpbnB1dCwgYWdlbnRfaWRlbnRpdHk/fVxuICAvLyB3aXRob3V0IGFuIG9wZXJhdGlvbiBmaWVsZC4gVW5hbWJpZ3VvdXM6IG5vIG90aGVyIENSVURFIG9wZXJhdGlvbiB1c2VzXG4gIC8vIHRvb2xfbmFtZSBhcyBhIHRvcC1sZXZlbCBwYXJhbWV0ZXIuXG4gIGlmIChpbnB1dCAmJiB0eXBlb2YgaW5wdXQgPT09ICdvYmplY3QnICYmICFBcnJheS5pc0FycmF5KGlucHV0KVxuICAgICAgJiYgdHlwZW9mIChpbnB1dCBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikudG9vbF9uYW1lID09PSAnc3RyaW5nJ1xuICAgICAgJiYgIShpbnB1dCBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikub3BlcmF0aW9uKSB7XG4gICAgY29uc3QgcmF3ID0gaW5wdXQgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgSW5wdXRGb3JtYXRNZXRyaWNzLnJlY29yZCgncGVybWlzc2lvbl9wcm9tcHRfcHJvdG9jb2wnKTtcbiAgICByZXR1cm4ge1xuICAgICAgb3BlcmF0aW9uOiAncGVybWlzc2lvbl9wcm9tcHQnLFxuICAgICAgcGFyYW1zOiByYXcsXG4gICAgfTtcbiAgfVxuXG4gIC8vIEludmFsaWQgZm9ybWF0IOKAlCBpbnB1dCBtYXRjaGVkIG5vbmUgb2Y6IHtvcGVyYXRpb24sIC4uLn0sIHt0b29sLCAuLi59LCB7dG9vbF9uYW1lLCAuLi59XG4gIC8vIENhbGxlcnMgaGFuZGxlIG51bGwgYnkgcmV0dXJuaW5nIGFuIFwiaW52YWxpZCBpbnB1dFwiIGVycm9yIHRvIHRoZSBjbGllbnQuXG4gIElucHV0Rm9ybWF0TWV0cmljcy5yZWNvcmQoJ2ludmFsaWQnKTtcbiAgcmV0dXJuIG51bGw7XG59XG5cbi8qKlxuICogR2VuZXJhdGUgYSBkaWFnbm9zdGljIHN1bW1hcnkgb2YgaW52YWxpZCBpbnB1dCBmb3IgZXJyb3IgbWVzc2FnZXMuXG4gKiBIZWxwcyBhZ2VudHMgYW5kIGRldmVsb3BlcnMgdW5kZXJzdGFuZCB3aGF0IHdhcyBhY3R1YWxseSByZWNlaXZlZCB3aGVuXG4gKiBwYXJzaW5nIGZhaWxzIOKAlCBlc3BlY2lhbGx5IHVzZWZ1bCBmb3IgZGVidWdnaW5nIHBhcmFsbGVsLWNhbGwgaXNzdWVzICgjMTY1NikuXG4gKlxuICogQHBhcmFtIGlucHV0IC0gVGhlIHJhdyBpbnB1dCB0aGF0IGZhaWxlZCB0byBwYXJzZVxuICogQHJldHVybnMgSHVtYW4tcmVhZGFibGUgZGlhZ25vc3RpYyBzdHJpbmcgZGVzY3JpYmluZyB3aGF0IHdhcyByZWNlaXZlZFxuICpcbiAqIEBleGFtcGxlXG4gKiBkZXNjcmliZUludmFsaWRJbnB1dChudWxsKVxuICogLy8gPT4gJ1JlY2VpdmVkOiBudWxsJ1xuICpcbiAqIGRlc2NyaWJlSW52YWxpZElucHV0KHsgcGFyYW1zOiB7IGVsZW1lbnRfbmFtZTogJ3gnIH0gfSlcbiAqIC8vID0+ICdSZWNlaXZlZDogeyBwYXJhbXMgfSAobWlzc2luZyBcIm9wZXJhdGlvblwiIGZpZWxkKSdcbiAqXG4gKiBkZXNjcmliZUludmFsaWRJbnB1dChbeyBvcGVyYXRpb246ICdhZGRFbnRyeScgfSwgeyBvcGVyYXRpb246ICdhZGRFbnRyeScgfV0pXG4gKiAvLyA9PiAnUmVjZWl2ZWQ6IGFycmF5IHdpdGggMiBpdGVtcyAodXNlIHsgb3BlcmF0aW9uczogWy4uLl0gfSBmb3IgYmF0Y2ggY2FsbHMpJ1xuICpcbiAqIGRlc2NyaWJlSW52YWxpZElucHV0KHsgb3BlcmF0aW9uOiAxMjMsIHBhcmFtczoge30gfSlcbiAqIC8vID0+ICdSZWNlaXZlZDogeyBvcGVyYXRpb24sIHBhcmFtcyB9IChcIm9wZXJhdGlvblwiIGlzIG51bWJlciwgZXhwZWN0ZWQgc3RyaW5nKSdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlc2NyaWJlSW52YWxpZElucHV0KGlucHV0OiB1bmtub3duKTogc3RyaW5nIHtcbiAgaWYgKGlucHV0ID09PSBudWxsKSByZXR1cm4gJ1JlY2VpdmVkOiBudWxsJztcbiAgaWYgKGlucHV0ID09PSB1bmRlZmluZWQpIHJldHVybiAnUmVjZWl2ZWQ6IHVuZGVmaW5lZCc7XG4gIGlmIChBcnJheS5pc0FycmF5KGlucHV0KSkgcmV0dXJuIGBSZWNlaXZlZDogYXJyYXkgd2l0aCAke2lucHV0Lmxlbmd0aH0gaXRlbXMgKHVzZSB7IG9wZXJhdGlvbnM6IFsuLi5dIH0gZm9yIGJhdGNoIGNhbGxzKWA7XG4gIGlmICh0eXBlb2YgaW5wdXQgIT09ICdvYmplY3QnKSByZXR1cm4gYFJlY2VpdmVkOiAke3R5cGVvZiBpbnB1dH1gO1xuXG4gIGNvbnN0IG9iaiA9IGlucHV0IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMob2JqKTtcblxuICAvLyBUcnVuY2F0ZSBrZXkgbGlzdCBmb3IgdmVyeSBsYXJnZSBpbnB1dHNcbiAgY29uc3Qga2V5UHJldmlldyA9IGtleXMubGVuZ3RoID4gOFxuICAgID8ga2V5cy5zbGljZSgwLCA4KS5qb2luKCcsICcpICsgYCwgLi4uICgke2tleXMubGVuZ3RofSBrZXlzIHRvdGFsKWBcbiAgICA6IGtleXMuam9pbignLCAnKTtcblxuICBjb25zdCBoaW50czogc3RyaW5nW10gPSBbXTtcbiAgaWYgKCFrZXlzLmluY2x1ZGVzKCdvcGVyYXRpb24nKSkge1xuICAgIGhpbnRzLnB1c2goJ21pc3NpbmcgXCJvcGVyYXRpb25cIiBmaWVsZCcpO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBvYmoub3BlcmF0aW9uICE9PSAnc3RyaW5nJykge1xuICAgIGhpbnRzLnB1c2goYFwib3BlcmF0aW9uXCIgaXMgJHt0eXBlb2Ygb2JqLm9wZXJhdGlvbn0sIGV4cGVjdGVkIHN0cmluZ2ApO1xuICB9XG5cbiAgLy8gQ2hlY2sgZm9yIGNvbnRlbnQgdGhhdCBtYXkgaGF2ZSBjYXVzZWQgcGFyc2luZyBpc3N1ZXMuXG4gIC8vIFRocmVzaG9sZDogY29udGVudCBvdmVyIHRoaXMgbGVuZ3RoIGlzIG1vcmUgbGlrZWx5IHRvIGhhdmUgSlNPTi1lbmNvZGluZ1xuICAvLyBpc3N1ZXMgd2l0aCBtYXJrZG93bi9zcGVjaWFsIGNoYXJhY3RlcnMuIE5vdCBhIGxpbWl0IOKAlCBqdXN0IGEgZGlhZ25vc3RpYyBzaWduYWwuXG4gIGNvbnN0IENPTlRFTlRfRElBR05PU1RJQ19USFJFU0hPTEQgPSA4MDtcbiAgaWYgKG9iai5wYXJhbXMgJiYgdHlwZW9mIG9iai5wYXJhbXMgPT09ICdvYmplY3QnKSB7XG4gICAgY29uc3QgcGFyYW1zID0gb2JqLnBhcmFtcyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICBpZiAodHlwZW9mIHBhcmFtcy5jb250ZW50ID09PSAnc3RyaW5nJyAmJiBwYXJhbXMuY29udGVudC5sZW5ndGggPiBDT05URU5UX0RJQUdOT1NUSUNfVEhSRVNIT0xEKSB7XG4gICAgICBoaW50cy5wdXNoKGBjb250ZW50IGZpZWxkIGlzICR7cGFyYW1zLmNvbnRlbnQubGVuZ3RofSBjaGFycyDigJQgaWYgY29udGVudCBjb250YWlucyBtYXJrZG93biBvciBzcGVjaWFsIGNoYXJhY3RlcnMsIGVuc3VyZSBpdCBpcyBwcm9wZXJseSBKU09OLWVuY29kZWRgKTtcbiAgICB9XG4gIH1cblxuICBjb25zdCBoaW50U3RyID0gaGludHMubGVuZ3RoID4gMCA/IGAgKCR7aGludHMuam9pbignOyAnKX0pYCA6ICcnO1xuICByZXR1cm4gYFJlY2VpdmVkOiB7ICR7a2V5UHJldmlld30gfSR7aGludFN0cn1gO1xufVxuIl19