@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.
321 lines • 34.5 kB
JavaScript
/**
* Friendly session names drawn from famous puppets, marionettes,
* and puppet characters throughout history.
*
* Names are assigned from a pool and returned after a cooldown period
* when sessions end. This keeps the active session list human-readable
* and on-brand for DollhouseMCP.
*
* @since v2.1.0 — Issue #1700
*/
import { randomInt } from 'node:crypto';
import { logger } from '../../utils/logger.js';
/**
* Famous puppets, marionettes, and puppet characters from around the world.
* Order doesn't matter — the pool is shuffled on startup.
*/
export const ALL_PUPPET_NAMES = [
// Classic & traditional
'Punch',
'Judy',
'Pinocchio',
'Petrouchka',
'Pulcinella',
'Guignol',
'Kasperle',
// Muppets & Jim Henson
'Kermit',
'Piggy',
'Fozzie',
'Gonzo',
'Scooter',
'Rowlf',
'Waldorf',
'Statler',
// Kukla, Fran and Ollie
'Kukla',
'Ollie',
// Howdy Doody era
'Howdy',
'Clarabell',
// Sesame Street
'Grover',
'Elmo',
'Ernie',
'Bert',
'Oscar',
// Ventriloquist & variety
'Mortimer',
'Lambchop',
'Madame',
'Topo',
// International puppetry
'Bunraku',
'Wayang',
'Petrushka',
'Hanneschen',
'Vitezslav',
// Modern & pop culture
'Salem',
'Triumph',
'Peanut',
'Achmed',
// Marionette traditions
'Fantoccini',
'Saltimbanque',
'Burattino',
'Harlequin',
// Dollhouse (TV series)
'Echo',
// Inside jokes
'Spike',
'Angel',
// Classic dolls
'Barbie',
'Ken',
'Skipper',
'Midge',
'Christie',
'Annie',
'Andy',
'Cathy',
'Teddy',
'Xavier',
'Strawberry',
'Blythe',
'Ginny',
'Betsy',
'Madeline',
];
/** Names that can never be assigned to a leader session */
const FOLLOWER_ONLY_NAMES = new Set(['Punch']);
/** Fisher-Yates shuffle using crypto.randomInt (unbiased, no modulo) */
function shuffleArray(arr) {
for (let i = arr.length - 1; i > 0; i--) {
const j = randomInt(i + 1);
[arr[i], arr[j]] = [arr[j], arr[i]];
}
return arr;
}
/** Shuffled copy of the name pool — randomized on each process start */
const PUPPET_NAMES = shuffleArray([...ALL_PUPPET_NAMES]);
/**
* Iconic attire and accessories drawn from famous dolls, puppets, and
* theatrical characters throughout history. Used to name console tokens
* so they never collide with the session puppet-name pool (#1871).
*
* Names evoke costume pieces — a token is something you wear or carry,
* not a person.
*/
export const ALL_TOKEN_NAMES = [
// Victorian & theatrical
'Top Hat',
'Monocle',
'Trench Coat',
'Opera Cape',
'Opera Gloves',
'Velvet Cloak',
'Lace Collar',
'Silk Cravat',
'Waistcoat',
'Gilt Button',
// Phantom, masks, mystery
'Half Mask',
'Domino Mask',
'Feathered Mask',
// Punch & Judy / Harlequin
'Jester Bells',
'Diamond Suit',
'Bell Cap',
'Slapstick',
'Red Nose',
// Puppet traditions
'Marionette Strings',
'Cracked Porcelain',
'Papier-Mâché',
// Classic dolls & characters
'Pink Corvette',
'Red Yarn Hair',
'Sailor Suit',
'Yellow Hat',
'Ruby Slippers',
'Glass Slipper',
'Blue Ribbon',
'Striped Stockings',
// Wizard / witch / fantasy
'Pointed Hat',
'Broomstick',
'Silver Wand',
'Tin Crown',
'Straw Hat',
// Adventure & mystery
'Deerstalker',
'Magnifying Glass',
'Feathered Cap',
'Silver Buckle',
'Wicker Basket',
];
/**
* Pick a random token name from the attire pool.
* Used by the console token module to name newly created tokens (#1871).
* Drawn from a separate pool to avoid collision with session puppet names.
*/
export function pickRandomTokenName() {
return ALL_TOKEN_NAMES[randomInt(ALL_TOKEN_NAMES.length)];
}
/**
* Canonical colors for each puppet character.
* Adjusted from true canonical colors for UI readability in both light/dark themes.
*/
const PUPPET_COLORS = {
'Punch': '#DC143C', // crimson red costume
'Judy': '#1E90FF', // blue dress
'Pinocchio': '#DAA520', // goldenrod (wooden, yellow hat)
'Petrouchka': '#B0BEC5', // blue-gray (white costume, adjusted for visibility)
'Pulcinella': '#90A4AE', // gray-blue (white costume, adjusted)
'Guignol': '#8B4513', // saddle brown
'Kasperle': '#FF0000', // red pointed cap
'Kermit': '#4CAF50', // green frog
'Piggy': '#E91E8C', // hot pink (glamorous pig)
'Fozzie': '#CC7722', // ochre brown bear
'Gonzo': '#4169E1', // royal blue
'Scooter': '#FF8C00', // dark orange
'Rowlf': '#8B6914', // dark goldenrod brown dog
'Waldorf': '#556B2F', // dark olive green
'Statler': '#708090', // slate gray
'Kukla': '#FF0000', // red nose and costume
'Ollie': '#228B22', // forest green dragon
'Howdy': '#E2725B', // terra cotta
'Clarabell': '#FFCC00', // bright yellow clown
'Grover': '#4682B4', // steel blue
'Elmo': '#FF2400', // scarlet red
'Ernie': '#F4A460', // sandy brown
'Bert': '#FFD700', // gold yellow
'Oscar': '#6B8E23', // olive drab green
'Mortimer': '#DEB887', // burlywood
'Lambchop': '#D4C5A9', // warm cream (adjusted from pure white)
'Madame': '#800080', // purple
'Topo': '#A0A0A0', // silver gray
'Bunraku': '#B22222', // firebrick red
'Wayang': '#6B4226', // dark leather brown (lightened for visibility)
'Petrushka': '#FF4500', // orange red
'Hanneschen': '#CD5C5C', // indian red
'Vitezslav': '#B8860B', // dark goldenrod
'Salem': '#4A4A4A', // dark gray (black cat, lightened for visibility)
'Triumph': '#6F4E37', // coffee brown
'Peanut': '#9370DB', // medium purple
'Achmed': '#C8BFA9', // bone/parchment (lightened from beige)
'Fantoccini': '#C41E3A', // cardinal red
'Saltimbanque': '#DAA520', // goldenrod
'Burattino': '#D2691E', // chocolate brown
'Harlequin': '#E60026', // diamond red
'Echo': '#5C6370', // slate (dark attire, lightened for visibility)
'Spike': '#E8DCC8', // platinum/bleach (lightened for readability)
'Angel': '#3D3D3D', // charcoal (black duster, lightened for visibility)
// Classic dolls
'Barbie': '#E91E90', // Barbie pink
'Ken': '#4A90D9', // Ken blue
'Skipper': '#FF6B6B', // coral red
'Midge': '#E87040', // warm auburn
'Christie': '#C06030', // warm brown
'Annie': '#E03030', // Raggedy Ann red yarn hair
'Andy': '#3070C0', // Raggedy Andy blue sailor outfit
'Cathy': '#D4A574', // Chatty Cathy vintage tan
'Teddy': '#A0784A', // Teddy Ruxpin bear brown
'Xavier': '#5AAF4A', // Xavier Roberts / Cabbage Patch green
'Strawberry': '#E8445A', // strawberry red-pink
'Blythe': '#7B68EE', // big-eyed purple
'Ginny': '#5B9BD5', // classic blue dress
'Betsy': '#DD7694', // rose pink
'Madeline': '#FFD700', // yellow hat
};
/** Cooldown period before a released name can be reused (ms) */
const NAME_COOLDOWN_MS = 5 * 60_000; // 5 minutes
/**
* Manages friendly session name assignment from the puppet name pool.
*/
export class SessionNamePool {
/** Names currently assigned to active sessions: sessionId → name */
assigned = new Map();
/** Reverse lookup: name → sessionId */
nameToSession = new Map();
/** Names in cooldown after session end */
cooldown = [];
/**
* Assign a friendly name to a session.
* Returns an existing assignment if the session already has one.
*
* @param isLeader - If true, follower-only names (e.g., Punch) are excluded
*/
assign(sessionId, isLeader = false) {
// Already assigned?
const existing = this.assigned.get(sessionId);
if (existing)
return existing;
// Flush expired cooldowns
this.flushCooldowns();
// Find an available name, respecting leader restrictions
const cooldownNames = new Set(this.cooldown.map(c => c.name));
const availableName = PUPPET_NAMES.find(name => !this.nameToSession.has(name) &&
!cooldownNames.has(name) &&
!(isLeader && FOLLOWER_ONLY_NAMES.has(name)));
if (availableName) {
this.assigned.set(sessionId, availableName);
this.nameToSession.set(availableName, sessionId);
logger.debug(`[SessionNames] Assigned '${availableName}' to ${sessionId}`);
return availableName;
}
// All names in use or cooling down — try cooldown names (oldest first)
if (this.cooldown.length > 0) {
const oldest = this.cooldown.shift();
this.assigned.set(sessionId, oldest.name);
this.nameToSession.set(oldest.name, sessionId);
logger.debug(`[SessionNames] Assigned '${oldest.name}' to ${sessionId} (early cooldown release)`);
return oldest.name;
}
// Truly exhausted — fall back to truncated session ID
const fallback = sessionId.split('-')[1] || sessionId.slice(0, 8);
this.assigned.set(sessionId, fallback);
logger.warn(`[SessionNames] Name pool exhausted, using fallback '${fallback}' for ${sessionId}`);
return fallback;
}
/**
* Release a name back to the pool with a cooldown period.
*/
release(sessionId) {
const name = this.assigned.get(sessionId);
if (!name)
return;
this.assigned.delete(sessionId);
this.nameToSession.delete(name);
// Only cooldown puppet names, not fallback IDs
if (PUPPET_NAMES.includes(name)) {
this.cooldown.push({ name, releasedAt: Date.now() });
}
logger.debug(`[SessionNames] Released '${name}' from ${sessionId} (cooldown ${NAME_COOLDOWN_MS / 1000}s)`);
}
/**
* Get the friendly name for a session, or undefined if not assigned.
*/
getName(sessionId) {
return this.assigned.get(sessionId);
}
/**
* Get the canonical color for an assigned session name.
*/
getColor(sessionId) {
const name = this.assigned.get(sessionId);
return name ? (PUPPET_COLORS[name] ?? undefined) : undefined;
}
/**
* Get all current assignments.
*/
getAll() {
return new Map(this.assigned);
}
flushCooldowns() {
const now = Date.now();
this.cooldown = this.cooldown.filter(c => (now - c.releasedAt) < NAME_COOLDOWN_MS);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2Vzc2lvbk5hbWVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3dlYi9jb25zb2xlL1Nlc3Npb25OYW1lcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7O0dBU0c7QUFFSCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUUvQzs7O0dBR0c7QUFDSCxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBc0I7SUFDakQsd0JBQXdCO0lBQ3hCLE9BQU87SUFDUCxNQUFNO0lBQ04sV0FBVztJQUNYLFlBQVk7SUFDWixZQUFZO0lBQ1osU0FBUztJQUNULFVBQVU7SUFFVix1QkFBdUI7SUFDdkIsUUFBUTtJQUNSLE9BQU87SUFDUCxRQUFRO0lBQ1IsT0FBTztJQUNQLFNBQVM7SUFDVCxPQUFPO0lBQ1AsU0FBUztJQUNULFNBQVM7SUFFVCx3QkFBd0I7SUFDeEIsT0FBTztJQUNQLE9BQU87SUFFUCxrQkFBa0I7SUFDbEIsT0FBTztJQUNQLFdBQVc7SUFFWCxnQkFBZ0I7SUFDaEIsUUFBUTtJQUNSLE1BQU07SUFDTixPQUFPO0lBQ1AsTUFBTTtJQUNOLE9BQU87SUFFUCwwQkFBMEI7SUFDMUIsVUFBVTtJQUNWLFVBQVU7SUFDVixRQUFRO0lBQ1IsTUFBTTtJQUVOLHlCQUF5QjtJQUN6QixTQUFTO0lBQ1QsUUFBUTtJQUNSLFdBQVc7SUFDWCxZQUFZO0lBQ1osV0FBVztJQUVYLHVCQUF1QjtJQUN2QixPQUFPO0lBQ1AsU0FBUztJQUNULFFBQVE7SUFDUixRQUFRO0lBRVIsd0JBQXdCO0lBQ3hCLFlBQVk7SUFDWixjQUFjO0lBQ2QsV0FBVztJQUNYLFdBQVc7SUFFWCx3QkFBd0I7SUFDeEIsTUFBTTtJQUVOLGVBQWU7SUFDZixPQUFPO0lBQ1AsT0FBTztJQUVQLGdCQUFnQjtJQUNoQixRQUFRO0lBQ1IsS0FBSztJQUNMLFNB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SUFBSSxVQUFVLFNBQVMsY0FBYyxnQkFBZ0IsR0FBRyxJQUFJLElBQUksQ0FBQyxDQUFDO0lBQzdHLENBQUM7SUFFRDs7T0FFRztJQUNILE9BQU8sQ0FBQyxTQUFpQjtRQUN2QixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3RDLENBQUM7SUFFRDs7T0FFRztJQUNILFFBQVEsQ0FBQyxTQUFpQjtRQUN4QixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUMxQyxPQUFPLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLElBQUksU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztJQUMvRCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxNQUFNO1FBQ0osT0FBTyxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDaEMsQ0FBQztJQUVPLGNBQWM7UUFDcEIsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsVUFBVSxDQUFDLEdBQUcsZ0JBQWdCLENBQUMsQ0FBQztJQUNyRixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEZyaWVuZGx5IHNlc3Npb24gbmFtZXMgZHJhd24gZnJvbSBmYW1vdXMgcHVwcGV0cywgbWFyaW9uZXR0ZXMsXG4gKiBhbmQgcHVwcGV0IGNoYXJhY3RlcnMgdGhyb3VnaG91dCBoaXN0b3J5LlxuICpcbiAqIE5hbWVzIGFyZSBhc3NpZ25lZCBmcm9tIGEgcG9vbCBhbmQgcmV0dXJuZWQgYWZ0ZXIgYSBjb29sZG93biBwZXJpb2RcbiAqIHdoZW4gc2Vzc2lvbnMgZW5kLiBUaGlzIGtlZXBzIHRoZSBhY3RpdmUgc2Vzc2lvbiBsaXN0IGh1bWFuLXJlYWRhYmxlXG4gKiBhbmQgb24tYnJhbmQgZm9yIERvbGxob3VzZU1DUC5cbiAqXG4gKiBAc2luY2UgdjIuMS4wIOKAlCBJc3N1ZSAjMTcwMFxuICovXG5cbmltcG9ydCB7IHJhbmRvbUludCB9IGZyb20gJ25vZGU6Y3J5cHRvJztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4uLy4uL3V0aWxzL2xvZ2dlci5qcyc7XG5cbi8qKlxuICogRmFtb3VzIHB1cHBldHMsIG1hcmlvbmV0dGVzLCBhbmQgcHVwcGV0IGNoYXJhY3RlcnMgZnJvbSBhcm91bmQgdGhlIHdvcmxkLlxuICogT3JkZXIgZG9lc24ndCBtYXR0ZXIg4oCUIHRoZSBwb29sIGlzIHNodWZmbGVkIG9uIHN0YXJ0dXAuXG4gKi9cbmV4cG9ydCBjb25zdCBBTExfUFVQUEVUX05BTUVTOiByZWFkb25seSBzdHJpbmdbXSA9IFtcbiAgLy8gQ2xhc3NpYyAmIHRyYWRpdGlvbmFsXG4gICdQdW5jaCcsXG4gICdKdWR5JyxcbiAgJ1Bpbm9jY2hpbycsXG4gICdQZXRyb3VjaGthJyxcbiAgJ1B1bGNpbmVsbGEnLFxuICAnR3VpZ25vbCcsXG4gICdLYXNwZXJsZScsXG5cbiAgLy8gTXVwcGV0cyAmIEppbSBIZW5zb25cbiAgJ0tlcm1pdCcsXG4gICdQaWdneScsXG4gICdGb3p6aWUnLFxuICAnR29uem8nLFxuICAnU2Nvb3RlcicsXG4gICdSb3dsZicsXG4gICdXYWxkb3JmJyxcbiAgJ1N0YXRsZXInLFxuXG4gIC8vIEt1a2xhLCBGcmFuIGFuZCBPbGxpZVxuICAnS3VrbGEnLFxuICAnT2xsaWUnLFxuXG4gIC8vIEhvd2R5IERvb2R5IGVyYVxuICAnSG93ZHknLFxuICAnQ2xhcmFiZWxsJyxcblxuICAvLyBTZXNhbWUgU3RyZWV0XG4gICdHcm92ZXInLFxuICAnRWxtbycsXG4gICdFcm5pZScsXG4gICdCZXJ0JyxcbiAgJ09zY2FyJyxcblxuICAvLyBWZW50cmlsb3F1aXN0ICYgdmFyaWV0eVxuICAnTW9ydGltZXInLFxuICAnTGFtYmNob3AnLFxuICAnTWFkYW1lJyxcbiAgJ1RvcG8nLFxuXG4gIC8vIEludGVybmF0aW9uYWwgcHVwcGV0cnlcbiAgJ0J1bnJha3UnLFxuICAnV2F5YW5nJyxcbiAgJ1BldHJ1c2hrYScsXG4gICdIYW5uZXNjaGVuJyxcbiAgJ1ZpdGV6c2xhdicsXG5cbiAgLy8gTW9kZXJuICYgcG9wIGN1bHR1cmVcbiAgJ1NhbGVtJyxcbiAgJ1RyaXVtcGgnLFxuICAnUGVhbnV0JyxcbiAgJ0FjaG1lZCcsXG5cbiAgLy8gTWFyaW9uZXR0ZSB0cmFkaXRpb25zXG4gICdGYW50b2NjaW5pJyxcbiAgJ1NhbHRpbWJhbnF1ZScsXG4gICdCdXJhdHRpbm8nLFxuICAnSGFybGVxdWluJyxcblxuICAvLyBEb2xsaG91c2UgKFRWIHNlcmllcylcbiAgJ0VjaG8nLFxuXG4gIC8vIEluc2lkZSBqb2tlc1xuICAnU3Bpa2UnLFxuICAnQW5nZWwnLFxuXG4gIC8vIENsYXNzaWMgZG9sbHNcbiAgJ0JhcmJpZScsXG4gICdLZW4nLFxuICAnU2tpcHBlcicsXG4gICdNaWRnZScsXG4gICdDaHJpc3RpZScsXG4gICdBbm5pZScsXG4gICdBbmR5JyxcbiAgJ0NhdGh5JyxcbiAgJ1RlZGR5JyxcbiAgJ1hhdmllcicsXG4gICdTdHJhd2JlcnJ5JyxcbiAgJ0JseXRoZScsXG4gICdHaW5ueScsXG4gICdCZXRzeScsXG4gICdNYWRlbGluZScsXG5dO1xuXG4vKiogTmFtZXMgdGhhdCBjYW4gbmV2ZXIgYmUgYXNzaWduZWQgdG8gYSBsZWFkZXIgc2Vzc2lvbiAqL1xuY29uc3QgRk9MTE9XRVJfT05MWV9OQU1FUyA9IG5ldyBTZXQoWydQdW5jaCddKTtcblxuLyoqIEZpc2hlci1ZYXRlcyBzaHVmZmxlIHVzaW5nIGNyeXB0by5yYW5kb21JbnQgKHVuYmlhc2VkLCBubyBtb2R1bG8pICovXG5mdW5jdGlvbiBzaHVmZmxlQXJyYXk8VD4oYXJyOiBUW10pOiBUW10ge1xuICBmb3IgKGxldCBpID0gYXJyLmxlbmd0aCAtIDE7IGkgPiAwOyBpLS0pIHtcbiAgICBjb25zdCBqID0gcmFuZG9tSW50KGkgKyAxKTtcbiAgICBbYXJyW2ldLCBhcnJbal1dID0gW2FycltqXSwgYXJyW2ldXTtcbiAgfVxuICByZXR1cm4gYXJyO1xufVxuXG4vKiogU2h1ZmZsZWQgY29weSBvZiB0aGUgbmFtZSBwb29sIOKAlCByYW5kb21pemVkIG9uIGVhY2ggcHJvY2VzcyBzdGFydCAqL1xuY29uc3QgUFVQUEVUX05BTUVTOiBzdHJpbmdbXSA9IHNodWZmbGVBcnJheShbLi4uQUxMX1BVUFBFVF9OQU1FU10pO1xuXG4vKipcbiAqIEljb25pYyBhdHRpcmUgYW5kIGFjY2Vzc29yaWVzIGRyYXduIGZyb20gZmFtb3VzIGRvbGxzLCBwdXBwZXRzLCBhbmRcbiAqIHRoZWF0cmljYWwgY2hhcmFjdGVycyB0aHJvdWdob3V0IGhpc3RvcnkuIFVzZWQgdG8gbmFtZSBjb25zb2xlIHRva2Vuc1xuICogc28gdGhleSBuZXZlciBjb2xsaWRlIHdpdGggdGhlIHNlc3Npb24gcHVwcGV0LW5hbWUgcG9vbCAoIzE4NzEpLlxuICpcbiAqIE5hbWVzIGV2b2tlIGNvc3R1bWUgcGllY2VzIOKAlCBhIHRva2VuIGlzIHNvbWV0aGluZyB5b3Ugd2VhciBvciBjYXJyeSxcbiAqIG5vdCBhIHBlcnNvbi5cbiAqL1xuZXhwb3J0IGNvbnN0IEFMTF9UT0tFTl9OQU1FUzogcmVhZG9ubHkgc3RyaW5nW10gPSBbXG4gIC8vIFZpY3RvcmlhbiAmIHRoZWF0cmljYWxcbiAgJ1RvcCBIYXQnLFxuICAnTW9ub2NsZScsXG4gICdUcmVuY2ggQ29hdCcsXG4gICdPcGVyYSBDYXBlJyxcbiAgJ09wZXJhIEdsb3ZlcycsXG4gICdWZWx2ZXQgQ2xvYWsnLFxuICAnTGFjZSBDb2xsYXInLFxuICAnU2lsayBDcmF2YXQnLFxuICAnV2Fpc3Rjb2F0JyxcbiAgJ0dpbHQgQnV0dG9uJyxcblxuICAvLyBQaGFudG9tLCBtYXNrcywgbXlzdGVyeVxuICAnSGFsZiBNYXNrJyxcbiAgJ0RvbWlubyBNYXNrJyxcbiAgJ0ZlYXRoZXJlZCBNYXNrJyxcblxuICAvLyBQdW5jaCAmIEp1ZHkgLyBIYXJsZXF1aW5cbiAgJ0plc3RlciBCZWxscycsXG4gICdEaWFtb25kIFN1aXQnLFxuICAnQmVsbCBDYXAnLFxuICAnU2xhcHN0aWNrJyxcbiAgJ1JlZCBOb3NlJyxcblxuICAvLyBQdXBwZXQgdHJhZGl0aW9uc1xuICAnTWFyaW9uZXR0ZSBTdHJpbmdzJyxcbiAgJ0NyYWNrZWQgUG9yY2VsYWluJyxcbiAgJ1BhcGllci1Nw6JjaMOpJyxcblxuICAvLyBDbGFzc2ljIGRvbGxzICYgY2hhcmFjdGVyc1xuICAnUGluayBDb3J2ZXR0ZScsXG4gICdSZWQgWWFybiBIYWlyJyxcbiAgJ1NhaWxvciBTdWl0JyxcbiAgJ1llbGxvdyBIYXQnLFxuICAnUnVieSBTbGlwcGVycycsXG4gICdHbGFzcyBTbGlwcGVyJyxcbiAgJ0JsdWUgUmliYm9uJyxcbiAgJ1N0cmlwZWQgU3RvY2tpbmdzJyxcblxuICAvLyBXaXphcmQgLyB3aXRjaCAvIGZhbnRhc3lcbiAgJ1BvaW50ZWQgSGF0JyxcbiAgJ0Jyb29tc3RpY2snLFxuICAnU2lsdmVyIFdhbmQnLFxuICAnVGluIENyb3duJyxcbiAgJ1N0cmF3IEhhdCcsXG5cbiAgLy8gQWR2ZW50dXJlICYgbXlzdGVyeVxuICAnRGVlcnN0YWxrZXInLFxuICAnTWFnbmlmeWluZyBHbGFzcycsXG4gICdGZWF0aGVyZWQgQ2FwJyxcbiAgJ1NpbHZlciBCdWNrbGUnLFxuICAnV2lja2VyIEJhc2tldCcsXG5dO1xuXG4vKipcbiAqIFBpY2sgYSByYW5kb20gdG9rZW4gbmFtZSBmcm9tIHRoZSBhdHRpcmUgcG9vbC5cbiAqIFVzZWQgYnkgdGhlIGNvbnNvbGUgdG9rZW4gbW9kdWxlIHRvIG5hbWUgbmV3bHkgY3JlYXRlZCB0b2tlbnMgKCMxODcxKS5cbiAqIERyYXduIGZyb20gYSBzZXBhcmF0ZSBwb29sIHRvIGF2b2lkIGNvbGxpc2lvbiB3aXRoIHNlc3Npb24gcHVwcGV0IG5hbWVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGlja1JhbmRvbVRva2VuTmFtZSgpOiBzdHJpbmcge1xuICByZXR1cm4gQUxMX1RPS0VOX05BTUVTW3JhbmRvbUludChBTExfVE9LRU5fTkFNRVMubGVuZ3RoKV07XG59XG5cbi8qKlxuICogQ2Fub25pY2FsIGNvbG9ycyBmb3IgZWFjaCBwdXBwZXQgY2hhcmFjdGVyLlxuICogQWRqdXN0ZWQgZnJvbSB0cnVlIGNhbm9uaWNhbCBjb2xvcnMgZm9yIFVJIHJlYWRhYmlsaXR5IGluIGJvdGggbGlnaHQvZGFyayB0aGVtZXMuXG4gKi9cbmNvbnN0IFBVUFBFVF9DT0xPUlM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICdQdW5jaCc6ICAgICAgICAnI0RDMTQzQycsIC8vIGNyaW1zb24gcmVkIGNvc3R1bWVcbiAgJ0p1ZHknOiAgICAgICAgICcjMUU5MEZGJywgLy8gYmx1ZSBkcmVzc1xuICAnUGlub2NjaGlvJzogICAgJyNEQUE1MjAnLCAvLyBnb2xkZW5yb2QgKHdvb2RlbiwgeWVsbG93IGhhdClcbiAgJ1BldHJvdWNoa2EnOiAgICcjQjBCRUM1JywgLy8gYmx1ZS1ncmF5ICh3aGl0ZSBjb3N0dW1lLCBhZGp1c3RlZCBmb3IgdmlzaWJpbGl0eSlcbiAgJ1B1bGNpbmVsbGEnOiAgICcjOTBBNEFFJywgLy8gZ3JheS1ibHVlICh3aGl0ZSBjb3N0dW1lLCBhZGp1c3RlZClcbiAgJ0d1aWdub2wnOiAgICAgICcjOEI0NTEzJywgLy8gc2FkZGxlIGJyb3duXG4gICdLYXNwZXJsZSc6ICAgICAnI0ZGMDAwMCcsIC8vIHJlZCBwb2ludGVkIGNhcFxuICAnS2VybWl0JzogICAgICAgJyM0Q0FGNTAnLCAvLyBncmVlbiBmcm9nXG4gICdQaWdneSc6ICAgICAgICAnI0U5MUU4QycsIC8vIGhvdCBwaW5rIChnbGFtb3JvdXMgcGlnKVxuICAnRm96emllJzogICAgICAgJyNDQzc3MjInLCAvLyBvY2hyZSBicm93biBiZWFyXG4gICdHb256byc6ICAgICAgICAnIzQxNjlFMScsIC8vIHJveWFsIGJsdWVcbiAgJ1Njb290ZXInOiAgICAgICcjRkY4QzAwJywgLy8gZGFyayBvcmFuZ2VcbiAgJ1Jvd2xmJzogICAgICAgICcjOEI2OTE0JywgLy8gZGFyayBnb2xkZW5yb2QgYnJvd24gZG9nXG4gICdXYWxkb3JmJzogICAgICAnIzU1NkIyRicsIC8vIGRhcmsgb2xpdmUgZ3JlZW5cbiAgJ1N0YXRsZXInOiAgICAgICcjNzA4MDkwJywgLy8gc2xhdGUgZ3JheVxuICAnS3VrbGEnOiAgICAgICAgJyNGRjAwMDAnLCAvLyByZWQgbm9zZSBhbmQgY29zdHVtZVxuICAnT2xsaWUnOiAgICAgICAgJyMyMjhCMjInLCAvLyBmb3Jlc3QgZ3JlZW4gZHJhZ29uXG4gICdIb3dkeSc6ICAgICAgICAnI0UyNzI1QicsIC8vIHRlcnJhIGNvdHRhXG4gICdDbGFyYWJlbGwnOiAgICAnI0ZGQ0MwMCcsIC8vIGJyaWdodCB5ZWxsb3cgY2xvd25cbiAgJ0dyb3Zlcic6ICAgICAgICcjNDY4MkI0JywgLy8gc3RlZWwgYmx1ZVxuICAnRWxtbyc6ICAgICAgICAgJyNGRjI0MDAnLCAvLyBzY2FybGV0IHJlZFxuICAnRXJuaWUnOiAgICAgICAgJyNGNEE0NjAnLCAvLyBzYW5keSBicm93blxuICAnQmVydCc6ICAgICAgICAgJyNGRkQ3MDAnLCAvLyBnb2xkIHllbGxvd1xuICAnT3NjYXInOiAgICAgICAgJyM2QjhFMjMnLCAvLyBvbGl2ZSBkcmFiIGdyZWVuXG4gICdNb3J0aW1lcic6ICAgICAnI0RFQjg4NycsIC8vIGJ1cmx5d29vZFxuICAnTGFtYmNob3AnOiAgICAgJyNENEM1QTknLCAvLyB3YXJtIGNyZWFtIChhZGp1c3RlZCBmcm9tIHB1cmUgd2hpdGUpXG4gICdNYWRhbWUnOiAgICAgICAnIzgwMDA4MCcsIC8vIHB1cnBsZVxuICAnVG9wbyc6ICAgICAgICAgJyNBMEEwQTAnLCAvLyBzaWx2ZXIgZ3JheVxuICAnQnVucmFrdSc6ICAgICAgJyNCMjIyMjInLCAvLyBmaXJlYnJpY2sgcmVkXG4gICdXYXlhbmcnOiAgICAgICAnIzZCNDIyNicsIC8vIGRhcmsgbGVhdGhlciBicm93biAobGlnaHRlbmVkIGZvciB2aXNpYmlsaXR5KVxuICAnUGV0cnVzaGthJzogICAgJyNGRjQ1MDAnLCAvLyBvcmFuZ2UgcmVkXG4gICdIYW5uZXNjaGVuJzogICAnI0NENUM1QycsIC8vIGluZGlhbiByZWRcbiAgJ1ZpdGV6c2xhdic6ICAgICcjQjg4NjBCJywgLy8gZGFyayBnb2xkZW5yb2RcbiAgJ1NhbGVtJzogICAgICAgICcjNEE0QTRBJywgLy8gZGFyayBncmF5IChibGFjayBjYXQsIGxpZ2h0ZW5lZCBmb3IgdmlzaWJpbGl0eSlcbiAgJ1RyaXVtcGgnOiAgICAgICcjNkY0RTM3JywgLy8gY29mZmVlIGJyb3duXG4gICdQZWFudXQnOiAgICAgICAnIzkzNzBEQicsIC8vIG1lZGl1bSBwdXJwbGVcbiAgJ0FjaG1lZCc6ICAgICAgICcjQzhCRkE5JywgLy8gYm9uZS9wYXJjaG1lbnQgKGxpZ2h0ZW5lZCBmcm9tIGJlaWdlKVxuICAnRmFudG9jY2luaSc6ICAgJyNDNDFFM0EnLCAvLyBjYXJkaW5hbCByZWRcbiAgJ1NhbHRpbWJhbnF1ZSc6ICcjREFBNTIwJywgLy8gZ29sZGVucm9kXG4gICdCdXJhdHRpbm8nOiAgICAnI0QyNjkxRScsIC8vIGNob2NvbGF0ZSBicm93blxuICAnSGFybGVxdWluJzogICAgJyNFNjAwMjYnLCAvLyBkaWFtb25kIHJlZFxuICAnRWNobyc6ICAgICAgICAgJyM1QzYzNzAnLCAvLyBzbGF0ZSAoZGFyayBhdHRpcmUsIGxpZ2h0ZW5lZCBmb3IgdmlzaWJpbGl0eSlcbiAgJ1NwaWtlJzogICAgICAgICcjRThEQ0M4JywgLy8gcGxhdGludW0vYmxlYWNoIChsaWdodGVuZWQgZm9yIHJlYWRhYmlsaXR5KVxuICAnQW5nZWwnOiAgICAgICAgJyMzRDNEM0QnLCAvLyBjaGFyY29hbCAoYmxhY2sgZHVzdGVyLCBsaWdodGVuZWQgZm9yIHZpc2liaWxpdHkpXG5cbiAgLy8gQ2xhc3NpYyBkb2xsc1xuICAnQmFyYmllJzogICAgICAgJyNFOTFFOTAnLCAvLyBCYXJiaWUgcGlua1xuICAnS2VuJzogICAgICAgICAgJyM0QTkwRDknLCAvLyBLZW4gYmx1ZVxuICAnU2tpcHBlcic6ICAgICAgJyNGRjZCNkInLCAvLyBjb3JhbCByZWRcbiAgJ01pZGdlJzogICAgICAgICcjRTg3MDQwJywgLy8gd2FybSBhdWJ1cm5cbiAgJ0NocmlzdGllJzogICAgICcjQzA2MDMwJywgLy8gd2FybSBicm93blxuICAnQW5uaWUnOiAgICAgICAgJyNFMDMwMzAnLCAvLyBSYWdnZWR5IEFubiByZWQgeWFybiBoYWlyXG4gICdBbmR5JzogICAgICAgICAnIzMwNzBDMCcsIC8vIFJhZ2dlZHkgQW5keSBibHVlIHNhaWxvciBvdXRmaXRcbiAgJ0NhdGh5JzogICAgICAgICcjRDRBNTc0JywgLy8gQ2hhdHR5IENhdGh5IHZpbnRhZ2UgdGFuXG4gICdUZWRkeSc6ICAgICAgICAnI0EwNzg0QScsIC8vIFRlZGR5IFJ1eHBpbiBiZWFyIGJyb3duXG4gICdYYXZpZXInOiAgICAgICAnIzVBQUY0QScsIC8vIFhhdmllciBSb2JlcnRzIC8gQ2FiYmFnZSBQYXRjaCBncmVlblxuICAnU3RyYXdiZXJyeSc6ICAgJyNFODQ0NUEnLCAvLyBzdHJhd2JlcnJ5IHJlZC1waW5rXG4gICdCbHl0aGUnOiAgICAgICAnIzdCNjhFRScsIC8vIGJpZy1leWVkIHB1cnBsZVxuICAnR2lubnknOiAgICAgICAgJyM1QjlCRDUnLCAvLyBjbGFzc2ljIGJsdWUgZHJlc3NcbiAgJ0JldHN5JzogICAgICAgICcjREQ3Njk0JywgLy8gcm9zZSBwaW5rXG4gICdNYWRlbGluZSc6ICAgICAnI0ZGRDcwMCcsIC8vIHllbGxvdyBoYXRcbn07XG5cbi8qKiBDb29sZG93biBwZXJpb2QgYmVmb3JlIGEgcmVsZWFzZWQgbmFtZSBjYW4gYmUgcmV1c2VkIChtcykgKi9cbmNvbnN0IE5BTUVfQ09PTERPV05fTVMgPSA1ICogNjBfMDAwOyAvLyA1IG1pbnV0ZXNcblxuaW50ZXJmYWNlIENvb2xkb3duRW50cnkge1xuICBuYW1lOiBzdHJpbmc7XG4gIHJlbGVhc2VkQXQ6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBNYW5hZ2VzIGZyaWVuZGx5IHNlc3Npb24gbmFtZSBhc3NpZ25tZW50IGZyb20gdGhlIHB1cHBldCBuYW1lIHBvb2wuXG4gKi9cbmV4cG9ydCBjbGFzcyBTZXNzaW9uTmFtZVBvb2wge1xuICAvKiogTmFtZXMgY3VycmVudGx5IGFzc2lnbmVkIHRvIGFjdGl2ZSBzZXNzaW9uczogc2Vzc2lvbklkIOKGkiBuYW1lICovXG4gIHByaXZhdGUgcmVhZG9ubHkgYXNzaWduZWQgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpO1xuICAvKiogUmV2ZXJzZSBsb29rdXA6IG5hbWUg4oaSIHNlc3Npb25JZCAqL1xuICBwcml2YXRlIHJlYWRvbmx5IG5hbWVUb1Nlc3Npb24gPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpO1xuICAvKiogTmFtZXMgaW4gY29vbGRvd24gYWZ0ZXIgc2Vzc2lvbiBlbmQgKi9cbiAgcHJpdmF0ZSBjb29sZG93bjogQ29vbGRvd25FbnRyeVtdID0gW107XG5cbiAgLyoqXG4gICAqIEFzc2lnbiBhIGZyaWVuZGx5IG5hbWUgdG8gYSBzZXNzaW9uLlxuICAgKiBSZXR1cm5zIGFuIGV4aXN0aW5nIGFzc2lnbm1lbnQgaWYgdGhlIHNlc3Npb24gYWxyZWFkeSBoYXMgb25lLlxuICAgKlxuICAgKiBAcGFyYW0gaXNMZWFkZXIgLSBJZiB0cnVlLCBmb2xsb3dlci1vbmx5IG5hbWVzIChlLmcuLCBQdW5jaCkgYXJlIGV4Y2x1ZGVkXG4gICAqL1xuICBhc3NpZ24oc2Vzc2lvbklkOiBzdHJpbmcsIGlzTGVhZGVyID0gZmFsc2UpOiBzdHJpbmcge1xuICAgIC8vIEFscmVhZHkgYXNzaWduZWQ/XG4gICAgY29uc3QgZXhpc3RpbmcgPSB0aGlzLmFzc2lnbmVkLmdldChzZXNzaW9uSWQpO1xuICAgIGlmIChleGlzdGluZykgcmV0dXJuIGV4aXN0aW5nO1xuXG4gICAgLy8gRmx1c2ggZXhwaXJlZCBjb29sZG93bnNcbiAgICB0aGlzLmZsdXNoQ29vbGRvd25zKCk7XG5cbiAgICAvLyBGaW5kIGFuIGF2YWlsYWJsZSBuYW1lLCByZXNwZWN0aW5nIGxlYWRlciByZXN0cmljdGlvbnNcbiAgICBjb25zdCBjb29sZG93bk5hbWVzID0gbmV3IFNldCh0aGlzLmNvb2xkb3duLm1hcChjID0+IGMubmFtZSkpO1xuICAgIGNvbnN0IGF2YWlsYWJsZU5hbWUgPSBQVVBQRVRfTkFNRVMuZmluZChcbiAgICAgIG5hbWUgPT4gIXRoaXMubmFtZVRvU2Vzc2lvbi5oYXMobmFtZSkgJiZcbiAgICAgICAgICAgICAgIWNvb2xkb3duTmFtZXMuaGFzKG5hbWUpICYmXG4gICAgICAgICAgICAgICEoaXNMZWFkZXIgJiYgRk9MTE9XRVJfT05MWV9OQU1FUy5oYXMobmFtZSkpXG4gICAgKTtcblxuICAgIGlmIChhdmFpbGFibGVOYW1lKSB7XG4gICAgICB0aGlzLmFzc2lnbmVkLnNldChzZXNzaW9uSWQsIGF2YWlsYWJsZU5hbWUpO1xuICAgICAgdGhpcy5uYW1lVG9TZXNzaW9uLnNldChhdmFpbGFibGVOYW1lLCBzZXNzaW9uSWQpO1xuICAgICAgbG9nZ2VyLmRlYnVnKGBbU2Vzc2lvbk5hbWVzXSBBc3NpZ25lZCAnJHthdmFpbGFibGVOYW1lfScgdG8gJHtzZXNzaW9uSWR9YCk7XG4gICAgICByZXR1cm4gYXZhaWxhYmxlTmFtZTtcbiAgICB9XG5cbiAgICAvLyBBbGwgbmFtZXMgaW4gdXNlIG9yIGNvb2xpbmcgZG93biDigJQgdHJ5IGNvb2xkb3duIG5hbWVzIChvbGRlc3QgZmlyc3QpXG4gICAgaWYgKHRoaXMuY29vbGRvd24ubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3Qgb2xkZXN0ID0gdGhpcy5jb29sZG93bi5zaGlmdCgpITtcbiAgICAgIHRoaXMuYXNzaWduZWQuc2V0KHNlc3Npb25JZCwgb2xkZXN0Lm5hbWUpO1xuICAgICAgdGhpcy5uYW1lVG9TZXNzaW9uLnNldChvbGRlc3QubmFtZSwgc2Vzc2lvbklkKTtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhgW1Nlc3Npb25OYW1lc10gQXNzaWduZWQgJyR7b2xkZXN0Lm5hbWV9JyB0byAke3Nlc3Npb25JZH0gKGVhcmx5IGNvb2xkb3duIHJlbGVhc2UpYCk7XG4gICAgICByZXR1cm4gb2xkZXN0Lm5hbWU7XG4gICAgfVxuXG4gICAgLy8gVHJ1bHkgZXhoYXVzdGVkIOKAlCBmYWxsIGJhY2sgdG8gdHJ1bmNhdGVkIHNlc3Npb24gSURcbiAgICBjb25zdCBmYWxsYmFjayA9IHNlc3Npb25JZC5zcGxpdCgnLScpWzFdIHx8IHNlc3Npb25JZC5zbGljZSgwLCA4KTtcbiAgICB0aGlzLmFzc2lnbmVkLnNldChzZXNzaW9uSWQsIGZhbGxiYWNrKTtcbiAgICBsb2dnZXIud2FybihgW1Nlc3Npb25OYW1lc10gTmFtZSBwb29sIGV4aGF1c3RlZCwgdXNpbmcgZmFsbGJhY2sgJyR7ZmFsbGJhY2t9JyBmb3IgJHtzZXNzaW9uSWR9YCk7XG4gICAgcmV0dXJuIGZhbGxiYWNrO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbGVhc2UgYSBuYW1lIGJhY2sgdG8gdGhlIHBvb2wgd2l0aCBhIGNvb2xkb3duIHBlcmlvZC5cbiAgICovXG4gIHJlbGVhc2Uoc2Vzc2lvbklkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBuYW1lID0gdGhpcy5hc3NpZ25lZC5nZXQoc2Vzc2lvbklkKTtcbiAgICBpZiAoIW5hbWUpIHJldHVybjtcblxuICAgIHRoaXMuYXNzaWduZWQuZGVsZXRlKHNlc3Npb25JZCk7XG4gICAgdGhpcy5uYW1lVG9TZXNzaW9uLmRlbGV0ZShuYW1lKTtcblxuICAgIC8vIE9ubHkgY29vbGRvd24gcHVwcGV0IG5hbWVzLCBub3QgZmFsbGJhY2sgSURzXG4gICAgaWYgKFBVUFBFVF9OQU1FUy5pbmNsdWRlcyhuYW1lKSkge1xuICAgICAgdGhpcy5jb29sZG93bi5wdXNoKHsgbmFtZSwgcmVsZWFzZWRBdDogRGF0ZS5ub3coKSB9KTtcbiAgICB9XG5cbiAgICBsb2dnZXIuZGVidWcoYFtTZXNzaW9uTmFtZXNdIFJlbGVhc2VkICcke25hbWV9JyBmcm9tICR7c2Vzc2lvbklkfSAoY29vbGRvd24gJHtOQU1FX0NPT0xET1dOX01TIC8gMTAwMH1zKWApO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgZnJpZW5kbHkgbmFtZSBmb3IgYSBzZXNzaW9uLCBvciB1bmRlZmluZWQgaWYgbm90IGFzc2lnbmVkLlxuICAgKi9cbiAgZ2V0TmFtZShzZXNzaW9uSWQ6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuYXNzaWduZWQuZ2V0KHNlc3Npb25JZCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBjYW5vbmljYWwgY29sb3IgZm9yIGFuIGFzc2lnbmVkIHNlc3Npb24gbmFtZS5cbiAgICovXG4gIGdldENvbG9yKHNlc3Npb25JZDogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBuYW1lID0gdGhpcy5hc3NpZ25lZC5nZXQoc2Vzc2lvbklkKTtcbiAgICByZXR1cm4gbmFtZSA/IChQVVBQRVRfQ09MT1JTW25hbWVdID8/IHVuZGVmaW5lZCkgOiB1bmRlZmluZWQ7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGFsbCBjdXJyZW50IGFzc2lnbm1lbnRzLlxuICAgKi9cbiAgZ2V0QWxsKCk6IE1hcDxzdHJpbmcsIHN0cmluZz4ge1xuICAgIHJldHVybiBuZXcgTWFwKHRoaXMuYXNzaWduZWQpO1xuICB9XG5cbiAgcHJpdmF0ZSBmbHVzaENvb2xkb3ducygpOiB2b2lkIHtcbiAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgIHRoaXMuY29vbGRvd24gPSB0aGlzLmNvb2xkb3duLmZpbHRlcihjID0+IChub3cgLSBjLnJlbGVhc2VkQXQpIDwgTkFNRV9DT09MRE9XTl9NUyk7XG4gIH1cbn1cbiJdfQ==