@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.
212 lines • 28.6 kB
JavaScript
/**
* GatheredData — Read-side aggregation over agent execution state.
*
* Provides structured views of agent execution data by querying existing
* decision history and goal state. This is NOT a new write pipeline —
* it aggregates data that's already captured by the agent state system
* and decision recording.
*
* Part of the Agentic Loop Completion (Epic #380, Issue #68).
*
* @since v2.0.0
*/
// =============================================================================
// Aggregation
// =============================================================================
/**
* Build gathered data for a specific goalId from agent state.
*
* Queries the agent's decision history and goal state to produce
* a chronological timeline of events. This is a read-side view —
* the underlying data was already recorded by recordDecision() and
* goal lifecycle methods.
*
* @param agentName - Name of the agent
* @param goalId - Goal ID to gather data for
* @param state - Agent's current state (from Agent.getState())
* @returns GatheredData aggregation, or null if goal not found
*/
export function getGatheredData(agentName, goalId, state) {
// Find the target goal
const goal = state.goals.find(g => g.id === goalId);
if (!goal) {
return null;
}
// Filter decisions for this goal
const goalDecisions = state.decisions.filter(d => d.goalId === goalId);
// Build the chronological timeline
const entries = [];
// 1. Goal creation event
entries.push(buildGoalCreatedEntry(goal));
// 2. Decision entries (chronological)
for (const decision of goalDecisions) {
entries.push(buildDecisionEntry(decision, goalId));
// If the decision has findings in the reasoning, add a finding entry
if (decision.reasoning && decision.reasoning.length > 0) {
entries.push(buildFindingEntry(decision, goalId));
}
}
// 3. Goal completion event (if completed or failed)
if (goal.status === 'completed') {
entries.push(buildGoalCompletedEntry(goal));
}
else if (goal.status === 'failed') {
entries.push(buildGoalFailedEntry(goal));
}
// Sort by timestamp (chronological)
entries.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
// Compute summary statistics
const summary = computeSummary(goalDecisions, goal);
return {
goalId,
agentName,
gatheredAt: new Date().toISOString(),
entries,
summary,
goal: {
description: goal.description,
status: goal.status,
createdAt: goal.createdAt instanceof Date
? goal.createdAt.toISOString()
: String(goal.createdAt),
completedAt: goal.completedAt instanceof Date
? goal.completedAt.toISOString()
: goal.completedAt ? String(goal.completedAt) : undefined,
},
};
}
// =============================================================================
// Entry Builders
// =============================================================================
function buildGoalCreatedEntry(goal) {
const timestamp = goal.createdAt instanceof Date
? goal.createdAt.toISOString()
: String(goal.createdAt);
return {
type: 'goal_created',
timestamp,
source: 'AgentManager.executeAgent',
goalId: goal.id,
content: {
summary: `Goal created: ${goal.description.substring(0, 100)}`,
details: {
priority: goal.priority,
importance: goal.importance,
urgency: goal.urgency,
},
},
};
}
function buildDecisionEntry(decision, goalId) {
const timestamp = decision.timestamp instanceof Date
? decision.timestamp.toISOString()
: String(decision.timestamp);
return {
type: 'decision',
timestamp,
source: 'Agent.recordDecision',
goalId,
content: {
summary: decision.decision,
details: {
confidence: decision.confidence,
outcome: decision.outcome,
framework: decision.framework,
riskLevel: decision.riskAssessment?.level,
},
},
};
}
function buildFindingEntry(decision, goalId) {
const timestamp = decision.timestamp instanceof Date
? decision.timestamp.toISOString()
: String(decision.timestamp);
return {
type: 'finding',
timestamp,
source: 'Agent.recordDecision',
goalId,
content: {
summary: decision.reasoning.substring(0, 200),
details: {
fullReasoning: decision.reasoning,
decisionId: decision.id,
},
},
};
}
function buildGoalCompletedEntry(goal) {
const timestamp = goal.completedAt instanceof Date
? goal.completedAt.toISOString()
: goal.completedAt ? String(goal.completedAt) : new Date().toISOString();
return {
type: 'goal_completed',
timestamp,
source: 'AgentManager.completeAgentGoal',
goalId: goal.id,
content: {
summary: `Goal completed: ${goal.description.substring(0, 100)}`,
details: {
actualEffort: goal.actualEffort,
estimatedEffort: goal.estimatedEffort,
},
},
};
}
function buildGoalFailedEntry(goal) {
const timestamp = goal.completedAt instanceof Date
? goal.completedAt.toISOString()
: goal.completedAt ? String(goal.completedAt) : new Date().toISOString();
return {
type: 'goal_failed',
timestamp,
source: 'AgentManager.completeAgentGoal',
goalId: goal.id,
content: {
summary: `Goal failed: ${goal.description.substring(0, 100)}`,
details: {
notes: goal.notes,
},
},
};
}
// =============================================================================
// Summary Statistics
// =============================================================================
function computeSummary(decisions, goal) {
const successfulSteps = decisions.filter(d => d.outcome === 'success').length;
const failedSteps = decisions.filter(d => d.outcome === 'failure').length;
const partialSteps = decisions.filter(d => d.outcome === 'partial').length;
const confidences = decisions.map(d => d.confidence).filter(c => typeof c === 'number');
const averageConfidence = confidences.length > 0
? confidences.reduce((sum, c) => sum + c, 0) / confidences.length
: 0;
// Duration from goal creation to last decision or completion
const createdAt = goal.createdAt instanceof Date
? goal.createdAt.getTime()
: new Date(String(goal.createdAt)).getTime();
let endTime;
if (goal.completedAt) {
endTime = goal.completedAt instanceof Date
? goal.completedAt.getTime()
: new Date(String(goal.completedAt)).getTime();
}
else if (decisions.length > 0) {
const lastDecision = decisions[decisions.length - 1];
endTime = lastDecision.timestamp instanceof Date
? lastDecision.timestamp.getTime()
: new Date(String(lastDecision.timestamp)).getTime();
}
else {
endTime = Date.now();
}
return {
totalSteps: decisions.length,
successfulSteps,
failedSteps,
partialSteps,
averageConfidence: parseFloat(averageConfidence.toFixed(3)),
durationMs: Math.max(0, endTime - createdAt),
};
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2F0aGVyZWREYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2VsZW1lbnRzL2FnZW50cy9nYXRoZXJlZERhdGEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7O0dBV0c7QUE2REgsZ0ZBQWdGO0FBQ2hGLGNBQWM7QUFDZCxnRkFBZ0Y7QUFFaEY7Ozs7Ozs7Ozs7OztHQVlHO0FBQ0gsTUFBTSxVQUFVLGVBQWUsQ0FDN0IsU0FBaUIsRUFDakIsTUFBYyxFQUNkLEtBQTJCO0lBRTNCLHVCQUF1QjtJQUN2QixNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssTUFBTSxDQUFDLENBQUM7SUFDcEQsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ1YsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsaUNBQWlDO0lBQ2pDLE1BQU0sYUFBYSxHQUFHLEtBQUssQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sS0FBSyxNQUFNLENBQUMsQ0FBQztJQUV2RSxtQ0FBbUM7SUFDbkMsTUFBTSxPQUFPLEdBQXdCLEVBQUUsQ0FBQztJQUV4Qyx5QkFBeUI7SUFDekIsT0FBTyxDQUFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBRTFDLHNDQUFzQztJQUN0QyxLQUFLLE1BQU0sUUFBUSxJQUFJLGFBQWEsRUFBRSxDQUFDO1FBQ3JDLE9BQU8sQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFFbkQscUVBQXFFO1FBQ3JFLElBQUksUUFBUSxDQUFDLFNBQVMsSUFBSSxRQUFRLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN4RCxP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SSxPQUFlLENBQUM7SUFDcEIsSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDckIsT0FBTyxHQUFHLElBQUksQ0FBQyxXQUFXLFlBQVksSUFBSTtZQUN4QyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUU7WUFDNUIsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNuRCxDQUFDO1NBQU0sSUFBSSxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ2hDLE1BQU0sWUFBWSxHQUFHLFNBQVMsQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3JELE9BQU8sR0FBRyxZQUFZLENBQUMsU0FBUyxZQUFZLElBQUk7WUFDOUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFO1lBQ2xDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDekQsQ0FBQztTQUFNLENBQUM7UUFDTixPQUFPLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQ3ZCLENBQUM7SUFFRCxPQUFPO1FBQ0wsVUFBVSxFQUFFLFNBQVMsQ0FBQyxNQUFNO1FBQzVCLGVBQWU7UUFDZixXQUFXO1FBQ1gsWUFBWTtRQUNaLGlCQUFpQixFQUFFLFVBQVUsQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0QsVUFBVSxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLE9BQU8sR0FBRyxTQUFTLENBQUM7S0FDN0MsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEdhdGhlcmVkRGF0YSDigJQgUmVhZC1zaWRlIGFnZ3JlZ2F0aW9uIG92ZXIgYWdlbnQgZXhlY3V0aW9uIHN0YXRlLlxuICpcbiAqIFByb3ZpZGVzIHN0cnVjdHVyZWQgdmlld3Mgb2YgYWdlbnQgZXhlY3V0aW9uIGRhdGEgYnkgcXVlcnlpbmcgZXhpc3RpbmdcbiAqIGRlY2lzaW9uIGhpc3RvcnkgYW5kIGdvYWwgc3RhdGUuIFRoaXMgaXMgTk9UIGEgbmV3IHdyaXRlIHBpcGVsaW5lIOKAlFxuICogaXQgYWdncmVnYXRlcyBkYXRhIHRoYXQncyBhbHJlYWR5IGNhcHR1cmVkIGJ5IHRoZSBhZ2VudCBzdGF0ZSBzeXN0ZW1cbiAqIGFuZCBkZWNpc2lvbiByZWNvcmRpbmcuXG4gKlxuICogUGFydCBvZiB0aGUgQWdlbnRpYyBMb29wIENvbXBsZXRpb24gKEVwaWMgIzM4MCwgSXNzdWUgIzY4KS5cbiAqXG4gKiBAc2luY2UgdjIuMC4wXG4gKi9cblxuaW1wb3J0IHR5cGUgeyBBZ2VudFN0YXRlLCBBZ2VudEdvYWwsIEFnZW50RGVjaXNpb24gfSBmcm9tICcuL3R5cGVzLmpzJztcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFR5cGVzXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIEEgc2luZ2xlIGVudHJ5IGluIHRoZSBnYXRoZXJlZCBkYXRhIHRpbWVsaW5lLlxuICogUmVwcmVzZW50cyBhIGRpc2NyZXRlIGV2ZW50IGR1cmluZyBhZ2VudCBleGVjdXRpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR2F0aGVyZWREYXRhRW50cnkge1xuICAvKiogRW50cnkgdHlwZSBmb3IgZmlsdGVyaW5nIGFuZCBwcmVzZW50YXRpb24gKi9cbiAgdHlwZTogJ2RlY2lzaW9uJyB8ICdnb2FsX2NyZWF0ZWQnIHwgJ2dvYWxfY29tcGxldGVkJyB8ICdnb2FsX2ZhaWxlZCcgfCAnZmluZGluZycgfCAnbWV0cmljJztcbiAgLyoqIElTTyA4NjAxIHRpbWVzdGFtcCBvZiB3aGVuIHRoaXMgZW50cnkgb2NjdXJyZWQgKi9cbiAgdGltZXN0YW1wOiBzdHJpbmc7XG4gIC8qKiBDb21wb25lbnQgb3Igc3Vic3lzdGVtIHRoYXQgZ2VuZXJhdGVkIHRoaXMgZW50cnkgKi9cbiAgc291cmNlOiBzdHJpbmc7XG4gIC8qKiBHb2FsIElEIHRoaXMgZW50cnkgcmVsYXRlcyB0byAqL1xuICBnb2FsSWQ6IHN0cmluZztcbiAgLyoqIFN0cnVjdHVyZWQgY29udGVudCAqL1xuICBjb250ZW50OiB7XG4gICAgLyoqIEh1bWFuLXJlYWRhYmxlIHN1bW1hcnkgb2YgdGhlIGVudHJ5ICovXG4gICAgc3VtbWFyeTogc3RyaW5nO1xuICAgIC8qKiBBZGRpdGlvbmFsIHN0cnVjdHVyZWQgZGV0YWlscyAqL1xuICAgIGRldGFpbHM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgfTtcbn1cblxuLyoqXG4gKiBBZ2dyZWdhdGVkIGdhdGhlcmVkIGRhdGEgZm9yIGEgc3BlY2lmaWMgZ29hbCBleGVjdXRpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR2F0aGVyZWREYXRhIHtcbiAgLyoqIEdvYWwgSUQgdGhlIGRhdGEgd2FzIGdhdGhlcmVkIGZvciAqL1xuICBnb2FsSWQ6IHN0cmluZztcbiAgLyoqIEFnZW50IG5hbWUgKi9cbiAgYWdlbnROYW1lOiBzdHJpbmc7XG4gIC8qKiBJU08gODYwMSB0aW1lc3RhbXAgd2hlbiB0aGlzIGRhdGEgd2FzIGdhdGhlcmVkICovXG4gIGdhdGhlcmVkQXQ6IHN0cmluZztcbiAgLyoqIFRpbWVsaW5lIG9mIGV2ZW50cyBpbiBjaHJvbm9sb2dpY2FsIG9yZGVyICovXG4gIGVudHJpZXM6IEdhdGhlcmVkRGF0YUVudHJ5W107XG4gIC8qKiBTdW1tYXJ5IHN0YXRpc3RpY3MgKi9cbiAgc3VtbWFyeToge1xuICAgIHRvdGFsU3RlcHM6IG51bWJlcjtcbiAgICBzdWNjZXNzZnVsU3RlcHM6IG51bWJlcjtcbiAgICBmYWlsZWRTdGVwczogbnVtYmVyO1xuICAgIHBhcnRpYWxTdGVwczogbnVtYmVyO1xuICAgIGF2ZXJhZ2VDb25maWRlbmNlOiBudW1iZXI7XG4gICAgLyoqIER1cmF0aW9uIGZyb20gZ29hbCBjcmVhdGlvbiB0byBsYXN0IGRlY2lzaW9uIChvciBub3cpICovXG4gICAgZHVyYXRpb25NczogbnVtYmVyO1xuICB9O1xuICAvKiogR29hbCBtZXRhZGF0YSBzbmFwc2hvdCAqL1xuICBnb2FsOiB7XG4gICAgZGVzY3JpcHRpb246IHN0cmluZztcbiAgICBzdGF0dXM6IHN0cmluZztcbiAgICBjcmVhdGVkQXQ6IHN0cmluZztcbiAgICBjb21wbGV0ZWRBdD86IHN0cmluZztcbiAgfTtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEFnZ3JlZ2F0aW9uXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIEJ1aWxkIGdhdGhlcmVkIGRhdGEgZm9yIGEgc3BlY2lmaWMgZ29hbElkIGZyb20gYWdlbnQgc3RhdGUuXG4gKlxuICogUXVlcmllcyB0aGUgYWdlbnQncyBkZWNpc2lvbiBoaXN0b3J5IGFuZCBnb2FsIHN0YXRlIHRvIHByb2R1Y2VcbiAqIGEgY2hyb25vbG9naWNhbCB0aW1lbGluZSBvZiBldmVudHMuIFRoaXMgaXMgYSByZWFkLXNpZGUgdmlldyDigJRcbiAqIHRoZSB1bmRlcmx5aW5nIGRhdGEgd2FzIGFscmVhZHkgcmVjb3JkZWQgYnkgcmVjb3JkRGVjaXNpb24oKSBhbmRcbiAqIGdvYWwgbGlmZWN5Y2xlIG1ldGhvZHMuXG4gKlxuICogQHBhcmFtIGFnZW50TmFtZSAtIE5hbWUgb2YgdGhlIGFnZW50XG4gKiBAcGFyYW0gZ29hbElkIC0gR29hbCBJRCB0byBnYXRoZXIgZGF0YSBmb3JcbiAqIEBwYXJhbSBzdGF0ZSAtIEFnZW50J3MgY3VycmVudCBzdGF0ZSAoZnJvbSBBZ2VudC5nZXRTdGF0ZSgpKVxuICogQHJldHVybnMgR2F0aGVyZWREYXRhIGFnZ3JlZ2F0aW9uLCBvciBudWxsIGlmIGdvYWwgbm90IGZvdW5kXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRHYXRoZXJlZERhdGEoXG4gIGFnZW50TmFtZTogc3RyaW5nLFxuICBnb2FsSWQ6IHN0cmluZyxcbiAgc3RhdGU6IFJlYWRvbmx5PEFnZW50U3RhdGU+XG4pOiBHYXRoZXJlZERhdGEgfCBudWxsIHtcbiAgLy8gRmluZCB0aGUgdGFyZ2V0IGdvYWxcbiAgY29uc3QgZ29hbCA9IHN0YXRlLmdvYWxzLmZpbmQoZyA9PiBnLmlkID09PSBnb2FsSWQpO1xuICBpZiAoIWdvYWwpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIC8vIEZpbHRlciBkZWNpc2lvbnMgZm9yIHRoaXMgZ29hbFxuICBjb25zdCBnb2FsRGVjaXNpb25zID0gc3RhdGUuZGVjaXNpb25zLmZpbHRlcihkID0+IGQuZ29hbElkID09PSBnb2FsSWQpO1xuXG4gIC8vIEJ1aWxkIHRoZSBjaHJvbm9sb2dpY2FsIHRpbWVsaW5lXG4gIGNvbnN0IGVudHJpZXM6IEdhdGhlcmVkRGF0YUVudHJ5W10gPSBbXTtcblxuICAvLyAxLiBHb2FsIGNyZWF0aW9uIGV2ZW50XG4gIGVudHJpZXMucHVzaChidWlsZEdvYWxDcmVhdGVkRW50cnkoZ29hbCkpO1xuXG4gIC8vIDIuIERlY2lzaW9uIGVudHJpZXMgKGNocm9ub2xvZ2ljYWwpXG4gIGZvciAoY29uc3QgZGVjaXNpb24gb2YgZ29hbERlY2lzaW9ucykge1xuICAgIGVudHJpZXMucHVzaChidWlsZERlY2lzaW9uRW50cnkoZGVjaXNpb24sIGdvYWxJZCkpO1xuXG4gICAgLy8gSWYgdGhlIGRlY2lzaW9uIGhhcyBmaW5kaW5ncyBpbiB0aGUgcmVhc29uaW5nLCBhZGQgYSBmaW5kaW5nIGVudHJ5XG4gICAgaWYgKGRlY2lzaW9uLnJlYXNvbmluZyAmJiBkZWNpc2lvbi5yZWFzb25pbmcubGVuZ3RoID4gMCkge1xuICAgICAgZW50cmllcy5wdXNoKGJ1aWxkRmluZGluZ0VudHJ5KGRlY2lzaW9uLCBnb2FsSWQpKTtcbiAgICB9XG4gIH1cblxuICAvLyAzLiBHb2FsIGNvbXBsZXRpb24gZXZlbnQgKGlmIGNvbXBsZXRlZCBvciBmYWlsZWQpXG4gIGlmIChnb2FsLnN0YXR1cyA9PT0gJ2NvbXBsZXRlZCcpIHtcbiAgICBlbnRyaWVzLnB1c2goYnVpbGRHb2FsQ29tcGxldGVkRW50cnkoZ29hbCkpO1xuICB9IGVsc2UgaWYgKGdvYWwuc3RhdHVzID09PSAnZmFpbGVkJykge1xuICAgIGVudHJpZXMucHVzaChidWlsZEdvYWxGYWlsZWRFbnRyeShnb2FsKSk7XG4gIH1cblxuICAvLyBTb3J0IGJ5IHRpbWVzdGFtcCAoY2hyb25vbG9naWNhbClcbiAgZW50cmllcy5zb3J0KChhLCBiKSA9PiBhLnRpbWVzdGFtcC5sb2NhbGVDb21wYXJlKGIudGltZXN0YW1wKSk7XG5cbiAgLy8gQ29tcHV0ZSBzdW1tYXJ5IHN0YXRpc3RpY3NcbiAgY29uc3Qgc3VtbWFyeSA9IGNvbXB1dGVTdW1tYXJ5KGdvYWxEZWNpc2lvbnMsIGdvYWwpO1xuXG4gIHJldHVybiB7XG4gICAgZ29hbElkLFxuICAgIGFnZW50TmFtZSxcbiAgICBnYXRoZXJlZEF0OiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgZW50cmllcyxcbiAgICBzdW1tYXJ5LFxuICAgIGdvYWw6IHtcbiAgICAgIGRlc2NyaXB0aW9uOiBnb2FsLmRlc2NyaXB0aW9uLFxuICAgICAgc3RhdHVzOiBnb2FsLnN0YXR1cyxcbiAgICAgIGNyZWF0ZWRBdDogZ29hbC5jcmVhdGVkQXQgaW5zdGFuY2VvZiBEYXRlXG4gICAgICAgID8gZ29hbC5jcmVhdGVkQXQudG9JU09TdHJpbmcoKVxuICAgICAgICA6IFN0cmluZyhnb2FsLmNyZWF0ZWRBdCksXG4gICAgICBjb21wbGV0ZWRBdDogZ29hbC5jb21wbGV0ZWRBdCBpbnN0YW5jZW9mIERhdGVcbiAgICAgICAgPyBnb2FsLmNvbXBsZXRlZEF0LnRvSVNPU3RyaW5nKClcbiAgICAgICAgOiBnb2FsLmNvbXBsZXRlZEF0ID8gU3RyaW5nKGdvYWwuY29tcGxldGVkQXQpIDogdW5kZWZpbmVkLFxuICAgIH0sXG4gIH07XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBFbnRyeSBCdWlsZGVyc1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZnVuY3Rpb24gYnVpbGRHb2FsQ3JlYXRlZEVudHJ5KGdvYWw6IEFnZW50R29hbCk6IEdhdGhlcmVkRGF0YUVudHJ5IHtcbiAgY29uc3QgdGltZXN0YW1wID0gZ29hbC5jcmVhdGVkQXQgaW5zdGFuY2VvZiBEYXRlXG4gICAgPyBnb2FsLmNyZWF0ZWRBdC50b0lTT1N0cmluZygpXG4gICAgOiBTdHJpbmcoZ29hbC5jcmVhdGVkQXQpO1xuXG4gIHJldHVybiB7XG4gICAgdHlwZTogJ2dvYWxfY3JlYXRlZCcsXG4gICAgdGltZXN0YW1wLFxuICAgIHNvdXJjZTogJ0FnZW50TWFuYWdlci5leGVjdXRlQWdlbnQnLFxuICAgIGdvYWxJZDogZ29hbC5pZCxcbiAgICBjb250ZW50OiB7XG4gICAgICBzdW1tYXJ5OiBgR29hbCBjcmVhdGVkOiAke2dvYWwuZGVzY3JpcHRpb24uc3Vic3RyaW5nKDAsIDEwMCl9YCxcbiAgICAgIGRldGFpbHM6IHtcbiAgICAgICAgcHJpb3JpdHk6IGdvYWwucHJpb3JpdHksXG4gICAgICAgIGltcG9ydGFuY2U6IGdvYWwuaW1wb3J0YW5jZSxcbiAgICAgICAgdXJnZW5jeTogZ29hbC51cmdlbmN5LFxuICAgICAgfSxcbiAgICB9LFxuICB9O1xufVxuXG5mdW5jdGlvbiBidWlsZERlY2lzaW9uRW50cnkoZGVjaXNpb246IEFnZW50RGVjaXNpb24sIGdvYWxJZDogc3RyaW5nKTogR2F0aGVyZWREYXRhRW50cnkge1xuICBjb25zdCB0aW1lc3RhbXAgPSBkZWNpc2lvbi50aW1lc3RhbXAgaW5zdGFuY2VvZiBEYXRlXG4gICAgPyBkZWNpc2lvbi50aW1lc3RhbXAudG9JU09TdHJpbmcoKVxuICAgIDogU3RyaW5nKGRlY2lzaW9uLnRpbWVzdGFtcCk7XG5cbiAgcmV0dXJuIHtcbiAgICB0eXBlOiAnZGVjaXNpb24nLFxuICAgIHRpbWVzdGFtcCxcbiAgICBzb3VyY2U6ICdBZ2VudC5yZWNvcmREZWNpc2lvbicsXG4gICAgZ29hbElkLFxuICAgIGNvbnRlbnQ6IHtcbiAgICAgIHN1bW1hcnk6IGRlY2lzaW9uLmRlY2lzaW9uLFxuICAgICAgZGV0YWlsczoge1xuICAgICAgICBjb25maWRlbmNlOiBkZWNpc2lvbi5jb25maWRlbmNlLFxuICAgICAgICBvdXRjb21lOiBkZWNpc2lvbi5vdXRjb21lLFxuICAgICAgICBmcmFtZXdvcms6IGRlY2lzaW9uLmZyYW1ld29yayxcbiAgICAgICAgcmlza0xldmVsOiBkZWNpc2lvbi5yaXNrQXNzZXNzbWVudD8ubGV2ZWwsXG4gICAgICB9LFxuICAgIH0sXG4gIH07XG59XG5cbmZ1bmN0aW9uIGJ1aWxkRmluZGluZ0VudHJ5KGRlY2lzaW9uOiBBZ2VudERlY2lzaW9uLCBnb2FsSWQ6IHN0cmluZyk6IEdhdGhlcmVkRGF0YUVudHJ5IHtcbiAgY29uc3QgdGltZXN0YW1wID0gZGVjaXNpb24udGltZXN0YW1wIGluc3RhbmNlb2YgRGF0ZVxuICAgID8gZGVjaXNpb24udGltZXN0YW1wLnRvSVNPU3RyaW5nKClcbiAgICA6IFN0cmluZyhkZWNpc2lvbi50aW1lc3RhbXApO1xuXG4gIHJldHVybiB7XG4gICAgdHlwZTogJ2ZpbmRpbmcnLFxuICAgIHRpbWVzdGFtcCxcbiAgICBzb3VyY2U6ICdBZ2VudC5yZWNvcmREZWNpc2lvbicsXG4gICAgZ29hbElkLFxuICAgIGNvbnRlbnQ6IHtcbiAgICAgIHN1bW1hcnk6IGRlY2lzaW9uLnJlYXNvbmluZy5zdWJzdHJpbmcoMCwgMjAwKSxcbiAgICAgIGRldGFpbHM6IHtcbiAgICAgICAgZnVsbFJlYXNvbmluZzogZGVjaXNpb24ucmVhc29uaW5nLFxuICAgICAgICBkZWNpc2lvbklkOiBkZWNpc2lvbi5pZCxcbiAgICAgIH0sXG4gICAgfSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gYnVpbGRHb2FsQ29tcGxldGVkRW50cnkoZ29hbDogQWdlbnRHb2FsKTogR2F0aGVyZWREYXRhRW50cnkge1xuICBjb25zdCB0aW1lc3RhbXAgPSBnb2FsLmNvbXBsZXRlZEF0IGluc3RhbmNlb2YgRGF0ZVxuICAgID8gZ29hbC5jb21wbGV0ZWRBdC50b0lTT1N0cmluZygpXG4gICAgOiBnb2FsLmNvbXBsZXRlZEF0ID8gU3RyaW5nKGdvYWwuY29tcGxldGVkQXQpIDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpO1xuXG4gIHJldHVybiB7XG4gICAgdHlwZTogJ2dvYWxfY29tcGxldGVkJyxcbiAgICB0aW1lc3RhbXAsXG4gICAgc291cmNlOiAnQWdlbnRNYW5hZ2VyLmNvbXBsZXRlQWdlbnRHb2FsJyxcbiAgICBnb2FsSWQ6IGdvYWwuaWQsXG4gICAgY29udGVudDoge1xuICAgICAgc3VtbWFyeTogYEdvYWwgY29tcGxldGVkOiAke2dvYWwuZGVzY3JpcHRpb24uc3Vic3RyaW5nKDAsIDEwMCl9YCxcbiAgICAgIGRldGFpbHM6IHtcbiAgICAgICAgYWN0dWFsRWZmb3J0OiBnb2FsLmFjdHVhbEVmZm9ydCxcbiAgICAgICAgZXN0aW1hdGVkRWZmb3J0OiBnb2FsLmVzdGltYXRlZEVmZm9ydCxcbiAgICAgIH0sXG4gICAgfSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gYnVpbGRHb2FsRmFpbGVkRW50cnkoZ29hbDogQWdlbnRHb2FsKTogR2F0aGVyZWREYXRhRW50cnkge1xuICBjb25zdCB0aW1lc3RhbXAgPSBnb2FsLmNvbXBsZXRlZEF0IGluc3RhbmNlb2YgRGF0ZVxuICAgID8gZ29hbC5jb21wbGV0ZWRBdC50b0lTT1N0cmluZygpXG4gICAgOiBnb2FsLmNvbXBsZXRlZEF0ID8gU3RyaW5nKGdvYWwuY29tcGxldGVkQXQpIDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpO1xuXG4gIHJldHVybiB7XG4gICAgdHlwZTogJ2dvYWxfZmFpbGVkJyxcbiAgICB0aW1lc3RhbXAsXG4gICAgc291cmNlOiAnQWdlbnRNYW5hZ2VyLmNvbXBsZXRlQWdlbnRHb2FsJyxcbiAgICBnb2FsSWQ6IGdvYWwuaWQsXG4gICAgY29udGVudDoge1xuICAgICAgc3VtbWFyeTogYEdvYWwgZmFpbGVkOiAke2dvYWwuZGVzY3JpcHRpb24uc3Vic3RyaW5nKDAsIDEwMCl9YCxcbiAgICAgIGRldGFpbHM6IHtcbiAgICAgICAgbm90ZXM6IGdvYWwubm90ZXMsXG4gICAgICB9LFxuICAgIH0sXG4gIH07XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBTdW1tYXJ5IFN0YXRpc3RpY3Ncbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmZ1bmN0aW9uIGNvbXB1dGVTdW1tYXJ5KFxuICBkZWNpc2lvbnM6IEFnZW50RGVjaXNpb25bXSxcbiAgZ29hbDogQWdlbnRHb2FsXG4pOiBHYXRoZXJlZERhdGFbJ3N1bW1hcnknXSB7XG4gIGNvbnN0IHN1Y2Nlc3NmdWxTdGVwcyA9IGRlY2lzaW9ucy5maWx0ZXIoZCA9PiBkLm91dGNvbWUgPT09ICdzdWNjZXNzJykubGVuZ3RoO1xuICBjb25zdCBmYWlsZWRTdGVwcyA9IGRlY2lzaW9ucy5maWx0ZXIoZCA9PiBkLm91dGNvbWUgPT09ICdmYWlsdXJlJykubGVuZ3RoO1xuICBjb25zdCBwYXJ0aWFsU3RlcHMgPSBkZWNpc2lvbnMuZmlsdGVyKGQgPT4gZC5vdXRjb21lID09PSAncGFydGlhbCcpLmxlbmd0aDtcblxuICBjb25zdCBjb25maWRlbmNlcyA9IGRlY2lzaW9ucy5tYXAoZCA9PiBkLmNvbmZpZGVuY2UpLmZpbHRlcihjID0+IHR5cGVvZiBjID09PSAnbnVtYmVyJyk7XG4gIGNvbnN0IGF2ZXJhZ2VDb25maWRlbmNlID0gY29uZmlkZW5jZXMubGVuZ3RoID4gMFxuICAgID8gY29uZmlkZW5jZXMucmVkdWNlKChzdW0sIGMpID0+IHN1bSArIGMsIDApIC8gY29uZmlkZW5jZXMubGVuZ3RoXG4gICAgOiAwO1xuXG4gIC8vIER1cmF0aW9uIGZyb20gZ29hbCBjcmVhdGlvbiB0byBsYXN0IGRlY2lzaW9uIG9yIGNvbXBsZXRpb25cbiAgY29uc3QgY3JlYXRlZEF0ID0gZ29hbC5jcmVhdGVkQXQgaW5zdGFuY2VvZiBEYXRlXG4gICAgPyBnb2FsLmNyZWF0ZWRBdC5nZXRUaW1lKClcbiAgICA6IG5ldyBEYXRlKFN0cmluZyhnb2FsLmNyZWF0ZWRBdCkpLmdldFRpbWUoKTtcblxuICBsZXQgZW5kVGltZTogbnVtYmVyO1xuICBpZiAoZ29hbC5jb21wbGV0ZWRBdCkge1xuICAgIGVuZFRpbWUgPSBnb2FsLmNvbXBsZXRlZEF0IGluc3RhbmNlb2YgRGF0ZVxuICAgICAgPyBnb2FsLmNvbXBsZXRlZEF0LmdldFRpbWUoKVxuICAgICAgOiBuZXcgRGF0ZShTdHJpbmcoZ29hbC5jb21wbGV0ZWRBdCkpLmdldFRpbWUoKTtcbiAgfSBlbHNlIGlmIChkZWNpc2lvbnMubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IGxhc3REZWNpc2lvbiA9IGRlY2lzaW9uc1tkZWNpc2lvbnMubGVuZ3RoIC0gMV07XG4gICAgZW5kVGltZSA9IGxhc3REZWNpc2lvbi50aW1lc3RhbXAgaW5zdGFuY2VvZiBEYXRlXG4gICAgICA/IGxhc3REZWNpc2lvbi50aW1lc3RhbXAuZ2V0VGltZSgpXG4gICAgICA6IG5ldyBEYXRlKFN0cmluZyhsYXN0RGVjaXNpb24udGltZXN0YW1wKSkuZ2V0VGltZSgpO1xuICB9IGVsc2Uge1xuICAgIGVuZFRpbWUgPSBEYXRlLm5vdygpO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICB0b3RhbFN0ZXBzOiBkZWNpc2lvbnMubGVuZ3RoLFxuICAgIHN1Y2Nlc3NmdWxTdGVwcyxcbiAgICBmYWlsZWRTdGVwcyxcbiAgICBwYXJ0aWFsU3RlcHMsXG4gICAgYXZlcmFnZUNvbmZpZGVuY2U6IHBhcnNlRmxvYXQoYXZlcmFnZUNvbmZpZGVuY2UudG9GaXhlZCgzKSksXG4gICAgZHVyYXRpb25NczogTWF0aC5tYXgoMCwgZW5kVGltZSAtIGNyZWF0ZWRBdCksXG4gIH07XG59XG4iXX0=