vibetunnel
Version:
Terminal sharing server with web interface - supports macOS, Linux, and headless environments
238 lines • 25.9 kB
JavaScript
;
/**
* Terminal title management utilities
*
* Generates and injects terminal title sequences based on working directory
* and running command.
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateTitleSequence = generateTitleSequence;
exports.extractCdDirectory = extractCdDirectory;
exports.shouldInjectTitle = shouldInjectTitle;
exports.injectTitleIfNeeded = injectTitleIfNeeded;
exports.generateDynamicTitle = generateDynamicTitle;
const os = __importStar(require("os"));
const path = __importStar(require("path"));
const git_js_1 = require("../../shared/utils/git.js");
const prompt_patterns_js_1 = require("./prompt-patterns.js");
// Pre-compiled regex patterns for performance
// Match cd command with optional arguments, handling newlines
// The argument capture group excludes command separators
const CD_REGEX = /^\s*cd(?:\s+([^;&|\n]+?))?(?:\s*[;&|\n]|$)/;
/**
* Generate a terminal title sequence (OSC 2)
*
* @param cwd Current working directory
* @param command Command being run
* @param sessionName Optional session name
* @returns Terminal title escape sequence
*/
function generateTitleSequence(cwd, command, sessionName) {
const homeDir = os.homedir();
const displayPath = cwd.startsWith(homeDir) ? cwd.replace(homeDir, '~') : cwd;
const fullCmd = command[0] || 'shell';
const cmdName = path.basename(fullCmd);
// Check if session name should be used exclusively
if (sessionName?.trim()) {
const trimmedName = sessionName.trim();
// Check if this is NOT an auto-generated name
const isAutoGenerated = trimmedName === `${cmdName} · ${cmdName}` ||
trimmedName === cmdName ||
trimmedName.match(new RegExp(`^${cmdName}\\s*\\(.*\\)$`));
if (!isAutoGenerated) {
// Use only the session name for custom names
return `\x1B]2;${trimmedName}\x07`;
}
}
// Build title parts for auto-generated or no session name
const parts = [displayPath, cmdName];
// For auto-generated names, still add them to the parts
if (sessionName?.trim()) {
const trimmedName = sessionName.trim();
// Skip redundant session names
if (trimmedName === `${cmdName} · ${cmdName}`) {
// Don't add redundant "claude · claude"
}
else if (trimmedName === cmdName) {
// Don't add if session name is just the command name
}
else if (trimmedName.match(new RegExp(`^${cmdName}\\s*\\(.*\\)$`))) {
// Skip auto-generated names like "python3 (~/projects)"
}
else {
// This case shouldn't happen now, but keep for safety
parts.push(trimmedName);
}
}
const title = parts.join(' · ');
// OSC 2 sequence: ESC ] 2 ; <title> BEL
return `\x1B]2;${title}\x07`;
}
/**
* Extract directory change from cd command
*
* @param input The input command string
* @param currentDir Current working directory
* @returns New directory if cd command detected, null otherwise
*/
function extractCdDirectory(input, currentDir) {
const match = input.match(CD_REGEX);
if (!match) {
return null;
}
// Handle cd without arguments (goes to home directory)
if (!match[1]) {
return os.homedir();
}
let targetDir = match[1].trim();
// Remove quotes if present
if ((targetDir.startsWith('"') && targetDir.endsWith('"')) ||
(targetDir.startsWith("'") && targetDir.endsWith("'"))) {
targetDir = targetDir.slice(1, -1);
}
// Handle special cases
if (targetDir === '-') {
// cd - (return to previous directory) - we can't track this accurately
return null;
}
if (!targetDir || targetDir === '~') {
return os.homedir();
}
if (targetDir.startsWith('~/')) {
return path.join(os.homedir(), targetDir.slice(2));
}
// Resolve relative paths
if (!path.isAbsolute(targetDir)) {
return path.resolve(currentDir, targetDir);
}
return targetDir;
}
/**
* Check if we should inject a title update
*
* @param data The terminal output data
* @returns True if this looks like a good time to inject a title
*/
function shouldInjectTitle(data) {
// Use unified prompt detector for consistency and performance
return prompt_patterns_js_1.PromptDetector.endsWithPrompt(data);
}
/**
* Inject title sequence into terminal output if appropriate
*
* @param data The terminal output data
* @param title The title sequence to inject
* @returns Data with title sequence injected if appropriate
*/
function injectTitleIfNeeded(data, title) {
if (shouldInjectTitle(data)) {
// Simply prepend the title sequence
return title + data;
}
return data;
}
/**
* Generate a dynamic terminal title with activity indicators
*
* @param cwd Current working directory
* @param command Command being run
* @param activity Current activity state
* @param sessionName Optional session name
* @param gitRepoPath Optional Git repository path
* @param gitBranch Optional Git branch name
* @returns Terminal title escape sequence
*/
function generateDynamicTitle(cwd, command, activity, sessionName, gitRepoPath, gitBranch) {
const homeDir = os.homedir();
const displayPath = cwd.startsWith(homeDir) ? cwd.replace(homeDir, '~') : cwd;
const fullCmd = command[0] || 'shell';
const cmdName = path.basename(fullCmd);
// Check if session name should be used exclusively
if (sessionName?.trim()) {
const trimmedName = sessionName.trim();
// Check if this is NOT an auto-generated name
const isAutoGenerated = trimmedName === `${cmdName} · ${cmdName}` ||
trimmedName === cmdName ||
trimmedName.match(new RegExp(`^${cmdName}\\s*\\(.*\\)$`));
if (!isAutoGenerated) {
// Use only the session name for custom names
if (activity.specificStatus) {
// Format: status · session name
return `\x1B]2;${activity.specificStatus.status} · ${trimmedName}\x07`;
}
else if (activity.isActive) {
// Format: ● session name
return `\x1B]2;● ${trimmedName}\x07`;
}
else {
// Just the session name when idle
return `\x1B]2;${trimmedName}\x07`;
}
}
}
// Build base parts for auto-generated or no session name
const baseParts = [];
// If in a Git repository, format as repoName-branch instead of full path
if (gitRepoPath && gitBranch) {
const repoName = (0, git_js_1.getBaseRepoName)(gitRepoPath);
baseParts.push(`${repoName}-${gitBranch}`);
}
else {
baseParts.push(displayPath);
}
baseParts.push(cmdName);
// Add session name if provided and auto-generated
if (sessionName?.trim()) {
baseParts.push(sessionName);
}
// If we have specific status, put it first
if (activity.specificStatus) {
// Format: status · repoName-branch/path · command · session name
const title = `${activity.specificStatus.status} · ${baseParts.join(' · ')}`;
return `\x1B]2;${title}\x07`;
}
// Otherwise use generic activity indicator (only when active)
if (activity.isActive) {
// Format: ● repoName-branch/path · command · session name
const title = `● ${baseParts.join(' · ')}`;
return `\x1B]2;${title}\x07`;
}
// When idle, no indicator - just repoName-branch/path · command · session name
const title = baseParts.join(' · ');
// OSC 2 sequence: ESC ] 2 ; <title> BEL
return `\x1B]2;${title}\x07`;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVybWluYWwtdGl0bGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VydmVyL3V0aWxzL3Rlcm1pbmFsLXRpdGxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7R0FLRzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFxQkgsc0RBa0RDO0FBU0QsZ0RBMENDO0FBUUQsOENBR0M7QUFTRCxrREFPQztBQWFELG9EQTJFQztBQTNPRCx1Q0FBeUI7QUFDekIsMkNBQTZCO0FBQzdCLHNEQUE0RDtBQUU1RCw2REFBc0Q7QUFFdEQsOENBQThDO0FBQzlDLDhEQUE4RDtBQUM5RCx5REFBeUQ7QUFDekQsTUFBTSxRQUFRLEdBQUcsNENBQTRDLENBQUM7QUFFOUQ7Ozs7Ozs7R0FPRztBQUNILFNBQWdCLHFCQUFxQixDQUNuQyxHQUFXLEVBQ1gsT0FBaUIsRUFDakIsV0FBb0I7SUFFcEIsTUFBTSxPQUFPLEdBQUcsRUFBRSxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQzdCLE1BQU0sV0FBVyxHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7SUFDOUUsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLE9BQU8sQ0FBQztJQUN0QyxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBRXZDLG1EQUFtRDtJQUNuRCxJQUFJLFdBQVcsRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDO1FBQ3hCLE1BQU0sV0FBVyxHQUFHLFdBQVcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUV2Qyw4Q0FBOEM7UUFDOUMsTUFBTSxlQUFlLEdBQ25CLFdBQVcsS0FBSyxHQUFHLE9BQU8sTUFBTSxPQUFPLEVBQUU7WUFD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QUksQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUM5QixDQUFDO0lBRUQsMkNBQTJDO0lBQzNDLElBQUksUUFBUSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQzVCLGlFQUFpRTtRQUNqRSxNQUFNLEtBQUssR0FBRyxHQUFHLFFBQVEsQ0FBQyxjQUFjLENBQUMsTUFBTSxNQUFNLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUM3RSxPQUFPLFVBQVUsS0FBSyxNQUFNLENBQUM7SUFDL0IsQ0FBQztJQUVELDhEQUE4RDtJQUM5RCxJQUFJLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUN0QiwwREFBMEQ7UUFDMUQsTUFBTSxLQUFLLEdBQUcsS0FBSyxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDM0MsT0FBTyxVQUFVLEtBQUssTUFBTSxDQUFDO0lBQy9CLENBQUM7SUFFRCwrRUFBK0U7SUFDL0UsTUFBTSxLQUFLLEdBQUcsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUVwQyx3Q0FBd0M7SUFDeEMsT0FBTyxVQUFVLEtBQUssTUFBTSxDQUFDO0FBQy9CLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFRlcm1pbmFsIHRpdGxlIG1hbmFnZW1lbnQgdXRpbGl0aWVzXG4gKlxuICogR2VuZXJhdGVzIGFuZCBpbmplY3RzIHRlcm1pbmFsIHRpdGxlIHNlcXVlbmNlcyBiYXNlZCBvbiB3b3JraW5nIGRpcmVjdG9yeVxuICogYW5kIHJ1bm5pbmcgY29tbWFuZC5cbiAqL1xuXG5pbXBvcnQgKiBhcyBvcyBmcm9tICdvcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgZ2V0QmFzZVJlcG9OYW1lIH0gZnJvbSAnLi4vLi4vc2hhcmVkL3V0aWxzL2dpdC5qcyc7XG5pbXBvcnQgdHlwZSB7IEFjdGl2aXR5U3RhdGUgfSBmcm9tICcuL2FjdGl2aXR5LWRldGVjdG9yLmpzJztcbmltcG9ydCB7IFByb21wdERldGVjdG9yIH0gZnJvbSAnLi9wcm9tcHQtcGF0dGVybnMuanMnO1xuXG4vLyBQcmUtY29tcGlsZWQgcmVnZXggcGF0dGVybnMgZm9yIHBlcmZvcm1hbmNlXG4vLyBNYXRjaCBjZCBjb21tYW5kIHdpdGggb3B0aW9uYWwgYXJndW1lbnRzLCBoYW5kbGluZyBuZXdsaW5lc1xuLy8gVGhlIGFyZ3VtZW50IGNhcHR1cmUgZ3JvdXAgZXhjbHVkZXMgY29tbWFuZCBzZXBhcmF0b3JzXG5jb25zdCBDRF9SRUdFWCA9IC9eXFxzKmNkKD86XFxzKyhbXjsmfFxcbl0rPykpPyg/OlxccypbOyZ8XFxuXXwkKS87XG5cbi8qKlxuICogR2VuZXJhdGUgYSB0ZXJtaW5hbCB0aXRsZSBzZXF1ZW5jZSAoT1NDIDIpXG4gKlxuICogQHBhcmFtIGN3ZCBDdXJyZW50IHdvcmtpbmcgZGlyZWN0b3J5XG4gKiBAcGFyYW0gY29tbWFuZCBDb21tYW5kIGJlaW5nIHJ1blxuICogQHBhcmFtIHNlc3Npb25OYW1lIE9wdGlvbmFsIHNlc3Npb24gbmFtZVxuICogQHJldHVybnMgVGVybWluYWwgdGl0bGUgZXNjYXBlIHNlcXVlbmNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZVRpdGxlU2VxdWVuY2UoXG4gIGN3ZDogc3RyaW5nLFxuICBjb21tYW5kOiBzdHJpbmdbXSxcbiAgc2Vzc2lvbk5hbWU/OiBzdHJpbmdcbik6IHN0cmluZyB7XG4gIGNvbnN0IGhvbWVEaXIgPSBvcy5ob21lZGlyKCk7XG4gIGNvbnN0IGRpc3BsYXlQYXRoID0gY3dkLnN0YXJ0c1dpdGgoaG9tZURpcikgPyBjd2QucmVwbGFjZShob21lRGlyLCAnficpIDogY3dkO1xuICBjb25zdCBmdWxsQ21kID0gY29tbWFuZFswXSB8fCAnc2hlbGwnO1xuICBjb25zdCBjbWROYW1lID0gcGF0aC5iYXNlbmFtZShmdWxsQ21kKTtcblxuICAvLyBDaGVjayBpZiBzZXNzaW9uIG5hbWUgc2hvdWxkIGJlIHVzZWQgZXhjbHVzaXZlbHlcbiAgaWYgKHNlc3Npb25OYW1lPy50cmltKCkpIHtcbiAgICBjb25zdCB0cmltbWVkTmFtZSA9IHNlc3Npb25OYW1lLnRyaW0oKTtcblxuICAgIC8vIENoZWNrIGlmIHRoaXMgaXMgTk9UIGFuIGF1dG8tZ2VuZXJhdGVkIG5hbWVcbiAgICBjb25zdCBpc0F1dG9HZW5lcmF0ZWQgPVxuICAgICAgdHJpbW1lZE5hbWUgPT09IGAke2NtZE5hbWV9IMK3ICR7Y21kTmFtZX1gIHx8XG4gICAgICB0cmltbWVkTmFtZSA9PT0gY21kTmFtZSB8fFxuICAgICAgdHJpbW1lZE5hbWUubWF0Y2gobmV3IFJlZ0V4cChgXiR7Y21kTmFtZX1cXFxccypcXFxcKC4qXFxcXCkkYCkpO1xuXG4gICAgaWYgKCFpc0F1dG9HZW5lcmF0ZWQpIHtcbiAgICAgIC8vIFVzZSBvbmx5IHRoZSBzZXNzaW9uIG5hbWUgZm9yIGN1c3RvbSBuYW1lc1xuICAgICAgcmV0dXJuIGBcXHgxQl0yOyR7dHJpbW1lZE5hbWV9XFx4MDdgO1xuICAgIH1cbiAgfVxuXG4gIC8vIEJ1aWxkIHRpdGxlIHBhcnRzIGZvciBhdXRvLWdlbmVyYXRlZCBvciBubyBzZXNzaW9uIG5hbWVcbiAgY29uc3QgcGFydHMgPSBbZGlzcGxheVBhdGgsIGNtZE5hbWVdO1xuXG4gIC8vIEZvciBhdXRvLWdlbmVyYXRlZCBuYW1lcywgc3RpbGwgYWRkIHRoZW0gdG8gdGhlIHBhcnRzXG4gIGlmIChzZXNzaW9uTmFtZT8udHJpbSgpKSB7XG4gICAgY29uc3QgdHJpbW1lZE5hbWUgPSBzZXNzaW9uTmFtZS50cmltKCk7XG5cbiAgICAvLyBTa2lwIHJlZHVuZGFudCBzZXNzaW9uIG5hbWVzXG4gICAgaWYgKHRyaW1tZWROYW1lID09PSBgJHtjbWROYW1lfSDCtyAke2NtZE5hbWV9YCkge1xuICAgICAgLy8gRG9uJ3QgYWRkIHJlZHVuZGFudCBcImNsYXVkZSDCtyBjbGF1ZGVcIlxuICAgIH0gZWxzZSBpZiAodHJpbW1lZE5hbWUgPT09IGNtZE5hbWUpIHtcbiAgICAgIC8vIERvbid0IGFkZCBpZiBzZXNzaW9uIG5hbWUgaXMganVzdCB0aGUgY29tbWFuZCBuYW1lXG4gICAgfSBlbHNlIGlmICh0cmltbWVkTmFtZS5tYXRjaChuZXcgUmVnRXhwKGBeJHtjbWROYW1lfVxcXFxzKlxcXFwoLipcXFxcKSRgKSkpIHtcbiAgICAgIC8vIFNraXAgYXV0by1nZW5lcmF0ZWQgbmFtZXMgbGlrZSBcInB5dGhvbjMgKH4vcHJvamVjdHMpXCJcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gVGhpcyBjYXNlIHNob3VsZG4ndCBoYXBwZW4gbm93LCBidXQga2VlcCBmb3Igc2FmZXR5XG4gICAgICBwYXJ0cy5wdXNoKHRyaW1tZWROYW1lKTtcbiAgICB9XG4gIH1cblxuICBjb25zdCB0aXRsZSA9IHBhcnRzLmpvaW4oJyDCtyAnKTtcblxuICAvLyBPU0MgMiBzZXF1ZW5jZTogRVNDIF0gMiA7IDx0aXRsZT4gQkVMXG4gIHJldHVybiBgXFx4MUJdMjske3RpdGxlfVxceDA3YDtcbn1cblxuLyoqXG4gKiBFeHRyYWN0IGRpcmVjdG9yeSBjaGFuZ2UgZnJvbSBjZCBjb21tYW5kXG4gKlxuICogQHBhcmFtIGlucHV0IFRoZSBpbnB1dCBjb21tYW5kIHN0cmluZ1xuICogQHBhcmFtIGN1cnJlbnREaXIgQ3VycmVudCB3b3JraW5nIGRpcmVjdG9yeVxuICogQHJldHVybnMgTmV3IGRpcmVjdG9yeSBpZiBjZCBjb21tYW5kIGRldGVjdGVkLCBudWxsIG90aGVyd2lzZVxuICovXG5leHBvcnQgZnVuY3Rpb24gZXh0cmFjdENkRGlyZWN0b3J5KGlucHV0OiBzdHJpbmcsIGN1cnJlbnREaXI6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xuICBjb25zdCBtYXRjaCA9IGlucHV0Lm1hdGNoKENEX1JFR0VYKTtcblxuICBpZiAoIW1hdGNoKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvLyBIYW5kbGUgY2Qgd2l0aG91dCBhcmd1bWVudHMgKGdvZXMgdG8gaG9tZSBkaXJlY3RvcnkpXG4gIGlmICghbWF0Y2hbMV0pIHtcbiAgICByZXR1cm4gb3MuaG9tZWRpcigpO1xuICB9XG5cbiAgbGV0IHRhcmdldERpciA9IG1hdGNoWzFdLnRyaW0oKTtcblxuICAvLyBSZW1vdmUgcXVvdGVzIGlmIHByZXNlbnRcbiAgaWYgKFxuICAgICh0YXJnZXREaXIuc3RhcnRzV2l0aCgnXCInKSAmJiB0YXJnZXREaXIuZW5kc1dpdGgoJ1wiJykpIHx8XG4gICAgKHRhcmdldERpci5zdGFydHNXaXRoKFwiJ1wiKSAmJiB0YXJnZXREaXIuZW5kc1dpdGgoXCInXCIpKVxuICApIHtcbiAgICB0YXJnZXREaXIgPSB0YXJnZXREaXIuc2xpY2UoMSwgLTEpO1xuICB9XG5cbiAgLy8gSGFuZGxlIHNwZWNpYWwgY2FzZXNcbiAgaWYgKHRhcmdldERpciA9PT0gJy0nKSB7XG4gICAgLy8gY2QgLSAocmV0dXJuIHRvIHByZXZpb3VzIGRpcmVjdG9yeSkgLSB3ZSBjYW4ndCB0cmFjayB0aGlzIGFjY3VyYXRlbHlcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGlmICghdGFyZ2V0RGlyIHx8IHRhcmdldERpciA9PT0gJ34nKSB7XG4gICAgcmV0dXJuIG9zLmhvbWVkaXIoKTtcbiAgfVxuXG4gIGlmICh0YXJnZXREaXIuc3RhcnRzV2l0aCgnfi8nKSkge1xuICAgIHJldHVybiBwYXRoLmpvaW4ob3MuaG9tZWRpcigpLCB0YXJnZXREaXIuc2xpY2UoMikpO1xuICB9XG5cbiAgLy8gUmVzb2x2ZSByZWxhdGl2ZSBwYXRoc1xuICBpZiAoIXBhdGguaXNBYnNvbHV0ZSh0YXJnZXREaXIpKSB7XG4gICAgcmV0dXJuIHBhdGgucmVzb2x2ZShjdXJyZW50RGlyLCB0YXJnZXREaXIpO1xuICB9XG5cbiAgcmV0dXJuIHRhcmdldERpcjtcbn1cblxuLyoqXG4gKiBDaGVjayBpZiB3ZSBzaG91bGQgaW5qZWN0IGEgdGl0bGUgdXBkYXRlXG4gKlxuICogQHBhcmFtIGRhdGEgVGhlIHRlcm1pbmFsIG91dHB1dCBkYXRhXG4gKiBAcmV0dXJucyBUcnVlIGlmIHRoaXMgbG9va3MgbGlrZSBhIGdvb2QgdGltZSB0byBpbmplY3QgYSB0aXRsZVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2hvdWxkSW5qZWN0VGl0bGUoZGF0YTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIC8vIFVzZSB1bmlmaWVkIHByb21wdCBkZXRlY3RvciBmb3IgY29uc2lzdGVuY3kgYW5kIHBlcmZvcm1hbmNlXG4gIHJldHVybiBQcm9tcHREZXRlY3Rvci5lbmRzV2l0aFByb21wdChkYXRhKTtcbn1cblxuLyoqXG4gKiBJbmplY3QgdGl0bGUgc2VxdWVuY2UgaW50byB0ZXJtaW5hbCBvdXRwdXQgaWYgYXBwcm9wcmlhdGVcbiAqXG4gKiBAcGFyYW0gZGF0YSBUaGUgdGVybWluYWwgb3V0cHV0IGRhdGFcbiAqIEBwYXJhbSB0aXRsZSBUaGUgdGl0bGUgc2VxdWVuY2UgdG8gaW5qZWN0XG4gKiBAcmV0dXJucyBEYXRhIHdpdGggdGl0bGUgc2VxdWVuY2UgaW5qZWN0ZWQgaWYgYXBwcm9wcmlhdGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluamVjdFRpdGxlSWZOZWVkZWQoZGF0YTogc3RyaW5nLCB0aXRsZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKHNob3VsZEluamVjdFRpdGxlKGRhdGEpKSB7XG4gICAgLy8gU2ltcGx5IHByZXBlbmQgdGhlIHRpdGxlIHNlcXVlbmNlXG4gICAgcmV0dXJuIHRpdGxlICsgZGF0YTtcbiAgfVxuXG4gIHJldHVybiBkYXRhO1xufVxuXG4vKipcbiAqIEdlbmVyYXRlIGEgZHluYW1pYyB0ZXJtaW5hbCB0aXRsZSB3aXRoIGFjdGl2aXR5IGluZGljYXRvcnNcbiAqXG4gKiBAcGFyYW0gY3dkIEN1cnJlbnQgd29ya2luZyBkaXJlY3RvcnlcbiAqIEBwYXJhbSBjb21tYW5kIENvbW1hbmQgYmVpbmcgcnVuXG4gKiBAcGFyYW0gYWN0aXZpdHkgQ3VycmVudCBhY3Rpdml0eSBzdGF0ZVxuICogQHBhcmFtIHNlc3Npb25OYW1lIE9wdGlvbmFsIHNlc3Npb24gbmFtZVxuICogQHBhcmFtIGdpdFJlcG9QYXRoIE9wdGlvbmFsIEdpdCByZXBvc2l0b3J5IHBhdGhcbiAqIEBwYXJhbSBnaXRCcmFuY2ggT3B0aW9uYWwgR2l0IGJyYW5jaCBuYW1lXG4gKiBAcmV0dXJucyBUZXJtaW5hbCB0aXRsZSBlc2NhcGUgc2VxdWVuY2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlRHluYW1pY1RpdGxlKFxuICBjd2Q6IHN0cmluZyxcbiAgY29tbWFuZDogc3RyaW5nW10sXG4gIGFjdGl2aXR5OiBBY3Rpdml0eVN0YXRlLFxuICBzZXNzaW9uTmFtZT86IHN0cmluZyxcbiAgZ2l0UmVwb1BhdGg/OiBzdHJpbmcsXG4gIGdpdEJyYW5jaD86IHN0cmluZ1xuKTogc3RyaW5nIHtcbiAgY29uc3QgaG9tZURpciA9IG9zLmhvbWVkaXIoKTtcbiAgY29uc3QgZGlzcGxheVBhdGggPSBjd2Quc3RhcnRzV2l0aChob21lRGlyKSA/IGN3ZC5yZXBsYWNlKGhvbWVEaXIsICd+JykgOiBjd2Q7XG4gIGNvbnN0IGZ1bGxDbWQgPSBjb21tYW5kWzBdIHx8ICdzaGVsbCc7XG4gIGNvbnN0IGNtZE5hbWUgPSBwYXRoLmJhc2VuYW1lKGZ1bGxDbWQpO1xuXG4gIC8vIENoZWNrIGlmIHNlc3Npb24gbmFtZSBzaG91bGQgYmUgdXNlZCBleGNsdXNpdmVseVxuICBpZiAoc2Vzc2lvbk5hbWU/LnRyaW0oKSkge1xuICAgIGNvbnN0IHRyaW1tZWROYW1lID0gc2Vzc2lvbk5hbWUudHJpbSgpO1xuXG4gICAgLy8gQ2hlY2sgaWYgdGhpcyBpcyBOT1QgYW4gYXV0by1nZW5lcmF0ZWQgbmFtZVxuICAgIGNvbnN0IGlzQXV0b0dlbmVyYXRlZCA9XG4gICAgICB0cmltbWVkTmFtZSA9PT0gYCR7Y21kTmFtZX0gwrcgJHtjbWROYW1lfWAgfHxcbiAgICAgIHRyaW1tZWROYW1lID09PSBjbWROYW1lIHx8XG4gICAgICB0cmltbWVkTmFtZS5tYXRjaChuZXcgUmVnRXhwKGBeJHtjbWROYW1lfVxcXFxzKlxcXFwoLipcXFxcKSRgKSk7XG5cbiAgICBpZiAoIWlzQXV0b0dlbmVyYXRlZCkge1xuICAgICAgLy8gVXNlIG9ubHkgdGhlIHNlc3Npb24gbmFtZSBmb3IgY3VzdG9tIG5hbWVzXG4gICAgICBpZiAoYWN0aXZpdHkuc3BlY2lmaWNTdGF0dXMpIHtcbiAgICAgICAgLy8gRm9ybWF0OiBzdGF0dXMgwrcgc2Vzc2lvbiBuYW1lXG4gICAgICAgIHJldHVybiBgXFx4MUJdMjske2FjdGl2aXR5LnNwZWNpZmljU3RhdHVzLnN0YXR1c30gwrcgJHt0cmltbWVkTmFtZX1cXHgwN2A7XG4gICAgICB9IGVsc2UgaWYgKGFjdGl2aXR5LmlzQWN0aXZlKSB7XG4gICAgICAgIC8vIEZvcm1hdDog4pePIHNlc3Npb24gbmFtZVxuICAgICAgICByZXR1cm4gYFxceDFCXTI74pePICR7dHJpbW1lZE5hbWV9XFx4MDdgO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gSnVzdCB0aGUgc2Vzc2lvbiBuYW1lIHdoZW4gaWRsZVxuICAgICAgICByZXR1cm4gYFxceDFCXTI7JHt0cmltbWVkTmFtZX1cXHgwN2A7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gQnVpbGQgYmFzZSBwYXJ0cyBmb3IgYXV0by1nZW5lcmF0ZWQgb3Igbm8gc2Vzc2lvbiBuYW1lXG4gIGNvbnN0IGJhc2VQYXJ0cyA9IFtdO1xuXG4gIC8vIElmIGluIGEgR2l0IHJlcG9zaXRvcnksIGZvcm1hdCBhcyByZXBvTmFtZS1icmFuY2ggaW5zdGVhZCBvZiBmdWxsIHBhdGhcbiAgaWYgKGdpdFJlcG9QYXRoICYmIGdpdEJyYW5jaCkge1xuICAgIGNvbnN0IHJlcG9OYW1lID0gZ2V0QmFzZVJlcG9OYW1lKGdpdFJlcG9QYXRoKTtcbiAgICBiYXNlUGFydHMucHVzaChgJHtyZXBvTmFtZX0tJHtnaXRCcmFuY2h9YCk7XG4gIH0gZWxzZSB7XG4gICAgYmFzZVBhcnRzLnB1c2goZGlzcGxheVBhdGgpO1xuICB9XG5cbiAgYmFzZVBhcnRzLnB1c2goY21kTmFtZSk7XG5cbiAgLy8gQWRkIHNlc3Npb24gbmFtZSBpZiBwcm92aWRlZCBhbmQgYXV0by1nZW5lcmF0ZWRcbiAgaWYgKHNlc3Npb25OYW1lPy50cmltKCkpIHtcbiAgICBiYXNlUGFydHMucHVzaChzZXNzaW9uTmFtZSk7XG4gIH1cblxuICAvLyBJZiB3ZSBoYXZlIHNwZWNpZmljIHN0YXR1cywgcHV0IGl0IGZpcnN0XG4gIGlmIChhY3Rpdml0eS5zcGVjaWZpY1N0YXR1cykge1xuICAgIC8vIEZvcm1hdDogc3RhdHVzIMK3IHJlcG9OYW1lLWJyYW5jaC9wYXRoIMK3IGNvbW1hbmQgwrcgc2Vzc2lvbiBuYW1lXG4gICAgY29uc3QgdGl0bGUgPSBgJHthY3Rpdml0eS5zcGVjaWZpY1N0YXR1cy5zdGF0dXN9IMK3ICR7YmFzZVBhcnRzLmpvaW4oJyDCtyAnKX1gO1xuICAgIHJldHVybiBgXFx4MUJdMjske3RpdGxlfVxceDA3YDtcbiAgfVxuXG4gIC8vIE90aGVyd2lzZSB1c2UgZ2VuZXJpYyBhY3Rpdml0eSBpbmRpY2F0b3IgKG9ubHkgd2hlbiBhY3RpdmUpXG4gIGlmIChhY3Rpdml0eS5pc0FjdGl2ZSkge1xuICAgIC8vIEZvcm1hdDog4pePIHJlcG9OYW1lLWJyYW5jaC9wYXRoIMK3IGNvbW1hbmQgwrcgc2Vzc2lvbiBuYW1lXG4gICAgY29uc3QgdGl0bGUgPSBg4pePICR7YmFzZVBhcnRzLmpvaW4oJyDCtyAnKX1gO1xuICAgIHJldHVybiBgXFx4MUJdMjske3RpdGxlfVxceDA3YDtcbiAgfVxuXG4gIC8vIFdoZW4gaWRsZSwgbm8gaW5kaWNhdG9yIC0ganVzdCByZXBvTmFtZS1icmFuY2gvcGF0aCDCtyBjb21tYW5kIMK3IHNlc3Npb24gbmFtZVxuICBjb25zdCB0aXRsZSA9IGJhc2VQYXJ0cy5qb2luKCcgwrcgJyk7XG5cbiAgLy8gT1NDIDIgc2VxdWVuY2U6IEVTQyBdIDIgOyA8dGl0bGU+IEJFTFxuICByZXR1cm4gYFxceDFCXTI7JHt0aXRsZX1cXHgwN2A7XG59XG4iXX0=