@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.
296 lines • 30.5 kB
JavaScript
/**
* Type-safe context examples for ensemble conditional activation
*
* This file demonstrates how to use the ConditionContext interface
* when writing activation conditions for ensemble elements.
*
* NOTE: Condition evaluation is not yet implemented. These examples
* show the correct syntax for when evaluation is added in the future.
*
* @see {@link ConditionContext} for available context properties
* @see docs/guides/ensembles.md#conditional-activation for full guide
*
* FIX: DMCP-SEC-006 - No security logging required
* RATIONALE: This file contains ONLY documentation examples and constant declarations.
* All exports are readonly example data (const objects and functions that return test fixtures).
* No security-relevant operations are performed.
* Security logging occurs in EnsembleManager.ts when ensembles are actually activated.
*
* VERIFICATION: All exports are const objects or test helper functions
* @security-audit-suppress DMCP-SEC-006
*/
// ============================================================================
// CONTEXT STRUCTURE
// ============================================================================
/**
* Example context object structure
*
* This shows what a real ConditionContext looks like at runtime.
* All properties are readonly and type-safe.
*/
const exampleContext = {
// Current element being evaluated
element: {
element_name: 'security-validator',
element_type: 'skill',
role: 'support',
priority: 85,
activation: 'conditional',
dependencies: ['input-parser', 'rule-engine'],
purpose: 'Validate security requirements before processing'
},
// Shared context values from other elements
context: {
environment: 'production',
security_review: true,
mode: 'strict',
user_role: 'admin',
request_count: 42,
override_enabled: false
},
// Element that set each context value
contextOwners: {
environment: 'config-loader',
security_review: 'security-checker',
mode: 'mode-detector',
user_role: 'auth-handler',
request_count: 'request-tracker',
override_enabled: 'override-manager'
},
// Activation state
state: {
activatedCount: 3,
failedCount: 0,
activatedElements: ['input-parser', 'rule-engine', 'config-loader'],
failedElements: [],
totalElements: 8
},
// Environment info (reserved for future use)
environment: {},
// Resource usage
resources: {
executionTimeMs: 1250,
contextSize: 6,
cachedInstances: 3
}
};
// ============================================================================
// CONDITION EXAMPLES
// ============================================================================
/**
* Example conditions using element properties
*
* These conditions reference the current element's metadata.
*/
const elementConditions = {
// Check element priority
highPriority: 'priority >= 80',
criticalPriority: 'priority > 90',
// Check element role
isPrimary: "role == 'primary'",
isSupport: "role == 'support'",
// Check dependencies
hasDependencies: 'dependencies.length > 0',
noDependencies: 'dependencies.length == 0',
// Combine multiple checks
criticalPrimaryElement: "priority > 90 && role == 'primary'",
supportWithDeps: "role == 'support' && dependencies.length > 0"
};
/**
* Example conditions using shared context
*
* These conditions reference values set by other elements.
*/
const contextConditions = {
// Check environment
isProduction: "context.environment == 'production'",
isDevelopment: "context.environment == 'development'",
// Check boolean flags
securityReviewPassed: 'context.security_review == true',
overrideEnabled: 'context.override_enabled == true',
// Check numeric values
highRequestCount: 'context.request_count > 100',
lowRequestCount: 'context.request_count < 10',
// Check string values
strictMode: "context.mode == 'strict'",
adminUser: "context.user_role == 'admin'",
// Combine multiple context checks
productionWithSecurity: "context.environment == 'production' && context.security_review == true",
adminOverride: "context.user_role == 'admin' || context.override_enabled == true"
};
/**
* Example conditions using activation state
*
* These conditions depend on how many elements have been activated.
*/
const stateConditions = {
// Check activation progress
afterThreeElements: 'state.activatedCount > 3',
firstElement: 'state.activatedCount == 0',
lastElement: 'state.activatedCount == state.totalElements - 1',
// Check for failures
noFailures: 'state.failedCount == 0',
hasFailures: 'state.failedCount > 0',
tooManyFailures: 'state.failedCount > 2',
// Percentage-based conditions
halfwayDone: 'state.activatedCount >= state.totalElements / 2',
mostlyDone: 'state.activatedCount >= state.totalElements * 0.8',
// Combined with other checks
lateStageNoCriticalFailures: 'state.activatedCount > 5 && state.failedCount < 2'
};
/**
* Example conditions using resource metrics
*
* These conditions gate activation based on resource usage.
*/
const resourceConditions = {
// Check execution time
fastExecution: 'resources.executionTimeMs < 5000',
slowExecution: 'resources.executionTimeMs > 10000',
// Check context size
smallContext: 'resources.contextSize < 100',
largeContext: 'resources.contextSize > 500',
// Check cached instances
fewInstances: 'resources.cachedInstances < 10',
manyInstances: 'resources.cachedInstances > 50',
// Combined resource checks
resourcesAvailable: 'resources.executionTimeMs < 20000 && resources.contextSize < 800',
approachingLimits: 'resources.executionTimeMs > 25000 || resources.contextSize > 900'
};
/**
* Example conditions using context ownership
*
* These conditions check which element set a context value.
*/
const ownershipConditions = {
// Check value source
securityCheckerApproved: "contextOwners.security_review == 'security-checker'",
configLoaderSet: "contextOwners.environment == 'config-loader'",
// Combine with value checks
trustedSecurityReview: "context.security_review == true && contextOwners.security_review == 'security-checker'",
authenticatedAdmin: "context.user_role == 'admin' && contextOwners.user_role == 'auth-handler'"
};
/**
* Complex real-world condition examples
*
* These combine multiple context properties for realistic scenarios.
*/
const complexConditions = {
// Security-gated activation
securityRequirementsMet: `
context.security_review == true &&
context.user_role == 'admin' &&
context.environment == 'production' &&
state.failedCount == 0
`.trim(),
// Progressive activation
progressiveActivation: `
state.activatedCount > 3 &&
state.failedCount < 2 &&
resources.executionTimeMs < 15000
`.trim(),
// Conditional override
allowedOverride: `
(context.user_role == 'admin' || context.override_enabled == true) &&
priority > 70 &&
state.failedCount == 0
`.trim(),
// Performance-based gating
performanceGated: `
resources.executionTimeMs < 20000 &&
resources.contextSize < 800 &&
state.activatedCount < state.totalElements * 0.9
`.trim(),
// Role-based activation
roleBased: `
(role == 'primary' && priority > 80) ||
(role == 'support' && state.activatedCount > 5) ||
(role == 'monitor')
`.trim()
};
// ============================================================================
// TYPE-SAFE CONTEXT USAGE
// ============================================================================
/**
* Demonstrates how to safely access context properties
*
* All properties are readonly and properly typed.
* TypeScript will catch typos and invalid property access.
*/
function demonstrateTypeSafety(ctx) {
// ✓ Valid property access - TypeScript allows
const _elementName = ctx.element.element_name;
const _priority = ctx.element.priority;
const _envValue = ctx.context.environment;
const _activatedCount = ctx.state.activatedCount;
// ✗ Invalid property access - TypeScript errors
// const invalid = ctx.element.invalidProperty; // Error: Property doesn't exist
// ctx.element.element_name = 'new-name'; // Error: readonly property
// ctx.state.activatedCount = 10; // Error: readonly property
// Type guards for unknown context values
if (typeof ctx.context.environment === 'string') {
// TypeScript knows environment is a string here
const _upper = ctx.context.environment.toUpperCase();
}
if (typeof ctx.context.request_count === 'number') {
// TypeScript knows request_count is a number here
const _doubled = ctx.context.request_count * 2;
}
}
/**
* Example of building context in tests
*
* Shows how to construct a valid ConditionContext for testing.
*/
function createTestContext() {
return {
element: {
element_name: 'test-element',
element_type: 'skill',
role: 'support',
priority: 50,
activation: 'conditional',
dependencies: []
},
context: {},
contextOwners: {},
state: {
activatedCount: 0,
failedCount: 0,
activatedElements: [],
failedElements: [],
totalElements: 5
},
environment: {},
resources: {
executionTimeMs: 0,
contextSize: 0,
cachedInstances: 0
}
};
}
// ============================================================================
// DOCUMENTATION EXPORTS
// ============================================================================
/**
* All example conditions organized by category
*
* Import and reference these in documentation and tests.
*/
export const CONDITIONS = {
element: elementConditions,
context: contextConditions,
state: stateConditions,
resources: resourceConditions,
ownership: ownershipConditions,
complex: complexConditions
};
/**
* Example context for documentation and testing
*/
export { exampleContext, createTestContext };
/**
* Type-safe context demonstration
*/
export { demonstrateTypeSafety };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGV4dC1leGFtcGxlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9lbGVtZW50cy9lbnNlbWJsZXMvY29udGV4dC1leGFtcGxlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvQkc7QUFJSCwrRUFBK0U7QUFDL0Usb0JBQW9CO0FBQ3BCLCtFQUErRTtBQUUvRTs7Ozs7R0FLRztBQUNILE1BQU0sY0FBYyxHQUFxQjtJQUN2QyxrQ0FBa0M7SUFDbEMsT0FBTyxFQUFFO1FBQ1AsWUFBWSxFQUFFLG9CQUFvQjtRQUNsQyxZQUFZLEVBQUUsT0FBTztRQUNyQixJQUFJLEVBQUUsU0FBUztRQUNmLFFBQVEsRUFBRSxFQUFFO1FBQ1osVUFBVSxFQUFFLGFBQWE7UUFDekIsWUFBWSxFQUFFLENBQUMsY0FBYyxFQUFFLGFBQWEsQ0FBQztRQUM3QyxPQUFPLEVBQUUsa0RBQWtEO0tBQzVEO0lBRUQsNENBQTRDO0lBQzVDLE9BQU8sRUFBRTtRQUNQLFdBQVcsRUFBRSxZQUFZO1FBQ3pCLGVBQWUsRUFBRSxJQUFJO1FBQ3JCLElBQUksRUFBRSxRQUFRO1FBQ2QsU0FBUyxFQUFFLE9BQU87UUFDbEIsYUFBYSxFQUFFLEVBQUU7UUFDakIsZ0JBQWdCLEVBQUUsS0FBSztLQUN4QjtJQUVELHNDQUFzQztJQUN0QyxhQUFhLEVBQUU7UUFDYixXQUFXLEVBQUUsZUFBZTtRQUM1QixlQUFlLEVBQUUsa0JBQWtCO1FBQ25DLElBQUksRUFBRSxlQUFlO1FBQ3JCLFNBQVMsRUFBRSxjQUFjO1FBQ3pCLGFBQWEsRUFBRSxpQkFBaUI7UUFDaEMsZ0JBQWdCLEVBQUUsa0JBQWtCO0tBQ3JDO0lBRUQsbUJBQW1CO0lBQ25CLEtBQUssRUFBRTtRQUNMLGNBQWMsRUFBRSxDQUFDO1FBQ2pCLFdBQVcsRUFBRSxDQUFDO1FBQ2QsaUJBQWlCLEVBQUUsQ0FBQyxjQUFjLEVBQUUsYUFBYSxFQUFFLGVBQWUsQ0FB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QUNyQixJQUFJLEVBQUUsU0FBUztZQUNmLFFBQVEsRUFBRSxFQUFFO1lBQ1osVUFBVSxFQUFFLGFBQWE7WUFDekIsWUFBWSxFQUFFLEVBQUU7U0FDakI7UUFDRCxPQUFPLEVBQUUsRUFBRTtRQUNYLGFBQWEsRUFBRSxFQUFFO1FBQ2pCLEtBQUssRUFBRTtZQUNMLGNBQWMsRUFBRSxDQUFDO1lBQ2pCLFdBQVcsRUFBRSxDQUFDO1lBQ2QsaUJBQWlCLEVBQUUsRUFBRTtZQUNyQixjQUFjLEVBQUUsRUFBRTtZQUNsQixhQUFhLEVBQUUsQ0FBQztTQUNqQjtRQUNELFdBQVcsRUFBRSxFQUFFO1FBQ2YsU0FBUyxFQUFFO1lBQ1QsZUFBZSxFQUFFLENBQUM7WUFDbEIsV0FBVyxFQUFFLENBQUM7WUFDZCxlQUFlLEVBQUUsQ0FBQztTQUNuQjtLQUNGLENBQUM7QUFDSixDQUFDO0FBRUQsK0VBQStFO0FBQy9FLHdCQUF3QjtBQUN4QiwrRUFBK0U7QUFFL0U7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLFVBQVUsR0FBRztJQUN4QixPQUFPLEVBQUUsaUJBQWlCO0lBQzFCLE9BQU8sRUFBRSxpQkFBaUI7SUFDMUIsS0FBSyxFQUFFLGVBQWU7SUFDdEIsU0FBUyxFQUFFLGtCQUFrQjtJQUM3QixTQUFTLEVBQUUsbUJBQW1CO0lBQzlCLE9BQU8sRUFBRSxpQkFBaUI7Q0FDbEIsQ0FBQztBQUVYOztHQUVHO0FBQ0gsT0FBTyxFQUFFLGNBQWMsRUFBRSxpQkFBaUIsRUFBRSxDQUFDO0FBRTdDOztHQUVHO0FBQ0gsT0FBTyxFQUFFLHFCQUFxQixFQUFFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFR5cGUtc2FmZSBjb250ZXh0IGV4YW1wbGVzIGZvciBlbnNlbWJsZSBjb25kaXRpb25hbCBhY3RpdmF0aW9uXG4gKlxuICogVGhpcyBmaWxlIGRlbW9uc3RyYXRlcyBob3cgdG8gdXNlIHRoZSBDb25kaXRpb25Db250ZXh0IGludGVyZmFjZVxuICogd2hlbiB3cml0aW5nIGFjdGl2YXRpb24gY29uZGl0aW9ucyBmb3IgZW5zZW1ibGUgZWxlbWVudHMuXG4gKlxuICogTk9URTogQ29uZGl0aW9uIGV2YWx1YXRpb24gaXMgbm90IHlldCBpbXBsZW1lbnRlZC4gVGhlc2UgZXhhbXBsZXNcbiAqIHNob3cgdGhlIGNvcnJlY3Qgc3ludGF4IGZvciB3aGVuIGV2YWx1YXRpb24gaXMgYWRkZWQgaW4gdGhlIGZ1dHVyZS5cbiAqXG4gKiBAc2VlIHtAbGluayBDb25kaXRpb25Db250ZXh0fSBmb3IgYXZhaWxhYmxlIGNvbnRleHQgcHJvcGVydGllc1xuICogQHNlZSBkb2NzL2d1aWRlcy9lbnNlbWJsZXMubWQjY29uZGl0aW9uYWwtYWN0aXZhdGlvbiBmb3IgZnVsbCBndWlkZVxuICpcbiAqIEZJWDogRE1DUC1TRUMtMDA2IC0gTm8gc2VjdXJpdHkgbG9nZ2luZyByZXF1aXJlZFxuICogUkFUSU9OQUxFOiBUaGlzIGZpbGUgY29udGFpbnMgT05MWSBkb2N1bWVudGF0aW9uIGV4YW1wbGVzIGFuZCBjb25zdGFudCBkZWNsYXJhdGlvbnMuXG4gKiBBbGwgZXhwb3J0cyBhcmUgcmVhZG9ubHkgZXhhbXBsZSBkYXRhIChjb25zdCBvYmplY3RzIGFuZCBmdW5jdGlvbnMgdGhhdCByZXR1cm4gdGVzdCBmaXh0dXJlcykuXG4gKiBObyBzZWN1cml0eS1yZWxldmFudCBvcGVyYXRpb25zIGFyZSBwZXJmb3JtZWQuXG4gKiBTZWN1cml0eSBsb2dnaW5nIG9jY3VycyBpbiBFbnNlbWJsZU1hbmFnZXIudHMgd2hlbiBlbnNlbWJsZXMgYXJlIGFjdHVhbGx5IGFjdGl2YXRlZC5cbiAqXG4gKiBWRVJJRklDQVRJT046IEFsbCBleHBvcnRzIGFyZSBjb25zdCBvYmplY3RzIG9yIHRlc3QgaGVscGVyIGZ1bmN0aW9uc1xuICogQHNlY3VyaXR5LWF1ZGl0LXN1cHByZXNzIERNQ1AtU0VDLTAwNlxuICovXG5cbmltcG9ydCB0eXBlIHsgQ29uZGl0aW9uQ29udGV4dCB9IGZyb20gJy4vdHlwZXMuanMnO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBDT05URVhUIFNUUlVDVFVSRVxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIEV4YW1wbGUgY29udGV4dCBvYmplY3Qgc3RydWN0dXJlXG4gKlxuICogVGhpcyBzaG93cyB3aGF0IGEgcmVhbCBDb25kaXRpb25Db250ZXh0IGxvb2tzIGxpa2UgYXQgcnVudGltZS5cbiAqIEFsbCBwcm9wZXJ0aWVzIGFyZSByZWFkb25seSBhbmQgdHlwZS1zYWZlLlxuICovXG5jb25zdCBleGFtcGxlQ29udGV4dDogQ29uZGl0aW9uQ29udGV4dCA9IHtcbiAgLy8gQ3VycmVudCBlbGVtZW50IGJlaW5nIGV2YWx1YXRlZFxuICBlbGVtZW50OiB7XG4gICAgZWxlbWVudF9uYW1lOiAnc2VjdXJpdHktdmFsaWRhdG9yJyxcbiAgICBlbGVtZW50X3R5cGU6ICdza2lsbCcsXG4gICAgcm9sZTogJ3N1cHBvcnQnLFxuICAgIHByaW9yaXR5OiA4NSxcbiAgICBhY3RpdmF0aW9uOiAnY29uZGl0aW9uYWwnLFxuICAgIGRlcGVuZGVuY2llczogWydpbnB1dC1wYXJzZXInLCAncnVsZS1lbmdpbmUnXSxcbiAgICBwdXJwb3NlOiAnVmFsaWRhdGUgc2VjdXJpdHkgcmVxdWlyZW1lbnRzIGJlZm9yZSBwcm9jZXNzaW5nJ1xuICB9LFxuXG4gIC8vIFNoYXJlZCBjb250ZXh0IHZhbHVlcyBmcm9tIG90aGVyIGVsZW1lbnRzXG4gIGNvbnRleHQ6IHtcbiAgICBlbnZpcm9ubWVudDogJ3Byb2R1Y3Rpb24nLFxuICAgIHNlY3VyaXR5X3JldmlldzogdHJ1ZSxcbiAgICBtb2RlOiAnc3RyaWN0JyxcbiAgICB1c2VyX3JvbGU6ICdhZG1pbicsXG4gICAgcmVxdWVzdF9jb3VudDogNDIsXG4gICAgb3ZlcnJpZGVfZW5hYmxlZDogZmFsc2VcbiAgfSxcblxuICAvLyBFbGVtZW50IHRoYXQgc2V0IGVhY2ggY29udGV4dCB2YWx1ZVxuICBjb250ZXh0T3duZXJzOiB7XG4gICAgZW52aXJvbm1lbnQ6ICdjb25maWctbG9hZGVyJyxcbiAgICBzZWN1cml0eV9yZXZpZXc6ICdzZWN1cml0eS1jaGVja2VyJyxcbiAgICBtb2RlOiAnbW9kZS1kZXRlY3RvcicsXG4gICAgdXNlcl9yb2xlOiAnYXV0aC1oYW5kbGVyJyxcbiAgICByZXF1ZXN0X2NvdW50OiAncmVxdWVzdC10cmFja2VyJyxcbiAgICBvdmVycmlkZV9lbmFibGVkOiAnb3ZlcnJpZGUtbWFuYWdlcidcbiAgfSxcblxuICAvLyBBY3RpdmF0aW9uIHN0YXRlXG4gIHN0YXRlOiB7XG4gICAgYWN0aXZhdGVkQ291bnQ6IDMsXG4gICAgZmFpbGVkQ291bnQ6IDAsXG4gICAgYWN0aXZhdGVkRWxlbWVudHM6IFsnaW5wdXQtcGFyc2VyJywgJ3J1bGUtZW5naW5lJywgJ2NvbmZpZy1sb2FkZXInXSxcbiAgICBmYWlsZWRFbGVtZW50czogW10sXG4gICAgdG90YWxFbGVtZW50czogOFxuICB9LFxuXG4gIC8vIEVudmlyb25tZW50IGluZm8gKHJlc2VydmVkIGZvciBmdXR1cmUgdXNlKVxuICBlbnZpcm9ubWVudDoge30sXG5cbiAgLy8gUmVzb3VyY2UgdXNhZ2VcbiAgcmVzb3VyY2VzOiB7XG4gICAgZXhlY3V0aW9uVGltZU1zOiAxMjUwLFxuICAgIGNvbnRleHRTaXplOiA2LFxuICAgIGNhY2hlZEluc3RhbmNlczogM1xuICB9XG59O1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBDT05ESVRJT04gRVhBTVBMRVNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBFeGFtcGxlIGNvbmRpdGlvbnMgdXNpbmcgZWxlbWVudCBwcm9wZXJ0aWVzXG4gKlxuICogVGhlc2UgY29uZGl0aW9ucyByZWZlcmVuY2UgdGhlIGN1cnJlbnQgZWxlbWVudCdzIG1ldGFkYXRhLlxuICovXG5jb25zdCBlbGVtZW50Q29uZGl0aW9ucyA9IHtcbiAgLy8gQ2hlY2sgZWxlbWVudCBwcmlvcml0eVxuICBoaWdoUHJpb3JpdHk6ICdwcmlvcml0eSA+PSA4MCcsXG4gIGNyaXRpY2FsUHJpb3JpdHk6ICdwcmlvcml0eSA+IDkwJyxcblxuICAvLyBDaGVjayBlbGVtZW50IHJvbGVcbiAgaXNQcmltYXJ5OiBcInJvbGUgPT0gJ3ByaW1hcnknXCIsXG4gIGlzU3VwcG9ydDogXCJyb2xlID09ICdzdXBwb3J0J1wiLFxuXG4gIC8vIENoZWNrIGRlcGVuZGVuY2llc1xuICBoYXNEZXBlbmRlbmNpZXM6ICdkZXBlbmRlbmNpZXMubGVuZ3RoID4gMCcsXG4gIG5vRGVwZW5kZW5jaWVzOiAnZGVwZW5kZW5jaWVzLmxlbmd0aCA9PSAwJyxcblxuICAvLyBDb21iaW5lIG11bHRpcGxlIGNoZWNrc1xuICBjcml0aWNhbFByaW1hcnlFbGVtZW50OiBcInByaW9yaXR5ID4gOTAgJiYgcm9sZSA9PSAncHJpbWFyeSdcIixcbiAgc3VwcG9ydFdpdGhEZXBzOiBcInJvbGUgPT0gJ3N1cHBvcnQnICYmIGRlcGVuZGVuY2llcy5sZW5ndGggPiAwXCJcbn0gYXMgY29uc3Q7XG5cbi8qKlxuICogRXhhbXBsZSBjb25kaXRpb25zIHVzaW5nIHNoYXJlZCBjb250ZXh0XG4gKlxuICogVGhlc2UgY29uZGl0aW9ucyByZWZlcmVuY2UgdmFsdWVzIHNldCBieSBvdGhlciBlbGVtZW50cy5cbiAqL1xuY29uc3QgY29udGV4dENvbmRpdGlvbnMgPSB7XG4gIC8vIENoZWNrIGVudmlyb25tZW50XG4gIGlzUHJvZHVjdGlvbjogXCJjb250ZXh0LmVudmlyb25tZW50ID09ICdwcm9kdWN0aW9uJ1wiLFxuICBpc0RldmVsb3BtZW50OiBcImNvbnRleHQuZW52aXJvbm1lbnQgPT0gJ2RldmVsb3BtZW50J1wiLFxuXG4gIC8vIENoZWNrIGJvb2xlYW4gZmxhZ3NcbiAgc2VjdXJpdHlSZXZpZXdQYXNzZWQ6ICdjb250ZXh0LnNlY3VyaXR5X3JldmlldyA9PSB0cnVlJyxcbiAgb3ZlcnJpZGVFbmFibGVkOiAnY29udGV4dC5vdmVycmlkZV9lbmFibGVkID09IHRydWUnLFxuXG4gIC8vIENoZWNrIG51bWVyaWMgdmFsdWVzXG4gIGhpZ2hSZXF1ZXN0Q291bnQ6ICdjb250ZXh0LnJlcXVlc3RfY291bnQgPiAxMDAnLFxuICBsb3dSZXF1ZXN0Q291bnQ6ICdjb250ZXh0LnJlcXVlc3RfY291bnQgPCAxMCcsXG5cbiAgLy8gQ2hlY2sgc3RyaW5nIHZhbHVlc1xuICBzdHJpY3RNb2RlOiBcImNvbnRleHQubW9kZSA9PSAnc3RyaWN0J1wiLFxuICBhZG1pblVzZXI6IFwiY29udGV4dC51c2VyX3JvbGUgPT0gJ2FkbWluJ1wiLFxuXG4gIC8vIENvbWJpbmUgbXVsdGlwbGUgY29udGV4dCBjaGVja3NcbiAgcHJvZHVjdGlvbldpdGhTZWN1cml0eTogXCJjb250ZXh0LmVudmlyb25tZW50ID09ICdwcm9kdWN0aW9uJyAmJiBjb250ZXh0LnNlY3VyaXR5X3JldmlldyA9PSB0cnVlXCIsXG4gIGFkbWluT3ZlcnJpZGU6IFwiY29udGV4dC51c2VyX3JvbGUgPT0gJ2FkbWluJyB8fCBjb250ZXh0Lm92ZXJyaWRlX2VuYWJsZWQgPT0gdHJ1ZVwiXG59IGFzIGNvbnN0O1xuXG4vKipcbiAqIEV4YW1wbGUgY29uZGl0aW9ucyB1c2luZyBhY3RpdmF0aW9uIHN0YXRlXG4gKlxuICogVGhlc2UgY29uZGl0aW9ucyBkZXBlbmQgb24gaG93IG1hbnkgZWxlbWVudHMgaGF2ZSBiZWVuIGFjdGl2YXRlZC5cbiAqL1xuY29uc3Qgc3RhdGVDb25kaXRpb25zID0ge1xuICAvLyBDaGVjayBhY3RpdmF0aW9uIHByb2dyZXNzXG4gIGFmdGVyVGhyZWVFbGVtZW50czogJ3N0YXRlLmFjdGl2YXRlZENvdW50ID4gMycsXG4gIGZpcnN0RWxlbWVudDogJ3N0YXRlLmFjdGl2YXRlZENvdW50ID09IDAnLFxuICBsYXN0RWxlbWVudDogJ3N0YXRlLmFjdGl2YXRlZENvdW50ID09IHN0YXRlLnRvdGFsRWxlbWVudHMgLSAxJyxcblxuICAvLyBDaGVjayBmb3IgZmFpbHVyZXNcbiAgbm9GYWlsdXJlczogJ3N0YXRlLmZhaWxlZENvdW50ID09IDAnLFxuICBoYXNGYWlsdXJlczogJ3N0YXRlLmZhaWxlZENvdW50ID4gMCcsXG4gIHRvb01hbnlGYWlsdXJlczogJ3N0YXRlLmZhaWxlZENvdW50ID4gMicsXG5cbiAgLy8gUGVyY2VudGFnZS1iYXNlZCBjb25kaXRpb25zXG4gIGhhbGZ3YXlEb25lOiAnc3RhdGUuYWN0aXZhdGVkQ291bnQgPj0gc3RhdGUudG90YWxFbGVtZW50cyAvIDInLFxuICBtb3N0bHlEb25lOiAnc3RhdGUuYWN0aXZhdGVkQ291bnQgPj0gc3RhdGUudG90YWxFbGVtZW50cyAqIDAuOCcsXG5cbiAgLy8gQ29tYmluZWQgd2l0aCBvdGhlciBjaGVja3NcbiAgbGF0ZVN0YWdlTm9Dcml0aWNhbEZhaWx1cmVzOiAnc3RhdGUuYWN0aXZhdGVkQ291bnQgPiA1ICYmIHN0YXRlLmZhaWxlZENvdW50IDwgMidcbn0gYXMgY29uc3Q7XG5cbi8qKlxuICogRXhhbXBsZSBjb25kaXRpb25zIHVzaW5nIHJlc291cmNlIG1ldHJpY3NcbiAqXG4gKiBUaGVzZSBjb25kaXRpb25zIGdhdGUgYWN0aXZhdGlvbiBiYXNlZCBvbiByZXNvdXJjZSB1c2FnZS5cbiAqL1xuY29uc3QgcmVzb3VyY2VDb25kaXRpb25zID0ge1xuICAvLyBDaGVjayBleGVjdXRpb24gdGltZVxuICBmYXN0RXhlY3V0aW9uOiAncmVzb3VyY2VzLmV4ZWN1dGlvblRpbWVNcyA8IDUwMDAnLFxuICBzbG93RXhlY3V0aW9uOiAncmVzb3VyY2VzLmV4ZWN1dGlvblRpbWVNcyA+IDEwMDAwJyxcblxuICAvLyBDaGVjayBjb250ZXh0IHNpemVcbiAgc21hbGxDb250ZXh0OiAncmVzb3VyY2VzLmNvbnRleHRTaXplIDwgMTAwJyxcbiAgbGFyZ2VDb250ZXh0OiAncmVzb3VyY2VzLmNvbnRleHRTaXplID4gNTAwJyxcblxuICAvLyBDaGVjayBjYWNoZWQgaW5zdGFuY2VzXG4gIGZld0luc3RhbmNlczogJ3Jlc291cmNlcy5jYWNoZWRJbnN0YW5jZXMgPCAxMCcsXG4gIG1hbnlJbnN0YW5jZXM6ICdyZXNvdXJjZXMuY2FjaGVkSW5zdGFuY2VzID4gNTAnLFxuXG4gIC8vIENvbWJpbmVkIHJlc291cmNlIGNoZWNrc1xuICByZXNvdXJjZXNBdmFpbGFibGU6ICdyZXNvdXJjZXMuZXhlY3V0aW9uVGltZU1zIDwgMjAwMDAgJiYgcmVzb3VyY2VzLmNvbnRleHRTaXplIDwgODAwJyxcbiAgYXBwcm9hY2hpbmdMaW1pdHM6ICdyZXNvdXJjZXMuZXhlY3V0aW9uVGltZU1zID4gMjUwMDAgfHwgcmVzb3VyY2VzLmNvbnRleHRTaXplID4gOTAwJ1xufSBhcyBjb25zdDtcblxuLyoqXG4gKiBFeGFtcGxlIGNvbmRpdGlvbnMgdXNpbmcgY29udGV4dCBvd25lcnNoaXBcbiAqXG4gKiBUaGVzZSBjb25kaXRpb25zIGNoZWNrIHdoaWNoIGVsZW1lbnQgc2V0IGEgY29udGV4dCB2YWx1ZS5cbiAqL1xuY29uc3Qgb3duZXJzaGlwQ29uZGl0aW9ucyA9IHtcbiAgLy8gQ2hlY2sgdmFsdWUgc291cmNlXG4gIHNlY3VyaXR5Q2hlY2tlckFwcHJvdmVkOiBcImNvbnRleHRPd25lcnMuc2VjdXJpdHlfcmV2aWV3ID09ICdzZWN1cml0eS1jaGVja2VyJ1wiLFxuICBjb25maWdMb2FkZXJTZXQ6IFwiY29udGV4dE93bmVycy5lbnZpcm9ubWVudCA9PSAnY29uZmlnLWxvYWRlcidcIixcblxuICAvLyBDb21iaW5lIHdpdGggdmFsdWUgY2hlY2tzXG4gIHRydXN0ZWRTZWN1cml0eVJldmlldzogXCJjb250ZXh0LnNlY3VyaXR5X3JldmlldyA9PSB0cnVlICYmIGNvbnRleHRPd25lcnMuc2VjdXJpdHlfcmV2aWV3ID09ICdzZWN1cml0eS1jaGVja2VyJ1wiLFxuICBhdXRoZW50aWNhdGVkQWRtaW46IFwiY29udGV4dC51c2VyX3JvbGUgPT0gJ2FkbWluJyAmJiBjb250ZXh0T3duZXJzLnVzZXJfcm9sZSA9PSAnYXV0aC1oYW5kbGVyJ1wiXG59IGFzIGNvbnN0O1xuXG4vKipcbiAqIENvbXBsZXggcmVhbC13b3JsZCBjb25kaXRpb24gZXhhbXBsZXNcbiAqXG4gKiBUaGVzZSBjb21iaW5lIG11bHRpcGxlIGNvbnRleHQgcHJvcGVydGllcyBmb3IgcmVhbGlzdGljIHNjZW5hcmlvcy5cbiAqL1xuY29uc3QgY29tcGxleENvbmRpdGlvbnMgPSB7XG4gIC8vIFNlY3VyaXR5LWdhdGVkIGFjdGl2YXRpb25cbiAgc2VjdXJpdHlSZXF1aXJlbWVudHNNZXQ6IGBcbiAgICBjb250ZXh0LnNlY3VyaXR5X3JldmlldyA9PSB0cnVlICYmXG4gICAgY29udGV4dC51c2VyX3JvbGUgPT0gJ2FkbWluJyAmJlxuICAgIGNvbnRleHQuZW52aXJvbm1lbnQgPT0gJ3Byb2R1Y3Rpb24nICYmXG4gICAgc3RhdGUuZmFpbGVkQ291bnQgPT0gMFxuICBgLnRyaW0oKSxcblxuICAvLyBQcm9ncmVzc2l2ZSBhY3RpdmF0aW9uXG4gIHByb2dyZXNzaXZlQWN0aXZhdGlvbjogYFxuICAgIHN0YXRlLmFjdGl2YXRlZENvdW50ID4gMyAmJlxuICAgIHN0YXRlLmZhaWxlZENvdW50IDwgMiAmJlxuICAgIHJlc291cmNlcy5leGVjdXRpb25UaW1lTXMgPCAxNTAwMFxuICBgLnRyaW0oKSxcblxuICAvLyBDb25kaXRpb25hbCBvdmVycmlkZVxuICBhbGxvd2VkT3ZlcnJpZGU6IGBcbiAgICAoY29udGV4dC51c2VyX3JvbGUgPT0gJ2FkbWluJyB8fCBjb250ZXh0Lm92ZXJyaWRlX2VuYWJsZWQgPT0gdHJ1ZSkgJiZcbiAgICBwcmlvcml0eSA+IDcwICYmXG4gICAgc3RhdGUuZmFpbGVkQ291bnQgPT0gMFxuICBgLnRyaW0oKSxcblxuICAvLyBQZXJmb3JtYW5jZS1iYXNlZCBnYXRpbmdcbiAgcGVyZm9ybWFuY2VHYXRlZDogYFxuICAgIHJlc291cmNlcy5leGVjdXRpb25UaW1lTXMgPCAyMDAwMCAmJlxuICAgIHJlc291cmNlcy5jb250ZXh0U2l6ZSA8IDgwMCAmJlxuICAgIHN0YXRlLmFjdGl2YXRlZENvdW50IDwgc3RhdGUudG90YWxFbGVtZW50cyAqIDAuOVxuICBgLnRyaW0oKSxcblxuICAvLyBSb2xlLWJhc2VkIGFjdGl2YXRpb25cbiAgcm9sZUJhc2VkOiBgXG4gICAgKHJvbGUgPT0gJ3ByaW1hcnknICYmIHByaW9yaXR5ID4gODApIHx8XG4gICAgKHJvbGUgPT0gJ3N1cHBvcnQnICYmIHN0YXRlLmFjdGl2YXRlZENvdW50ID4gNSkgfHxcbiAgICAocm9sZSA9PSAnbW9uaXRvcicpXG4gIGAudHJpbSgpXG59IGFzIGNvbnN0O1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBUWVBFLVNBRkUgQ09OVEVYVCBVU0FHRVxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIERlbW9uc3RyYXRlcyBob3cgdG8gc2FmZWx5IGFjY2VzcyBjb250ZXh0IHByb3BlcnRpZXNcbiAqXG4gKiBBbGwgcHJvcGVydGllcyBhcmUgcmVhZG9ubHkgYW5kIHByb3Blcmx5IHR5cGVkLlxuICogVHlwZVNjcmlwdCB3aWxsIGNhdGNoIHR5cG9zIGFuZCBpbnZhbGlkIHByb3BlcnR5IGFjY2Vzcy5cbiAqL1xuZnVuY3Rpb24gZGVtb25zdHJhdGVUeXBlU2FmZXR5KGN0eDogQ29uZGl0aW9uQ29udGV4dCk6IHZvaWQge1xuICAvLyDinJMgVmFsaWQgcHJvcGVydHkgYWNjZXNzIC0gVHlwZVNjcmlwdCBhbGxvd3NcbiAgY29uc3QgX2VsZW1lbnROYW1lID0gY3R4LmVsZW1lbnQuZWxlbWVudF9uYW1lO1xuICBjb25zdCBfcHJpb3JpdHkgPSBjdHguZWxlbWVudC5wcmlvcml0eTtcbiAgY29uc3QgX2VudlZhbHVlID0gY3R4LmNvbnRleHQuZW52aXJvbm1lbnQ7XG4gIGNvbnN0IF9hY3RpdmF0ZWRDb3VudCA9IGN0eC5zdGF0ZS5hY3RpdmF0ZWRDb3VudDtcblxuICAvLyDinJcgSW52YWxpZCBwcm9wZXJ0eSBhY2Nlc3MgLSBUeXBlU2NyaXB0IGVycm9yc1xuICAvLyBjb25zdCBpbnZhbGlkID0gY3R4LmVsZW1lbnQuaW52YWxpZFByb3BlcnR5OyAgICAgLy8gRXJyb3I6IFByb3BlcnR5IGRvZXNuJ3QgZXhpc3RcbiAgLy8gY3R4LmVsZW1lbnQuZWxlbWVudF9uYW1lID0gJ25ldy1uYW1lJzsgICAgICAgICAgIC8vIEVycm9yOiByZWFkb25seSBwcm9wZXJ0eVxuICAvLyBjdHguc3RhdGUuYWN0aXZhdGVkQ291bnQgPSAxMDsgICAgICAgICAgICAgICAgICAgLy8gRXJyb3I6IHJlYWRvbmx5IHByb3BlcnR5XG5cbiAgLy8gVHlwZSBndWFyZHMgZm9yIHVua25vd24gY29udGV4dCB2YWx1ZXNcbiAgaWYgKHR5cGVvZiBjdHguY29udGV4dC5lbnZpcm9ubWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAvLyBUeXBlU2NyaXB0IGtub3dzIGVudmlyb25tZW50IGlzIGEgc3RyaW5nIGhlcmVcbiAgICBjb25zdCBfdXBwZXIgPSBjdHguY29udGV4dC5lbnZpcm9ubWVudC50b1VwcGVyQ2FzZSgpO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBjdHguY29udGV4dC5yZXF1ZXN0X2NvdW50ID09PSAnbnVtYmVyJykge1xuICAgIC8vIFR5cGVTY3JpcHQga25vd3MgcmVxdWVzdF9jb3VudCBpcyBhIG51bWJlciBoZXJlXG4gICAgY29uc3QgX2RvdWJsZWQgPSBjdHguY29udGV4dC5yZXF1ZXN0X2NvdW50ICogMjtcbiAgfVxufVxuXG4vKipcbiAqIEV4YW1wbGUgb2YgYnVpbGRpbmcgY29udGV4dCBpbiB0ZXN0c1xuICpcbiAqIFNob3dzIGhvdyB0byBjb25zdHJ1Y3QgYSB2YWxpZCBDb25kaXRpb25Db250ZXh0IGZvciB0ZXN0aW5nLlxuICovXG5mdW5jdGlvbiBjcmVhdGVUZXN0Q29udGV4dCgpOiBDb25kaXRpb25Db250ZXh0IHtcbiAgcmV0dXJuIHtcbiAgICBlbGVtZW50OiB7XG4gICAgICBlbGVtZW50X25hbWU6ICd0ZXN0LWVsZW1lbnQnLFxuICAgICAgZWxlbWVudF90eXBlOiAnc2tpbGwnLFxuICAgICAgcm9sZTogJ3N1cHBvcnQnLFxuICAgICAgcHJpb3JpdHk6IDUwLFxuICAgICAgYWN0aXZhdGlvbjogJ2NvbmRpdGlvbmFsJyxcbiAgICAgIGRlcGVuZGVuY2llczogW11cbiAgICB9LFxuICAgIGNvbnRleHQ6IHt9LFxuICAgIGNvbnRleHRPd25lcnM6IHt9LFxuICAgIHN0YXRlOiB7XG4gICAgICBhY3RpdmF0ZWRDb3VudDogMCxcbiAgICAgIGZhaWxlZENvdW50OiAwLFxuICAgICAgYWN0aXZhdGVkRWxlbWVudHM6IFtdLFxuICAgICAgZmFpbGVkRWxlbWVudHM6IFtdLFxuICAgICAgdG90YWxFbGVtZW50czogNVxuICAgIH0sXG4gICAgZW52aXJvbm1lbnQ6IHt9LFxuICAgIHJlc291cmNlczoge1xuICAgICAgZXhlY3V0aW9uVGltZU1zOiAwLFxuICAgICAgY29udGV4dFNpemU6IDAsXG4gICAgICBjYWNoZWRJbnN0YW5jZXM6IDBcbiAgICB9XG4gIH07XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIERPQ1VNRU5UQVRJT04gRVhQT1JUU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIEFsbCBleGFtcGxlIGNvbmRpdGlvbnMgb3JnYW5pemVkIGJ5IGNhdGVnb3J5XG4gKlxuICogSW1wb3J0IGFuZCByZWZlcmVuY2UgdGhlc2UgaW4gZG9jdW1lbnRhdGlvbiBhbmQgdGVzdHMuXG4gKi9cbmV4cG9ydCBjb25zdCBDT05ESVRJT05TID0ge1xuICBlbGVtZW50OiBlbGVtZW50Q29uZGl0aW9ucyxcbiAgY29udGV4dDogY29udGV4dENvbmRpdGlvbnMsXG4gIHN0YXRlOiBzdGF0ZUNvbmRpdGlvbnMsXG4gIHJlc291cmNlczogcmVzb3VyY2VDb25kaXRpb25zLFxuICBvd25lcnNoaXA6IG93bmVyc2hpcENvbmRpdGlvbnMsXG4gIGNvbXBsZXg6IGNvbXBsZXhDb25kaXRpb25zXG59IGFzIGNvbnN0O1xuXG4vKipcbiAqIEV4YW1wbGUgY29udGV4dCBmb3IgZG9jdW1lbnRhdGlvbiBhbmQgdGVzdGluZ1xuICovXG5leHBvcnQgeyBleGFtcGxlQ29udGV4dCwgY3JlYXRlVGVzdENvbnRleHQgfTtcblxuLyoqXG4gKiBUeXBlLXNhZmUgY29udGV4dCBkZW1vbnN0cmF0aW9uXG4gKi9cbmV4cG9ydCB7IGRlbW9uc3RyYXRlVHlwZVNhZmV0eSB9O1xuIl19