vibetunnel
Version:
Terminal sharing server with web interface - supports macOS, Linux, and headless environments
167 lines • 20.3 kB
JavaScript
;
/**
* Unified prompt pattern detection for terminal output
* Pre-compiled regexes for optimal performance
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.endsWithPrompt = exports.isPromptOnly = exports.PromptDetector = void 0;
const logger_js_1 = require("./logger.js");
const logger = (0, logger_js_1.createLogger)('prompt-patterns');
// ANSI escape code pattern for stripping
// biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape codes require control characters
const ANSI_ESCAPE_REGEX = /\x1b\[[0-9;]*[a-zA-Z]/g;
// Single pre-compiled regex combining all prompt patterns
// (?<![.>]) - Negative lookbehind: not preceded by . or > (excludes Python)
// (?:\[[^\]]*\])? - Optional brackets for user@host, paths, etc
// [$>#%❯➜] - Common prompt characters
// \s* - Optional trailing whitespace
// (?:\x1b\[...)? - Optional ANSI escape sequence
// $ - End of string anchor
// biome-ignore lint/suspicious/noControlCharactersInRegex: Terminal prompts may contain escape sequences
const UNIFIED_PROMPT_END_REGEX = /(?<![.>])(?:\[[^\]]*\])?[$>#%❯➜]\s*(?:\x1b\[[0-9;]*[a-zA-Z])?$/;
// Regex for detecting if entire output is just a prompt (no other content)
// ^ - Start of string anchor
// (?:\[[^\]]*\])? - Optional brackets for user@host, paths, etc
// (?<!^[.>]{2}) - Negative lookbehind: not preceded by .. or >> at start
// [$>#%❯➜] - Common prompt characters
// \s* - Optional trailing whitespace
// $ - End of string anchor
const PROMPT_ONLY_REGEX = /^(?:\[[^\]]*\])?(?<!^[.>]{2})[$>#%❯➜]\s*$/;
// More specific patterns for different shells (for future shell-specific optimizations)
// Order matters - more specific patterns should come first
const SHELL_SPECIFIC_PATTERNS = {
// Multi-line prompts (like in Python REPL) - check FIRST before PowerShell
python: /^>>>\s*$/,
pythonContinuation: /^\.\.\.\s*$/,
// Bracketed prompts (user@host, git branch, etc.) - check early as they're specific
bracketed: /\][#$]\s*$/,
// Root prompt
root: /#\s*$/,
// PowerShell - now after Python to avoid false matches
powershell: /^PS.*>\s*$|^>\s*$/,
// Modern shells
zsh: /[%❯]\s*$/,
fish: /[❯➜]\s*$/,
// Basic shells - check last as $ is common
bash: /\$\s*$/,
sh: /\$\s*$/,
// With escape sequences (for color prompts)
// biome-ignore lint/suspicious/noControlCharactersInRegex: Terminal escape sequences
withEscape: /[$>#%❯➜]\s*\x1b\[/,
};
var PromptDetector;
(function (PromptDetector) {
// Cache for regex test results to avoid repeated tests
const endPromptCache = new Map();
const onlyPromptCache = new Map();
let cacheSize = 0;
const MAX_CACHE_SIZE = 1000;
/**
* Check if the entire output is just a prompt (no other content)
* Used by activity detector to determine if output is meaningful
*/
function isPromptOnly(data) {
// Input validation
if (data.length > 10000) {
logger.warn('Unusually long prompt input detected', { length: data.length });
return false;
}
const trimmed = data.trim();
// Check cache first
if (onlyPromptCache.has(trimmed)) {
const cachedResult = onlyPromptCache.get(trimmed);
return cachedResult ?? false;
}
const result = PROMPT_ONLY_REGEX.test(trimmed);
// Cache result
cacheResult(onlyPromptCache, trimmed, result);
return result;
}
PromptDetector.isPromptOnly = isPromptOnly;
/**
* Check if output ends with a prompt (for title injection)
* This is used to determine when to inject terminal title sequences
*/
function endsWithPrompt(data) {
// For title injection, we need to check the last part of the output
// Use last 100 chars as cache key to balance cache efficiency and accuracy
const cacheKey = data.slice(-100);
// Check cache first
if (endPromptCache.has(cacheKey)) {
const cachedResult = endPromptCache.get(cacheKey);
return cachedResult ?? false;
}
// Strip ANSI codes for more reliable detection
const cleanData = data.replace(ANSI_ESCAPE_REGEX, '');
const result = UNIFIED_PROMPT_END_REGEX.test(cleanData);
// Cache result
cacheResult(endPromptCache, cacheKey, result);
if (result) {
logger.debug('Detected prompt at end of output');
}
return result;
}
PromptDetector.endsWithPrompt = endsWithPrompt;
/**
* Get specific shell type based on prompt pattern
* This can be used for shell-specific optimizations in the future
*/
function getShellType(data) {
const trimmed = data.trim();
// Check each shell pattern
for (const [shell, pattern] of Object.entries(SHELL_SPECIFIC_PATTERNS)) {
if (pattern.test(trimmed)) {
return shell;
}
}
return null;
}
PromptDetector.getShellType = getShellType;
/**
* Helper to cache results with size limit
*/
function cacheResult(cache, key, value) {
if (cacheSize >= MAX_CACHE_SIZE) {
// Clear oldest entries when cache is full
const entriesToDelete = Math.floor(MAX_CACHE_SIZE * 0.2); // Clear 20%
const iterator = cache.keys();
for (let i = 0; i < entriesToDelete; i++) {
const keyToDelete = iterator.next().value;
if (keyToDelete) {
cache.delete(keyToDelete);
cacheSize--;
}
}
}
cache.set(key, value);
cacheSize++;
}
/**
* Clear all caches (useful for tests or memory management)
*/
function clearCache() {
endPromptCache.clear();
onlyPromptCache.clear();
cacheSize = 0;
logger.debug('Prompt pattern caches cleared');
}
PromptDetector.clearCache = clearCache;
/**
* Get cache statistics for monitoring
*/
function getCacheStats() {
return {
size: cacheSize,
maxSize: MAX_CACHE_SIZE,
hitRate: {
end: endPromptCache.size,
only: onlyPromptCache.size,
},
};
}
PromptDetector.getCacheStats = getCacheStats;
})(PromptDetector || (exports.PromptDetector = PromptDetector = {}));
// Export for backward compatibility
exports.isPromptOnly = PromptDetector.isPromptOnly;
exports.endsWithPrompt = PromptDetector.endsWithPrompt;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvbXB0LXBhdHRlcm5zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3NlcnZlci91dGlscy9wcm9tcHQtcGF0dGVybnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7R0FHRzs7O0FBRUgsMkNBQTJDO0FBRTNDLE1BQU0sTUFBTSxHQUFHLElBQUEsd0JBQVksRUFBQyxpQkFBaUIsQ0FBQyxDQUFDO0FBRS9DLHlDQUF5QztBQUN6Qyx3R0FBd0c7QUFDeEcsTUFBTSxpQkFBaUIsR0FBRyx3QkFBd0IsQ0FBQztBQUVuRCwwREFBMEQ7QUFDMUQsb0ZBQW9GO0FBQ3BGLGtFQUFrRTtBQUNsRSw4Q0FBOEM7QUFDOUMsbURBQW1EO0FBQ25ELG9EQUFvRDtBQUNwRCwyQ0FBMkM7QUFDM0MseUdBQXlHO0FBQ3pHLE1BQU0sd0JBQXdCLEdBQUcsZ0VBQWdFLENBQUM7QUFFbEcsMkVBQTJFO0FBQzNFLDZDQUE2QztBQUM3QyxrRUFBa0U7QUFDbEUsNkVBQTZFO0FBQzdFLDhDQUE4QztBQUM5QyxtREFBbUQ7QUFDbkQsMkNBQTJDO0FBQzNDLE1BQU0saUJBQWlCLEdBQUcsMkNBQTJDLENBQUM7QUFFdEUsd0ZBQXdGO0FBQ3hGLDJEQUEyRDtBQUMzRCxNQUFNLHVCQUF1QixHQUFHO0lBQzlCLDJFQUEyRTtJQUMzRSxNQUFNLEVBQUUsVUFBVTtJQUNsQixrQkFBa0IsRUFBRSxhQUFhO0lBRWpDLG9GQUFvRjtJQUNwRixTQUFTLEVBQUUsWUFBWTtJQUV2QixjQUFjO0lBQ2QsSUFBSSxFQUFFLE9BQU87SUFFYix1REFBdUQ7SUFDdkQsVUFBVSxFQUFFLG1CQUFtQjtJQUUvQixnQkFBZ0I7SUFDaEIsR0FBRyxFQUFFLFVBQVU7SUFDZixJQUFJLEVBQUUsVUFBVTtJQUVoQiwyQ0FBMkM7SUFDM0MsSUFBSSxFQUFFLFFBQVE7SUFDZCxFQUFFLEVBQUUsUUFBUTtJQUVaLDRDQUE0QztJQUM1QyxxRkFBcUY7SUFDckYsVUFBVSxFQUFF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O0lBYmUsNEJBQWEsZ0JBYTVCLENBQUE7QUFDSCxDQUFDLEVBaElnQixjQUFjLDhCQUFkLGNBQWMsUUFnSTlCO0FBRUQsb0NBQW9DO0FBQ3ZCLFFBQUEsWUFBWSxHQUFHLGNBQWMsQ0FBQyxZQUFZLENBQUM7QUFDM0MsUUFBQSxjQUFjLEdBQUcsY0FBYyxDQUFDLGNBQWMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVW5pZmllZCBwcm9tcHQgcGF0dGVybiBkZXRlY3Rpb24gZm9yIHRlcm1pbmFsIG91dHB1dFxuICogUHJlLWNvbXBpbGVkIHJlZ2V4ZXMgZm9yIG9wdGltYWwgcGVyZm9ybWFuY2VcbiAqL1xuXG5pbXBvcnQgeyBjcmVhdGVMb2dnZXIgfSBmcm9tICcuL2xvZ2dlci5qcyc7XG5cbmNvbnN0IGxvZ2dlciA9IGNyZWF0ZUxvZ2dlcigncHJvbXB0LXBhdHRlcm5zJyk7XG5cbi8vIEFOU0kgZXNjYXBlIGNvZGUgcGF0dGVybiBmb3Igc3RyaXBwaW5nXG4vLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL25vQ29udHJvbENoYXJhY3RlcnNJblJlZ2V4OiBBTlNJIGVzY2FwZSBjb2RlcyByZXF1aXJlIGNvbnRyb2wgY2hhcmFjdGVyc1xuY29uc3QgQU5TSV9FU0NBUEVfUkVHRVggPSAvXFx4MWJcXFtbMC05O10qW2EtekEtWl0vZztcblxuLy8gU2luZ2xlIHByZS1jb21waWxlZCByZWdleCBjb21iaW5pbmcgYWxsIHByb21wdCBwYXR0ZXJuc1xuLy8gKD88IVsuPl0pICAgICAgICAgLSBOZWdhdGl2ZSBsb29rYmVoaW5kOiBub3QgcHJlY2VkZWQgYnkgLiBvciA+IChleGNsdWRlcyBQeXRob24pXG4vLyAoPzpcXFtbXlxcXV0qXFxdKT8gICAtIE9wdGlvbmFsIGJyYWNrZXRzIGZvciB1c2VyQGhvc3QsIHBhdGhzLCBldGNcbi8vIFskPiMl4p2v4p6cXSAgICAgICAgIC0gQ29tbW9uIHByb21wdCBjaGFyYWN0ZXJzXG4vLyBcXHMqICAgICAgICAgICAgICAgLSBPcHRpb25hbCB0cmFpbGluZyB3aGl0ZXNwYWNlXG4vLyAoPzpcXHgxYlxcWy4uLik/ICAgIC0gT3B0aW9uYWwgQU5TSSBlc2NhcGUgc2VxdWVuY2Vcbi8vICQgICAgICAgICAgICAgICAgIC0gRW5kIG9mIHN0cmluZyBhbmNob3Jcbi8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9Db250cm9sQ2hhcmFjdGVyc0luUmVnZXg6IFRlcm1pbmFsIHByb21wdHMgbWF5IGNvbnRhaW4gZXNjYXBlIHNlcXVlbmNlc1xuY29uc3QgVU5JRklFRF9QUk9NUFRfRU5EX1JFR0VYID0gLyg/PCFbLj5dKSg/OlxcW1teXFxdXSpcXF0pP1skPiMl4p2v4p6cXVxccyooPzpcXHgxYlxcW1swLTk7XSpbYS16QS1aXSk/JC87XG5cbi8vIFJlZ2V4IGZvciBkZXRlY3RpbmcgaWYgZW50aXJlIG91dHB1dCBpcyBqdXN0IGEgcHJvbXB0IChubyBvdGhlciBjb250ZW50KVxuLy8gXiAgICAgICAgICAgICAgICAgLSBTdGFydCBvZiBzdHJpbmcgYW5jaG9yXG4vLyAoPzpcXFtbXlxcXV0qXFxdKT8gICAtIE9wdGlvbmFsIGJyYWNrZXRzIGZvciB1c2VyQGhvc3QsIHBhdGhzLCBldGNcbi8vICg/PCFeWy4+XXsyfSkgICAgIC0gTmVnYXRpdmUgbG9va2JlaGluZDogbm90IHByZWNlZGVkIGJ5IC4uIG9yID4+IGF0IHN0YXJ0XG4vLyBbJD4jJeKdr+KenF0gICAgICAgICAtIENvbW1vbiBwcm9tcHQgY2hhcmFjdGVyc1xuLy8gXFxzKiAgICAgICAgICAgICAgIC0gT3B0aW9uYWwgdHJhaWxpbmcgd2hpdGVzcGFjZVxuLy8gJCAgICAgICAgICAgICAgICAgLSBFbmQgb2Ygc3RyaW5nIGFuY2hvclxuY29uc3QgUFJPTVBUX09OTFlfUkVHRVggPSAvXig/OlxcW1teXFxdXSpcXF0pPyg/PCFeWy4+XXsyfSlbJD4jJeKdr+KenF1cXHMqJC87XG5cbi8vIE1vcmUgc3BlY2lmaWMgcGF0dGVybnMgZm9yIGRpZmZlcmVudCBzaGVsbHMgKGZvciBmdXR1cmUgc2hlbGwtc3BlY2lmaWMgb3B0aW1pemF0aW9ucylcbi8vIE9yZGVyIG1hdHRlcnMgLSBtb3JlIHNwZWNpZmljIHBhdHRlcm5zIHNob3VsZCBjb21lIGZpcnN0XG5jb25zdCBTSEVMTF9TUEVDSUZJQ19QQVRURVJOUyA9IHtcbiAgLy8gTXVsdGktbGluZSBwcm9tcHRzIChsaWtlIGluIFB5dGhvbiBSRVBMKSAtIGNoZWNrIEZJUlNUIGJlZm9yZSBQb3dlclNoZWxsXG4gIHB5dGhvbjogL14+Pj5cXHMqJC8sXG4gIHB5dGhvbkNvbnRpbnVhdGlvbjogL15cXC5cXC5cXC5cXHMqJC8sXG5cbiAgLy8gQnJhY2tldGVkIHByb21wdHMgKHVzZXJAaG9zdCwgZ2l0IGJyYW5jaCwgZXRjLikgLSBjaGVjayBlYXJseSBhcyB0aGV5J3JlIHNwZWNpZmljXG4gIGJyYWNrZXRlZDogL1xcXVsjJF1cXHMqJC8sXG5cbiAgLy8gUm9vdCBwcm9tcHRcbiAgcm9vdDogLyNcXHMqJC8sXG5cbiAgLy8gUG93ZXJTaGVsbCAtIG5vdyBhZnRlciBQeXRob24gdG8gYXZvaWQgZmFsc2UgbWF0Y2hlc1xuICBwb3dlcnNoZWxsOiAvXlBTLio+XFxzKiR8Xj5cXHMqJC8sXG5cbiAgLy8gTW9kZXJuIHNoZWxsc1xuICB6c2g6IC9bJeKdr11cXHMqJC8sXG4gIGZpc2g6IC9b4p2v4p6cXVxccyokLyxcblxuICAvLyBCYXNpYyBzaGVsbHMgLSBjaGVjayBsYXN0IGFzICQgaXMgY29tbW9uXG4gIGJhc2g6IC9cXCRcXHMqJC8sXG4gIHNoOiAvXFwkXFxzKiQvLFxuXG4gIC8vIFdpdGggZXNjYXBlIHNlcXVlbmNlcyAoZm9yIGNvbG9yIHByb21wdHMpXG4gIC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvbm9Db250cm9sQ2hhcmFjdGVyc0luUmVnZXg6IFRlcm1pbmFsIGVzY2FwZSBzZXF1ZW5jZXNcbiAgd2l0aEVzY2FwZTogL1skPiMl4p2v4p6cXVxccypcXHgxYlxcWy8sXG59O1xuXG5leHBvcnQgbmFtZXNwYWNlIFByb21wdERldGVjdG9yIHtcbiAgLy8gQ2FjaGUgZm9yIHJlZ2V4IHRlc3QgcmVzdWx0cyB0byBhdm9pZCByZXBlYXRlZCB0ZXN0c1xuICBjb25zdCBlbmRQcm9tcHRDYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBib29sZWFuPigpO1xuICBjb25zdCBvbmx5UHJvbXB0Q2FjaGUgPSBuZXcgTWFwPHN0cmluZywgYm9vbGVhbj4oKTtcbiAgbGV0IGNhY2hlU2l6ZSA9IDA7XG4gIGNvbnN0IE1BWF9DQUNIRV9TSVpFID0gMTAwMDtcblxuICAvKipcbiAgICogQ2hlY2sgaWYgdGhlIGVudGlyZSBvdXRwdXQgaXMganVzdCBhIHByb21wdCAobm8gb3RoZXIgY29udGVudClcbiAgICogVXNlZCBieSBhY3Rpdml0eSBkZXRlY3RvciB0byBkZXRlcm1pbmUgaWYgb3V0cHV0IGlzIG1lYW5pbmdmdWxcbiAgICovXG4gIGV4cG9ydCBmdW5jdGlvbiBpc1Byb21wdE9ubHkoZGF0YTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgLy8gSW5wdXQgdmFsaWRhdGlvblxuICAgIGlmIChkYXRhLmxlbmd0aCA+IDEwMDAwKSB7XG4gICAgICBsb2dnZXIud2FybignVW51c3VhbGx5IGxvbmcgcHJvbXB0IGlucHV0IGRldGVjdGVkJywgeyBsZW5ndGg6IGRhdGEubGVuZ3RoIH0pO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IHRyaW1tZWQgPSBkYXRhLnRyaW0oKTtcblxuICAgIC8vIENoZWNrIGNhY2hlIGZpcnN0XG4gICAgaWYgKG9ubHlQcm9tcHRDYWNoZS5oYXModHJpbW1lZCkpIHtcbiAgICAgIGNvbnN0IGNhY2hlZFJlc3VsdCA9IG9ubHlQcm9tcHRDYWNoZS5nZXQodHJpbW1lZCk7XG4gICAgICByZXR1cm4gY2FjaGVkUmVzdWx0ID8/IGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IHJlc3VsdCA9IFBST01QVF9PTkxZX1JFR0VYLnRlc3QodHJpbW1lZCk7XG5cbiAgICAvLyBDYWNoZSByZXN1bHRcbiAgICBjYWNoZVJlc3VsdChvbmx5UHJvbXB0Q2FjaGUsIHRyaW1tZWQsIHJlc3VsdCk7XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIG91dHB1dCBlbmRzIHdpdGggYSBwcm9tcHQgKGZvciB0aXRsZSBpbmplY3Rpb24pXG4gICAqIFRoaXMgaXMgdXNlZCB0byBkZXRlcm1pbmUgd2hlbiB0byBpbmplY3QgdGVybWluYWwgdGl0bGUgc2VxdWVuY2VzXG4gICAqL1xuICBleHBvcnQgZnVuY3Rpb24gZW5kc1dpdGhQcm9tcHQoZGF0YTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgLy8gRm9yIHRpdGxlIGluamVjdGlvbiwgd2UgbmVlZCB0byBjaGVjayB0aGUgbGFzdCBwYXJ0IG9mIHRoZSBvdXRwdXRcbiAgICAvLyBVc2UgbGFzdCAxMDAgY2hhcnMgYXMgY2FjaGUga2V5IHRvIGJhbGFuY2UgY2FjaGUgZWZmaWNpZW5jeSBhbmQgYWNjdXJhY3lcbiAgICBjb25zdCBjYWNoZUtleSA9IGRhdGEuc2xpY2UoLTEwMCk7XG5cbiAgICAvLyBDaGVjayBjYWNoZSBmaXJzdFxuICAgIGlmIChlbmRQcm9tcHRDYWNoZS5oYXMoY2FjaGVLZXkpKSB7XG4gICAgICBjb25zdCBjYWNoZWRSZXN1bHQgPSBlbmRQcm9tcHRDYWNoZS5nZXQoY2FjaGVLZXkpO1xuICAgICAgcmV0dXJuIGNhY2hlZFJlc3VsdCA/PyBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBTdHJpcCBBTlNJIGNvZGVzIGZvciBtb3JlIHJlbGlhYmxlIGRldGVjdGlvblxuICAgIGNvbnN0IGNsZWFuRGF0YSA9IGRhdGEucmVwbGFjZShBTlNJX0VTQ0FQRV9SRUdFWCwgJycpO1xuICAgIGNvbnN0IHJlc3VsdCA9IFVOSUZJRURfUFJPTVBUX0VORF9SRUdFWC50ZXN0KGNsZWFuRGF0YSk7XG5cbiAgICAvLyBDYWNoZSByZXN1bHRcbiAgICBjYWNoZVJlc3VsdChlbmRQcm9tcHRDYWNoZSwgY2FjaGVLZXksIHJlc3VsdCk7XG5cbiAgICBpZiAocmVzdWx0KSB7XG4gICAgICBsb2dnZXIuZGVidWcoJ0RldGVjdGVkIHByb21wdCBhdCBlbmQgb2Ygb3V0cHV0Jyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgc3BlY2lmaWMgc2hlbGwgdHlwZSBiYXNlZCBvbiBwcm9tcHQgcGF0dGVyblxuICAgKiBUaGlzIGNhbiBiZSB1c2VkIGZvciBzaGVsbC1zcGVjaWZpYyBvcHRpbWl6YXRpb25zIGluIHRoZSBmdXR1cmVcbiAgICovXG4gIGV4cG9ydCBmdW5jdGlvbiBnZXRTaGVsbFR5cGUoZGF0YTogc3RyaW5nKToga2V5b2YgdHlwZW9mIFNIRUxMX1NQRUNJRklDX1BBVFRFUk5TIHwgbnVsbCB7XG4gICAgY29uc3QgdHJpbW1lZCA9IGRhdGEudHJpbSgpO1xuXG4gICAgLy8gQ2hlY2sgZWFjaCBzaGVsbCBwYXR0ZXJuXG4gICAgZm9yIChjb25zdCBbc2hlbGwsIHBhdHRlcm5dIG9mIE9iamVjdC5lbnRyaWVzKFNIRUxMX1NQRUNJRklDX1BBVFRFUk5TKSkge1xuICAgICAgaWYgKHBhdHRlcm4udGVzdCh0cmltbWVkKSkge1xuICAgICAgICByZXR1cm4gc2hlbGwgYXMga2V5b2YgdHlwZW9mIFNIRUxMX1NQRUNJRklDX1BBVFRFUk5TO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIEhlbHBlciB0byBjYWNoZSByZXN1bHRzIHdpdGggc2l6ZSBsaW1pdFxuICAgKi9cbiAgZnVuY3Rpb24gY2FjaGVSZXN1bHQoY2FjaGU6IE1hcDxzdHJpbmcsIGJvb2xlYW4+LCBrZXk6IHN0cmluZywgdmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBpZiAoY2FjaGVTaXplID49IE1BWF9DQUNIRV9TSVpFKSB7XG4gICAgICAvLyBDbGVhciBvbGRlc3QgZW50cmllcyB3aGVuIGNhY2hlIGlzIGZ1bGxcbiAgICAgIGNvbnN0IGVudHJpZXNUb0RlbGV0ZSA9IE1hdGguZmxvb3IoTUFYX0NBQ0hFX1NJWkUgKiAwLjIpOyAvLyBDbGVhciAyMCVcbiAgICAgIGNvbnN0IGl0ZXJhdG9yID0gY2FjaGUua2V5cygpO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBlbnRyaWVzVG9EZWxldGU7IGkrKykge1xuICAgICAgICBjb25zdCBrZXlUb0RlbGV0ZSA9IGl0ZXJhdG9yLm5leHQoKS52YWx1ZTtcbiAgICAgICAgaWYgKGtleVRvRGVsZXRlKSB7XG4gICAgICAgICAgY2FjaGUuZGVsZXRlKGtleVRvRGVsZXRlKTtcbiAgICAgICAgICBjYWNoZVNpemUtLTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGNhY2hlLnNldChrZXksIHZhbHVlKTtcbiAgICBjYWNoZVNpemUrKztcbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhciBhbGwgY2FjaGVzICh1c2VmdWwgZm9yIHRlc3RzIG9yIG1lbW9yeSBtYW5hZ2VtZW50KVxuICAgKi9cbiAgZXhwb3J0IGZ1bmN0aW9uIGNsZWFyQ2FjaGUoKTogdm9pZCB7XG4gICAgZW5kUHJvbXB0Q2FjaGUuY2xlYXIoKTtcbiAgICBvbmx5UHJvbXB0Q2FjaGUuY2xlYXIoKTtcbiAgICBjYWNoZVNpemUgPSAwO1xuICAgIGxvZ2dlci5kZWJ1ZygnUHJvbXB0IHBhdHRlcm4gY2FjaGVzIGNsZWFyZWQnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgY2FjaGUgc3RhdGlzdGljcyBmb3IgbW9uaXRvcmluZ1xuICAgKi9cbiAgZXhwb3J0IGZ1bmN0aW9uIGdldENhY2hlU3RhdHMoKToge1xuICAgIHNpemU6IG51bWJlcjtcbiAgICBtYXhTaXplOiBudW1iZXI7XG4gICAgaGl0UmF0ZTogeyBlbmQ6IG51bWJlcjsgb25seTogbnVtYmVyIH07XG4gIH0ge1xuICAgIHJldHVybiB7XG4gICAgICBzaXplOiBjYWNoZVNpemUsXG4gICAgICBtYXhTaXplOiBNQVhfQ0FDSEVfU0laRSxcbiAgICAgIGhpdFJhdGU6IHtcbiAgICAgICAgZW5kOiBlbmRQcm9tcHRDYWNoZS5zaXplLFxuICAgICAgICBvbmx5OiBvbmx5UHJvbXB0Q2FjaGUuc2l6ZSxcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxufVxuXG4vLyBFeHBvcnQgZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHlcbmV4cG9ydCBjb25zdCBpc1Byb21wdE9ubHkgPSBQcm9tcHREZXRlY3Rvci5pc1Byb21wdE9ubHk7XG5leHBvcnQgY29uc3QgZW5kc1dpdGhQcm9tcHQgPSBQcm9tcHREZXRlY3Rvci5lbmRzV2l0aFByb21wdDtcbiJdfQ==