UNPKG

llmverify

Version:

AI Output Verification Toolkit — Local-first LLM safety, hallucination detection, PII redaction, prompt injection defense, and runtime monitoring. Zero telemetry. OWASP LLM Top 10 aligned.

157 lines 15.9 kB
"use strict"; /** * Health Score Engine * * Aggregates engine results into a composite health score. * Provides actionable health status and recommendations. * * WHAT THIS DOES: * ✅ Combines multiple engine results * ✅ Calculates weighted health score * ✅ Provides actionable status levels * ✅ Generates recommendations * * WHAT THIS DOES NOT DO: * ❌ Predict future health * ❌ Identify root causes * ❌ Guarantee accuracy of individual engines * * @module engines/runtime/health-score * @author Haiec * @license MIT */ Object.defineProperty(exports, "__esModule", { value: true }); exports.HealthScoreEngine = HealthScoreEngine; exports.isHealthy = isHealthy; exports.getAlertLevel = getAlertLevel; /** * Default weights for each metric. * Consistency and latency are weighted higher as they're most impactful. */ const DEFAULT_WEIGHTS = { consistency: 0.25, structure: 0.15, latency: 0.25, token_rate: 0.15, fingerprint: 0.20 }; /** * Generates recommendations based on engine results. */ function generateRecommendations(results) { const recommendations = []; for (const result of results) { if (result.status === 'error') { switch (result.metric) { case 'latency': recommendations.push('High latency detected. Consider checking provider status or implementing retry logic.'); break; case 'token_rate': recommendations.push('Low token rate detected. Provider may be throttling or experiencing issues.'); break; case 'fingerprint': recommendations.push('Response structure has changed significantly. Verify model behavior.'); break; case 'structure': recommendations.push('Structural anomalies detected. Check for truncation or format issues.'); break; case 'consistency': recommendations.push('Response consistency issues detected. Consider implementing validation.'); break; } } else if (result.status === 'warn') { switch (result.metric) { case 'latency': recommendations.push('Latency slightly elevated. Monitor for trends.'); break; case 'token_rate': recommendations.push('Token rate below normal. May indicate early throttling.'); break; case 'fingerprint': recommendations.push('Minor structural drift detected. May be normal variation.'); break; } } } return recommendations; } /** * Aggregates engine results into a health report. * * @param results - Array of engine results to aggregate * @param weights - Optional custom weights for each metric * @returns Comprehensive health report * * @example * const results = [latencyResult, tokenRateResult, fingerprintResult]; * const report = HealthScoreEngine(results); * * if (report.health === 'unstable') { * alert('LLM health critical!'); * } */ function HealthScoreEngine(results, weights) { const effectiveWeights = { ...DEFAULT_WEIGHTS, ...weights }; // Calculate weighted score let score = 0; let totalWeight = 0; for (const result of results) { const weight = effectiveWeights[result.metric] || 0.1; score += result.value * weight; totalWeight += weight; } // Normalize score score = totalWeight > 0 ? Math.min(1, score / totalWeight * Object.keys(effectiveWeights).length / results.length) : 0; score = Math.min(1, score); // Determine health status let health; if (score <= 0.25) { health = 'stable'; } else if (score <= 0.5) { health = 'minor_variation'; } else if (score <= 0.75) { health = 'degraded'; } else { health = 'unstable'; } // Check for any critical errors that should override const hasError = results.some(r => r.status === 'error'); if (hasError && health === 'stable') { health = 'minor_variation'; } // Generate recommendations const recommendations = generateRecommendations(results); return { health, score: Math.round(score * 100) / 100, engineResults: results, timestamp: Date.now(), recommendations: recommendations.length > 0 ? recommendations : undefined }; } /** * Quick health check - returns true if healthy. */ function isHealthy(report) { return report.health === 'stable' || report.health === 'minor_variation'; } /** * Gets severity level for alerting. */ function getAlertLevel(report) { switch (report.health) { case 'stable': return 'none'; case 'minor_variation': return 'info'; case 'degraded': return 'warning'; case 'unstable': return 'critical'; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVhbHRoLXNjb3JlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2VuZ2luZXMvcnVudGltZS9oZWFsdGgtc2NvcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW9CRzs7QUEwRUgsOENBZ0RDO0FBS0QsOEJBRUM7QUFLRCxzQ0FXQztBQTdJRDs7O0dBR0c7QUFDSCxNQUFNLGVBQWUsR0FBMkI7SUFDOUMsV0FBVyxFQUFFLElBQUk7SUFDakIsU0FBUyxFQUFFLElBQUk7SUFDZixPQUFPLEVBQUUsSUFBSTtJQUNiLFVBQVUsRUFBRSxJQUFJO0lBQ2hCLFdBQVcsRUFBRSxJQUFJO0NBQ2xCLENBQUM7QUFFRjs7R0FFRztBQUNILFNBQVMsdUJBQXVCLENBQUMsT0FBdUI7SUFDdEQsTUFBTSxlQUFlLEdBQWEsRUFBRSxDQUFDO0lBRXJDLEtBQUssTUFBTSxNQUFNLElBQUksT0FBTyxFQUFFLENBQUM7UUFDN0IsSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLE9BQU8sRUFBRSxDQUFDO1lBQzlCLFFBQVEsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUN0QixLQUFLLFNBQVM7b0JBQ1osZUFBZSxDQUFDLElBQUksQ0FBQyx1RkFBdUYsQ0FBQyxDQUFDO29CQUM5RyxNQUFNO2dCQUNSLEtBQUssWUFBWTtvQkFDZixlQUFlLENBQUMsSUFBSSxDQUFDLDZFQUE2RSxDQUFDLENBQUM7b0JBQ3BHLE1BQU07Z0JBQ1IsS0FBSyxhQUFhO29CQUNoQixlQUFlLENBQUMsSUFBSSxDQUFDLHNFQUFzRSxDQUFDLENBQUM7b0JBQzdGLE1BQU07Z0JBQ1IsS0FBSyxXQUFXO29CQUNkLGVBQWUsQ0FBQyxJQUFJLENBQUMsdUVBQXVFLENBQUMsQ0FBQztvQkFDOUYsTUFBTTtnQkFDUixLQUFLLGFBQWE7b0JBQ2hCLGVBQWUsQ0FBQyxJQUFJLENBQUMseUVBQXlFLENBQUMsQ0FBQztvQkFDaEcsTUFBTTtZQUNWLENBQUM7UUFDSCxDQUFDO2FBQU0sSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLE1BQU0sRUFBRSxDQUFDO1lBQ3BDLFFBQVEsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUN0QixLQUFLLFNBQVM7b0JBQ1osZUFBZSxDQUFDLElBQUksQ0FBQyxnREFBZ0QsQ0FBQyxDQUFDO29CQUN2RSxNQUFNO2dCQUNSLEtBQUssWUFBWTtvQkFDZixlQUFlLENBQUMsSUFBSSxDQUFDLHlEQUF5RCxDQUFDLENBQUM7b0JBQ2hGLE1BQU07Z0JBQ1IsS0FBSyxhQUFhO29CQUNoQixlQUFlLENBQUMsSUFBSSxDQUFDLDJEQUEyRCxDQUFDLENBQUM7b0JBQ2xGLE1BQU07WUFDVixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFRCxPQUFPLGVBQWUsQ0FBQztBQUN6QixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7O0dBY0c7QUFDSCxTQUFnQixpQkFBaUIsQ0FDL0IsT0FBdUIsRUFDdkIsT0FBZ0M7SUFFaEMsTUFBTSxnQkFBZ0IsR0FBRyxFQUFFLEdBQUcsZUFBZSxFQUFFLEdBQUcsT0FBTyxFQUFFLENBQUM7SUFFNUQsMkJBQTJCO0lBQzNCLElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQztJQUNkLElBQUksV0FBVyxHQUFHLENBQUMsQ0FBQztJQUVwQixLQUFLLE1BQU0sTUFBTSxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBQzdCLE1BQU0sTUFBTSxHQUFHLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxHQUFHLENBQUM7UUFDdEQsS0FBSyxJQUFJLE1BQU0sQ0FBQyxLQUFLLEdBQUcsTUFBTSxDQUFDO1FBQy9CLFdBQVcsSUFBSSxNQUFNLENBQUM7SUFDeEIsQ0FBQztJQUVELGtCQUFrQjtJQUNsQixLQUFLLEdBQUcsV0FBVyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsS0FBSyxHQUFHLFdBQVcsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZILEtBQUssR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUUzQiwwQkFBMEI7SUFDMUIsSUFBSSxNQUFvQixDQUFDO0lBQ3pCLElBQUksS0FBSyxJQUFJLElBQUksRUFBRSxDQUFDO1FBQ2xCLE1BQU0sR0FBRyxRQUFRLENBQUM7SUFDcEIsQ0FBQztTQUFNLElBQUksS0FBSyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQ3hCLE1BQU0sR0FBRyxpQkFBaUIsQ0FBQztJQUM3QixDQUFDO1NBQU0sSUFBSSxLQUFLLElBQUksSUFBSSxFQUFFLENBQUM7UUFDekIsTUFBTSxHQUFHLFVBQVUsQ0FBQztJQUN0QixDQUFDO1NBQU0sQ0FBQztRQUNOLE1BQU0sR0FBRyxVQUFVLENBQUM7SUFDdEIsQ0FBQztJQUVELHFEQUFxRDtJQUNyRCxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sS0FBSyxPQUFPLENBQUMsQ0FBQztJQUN6RCxJQUFJLFFBQVEsSUFBSSxNQUFNLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDcEMsTUFBTSxHQUFHLGlCQUFpQixDQUFDO0lBQzdCLENBQUM7SUFFRCwyQkFBMkI7SUFDM0IsTUFBTSxlQUFlLEdBQUcsdUJBQXVCLENBQUMsT0FBTyxDQUFDLENBQUM7SUFFekQsT0FBTztRQUNMLE1BQU07UUFDTixLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEdBQUcsR0FBRyxDQUFDLEdBQUcsR0FBRztRQUNwQyxhQUFhLEVBQUUsT0FBTztRQUN0QixTQUFTLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNyQixlQUFlLEVBQUUsZUFBZSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsU0FBUztLQUMxRSxDQUFDO0FBQ0osQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBZ0IsU0FBUyxDQUFDLE1BQW9CO0lBQzVDLE9BQU8sTUFBTSxDQUFDLE1BQU0sS0FBSyxRQUFRLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxpQkFBaUIsQ0FBQztBQUMzRSxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFnQixhQUFhLENBQUMsTUFBb0I7SUFDaEQsUUFBUSxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDdEIsS0FBSyxRQUFRO1lBQ1gsT0FBTyxNQUFNLENBQUM7UUFDaEIsS0FBSyxpQkFBaUI7WUFDcEIsT0FBTyxNQUFNLENBQUM7UUFDaEIsS0FBSyxVQUFVO1lBQ2IsT0FBTyxTQUFTLENBQUM7UUFDbkIsS0FBSyxVQUFVO1lBQ2IsT0FBTyxVQUFVLENBQUM7SUFDdEIsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEhlYWx0aCBTY29yZSBFbmdpbmVcbiAqIFxuICogQWdncmVnYXRlcyBlbmdpbmUgcmVzdWx0cyBpbnRvIGEgY29tcG9zaXRlIGhlYWx0aCBzY29yZS5cbiAqIFByb3ZpZGVzIGFjdGlvbmFibGUgaGVhbHRoIHN0YXR1cyBhbmQgcmVjb21tZW5kYXRpb25zLlxuICogXG4gKiBXSEFUIFRISVMgRE9FUzpcbiAqIOKchSBDb21iaW5lcyBtdWx0aXBsZSBlbmdpbmUgcmVzdWx0c1xuICog4pyFIENhbGN1bGF0ZXMgd2VpZ2h0ZWQgaGVhbHRoIHNjb3JlXG4gKiDinIUgUHJvdmlkZXMgYWN0aW9uYWJsZSBzdGF0dXMgbGV2ZWxzXG4gKiDinIUgR2VuZXJhdGVzIHJlY29tbWVuZGF0aW9uc1xuICogXG4gKiBXSEFUIFRISVMgRE9FUyBOT1QgRE86XG4gKiDinYwgUHJlZGljdCBmdXR1cmUgaGVhbHRoXG4gKiDinYwgSWRlbnRpZnkgcm9vdCBjYXVzZXNcbiAqIOKdjCBHdWFyYW50ZWUgYWNjdXJhY3kgb2YgaW5kaXZpZHVhbCBlbmdpbmVzXG4gKiBcbiAqIEBtb2R1bGUgZW5naW5lcy9ydW50aW1lL2hlYWx0aC1zY29yZVxuICogQGF1dGhvciBIYWllY1xuICogQGxpY2Vuc2UgTUlUXG4gKi9cblxuaW1wb3J0IHsgRW5naW5lUmVzdWx0LCBIZWFsdGhSZXBvcnQsIEhlYWx0aFN0YXR1cyB9IGZyb20gJy4uLy4uL3R5cGVzL3J1bnRpbWUnO1xuXG4vKipcbiAqIERlZmF1bHQgd2VpZ2h0cyBmb3IgZWFjaCBtZXRyaWMuXG4gKiBDb25zaXN0ZW5jeSBhbmQgbGF0ZW5jeSBhcmUgd2VpZ2h0ZWQgaGlnaGVyIGFzIHRoZXkncmUgbW9zdCBpbXBhY3RmdWwuXG4gKi9cbmNvbnN0IERFRkFVTFRfV0VJR0hUUzogUmVjb3JkPHN0cmluZywgbnVtYmVyPiA9IHtcbiAgY29uc2lzdGVuY3k6IDAuMjUsXG4gIHN0cnVjdHVyZTogMC4xNSxcbiAgbGF0ZW5jeTogMC4yNSxcbiAgdG9rZW5fcmF0ZTogMC4xNSxcbiAgZmluZ2VycHJpbnQ6IDAuMjBcbn07XG5cbi8qKlxuICogR2VuZXJhdGVzIHJlY29tbWVuZGF0aW9ucyBiYXNlZCBvbiBlbmdpbmUgcmVzdWx0cy5cbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVSZWNvbW1lbmRhdGlvbnMocmVzdWx0czogRW5naW5lUmVzdWx0W10pOiBzdHJpbmdbXSB7XG4gIGNvbnN0IHJlY29tbWVuZGF0aW9uczogc3RyaW5nW10gPSBbXTtcblxuICBmb3IgKGNvbnN0IHJlc3VsdCBvZiByZXN1bHRzKSB7XG4gICAgaWYgKHJlc3VsdC5zdGF0dXMgPT09ICdlcnJvcicpIHtcbiAgICAgIHN3aXRjaCAocmVzdWx0Lm1ldHJpYykge1xuICAgICAgICBjYXNlICdsYXRlbmN5JzpcbiAgICAgICAgICByZWNvbW1lbmRhdGlvbnMucHVzaCgnSGlnaCBsYXRlbmN5IGRldGVjdGVkLiBDb25zaWRlciBjaGVja2luZyBwcm92aWRlciBzdGF0dXMgb3IgaW1wbGVtZW50aW5nIHJldHJ5IGxvZ2ljLicpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICd0b2tlbl9yYXRlJzpcbiAgICAgICAgICByZWNvbW1lbmRhdGlvbnMucHVzaCgnTG93IHRva2VuIHJhdGUgZGV0ZWN0ZWQuIFByb3ZpZGVyIG1heSBiZSB0aHJvdHRsaW5nIG9yIGV4cGVyaWVuY2luZyBpc3N1ZXMuJyk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2ZpbmdlcnByaW50JzpcbiAgICAgICAgICByZWNvbW1lbmRhdGlvbnMucHVzaCgnUmVzcG9uc2Ugc3RydWN0dXJlIGhhcyBjaGFuZ2VkIHNpZ25pZmljYW50bHkuIFZlcmlmeSBtb2RlbCBiZWhhdmlvci4nKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnc3RydWN0dXJlJzpcbiAgICAgICAgICByZWNvbW1lbmRhdGlvbnMucHVzaCgnU3RydWN0dXJhbCBhbm9tYWxpZXMgZGV0ZWN0ZWQuIENoZWNrIGZvciB0cnVuY2F0aW9uIG9yIGZvcm1hdCBpc3N1ZXMuJyk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2NvbnNpc3RlbmN5JzpcbiAgICAgICAgICByZWNvbW1lbmRhdGlvbnMucHVzaCgnUmVzcG9uc2UgY29uc2lzdGVuY3kgaXNzdWVzIGRldGVjdGVkLiBDb25zaWRlciBpbXBsZW1lbnRpbmcgdmFsaWRhdGlvbi4nKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHJlc3VsdC5zdGF0dXMgPT09ICd3YXJuJykge1xuICAgICAgc3dpdGNoIChyZXN1bHQubWV0cmljKSB7XG4gICAgICAgIGNhc2UgJ2xhdGVuY3knOlxuICAgICAgICAgIHJlY29tbWVuZGF0aW9ucy5wdXNoKCdMYXRlbmN5IHNsaWdodGx5IGVsZXZhdGVkLiBNb25pdG9yIGZvciB0cmVuZHMuJyk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3Rva2VuX3JhdGUnOlxuICAgICAgICAgIHJlY29tbWVuZGF0aW9ucy5wdXNoKCdUb2tlbiByYXRlIGJlbG93IG5vcm1hbC4gTWF5IGluZGljYXRlIGVhcmx5IHRocm90dGxpbmcuJyk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2ZpbmdlcnByaW50JzpcbiAgICAgICAgICByZWNvbW1lbmRhdGlvbnMucHVzaCgnTWlub3Igc3RydWN0dXJhbCBkcmlmdCBkZXRlY3RlZC4gTWF5IGJlIG5vcm1hbCB2YXJpYXRpb24uJyk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJlY29tbWVuZGF0aW9ucztcbn1cblxuLyoqXG4gKiBBZ2dyZWdhdGVzIGVuZ2luZSByZXN1bHRzIGludG8gYSBoZWFsdGggcmVwb3J0LlxuICogXG4gKiBAcGFyYW0gcmVzdWx0cyAtIEFycmF5IG9mIGVuZ2luZSByZXN1bHRzIHRvIGFnZ3JlZ2F0ZVxuICogQHBhcmFtIHdlaWdodHMgLSBPcHRpb25hbCBjdXN0b20gd2VpZ2h0cyBmb3IgZWFjaCBtZXRyaWNcbiAqIEByZXR1cm5zIENvbXByZWhlbnNpdmUgaGVhbHRoIHJlcG9ydFxuICogXG4gKiBAZXhhbXBsZVxuICogY29uc3QgcmVzdWx0cyA9IFtsYXRlbmN5UmVzdWx0LCB0b2tlblJhdGVSZXN1bHQsIGZpbmdlcnByaW50UmVzdWx0XTtcbiAqIGNvbnN0IHJlcG9ydCA9IEhlYWx0aFNjb3JlRW5naW5lKHJlc3VsdHMpO1xuICogXG4gKiBpZiAocmVwb3J0LmhlYWx0aCA9PT0gJ3Vuc3RhYmxlJykge1xuICogICBhbGVydCgnTExNIGhlYWx0aCBjcml0aWNhbCEnKTtcbiAqIH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEhlYWx0aFNjb3JlRW5naW5lKFxuICByZXN1bHRzOiBFbmdpbmVSZXN1bHRbXSxcbiAgd2VpZ2h0cz86IFJlY29yZDxzdHJpbmcsIG51bWJlcj5cbik6IEhlYWx0aFJlcG9ydCB7XG4gIGNvbnN0IGVmZmVjdGl2ZVdlaWdodHMgPSB7IC4uLkRFRkFVTFRfV0VJR0hUUywgLi4ud2VpZ2h0cyB9O1xuXG4gIC8vIENhbGN1bGF0ZSB3ZWlnaHRlZCBzY29yZVxuICBsZXQgc2NvcmUgPSAwO1xuICBsZXQgdG90YWxXZWlnaHQgPSAwO1xuXG4gIGZvciAoY29uc3QgcmVzdWx0IG9mIHJlc3VsdHMpIHtcbiAgICBjb25zdCB3ZWlnaHQgPSBlZmZlY3RpdmVXZWlnaHRzW3Jlc3VsdC5tZXRyaWNdIHx8IDAuMTtcbiAgICBzY29yZSArPSByZXN1bHQudmFsdWUgKiB3ZWlnaHQ7XG4gICAgdG90YWxXZWlnaHQgKz0gd2VpZ2h0O1xuICB9XG5cbiAgLy8gTm9ybWFsaXplIHNjb3JlXG4gIHNjb3JlID0gdG90YWxXZWlnaHQgPiAwID8gTWF0aC5taW4oMSwgc2NvcmUgLyB0b3RhbFdlaWdodCAqIE9iamVjdC5rZXlzKGVmZmVjdGl2ZVdlaWdodHMpLmxlbmd0aCAvIHJlc3VsdHMubGVuZ3RoKSA6IDA7XG4gIHNjb3JlID0gTWF0aC5taW4oMSwgc2NvcmUpO1xuXG4gIC8vIERldGVybWluZSBoZWFsdGggc3RhdHVzXG4gIGxldCBoZWFsdGg6IEhlYWx0aFN0YXR1cztcbiAgaWYgKHNjb3JlIDw9IDAuMjUpIHtcbiAgICBoZWFsdGggPSAnc3RhYmxlJztcbiAgfSBlbHNlIGlmIChzY29yZSA8PSAwLjUpIHtcbiAgICBoZWFsdGggPSAnbWlub3JfdmFyaWF0aW9uJztcbiAgfSBlbHNlIGlmIChzY29yZSA8PSAwLjc1KSB7XG4gICAgaGVhbHRoID0gJ2RlZ3JhZGVkJztcbiAgfSBlbHNlIHtcbiAgICBoZWFsdGggPSAndW5zdGFibGUnO1xuICB9XG5cbiAgLy8gQ2hlY2sgZm9yIGFueSBjcml0aWNhbCBlcnJvcnMgdGhhdCBzaG91bGQgb3ZlcnJpZGVcbiAgY29uc3QgaGFzRXJyb3IgPSByZXN1bHRzLnNvbWUociA9PiByLnN0YXR1cyA9PT0gJ2Vycm9yJyk7XG4gIGlmIChoYXNFcnJvciAmJiBoZWFsdGggPT09ICdzdGFibGUnKSB7XG4gICAgaGVhbHRoID0gJ21pbm9yX3ZhcmlhdGlvbic7XG4gIH1cblxuICAvLyBHZW5lcmF0ZSByZWNvbW1lbmRhdGlvbnNcbiAgY29uc3QgcmVjb21tZW5kYXRpb25zID0gZ2VuZXJhdGVSZWNvbW1lbmRhdGlvbnMocmVzdWx0cyk7XG5cbiAgcmV0dXJuIHtcbiAgICBoZWFsdGgsXG4gICAgc2NvcmU6IE1hdGgucm91bmQoc2NvcmUgKiAxMDApIC8gMTAwLFxuICAgIGVuZ2luZVJlc3VsdHM6IHJlc3VsdHMsXG4gICAgdGltZXN0YW1wOiBEYXRlLm5vdygpLFxuICAgIHJlY29tbWVuZGF0aW9uczogcmVjb21tZW5kYXRpb25zLmxlbmd0aCA+IDAgPyByZWNvbW1lbmRhdGlvbnMgOiB1bmRlZmluZWRcbiAgfTtcbn1cblxuLyoqXG4gKiBRdWljayBoZWFsdGggY2hlY2sgLSByZXR1cm5zIHRydWUgaWYgaGVhbHRoeS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzSGVhbHRoeShyZXBvcnQ6IEhlYWx0aFJlcG9ydCk6IGJvb2xlYW4ge1xuICByZXR1cm4gcmVwb3J0LmhlYWx0aCA9PT0gJ3N0YWJsZScgfHwgcmVwb3J0LmhlYWx0aCA9PT0gJ21pbm9yX3ZhcmlhdGlvbic7XG59XG5cbi8qKlxuICogR2V0cyBzZXZlcml0eSBsZXZlbCBmb3IgYWxlcnRpbmcuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRBbGVydExldmVsKHJlcG9ydDogSGVhbHRoUmVwb3J0KTogJ25vbmUnIHwgJ2luZm8nIHwgJ3dhcm5pbmcnIHwgJ2NyaXRpY2FsJyB7XG4gIHN3aXRjaCAocmVwb3J0LmhlYWx0aCkge1xuICAgIGNhc2UgJ3N0YWJsZSc6XG4gICAgICByZXR1cm4gJ25vbmUnO1xuICAgIGNhc2UgJ21pbm9yX3ZhcmlhdGlvbic6XG4gICAgICByZXR1cm4gJ2luZm8nO1xuICAgIGNhc2UgJ2RlZ3JhZGVkJzpcbiAgICAgIHJldHVybiAnd2FybmluZyc7XG4gICAgY2FzZSAndW5zdGFibGUnOlxuICAgICAgcmV0dXJuICdjcml0aWNhbCc7XG4gIH1cbn1cbiJdfQ==