@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.
297 lines • 33.4 kB
JavaScript
/**
* Goal Template System for Agent Goal Management
*
* Provides pre-configured goal templates for common patterns,
* making it easier to create well-structured goals with appropriate
* settings for different scenarios.
*/
import { SecurityMonitor } from '../../security/securityMonitor.js';
// Pre-defined goal templates
export const GOAL_TEMPLATES = {
// Development templates
'feature-implementation': {
id: 'feature-implementation',
name: 'Feature Implementation',
description: 'Implement a new feature with proper testing and documentation',
category: 'development',
defaultValues: {
priority: 'high',
importance: 8,
urgency: 5,
estimatedEffort: 8,
riskLevel: 'medium',
tags: ['feature', 'development', 'implementation']
},
requiredFields: ['featureName', 'specifications'],
successCriteria: [
'Code implemented and tested',
'Unit tests passing',
'Documentation updated',
'Code reviewed'
],
riskMitigations: [
'Break down into smaller tasks',
'Early prototype validation',
'Regular progress reviews'
]
},
'bug-fix-critical': {
id: 'bug-fix-critical',
name: 'Critical Bug Fix',
description: 'Fix a critical production bug affecting users',
category: 'maintenance',
defaultValues: {
priority: 'critical',
importance: 10,
urgency: 10,
estimatedEffort: 2,
riskLevel: 'high',
tags: ['bug', 'critical', 'production']
},
requiredFields: ['bugId', 'impactDescription'],
successCriteria: [
'Bug identified and reproduced',
'Fix implemented and tested',
'Regression tests added',
'Deployed to production'
],
riskMitigations: [
'Rollback plan prepared',
'Thorough testing in staging',
'Monitor after deployment'
]
},
'research-spike': {
id: 'research-spike',
name: 'Research Spike',
description: 'Time-boxed research to explore technical options',
category: 'research',
defaultValues: {
priority: 'medium',
importance: 7,
urgency: 3,
estimatedEffort: 4,
riskLevel: 'low',
tags: ['research', 'spike', 'exploration']
},
requiredFields: ['researchQuestion', 'timeBox'],
successCriteria: [
'Research question answered',
'Options documented',
'Recommendations provided',
'Decision criteria established'
]
},
'security-audit': {
id: 'security-audit',
name: 'Security Audit',
description: 'Conduct security audit of system or component',
category: 'operations',
defaultValues: {
priority: 'high',
importance: 9,
urgency: 6,
estimatedEffort: 6,
riskLevel: 'medium',
tags: ['security', 'audit', 'compliance']
},
requiredFields: ['auditScope', 'complianceFramework'],
successCriteria: [
'Vulnerabilities identified',
'Risk assessment completed',
'Remediation plan created',
'Report generated'
]
},
'performance-optimization': {
id: 'performance-optimization',
name: 'Performance Optimization',
description: 'Optimize system performance based on metrics',
category: 'maintenance',
defaultValues: {
priority: 'medium',
importance: 6,
urgency: 4,
estimatedEffort: 8,
riskLevel: 'medium',
tags: ['performance', 'optimization', 'metrics']
},
requiredFields: ['performanceMetrics', 'targetImprovement'],
successCriteria: [
'Baseline metrics captured',
'Optimizations implemented',
'Performance improved by target %',
'No regression in functionality'
]
},
'documentation-update': {
id: 'documentation-update',
name: 'Documentation Update',
description: 'Update technical or user documentation',
category: 'maintenance',
defaultValues: {
priority: 'low',
importance: 5,
urgency: 2,
estimatedEffort: 3,
riskLevel: 'low',
tags: ['documentation', 'maintenance']
},
requiredFields: ['documentType', 'sections'],
successCriteria: [
'Documentation reviewed',
'Updates completed',
'Reviewed by stakeholders',
'Published to appropriate location'
]
},
'quarterly-planning': {
id: 'quarterly-planning',
name: 'Quarterly Planning',
description: 'Plan goals and priorities for the quarter',
category: 'planning',
defaultValues: {
priority: 'high',
importance: 9,
urgency: 7,
estimatedEffort: 12,
riskLevel: 'low',
tags: ['planning', 'quarterly', 'strategy']
},
requiredFields: ['quarter', 'objectives'],
successCriteria: [
'Goals defined and prioritized',
'Resources allocated',
'Timeline established',
'Stakeholder alignment'
]
},
'custom-goal': {
id: 'custom-goal',
name: 'Custom Goal',
description: 'Create a custom goal with your own parameters',
category: 'custom',
defaultValues: {
priority: 'medium',
importance: 5,
urgency: 5,
riskLevel: 'medium',
tags: ['custom']
}
}
};
/**
* Apply a goal template to create a new goal
*/
export function applyGoalTemplate(templateId, customFields) {
// SECURITY FIX: Add audit logging for goal template usage
SecurityMonitor.logSecurityEvent({
type: 'GOAL_TEMPLATE_APPLIED',
severity: 'LOW',
source: 'applyGoalTemplate',
details: `Goal template '${templateId}' applied`
});
const template = GOAL_TEMPLATES[templateId];
if (!template) {
throw new Error(`Goal template '${templateId}' not found`);
}
// Validate required fields
if (template.requiredFields) {
for (const field of template.requiredFields) {
if (!customFields[field]) {
throw new Error(`Required field '${field}' missing for template '${template.name}'`);
}
}
}
// Calculate Eisenhower quadrant based on template defaults
const importance = customFields.importance || template.defaultValues.importance;
const urgency = customFields.urgency || template.defaultValues.urgency;
const eisenhowerQuadrant = calculateEisenhowerQuadrant(importance, urgency);
// Ensure description is provided
const description = customFields.description ||
`${template.name}: ${template.requiredFields?.map(f => customFields[f]).filter(Boolean).join(' - ') || template.description}`;
return {
...template.defaultValues,
...customFields,
description,
eisenhowerQuadrant,
templateId,
createdAt: new Date(),
updatedAt: new Date()
};
}
/**
* Calculate Eisenhower quadrant from importance and urgency
*/
function calculateEisenhowerQuadrant(importance, urgency) {
if (importance >= 7 && urgency >= 7)
return 'do_first';
if (importance >= 7 && urgency < 7)
return 'schedule';
if (importance < 7 && urgency >= 7)
return 'delegate';
return 'eliminate';
}
/**
* Get template recommendations based on goal description
*/
export function recommendGoalTemplate(description) {
const lowercaseDesc = description.toLowerCase();
const recommendations = [];
// Keywords mapping to templates
const keywordMap = {
'feature-implementation': ['feature', 'implement', 'develop', 'build'],
'bug-fix-critical': ['bug', 'fix', 'critical', 'urgent', 'broken', 'error'],
'research-spike': ['research', 'explore', 'investigate', 'spike', 'evaluate'],
'security-audit': ['security', 'audit', 'vulnerability', 'compliance'],
'performance-optimization': ['performance', 'optimize', 'speed', 'slow', 'latency'],
'documentation-update': ['document', 'docs', 'readme', 'guide', 'manual'],
'quarterly-planning': ['plan', 'quarter', 'roadmap', 'strategy']
};
// Check for keyword matches
for (const [templateId, keywords] of Object.entries(keywordMap)) {
if (keywords.some(keyword => lowercaseDesc.includes(keyword))) {
recommendations.push(templateId);
}
}
// Always include custom as an option
if (recommendations.length === 0) {
recommendations.push('custom-goal');
}
return recommendations;
}
/**
* Validate goal against its template
*/
export function validateGoalAgainstTemplate(goal, // AgentGoal type
templateId) {
if (!templateId || !GOAL_TEMPLATES[templateId]) {
return { valid: true, errors: [] };
}
// SECURITY FIX: Add audit logging for template validation
SecurityMonitor.logSecurityEvent({
type: 'GOAL_TEMPLATE_VALIDATION',
severity: 'LOW',
source: 'validateGoalAgainstTemplate',
details: `Validating goal against template '${templateId}'`
});
const template = GOAL_TEMPLATES[templateId];
const errors = [];
// Check required fields
if (template.requiredFields) {
for (const field of template.requiredFields) {
if (!goal[field]) {
errors.push(`Missing required field: ${field}`);
}
}
}
// Validate risk level matches template category
if (template.category === 'operations' && goal.riskLevel === 'high') {
errors.push('High risk operations goals require additional approval');
}
return {
valid: errors.length === 0,
errors
};
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ29hbFRlbXBsYXRlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9lbGVtZW50cy9hZ2VudHMvZ29hbFRlbXBsYXRlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFHSCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFxQnBFLDZCQUE2QjtBQUM3QixNQUFNLENBQUMsTUFBTSxjQUFjLEdBQWlDO0lBQzFELHdCQUF3QjtJQUN4Qix3QkFBd0IsRUFBRTtRQUN4QixFQUFFLEVBQUUsd0JBQXdCO1FBQzVCLElBQUksRUFBRSx3QkFBd0I7UUFDOUIsV0FBVyxFQUFFLCtEQUErRDtRQUM1RSxRQUFRLEVBQUUsYUFBYTtRQUN2QixhQUFhLEVBQUU7WUFDYixRQUFRLEVBQUUsTUFBTTtZQUNoQixVQUFVLEVBQUUsQ0FBQztZQUNiLE9BQU8sRUFBRSxDQUFDO1lBQ1YsZUFBZSxFQUFFLENBQUM7WUFDbEIsU0FBUyxFQUFFLFFBQVE7WUFDbkIsSUFBSSxFQUFFLENBQUMsU0FBUyxFQUFFLGFBQWEsRUFBRSxnQkFBZ0IsQ0FBQztTQUNuRDtRQUNELGNBQWMsRUFBRSxDQUFDLGFBQWEsRUFBRSxnQkFBZ0IsQ0FBQztRQUNqRCxlQUFlLEVBQUU7WUFDZiw2QkFBNkI7WUFDN0Isb0JBQW9CO1lBQ3BCLHVCQUF1QjtZQUN2QixlQUFlO1NBQ2hCO1FBQ0QsZUFBZSxFQUFFO1lBQ2YsK0JBQStCO1lBQy9CLDRCQUE0QjtZQUM1QiwwQkFBMEI7U0FDM0I7S0FDRjtJQUVELGtCQUFrQixFQUFFO1FBQ2xCLEVBQUUsRUFBRSxrQkFBa0I7UUFDdEIsSUFBSSxFQUFFLGtCQUFrQjtRQUN4QixXQUFXLEVBQUUsK0NBQStDO1FBQzVELFFBQVEsRUFBRSxhQUFhO1FBQ3ZCLGFBQWEsRUFBRTtZQUNiLFFBQVEsRUFBRSxVQUFVO1lBQ3BCLFVBQVUsRUFBRSxFQUFFO1lBQ2QsT0FBTyxFQUFFLEVBQUU7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cUNBQXFDLFVBQVUsR0FBRztLQUM1RCxDQUFDLENBQUM7SUFFSCxNQUFNLFFBQVEsR0FBRyxjQUFjLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDNUMsTUFBTSxNQUFNLEdBQWEsRUFBRSxDQUFDO0lBRTVCLHdCQUF3QjtJQUN4QixJQUFJLFFBQVEsQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUM1QixLQUFLLE1BQU0sS0FBSyxJQUFJLFFBQVEsQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUM1QyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7Z0JBQ2pCLE1BQU0sQ0FBQyxJQUFJLENBQUMsMkJBQTJCLEtBQUssRUFBRSxDQUFDLENBQUM7WUFDbEQsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQsZ0RBQWdEO0lBQ2hELElBQUksUUFBUSxDQUFDLFFBQVEsS0FBSyxZQUFZLElBQUksSUFBSSxDQUFDLFNBQVMsS0FBSyxNQUFNLEVBQUUsQ0FBQztRQUNwRSxNQUFNLENBQUMsSUFBSSxDQUFDLHdEQUF3RCxDQUFDLENBQUM7SUFDeEUsQ0FBQztJQUVELE9BQU87UUFDTCxLQUFLLEVBQUUsTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQzFCLE1BQU07S0FDUCxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogR29hbCBUZW1wbGF0ZSBTeXN0ZW0gZm9yIEFnZW50IEdvYWwgTWFuYWdlbWVudFxuICogXG4gKiBQcm92aWRlcyBwcmUtY29uZmlndXJlZCBnb2FsIHRlbXBsYXRlcyBmb3IgY29tbW9uIHBhdHRlcm5zLFxuICogbWFraW5nIGl0IGVhc2llciB0byBjcmVhdGUgd2VsbC1zdHJ1Y3R1cmVkIGdvYWxzIHdpdGggYXBwcm9wcmlhdGVcbiAqIHNldHRpbmdzIGZvciBkaWZmZXJlbnQgc2NlbmFyaW9zLlxuICovXG5cbmltcG9ydCB7IEdvYWxQcmlvcml0eSwgR29hbFN0YXR1cywgRWlzZW5ob3dlclF1YWRyYW50IH0gZnJvbSAnLi90eXBlcy5qcyc7XG5pbXBvcnQgeyBTZWN1cml0eU1vbml0b3IgfSBmcm9tICcuLi8uLi9zZWN1cml0eS9zZWN1cml0eU1vbml0b3IuanMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEdvYWxUZW1wbGF0ZSB7XG4gIGlkOiBzdHJpbmc7XG4gIG5hbWU6IHN0cmluZztcbiAgZGVzY3JpcHRpb246IHN0cmluZztcbiAgY2F0ZWdvcnk6ICdkZXZlbG9wbWVudCcgfCAnb3BlcmF0aW9ucycgfCAncmVzZWFyY2gnIHwgJ3BsYW5uaW5nJyB8ICdtYWludGVuYW5jZScgfCAnY3VzdG9tJztcbiAgZGVmYXVsdFZhbHVlczoge1xuICAgIHByaW9yaXR5OiBHb2FsUHJpb3JpdHk7XG4gICAgaW1wb3J0YW5jZTogbnVtYmVyOyAgLy8gMS0xMFxuICAgIHVyZ2VuY3k6IG51bWJlcjsgICAgIC8vIDEtMTBcbiAgICBlc3RpbWF0ZWRFZmZvcnQ/OiBudW1iZXI7ICAvLyBob3Vyc1xuICAgIHJpc2tMZXZlbD86ICdsb3cnIHwgJ21lZGl1bScgfCAnaGlnaCc7XG4gICAgdGFncz86IHN0cmluZ1tdO1xuICB9O1xuICByZXF1aXJlZEZpZWxkcz86IHN0cmluZ1tdO1xuICBzdWdnZXN0ZWREZXBlbmRlbmNpZXM/OiBzdHJpbmdbXTtcbiAgc3VjY2Vzc0NyaXRlcmlhPzogc3RyaW5nW107XG4gIHJpc2tNaXRpZ2F0aW9ucz86IHN0cmluZ1tdO1xufVxuXG4vLyBQcmUtZGVmaW5lZCBnb2FsIHRlbXBsYXRlc1xuZXhwb3J0IGNvbnN0IEdPQUxfVEVNUExBVEVTOiBSZWNvcmQ8c3RyaW5nLCBHb2FsVGVtcGxhdGU+ID0ge1xuICAvLyBEZXZlbG9wbWVudCB0ZW1wbGF0ZXNcbiAgJ2ZlYXR1cmUtaW1wbGVtZW50YXRpb24nOiB7XG4gICAgaWQ6ICdmZWF0dXJlLWltcGxlbWVudGF0aW9uJyxcbiAgICBuYW1lOiAnRmVhdHVyZSBJbXBsZW1lbnRhdGlvbicsXG4gICAgZGVzY3JpcHRpb246ICdJbXBsZW1lbnQgYSBuZXcgZmVhdHVyZSB3aXRoIHByb3BlciB0ZXN0aW5nIGFuZCBkb2N1bWVudGF0aW9uJyxcbiAgICBjYXRlZ29yeTogJ2RldmVsb3BtZW50JyxcbiAgICBkZWZhdWx0VmFsdWVzOiB7XG4gICAgICBwcmlvcml0eTogJ2hpZ2gnLFxuICAgICAgaW1wb3J0YW5jZTogOCxcbiAgICAgIHVyZ2VuY3k6IDUsXG4gICAgICBlc3RpbWF0ZWRFZmZvcnQ6IDgsXG4gICAgICByaXNrTGV2ZWw6ICdtZWRpdW0nLFxuICAgICAgdGFnczogWydmZWF0dXJlJywgJ2RldmVsb3BtZW50JywgJ2ltcGxlbWVudGF0aW9uJ11cbiAgICB9LFxuICAgIHJlcXVpcmVkRmllbGRzOiBbJ2ZlYXR1cmVOYW1lJywgJ3NwZWNpZmljYXRpb25zJ10sXG4gICAgc3VjY2Vzc0NyaXRlcmlhOiBbXG4gICAgICAnQ29kZSBpbXBsZW1lbnRlZCBhbmQgdGVzdGVkJyxcbiAgICAgICdVbml0IHRlc3RzIHBhc3NpbmcnLFxuICAgICAgJ0RvY3VtZW50YXRpb24gdXBkYXRlZCcsXG4gICAgICAnQ29kZSByZXZpZXdlZCdcbiAgICBdLFxuICAgIHJpc2tNaXRpZ2F0aW9uczogW1xuICAgICAgJ0JyZWFrIGRvd24gaW50byBzbWFsbGVyIHRhc2tzJyxcbiAgICAgICdFYXJseSBwcm90b3R5cGUgdmFsaWRhdGlvbicsXG4gICAgICAnUmVndWxhciBwcm9ncmVzcyByZXZpZXdzJ1xuICAgIF1cbiAgfSxcblxuICAnYnVnLWZpeC1jcml0aWNhbCc6IHtcbiAgICBpZDogJ2J1Zy1maXgtY3JpdGljYWwnLFxuICAgIG5hbWU6ICdDcml0aWNhbCBCdWcgRml4JyxcbiAgICBkZXNjcmlwdGlvbjogJ0ZpeCBhIGNyaXRpY2FsIHByb2R1Y3Rpb24gYnVnIGFmZmVjdGluZyB1c2VycycsXG4gICAgY2F0ZWdvcnk6ICdtYWludGVuYW5jZScsXG4gICAgZGVmYXVsdFZhbHVlczoge1xuICAgICAgcHJpb3JpdHk6ICdjcml0aWNhbCcsXG4gICAgICBpbXBvcnRhbmNlOiAxMCxcbiAgICAgIHVyZ2VuY3k6IDEwLFxuICAgICAgZXN0aW1hdGVkRWZmb3J0OiAyLFxuICAgICAgcmlza0xldmVsOiAnaGlnaCcsXG4gICAgICB0YWdzOiBbJ2J1ZycsICdjcml0aWNhbCcsICdwcm9kdWN0aW9uJ11cbiAgICB9LFxuICAgIHJlcXVpcmVkRmllbGRzOiBbJ2J1Z0lkJywgJ2ltcGFjdERlc2NyaXB0aW9uJ10sXG4gICAgc3VjY2Vzc0NyaXRlcmlhOiBbXG4gICAgICAnQnVnIGlkZW50aWZpZWQgYW5kIHJlcHJvZHVjZWQnLFxuICAgICAgJ0ZpeCBpbXBsZW1lbnRlZCBhbmQgdGVzdGVkJyxcbiAgICAgICdSZWdyZXNzaW9uIHRlc3RzIGFkZGVkJyxcbiAgICAgICdEZXBsb3llZCB0byBwcm9kdWN0aW9uJ1xuICAgIF0sXG4gICAgcmlza01pdGlnYXRpb25zOiBbXG4gICAgICAnUm9sbGJhY2sgcGxhbiBwcmVwYXJlZCcsXG4gICAgICAnVGhvcm91Z2ggdGVzdGluZyBpbiBzdGFnaW5nJyxcbiAgICAgICdNb25pdG9yIGFmdGVyIGRlcGxveW1lbnQnXG4gICAgXVxuICB9LFxuXG4gICdyZXNlYXJjaC1zcGlrZSc6IHtcbiAgICBpZDogJ3Jlc2VhcmNoLXNwaWtlJyxcbiAgICBuYW1lOiAnUmVzZWFyY2ggU3Bpa2UnLFxuICAgIGRlc2NyaXB0aW9uOiAnVGltZS1ib3hlZCByZXNlYXJjaCB0byBleHBsb3JlIHRlY2huaWNhbCBvcHRpb25zJyxcbiAgICBjYXRlZ29yeTogJ3Jlc2VhcmNoJyxcbiAgICBkZWZhdWx0VmFsdWVzOiB7XG4gICAgICBwcmlvcml0eTogJ21lZGl1bScsXG4gICAgICBpbXBvcnRhbmNlOiA3LFxuICAgICAgdXJnZW5jeTogMyxcbiAgICAgIGVzdGltYXRlZEVmZm9ydDogNCxcbiAgICAgIHJpc2tMZXZlbDogJ2xvdycsXG4gICAgICB0YWdzOiBbJ3Jlc2VhcmNoJywgJ3NwaWtlJywgJ2V4cGxvcmF0aW9uJ11cbiAgICB9LFxuICAgIHJlcXVpcmVkRmllbGRzOiBbJ3Jlc2VhcmNoUXVlc3Rpb24nLCAndGltZUJveCddLFxuICAgIHN1Y2Nlc3NDcml0ZXJpYTogW1xuICAgICAgJ1Jlc2VhcmNoIHF1ZXN0aW9uIGFuc3dlcmVkJyxcbiAgICAgICdPcHRpb25zIGRvY3VtZW50ZWQnLFxuICAgICAgJ1JlY29tbWVuZGF0aW9ucyBwcm92aWRlZCcsXG4gICAgICAnRGVjaXNpb24gY3JpdGVyaWEgZXN0YWJsaXNoZWQnXG4gICAgXVxuICB9LFxuXG4gICdzZWN1cml0eS1hdWRpdCc6IHtcbiAgICBpZDogJ3NlY3VyaXR5LWF1ZGl0JyxcbiAgICBuYW1lOiAnU2VjdXJpdHkgQXVkaXQnLFxuICAgIGRlc2NyaXB0aW9uOiAnQ29uZHVjdCBzZWN1cml0eSBhdWRpdCBvZiBzeXN0ZW0gb3IgY29tcG9uZW50JyxcbiAgICBjYXRlZ29yeTogJ29wZXJhdGlvbnMnLFxuICAgIGRlZmF1bHRWYWx1ZXM6IHtcbiAgICAgIHByaW9yaXR5OiAnaGlnaCcsXG4gICAgICBpbXBvcnRhbmNlOiA5LFxuICAgICAgdXJnZW5jeTogNixcbiAgICAgIGVzdGltYXRlZEVmZm9ydDogNixcbiAgICAgIHJpc2tMZXZlbDogJ21lZGl1bScsXG4gICAgICB0YWdzOiBbJ3NlY3VyaXR5JywgJ2F1ZGl0JywgJ2NvbXBsaWFuY2UnXVxuICAgIH0sXG4gICAgcmVxdWlyZWRGaWVsZHM6IFsnYXVkaXRTY29wZScsICdjb21wbGlhbmNlRnJhbWV3b3JrJ10sXG4gICAgc3VjY2Vzc0NyaXRlcmlhOiBbXG4gICAgICAnVnVsbmVyYWJpbGl0aWVzIGlkZW50aWZpZWQnLFxuICAgICAgJ1Jpc2sgYXNzZXNzbWVudCBjb21wbGV0ZWQnLFxuICAgICAgJ1JlbWVkaWF0aW9uIHBsYW4gY3JlYXRlZCcsXG4gICAgICAnUmVwb3J0IGdlbmVyYXRlZCdcbiAgICBdXG4gIH0sXG5cbiAgJ3BlcmZvcm1hbmNlLW9wdGltaXphdGlvbic6IHtcbiAgICBpZDogJ3BlcmZvcm1hbmNlLW9wdGltaXphdGlvbicsXG4gICAgbmFtZTogJ1BlcmZvcm1hbmNlIE9wdGltaXphdGlvbicsXG4gICAgZGVzY3JpcHRpb246ICdPcHRpbWl6ZSBzeXN0ZW0gcGVyZm9ybWFuY2UgYmFzZWQgb24gbWV0cmljcycsXG4gICAgY2F0ZWdvcnk6ICdtYWludGVuYW5jZScsXG4gICAgZGVmYXVsdFZhbHVlczoge1xuICAgICAgcHJpb3JpdHk6ICdtZWRpdW0nLFxuICAgICAgaW1wb3J0YW5jZTogNixcbiAgICAgIHVyZ2VuY3k6IDQsXG4gICAgICBlc3RpbWF0ZWRFZmZvcnQ6IDgsXG4gICAgICByaXNrTGV2ZWw6ICdtZWRpdW0nLFxuICAgICAgdGFnczogWydwZXJmb3JtYW5jZScsICdvcHRpbWl6YXRpb24nLCAnbWV0cmljcyddXG4gICAgfSxcbiAgICByZXF1aXJlZEZpZWxkczogWydwZXJmb3JtYW5jZU1ldHJpY3MnLCAndGFyZ2V0SW1wcm92ZW1lbnQnXSxcbiAgICBzdWNjZXNzQ3JpdGVyaWE6IFtcbiAgICAgICdCYXNlbGluZSBtZXRyaWNzIGNhcHR1cmVkJyxcbiAgICAgICdPcHRpbWl6YXRpb25zIGltcGxlbWVudGVkJyxcbiAgICAgICdQZXJmb3JtYW5jZSBpbXByb3ZlZCBieSB0YXJnZXQgJScsXG4gICAgICAnTm8gcmVncmVzc2lvbiBpbiBmdW5jdGlvbmFsaXR5J1xuICAgIF1cbiAgfSxcblxuICAnZG9jdW1lbnRhdGlvbi11cGRhdGUnOiB7XG4gICAgaWQ6ICdkb2N1bWVudGF0aW9uLXVwZGF0ZScsXG4gICAgbmFtZTogJ0RvY3VtZW50YXRpb24gVXBkYXRlJyxcbiAgICBkZXNjcmlwdGlvbjogJ1VwZGF0ZSB0ZWNobmljYWwgb3IgdXNlciBkb2N1bWVudGF0aW9uJyxcbiAgICBjYXRlZ29yeTogJ21haW50ZW5hbmNlJyxcbiAgICBkZWZhdWx0VmFsdWVzOiB7XG4gICAgICBwcmlvcml0eTogJ2xvdycsXG4gICAgICBpbXBvcnRhbmNlOiA1LFxuICAgICAgdXJnZW5jeTogMixcbiAgICAgIGVzdGltYXRlZEVmZm9ydDogMyxcbiAgICAgIHJpc2tMZXZlbDogJ2xvdycsXG4gICAgICB0YWdzOiBbJ2RvY3VtZW50YXRpb24nLCAnbWFpbnRlbmFuY2UnXVxuICAgIH0sXG4gICAgcmVxdWlyZWRGaWVsZHM6IFsnZG9jdW1lbnRUeXBlJywgJ3NlY3Rpb25zJ10sXG4gICAgc3VjY2Vzc0NyaXRlcmlhOiBbXG4gICAgICAnRG9jdW1lbnRhdGlvbiByZXZpZXdlZCcsXG4gICAgICAnVXBkYXRlcyBjb21wbGV0ZWQnLFxuICAgICAgJ1Jldmlld2VkIGJ5IHN0YWtlaG9sZGVycycsXG4gICAgICAnUHVibGlzaGVkIHRvIGFwcHJvcHJpYXRlIGxvY2F0aW9uJ1xuICAgIF1cbiAgfSxcblxuICAncXVhcnRlcmx5LXBsYW5uaW5nJzoge1xuICAgIGlkOiAncXVhcnRlcmx5LXBsYW5uaW5nJyxcbiAgICBuYW1lOiAnUXVhcnRlcmx5IFBsYW5uaW5nJyxcbiAgICBkZXNjcmlwdGlvbjogJ1BsYW4gZ29hbHMgYW5kIHByaW9yaXRpZXMgZm9yIHRoZSBxdWFydGVyJyxcbiAgICBjYXRlZ29yeTogJ3BsYW5uaW5nJyxcbiAgICBkZWZhdWx0VmFsdWVzOiB7XG4gICAgICBwcmlvcml0eTogJ2hpZ2gnLFxuICAgICAgaW1wb3J0YW5jZTogOSxcbiAgICAgIHVyZ2VuY3k6IDcsXG4gICAgICBlc3RpbWF0ZWRFZmZvcnQ6IDEyLFxuICAgICAgcmlza0xldmVsOiAnbG93JyxcbiAgICAgIHRhZ3M6IFsncGxhbm5pbmcnLCAncXVhcnRlcmx5JywgJ3N0cmF0ZWd5J11cbiAgICB9LFxuICAgIHJlcXVpcmVkRmllbGRzOiBbJ3F1YXJ0ZXInLCAnb2JqZWN0aXZlcyddLFxuICAgIHN1Y2Nlc3NDcml0ZXJpYTogW1xuICAgICAgJ0dvYWxzIGRlZmluZWQgYW5kIHByaW9yaXRpemVkJyxcbiAgICAgICdSZXNvdXJjZXMgYWxsb2NhdGVkJyxcbiAgICAgICdUaW1lbGluZSBlc3RhYmxpc2hlZCcsXG4gICAgICAnU3Rha2Vob2xkZXIgYWxpZ25tZW50J1xuICAgIF1cbiAgfSxcblxuICAnY3VzdG9tLWdvYWwnOiB7XG4gICAgaWQ6ICdjdXN0b20tZ29hbCcsXG4gICAgbmFtZTogJ0N1c3RvbSBHb2FsJyxcbiAgICBkZXNjcmlwdGlvbjogJ0NyZWF0ZSBhIGN1c3RvbSBnb2FsIHdpdGggeW91ciBvd24gcGFyYW1ldGVycycsXG4gICAgY2F0ZWdvcnk6ICdjdXN0b20nLFxuICAgIGRlZmF1bHRWYWx1ZXM6IHtcbiAgICAgIHByaW9yaXR5OiAnbWVkaXVtJyxcbiAgICAgIGltcG9ydGFuY2U6IDUsXG4gICAgICB1cmdlbmN5OiA1LFxuICAgICAgcmlza0xldmVsOiAnbWVkaXVtJyxcbiAgICAgIHRhZ3M6IFsnY3VzdG9tJ11cbiAgICB9XG4gIH1cbn07XG5cbi8qKlxuICogQXBwbHkgYSBnb2FsIHRlbXBsYXRlIHRvIGNyZWF0ZSBhIG5ldyBnb2FsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBseUdvYWxUZW1wbGF0ZShcbiAgdGVtcGxhdGVJZDogc3RyaW5nLFxuICBjdXN0b21GaWVsZHM6IFJlY29yZDxzdHJpbmcsIGFueT5cbik6IFBhcnRpYWw8YW55PiB7ICAvLyBSZXR1cm5zIHBhcnRpYWwgQWdlbnRHb2FsXG4gIC8vIFNFQ1VSSVRZIEZJWDogQWRkIGF1ZGl0IGxvZ2dpbmcgZm9yIGdvYWwgdGVtcGxhdGUgdXNhZ2VcbiAgU2VjdXJpdHlNb25pdG9yLmxvZ1NlY3VyaXR5RXZlbnQoe1xuICAgIHR5cGU6ICdHT0FMX1RFTVBMQVRFX0FQUExJRUQnLFxuICAgIHNldmVyaXR5OiAnTE9XJyxcbiAgICBzb3VyY2U6ICdhcHBseUdvYWxUZW1wbGF0ZScsXG4gICAgZGV0YWlsczogYEdvYWwgdGVtcGxhdGUgJyR7dGVtcGxhdGVJZH0nIGFwcGxpZWRgXG4gIH0pO1xuXG4gIGNvbnN0IHRlbXBsYXRlID0gR09BTF9URU1QTEFURVNbdGVtcGxhdGVJZF07XG4gIGlmICghdGVtcGxhdGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEdvYWwgdGVtcGxhdGUgJyR7dGVtcGxhdGVJZH0nIG5vdCBmb3VuZGApO1xuICB9XG5cbiAgLy8gVmFsaWRhdGUgcmVxdWlyZWQgZmllbGRzXG4gIGlmICh0ZW1wbGF0ZS5yZXF1aXJlZEZpZWxkcykge1xuICAgIGZvciAoY29uc3QgZmllbGQgb2YgdGVtcGxhdGUucmVxdWlyZWRGaWVsZHMpIHtcbiAgICAgIGlmICghY3VzdG9tRmllbGRzW2ZpZWxkXSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFJlcXVpcmVkIGZpZWxkICcke2ZpZWxkfScgbWlzc2luZyBmb3IgdGVtcGxhdGUgJyR7dGVtcGxhdGUubmFtZX0nYCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gQ2FsY3VsYXRlIEVpc2VuaG93ZXIgcXVhZHJhbnQgYmFzZWQgb24gdGVtcGxhdGUgZGVmYXVsdHNcbiAgY29uc3QgaW1wb3J0YW5jZSA9IGN1c3RvbUZpZWxkcy5pbXBvcnRhbmNlIHx8IHRlbXBsYXRlLmRlZmF1bHRWYWx1ZXMuaW1wb3J0YW5jZTtcbiAgY29uc3QgdXJnZW5jeSA9IGN1c3RvbUZpZWxkcy51cmdlbmN5IHx8IHRlbXBsYXRlLmRlZmF1bHRWYWx1ZXMudXJnZW5jeTtcbiAgY29uc3QgZWlzZW5ob3dlclF1YWRyYW50ID0gY2FsY3VsYXRlRWlzZW5ob3dlclF1YWRyYW50KGltcG9ydGFuY2UsIHVyZ2VuY3kpO1xuXG4gIC8vIEVuc3VyZSBkZXNjcmlwdGlvbiBpcyBwcm92aWRlZFxuICBjb25zdCBkZXNjcmlwdGlvbiA9IGN1c3RvbUZpZWxkcy5kZXNjcmlwdGlvbiB8fCBcbiAgICBgJHt0ZW1wbGF0ZS5uYW1lfTogJHt0ZW1wbGF0ZS5yZXF1aXJlZEZpZWxkcz8ubWFwKGYgPT4gY3VzdG9tRmllbGRzW2ZdKS5maWx0ZXIoQm9vbGVhbikuam9pbignIC0gJykgfHwgdGVtcGxhdGUuZGVzY3JpcHRpb259YDtcblxuICByZXR1cm4ge1xuICAgIC4uLnRlbXBsYXRlLmRlZmF1bHRWYWx1ZXMsXG4gICAgLi4uY3VzdG9tRmllbGRzLFxuICAgIGRlc2NyaXB0aW9uLFxuICAgIGVpc2VuaG93ZXJRdWFkcmFudCxcbiAgICB0ZW1wbGF0ZUlkLFxuICAgIGNyZWF0ZWRBdDogbmV3IERhdGUoKSxcbiAgICB1cGRhdGVkQXQ6IG5ldyBEYXRlKClcbiAgfTtcbn1cblxuLyoqXG4gKiBDYWxjdWxhdGUgRWlzZW5ob3dlciBxdWFkcmFudCBmcm9tIGltcG9ydGFuY2UgYW5kIHVyZ2VuY3lcbiAqL1xuZnVuY3Rpb24gY2FsY3VsYXRlRWlzZW5ob3dlclF1YWRyYW50KGltcG9ydGFuY2U6IG51bWJlciwgdXJnZW5jeTogbnVtYmVyKTogRWlzZW5ob3dlclF1YWRyYW50IHtcbiAgaWYgKGltcG9ydGFuY2UgPj0gNyAmJiB1cmdlbmN5ID49IDcpIHJldHVybiAnZG9fZmlyc3QnO1xuICBpZiAoaW1wb3J0YW5jZSA+PSA3ICYmIHVyZ2VuY3kgPCA3KSByZXR1cm4gJ3NjaGVkdWxlJztcbiAgaWYgKGltcG9ydGFuY2UgPCA3ICYmIHVyZ2VuY3kgPj0gNykgcmV0dXJuICdkZWxlZ2F0ZSc7XG4gIHJldHVybiAnZWxpbWluYXRlJztcbn1cblxuLyoqXG4gKiBHZXQgdGVtcGxhdGUgcmVjb21tZW5kYXRpb25zIGJhc2VkIG9uIGdvYWwgZGVzY3JpcHRpb25cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlY29tbWVuZEdvYWxUZW1wbGF0ZShkZXNjcmlwdGlvbjogc3RyaW5nKTogc3RyaW5nW10ge1xuICBjb25zdCBsb3dlcmNhc2VEZXNjID0gZGVzY3JpcHRpb24udG9Mb3dlckNhc2UoKTtcbiAgY29uc3QgcmVjb21tZW5kYXRpb25zOiBzdHJpbmdbXSA9IFtdO1xuXG4gIC8vIEtleXdvcmRzIG1hcHBpbmcgdG8gdGVtcGxhdGVzXG4gIGNvbnN0IGtleXdvcmRNYXA6IFJlY29yZDxzdHJpbmcsIHN0cmluZ1tdPiA9IHtcbiAgICAnZmVhdHVyZS1pbXBsZW1lbnRhdGlvbic6IFsnZmVhdHVyZScsICdpbXBsZW1lbnQnLCAnZGV2ZWxvcCcsICdidWlsZCddLFxuICAgICdidWctZml4LWNyaXRpY2FsJzogWydidWcnLCAnZml4JywgJ2NyaXRpY2FsJywgJ3VyZ2VudCcsICdicm9rZW4nLCAnZXJyb3InXSxcbiAgICAncmVzZWFyY2gtc3Bpa2UnOiBbJ3Jlc2VhcmNoJywgJ2V4cGxvcmUnLCAnaW52ZXN0aWdhdGUnLCAnc3Bpa2UnLCAnZXZhbHVhdGUnXSxcbiAgICAnc2VjdXJpdHktYXVkaXQnOiBbJ3NlY3VyaXR5JywgJ2F1ZGl0JywgJ3Z1bG5lcmFiaWxpdHknLCAnY29tcGxpYW5jZSddLFxuICAgICdwZXJmb3JtYW5jZS1vcHRpbWl6YXRpb24nOiBbJ3BlcmZvcm1hbmNlJywgJ29wdGltaXplJywgJ3NwZWVkJywgJ3Nsb3cnLCAnbGF0ZW5jeSddLFxuICAgICdkb2N1bWVudGF0aW9uLXVwZGF0ZSc6IFsnZG9jdW1lbnQnLCAnZG9jcycsICdyZWFkbWUnLCAnZ3VpZGUnLCAnbWFudWFsJ10sXG4gICAgJ3F1YXJ0ZXJseS1wbGFubmluZyc6IFsncGxhbicsICdxdWFydGVyJywgJ3JvYWRtYXAnLCAnc3RyYXRlZ3knXVxuICB9O1xuXG4gIC8vIENoZWNrIGZvciBrZXl3b3JkIG1hdGNoZXNcbiAgZm9yIChjb25zdCBbdGVtcGxhdGVJZCwga2V5d29yZHNdIG9mIE9iamVjdC5lbnRyaWVzKGtleXdvcmRNYXApKSB7XG4gICAgaWYgKGtleXdvcmRzLnNvbWUoa2V5d29yZCA9PiBsb3dlcmNhc2VEZXNjLmluY2x1ZGVzKGtleXdvcmQpKSkge1xuICAgICAgcmVjb21tZW5kYXRpb25zLnB1c2godGVtcGxhdGVJZCk7XG4gICAgfVxuICB9XG5cbiAgLy8gQWx3YXlzIGluY2x1ZGUgY3VzdG9tIGFzIGFuIG9wdGlvblxuICBpZiAocmVjb21tZW5kYXRpb25zLmxlbmd0aCA9PT0gMCkge1xuICAgIHJlY29tbWVuZGF0aW9ucy5wdXNoKCdjdXN0b20tZ29hbCcpO1xuICB9XG5cbiAgcmV0dXJuIHJlY29tbWVuZGF0aW9ucztcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZSBnb2FsIGFnYWluc3QgaXRzIHRlbXBsYXRlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZUdvYWxBZ2FpbnN0VGVtcGxhdGUoXG4gIGdvYWw6IGFueSwgIC8vIEFnZW50R29hbCB0eXBlXG4gIHRlbXBsYXRlSWQ/OiBzdHJpbmdcbik6IHsgdmFsaWQ6IGJvb2xlYW47IGVycm9yczogc3RyaW5nW10gfSB7XG4gIGlmICghdGVtcGxhdGVJZCB8fCAhR09BTF9URU1QTEFURVNbdGVtcGxhdGVJZF0pIHtcbiAgICByZXR1cm4geyB2YWxpZDogdHJ1ZSwgZXJyb3JzOiBbXSB9O1xuICB9XG5cbiAgLy8gU0VDVVJJVFkgRklYOiBBZGQgYXVkaXQgbG9nZ2luZyBmb3IgdGVtcGxhdGUgdmFsaWRhdGlvblxuICBTZWN1cml0eU1vbml0b3IubG9nU2VjdXJpdHlFdmVudCh7XG4gICAgdHlwZTogJ0dPQUxfVEVNUExBVEVfVkFMSURBVElPTicsXG4gICAgc2V2ZXJpdHk6ICdMT1cnLFxuICAgIHNvdXJjZTogJ3ZhbGlkYXRlR29hbEFnYWluc3RUZW1wbGF0ZScsXG4gICAgZGV0YWlsczogYFZhbGlkYXRpbmcgZ29hbCBhZ2FpbnN0IHRlbXBsYXRlICcke3RlbXBsYXRlSWR9J2BcbiAgfSk7XG5cbiAgY29uc3QgdGVtcGxhdGUgPSBHT0FMX1RFTVBMQVRFU1t0ZW1wbGF0ZUlkXTtcbiAgY29uc3QgZXJyb3JzOiBzdHJpbmdbXSA9IFtdO1xuXG4gIC8vIENoZWNrIHJlcXVpcmVkIGZpZWxkc1xuICBpZiAodGVtcGxhdGUucmVxdWlyZWRGaWVsZHMpIHtcbiAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIHRlbXBsYXRlLnJlcXVpcmVkRmllbGRzKSB7XG4gICAgICBpZiAoIWdvYWxbZmllbGRdKSB7XG4gICAgICAgIGVycm9ycy5wdXNoKGBNaXNzaW5nIHJlcXVpcmVkIGZpZWxkOiAke2ZpZWxkfWApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIFZhbGlkYXRlIHJpc2sgbGV2ZWwgbWF0Y2hlcyB0ZW1wbGF0ZSBjYXRlZ29yeVxuICBpZiAodGVtcGxhdGUuY2F0ZWdvcnkgPT09ICdvcGVyYXRpb25zJyAmJiBnb2FsLnJpc2tMZXZlbCA9PT0gJ2hpZ2gnKSB7XG4gICAgZXJyb3JzLnB1c2goJ0hpZ2ggcmlzayBvcGVyYXRpb25zIGdvYWxzIHJlcXVpcmUgYWRkaXRpb25hbCBhcHByb3ZhbCcpO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICB2YWxpZDogZXJyb3JzLmxlbmd0aCA9PT0gMCxcbiAgICBlcnJvcnNcbiAgfTtcbn0iXX0=